using System; using System.Collections.Generic; using System.Linq; using UnitTestSharp; namespace Vellum.UnitTests { public class LoadAdjustmentTests : TestFixture { public enum Color { Red, Green = 5, } [Flags] public enum Toppings { None = 0, Nuts = 1, Cream = 2, } public enum Tiny : byte { Low = 1, } public static IReadOnlyList Load(string text, out T value) { SaveSession session = SaveConvertersTests.Session(); SaveNode list = SaveNode.NewList(); list.Items.Add(SaveNode.OfText(text)); T[] loaded = session.FromNode(list); value = loaded[0]; return session.Sandbox.Issues; } public static string DoubleText(double number) { return SavedValue.DoubleText(number); } public class IntegerTests : TestFixture { public void ExactFit_RecordsNothing() { byte value; CheckEqual(0, Load("200", out value).Count); CheckEqual((byte)200, value); } public void TooBig_IsClamped() { byte value; IReadOnlyList issues = Load("300", out value); CheckEqual((byte)255, value); CheckEqual(LoadIssueKind.Clamped, issues.Single().Kind); CheckEqual("[0]", issues.Single().Path); } public void NegativeForAnUnsigned_IsClampedToZero() { uint value; CheckEqual(LoadIssueKind.Clamped, Load("-5", out value).Single().Kind); CheckEqual(0u, value); } public void TooBigForALong_IsClampedToTheMaximum() { long value; CheckEqual(LoadIssueKind.Clamped, Load("99999999999999999999", out value).Single().Kind); CheckEqual(long.MaxValue, value); } public void UnsignedMaximum_IsExact() { ulong value; CheckEqual(0, Load(ulong.MaxValue.ToString(), out value).Count); CheckEqual(ulong.MaxValue, value); } public void WholeDoubleThatFits_RecordsNothing() { int value; CheckEqual(0, Load(DoubleText(5.0), out value).Count); CheckEqual(5, value); } public void WholeDoubleBeyondTheType_IsClamped() { int value; CheckEqual(LoadIssueKind.Clamped, Load(DoubleText(1e12), out value).Single().Kind); CheckEqual(int.MaxValue, value); } public void FractionalDouble_IsRoundedToTheNearestWholeNumber() { int value; CheckEqual(LoadIssueKind.Rounded, Load(DoubleText(2.5), out value).Single().Kind); CheckEqual(3, value); } public void NegativeFractionalDouble_IsRoundedAwayFromZero() { int value; Load(DoubleText(-2.5), out value); CheckEqual(-3, value); } public void NaN_LeavesTheInitialValueAndRecordsIt() { SaveSession session = SaveConvertersTests.Session(); SaveNode list = SaveNode.NewList(); list.Items.Add(SaveNode.OfText(DoubleText(double.NaN))); session.FromNode(list); CheckEqual(LoadIssueKind.BadData, session.Sandbox.Issues.Single().Kind); } public void ExactDoubleInAnIntegerNode_RecordsNothing() { SaveSession session = SaveConvertersTests.Session(); SaveNode list = SaveNode.NewList(); list.Items.Add(SaveNode.OfDouble(7.0)); int[] loaded = session.FromNode(list); CheckEqual(7, loaded[0]); CheckEqual(0, session.Sandbox.Issues.Count); } } public class FloatingPointTests : TestFixture { public void IntegerThatIsAnExactDouble_RecordsNothing() { double value; CheckEqual(0, Load("9007199254740992", out value).Count); CheckEqual(9007199254740992.0, value); } public void IntegerPastTwoToThe53_IsRounded() { double value; CheckEqual(LoadIssueKind.Rounded, Load("9007199254740993", out value).Single().Kind); CheckEqual(9007199254740992.0, value); } public void LargeIntegerThatIsAnExactDouble_RecordsNothing() { double value; CheckEqual(0, Load("1152921504606846976", out value).Count); } public void SmallInteger_RecordsNothing() { double value; CheckEqual(0, Load("12", out value).Count); CheckEqual(12.0, value); } public void DoubleThatIsExactlyAFloat_RecordsNothing() { float value; CheckEqual(0, Load(DoubleText(0.5), out value).Count); CheckEqual(0.5f, value); } public void DoubleThatIsNotAFloat_IsRounded() { float value; CheckEqual(LoadIssueKind.Rounded, Load(DoubleText(0.1), out value).Single().Kind); CheckEqual(0.1f, value); } public void DoubleTooBigForAFloat_IsClampedToInfinity() { float value; CheckEqual(LoadIssueKind.Clamped, Load(DoubleText(1e300), out value).Single().Kind); CheckTrue(float.IsPositiveInfinity(value)); } public void NaNInAFloat_RecordsNothing() { float value; CheckEqual(0, Load(DoubleText(double.NaN), out value).Count); CheckTrue(float.IsNaN(value)); } } public class EnumTests : TestFixture { public void Name_RecordsNothing() { Color value; CheckEqual(0, Load("Green", out value).Count); CheckEqual(Color.Green, value); } public void NumberOfAMember_LoadsTheMemberAndRecordsIt() { Color value; CheckEqual(LoadIssueKind.NumberAsEnum, Load("5", out value).Single().Kind); CheckEqual(Color.Green, value); } public void NumberOfNoMember_IsRecordedAndNothingIsLoaded() { SaveSession session = SaveConvertersTests.Session(); SaveNode list = SaveNode.NewList(); list.Items.Add(SaveNode.OfText("3")); Color[] loaded = session.FromNode(list); CheckEqual(Color.Red, loaded[0]); CheckEqual(LoadIssueKind.UndefinedEnumValue, session.Sandbox.Issues.Single().Kind); } public void NumberTooBigForTheUnderlyingType_IsUndefined() { SaveSession session = SaveConvertersTests.Session(); SaveNode list = SaveNode.NewList(); list.Items.Add(SaveNode.OfText("257")); session.FromNode(list); CheckEqual(LoadIssueKind.UndefinedEnumValue, session.Sandbox.Issues.Single().Kind); } public void NegativeNumberForAnUnsignedEnum_IsUndefined() { SaveSession session = SaveConvertersTests.Session(); SaveNode list = SaveNode.NewList(); list.Items.Add(SaveNode.OfText("-1")); session.FromNode(list); CheckEqual(LoadIssueKind.UndefinedEnumValue, session.Sandbox.Issues.Single().Kind); } public void FlagsCombination_LoadsAndRecordsIt() { Toppings value; CheckEqual(LoadIssueKind.NumberAsEnum, Load("3", out value).Single().Kind); CheckEqual(Toppings.Nuts | Toppings.Cream, value); } public void FlagsNumberWithAnUndefinedBit_IsUndefined() { SaveSession session = SaveConvertersTests.Session(); SaveNode list = SaveNode.NewList(); list.Items.Add(SaveNode.OfText("4")); session.FromNode(list); CheckEqual(LoadIssueKind.UndefinedEnumValue, session.Sandbox.Issues.Single().Kind); } public void UnknownName_IsBadData() { SaveSession session = SaveConvertersTests.Session(); SaveNode list = SaveNode.NewList(); list.Items.Add(SaveNode.OfText("Blue")); session.FromNode(list); CheckEqual(LoadIssueKind.BadData, session.Sandbox.Issues.Single().Kind); } public void RootEnumThatIsUndefined_Throws() { CheckThrow(typeof(UndefinedEnumValueException)); SaveConvertersTests.Session().FromNode(SaveNode.OfText("3")); } } public class StrictTests : TestFixture { public void SavedValueWithoutNotes_StillThrowsForANumberOutOfRange() { byte value; CheckThrow(typeof(System.IO.InvalidDataException)); SavedValue.TryFromNode(SaveNode.OfText("300"), out value); } public void SavedValueWithoutNotes_StillReadsANumberAsAnEnumName() { CheckEqual(Color.Green, SavedValue.FromNode(SaveNode.OfText("5"), typeof(Color))); } } } }