public void CannotTryGetValueAtPath()
        {
            var container = new PropertyPathTestContainer();

            Assert.That(container.Float, Is.EqualTo(5.0f));
            Assert.That(container.Strings, Is.EqualTo(new [] { "one", "two", "three" }));
            Assert.That(container.Nested.Int, Is.EqualTo(15));
            Assert.That(container.Nested.Doubles, Is.EqualTo(new [] { 1.0, 2.0, 3.0 }));

            container.Float = 20.0f;
            {
                Assert.That(PropertyContainer.TryGetValueAtPath <PropertyPathTestContainer, float>(ref container, new PropertyPath("Floats"), out var value), Is.EqualTo(false));
            }
            container.Strings[1] = "four";
            {
                Assert.That(PropertyContainer.TryGetValueAtPath <PropertyPathTestContainer, string>(ref container, new PropertyPath("String[1]"), out var value), Is.EqualTo(false));
            }
            container.Nested.Int = 5;
            {
                Assert.That(PropertyContainer.TryGetValueAtPath <PropertyPathTestContainer, int>(ref container, new PropertyPath("Nested.Ints"), out var value), Is.EqualTo(false));
            }
            container.Nested.Doubles[2] = 6.0;
            {
                Assert.That(PropertyContainer.TryGetValueAtPath <PropertyPathTestContainer, double>(ref container, new PropertyPath("Nested.Dobles[2]"), out var value), Is.EqualTo(false));
            }
        }
        public void CanTrySetCountAtPath()
        {
            var container = new PropertyPathTestContainer();

            container.Strings.Clear();
            container.Strings.AddRange(new [] { "This", "Has", "Five", "Items", "!" });

            Assert.That(PropertyContainer.TrySetCountAtPath(ref container, new PropertyPath("Strings"), 3), Is.EqualTo(true));
            Assert.That(container.Strings.Count, Is.EqualTo(3));
            Assert.That(container.Strings[0], Is.EqualTo("This"));
            Assert.That(container.Strings[1], Is.EqualTo("Has"));
            Assert.That(container.Strings[2], Is.EqualTo("Five"));

            Assert.That(PropertyContainer.TrySetCountAtPath(ref container, new PropertyPath("Strings"), 4), Is.EqualTo(true));
            Assert.That(container.Strings.Count, Is.EqualTo(4));
            Assert.That(container.Strings[3], Is.EqualTo(null));

            container.Nested.Doubles.Clear();
            container.Nested.Doubles.AddRange(new [] { 1.0, 2.0, 3.0 });
            Assert.That(PropertyContainer.TrySetCountAtPath(ref container, new PropertyPath("Nested.Doubles"), 4), Is.EqualTo(true));
            Assert.That(container.Nested.Doubles.Count, Is.EqualTo(4));
            Assert.That(container.Nested.Doubles[0], Is.EqualTo(1.0));
            Assert.That(container.Nested.Doubles[1], Is.EqualTo(2.0));
            Assert.That(container.Nested.Doubles[2], Is.EqualTo(3.0));
            Assert.That(container.Nested.Doubles[3], Is.EqualTo(0.0));
        }
        public void CannotGetValueAtPath()
        {
            var container = new PropertyPathTestContainer();

            Assert.That(container.Float, Is.EqualTo(5.0f));
            Assert.That(container.Strings, Is.EqualTo(new [] { "one", "two", "three" }));
            Assert.That(container.Nested.Int, Is.EqualTo(15));
            Assert.That(container.Nested.Doubles, Is.EqualTo(new [] { 1.0, 2.0, 3.0 }));

            container.Float = 20.0f;
            Assert.Throws <ArgumentException>(() => PropertyContainer.GetValueAtPath <PropertyPathTestContainer, float>(ref container, new PropertyPath("Floatd")));
            Assert.Throws <InvalidCastException>(() => PropertyContainer.GetValueAtPath <PropertyPathTestContainer, VisitErrorCode>(ref container, new PropertyPath("Float")));

            container.Strings[1] = "four";
            Assert.Throws <ArgumentException>(() => PropertyContainer.GetValueAtPath <PropertyPathTestContainer, string>(ref container, new PropertyPath("String[1]")));
            Assert.Throws <InvalidCastException>(() => PropertyContainer.GetValueAtPath <PropertyPathTestContainer, VisitErrorCode>(ref container, new PropertyPath("Strings[1]")));

            container.Nested.Int = 5;

            Assert.Throws <ArgumentException>(() => PropertyContainer.GetValueAtPath <PropertyPathTestContainer, int>(ref container, new PropertyPath("Nested.Ints")));
            Assert.Throws <InvalidCastException>(() => PropertyContainer.GetValueAtPath <PropertyPathTestContainer, PropertyPathTests>(ref container, new PropertyPath("Nested.Int")));

            container.Nested.Doubles[2] = 6.0;
            Assert.Throws <ArgumentException>(() => PropertyContainer.GetValueAtPath <PropertyPathTestContainer, double>(ref container, new PropertyPath("Nested.Double[2]")));
            Assert.Throws <InvalidCastException>(() => PropertyContainer.GetValueAtPath <PropertyPathTestContainer, VisitErrorCode>(ref container, new PropertyPath("Nested.Doubles[2]")));
        }
        public void CannotTrySetValueAtPath()
        {
            var container = new PropertyPathTestContainer();

            Assert.That(container.Float, Is.EqualTo(5.0f));
            Assert.That(container.Strings, Is.EqualTo(new [] { "one", "two", "three" }));
            Assert.That(container.Nested.Int, Is.EqualTo(15));
            Assert.That(container.Nested.Doubles, Is.EqualTo(new [] { 1.0, 2.0, 3.0 }));

            Assert.That(PropertyContainer.TrySetValueAtPath(ref container, new PropertyPath("Floats"), 20.0f), Is.EqualTo(false));
            Assert.That(container.Float, Is.EqualTo(5.0f));

            Assert.That(PropertyContainer.TrySetValueAtPath(ref container, new PropertyPath("Float"), VisitErrorCode.Ok), Is.EqualTo(false));
            Assert.That(container.Float, Is.EqualTo(5.0f));

            Assert.That(PropertyContainer.TrySetValueAtPath(ref container, new PropertyPath("String[1]"), "four"), Is.EqualTo(false));
            Assert.That(container.Strings, Is.EqualTo(new [] { "one", "two", "three" }));

            Assert.That(PropertyContainer.TrySetValueAtPath(ref container, new PropertyPath("Strings[1]"), VisitErrorCode.Ok), Is.EqualTo(false));
            Assert.That(container.Strings, Is.EqualTo(new [] { "one", "two", "three" }));

            Assert.That(PropertyContainer.TrySetValueAtPath(ref container, new PropertyPath("Nested.Isnt"), 5), Is.EqualTo(false));
            Assert.That(container.Nested.Int, Is.EqualTo(15));

            Assert.That(PropertyContainer.TrySetValueAtPath(ref container, new PropertyPath("Nested.Int"), VisitErrorCode.Ok), Is.EqualTo(false));
            Assert.That(container.Nested.Int, Is.EqualTo(15));

            Assert.That(PropertyContainer.TrySetValueAtPath(ref container, new PropertyPath("Nested.Doublses[2]"), 6.0), Is.EqualTo(false));
            Assert.That(container.Nested.Doubles, Is.EqualTo(new [] { 1.0, 2.0, 3.0 }));

            Assert.That(PropertyContainer.TrySetValueAtPath(ref container, new PropertyPath("Nested.Doubles[2]"), VisitErrorCode.Ok), Is.EqualTo(false));
            Assert.That(container.Nested.Doubles, Is.EqualTo(new [] { 1.0, 2.0, 3.0 }));
        }
        public void CannotSetValueAtPath()
        {
            var container = new PropertyPathTestContainer();

            Assert.That(container.Float, Is.EqualTo(5.0f));
            Assert.That(container.Strings, Is.EqualTo(new [] { "one", "two", "three" }));
            Assert.That(container.Nested.Int, Is.EqualTo(15));
            Assert.That(container.Nested.Doubles, Is.EqualTo(new [] { 1.0, 2.0, 3.0 }));

            Assert.Throws <ArgumentException>(() => PropertyContainer.SetValueAtPath(ref container, new PropertyPath("Floats"), 20.0f));
            Assert.That(container.Float, Is.EqualTo(5.0f));

            Assert.Throws <InvalidCastException>(() => PropertyContainer.SetValueAtPath(ref container, new PropertyPath("Float"), VisitErrorCode.Ok));
            Assert.That(container.Float, Is.EqualTo(5.0f));

            Assert.Throws <ArgumentException>(() => PropertyContainer.SetValueAtPath(ref container, new PropertyPath("String[1]"), "four"));
            Assert.That(container.Strings, Is.EqualTo(new [] { "one", "two", "three" }));

            Assert.Throws <InvalidCastException>(() => PropertyContainer.SetValueAtPath(ref container, new PropertyPath("Strings[1]"), VisitErrorCode.Ok));
            Assert.That(container.Strings, Is.EqualTo(new [] { "one", "two", "three" }));

            Assert.Throws <ArgumentException>(() => PropertyContainer.SetValueAtPath(ref container, new PropertyPath("Nested.Isnt"), 5));
            Assert.That(container.Nested.Int, Is.EqualTo(15));

            Assert.Throws <InvalidCastException>(() => PropertyContainer.SetValueAtPath(ref container, new PropertyPath("Nested.Int"), VisitErrorCode.Ok));
            Assert.That(container.Nested.Int, Is.EqualTo(15));

            Assert.Throws <ArgumentException>(() => PropertyContainer.SetValueAtPath(ref container, new PropertyPath("Nested.Doublses[2]"), 6.0));
            Assert.That(container.Nested.Doubles, Is.EqualTo(new [] { 1.0, 2.0, 3.0 }));

            Assert.Throws <InvalidCastException>(() => PropertyContainer.SetValueAtPath(ref container, new PropertyPath("Nested.Doubles[2]"), VisitErrorCode.Ok));
            Assert.That(container.Nested.Doubles, Is.EqualTo(new [] { 1.0, 2.0, 3.0 }));
        }
        public void TryCanGetCountAtPath(string path, bool expected, int expectedCount)
        {
            var container    = new PropertyPathTestContainer();
            var propertyPath = new PropertyPath(path);

            Assert.That(PropertyContainer.TryGetCountAtPath(ref container, propertyPath, out var count), Is.EqualTo(expected));
            Assert.That(count == expectedCount);
        }
        public void CannotTrySetCountAtPath()
        {
            var container = new PropertyPathTestContainer();

            container.Strings.Clear();
            container.Strings.AddRange(new [] { "This", "Has", "Five", "Items", "!" });

            Assert.That(PropertyContainer.TrySetCountAtPath(ref container, new PropertyPath("Strisngs"), 3), Is.EqualTo(false));

            container.Nested.Doubles.Clear();
            container.Nested.Doubles.AddRange(new [] { 1.0, 2.0, 3.0 });
            Assert.That(PropertyContainer.TrySetCountAtPath(ref container, new PropertyPath("Nested.Double"), 4), Is.EqualTo(false));
        }
        public void CannotSetCountAtPath()
        {
            var container = new PropertyPathTestContainer();

            container.Strings.Clear();
            container.Strings.AddRange(new [] { "This", "Has", "Five", "Items", "!" });

            Assert.Throws <ArgumentException>(() => PropertyContainer.SetCountAtPath(ref container, new PropertyPath("Strisngs"), 3));

            container.Nested.Doubles.Clear();
            container.Nested.Doubles.AddRange(new [] { 1.0, 2.0, 3.0 });
            Assert.Throws <ArgumentException>(() => PropertyContainer.SetCountAtPath(ref container, new PropertyPath("Nested.Double"), 4));
        }
        public void CanTryVisitAtPath(string path, bool expected)
        {
            var container     = new PropertyPathTestContainer();
            var visitor       = new PathVisitor();
            var changeTracker = new ChangeTracker();
            var propertyPath  = new PropertyPath(path);

            Assert.That(PropertyContainer.TryVisitAtPath(ref container, propertyPath, visitor, ref changeTracker), Is.EqualTo(expected));
            if (expected)
            {
                var lastPart = propertyPath[propertyPath.PartsCount - 1];
                var name     = lastPart.IsListItem ? $"[{lastPart.Index}]" : lastPart.Name;
                Assert.That(visitor.Last == name);
            }
        }
        public void CanVisitAtPath(string path, bool expected)
        {
            var container     = new PropertyPathTestContainer();
            var visitor       = new PathVisitor();
            var changeTracker = new ChangeTracker();
            var propertyPath  = new PropertyPath(path);

            if (expected)
            {
                PropertyContainer.VisitAtPath(ref container, propertyPath, visitor, ref changeTracker);
                var lastPart = propertyPath[propertyPath.PartsCount - 1];
                var name     = lastPart.IsListItem ? $"[{lastPart.Index}]" : lastPart.Name;
                Assert.That(visitor.Last == name);
            }
            else
            {
                Assert.Throws <ArgumentException>(() => PropertyContainer.VisitAtPath(ref container, propertyPath, visitor, ref changeTracker));
            }
        }
        public void CanSetValueAtPath()
        {
            var container = new PropertyPathTestContainer();

            Assert.That(container.Float, Is.EqualTo(5.0f));
            Assert.That(container.Strings, Is.EqualTo(new [] { "one", "two", "three" }));
            Assert.That(container.Nested.Int, Is.EqualTo(15));
            Assert.That(container.Nested.Doubles, Is.EqualTo(new [] { 1.0, 2.0, 3.0 }));

            PropertyContainer.SetValueAtPath(ref container, new PropertyPath("Float"), 20.0f);
            Assert.That(container.Float, Is.EqualTo(20.0f));

            PropertyContainer.SetValueAtPath(ref container, new PropertyPath("Strings[1]"), "four");
            Assert.That(container.Strings, Is.EqualTo(new [] { "one", "four", "three" }));

            PropertyContainer.SetValueAtPath(ref container, new PropertyPath("Nested.Int"), 5);
            Assert.That(container.Nested.Int, Is.EqualTo(5));

            PropertyContainer.SetValueAtPath(ref container, new PropertyPath("Nested.Doubles[2]"), 6.0);
            Assert.That(container.Nested.Doubles, Is.EqualTo(new [] { 1.0, 2.0, 6.0 }));
        }
        public void CanGetValueAtPath()
        {
            var container = new PropertyPathTestContainer();

            Assert.That(container.Float, Is.EqualTo(5.0f));
            Assert.That(container.Strings, Is.EqualTo(new [] { "one", "two", "three" }));
            Assert.That(container.Nested.Int, Is.EqualTo(15));
            Assert.That(container.Nested.Doubles, Is.EqualTo(new [] { 1.0, 2.0, 3.0 }));

            container.Float = 20.0f;
            Assert.That(PropertyContainer.GetValueAtPath <PropertyPathTestContainer, float>(ref container, new PropertyPath("Float")), Is.EqualTo(container.Float));

            container.Strings[1] = "four";
            Assert.That(PropertyContainer.GetValueAtPath <PropertyPathTestContainer, string>(ref container, new PropertyPath("Strings[1]")), Is.EqualTo("four"));

            container.Nested.Int = 5;

            Assert.That(PropertyContainer.GetValueAtPath <PropertyPathTestContainer, int>(ref container, new PropertyPath("Nested.Int")), Is.EqualTo(container.Nested.Int));

            container.Nested.Doubles[2] = 6.0;
            Assert.That(PropertyContainer.GetValueAtPath <PropertyPathTestContainer, double>(ref container, new PropertyPath("Nested.Doubles[2]")), Is.EqualTo(6.0));
        }