예제 #1
0
        public void PropertyRecursion_callsOnMaxDepthReached()
        {
            var victim     = new RecursionVictim();
            var childTwo   = new RecursionChildTwo();
            var childThree = new RecursionChildThree
            {
                ChildTwo = childTwo
            };

            victim.PropChildTwo   = childTwo;
            victim.PropChildThree = childThree;

            Traverser.TraverseInstance(victim, 1, listener);

            A.CallTo(() => listener.OnMaxDepthReached(A <InstanceTraversalContext> ._)).MustHaveHappenedOnceExactly();
        }
예제 #2
0
        public void RecursionDoesNotCall_OnConstructor_forRecursedTypes()
        {
            var victim     = new RecursionVictim();
            var childTwo   = new RecursionChildTwo();
            var childThree = new RecursionChildThree
            {
                ChildTwo = childTwo
            };

            victim.PropChildTwo   = childTwo;
            victim.PropChildThree = childThree;

            Traverser.TraverseInstance(victim, 5, listener);

            var victimCtor = GetConstructor(typeof(RecursionVictim), new Type[0]);

            A.CallTo(() => listener.OnConstructor(A <ConstructorInfo> .That.Matches(x => x != victimCtor), A <InstanceTraversalContext> ._)).MustNotHaveHappened();
        }
예제 #3
0
        public void FieldRecursion_stopsWhenOnFieldReturnsFalse()
        {
            var victim     = new RecursionVictim();
            var childTwo   = new RecursionChildTwo();
            var childThree = new RecursionChildThree
            {
                ChildTwo = childTwo
            };

            victim.FieldChildTwo   = childTwo;
            victim.FieldChildThree = childThree;

            var type       = victim.GetType();
            var child2Type = typeof(RecursionChildTwo);
            var child3Type = typeof(RecursionChildThree);


            var callCounts = new Dictionary <string, int>
            {
                { ".FieldChildTwo", 0 },
                { "FieldChildTwo.ChildTwoString", 0 },
                { ".FieldChildThree", 0 },
                { "FieldChildThree.ChildThreeString", 0 },
                { "FieldChildThree.ChildTwo", 0 },
                { "FieldChildThree.ChildTwo.ChildTwoString", 0 }
            };

            // first we get a call for the top level child two field
            A.CallTo(() => listener.OnField(GetField(type, "FieldChildTwo"), A <Func <object> > ._, A <InstanceTraversalContext> ._))
            .Invokes(x =>
            {
                var ctx = (InstanceTraversalContext)x.Arguments[2];
                Assert.Equal(0, ctx.CurrentDepth);

                callCounts[".FieldChildTwo"]++;
            })
            .Returns(new SimpleInstanceListenerOnFieldOrPropResult {
                DoContinueRecursion = true
            });

            // we then dig into the top level child two field instance
            // and this is also triggered for the FieldChildThree.ChildTwo instance
            A.CallTo(() => listener.OnProperty(GetProp(child2Type, "ChildTwoString"), A <Func <object> > ._, A <InstanceTraversalContext> ._))
            .Invokes(x =>
            {
                var ctx = (InstanceTraversalContext)x.Arguments[2];

                if (ctx.CurrentDepth == 1)
                {
                    Assert.Equal(1, ctx.CurrentDepth);
                    Assert.Equal("FieldChildTwo", ctx.BreadcrumbAsString);

                    callCounts["FieldChildTwo.ChildTwoString"]++;
                }
                else if (ctx.CurrentDepth == 2)
                {
                    Assert.Equal(2, ctx.CurrentDepth);
                    Assert.Equal("FieldChildThree.ChildTwo", ctx.BreadcrumbAsString);

                    callCounts["FieldChildThree.ChildTwo.ChildTwoString"]++;
                }
            })
            .Returns(new SimpleInstanceListenerOnFieldOrPropResult {
                DoContinueRecursion = true
            });

            // then we visit the FieldChildThree top level field
            A.CallTo(() => listener.OnField(GetField(type, "FieldChildThree"), A <Func <object> > ._, A <InstanceTraversalContext> ._))
            .Invokes(x =>
            {
                var ctx = (InstanceTraversalContext)x.Arguments[2];
                Assert.Equal(0, ctx.CurrentDepth);

                callCounts[".FieldChildThree"]++;
            })
            .Returns(new SimpleInstanceListenerOnFieldOrPropResult {
                DoContinueRecursion = false
            });                                                                                          // do not traverse further down this path


            // if traversal continues although it should not, then FieldChildThree.ChildThreeString is next
            A.CallTo(() => listener.OnProperty(GetProp(child3Type, "ChildThreeString"), A <Func <object> > ._, A <InstanceTraversalContext> ._))
            .Invokes(x =>
            {
                var ctx = (InstanceTraversalContext)x.Arguments[2];
                Assert.Equal(1, ctx.CurrentDepth);
                Assert.Equal("FieldChildThree", ctx.BreadcrumbAsString);

                callCounts["FieldChildThree.ChildThreeString"]++;
            })
            .Returns(new SimpleInstanceListenerOnFieldOrPropResult {
                DoContinueRecursion = true
            });


            // if traversal continues although it should not, then FieldChildThree.ChildTwo is next
            A.CallTo(() => listener.OnProperty(GetProp(child3Type, "ChildTwo"), A <Func <object> > ._, A <InstanceTraversalContext> ._))
            .Invokes(x =>
            {
                var ctx = (InstanceTraversalContext)x.Arguments[2];
                Assert.Equal(1, ctx.CurrentDepth);
                Assert.Equal("FieldChildThree", ctx.BreadcrumbAsString);

                callCounts["FieldChildThree.ChildTwo"]++;
            })
            .Returns(new SimpleInstanceListenerOnFieldOrPropResult {
                DoContinueRecursion = true
            });

            Traverser.TraverseInstance(victim, 5, listener);

            // these should have been called exactly once
            Assert.Equal(1, callCounts[".FieldChildTwo"]);
            Assert.Equal(1, callCounts["FieldChildTwo.ChildTwoString"]);
            Assert.Equal(1, callCounts[".FieldChildThree"]);

            // these should not have been called as traversal should stop at .FieldChildThree
            Assert.Equal(0, callCounts["FieldChildThree.ChildThreeString"]);
            Assert.Equal(0, callCounts["FieldChildThree.ChildTwo"]);
            Assert.Equal(0, callCounts["FieldChildThree.ChildTwo.ChildTwoString"]);
        }
