Skip to content

Commit

Permalink
Support null for copy method properly.
Browse files Browse the repository at this point in the history
String and Type are now copyable.
  • Loading branch information
KeRNeLith committed Sep 2, 2019
1 parent 7db7aab commit bddf070
Show file tree
Hide file tree
Showing 8 changed files with 143 additions and 80 deletions.
55 changes: 43 additions & 12 deletions src/ImmediateReflection.Tests/ConstructorTestHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -757,6 +757,8 @@ public static IEnumerable<TestCaseData> CreateHasDefaultConstructorTestCases
yield return new TestCaseData(typeof(List<int>)) { ExpectedResult = true };
yield return new TestCaseData(typeof(Dictionary<int, string>)) { ExpectedResult = true };

yield return new TestCaseData(typeof(string)) { ExpectedResult = false };
yield return new TestCaseData(typeof(Type)) { ExpectedResult = false };
yield return new TestCaseData(typeof(NoDefaultConstructor)) { ExpectedResult = false };
yield return new TestCaseData(typeof(NotAccessibleDefaultConstructor)) { ExpectedResult = false };
yield return new TestCaseData(typeof(AbstractDefaultConstructor)) { ExpectedResult = false };
Expand Down Expand Up @@ -827,6 +829,8 @@ public static IEnumerable<TestCaseData> CreateDefaultConstructorNoThrowTestCases
yield return new TestCaseData(typeof(List<int>), false);
yield return new TestCaseData(typeof(Dictionary<int, string>), false);

yield return new TestCaseData(typeof(string), true);
yield return new TestCaseData(typeof(Type), true);
yield return new TestCaseData(typeof(NoDefaultConstructor), true);
yield return new TestCaseData(typeof(NotAccessibleDefaultConstructor), true);
yield return new TestCaseData(typeof(IList<int>), true);
Expand Down Expand Up @@ -981,6 +985,8 @@ public static IEnumerable<TestCaseData> CreateNotDefaultConstructorNoThrowNullPa
yield return new TestCaseData(typeof(List<int>), false, null);
yield return new TestCaseData(typeof(Dictionary<int, string>), false, null);

