public void QueryCell()
        {
            var cmdrData = NewCmdrData();

            var found = false;
            var done  = false;

            cmdrData.Property.QueryCellResult += (i, o) =>
            {
                Assert.IsTrue(o.Id >= 0);

                Console.WriteLine("Query: {0}, {1}", o.Id, o.Model);
                found = true;
            };

            cmdrData.Property.QueryCellEnd += (i, x, z) =>
            {
                Assert.AreEqual(0, x);
                Assert.AreEqual(0, z);
                done = true;
            };

            cmdrData.Property.QueryCell(0, 0);

            TestPump.AllUntil(() => found && done, cmdrData);

            Assert.IsTrue(done, "QueryCellEnd never fired");

            if (!found)
            {
                Assert.Inconclusive("No objects were found in query; is 0, 0 in test world empty?");
            }
        }
        public void Goto()
        {
            var punch = NewPunch();
            var judy  = NewJudy();
            var fired = 0;

            punch.Avatars.Change += (i, a) =>
            {
                if (a.Name != Names.Judy.AsBotName())
                {
                    return;
                }

                switch (fired)
                {
                case 0:
                    Assert.AreEqual(Samples.AvPosition, a.Position);
                    judy.GoTo(AvatarPosition.GroundZero);
                    break;

                case 1:
                    Assert.AreEqual(AvatarPosition.GroundZero, a.Position);
                    break;
                }

                fired++;
            };

            judy.GoTo(Samples.AvPosition);
            TestPump.AllUntil(() => fired >= 2, punch, judy);

            Assert.IsTrue(fired == 2, "State change event not fired exactly twice");
        }
Example #3
0
        public void ListWorlds()
        {
            var cmdrData = NewCmdrData(false);
            var fired    = 0;

            cmdrData.Data.WorldEntry += (i, w) =>
            {
                Console.WriteLine("World: {0}, {1}, {2} users", w.Name, w.State, w.UserCount);
                fired++;
            };

            cmdrData.EnterTestWorld();
            TestPump.AllUntilTimeout(cmdrData);

            Assert.IsTrue(fired >= 1, "Initial world entry event not fired at least once");
            fired = 0;

            cmdrData.Data.ListWorlds();
            TestPump.AllUntilTimeout(cmdrData);

            Assert.IsTrue(fired > 1, "World entry event not fired at least once upon manual request");

            if (fired < 3)
            {
                Assert.Inconclusive("World entry event did not fire more than three times. This may be because there are not enough worlds online");
            }
        }
