-
Notifications
You must be signed in to change notification settings - Fork 126
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
125 changed files
with
782 additions
and
540 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
namespace DotNext.Runtime; | ||
|
||
[TestClass] | ||
public class BoxedValueTests | ||
{ | ||
[TestMethod] | ||
public void BoxUnbox() | ||
{ | ||
var obj = (BoxedValue<int>)42; | ||
Assert.AreEqual(42.GetHashCode(), obj.GetHashCode()); | ||
Assert.AreEqual(42, obj.Unbox()); | ||
Assert.AreEqual(42, obj); | ||
Assert.AreEqual(typeof(int), obj.GetType()); | ||
} | ||
|
||
[TestMethod] | ||
public void Unwrap() | ||
{ | ||
object? obj = null; | ||
Assert.IsNull(BoxedValue<int>.GetTypedReference(obj)); | ||
|
||
obj = 42; | ||
Assert.AreEqual(42, BoxedValue<int>.GetTypedReference(obj)); | ||
|
||
obj = string.Empty; | ||
Assert.ThrowsException<ArgumentException>(() => BoxedValue<int>.GetTypedReference(obj)); | ||
} | ||
|
||
[TestMethod] | ||
public void ToUntypedReference() | ||
{ | ||
ValueType obj = BoxedValue<int>.Box(42); | ||
Assert.AreEqual(42, obj); | ||
} | ||
|
||
private struct MutableStruct | ||
{ | ||
public int Value; | ||
} | ||
|
||
[TestMethod] | ||
public void BitwiseCopyImmutable() | ||
{ | ||
var boxed1 = (BoxedValue<int>)42; | ||
var boxed2 = boxed1.Copy(); | ||
Assert.AreNotSame(boxed1, boxed2); | ||
Assert.AreEqual(42, boxed1); | ||
Assert.AreEqual(42, boxed2); | ||
} | ||
|
||
[TestMethod] | ||
public void BitwiseCopyMutable() | ||
{ | ||
var boxed1 = (BoxedValue<MutableStruct>)new MutableStruct(); | ||
var boxed2 = boxed1.Copy(); | ||
Assert.AreNotSame(boxed1, boxed2); | ||
|
||
boxed1.Unbox().Value = 42; | ||
boxed2.Unbox().Value = 43; | ||
|
||
Assert.AreNotEqual(boxed1.Unbox().Value, boxed2.Unbox().Value); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,187 @@ | ||
using System.Runtime.CompilerServices; | ||
using System.Runtime.InteropServices; | ||
|
||
namespace DotNext.Runtime; | ||
|
||
[TestClass] | ||
public class ValueReferenceTests | ||
{ | ||
[TestMethod] | ||
public void MutableFieldRef() | ||
{ | ||
var obj = new MyClass { AnotherField = string.Empty }; | ||
var reference = new ValueReference<int>(obj, ref obj.Field); | ||
|
||
obj.Field = 20; | ||
Assert.AreEqual(obj.Field, reference.Value); | ||
|
||
reference.Value = 42; | ||
Assert.AreEqual(obj.Field, reference.Value); | ||
Assert.IsTrue(string.IsNullOrEmpty(obj.AnotherField)); | ||
} | ||
|
||
[TestMethod] | ||
public void ImmutableFieldRef() | ||
{ | ||
var obj = new MyClass { AnotherField = string.Empty }; | ||
var reference = new ReadOnlyValueReference<int>(obj, in obj.Field); | ||
|
||
obj.Field = 20; | ||
Assert.AreEqual(obj.Field, reference.Value); | ||
|
||
Assert.AreEqual(obj.Field, reference.Value); | ||
Assert.IsTrue(string.IsNullOrEmpty(obj.AnotherField)); | ||
} | ||
|
||
[TestMethod] | ||
public void MutableToImmutableRef() | ||
{ | ||
var obj = new MyClass { AnotherField = string.Empty }; | ||
var reference = new ValueReference<int>(obj, ref obj.Field); | ||
ReadOnlyValueReference<int> roReference = reference; | ||
|
||
obj.Field = 20; | ||
Assert.AreEqual(roReference.Value, reference.Value); | ||
|
||
reference.Value = 42; | ||
Assert.AreEqual(roReference.Value, reference.Value); | ||
} | ||
|
||
[TestMethod] | ||
public void MutableRefEquality() | ||
{ | ||
var obj = new MyClass { AnotherField = string.Empty }; | ||
var reference1 = new ValueReference<int>(obj, ref obj.Field); | ||
var reference2 = new ValueReference<int>(obj, ref obj.Field); | ||
|
||
Assert.AreEqual(reference1, reference2); | ||
} | ||
|
||
[TestMethod] | ||
public void ImmutableRefEquality() | ||
{ | ||
var obj = new MyClass { AnotherField = string.Empty }; | ||
var reference1 = new ReadOnlyValueReference<int>(obj, in obj.Field); | ||
var reference2 = new ReadOnlyValueReference<int>(obj, in obj.Field); | ||
|
||
Assert.AreEqual(reference1, reference2); | ||
} | ||
|
||
[TestMethod] | ||
public void ReferenceToArray() | ||
{ | ||
var array = new string[1]; | ||
var reference = new ValueReference<string>(array, 0) | ||
{ | ||
Value = "Hello, world!" | ||
}; | ||
|
||
Assert.AreSame(array[0], reference.Value); | ||
Assert.AreSame(array[0], reference.ToString()); | ||
} | ||
|
||
[TestMethod] | ||
public void MutableEmptyRef() | ||
{ | ||
var reference = default(ValueReference<string>); | ||
Assert.IsTrue(reference.IsEmpty); | ||
Assert.IsNull(reference.ToString()); | ||
|
||
Span<string> span = reference; | ||
Assert.IsTrue(span.IsEmpty); | ||
|
||
Assert.ThrowsException<NullReferenceException>((Func<string>)reference); | ||
Assert.ThrowsException<NullReferenceException>(((Action<string>)reference).Bind(string.Empty)); | ||
} | ||
|
||
[TestMethod] | ||
public void ImmutableEmptyRef() | ||
{ | ||
var reference = default(ReadOnlyValueReference<string>); | ||
Assert.IsTrue(reference.IsEmpty); | ||
Assert.IsNull(reference.ToString()); | ||
|
||
ReadOnlySpan<string> span = reference; | ||
Assert.IsTrue(span.IsEmpty); | ||
|
||
Assert.ThrowsException<NullReferenceException>((Func<string>)reference); | ||
} | ||
|
||
[TestMethod] | ||
public void AnonymousValue() | ||
{ | ||
var reference = new ValueReference<int>(42); | ||
Assert.AreEqual(42, reference.Value); | ||
|
||
((Action<int>)reference).Invoke(52); | ||
Assert.AreEqual(52, ToFunc<ValueReference<int>, int>(reference).Invoke()); | ||
|
||
ReadOnlyValueReference<int> roRef = reference; | ||
Assert.AreEqual(52, roRef.Value); | ||
Assert.AreEqual(52, ToFunc<ReadOnlyValueReference<int>, int>(reference).Invoke()); | ||
} | ||
|
||
private static Func<T> ToFunc<TSupplier, T>(TSupplier supplier) | ||
where TSupplier : ISupplier<T> | ||
=> supplier.ToDelegate(); | ||
|
||
[TestMethod] | ||
public void IncorrectReference() | ||
{ | ||
byte[] empty = []; | ||
Assert.ThrowsException<ArgumentOutOfRangeException>(() => new ValueReference<byte>(empty, ref MemoryMarshal.GetArrayDataReference(empty))); | ||
Assert.ThrowsException<ArgumentOutOfRangeException>(() => new ReadOnlyValueReference<byte>(empty, ref MemoryMarshal.GetArrayDataReference(empty))); | ||
} | ||
|
||
[TestMethod] | ||
public void ReferenceSize() | ||
{ | ||
Assert.AreEqual(Unsafe.SizeOf<ValueReference<float>>(), nint.Size + nint.Size); | ||
} | ||
|
||
[TestMethod] | ||
public void BoxedValueInterop() | ||
{ | ||
var boxedInt = BoxedValue<int>.Box(42); | ||
ValueReference<int> reference = boxedInt; | ||
|
||
boxedInt.Unbox() = 56; | ||
Assert.AreEqual(boxedInt, reference.Value); | ||
} | ||
|
||
[TestMethod] | ||
public void ArrayCovariance() | ||
{ | ||
string[] array = ["a", "b"]; | ||
Assert.ThrowsException<ArrayTypeMismatchException>(() => new ValueReference<object>(array, 0)); | ||
|
||
var roRef = new ReadOnlyValueReference<object>(array, 1); | ||
Assert.AreEqual("b", roRef.Value); | ||
} | ||
|
||
[TestMethod] | ||
public void SpanInterop() | ||
{ | ||
var reference = new ValueReference<int>(42); | ||
Span<int> span = reference; | ||
Assert.AreEqual(1, span.Length); | ||
|
||
Assert.IsTrue(Unsafe.AreSame(in reference.Value, in span[0])); | ||
} | ||
|
||
[TestMethod] | ||
public void ReadOnlySpanInterop() | ||
{ | ||
ReadOnlyValueReference<int> reference = new ValueReference<int>(42); | ||
ReadOnlySpan<int> span = reference; | ||
Assert.AreEqual(1, span.Length); | ||
|
||
Assert.IsTrue(Unsafe.AreSame(in reference.Value, in span[0])); | ||
} | ||
|
||
private record MyClass | ||
{ | ||
internal int Field; | ||
internal string? AnotherField; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.