using System; using System.Collections.Generic; using UnitTestSharp; namespace Vellum.UnitTests { public class OpenConverterTests : TestFixture { public class OfTests : TestFixture { public void GenericConverter_KeepsItselfAndTheGenericTypeItConverts() { OpenConverter open = OpenConverter.Of(typeof(BoxConverter<>)); CheckTrue(open.Definition == typeof(BoxConverter<>)); CheckTrue(open.ConvertedDefinition == typeof(Box<>)); } public void ParametersInAnotherOrderThanTheConvertedTypesArguments_AreAccepted() { CheckTrue(OpenConverter.Of(typeof(PairConverter<,>)).ConvertedDefinition == typeof(Pair<,>)); } public void ConverterOfAPartlyClosedType_Throws() { CheckThrow(typeof(InvalidOperationException)); OpenConverter.Of(typeof(PartlyClosedConverter<>)); } public void ConverterUsingAParameterTwice_Throws() { CheckThrow(typeof(InvalidOperationException)); OpenConverter.Of(typeof(RepeatedParameterConverter<,>)); } public void ConverterThatNamesNoTypeItConverts_Throws() { CheckThrow(typeof(InvalidOperationException)); OpenConverter.Of(typeof(UntypedGenericConverter<>)); } public void ConverterWhoseArgumentIsMadeFromAParameter_Throws() { CheckThrow(typeof(InvalidOperationException)); OpenConverter.Of(typeof(NestedArgumentConverter<>)); } public void ConverterWithAParameterTheConvertedTypeDoesntUse_Throws() { CheckThrow(typeof(InvalidOperationException)); OpenConverter.Of(typeof(ExtraParameterConverter<,>)); } public void ConverterOfAnyType_Throws() { CheckThrow(typeof(InvalidOperationException)); OpenConverter.Of(typeof(AnyTypeConverter<>)); } public void ConverterOfAnArrayOfAnotherType_Throws() { CheckThrow(typeof(InvalidOperationException)); OpenConverter.Of(typeof(IntArrayConverter<>)); } public void ConverterOfAnArrayOfItsParameter_Throws() { CheckThrow(typeof(InvalidOperationException)); OpenConverter.Of(typeof(ArrayOfParameterConverter<>)); } public void ConverterOfAMultiDimensionalArray_Throws() { CheckThrow(typeof(InvalidOperationException)); OpenConverter.Of(typeof(MultiDimensionalConverter<>)); } public void AbstractConverter_Throws() { CheckThrow(typeof(InvalidOperationException)); OpenConverter.Of(typeof(AbstractBoxConverter<>)); } public void ConverterThatIsntGeneric_Throws() { CheckThrow(typeof(InvalidOperationException)); OpenConverter.Of(typeof(PointConverter)); } public void GenericTypeThatIsntAConverter_Throws() { CheckThrow(typeof(InvalidOperationException)); OpenConverter.Of(typeof(Box<>)); } public void ClosedGenericConverter_Throws() { CheckThrow(typeof(InvalidOperationException)); OpenConverter.Of(typeof(BoxConverter)); } public void EachConverter_KnowsWhatItHandles() { CheckEqual(OpenKind.Generic, OpenConverter.Of(typeof(BoxConverter<>)).Kind); CheckEqual(OpenKind.Family, OpenConverter.Of(typeof(CreatureConverter<>)).Kind); } public void FamilyConverter_KeepsTheBaseClassAndConvertsNoGenericType() { OpenConverter open = OpenConverter.Of(typeof(CreatureConverter<>)); CheckTrue(open.Definition == typeof(CreatureConverter<>)); CheckTrue(open.FamilyBase == typeof(Creature)); CheckNull(open.ConvertedDefinition); } public void FamilyOfAGenericBase_KeepsTheBaseWithItsArgumentsOpen() { OpenConverter open = OpenConverter.Of(typeof(HerdConverter<,>)); CheckTrue(open.FamilyBase.GetGenericTypeDefinition() == typeof(Herd<>)); CheckTrue(open.FamilyBase.ContainsGenericParameters); } public void ConvertersThatAreNotFamilies_HaveNoBase() { CheckNull(OpenConverter.Of(typeof(BoxConverter<>)).FamilyBase); } public void FamilyWhoseOwnParameterIsMarkedSaveable_Throws() { CheckThrow(typeof(InvalidOperationException)); OpenConverter.Of(typeof(MarkedSubjectConverter<>)); } public void FamilyWithTwoConstraints_Throws() { CheckThrow(typeof(InvalidOperationException)); OpenConverter.Of(typeof(TwoConstraintFamilyConverter<>)); } public void FamilyWithAClassConstraint_Throws() { CheckThrow(typeof(InvalidOperationException)); OpenConverter.Of(typeof(ClassConstrainedFamilyConverter<>)); } public void FamilyWithANewConstraint_Throws() { CheckThrow(typeof(InvalidOperationException)); OpenConverter.Of(typeof(NewConstrainedFamilyConverter<>)); } public void FamilyConstrainedToAnInterface_KeepsTheInterfaceAsItsBase() { OpenConverter open = OpenConverter.Of(typeof(InterfaceFamilyConverter<>)); CheckEqual(OpenKind.Family, open.Kind); CheckTrue(open.FamilyBase == typeof(ICloneable)); } public void FamilyOfAGenericInterface_KeepsItWithItsArgumentsOpen() { OpenConverter open = OpenConverter.Of(typeof(VesselConverter<,>)); CheckTrue(open.FamilyBase.GetGenericTypeDefinition() == typeof(IVessel<>)); } public void FamilyConstrainedToAnotherParameter_Throws() { CheckThrow(typeof(InvalidOperationException)); OpenConverter.Of(typeof(ParameterConstrainedFamilyConverter<,>)); } public void FamilyWithAParameterTheBaseDoesntUse_Throws() { CheckThrow(typeof(InvalidOperationException)); OpenConverter.Of(typeof(UnboundFamilyConverter<,>)); } public void FamilyWhoseBaseTakesItself_Throws() { CheckThrow(typeof(InvalidOperationException)); OpenConverter.Of(typeof(SelfReferencingFamilyConverter<>)); } public void FamilyWhoseBaseHasAClosedArgument_Throws() { CheckThrow(typeof(InvalidOperationException)); OpenConverter.Of(typeof(ClosedBaseFamilyConverter<>)); } public void FamilyWhoseBaseUsesAParameterTwice_Throws() { CheckThrow(typeof(InvalidOperationException)); OpenConverter.Of(typeof(RepeatedBaseArgumentFamilyConverter<,>)); } } public class SaveableArgumentsTests : TestFixture { public void GenericConverter_ListsTheArgumentsOfItsMarkedParameters() { CheckEqual(new[] { typeof(int) }, OpenConverter.Of(typeof(MarkedBoxConverter<>)).SaveableArguments(typeof(Box))); CheckEqual(new[] { typeof(string) }, OpenConverter.Of(typeof(MarkedPairConverter<,>)).SaveableArguments(typeof(Pair))); } public void FamilyConverter_ListsTheArgumentsTheBaseGivesItsMarkedParameters() { CheckEqual(new[] { typeof(int) }, OpenConverter.Of(typeof(MarkedHerdConverter<,>)).SaveableArguments(typeof(IntHerd))); } public void ConverterWithNoMarkedParameter_ListsNothing() { CheckEqual(0, OpenConverter.Of(typeof(BoxConverter<>)).SaveableArguments(typeof(Box)).Length); CheckEqual(0, OpenConverter.Of(typeof(CreatureConverter<>)).SaveableArguments(typeof(Wolf)).Length); } public void TypeTheConverterDoesNotHandle_ListsNothing() { CheckEqual(0, OpenConverter.Of(typeof(MarkedBoxConverter<>)).SaveableArguments(typeof(int)).Length); } } public class HandlesTests : TestFixture { public void TypeTheConverterCloses_IsHandled() { CheckTrue(OpenConverter.Of(typeof(BoxConverter<>)).Handles(typeof(Box))); CheckTrue(OpenConverter.Of(typeof(CreatureConverter<>)).Handles(typeof(Wolf))); } public void TypeTheConverterDoesNotClose_IsNotHandled() { CheckFalse(OpenConverter.Of(typeof(BoxConverter<>)).Handles(typeof(int))); CheckFalse(OpenConverter.Of(typeof(StructBoxConverter<>)).Handles(typeof(Box))); CheckFalse(OpenConverter.Of(typeof(CreatureConverter<>)).Handles(typeof(AbstractCreature))); CheckFalse(OpenConverter.Of(typeof(CreatureConverter<>)).Handles(typeof(string))); } public void ConverterWhoseConstructorThrows_IsHandledWithoutMakingIt() { CheckTrue(OpenConverter.Of(typeof(ThrowingCreatureConverter<>)).Handles(typeof(Wolf))); } } public class CloseTests : TestFixture { public void GenericType_GetsTheConverterClosedOverItsArgument() { SaveConverter closed = OpenConverter.Of(typeof(BoxConverter<>)).Close(typeof(Box)); CheckTrue(closed.GetType() == typeof(BoxConverter)); CheckTrue(closed.ValueType == typeof(Box)); } public void EachParameter_TakesTheArgumentInTheConvertedTypesPlaceForIt() { SaveConverter closed = OpenConverter.Of(typeof(PairConverter<,>)).Close(typeof(Pair)); CheckTrue(closed.GetType() == typeof(PairConverter)); CheckTrue(closed.ValueType == typeof(Pair)); } public void ConvertedTypeThatIsADifferentGenericType_IsNull() { CheckNull(OpenConverter.Of(typeof(BoxConverter<>)).Close(typeof(List))); CheckNull(OpenConverter.Of(typeof(BoxConverter<>)).Close(typeof(Pair))); } public void TypeThatIsntGeneric_IsNull() { CheckNull(OpenConverter.Of(typeof(BoxConverter<>)).Close(typeof(int))); CheckNull(OpenConverter.Of(typeof(BoxConverter<>)).Close(typeof(int[]))); } public void OpenType_IsNull() { CheckNull(OpenConverter.Of(typeof(BoxConverter<>)).Close(typeof(Box<>))); } public void ArgumentThatBreaksAConstraint_IsNull() { OpenConverter open = OpenConverter.Of(typeof(StructBoxConverter<>)); CheckNull(open.Close(typeof(Box))); CheckTrue(open.Close(typeof(Box)).GetType() == typeof(StructBoxConverter)); } public void ConstructorThatThrows_ThrowsItsOwnException() { OpenConverter open = OpenConverter.Of(typeof(ThrowingBoxConverter<>)); CheckThrow(typeof(FormatException)); open.Close(typeof(Box)); } public void Family_GetsTheConverterClosedOverTheType() { SaveConverter closed = OpenConverter.Of(typeof(CreatureConverter<>)).Close(typeof(Wolf)); CheckTrue(closed.GetType() == typeof(CreatureConverter)); CheckTrue(closed.ValueType == typeof(Wolf)); } public void Family_IncludesTheBaseItselfAndTypesFurtherDown() { OpenConverter open = OpenConverter.Of(typeof(CreatureConverter<>)); CheckTrue(open.Close(typeof(Creature)).GetType() == typeof(CreatureConverter)); CheckTrue(open.Close(typeof(AlphaWolf)).GetType() == typeof(CreatureConverter)); } public void Family_IsNullForTypesOutsideIt() { OpenConverter open = OpenConverter.Of(typeof(CreatureConverter<>)); CheckNull(open.Close(typeof(string))); CheckNull(open.Close(typeof(int))); CheckNull(open.Close(typeof(Box))); CheckNull(open.Close(typeof(int[]))); } public void Family_IsNullForAbstractTypes() { CheckNull(OpenConverter.Of(typeof(CreatureConverter<>)).Close(typeof(AbstractCreature))); } public void Family_IsNullForTypesThatAreNotClasses() { OpenConverter open = OpenConverter.Of(typeof(CreatureConverter<>)); CheckNull(open.Close(typeof(IDisposable))); CheckNull(open.Close(typeof(Point))); } public void InterfaceFamily_ClosesForClassesAndStructsThatImplementIt() { OpenConverter open = OpenConverter.Of(typeof(AquaticConverter<>)); CheckTrue(open.Close(typeof(Otter)).GetType() == typeof(AquaticConverter)); CheckTrue(open.Close(typeof(Sprat)).GetType() == typeof(AquaticConverter)); } public void InterfaceFamily_ClosesForTypesThatImplementItThroughABaseClassOrInterface() { CheckTrue(OpenConverter.Of(typeof(AquaticConverter<>)).Close(typeof(Cod)).GetType() == typeof(AquaticConverter)); CheckTrue(OpenConverter.Of(typeof(CarnivoreConverter<>)).Close(typeof(Orca)).GetType() == typeof(CarnivoreConverter)); } public void InterfaceFamily_IsNullForTypesThatAreNotConcreteImplementers() { OpenConverter open = OpenConverter.Of(typeof(AquaticConverter<>)); CheckNull(open.Close(typeof(AbstractAquatic))); CheckNull(open.Close(typeof(IAquatic))); CheckNull(open.Close(typeof(Lynx))); CheckNull(open.Close(typeof(int))); } public void InterfaceFamilyOfAGenericInterface_TakesTheOtherParametersFromTheInterface() { SaveConverter closed = OpenConverter.Of(typeof(VesselConverter<,>)).Close(typeof(Barrel)); CheckTrue(closed.GetType() == typeof(VesselConverter)); } public void InterfaceImplementedAtTwoInstantiations_Throws() { OpenConverter open = OpenConverter.Of(typeof(VesselConverter<,>)); CheckThrow(typeof(InvalidOperationException)); open.Close(typeof(Twin)); } public void FamilyOfAGenericBase_TakesTheOtherParametersFromTheBase() { OpenConverter open = OpenConverter.Of(typeof(HerdConverter<,>)); CheckTrue(open.Close(typeof(IntHerd)).GetType() == typeof(HerdConverter)); CheckTrue(open.Close(typeof(StringHerd)).GetType() == typeof(HerdConverter)); CheckTrue(open.Close(typeof(Herd)).GetType() == typeof(HerdConverter, double>)); } public void FamilyOfAGenericBase_FindsTheBaseBeneathOtherGenericTypes() { SaveConverter closed = OpenConverter.Of(typeof(HerdConverter<,>)).Close(typeof(NameHerd)); CheckTrue(closed.GetType() == typeof(HerdConverter)); } public void FamilyOfAGenericBase_IsNullForAnotherGenericType() { CheckNull(OpenConverter.Of(typeof(HerdConverter<,>)).Close(typeof(Pairing))); } public void FamilyWhoseArgumentBreaksAConstraint_IsNull() { OpenConverter open = OpenConverter.Of(typeof(StructHerdConverter<,>)); CheckNull(open.Close(typeof(StringHerd))); CheckTrue(open.Close(typeof(IntHerd)).GetType() == typeof(StructHerdConverter)); } public void FamilyConstructorThatThrows_ThrowsItsOwnException() { OpenConverter open = OpenConverter.Of(typeof(ThrowingCreatureConverter<>)); CheckThrow(typeof(FormatException)); open.Close(typeof(Wolf)); } } } }