Example #4
0
        public void GetNode()
        {
            var cmdrData = NewCmdrData();
            var fired    = 0;

            cmdrData.Terrain.GetNode += (i, n, x, z) =>
            {
                Console.WriteLine("Get node from tile {0}x{1}: rev. {2} @ {3}x{4}", x, z, n.Revision, n.X, n.Z);

                Assert.AreEqual(16, x);
                Assert.AreEqual(32, z);
                Assert.IsTrue(n.Revision >= 0);
                Assert.IsTrue(n.X >= 0 && n.X < 4);
                Assert.IsTrue(n.Z >= 0 && n.Z < 4);
                Assert.IsTrue(n.Cells.Length == 64);

                fired++;
            };

            cmdrData.Terrain.QueryTile(16, 32);
            cmdrData.Terrain.QueryTile(16, 32, new int[4, 4]
            {
                { -1, -1, -1, -1 },
                { -1, -1, -1, -1 },
                { -1, -1, -1, -1 },
                { -1, -1, -1, -1 },
            });

            TestPump.AllUntil(() => fired >= 32, cmdrData);

            Assert.IsTrue(fired == 32, "GetNode never fired exactly 32 times");
        }
        public void ObjectDelete()
        {
            var punch = NewPunch();
            var judy  = NewJudy();

            var objIds    = new HashSet <int>();
            var events    = 0;
            var callbacks = 0;

            punch.Property.ObjectCreate += (i, s, o) =>
            {
                if (s != SessionOf(judy))
                {
                    return;
                }

                if (objIds.Count == 0)
                {
                    judy.Property.DeleteObject(o);
                }
                else
                {
                    judy.Property.DeleteObject(o.Id);
                }

                objIds.Add(o.Id);
            };

            punch.Property.ObjectDelete += (i, s, id) =>
            {
                if (s != SessionOf(judy))
                {
                    return;
                }

                Assert.IsTrue(objIds.Remove(id));
                events++;
            };

            judy.Property.CallbackObjectDelete += (i, rc, o) =>
            {
                if (rc != ReasonCode.Success)
                {
                    throw new Exception("Reason code failure: " + rc.ToString());
                }

                callbacks++;
            };

            judy.Property.AddObject(Samples.VPObject);
            judy.Property.AddObject(Samples.VPObject);

            TestPump.AllUntil(() => events + callbacks >= 6, punch, judy);

            Assert.IsTrue(events == 2, "ObjectDelete event not fired exactly twice");
            Assert.IsTrue(callbacks == 2, "CallbackObjectDelete not fired exactly twice");
            Assert.IsTrue(objIds.Count == 0);
        }
        public void Pump_Safety()
        {
            var punch = NewPunch();
            var judy  = NewJudy();

            punch.Chat += (i, c) => punch.Pump();
            judy.Say("MethodPump_Safety");

            TestPump.AllUntilTimeout(punch, judy);
        }
        public void ObjectGet()
        {
            var punch = NewPunch();
            var judy  = NewJudy();

            var objIds    = new HashSet <int>();
            var callbacks = 0;

            punch.Property.ObjectCreate += (i, s, o) =>
            {
                if (s != SessionOf(judy))
                {
                    return;
                }

                objIds.Add(o.Id);
                punch.Property.GetObject(o.Id);
            };

            punch.Property.CallbackObjectGet += (i, rc, o) =>
            {
                if (rc != ReasonCode.Success)
                {
                    throw new Exception("Reason code failure: " + rc.ToString());
                }

                Assert.IsTrue(objIds.Contains(o.Id));

                // Inaccurate sanity test
                Assert.IsTrue(o.Time.Year >= 2014);

                Assert.AreEqual(Samples.VPObject.Model, o.Model);
                Assert.AreEqual(UserIdOf(judy), o.Owner);
                Assert.AreEqual(Samples.VPObject.Position, o.Position);
                Assert.AreEqual(Samples.VPObject.Action, o.Action);
                // TODO: reintroduce this check when unknown VP bug is fixed
                //Assert.AreEqual(Samples.VPObject.Data.Length, o.Data.Length);
                Assert.AreEqual(Samples.VPObject.Description, o.Description);
                Assert.AreEqual(Samples.VPObject.Rotation, o.Rotation);
                Assert.AreEqual(Samples.VPObject.Type, o.Type);
                Assert.AreEqual(Samples.Rotation, o.Rotation);

                callbacks++;
            };

            judy.Property.AddObject(Samples.VPObject);
            judy.Property.AddObject(Samples.VPObject);
            judy.Property.AddObject(Samples.VPObject);

            TestPump.AllUntil(() => callbacks >= 3, punch, judy);

            Assert.IsTrue(callbacks == 3, "CallbackObjectGet not fired exactly three times");
        }
        public void Change()
        {
            var cmdrData = NewCmdrData();
            var bots     = new Instance[5];
            var sessions = new HashSet <int>();
            var fired    = 0;
            var lastId   = -1;

            cmdrData.Avatars.Change += (i, a) =>
            {
                if (a.Name != Names.Punch.AsBotName())
                {
                    return;
                }

                if (lastId == -1)
                {
                    lastId = a.Id;
                }

                Assert.IsTrue(a.IsBot);
                Assert.AreEqual(lastId, a.Id);
                Assert.AreEqual(Samples.AvPosition, a.Position);
                Assert.AreEqual(0, a.Type);
                Assert.IsTrue(sessions.Add(a.Session));

                fired++;
            };

            for (var i = 0; i < 5; i++)
            {
                bots[i] = new Instance()
                          .TestLogin(Names.Punch)
                          .EnterTestWorld();

                TestPump.AllOnce(cmdrData);
                bots[i].GoTo(Samples.AvPosition);
                TestPump.AllOnce(cmdrData, bots[i], cmdrData);
            }

            TestPump.AllUntil(() => fired >= 5, cmdrData);

            foreach (var bot in bots)
            {
                bot.Dispose();
            }

            Assert.IsTrue(fired == 5, "Avatar change event not fired exactly five times");
        }
        public void Teleported()
        {
            var punch = NewPunch();
            var judy  = NewJudy();
            var fired = 0;

            punch.Avatars.Teleported += (i, s, t, w) =>
            {
                if (s != SessionOf(judy))
                {
                    return;
                }

                switch (fired)
                {
                case 0:
                    Assert.AreEqual("", w);
                    Assert.AreEqual(Samples.AvPosition, t);
                    break;

                case 1:
                    Assert.AreEqual(Settings.World, w);
                    Assert.AreEqual(Samples.AvPosition, t);
                    break;

                case 2:
                    Assert.AreEqual("", w);
                    Assert.AreEqual(new AvatarPosition(Samples.Vector3, 66, 88), t);
                    break;

                case 3:
                    Assert.AreEqual(Settings.World, w);
                    Assert.AreEqual(new AvatarPosition(Samples.Vector3, 44, 22), t);
                    break;
                }

                fired++;
            };

            judy.Avatars.Teleport(SessionOf(punch), Samples.AvPosition);
            judy.Avatars.Teleport(SessionOf(punch), Settings.World, Samples.AvPosition);
            judy.Avatars.Teleport(SessionOf(punch), Samples.Vector3, 66, 88);
            judy.Avatars.Teleport(SessionOf(punch), Settings.World, Samples.Vector3, 44, 22);

            TestPump.AllUntil(() => fired >= 4, punch, judy);

            Assert.IsTrue(fired == 4, "Avatar teleport request event not fired exactly four times");
        }
