Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Tests/NFUnitTestTypes/NFUnitTestTypes.nfproj
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
</PropertyGroup>
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.props" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.props')" />
<ItemGroup>
<Compile Include="UnitTestGuid.cs" />
<Compile Include="UnitTestObjectTypeTests.cs" />
<Compile Include="UnitTestsSpanByte.cs" />
<Compile Include="UnitTestSubTypeTests.cs" />
Expand All @@ -47,4 +48,4 @@
<ProjectConfigurationsDeclaredAsItems />
</ProjectCapabilities>
</ProjectExtensions>
</Project>
</Project>
140 changes: 140 additions & 0 deletions Tests/NFUnitTestTypes/UnitTestGuid.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using nanoFramework.TestFramework;

namespace NFUnitTestTypes
{
[TestClass]
class UnitTestGuid
{
[TestMethod]
public void Guid_Compare_To_Empty()
{
var empty = Guid.Empty;
var notEmpty = Guid.NewGuid();
Assert.IsFalse(empty == notEmpty);
}

[TestMethod]
public void Guid_Empty_IsAllZeros()
{
var empty = Guid.Empty;
var bytes = empty.ToByteArray();
foreach (var b in bytes)
{
Assert.AreEqual((byte)0, b);
}
}

[TestMethod]
public void Guid_Constructor_ByteArray_RoundTrip()
{
var original = Guid.NewGuid();
var bytes = original.ToByteArray();
var roundTrip = new Guid(bytes);
Assert.AreEqual(original, roundTrip);
}

[TestMethod]
public void Guid_Equals_And_Operator()
{
var g1 = Guid.NewGuid();
var g2 = new Guid(g1.ToByteArray());
Assert.IsTrue(g1.Equals(g2));
Assert.IsTrue(g1 == g2);
Assert.IsFalse(g1 != g2);
}

[TestMethod]
public void Guid_NotEquals_And_Operator()
{
var g1 = Guid.NewGuid();
var g2 = Guid.NewGuid();
Assert.IsFalse(g1.Equals(g2));
Assert.IsFalse(g1 == g2);
Assert.IsTrue(g1 != g2);
}

[TestMethod]
public void Guid_ToString_And_Parse()
{
var g1 = Guid.NewGuid();
var str = g1.ToString();
var g2 = new Guid(str);
Assert.AreEqual(g1, g2);
}

[TestMethod]
public void Guid_GetHashCode_Consistent()
{
var g1 = Guid.NewGuid();
var g2 = new Guid(g1.ToByteArray());
Assert.AreEqual(g1.GetHashCode(), g2.GetHashCode());
}

[TestMethod]
public void Guid_CompareTo_Object_And_Self()
{
var g1 = Guid.NewGuid();
var g2 = new Guid(g1.ToByteArray());
Assert.AreEqual(0, g1.CompareTo(g2));
Assert.AreEqual(0, g1.CompareTo((object)g2));
Assert.AreEqual(1, g1.CompareTo(null));
}

[TestMethod]
public void Guid_CompareTo_InvalidType_Throws()
{
var g1 = Guid.NewGuid();
Assert.ThrowsException(typeof(ArgumentException), () =>
{
g1.CompareTo("not a guid");
});
}

[TestMethod]
public void Guid_TryParseGuidWithDashes_Valid()
{
var g1 = Guid.NewGuid();
var str = g1.ToString();
bool parsed = Guid.TryParseGuidWithDashes(str, out var g2);
Assert.IsTrue(parsed);
Assert.AreEqual(g1, g2);
}

[TestMethod]
public void Guid_TryParseGuidWithDashes_Invalid()
{
bool parsed = Guid.TryParseGuidWithDashes("invalid-guid", out var g2);
Assert.IsFalse(parsed);
Assert.AreEqual(Guid.Empty, g2);
}

[TestMethod]
public void Guid_Constructor_String_WithBraces()
{
var g1 = Guid.NewGuid();
var str = "{" + g1.ToString() + "}";
var g2 = new Guid(str);
Assert.AreEqual(g1, g2);
}

[TestMethod]
public void Guid_Constructor_String_Invalid_Throws()
{
Assert.ThrowsException(typeof(ArgumentException), () =>
{
var g = new Guid("invalid-guid");
});
}

[TestMethod]
public void Guid_GetHashCode_Empty()
{
var empty = Guid.Empty;
Assert.AreEqual(0, empty.GetHashCode());
}
}
}
79 changes: 67 additions & 12 deletions nanoFramework.CoreLibrary/System/Guid.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ public struct Guid
/// </summary>
public static readonly Guid Empty = new Guid(new byte[16]);

