Skip to content

Commit ed90c8e

Browse files
authored
Add Span<T> and ReadOnlySpan<T> (#249)
1 parent fa61139 commit ed90c8e

File tree

17 files changed

+1408
-54
lines changed

17 files changed

+1408
-54
lines changed

Tests/NFUnitTestSystemLib/NFUnitTestSystemLib.nfproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
</PropertyGroup>
2525
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.props" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.props')" />
2626
<ItemGroup>
27+
<Compile Include="UnitTestNullable.cs" />
2728
<Compile Include="UnitTestUInt64.cs" />
2829
<Compile Include="UnitTestUInt32.cs" />
2930
<Compile Include="UnitTestSingle.cs" />
Lines changed: 266 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,266 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System;
5+
using nanoFramework.TestFramework;
6+
7+
namespace NFUnitTestSystemLib
8+
{
9+
[TestClass]
10+
public class UnitTestNullable
11+
{
12+
[TestMethod]
13+
public void Ctor_Empty()
14+
{
15+
// Nullable and Nullable<T> are mostly verbatim ports so we don't test much here.
16+
17+
int? n = default(int?);
18+
Assert.IsFalse(n.HasValue);
19+
20+
// TODO replace with Assert.ThrowsException<InvalidOperationException> when available
21+
Assert.ThrowsException(
22+
typeof(InvalidOperationException),
23+
() => _ = n.Value);
24+
Assert.ThrowsException(
25+
typeof(InvalidOperationException),
26+
() => _ = (int)n);
27+
28+
Assert.IsNull(n);
29+
Assert.AreNotEqual(7, n);
30+
Assert.AreEqual(0, n.GetHashCode());
31+
Assert.AreEqual("", n.ToString());
32+
Assert.AreEqual(default(int), n.GetValueOrDefault());
33+
Assert.AreEqual(999, n.GetValueOrDefault(999));
34+
35+
n = new int?(42);
36+
Assert.IsTrue(n.HasValue);
37+
Assert.AreEqual(42, n.Value);
38+
Assert.AreEqual(42, (int)n);
39+
Assert.IsNotNull(n);
40+
Assert.AreNotEqual(7, n);
41+
Assert.AreEqual(42, n);
42+
Assert.AreEqual(42.GetHashCode(), n.GetHashCode());
43+
Assert.AreEqual(42.ToString(), n.ToString());
44+
Assert.AreEqual(42, n.GetValueOrDefault());
45+
Assert.AreEqual(42, n.GetValueOrDefault(999));
46+
47+
n = 88;
48+
Assert.IsTrue(n.HasValue);
49+
Assert.AreEqual(88, n.Value);
50+
}
51+
52+
[TestMethod]
53+
public static void Boxing()
54+
{
55+
int? n = new int?(42);
56+
Unbox(n);
57+
}
58+
59+
private static void Unbox(object o)
60+
{
61+
Type t = o.GetType();
62+
63+
// TOOD: replace with Assert.IsNotType<int?>(t); when available
64+
Assert.IsNotInstanceOfType(typeof(int?), t);
65+
66+
Assert.AreEqual(typeof(int), t);
67+
}
68+
69+
[TestMethod]
70+
public static void ExplicitCast_T()
71+
{
72+
int? nullable = 5;
73+
int value = (int)nullable;
74+
Assert.AreEqual(5, value);
75+
76+
nullable = null;
77+
// TODO replace with Assert.Throws<InvalidOperationException>(() => (int)nullable); when available
78+
Assert.ThrowsException(
79+
typeof(InvalidOperationException),
80+
() => _ = (int)nullable);
81+
}
82+
83+
[TestMethod]
84+
public static void GetUnderlyingType()
85+
{
86+
Assert.AreEqual(typeof(int), Nullable.GetUnderlyingType(typeof(int?)));
87+
Assert.AreEqual(null, Nullable.GetUnderlyingType(typeof(int)));
88+
Assert.AreEqual(null, Nullable.GetUnderlyingType(typeof(G<int>)));
89+
}
90+
91+
[TestMethod]
92+
public static void GetUnderlyingType_NullType_ThrowsArgumentNullException()
93+
{
94+
// TODO replace with Assert.Throws<ArgumentNullException>("nullableType", () => Nullable.GetUnderlyingType(null)); when available
95+
Assert.ThrowsException(
96+
typeof(ArgumentNullException),
97+
() => Nullable.GetUnderlyingType(null)
98+
);
99+
}
100+
101+
// TODO: Uncomment when available
102+
//[TestMethod]
103+
//public static void GetValueRefOrDefaultRef_WithValue()
104+
//{
105+
// static void Test<T>(T before, T after)
106+
// where T : struct
107+
// {
108+
// T? nullable = before;
109+
// ref readonly T reference = ref Nullable.GetValueRefOrDefaultRef(in nullable);
110+
111+
// Assert.AreEqual(before, nullable!.Value);
112+
113+
// Unsafe.AsRef<T>(in reference) = after;
114+
115+
// Assert.Equal(after, nullable.Value);
116+
// }
117+
118+
// Test((byte)0, (byte)42);
119+
// Test(0, 42);
120+
// Test(1.3f, 3.14f);
121+
// Test(0.555, 8.49);
122+
// Test(Guid.NewGuid(), Guid.NewGuid());
123+
//}
124+
125+
// TODO: Uncomment when available
126+
//[TestMethod]
127+
//public static void GetValueRefOrDefaultRef_WithDefault()
128+
//{
129+
// static void Test<T>()
130+
// where T : struct
131+
// {
132+
// T? nullable = null;
133+
// ref readonly T reference = ref Nullable.GetValueRefOrDefaultRef(in nullable);
134+
135+
// Assert.Equal(nullable!.GetValueOrDefault(), reference);
136+
// }
137+
138+
// Test<byte>();
139+
// Test<int>();
140+
// Test<float>();
141+
// Test<double>();
142+
// Test<Guid>();
143+
//}
144+
145+
// TODO: Uncomment when available
146+
//[TestMethod]
147+
//public static void GetValueRefOrDefaultRef_UnsafeWriteToNullMaintainsExpectedBehavior()
148+
//{
149+
// static void Test<T>(T after)
150+
// where T : struct
151+
// {
152+
// T? nullable = null;
153+
// ref readonly T reference = ref Nullable.GetValueRefOrDefaultRef(in nullable);
154+
155+
// Unsafe.AsRef<T>(in reference) = after;
156+
157+
// Assert.Equal(after, nullable.GetValueOrDefault()); // GetValueOrDefault() unconditionally returns the field
158+
// Assert.False(nullable.HasValue);
159+
// Assert.Equal(0, nullable.GetHashCode()); // GetHashCode() returns 0 if HasValue is false, without reading the field
160+
// Assert.Throws<InvalidOperationException>(() => nullable.Value); // Accessing the value should still throw despite the write
161+
// Assert.Throws<InvalidOperationException>(() => (T)nullable);
162+
// }
163+
164+
// Test((byte)42);
165+
// Test(42);
166+
// Test(3.14f);
167+
// Test(8.49);
168+
// Test(Guid.NewGuid());
169+
//}
170+
171+
[TestMethod]
172+
public static void Compare_Equals()
173+
{
174+
// Case 1: (null, null, 0)
175+
int? n1 = null;
176+
int? n2 = null;
177+
int expected = 0;
178+
Assert.AreEqual(expected == 0, Nullable.Equals(n1, n2));
179+
Assert.AreEqual(expected == 0, n1.Equals(n2));
180+
// TODO Assert.AreEqual(expected, Nullable.Compare(n1, n2));
181+
182+
// Case 2: (7, null, 1)
183+
n1 = 7;
184+
n2 = null;
185+
expected = 1;
186+
Assert.AreEqual(expected == 0, Nullable.Equals(n1, n2));
187+
Assert.AreEqual(expected == 0, n1.Equals(n2));
188+
// TODO Assert.AreEqual(expected, Nullable.Compare(n1, n2));
189+
190+
// Case 3: (null, 7, -1)
191+
n1 = null;
192+
n2 = 7;
193+
expected = -1;
194+
Assert.AreEqual(expected == 0, Nullable.Equals(n1, n2));
195+
Assert.AreEqual(expected == 0, n1.Equals(n2));
196+
// TODO Assert.AreEqual(expected, Nullable.Compare(n1, n2));
197+
198+
// Case 4: (7, 7, 0)
199+
n1 = 7;
200+
n2 = 7;
201+
expected = 0;
202+
Assert.AreEqual(expected == 0, Nullable.Equals(n1, n2));
203+
Assert.AreEqual(expected == 0, n1.Equals(n2));
204+
// TODO Assert.AreEqual(expected, Nullable.Compare(n1, n2));
205+
206+
// Case 5: (7, 5, 1)
207+
n1 = 7;
208+
n2 = 5;
209+
expected = 1;
210+
Assert.AreEqual(expected == 0, Nullable.Equals(n1, n2));
211+
Assert.AreEqual(expected == 0, n1.Equals(n2));
212+
// TODO Assert.AreEqual(expected, Nullable.Compare(n1, n2));
213+
214+
// Case 6: (5, 7, -1)
215+
n1 = 5;
216+
n2 = 7;
217+
expected = -1;
218+
Assert.AreEqual(expected == 0, Nullable.Equals(n1, n2));
219+
Assert.AreEqual(expected == 0, n1.Equals(n2));
220+
// TODO Assert.AreEqual(expected, Nullable.Compare(n1, n2));
221+
}
222+
223+
//[TestMethod]
224+
//public static void MutatingMethods_MutationsAffectOriginal()
225+
//{
226+
// MutatingStruct? ms = new MutatingStruct() { Value = 1 };
227+
228+
// for (int i = 1; i <= 2; i++)
229+
// {
230+
// Assert.AreEqual(i.ToString(), ms.Value.ToString());
231+
// Assert.AreEqual(i, ms.Value.Value);
232+
233+
// Assert.AreEqual(i.ToString(), ms.ToString());
234+
// Assert.AreEqual(i + 1, ms.Value.Value);
235+
// }
236+
237+
// for (int i = 3; i <= 4; i++)
238+
// {
239+
// Assert.AreEqual(i, ms.Value.GetHashCode());
240+
// Assert.AreEqual(i, ms.Value.Value);
241+
242+
// Assert.AreEqual(i, ms.GetHashCode());
243+
// Assert.AreEqual(i + 1, ms.Value.Value);
244+
// }
245+
246+
// for (int i = 5; i <= 6; i++)
247+
// {
248+
// ms.Value.Equals(new object());
249+
// Assert.AreEqual(i, ms.Value.Value);
250+
251+
// ms.Equals(new object());
252+
// Assert.AreEqual(i + 1, ms.Value.Value);
253+
// }
254+
//}
255+
256+
//private struct MutatingStruct
257+
//{
258+
// public int Value;
259+
// public override string ToString() => Value++.ToString();
260+
// public override bool Equals(object obj) => Value++.Equals(null);
261+
// public override int GetHashCode() => Value++.GetHashCode();
262+
//}
263+
264+
public class G<T> { }
265+
}
266+
}

Tests/NFUnitTestSystemLib/UnitTestReflectionTypeTest.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Collections;
66
using System.Reflection;
77
using nanoFramework.TestFramework;
8+
using static NFUnitTestSystemLib.UnitTestNullable;
89

910
namespace NFUnitTestSystemLib
1011
{
@@ -163,6 +164,7 @@ public void SystemReflectionType_SystemType_Test2()
163164

164165
Assert.IsTrue(typeof(Array).IsInstanceOfType(blah));
165166
Assert.IsTrue(typeof(TestStruct[]).IsArray);
167+
Assert.IsTrue(typeof(G<int>[]).IsArray);
166168
Assert.IsFalse(typeof(Array).IsValueType);
167169
Assert.IsTrue(typeof(TestStruct).IsValueType);
168170
Assert.IsTrue(typeof(Type).IsSubclassOf(typeof(MemberInfo)));

0 commit comments

Comments
 (0)