yield return new TestCaseData(typeof(string), true, null);
yield return new TestCaseData(typeof(Type), true, null);
yield return new TestCaseData(typeof(NoDefaultConstructor), true, null);
yield return new TestCaseData(typeof(NotAccessibleDefaultConstructor), true, null);
yield return new TestCaseData(typeof(AbstractDefaultConstructor), true, null);
Expand Down Expand Up @@ -1031,6 +1037,10 @@ public static IEnumerable<TestCaseData> CreateNotDefaultConstructorNoThrowNotNul
yield return new TestCaseData(typeof(int), true, new object[] { 12 });
yield return new TestCaseData(typeof(TestStruct), true, new object[] { 12 });
yield return new TestCaseData(typeof(TestEnum), true, new object[] { 1 });
yield return new TestCaseData(typeof(string), true, new object[] { });
yield return new TestCaseData(typeof(string), true, new object[] { "str" });
yield return new TestCaseData(typeof(Type), true, new object[] { });
yield return new TestCaseData(typeof(Type), true, new object[] { typeof(int) });
yield return new TestCaseData(typeof(DefaultConstructor), true, new object[] { 12 });
yield return new TestCaseData(typeof(MultipleConstructors), true, new object[] { 12.5f, 12 });
yield return new TestCaseData(typeof(TemplateStruct<double>), true, new object[] { 25 });
Expand Down Expand Up @@ -1095,15 +1105,21 @@ public static IEnumerable<TestCaseData> CreateHasCopyConstructorTestCases
[UsedImplicitly]
get
{
yield return new TestCaseData(typeof(int)) { ExpectedResult = true }; // Not has a real copy constructor but it's more convenient
yield return new TestCaseData(typeof(TestStruct)) { ExpectedResult = true }; // Not has a real copy constructor but it's more convenient
yield return new TestCaseData(typeof(TestEnum)) { ExpectedResult = true }; // Not has a real copy constructor but it's more convenient
// Not has a real copy constructor but it's more convenient
yield return new TestCaseData(typeof(int)) { ExpectedResult = true };
yield return new TestCaseData(typeof(TestStruct)) { ExpectedResult = true };
yield return new TestCaseData(typeof(TestEnum)) { ExpectedResult = true };
yield return new TestCaseData(typeof(string)) { ExpectedResult = true };
yield return new TestCaseData(typeof(Type)) { ExpectedResult = true };

// Normal copy constructor
yield return new TestCaseData(typeof(CopyConstructorClass)) { ExpectedResult = true };
yield return new TestCaseData(typeof(CopyInheritedCopyConstructorClass)) { ExpectedResult = true };
yield return new TestCaseData(typeof(MultipleCopyConstructorClass)) { ExpectedResult = true };
yield return new TestCaseData(typeof(TemplateCopyConstructor<double>)) { ExpectedResult = true };
yield return new TestCaseData(typeof(CopyConstructorThrows)) { ExpectedResult = true };

// No copy constructor
yield return new TestCaseData(typeof(NoCopyConstructorClass)) { ExpectedResult = false };
yield return new TestCaseData(typeof(NoCopyInheritedCopyConstructorClass)) { ExpectedResult = false };
yield return new TestCaseData(typeof(BaseCopyInheritedCopyConstructorClass)) { ExpectedResult = false };
Expand All @@ -1129,9 +1145,15 @@ public static IEnumerable<TestCaseData> CreateCopyConstructorTestCases
[UsedImplicitly]
get
{
yield return new TestCaseData(typeof(CopyConstructorClass), null);
yield return new TestCaseData(typeof(NoCopyConstructorClass), null);
yield return new TestCaseData(typeof(AbstractCopyConstructor), null);

yield return new TestCaseData(typeof(int), 25);
yield return new TestCaseData(typeof(TestStruct), new TestStruct { TestValue = 12 });
yield return new TestCaseData(typeof(TestEnum), TestEnum.EnumValue2);
yield return new TestCaseData(typeof(string), "string test value");
yield return new TestCaseData(typeof(Type), typeof(int));
yield return new TestCaseData(typeof(CopyConstructorClass), new CopyConstructorClass(42));
yield return new TestCaseData(typeof(CopyInheritedCopyConstructorClass), new CopyInheritedCopyConstructorClass(28));
yield return new TestCaseData(typeof(MultipleCopyConstructorClass), new MultipleCopyConstructorClass(56));
Expand All @@ -1142,8 +1164,10 @@ public static IEnumerable<TestCaseData> CreateCopyConstructorTestCases
public static void Copy([NotNull] Type type, [CanBeNull] object other, [NotNull, InstantHandle] Func<object, object> ctor)
{
object instance = ctor(other);
Assert.IsNotNull(instance);
if (type.IsValueType)

if (other is null)
Assert.IsNull(instance);
else if (type.IsValueType || type == typeof(string) || type == typeof(Type))
Assert.AreEqual(other, instance);
else
Assert.AreEqual(Activator.CreateInstance(type, other), instance);
Expand All @@ -1155,9 +1179,15 @@ public static IEnumerable<TestCaseData> CreateCopyConstructorNoThrowTestCases
[UsedImplicitly]
get
{
yield return new TestCaseData(typeof(CopyConstructorClass), null, false);
yield return new TestCaseData(typeof(NoCopyConstructorClass), null, false);
yield return new TestCaseData(typeof(AbstractCopyConstructor), null, false);

yield return new TestCaseData(typeof(int), 1, false);
yield return new TestCaseData(typeof(TestStruct), new TestStruct { TestValue = 2 }, false);
yield return new TestCaseData(typeof(TestEnum), TestEnum.EnumValue2, false);
yield return new TestCaseData(typeof(string), "string test value", false);
yield return new TestCaseData(typeof(Type), typeof(int), false);
yield return new TestCaseData(typeof(CopyConstructorClass), new CopyConstructorClass(3), false);
yield return new TestCaseData(typeof(CopyInheritedCopyConstructorClass), new CopyInheritedCopyConstructorClass(4), false);
yield return new TestCaseData(typeof(MultipleCopyConstructorClass), new MultipleCopyConstructorClass(5), false);
Expand All @@ -1175,12 +1205,12 @@ public static IEnumerable<TestCaseData> CreateCopyConstructorNoThrowTestCases
yield return new TestCaseData(typeof(IList<int>), new List<int>(), true);
yield return new TestCaseData(typeof(IDictionary<int, string>), new Dictionary<int, string>(), true);
yield return new TestCaseData(typeof(int[]), new int[0], true);
yield return new TestCaseData(typeof(AbstractCopyConstructor), null, true);
yield return new TestCaseData(typeof(StaticClass), null, true);
yield return new TestCaseData(typeof(TemplateStruct<>), null, true);
yield return new TestCaseData(typeof(TemplateCopyConstructor<>), null, true);
yield return new TestCaseData(typeof(AbstractCopyConstructor), new CopyConstructorClass(12), true);
yield return new TestCaseData(typeof(StaticClass), new CopyConstructorClass(12), true);
yield return new TestCaseData(typeof(TemplateStruct<>), new CopyConstructorClass(12), true);
yield return new TestCaseData(typeof(TemplateCopyConstructor<>), new CopyConstructorClass(12), true);
// ReSharper disable once PossibleMistakenCallToGetType.2
yield return new TestCaseData(typeof(CopyConstructorClass).GetType(), null, true);
yield return new TestCaseData(typeof(CopyConstructorClass).GetType(), new CopyConstructorClass(12), true);
yield return new TestCaseData(typeof(CopyConstructorThrows), new CopyConstructorThrows(), true);
}
}
Expand All @@ -1197,8 +1227,9 @@ public static void TryCopy([NotNull] Type type, [CanBeNull] object other, bool e
}
else
{
Assert.IsNotNull(instance);
if (type.IsValueType)
if (other is null)
Assert.IsNull(instance);
else if (type.IsValueType || type == typeof(string) || type == typeof(Type))
Assert.AreEqual(other, instance);
else
Assert.AreEqual(Activator.CreateInstance(type, other), instance);
Expand Down
44 changes: 27 additions & 17 deletions src/ImmediateReflection.Tests/Extensions/ObjectExtensionsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,23 @@ public static IEnumerable<TestCaseData> CreateObjectHasCopyConstructorTestCases
[UsedImplicitly]
get
{
yield return new TestCaseData(42) { ExpectedResult = true }; // Not has a real copy constructor but it's more convenient
yield return new TestCaseData(new TestStruct { TestValue = 12 }) { ExpectedResult = true }; // Not has a real copy constructor but it's more convenient
yield return new TestCaseData(TestEnum.EnumValue2) { ExpectedResult = true }; // Not has a real copy constructor but it's more convenient
// Not has a real copy constructor but it's more convenient
yield return new TestCaseData(42) { ExpectedResult = true };
yield return new TestCaseData(new TestStruct { TestValue = 12 }) { ExpectedResult = true };
yield return new TestCaseData(TestEnum.EnumValue2) { ExpectedResult = true };
yield return new TestCaseData("string value") { ExpectedResult = true };
yield return new TestCaseData(typeof(double)) { ExpectedResult = true };

// Normal copy constructor
yield return new TestCaseData(new CopyConstructorClass(25)) { ExpectedResult = true };
yield return new TestCaseData(new CopyInheritedCopyConstructorClass(66)) { ExpectedResult = true };
yield return new TestCaseData(new MultipleCopyConstructorClass(33)) { ExpectedResult = true };
yield return new TestCaseData(new TemplateCopyConstructor<double>(7.5)) { ExpectedResult = true };

// Has copy constructor but not usable
yield return new TestCaseData(typeof(AbstractCopyConstructor)) { ExpectedResult = true };

// No copy constructor
yield return new TestCaseData(new NoCopyConstructorClass()) { ExpectedResult = false };
yield return new TestCaseData(new NoCopyInheritedCopyConstructorClass(1)) { ExpectedResult = false };
yield return new TestCaseData(new BaseCopyInheritedCopyConstructorClass(2)) { ExpectedResult = false };
Expand All @@ -49,7 +58,7 @@ public bool HasCopyConstructor([NotNull] object instance)
public void HasCopyConstructor_Throws()
{
// ReSharper disable once AssignNullToNotNullAttribute
Assert.Throws<ArgumentNullException>(() => ObjectExtensions.HasCopyConstructor<PublicTestClass>(null));
Assert.Throws<ArgumentNullException>(() => ObjectExtensions.HasCopyConstructor<object>(null));
}

#region Copy/TryCopy
Expand All @@ -66,9 +75,6 @@ public void Copy([NotNull] Type type, [CanBeNull] object other)
[Test]
public void Copy_Throws()
{
// ReSharper disable once AssignNullToNotNullAttribute
Assert.Throws<ArgumentNullException>(() => ObjectExtensions.Copy<PublicTestClass>(null));

Assert.Throws<MissingMethodException>(() => ObjectExtensions.Copy(new NoCopyConstructorClass()));
Assert.Throws<MissingMethodException>(() => ObjectExtensions.Copy(new NotAccessibleCopyConstructor()));
Assert.Throws<MissingMethodException>(() => ObjectExtensions.Copy(new List<int>()));
Expand All @@ -86,14 +92,25 @@ public static IEnumerable<TestCaseData> CreateObjectTryCopyConstructorTestCases
[UsedImplicitly]
get
{
yield return new TestCaseData(typeof(int), 42, false); // Not has a real copy constructor but it's more convenient
yield return new TestCaseData(typeof(TestStruct), new TestStruct { TestValue = 12 }, false); // Not has a real copy constructor but it's more convenient
yield return new TestCaseData(typeof(TestEnum), TestEnum.EnumValue2, false); // Not has a real copy constructor but it's more convenient
// Null instance always return null
yield return new TestCaseData(typeof(CopyConstructorClass), null, false);
yield return new TestCaseData(typeof(NoCopyConstructorClass), null, false);
yield return new TestCaseData(typeof(AbstractCopyConstructor), null, false);

// Not has a real copy constructor but it's more convenient
yield return new TestCaseData(typeof(int), 42, false);
yield return new TestCaseData(typeof(TestStruct), new TestStruct { TestValue = 12 }, false);
yield return new TestCaseData(typeof(TestEnum), TestEnum.EnumValue2, false);
yield return new TestCaseData(typeof(string), "string test", false);
yield return new TestCaseData(typeof(Type), typeof(float), false);

// Normal copy constructor
yield return new TestCaseData(typeof(CopyConstructorClass), new CopyConstructorClass(25), false);
yield return new TestCaseData(typeof(CopyInheritedCopyConstructorClass), new CopyInheritedCopyConstructorClass(66), false);
yield return new TestCaseData(typeof(MultipleCopyConstructorClass), new MultipleCopyConstructorClass(33), false);
yield return new TestCaseData(typeof(TemplateCopyConstructor<double>), new TemplateCopyConstructor<double>(7.5), false);

// No copy constructor
yield return new TestCaseData(typeof(NoCopyConstructorClass), new NoCopyConstructorClass(), true);
yield return new TestCaseData(typeof(NoCopyInheritedCopyConstructorClass), new NoCopyInheritedCopyConstructorClass(1), true);
yield return new TestCaseData(typeof(BaseCopyInheritedCopyConstructorClass), new BaseCopyInheritedCopyConstructorClass(2), true);
Expand All @@ -116,13 +133,6 @@ public void TryCopy([NotNull] Type type, [CanBeNull] object other, bool expectFa
(object o, out object instance, out Exception exception) => ObjectExtensions.TryCopy(o, out instance, out exception));
}

[Test]
public void TryCopy_Throws()
{
// ReSharper disable once AssignNullToNotNullAttribute
Assert.Throws<ArgumentNullException>(() => ObjectExtensions.TryCopy<PublicTestClass>(null, out _, out _));
}

#endregion
}
}
Expand Down
Loading

0 comments on commit bddf070

Please sign in to comment.