public Guid()
{
// All zeros
_data = new int[4];
}

/// <summary>
/// Initializes a new instance of the <see cref="Guid"/> structure by using the specified integers and bytes.
/// </summary>
Expand Down Expand Up @@ -163,26 +169,32 @@ public int CompareTo(object value)
if (value == null)
{
return 1;
}

#pragma warning disable S3928 // Parameter names used into ArgumentException constructors should match an existing one
if (value is not Guid)
}
if (value is not Guid other)
{
throw new ArgumentException();
}
#pragma warning restore S3928 // Parameter names used into ArgumentException constructors should match an existing one

int[] other = ((Guid)value)._data;
other ??= new int[4];
return CompareTo(other);
}

/// <summary>
/// Compares the current instance with another object of the same type and returns an integer that indicates whether the current instance precedes, follows, or occurs in the same position in the sort order as the other object.
/// </summary>
/// <param name="other">An object to compare with this instance.</param>
/// <returns>A value that indicates the relative order of the objects being compared.</returns>
public int CompareTo(Guid other)
{
_data ??= new int[4];
other._data ??= new int[4];
for (int i = 0; i < 4; i++)
{
if (_data[i] != other[i])
if (_data[i] != other._data[i])
{
return _data[i] - other[i];
return _data[i] - other._data[i];
}
}

return 0;
}

Expand All @@ -201,6 +213,9 @@ public int CompareTo(object value)
/// </remarks>
public byte[] ToByteArray()
{
// Initialize if null (treat as Empty)
_data ??= new int[4];

byte[] buffer = new byte[16];

int index = 0;
Expand Down Expand Up @@ -289,10 +304,19 @@ public override bool Equals(object o)
return false;
}

int[] other = ((Guid)o)._data;
other ??= new int[4];
return o is Guid other && Equals(other);
}

return (_data[0] == other[0]) && (_data[1] == other[1]) && (_data[2] == other[2]) && (_data[3] == other[3]);
/// <summary>
/// Indicates whether the current object is equal to another object of the same type.
/// </summary>
/// <param name="other">An object to compare with this object.</param>
/// <returns>true if the current object is equal to the other parameter; otherwise, false.</returns>
public bool Equals(Guid other)
{
_data ??= new int[4];
other._data ??= new int[4];
return (_data[0] == other._data[0]) && (_data[1] == other._data[1]) && (_data[2] == other._data[2]) && (_data[3] == other._data[3]);
}

/// <summary>
Expand All @@ -301,6 +325,8 @@ public override bool Equals(object o)
/// <returns>The hash code for this instance.</returns>
public override int GetHashCode()
{
// Initialize if null (treat as Empty)
_data ??= new int[4];
return _data[0] ^ _data[1] ^ _data[2] ^ _data[3];
}

Expand Down Expand Up @@ -447,5 +473,34 @@ private static long HexStringToLong(string str, ref int parsePos, int requiredLe
parsePos += requiredLength;
return result;
}

/// <summary>
/// Determines whether two specified instances of <see cref="Guid"/> are equal.
/// </summary>
/// <param name="a">The first <see cref="Guid"/> to compare.</param>
/// <param name="b">The second <see cref="Guid"/> to compare.</param>
/// <returns><see langword="true"/> if <paramref name="a"/> equals <paramref name="b"/>; otherwise, <see langword="false"/>.</returns>
public static bool operator ==(Guid a, Guid b)
{
// Defensive null handling, though _data should always be initialized
a._data ??= new int[4];
b._data ??= new int[4];

return (a._data[0] == b._data[0]) &&
(a._data[1] == b._data[1]) &&
(a._data[2] == b._data[2]) &&
(a._data[3] == b._data[3]);
}

/// <summary>
/// Determines whether two specified instances of <see cref="Guid"/> are not equal.
/// </summary>
/// <param name="a">The first <see cref="Guid"/> to compare.</param>
/// <param name="b">The second <see cref="Guid"/> to compare.</param>
/// <returns><see langword="true"/> if <paramref name="a"/> does not equal <paramref name="b"/>; otherwise, <see langword="false"/>.</returns>
public static bool operator !=(Guid a, Guid b)
{
return !(a == b);
}
}
}
Loading