Example #10
0
        public void Enter_Shadow()
        {
            var punch = NewPunch();
            var judy  = NewJudy(false);

            punch.Avatars.Enter += (i, a) =>
            {
                if (a.Name == Names.Judy.AsBotName())
                {
                    Assert.Fail("Should not have seen {0} enter", Names.Judy);
                }
            };

            judy.Enter(Settings.World, false);

            TestPump.AllUntilTimeout(punch, judy);
        }
        public void ObjectGet_Exceptions()
        {
            var cmdrData = NewCmdrData();
            var fired    = false;

            cmdrData.Property.CallbackObjectGet += (i, rc, o) =>
            {
                Assert.AreEqual(ReasonCode.ObjectNotFound, rc);
                fired = true;
            };

            cmdrData.Property.GetObject(-1);

            TestPump.AllUntil(() => fired, cmdrData);

            Assert.IsTrue(fired, "CallbackObjectGet never fired");
        }
Example #12
0
        public void SetNode()
        {
            var cmdrData = NewCmdrData();
            var fired    = 0;

            List <TerrainNode> backup = new List <TerrainNode>();

            cmdrData.Terrain.GetNode += (i, n, x, z) =>
            {
                Assert.AreEqual(4, x);
                Assert.AreEqual(8, z);

                backup.Add(n);
            };

            cmdrData.Terrain.CallbackNodeSet += (i, rc, n, x, z) =>
            {
                if (rc != ReasonCode.Success)
                {
                    throw new Exception("Reason code failure: " + rc.ToString());
                }

                Assert.AreEqual(4, x);
                Assert.AreEqual(8, z);
                Assert.IsTrue(n.Revision >= 0);
                Assert.IsTrue(n.X >= 0 && n.X < 4);
                Assert.IsTrue(n.Z >= 0 && n.Z < 4);
                Assert.IsTrue(n.Cells.Length == 64);

                fired++;
            };

            cmdrData.Terrain.QueryTile(4, 8);

            TestPump.AllUntil(() => backup.Count >= 16, cmdrData);

            foreach (var node in backup)
            {
                cmdrData.Terrain.SetNode(node, 4, 8);
            }

            TestPump.AllUntil(() => fired >= 16, cmdrData);

            Assert.IsTrue(fired == 16, "CallbackNodeSet never fired exactly 16 times");
        }
Example #13
0
        public void Pump_Async()
        {
            var punch = NewPunch();
            var judy  = NewJudy();

            Action pump = () =>
            {
                for (var i = 0; i < 10; i++)
                {
                    TestPump.AllOnce(punch, judy);
                }
            };

            Task.WaitAll(
                Task.Factory.StartNew(() => pump),
                Task.Factory.StartNew(() => pump)
                );
        }
        public void UrlRequest()
        {
            var punch = NewPunch();
            var judy  = NewJudy();
            var fired = 0;

            punch.Avatars.UrlRequest += (i, s, u, t) =>
            {
                if (s != SessionOf(judy))
                {
                    return;
                }

                switch (fired)
                {
                case 0:
                    Assert.AreEqual(Strings.SampleURL, u);
                    Assert.AreEqual(UrlTarget.Browser, t);
                    break;

                case 1:
                    Assert.AreEqual(Strings.SampleURLUnicode, u);
                    Assert.AreEqual(UrlTarget.Overlay, t);
                    break;

                case 2:
                    Assert.AreEqual("", u);
                    Assert.AreEqual(UrlTarget.Overlay, t);
                    break;
                }

                fired++;
            };

            judy.Avatars.SendUrl(SessionOf(punch), Strings.SampleURL, UrlTarget.Browser);
            judy.Avatars.SendUrl(SessionOf(punch), Strings.SampleURLUnicode, UrlTarget.Overlay);
            judy.Avatars.ClearUrl(SessionOf(punch));

            TestPump.AllUntil(() => fired >= 3, punch, judy);

            Assert.IsTrue(fired == 3, "Avatar URL request event not fired exactly three times");
        }
