using System; using System.IO; using System.Reflection; using System.Runtime.Serialization; using UnitTestSharp; namespace Vellum.UnitTests { public class ConstructorRunnerTests : TestFixture { public static T Blank() { return (T)FormatterServices.GetUninitializedObject(typeof(T)); } public class Hothead { public Hothead(SaveReader reader) { throw new InvalidDataException("This constructor always throws."); } } public class HasReaderConstructorTests : TestFixture { public void TypeWithOne_IsTrue() { CheckTrue(ConstructorRunner.HasReaderConstructor(typeof(Ring))); } public void TypeWithout_IsFalse() { CheckFalse(ConstructorRunner.HasReaderConstructor(typeof(Knob))); } } public class RunReaderConstructorTests : TestFixture { public static SaveReader ReaderOf(string name) { SaveNode table = SaveNode.NewTable(); table.Entries["Name"] = SaveNode.OfText(name); return new SaveReader(table, SaveConvertersTests.Session()); } public void ObjectThatNeverWasConstructed_IsConstructed() { Vertex blank = Blank(); CheckNull(blank.Neighbors); ConstructorRunner.RunReaderConstructor(blank, ReaderOf("v")); CheckEqual("v", blank.Name); CheckNotNull(blank.Neighbors); } public void SecondRun_ConstructsAgain() { Vertex blank = Blank(); ConstructorRunner.RunReaderConstructor(blank, ReaderOf("first")); ConstructorRunner.RunReaderConstructor(blank, ReaderOf("second")); CheckEqual("second", blank.Name); } public void ObjectWithData_KeepsItsIdentityAndGetsTheSavedData() { var vertex = new Vertex { Name = "old" }; Vertex same = vertex; ConstructorRunner.RunReaderConstructor(vertex, ReaderOf("new")); CheckTrue(ReferenceEquals(same, vertex)); CheckEqual("new", vertex.Name); } public void TypeWithoutOne_Throws() { CheckThrow(typeof(InvalidOperationException)); ConstructorRunner.RunReaderConstructor(Blank(), ReaderOf("x")); } public void TypeWithoutOneAskedTwice_ThrowsEachTime() { bool threwFirst = false; try { ConstructorRunner.RunReaderConstructor(Blank(), ReaderOf("x")); } catch (InvalidOperationException) { threwFirst = true; } CheckTrue(threwFirst); CheckThrow(typeof(InvalidOperationException)); ConstructorRunner.RunReaderConstructor(Blank(), ReaderOf("x")); } } public class RunByReflectionTests : TestFixture { private static ConstructorInfo ReaderConstructorOf() { return typeof(OwnerType).GetConstructor( BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new[] { typeof(SaveReader) }, null); } public void ObjectThatNeverWasConstructed_IsConstructed() { Vertex blank = Blank(); ConstructorRunner.RunByReflection(ReaderConstructorOf())(blank, RunReaderConstructorTests.ReaderOf("v")); CheckEqual("v", blank.Name); CheckNotNull(blank.Neighbors); } public void ObjectWithData_KeepsItsIdentityAndGetsTheSavedData() { var vertex = new Vertex { Name = "old" }; Vertex same = vertex; ConstructorRunner.RunByReflection(ReaderConstructorOf())(vertex, RunReaderConstructorTests.ReaderOf("new")); CheckTrue(ReferenceEquals(same, vertex)); CheckEqual("new", vertex.Name); } public void ConstructorThatThrows_ThrowsWhatItThrew() { CheckThrow(typeof(InvalidDataException)); ConstructorRunner.RunByReflection(ReaderConstructorOf())(Blank(), RunReaderConstructorTests.ReaderOf("x")); } } public class RunTests : TestFixture { public void ConstructorThatTakesTheArguments_RunsOnTheObject() { var spouse = Blank(); var partner = new Spouse("bob", null); ConstructorRunner.Run(spouse, "ann", partner); CheckEqual("ann", spouse.Name); CheckTrue(ReferenceEquals(partner, spouse.Partner)); CheckEqual(6, spouse.PairedLength); } public void NullForAReferenceParameter_Fits() { var spouse = Blank(); ConstructorRunner.Run(spouse, "ann", null); CheckNull(spouse.Partner); } public void ValueTypeParameter_Fits() { var counted = Blank(); ConstructorRunner.Run(counted, 5); CheckEqual(5, counted.Number); } public void NullForAValueTypeParameter_DoesntFit() { CheckThrow(typeof(InvalidOperationException)); ConstructorRunner.Run(Blank(), new object[] { null }); } public void WrongNumberOfArguments_Throws() { CheckThrow(typeof(InvalidOperationException)); ConstructorRunner.Run(Blank(), "ann"); } public void ArgumentOfTheWrongType_Throws() { CheckThrow(typeof(InvalidOperationException)); ConstructorRunner.Run(Blank(), 5, null); } public void ArgumentsTwoConstructorsAccept_Throws() { CheckThrow(typeof(InvalidOperationException)); ConstructorRunner.Run(Blank(), "a", "b"); } public void NullTwoConstructorsAccept_Throws() { CheckThrow(typeof(InvalidOperationException)); ConstructorRunner.Run(Blank(), new object[] { null }); } public void ConstructorThatThrows_ThrowsWhatItThrew() { CheckThrow(typeof(NullReferenceException)); ConstructorRunner.Run(Blank(), null, null); } } } }