예제 #4
0
        public void PropertyRecursion_withinDepth_works()
        {
            var victim     = new RecursionVictim();
            var childTwo   = new RecursionChildTwo();
            var childThree = new RecursionChildThree
            {
                ChildTwo = childTwo
            };

            victim.PropChildTwo   = childTwo;
            victim.PropChildThree = childThree;

            var type       = victim.GetType();
            var child2Type = typeof(RecursionChildTwo);
            var child3Type = typeof(RecursionChildThree);


            var callCounts = new Dictionary <string, int>
            {
                { ".PropChildTwo", 0 },
                { "PropChildTwo.ChildTwoString", 0 },
                { ".PropChildThree", 0 },
                { "PropChildThree.ChildThreeString", 0 },
                { "PropChildThree.ChildTwo", 0 },
                { "PropChildThree.ChildTwo.ChildTwoString", 0 }
            };

            // first we get a call for the top level child two property
            A.CallTo(() => listener.OnProperty(GetProp(type, "PropChildTwo"), A <Func <object> > ._, A <InstanceTraversalContext> ._))
            .Invokes(x =>
            {
                var ctx = (InstanceTraversalContext)x.Arguments[2];
                Assert.Equal(0, ctx.CurrentDepth);

                callCounts[".PropChildTwo"]++;
            })
            .Returns(new SimpleInstanceListenerOnFieldOrPropResult {
                DoContinueRecursion = true
            });

            // we then dig into the top level child two prop instance
            // and this is also triggered for the PropChildThree.ChildTwo instance
            A.CallTo(() => listener.OnProperty(GetProp(child2Type, "ChildTwoString"), A <Func <object> > ._, A <InstanceTraversalContext> ._))
            .Invokes(x =>
            {
                var ctx = (InstanceTraversalContext)x.Arguments[2];

                if (ctx.CurrentDepth == 1)
                {
                    Assert.Equal(1, ctx.CurrentDepth);
                    Assert.Equal("PropChildTwo", ctx.BreadcrumbAsString);

                    callCounts["PropChildTwo.ChildTwoString"]++;
                }
                else if (ctx.CurrentDepth == 2)
                {
                    Assert.Equal(2, ctx.CurrentDepth);
                    Assert.Equal("PropChildThree.ChildTwo", ctx.BreadcrumbAsString);

                    callCounts["PropChildThree.ChildTwo.ChildTwoString"]++;
                }
            })
            .Returns(new SimpleInstanceListenerOnFieldOrPropResult {
                DoContinueRecursion = true
            });

            // then we visit the PropChildThree top level prop
            A.CallTo(() => listener.OnProperty(GetProp(type, "PropChildThree"), A <Func <object> > ._, A <InstanceTraversalContext> ._))
            .Invokes(x =>
            {
                var ctx = (InstanceTraversalContext)x.Arguments[2];
                Assert.Equal(0, ctx.CurrentDepth);

                callCounts[".PropChildThree"]++;
            })
            .Returns(new SimpleInstanceListenerOnFieldOrPropResult {
                DoContinueRecursion = true
            });


            // next up is PropChildThree.ChildThreeString
            A.CallTo(() => listener.OnProperty(GetProp(child3Type, "ChildThreeString"), A <Func <object> > ._, A <InstanceTraversalContext> ._))
            .Invokes(x =>
            {
                var ctx = (InstanceTraversalContext)x.Arguments[2];
                Assert.Equal(1, ctx.CurrentDepth);
                Assert.Equal("PropChildThree", ctx.BreadcrumbAsString);

                callCounts["PropChildThree.ChildThreeString"]++;
            })
            .Returns(new SimpleInstanceListenerOnFieldOrPropResult {
                DoContinueRecursion = true
            });


            // next up is PropChildThree.ChildTwo
            A.CallTo(() => listener.OnProperty(GetProp(child3Type, "ChildTwo"), A <Func <object> > ._, A <InstanceTraversalContext> ._))
            .Invokes(x =>
            {
                var ctx = (InstanceTraversalContext)x.Arguments[2];
                Assert.Equal(1, ctx.CurrentDepth);
                Assert.Equal("PropChildThree", ctx.BreadcrumbAsString);

                callCounts["PropChildThree.ChildTwo"]++;
            })
            .Returns(new SimpleInstanceListenerOnFieldOrPropResult {
                DoContinueRecursion = true
            });

            Traverser.TraverseInstance(victim, 5, listener);

            // all "methods" should have been called exactly once
            foreach (var(key, value) in callCounts)
            {
                // this sillyness provides us with a hint for which thing was not called as expected
                Assert.Equal($"{key}=1", $"{key}={value}");
            }
        }