public void JsonObjectDynamicGetters()
        {
            dynamic team = new JsonObject();

            team["TeamSize"]    = this.teamMembersValues.Length;
            team["TeamName"]    = this.teamNameValue;
            team["TeamMascots"] = null;
            team["TeamMembers"] = new JsonArray
            {
                this.teamMembersValues[0], this.teamMembersValues[1], this.teamMembersValues[2],
                this.teamMembersValues[3], this.teamMembersValues[4]
            };

            Assert.Equal(this.teamMembersValues.Length, (int)team.TeamSize);
            Assert.Equal(this.teamNameValue, (string)team.TeamName);
            Assert.NotNull(team.TeamMascots);
            Assert.True(team.TeamMascots is JsonValue); // default

            for (int i = 0; i < this.teamMembersValues.Length; i++)
            {
                Assert.Equal(this.teamMembersValues[i], (string)team.TeamMembers[i]);
            }

            for (int i = 0; i < this.teamMembersValues.Length; i++)
            {
                Assert.Equal(this.teamMembersValues[i], (string)team.TeamMembers[i]);
            }

            // Negative tests for getters
            JsonValueTests.ExpectException <InvalidCastException>(delegate { int fail = (int)team.NonExistentProp; });
        }
        public void ArithmeticConversion()
        {
            JsonObject jo = new JsonObject
            {
                { "byteVal", (byte)10 },
                { "sbyteVal", (sbyte)10 },
                { "shortVal", (short)10 },
                { "ushortVal", (ushort)10 },
                { "intVal", 10 },
                { "uintVal", (uint)10 },
                { "longVal", 10L },
                { "ulongVal", (ulong)10 },
                { "charVal", (char)10 },
                { "decimalVal", 10m },
                { "doubleVal", 10.0 },
                { "floatVal", 10f },
            };
            dynamic dyn = jo;

            Log.Info("Conversion from byte");
            // DISABLED, 197387, ValidateResult<int>(dyn.byteVal + (byte)10, 20);
            JsonValueTests.ExpectException <InvalidOperationException>(() => Log.Info("{0}", dyn.byteVal + (sbyte)10));
            ValidateResult <short>(dyn.byteVal + (short)10, 20);
            ValidateResult <ushort>(dyn.byteVal + (ushort)10, 20);
            ValidateResult <int>(dyn.byteVal + (int)10, 20);
            ValidateResult <uint>(dyn.byteVal + (uint)10, 20);
            ValidateResult <long>(dyn.byteVal + 10L, 20);
            ValidateResult <ulong>(dyn.byteVal + (ulong)10, 20);
            ValidateResult <decimal>(dyn.byteVal + 10m, 20);
            ValidateResult <float>(dyn.byteVal + 10f, 20);
            ValidateResult <double>(dyn.byteVal + 10.0, 20);

            Log.Info("Conversion from sbyte");
            JsonValueTests.ExpectException <InvalidOperationException>(() => Log.Info("{0}", dyn.sbyteVal + (byte)10));
            // DISABLED, 197387, ValidateResult<int>(dyn.sbyteVal + (sbyte)10, 20);
            ValidateResult <short>(dyn.sbyteVal + (short)10, 20);
            JsonValueTests.ExpectException <InvalidOperationException>(() => Log.Info("{0}", dyn.sbyteVal + (ushort)10));
            ValidateResult <int>(dyn.sbyteVal + (int)10, 20);
            JsonValueTests.ExpectException <InvalidOperationException>(() => Log.Info("{0}", dyn.sbyteVal + (uint)10));
            ValidateResult <long>(dyn.sbyteVal + 10L, 20);
            JsonValueTests.ExpectException <InvalidOperationException>(() => Log.Info("{0}", dyn.sbyteVal + (ulong)10));
            ValidateResult <decimal>(dyn.sbyteVal + 10m, 20);
            ValidateResult <float>(dyn.sbyteVal + 10f, 20);
            ValidateResult <double>(dyn.sbyteVal + 10.0, 20);

            Log.Info("Conversion from short");
            ValidateResult <short>(dyn.shortVal + (byte)10, 20);
            ValidateResult <short>(dyn.shortVal + (sbyte)10, 20);
            ValidateResult <short>(dyn.shortVal + (short)10, 20);
            JsonValueTests.ExpectException <InvalidOperationException>(() => Log.Info("{0}", dyn.shortVal + (ushort)10));
            ValidateResult <int>(dyn.shortVal + (int)10, 20);
            JsonValueTests.ExpectException <InvalidOperationException>(() => Log.Info("{0}", dyn.shortVal + (uint)10));
            ValidateResult <long>(dyn.shortVal + 10L, 20);
            JsonValueTests.ExpectException <InvalidOperationException>(() => Log.Info("{0}", dyn.shortVal + (ulong)10));
            ValidateResult <decimal>(dyn.shortVal + 10m, 20);
            ValidateResult <float>(dyn.shortVal + 10f, 20);
            ValidateResult <double>(dyn.shortVal + 10.0, 20);

            Log.Info("Conversion from ushort");
            ValidateResult <ushort>(dyn.ushortVal + (byte)10, 20);
            JsonValueTests.ExpectException <InvalidOperationException>(() => Log.Info("{0}", dyn.ushortVal + (sbyte)10));
            JsonValueTests.ExpectException <InvalidOperationException>(() => Log.Info("{0}", dyn.ushortVal + (short)10));
            ValidateResult <ushort>(dyn.ushortVal + (ushort)10, 20);
            ValidateResult <int>(dyn.ushortVal + (int)10, 20);
            ValidateResult <uint>(dyn.ushortVal + (uint)10, 20);
            ValidateResult <long>(dyn.ushortVal + 10L, 20);
            ValidateResult <ulong>(dyn.ushortVal + (ulong)10, 20);
            ValidateResult <decimal>(dyn.ushortVal + 10m, 20);
            ValidateResult <float>(dyn.ushortVal + 10f, 20);
            ValidateResult <double>(dyn.ushortVal + 10.0, 20);

            Log.Info("Conversion from int");
            ValidateResult <int>(dyn.intVal + (byte)10, 20);
            ValidateResult <int>(dyn.intVal + (sbyte)10, 20);
            ValidateResult <int>(dyn.intVal + (short)10, 20);
            ValidateResult <int>(dyn.intVal + (ushort)10, 20);
            ValidateResult <int>(dyn.intVal + (int)10, 20);
            JsonValueTests.ExpectException <InvalidOperationException>(() => Log.Info("{0}", dyn.intVal + (uint)10));
            ValidateResult <long>(dyn.intVal + 10L, 20);
            JsonValueTests.ExpectException <InvalidOperationException>(() => Log.Info("{0}", dyn.intVal + (ulong)10));
            ValidateResult <decimal>(dyn.intVal + 10m, 20);
            ValidateResult <float>(dyn.intVal + 10f, 20);
            ValidateResult <double>(dyn.intVal + 10.0, 20);

            Log.Info("Conversion from uint");
            ValidateResult <uint>(dyn.uintVal + (byte)10, 20);
            JsonValueTests.ExpectException <InvalidOperationException>(() => Log.Info("{0}", dyn.uintVal + (sbyte)10));
            JsonValueTests.ExpectException <InvalidOperationException>(() => Log.Info("{0}", dyn.uintVal + (short)10));
            ValidateResult <uint>(dyn.uintVal + (ushort)10, 20);
            JsonValueTests.ExpectException <InvalidOperationException>(() => Log.Info("{0}", dyn.uintVal + (int)10));
            ValidateResult <uint>(dyn.uintVal + (uint)10, 20);
            ValidateResult <long>(dyn.uintVal + 10L, 20);
            ValidateResult <ulong>(dyn.uintVal + (ulong)10, 20);
            ValidateResult <decimal>(dyn.uintVal + 10m, 20);
            ValidateResult <float>(dyn.uintVal + 10f, 20);
            ValidateResult <double>(dyn.uintVal + 10.0, 20);

            Log.Info("Conversion from long");
            ValidateResult <long>(dyn.longVal + (byte)10, 20);
            ValidateResult <long>(dyn.longVal + (sbyte)10, 20);
            ValidateResult <long>(dyn.longVal + (short)10, 20);
            ValidateResult <long>(dyn.longVal + (ushort)10, 20);
            ValidateResult <long>(dyn.longVal + (int)10, 20);
            ValidateResult <long>(dyn.longVal + (uint)10, 20);
            ValidateResult <long>(dyn.longVal + 10L, 20);
            JsonValueTests.ExpectException <InvalidOperationException>(() => Log.Info("{0}", dyn.longVal + (ulong)10));
            ValidateResult <decimal>(dyn.longVal + 10m, 20);
            ValidateResult <float>(dyn.longVal + 10f, 20);
            ValidateResult <double>(dyn.longVal + 10.0, 20);

            Log.Info("Conversion from ulong");
            ValidateResult <ulong>(dyn.ulongVal + (byte)10, 20);
            JsonValueTests.ExpectException <InvalidOperationException>(() => Log.Info("{0}", dyn.ulongVal + (sbyte)10));
            JsonValueTests.ExpectException <InvalidOperationException>(() => Log.Info("{0}", dyn.ulongVal + (short)10));
            ValidateResult <ulong>(dyn.ulongVal + (ushort)10, 20);
            JsonValueTests.ExpectException <InvalidOperationException>(() => Log.Info("{0}", dyn.ulongVal + (int)10));
            ValidateResult <ulong>(dyn.ulongVal + (uint)10, 20);
            JsonValueTests.ExpectException <InvalidOperationException>(() => Log.Info("{0}", dyn.ulongVal + (long)10));
            ValidateResult <ulong>(dyn.ulongVal + (ulong)10, 20);
            ValidateResult <decimal>(dyn.ulongVal + 10m, 20);
            ValidateResult <float>(dyn.ulongVal + 10f, 20);
            ValidateResult <double>(dyn.ulongVal + 10.0, 20);

            Log.Info("Conversion from float");
            ValidateResult <float>(dyn.floatVal + (byte)10, 20);
            ValidateResult <float>(dyn.floatVal + (sbyte)10, 20);
            ValidateResult <float>(dyn.floatVal + (short)10, 20);
            ValidateResult <float>(dyn.floatVal + (ushort)10, 20);
            ValidateResult <float>(dyn.floatVal + (int)10, 20);
            ValidateResult <float>(dyn.floatVal + (uint)10, 20);
            ValidateResult <float>(dyn.floatVal + 10L, 20);
            ValidateResult <float>(dyn.floatVal + (ulong)10, 20);
            JsonValueTests.ExpectException <InvalidOperationException>(() => Log.Info("{0}", dyn.floatVal + 10m));
            ValidateResult <float>(dyn.floatVal + 10f, 20);
            ValidateResult <double>(dyn.floatVal + 10.0, 20);

            Log.Info("Conversion from double");
            ValidateResult <double>(dyn.doubleVal + (byte)10, 20);
            ValidateResult <double>(dyn.doubleVal + (sbyte)10, 20);
            ValidateResult <double>(dyn.doubleVal + (short)10, 20);
            ValidateResult <double>(dyn.doubleVal + (ushort)10, 20);
            ValidateResult <double>(dyn.doubleVal + (int)10, 20);
            ValidateResult <double>(dyn.doubleVal + (uint)10, 20);
            ValidateResult <double>(dyn.doubleVal + 10L, 20);
            ValidateResult <double>(dyn.doubleVal + (ulong)10, 20);
            JsonValueTests.ExpectException <InvalidOperationException>(() => Log.Info("{0}", dyn.doubleVal + 10m));
            ValidateResult <double>(dyn.doubleVal + 10f, 20);
            ValidateResult <double>(dyn.doubleVal + 10.0, 20);

            Log.Info("Conversion from decimal");
            ValidateResult <decimal>(dyn.decimalVal + (byte)10, 20);
            ValidateResult <decimal>(dyn.decimalVal + (sbyte)10, 20);
            ValidateResult <decimal>(dyn.decimalVal + (short)10, 20);
            ValidateResult <decimal>(dyn.decimalVal + (ushort)10, 20);
            ValidateResult <decimal>(dyn.decimalVal + (int)10, 20);
            ValidateResult <decimal>(dyn.decimalVal + (uint)10, 20);
            ValidateResult <decimal>(dyn.decimalVal + 10L, 20);
            ValidateResult <decimal>(dyn.decimalVal + (ulong)10, 20);
            ValidateResult <decimal>(dyn.decimalVal + 10m, 20);
            JsonValueTests.ExpectException <InvalidOperationException>(() => Log.Info("{0}", dyn.decimalVal + 10f));
            JsonValueTests.ExpectException <InvalidOperationException>(() => Log.Info("{0}", dyn.decimalVal + 10.0));
        }
        public void DynamicRelationalOperators()
        {
            JsonValue jv = new JsonObject {
                { "one", 1 }, { "one_point_two", 1.2 }, { "decimal_one_point_one", 1.1m }, { "trueValue", true }, { "str", "hello" }
            };
            dynamic   dyn = jv;
            JsonValue defaultJsonValue = jv.ValueOrDefault(-1);

            Log.Info("Equality");
            Assert.True(dyn.one == 1);
            Assert.True(dyn.one_point_two == 1.2);
            Assert.False(dyn.one == 1.2);
            Assert.False(dyn.one_point_two == 1);
            Assert.False(dyn.one == 2);
            Assert.False(dyn.one_point_two == 1.3);
            Assert.True(dyn.one == 1m);
            Assert.False(dyn.one == 2m);
            Assert.True(dyn.decimal_one_point_one == 1.1m);

            Assert.True(dyn.NotHere == null);
            Assert.True(dyn.NotHere == dyn.NotHere);
            Assert.True(dyn.NotHere == defaultJsonValue);
            // DISABLED, 197375, Assert.False(dyn.NotHere == 1);
            Assert.False(dyn.NotHere == jv);

            Log.Info("Inequality");
            Assert.False(dyn.one != 1);
            Assert.False(dyn.one_point_two != 1.2);
            Assert.True(dyn.one != 1.2);
            Assert.True(dyn.one_point_two != 1);
            Assert.True(dyn.one != 2);
            Assert.True(dyn.one_point_two != 1.3);
            Assert.False(dyn.one != 1m);
            Assert.True(dyn.one != 2m);

            Assert.False(dyn.NotHere != null);
            Assert.False(dyn.NotHere != dyn.NotHere);
            Assert.False(dyn.NotHere != defaultJsonValue);
            // DISABLED, 197375, Assert.True(dyn.NotHere != 1);
            Assert.True(dyn.NotHere != jv);

            Log.Info("Less than");
            Assert.True(dyn.one < 2);
            Assert.False(dyn.one < 1);
            Assert.False(dyn.one < 0);
            Assert.True(dyn.one_point_two < 1.3);
            Assert.False(dyn.one_point_two < 1.2);
            Assert.False(dyn.one_point_two < 1.1);

            Assert.True(dyn.one < 1.1);
            Assert.Equal(1 < 1.0, dyn.one < 1.0);
            Assert.False(dyn.one < 0.9);
            Assert.True(dyn.one_point_two < 2);
            Assert.False(dyn.one_point_two < 1);
            Assert.Equal(1.2 < 1.2f, dyn.one_point_two < 1.2f);

            Log.Info("Greater than");
            Assert.False(dyn.one > 2);
            Assert.False(dyn.one > 1);
            Assert.True(dyn.one > 0);
            Assert.False(dyn.one_point_two > 1.3);
            Assert.False(dyn.one_point_two > 1.2);
            Assert.True(dyn.one_point_two > 1.1);

            Assert.False(dyn.one > 1.1);
            Assert.Equal(1 > 1.0, dyn.one > 1.0);
            Assert.True(dyn.one > 0.9);
            Assert.False(dyn.one_point_two > 2);
            Assert.True(dyn.one_point_two > 1);
            Assert.Equal(1.2 > 1.2f, dyn.one_point_two > 1.2f);

            Log.Info("Less than or equals");
            Assert.True(dyn.one <= 2);
            Assert.True(dyn.one <= 1);
            Assert.False(dyn.one <= 0);
            Assert.True(dyn.one_point_two <= 1.3);
            Assert.True(dyn.one_point_two <= 1.2);
            Assert.False(dyn.one_point_two <= 1.1);

            Assert.True(dyn.one <= 1.1);
            Assert.Equal(1 <= 1.0, dyn.one <= 1.0);
            Assert.False(dyn.one <= 0.9);
            Assert.True(dyn.one_point_two <= 2);
            Assert.False(dyn.one_point_two <= 1);
            Assert.Equal(1.2 <= 1.2f, dyn.one_point_two <= 1.2f);

            Log.Info("Greater than or equals");
            Assert.False(dyn.one >= 2);
            Assert.True(dyn.one >= 1);
            Assert.True(dyn.one >= 0);
            Assert.False(dyn.one_point_two >= 1.3);
            Assert.True(dyn.one_point_two >= 1.2);
            Assert.True(dyn.one_point_two >= 1.1);

            Assert.False(dyn.one >= 1.1);
            Assert.Equal(1 >= 1.0, dyn.one >= 1.0);
            Assert.True(dyn.one >= 0.9);
            Assert.False(dyn.one_point_two >= 2);
            Assert.True(dyn.one_point_two >= 1);
            Assert.Equal(1.2 >= 1.2f, dyn.one_point_two >= 1.2f);

            Log.Info("Invalid number conversions");
            JsonValueTests.ExpectException <InvalidOperationException>(() => { Log.Info(dyn.decimal_one_point_one == 1.1); });
            JsonValueTests.ExpectException <InvalidOperationException>(() => { Log.Info(dyn.one != (uint)2); });

            Log.Info("Invalid data types for relational operators");
            JsonValueTests.ExpectException <InvalidOperationException>(() => { Log.Info(dyn.trueValue >= dyn.trueValue); });
            JsonValueTests.ExpectException <InvalidOperationException>(() => { Log.Info(dyn.NotHere < dyn.NotHere); });
            JsonValueTests.ExpectException <InvalidOperationException>(() => { Log.Info(dyn.str < "Jello"); });

            // DISABLED, 197315
            Log.Info("Conversions from string");
            jv = new JsonObject {
                { "one", "1" }, { "twelve_point_two", "1.22e1" }
            };
            dyn = jv;
            Assert.True(dyn.one == 1);
            Assert.True(dyn.twelve_point_two == 1.22e1);
            Assert.True(dyn.one >= 0.5f);
            Assert.True(dyn.twelve_point_two <= 13);
            Assert.True(dyn.one < 2);
            Assert.Equal(dyn.twelve_point_two.ReadAs <int>() > 12, dyn.twelve_point_two > 12);
        }
        public void DynamicBooleanOperators()
        {
            JsonValue jv;
            dynamic   dyn;

            foreach (bool value in new bool[] { true, false })
            {
                jv  = value;
                dyn = jv;
                Log.Info("IsTrue, {0}", jv);
                if (dyn)
                {
                    Assert.True(value, "Boolean evaluation should not enter 'if' clause.");
                }
                else
                {
                    Assert.False(value, "Boolean evaluation should not enter 'else' clause.");
                }
            }

            foreach (string value in new string[] { "true", "false", "True", "False" })
            {
                bool isTrueValue = value.Equals("true", StringComparison.InvariantCultureIgnoreCase);
                jv  = new JsonPrimitive(value);
                dyn = jv;
                Log.Info("IsTrue, {0}", jv);
                if (dyn)
                {
                    Assert.True(isTrueValue, "Boolean evaluation should not enter 'if' clause.");
                }
                else
                {
                    Assert.False(isTrueValue, "Boolean evaluation should not enter 'else' clause.");
                }
            }

            foreach (bool first in new bool[] { false, true })
            {
                dynamic dyn1 = new JsonPrimitive(first);
                Log.Info("Negation, {0}", first);
                Assert.Equal(!first, !dyn1);
                foreach (bool second in new bool[] { false, true })
                {
                    dynamic dyn2 = new JsonPrimitive(second);
                    Log.Info("Boolean AND, {0} && {1}", first, second);
                    Assert.Equal(first && second, (bool)(dyn1 && dyn2));
                    Log.Info("Boolean OR, {0} && {1}", first, second);
                    Assert.Equal(first || second, (bool)(dyn1 || dyn2));
                }
            }

            Log.Info("Invalid boolean operator usage");
            dynamic boolDyn = new JsonPrimitive(true);
            dynamic intDyn  = new JsonPrimitive(1);
            dynamic strDyn  = new JsonPrimitive("hello");

            JsonValueTests.ExpectException <InvalidOperationException>(() => { Log.Info("{0}", !intDyn); });

            JsonValueTests.ExpectException <InvalidOperationException>(() => { Log.Info("{0}", !strDyn); });
            JsonValueTests.ExpectException <InvalidCastException>(() => { Log.Info("{0}", intDyn && intDyn); });
            JsonValueTests.ExpectException <InvalidCastException>(() => { Log.Info("{0}", intDyn || true); });
            JsonValueTests.ExpectException <InvalidOperationException>(() => { Log.Info("{0}", boolDyn && 1); });
            JsonValueTests.ExpectException <InvalidOperationException>(() => { Log.Info("{0}", boolDyn && intDyn); });
            JsonValueTests.ExpectException <InvalidOperationException>(() => { Log.Info("{0}", boolDyn && "hello"); });
            JsonValueTests.ExpectException <InvalidOperationException>(() => { Log.Info("{0}", boolDyn && strDyn); });
            JsonValueTests.ExpectException <FormatException>(() => { Log.Info("{0}", strDyn && boolDyn); });
            JsonValueTests.ExpectException <FormatException>(() => { Log.Info("{0}", strDyn || true); });

            JsonValueTests.ExpectException <InvalidOperationException>(() => { Log.Info("{0}", !intDyn.NotHere); });
            JsonValueTests.ExpectException <InvalidOperationException>(() => { Log.Info("{0}", !intDyn.NotHere && true); });
            JsonValueTests.ExpectException <InvalidOperationException>(() => { Log.Info("{0}", !intDyn.NotHere || false); });
        }