Example #15
0
        public void Say_Chunked()
        {
            var punch = NewPunch();
            var judy  = NewJudy();
            var fired = 0;

            punch.Chat += (i, c) =>
            {
                if (c.Name != Names.Judy.AsBotName())
                {
                    return;
                }

                fired++;
            };

            judy.Say(Strings.TooLong);
            TestPump.AllUntil(() => fired >= 3, punch, judy);

            Assert.IsTrue(fired == 3, "Chat event not fired exactly three times");
        }
Example #16
0
        public void GetUserAttributes()
        {
            var cmdrData = NewCmdrData();
            var fired    = 0;

            cmdrData.Data.UserAttributes += (i, d) =>
            {
                Console.WriteLine("Attributes: {0}, {1}, {2}", d.Name, d.ID, d.RegistrationTime);
                fired++;
            };

            cmdrData.Data.GetUserAttributes(1);
            cmdrData.Data.GetUserAttributes(int.MaxValue);
            cmdrData.Data.GetUserAttributes(2);
            cmdrData.Data.GetUserAttributes(int.MaxValue - 1);
            cmdrData.Data.GetUserAttributes(3);

            TestPump.AllUntil(() => fired >= 3, cmdrData);

            Assert.IsTrue(fired == 3, "State change event not fired exactly three times");
        }
Example #17
0
        public void Say_Unicode()
        {
            var punch = NewPunch();
            var judy  = NewJudy();
            var fired = false;

            punch.Chat += (i, c) =>
            {
                if (c.Name != Names.Judy.AsBotName())
                {
                    return;
                }

                Assert.AreEqual(Strings.SampleUnicode, c.Message);
                fired = true;
            };

            judy.Say(Strings.SampleUnicode);
            TestPump.AllUntil(() => fired, punch, judy);

            Assert.IsTrue(fired, "Chat event not fired");
        }
Example #18
0
        public void ConsoleMessage_Chunked()
        {
            var punch = NewPunch();
            var judy  = NewJudy();
            var fired = 0;

            punch.Console += (i, c) =>
            {
                if (c.Name != Names.Judy)
                {
                    return;
                }

                fired++;
            };

            judy.ConsoleMessage(SessionOf(punch), Names.Judy, Strings.TooLong);
            judy.ConsoleMessage(SessionOf(punch) - 1, Names.Judy, Strings.TooLong);
            TestPump.AllUntil(() => fired >= 3, punch, judy);

            Assert.IsTrue(fired == 3, "Console event not fired exactly three times");
        }
        public void Leave()
        {
            var cmdrData = NewCmdrData();
            var bots     = new Instance[5];
            var sessions = new HashSet <int>();
            var fired    = 0;

            cmdrData.Avatars.Leave += (i, n, s) =>
            {
                if (n != Names.Punch.AsBotName())
                {
                    return;
                }

                Assert.IsTrue(sessions.Add(s));

                fired++;
            };

            for (var i = 0; i < 5; i++)
            {
                bots[i] = new Instance()
                          .TestLogin(Names.Punch)
                          .EnterTestWorld();

                TestPump.AllOnce(cmdrData);
                bots[i].Leave();
                TestPump.AllOnce(cmdrData, bots[i], cmdrData);
            }

            TestPump.AllUntil(() => fired >= 5, cmdrData);

            foreach (var bot in bots)
            {
                bot.Dispose();
            }

            Assert.IsTrue(fired == 5, "Avatar leave event not fired exactly five times");
        }
