Skip to content

Commit 28f127a

Browse files
authored
Merge pull request #24 from chwarr/nullable
Add Nullable<> support to CombinatorialData/PairwiseData
2 parents 6f435e2 + e60fd6b commit 28f127a

File tree

2 files changed

+75
-1
lines changed

2 files changed

+75
-1
lines changed

src/Xunit.Combinatorial.Tests/CombinatorialDataAttributeTests.cs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
using System.Linq;
66
using System.Reflection;
77
using System.Runtime.CompilerServices;
8-
using System.Text;
98
using Sdk;
109
using Validation;
1110

@@ -51,6 +50,17 @@ public void GetData_Int()
5150
});
5251
}
5352

53+
[Fact]
54+
public void GetData_NullableInt()
55+
{
56+
AssertData(new object[][]
57+
{
58+
new object[] { null },
59+
new object[] { 0 },
60+
new object[] { 1 },
61+
});
62+
}
63+
5464
[Fact]
5565
public void GetData_Int_35()
5666
{
@@ -92,13 +102,32 @@ public void GetData_DateTimeKind()
92102
});
93103
}
94104

105+
[Fact]
106+
public void GetData_NullableDateTimeKind()
107+
{
108+
AssertData(new object[][]
109+
{
110+
new object[] { null },
111+
new object[] { DateTimeKind.Unspecified },
112+
new object[] { DateTimeKind.Utc },
113+
new object[] { DateTimeKind.Local },
114+
});
115+
}
116+
95117
[Fact]
96118
public void GetData_UnsupportedType()
97119
{
98120
Assert.Throws<NotSupportedException>(() => GetData(new CombinatorialDataAttribute()));
99121
Assert.Throws<NotSupportedException>(() => GetData(new PairwiseDataAttribute()));
100122
}
101123

124+
[Fact]
125+
public void GetData_UnsupportedNullableType()
126+
{
127+
Assert.Throws<NotSupportedException>(() => GetData(new CombinatorialDataAttribute()));
128+
Assert.Throws<NotSupportedException>(() => GetData(new PairwiseDataAttribute()));
129+
}
130+
102131
[Fact]
103132
public void GetData_CustomDataFromDerivedAttriute()
104133
{
@@ -120,10 +149,13 @@ private static void Suppose_NoArguments() { }
120149
private static void Suppose_Bool(bool p1) { }
121150
private static void Suppose_BoolBool(bool p1, bool p2) { }
122151
private static void Suppose_Int(int p1) { }
152+
private static void Suppose_NullableInt(int? p1) { }
123153
private static void Suppose_Int_35([CombinatorialValues(3, 5)] int p1) { }
124154
private static void Suppose_string_int_bool_Values([CombinatorialValues("a", "b")]string p1, [CombinatorialValues(2, 4, 6)]int p2, bool p3) { }
125155
private static void Suppose_DateTimeKind(DateTimeKind p1) { }
156+
private static void Suppose_NullableDateTimeKind(DateTimeKind? p1) { }
126157
private static void Suppose_UnsupportedType(System.AggregateException p1) { }
158+
private static void Suppose_UnsupportedNullableType(Guid? p1) { }
127159

128160
private static void AssertData(IEnumerable<object[]> expectedCombinatorial, [CallerMemberName] string testMethodName = null)
129161
{

src/Xunit.Combinatorial/ValuesUtilities.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,52 @@ internal static IEnumerable<object> GetValuesFor(Type dataType)
6161
yield return Enum.Parse(dataType, name);
6262
}
6363
}
64+
else if (IsNullable(dataType, out Type innerDataType))
65+
{
66+
yield return null;
67+
foreach (object value in GetValuesFor(innerDataType))
68+
{
69+
yield return value;
70+
}
71+
}
6472
else
6573
{
6674
throw new NotSupportedException();
6775
}
6876
}
77+
78+
/// <summary>
79+
/// Determines whether <paramref name="dataType"/> is <see cref="Nullable{T}"/>
80+
/// and extracts the inner type, if any.
81+
/// </summary>
82+
/// <param name="dataType">
83+
/// The type to test whether it is <see cref="Nullable{T}"/>
84+
/// </param>
85+
/// <param name="innerDataType">
86+
/// When this method returns, contains the inner type of the Nullable, if the
87+
/// type is Nullable is found; otherwise, null.
88+
/// </param>
89+
/// <returns>
90+
/// <see langword="true"/> if the type is a Nullable type; otherwise <see langword="false"/>.
91+
/// </returns>
92+
private static bool IsNullable(Type dataType, out Type innerDataType)
93+
{
94+
innerDataType = null;
95+
96+
var ti = dataType.GetTypeInfo();
97+
98+
if (!ti.IsGenericType)
99+
{
100+
return false;
101+
}
102+
103+
if (ti.GetGenericTypeDefinition() != typeof(Nullable<>))
104+
{
105+
return false;
106+
}
107+
108+
innerDataType = ti.GenericTypeArguments[0];
109+
return true;
110+
}
69111
}
70112
}

0 commit comments

Comments
 (0)