Example #20
0
        public void ConsoleBroadcast()
        {
            var cmdrData = NewCmdrData();
            var punch    = NewPunch();
            var judy     = NewJudy();
            var fired    = 0;

            cmdrData.Console += (i, c) =>
            {
                if (c.Name != Names.Judy)
                {
                    return;
                }

                Assert.AreEqual(Samples.Color, c.Color);
                Assert.AreEqual(Samples.ChatEffect, c.Effect);
                Assert.AreEqual(Strings.SampleUnicode, c.Message);
                fired++;
            };

            punch.Console += (i, c) =>
            {
                if (c.Name != Names.Judy)
                {
                    return;
                }

                Assert.AreEqual(Samples.Color, c.Color);
                Assert.AreEqual(Samples.ChatEffect, c.Effect);
                Assert.AreEqual(Strings.SampleUnicode, c.Message);
                fired++;
            };

            judy.ConsoleBroadcast(Samples.ChatEffect, Samples.Color, Names.Judy, Strings.SampleUnicode);
            TestPump.AllUntil(() => fired >= 2, cmdrData, punch, judy);

            Assert.IsTrue(fired == 2, "Console event not fired exactly twice");
        }
Example #21
0
        public void WorldSettings()
        {
            var cmdrData = NewCmdrData(false);
            var fired    = 0;
            var done     = false;

            cmdrData.Data.WorldSetting += (i, k, v) =>
            {
                Console.WriteLine("World setting: {0} = {1}", k, v);
                fired++;
            };

            cmdrData.Data.WorldSettingsDone += (i) => done = true;

            cmdrData.EnterTestWorld();
            TestPump.AllUntilTimeout(cmdrData);

            Assert.IsTrue(done, "World settings retrival done event never fired");

            if (fired <= 0)
            {
                Assert.Inconclusive("World setting event never fired. This may be because the configured test world has none");
            }
        }
        public void Clicked()
        {
            var punch = NewPunch();
            var judy  = NewJudy();
            var fired = 0;

            punch.Avatars.Clicked += (i, a) =>
            {
                if (a.SourceSession != SessionOf(judy))
                {
                    return;
                }

                Assert.AreEqual(a.TargetSession, SessionOf(punch));

                switch (fired)
                {
                case 0:
                    Assert.AreEqual(Vector3.Zero, a.Position);
                    break;

                case 1:
                    Assert.AreEqual(Samples.Vector3, a.Position);
                    break;
                }

                fired++;
            };

            judy.Avatars.Click(SessionOf(punch));
            judy.Avatars.Click(SessionOf(punch), Samples.Vector3);

            TestPump.AllUntil(() => fired >= 2, punch, judy);

            Assert.IsTrue(fired == 2, "Avatar click event not fired exactly twice times");
        }
        public void ObjectCreate()
        {
            var punch = NewPunch();
            var judy  = NewJudy();

            var events    = 0;
            var callbacks = 0;

            punch.Property.ObjectCreate += (i, s, o) =>
            {
                if (s != SessionOf(judy))
                {
                    return;
                }

                Assert.AreEqual(UserIdOf(judy), o.Owner);
                Assert.AreEqual(Samples.VPObject.Position, o.Position);
                StringAssert.Contains(o.Model, "sign5.rwx");

                if (o.Model.EndsWith("sample"))
                {
                    Assert.AreEqual(Samples.VPObject.Action, o.Action);
                    Assert.AreEqual(Samples.VPObject.Data.Length, o.Data.Length);
                    Assert.AreEqual(Samples.VPObject.Description, o.Description);
                    Assert.AreEqual(Samples.VPObject.Rotation, o.Rotation);
                    Assert.AreEqual(Samples.VPObject.Type, o.Type);
                }
                else if (o.Model.EndsWith("sample2"))
                {
                    Assert.AreEqual(Rotation.Zero, o.Rotation);
                }
                else if (o.Model.EndsWith("sample3"))
                {
                    Assert.AreEqual(Samples.Rotation, o.Rotation);
                }
                else
                {
                    Assert.Inconclusive("Unexpected object with partial name match");
                }

                // Inaccurate sanity test
                Assert.IsTrue(o.Time.Year >= 2014);

                events++;
            };

            judy.Property.CallbackObjectCreate += (i, rc, o) =>
            {
                if (rc != ReasonCode.Success)
                {
                    throw new Exception("Reason code failure: " + rc.ToString());
                }

                callbacks++;
            };

            judy.Property.AddObject(Samples.VPObject);
            judy.Property.CreateObject("sign5.rwx#sample2", Samples.Vector3);
            judy.Property.CreateObject("sign5.rwx#sample3", Samples.Vector3, Samples.Rotation);

            TestPump.AllUntil(() => events + callbacks >= 6, punch, judy);

            Assert.IsTrue(events == 3, "ObjectCreate event not fired exactly three times");
            Assert.IsTrue(callbacks == 3, "CallbackObjectCreate not fired exactly three times");
        }
        public void ObjectBump()
        {
            var cmdrData  = NewCmdrData();
            var punch     = NewPunch();
            var judy      = NewJudy();
            var judyBumps = 0;
            var dataBumps = 0;
            var objId     = -1;

            punch.Property.ObjectCreate += (i, s, o) =>
            {
                if (s != SessionOf(judy))
                {
                    return;
                }

                objId = o.Id;

                punch.Property.BeginBump(objId);
                punch.Property.BeginBump(o);
                punch.Property.EndBump(o.Id);
                punch.Property.EndBump(o);

#if false
                punch.Property.BeginBump(objId, SessionOf(judy));
                punch.Property.BeginBump(o, SessionOf(judy));
                punch.Property.EndBump(o.Id, SessionOf(judy));
                punch.Property.EndBump(o, SessionOf(judy));
#endif
            };

            VP.PropertyContainer.ObjectBumpArgs judyBump = (i, s, id) =>
            {
                if (s != SessionOf(punch))
                {
                    return;
                }

                Assert.AreEqual(objId, id);

                judyBumps++;
            };

            VP.PropertyContainer.ObjectBumpArgs dataBump = (i, s, id) =>
            {
                if (s != SessionOf(punch))
                {
                    return;
                }

                Assert.AreEqual(objId, id);

                dataBumps++;
            };

            judy.Property.ObjectBumpBegin     += judyBump;
            judy.Property.ObjectBumpEnd       += judyBump;
            cmdrData.Property.ObjectBumpBegin += dataBump;
            cmdrData.Property.ObjectBumpEnd   += dataBump;

            judy.Property.AddObject(Samples.VPObject);

            TestPump.AllUntil(() => dataBumps + judyBumps >= 8, punch, judy, cmdrData);

            Assert.IsTrue(dataBumps == 4, "ObjectBump* events not fired for Data exactly four times");
            Assert.IsTrue(judyBumps == 4, "ObjectBump* events not fired for Judy exactly four times");
        }
        public void ObjectClick()
        {
            var cmdrData   = NewCmdrData();
            var punch      = NewPunch();
            var judy       = NewJudy();
            var judyClicks = 0;
            var dataClicks = 0;
            var objId      = -1;

            punch.Property.ObjectCreate += (i, s, o) =>
            {
                if (s != SessionOf(judy))
                {
                    return;
                }

                objId = o.Id;

                punch.Property.ClickObject(o.Id);
                punch.Property.ClickObject(o);
                punch.Property.ClickObject(o.Id, SessionOf(judy));
                punch.Property.ClickObject(o, SessionOf(judy));

                punch.Property.ClickObject(o.Id, Samples.Vector3);
                punch.Property.ClickObject(o, Samples.Vector3);
                punch.Property.ClickObject(o.Id, Samples.Vector3, SessionOf(judy));
                punch.Property.ClickObject(o, Samples.Vector3, SessionOf(judy));
            };

            judy.Property.ObjectClick += (i, c) =>
            {
                if (c.Session != SessionOf(punch))
                {
                    return;
                }

                Assert.AreEqual(objId, c.Id);

                if (!c.Position.Equals(Vector3.Zero))
                {
                    Assert.AreEqual(Samples.Vector3, c.Position);
                }

                judyClicks++;
            };

            cmdrData.Property.ObjectClick += (i, c) =>
            {
                if (c.Session != SessionOf(punch))
                {
                    return;
                }

                Assert.AreEqual(objId, c.Id);

                if (!c.Position.Equals(Vector3.Zero))
                {
                    Assert.AreEqual(Samples.Vector3, c.Position);
                }

                dataClicks++;
            };

            judy.Property.AddObject(Samples.VPObject);

            TestPump.AllUntil(() => dataClicks + judyClicks >= 12, punch, judy, cmdrData);

            Assert.IsTrue(dataClicks == 4, "ObjectClick event not fired for Data exactly four times");
            Assert.IsTrue(judyClicks == 8, "ObjectClick event not fired for Judy exactly eight times");
        }