Example #1
0
        public static void Run(TestHelper helper)
        {
            Communicator?communicator = helper.Communicator();

            TestHelper.Assert(communicator != null);
            TextWriter output = helper.GetWriter();
            bool       ice1   = communicator.DefaultProtocol == Protocol.Ice1;

            output.Write("testing communicator operations... ");
            output.Flush();
            {
                // Test: Exercise AddAdminFacet, FindAdminFacet, RemoveAdminFacet with a typical configuration.
                var properties = new Dictionary <string, string>
                {
                    ["Ice.Admin.Endpoints"]    = ice1 ? "tcp -h 127.0.0.1" : "ice+tcp://127.0.0.1:0",
                    ["Ice.Admin.InstanceName"] = "Test"
                };
                using var com = new Communicator(properties);
                TestFacets(com, true, false);
            }
            {
                // Test: Verify that the operations work correctly in the presence of facet filters.
                var properties = new Dictionary <string, string>
                {
                    ["Ice.Admin.Endpoints"]    = ice1 ? "tcp -h 127.0.0.1" : "ice+tcp://127.0.0.1:0",
                    ["Ice.Admin.InstanceName"] = "Test",
                    ["Ice.Admin.Facets"]       = "Properties"
                };
                using var com = new Communicator(properties);
                TestFacets(com, false, true);
            }
            {
                // Test: Verify that the operations work correctly with the Admin object disabled.
                using var com = new Communicator();
                TestFacets(com, false, false);
            }
            {
                // Test: Verify that the operations work correctly with Ice.Admin.Enabled=1
                var properties = new Dictionary <string, string>()
                {
                    { "Ice.Admin.Enabled", "1" }
                };
                using var com = new Communicator(properties);
                TestHelper.Assert(com.GetAdmin() == null);
                var id = Identity.Parse("test-admin");
                try
                {
                    com.CreateAdmin(null, id);
                    TestHelper.Assert(false);
                }
                catch (InvalidConfigurationException)
                {
                }

                ObjectAdapter adapter = com.CreateObjectAdapter();
                TestHelper.Assert(com.CreateAdmin(adapter, id) != null);
                TestHelper.Assert(com.GetAdmin() != null);

                TestFacets(com, true, false);
            }
            {
                // Test: Verify that the operations work correctly when creation of the Admin object is delayed.
                var properties = new Dictionary <string, string>()
                {
                    { "Ice.Admin.Endpoints", ice1 ? "tcp -h 127.0.0.1" : "ice+tcp://127.0.0.1:0" },
                    { "Ice.Admin.InstanceName", "Test" },
                    { "Ice.Admin.DelayCreation", "1" }
                };

                using var com = new Communicator(properties);
                TestFacets(com, true, false);
                com.GetAdmin();
                TestFacets(com, true, false);
            }
            output.WriteLine("ok");

            var factory = IRemoteCommunicatorFactoryPrx.Parse(helper.GetTestProxy("factory", 0), communicator);

            output.Write("testing process facet... ");
            output.Flush();
            {
                // Test: Verify that Process.Shutdown() operation shuts down the communicator.
                var props = new Dictionary <string, string>
                {
                    { "Ice.Admin.Endpoints", ice1 ? "tcp -h 127.0.0.1" : "ice+tcp://127.0.0.1:0" },
                    { "Ice.Admin.InstanceName", "Test" }
                };
                IRemoteCommunicatorPrx?com = factory.CreateCommunicator(props);
                TestHelper.Assert(com != null);
                IObjectPrx?obj = com.GetAdmin();
                TestHelper.Assert(obj != null);
                IProcessPrx proc = obj.Clone("Process", IProcessPrx.Factory);
                proc.Shutdown();
                com.WaitForShutdown();
                com.Destroy();
            }
            output.WriteLine("ok");

            output.Write("testing properties facet... ");
            output.Flush();
            {
                var props = new Dictionary <string, string>
                {
                    { "Ice.Admin.Endpoints", ice1 ? "tcp -h 127.0.0.1" : "ice+tcp://127.0.0.1:0" },
                    { "Ice.Admin.InstanceName", "Test" },
                    { "Prop1", "1" },
                    { "Prop2", "2" },
                    { "Prop3", "3" }
                };
                IRemoteCommunicatorPrx?com = factory.CreateCommunicator(props);
                TestHelper.Assert(com != null);
                IObjectPrx?obj = com.GetAdmin();
                TestHelper.Assert(obj != null);
                IPropertiesAdminPrx pa = obj.Clone("Properties", IPropertiesAdminPrx.Factory);

                // Test: PropertiesAdmin.GetProperty()
                TestHelper.Assert(pa.GetProperty("Prop2") == "2");
                TestHelper.Assert(pa.GetProperty("Bogus").Length == 0);

                // Test: PropertiesAdmin.GetProperties()
                Dictionary <string, string> pd = pa.GetPropertiesForPrefix("");
                TestHelper.Assert(pd.Count == 7);
                TestHelper.Assert(pd["Ice.ProgramName"] == "server");
                TestHelper.Assert(pd["Ice.Admin.Endpoints"] == (ice1 ? "tcp -h 127.0.0.1" : "ice+tcp://127.0.0.1:0"));
                TestHelper.Assert(pd["Ice.Admin.InstanceName"] == "Test");
                TestHelper.Assert(pd["Prop1"] == "1");
                TestHelper.Assert(pd["Prop2"] == "2");
                TestHelper.Assert(pd["Prop3"] == "3");
                TestHelper.Assert(pd["Ice.Default.Protocol"] == communicator.DefaultProtocol.GetName());

                Dictionary <string, string> changes;

                // Test: PropertiesAdmin.SetProperties()
                var setProps = new Dictionary <string, string>
                {
                    { "Prop1", "10" }, // Changed
                    { "Prop2", "20" }, // Changed
                    { "Prop3", "" },   // Removed
                    { "Prop4", "4" },  // Added
                    { "Prop5", "5" } // Added
                };
                pa.SetProperties(setProps);
                TestHelper.Assert(pa.GetProperty("Prop1").Equals("10"));
                TestHelper.Assert(pa.GetProperty("Prop2").Equals("20"));
                TestHelper.Assert(pa.GetProperty("Prop3").Length == 0);
                TestHelper.Assert(pa.GetProperty("Prop4").Equals("4"));
                TestHelper.Assert(pa.GetProperty("Prop5").Equals("5"));
                changes = com.GetChanges();
                TestHelper.Assert(changes.Count == 5);
                TestHelper.Assert(changes["Prop1"].Equals("10"));
                TestHelper.Assert(changes["Prop2"].Equals("20"));
                TestHelper.Assert(changes["Prop3"].Length == 0);
                TestHelper.Assert(changes["Prop4"].Equals("4"));
                TestHelper.Assert(changes["Prop5"].Equals("5"));
                pa.SetProperties(setProps);
                changes = com.GetChanges();
                TestHelper.Assert(changes.Count == 0);

                com.Destroy();
            }
            output.WriteLine("ok");

            output.Write("testing logger facet... ");
            output.Flush();
            {
                var props = new Dictionary <string, string>
                {
                    { "Ice.Admin.Endpoints", ice1 ? "tcp -h 127.0.0.1" : "ice+tcp://127.0.0.1:0" },
                    { "Ice.Admin.InstanceName", "Test" },
                    { "NullLogger", "1" }
                };
                IRemoteCommunicatorPrx?com = factory.CreateCommunicator(props);
                TestHelper.Assert(com != null);
                com.Trace("testCat", "trace");
                com.Warning("warning");
                com.Error("error");
                com.Print("print");

                IObjectPrx?obj = com.GetAdmin();
                TestHelper.Assert(obj != null);
                ILoggerAdminPrx logger = obj.Clone("Logger", ILoggerAdminPrx.Factory);

                // Get all
                (LogMessage[] logMessages, string prefix) =
                    logger.GetLog(Array.Empty <LogMessageType>(), Array.Empty <string>(), -1);

                TestHelper.Assert(logMessages.Length == 4);
                TestHelper.Assert(prefix.Equals("NullLogger"));
                TestHelper.Assert(logMessages[0].TraceCategory.Equals("testCat") && logMessages[0].Message.Equals("trace"));
                TestHelper.Assert(logMessages[1].Message.Equals("warning"));
                TestHelper.Assert(logMessages[2].Message.Equals("error"));
                TestHelper.Assert(logMessages[3].Message.Equals("print"));

                // Get only errors and warnings
                com.Error("error2");
                com.Print("print2");
                com.Trace("testCat", "trace2");
                com.Warning("warning2");

                LogMessageType[] messageTypes = { LogMessageType.ErrorMessage, LogMessageType.WarningMessage };

                (logMessages, prefix) = logger.GetLog(messageTypes, Array.Empty <string>(), -1);

                TestHelper.Assert(logMessages.Length == 4);
                TestHelper.Assert(prefix.Equals("NullLogger"));

                foreach (LogMessage msg in logMessages)
                {
                    TestHelper.Assert(msg.Type == LogMessageType.ErrorMessage || msg.Type == LogMessageType.WarningMessage);
                }

                // Get only errors and traces with Cat = "testCat"
                com.Trace("testCat2", "A");
                com.Trace("testCat", "trace3");
                com.Trace("testCat2", "B");

                messageTypes = new LogMessageType[] { LogMessageType.ErrorMessage, LogMessageType.TraceMessage };
                string[] categories = { "testCat" };
                (logMessages, prefix) = logger.GetLog(messageTypes, categories, -1);
                TestHelper.Assert(logMessages.Length == 5);
                TestHelper.Assert(prefix.Equals("NullLogger"));

                foreach (LogMessage msg in logMessages)
                {
                    TestHelper.Assert(msg.Type == LogMessageType.ErrorMessage ||
                                      (msg.Type == LogMessageType.TraceMessage && msg.TraceCategory.Equals("testCat")));
                }

                // Same, but limited to last 2 messages(trace3 + error3)
                com.Error("error3");

                (logMessages, prefix) = logger.GetLog(messageTypes, categories, 2);
                TestHelper.Assert(logMessages.Length == 2);
                TestHelper.Assert(prefix.Equals("NullLogger"));

                TestHelper.Assert(logMessages[0].Message.Equals("trace3"));
                TestHelper.Assert(logMessages[1].Message.Equals("error3"));

                // Now, test RemoteLogger
                ObjectAdapter adapter = communicator.CreateObjectAdapterWithEndpoints("RemoteLoggerAdapter",
                                                                                      ice1 ? "tcp -h localhost" : "ice+tcp://localhost:0", serializeDispatch: true);

                var remoteLogger = new RemoteLogger();

                IRemoteLoggerPrx myProxy = adapter.AddWithUUID(remoteLogger, IRemoteLoggerPrx.Factory);

                adapter.Activate();

                // No filtering
                (logMessages, prefix) = logger.GetLog(Array.Empty <LogMessageType>(), Array.Empty <string>(), -1);

                logger.AttachRemoteLogger(myProxy, Array.Empty <LogMessageType>(), Array.Empty <string>(), -1);
                remoteLogger.Wait(1);

                foreach (LogMessage m in logMessages)
                {
                    remoteLogger.CheckNextInit(prefix, m.Type, m.Message, m.TraceCategory);
                }

                com.Trace("testCat", "rtrace");
                com.Warning("rwarning");
                com.Error("rerror");
                com.Print("rprint");

                remoteLogger.Wait(4);

                remoteLogger.CheckNextLog(LogMessageType.TraceMessage, "rtrace", "testCat");
                remoteLogger.CheckNextLog(LogMessageType.WarningMessage, "rwarning", "");
                remoteLogger.CheckNextLog(LogMessageType.ErrorMessage, "rerror", "");
                remoteLogger.CheckNextLog(LogMessageType.PrintMessage, "rprint", "");

                TestHelper.Assert(logger.DetachRemoteLogger(myProxy));
                TestHelper.Assert(!logger.DetachRemoteLogger(myProxy));

                // Use Error + Trace with "traceCat" filter with 4 limit
                (logMessages, prefix) = logger.GetLog(messageTypes, categories, 4);
                TestHelper.Assert(logMessages.Length == 4);

                logger.AttachRemoteLogger(myProxy, messageTypes, categories, 4);
                remoteLogger.Wait(1);

                foreach (LogMessage m in logMessages)
                {
                    remoteLogger.CheckNextInit(prefix, m.Type, m.Message, m.TraceCategory);
                }

                com.Warning("rwarning2");
                com.Trace("testCat", "rtrace2");
                com.Warning("rwarning3");
                com.Error("rerror2");
                com.Print("rprint2");

                remoteLogger.Wait(2);

                remoteLogger.CheckNextLog(LogMessageType.TraceMessage, "rtrace2", "testCat");
                remoteLogger.CheckNextLog(LogMessageType.ErrorMessage, "rerror2", "");

                // Attempt reconnection with slightly different proxy
                try
                {
                    logger.AttachRemoteLogger(myProxy.Clone(oneway: true), messageTypes, categories, 4);
                    TestHelper.Assert(false);
                }
                catch (RemoteLoggerAlreadyAttachedException)
                {
                    // expected
                }

                com.Destroy();
            }
            output.WriteLine("ok");

            output.Write("testing custom facet... ");
            output.Flush();
            {
                // Test: Verify that the custom facet is present.
                var props = new Dictionary <string, string>
                {
                    { "Ice.Admin.Endpoints", ice1 ? "tcp -h 127.0.0.1" : "ice+tcp://127.0.0.1:0" },
                    { "Ice.Admin.InstanceName", "Test" }
                };
                IRemoteCommunicatorPrx?com = factory.CreateCommunicator(props);
                TestHelper.Assert(com != null);
                IObjectPrx?obj = com.GetAdmin();
                TestHelper.Assert(obj != null);
                ITestFacetPrx tf = obj.Clone("TestFacet", ITestFacetPrx.Factory);
                tf.Op();
                com.Destroy();
            }
            output.WriteLine("ok");

            output.Write("testing facet filtering... ");
            output.Flush();
            {
                // Test: Set Ice.Admin.Facets to expose only the Properties facet, meaning no other facet is available.
                var props = new Dictionary <string, string>
                {
                    { "Ice.Admin.Endpoints", ice1 ? "tcp -h 127.0.0.1" : "ice+tcp://127.0.0.1:0" },
                    { "Ice.Admin.InstanceName", "Test" },
                    { "Ice.Admin.Facets", "Properties" }
                };
                IRemoteCommunicatorPrx?com = factory.CreateCommunicator(props);
                TestHelper.Assert(com != null);
                IObjectPrx?obj = com.GetAdmin();
                TestHelper.Assert(obj != null);
                try
                {
                    IProcessPrx.CheckedCast(obj.Clone(facet: "Process", IObjectPrx.Factory));
                    TestHelper.Assert(false);
                }
                catch (ObjectNotExistException)
                {
                }

                try
                {
                    ITestFacetPrx.CheckedCast(obj.Clone(facet: "TestFacet", IObjectPrx.Factory));
                    TestHelper.Assert(false);
                }
                catch (ObjectNotExistException)
                {
                }
                com.Destroy();
            }
            {
                // Test: Set Ice.Admin.Facets to expose only the Process facet, meaning no other facet is available.
                var props = new Dictionary <string, string>
                {
                    { "Ice.Admin.Endpoints", ice1 ? "tcp -h 127.0.0.1" : "ice+tcp://127.0.0.1:0" },
                    { "Ice.Admin.InstanceName", "Test" },
                    { "Ice.Admin.Facets", "Process" }
                };
                IRemoteCommunicatorPrx?com = factory.CreateCommunicator(props);
                TestHelper.Assert(com != null);
                IObjectPrx?obj = com.GetAdmin();
                TestHelper.Assert(obj != null);
                try
                {
                    IPropertiesAdminPrx.CheckedCast(obj.Clone(facet: "Properties", IObjectPrx.Factory));
                    TestHelper.Assert(false);
                }
                catch (ObjectNotExistException)
                {
                }

                try
                {
                    ITestFacetPrx.CheckedCast(obj.Clone(facet: "TestFacet", IObjectPrx.Factory));
                    TestHelper.Assert(false);
                }
                catch (ObjectNotExistException)
                {
                }
                com.Destroy();
            }
            {
                // Test: Set Ice.Admin.Facets to expose only the TestFacet facet, meaning no other facet is available.
                var props = new Dictionary <string, string>
                {
                    { "Ice.Admin.Endpoints", ice1 ? "tcp -h 127.0.0.1" : "ice+tcp://127.0.0.1:0" },
                    { "Ice.Admin.InstanceName", "Test" },
                    { "Ice.Admin.Facets", "TestFacet" }
                };
                IRemoteCommunicatorPrx?com = factory.CreateCommunicator(props);
                TestHelper.Assert(com != null);
                IObjectPrx?obj = com.GetAdmin();
                TestHelper.Assert(obj != null);
                try
                {
                    IPropertiesAdminPrx.CheckedCast(obj.Clone(facet: "Properties", IObjectPrx.Factory));
                    TestHelper.Assert(false);
                }
                catch (ObjectNotExistException)
                {
                }

                try
                {
                    IProcessPrx.CheckedCast(obj.Clone(facet: "Process", IObjectPrx.Factory));
                    TestHelper.Assert(false);
                }
                catch (ObjectNotExistException)
                {
                }
                com.Destroy();
            }
            {
                // Test: Set Ice.Admin.Facets to expose two facets. Use whitespace to separate the facet names.
                var props = new Dictionary <string, string>
                {
                    { "Ice.Admin.Endpoints", ice1 ? "tcp -h 127.0.0.1" : "ice+tcp://127.0.0.1:0" },
                    { "Ice.Admin.InstanceName", "Test" },
                    { "Ice.Admin.Facets", "Properties TestFacet" }
                };
                IRemoteCommunicatorPrx?com = factory.CreateCommunicator(props);
                TestHelper.Assert(com != null);
                IObjectPrx?obj = com.GetAdmin();
                TestHelper.Assert(obj != null);
                IPropertiesAdminPrx pa = obj.Clone("Properties", IPropertiesAdminPrx.Factory);
                TestHelper.Assert(pa.GetProperty("Ice.Admin.InstanceName").Equals("Test"));
                var tf = ITestFacetPrx.CheckedCast(obj.Clone(facet: "TestFacet", IObjectPrx.Factory));
                tf !.Op();
                try
                {
                    IProcessPrx.CheckedCast(obj.Clone(facet: "Process", IObjectPrx.Factory));
                    TestHelper.Assert(false);
                }
                catch (ObjectNotExistException)
                {
                }
                com.Destroy();
            }
            {
                // Test: Set Ice.Admin.Facets to expose two facets. Use a comma to separate the facet names.
                var props = new Dictionary <string, string>
                {
                    { "Ice.Admin.Endpoints", ice1 ? "tcp -h 127.0.0.1" : "ice+tcp://127.0.0.1:0" },
                    { "Ice.Admin.InstanceName", "Test" },
                    { "Ice.Admin.Facets", "TestFacet, Process" }
                };
                IRemoteCommunicatorPrx?com = factory.CreateCommunicator(props);
                TestHelper.Assert(com != null);
                IObjectPrx?obj = com.GetAdmin();
                TestHelper.Assert(obj != null);
                try
                {
                    IPropertiesAdminPrx.CheckedCast(obj.Clone(facet: "Properties", IObjectPrx.Factory));
                    TestHelper.Assert(false);
                }
                catch (ObjectNotExistException)
                {
                }
                var tf = ITestFacetPrx.CheckedCast(obj.Clone(facet: "TestFacet", IObjectPrx.Factory));
                TestHelper.Assert(tf != null);
                tf.Op();
                var proc = IProcessPrx.CheckedCast(obj.Clone(facet: "Process", IObjectPrx.Factory));
                TestHelper.Assert(proc != null);
                proc.Shutdown();
                com.WaitForShutdown();
                com.Destroy();
            }
            output.WriteLine("ok");

            factory.Shutdown();
        }
Example #2
0
        public static void Run(TestHelper helper)
        {
            Communicator?communicator = helper.Communicator;

            TestHelper.Assert(communicator != null);
            var admin = IObjectPrx.Parse("DemoIceBox/admin:default -h localhost -p 9996 -t 10000", communicator);

            ITestFacetPrx?facet;

            Console.Out.Write("testing custom facet... ");
            Console.Out.Flush();
            {
                // Test: Verify that the custom facet is present.
                facet = admin.Clone(IObjectPrx.Factory, facet: "TestFacet").Clone(ITestFacetPrx.Factory);
                TestHelper.Assert(facet != null);
                facet.IcePing();
            }
            Console.Out.WriteLine("ok");

            Console.Out.Write("testing properties facet... ");
            Console.Out.Flush();
            {
                IPropertiesAdminPrx pa = admin.Clone(IObjectPrx.Factory,
                                                     facet: "IceBox.Service.TestService.Properties").Clone(IPropertiesAdminPrx.Factory);

                // Test: PropertiesAdmin.GetProperty()
                TestHelper.Assert(pa != null);
                TestHelper.Assert(pa.GetProperty("Prop1") == "1");
                TestHelper.Assert(pa.GetProperty("Bogus").Length == 0);

                // Test: PropertiesAdmin.GetProperties()
                Dictionary <string, string> pd = pa.GetPropertiesForPrefix("");
                TestHelper.Assert(pd.Count == 6);
                TestHelper.Assert(pd["Prop1"] == "1");
                TestHelper.Assert(pd["Prop2"] == "2");
                TestHelper.Assert(pd["Prop3"] == "3");
                TestHelper.Assert(pd["Ice.Config"] == "config.service");
                TestHelper.Assert(pd["Ice.ProgramName"] == "IceBox-TestService");
                TestHelper.Assert(pd["Ice.Admin.Enabled"] == "1");

                Dictionary <string, string> changes;

                // Test: PropertiesAdmin.SetProperties()
                var setProps = new Dictionary <string, string>
                {
                    { "Prop1", "10" }, // Changed
                    { "Prop2", "20" }, // Changed
                    { "Prop3", "" },   // Removed
                    { "Prop4", "4" },  // Added
                    { "Prop5", "5" } // Added
                };
                pa.SetProperties(setProps);
                TestHelper.Assert(pa.GetProperty("Prop1") == "10");
                TestHelper.Assert(pa.GetProperty("Prop2") == "20");
                TestHelper.Assert(pa.GetProperty("Prop3").Length == 0);
                TestHelper.Assert(pa.GetProperty("Prop4") == "4");
                TestHelper.Assert(pa.GetProperty("Prop5") == "5");
                changes = facet.GetChanges();
                TestHelper.Assert(changes.Count == 5);
                TestHelper.Assert(changes["Prop1"] == "10");
                TestHelper.Assert(changes["Prop2"] == "20");
                TestHelper.Assert(changes["Prop3"].Length == 0);
                TestHelper.Assert(changes["Prop4"] == "4");
                TestHelper.Assert(changes["Prop5"] == "5");
                pa.SetProperties(setProps);
                changes = facet.GetChanges();
                TestHelper.Assert(changes.Count == 0);
            }
            Console.Out.WriteLine("ok");

            Console.Out.Write("testing metrics admin facet... ");
            Console.Out.Flush();
            {
                IMetricsAdminPrx?ma = admin.Clone(
                    IObjectPrx.Factory,
                    facet: "IceBox.Service.TestService.Metrics").CheckedCast(IMetricsAdminPrx.Factory);

                IPropertiesAdminPrx?pa = admin.Clone(
                    IObjectPrx.Factory,
                    facet: "IceBox.Service.TestService.Properties").CheckedCast(IPropertiesAdminPrx.Factory);

                TestHelper.Assert(ma != null && pa != null);
                string[] views = ma.GetMetricsViewNames().ReturnValue;
                TestHelper.Assert(views.Length == 0);

                var setProps = new Dictionary <string, string>
                {
                    { "IceMX.Metrics.Debug.GroupBy", "id" },
                    { "IceMX.Metrics.All.GroupBy", "none" },
                    { "IceMX.Metrics.Parent.GroupBy", "parent" }
                };
                pa.SetProperties(setProps);
                pa.SetProperties(new Dictionary <string, string>());

                views = ma.GetMetricsViewNames().ReturnValue;
                TestHelper.Assert(views.Length == 3);

                // Make sure that the IceBox communicator metrics admin is a separate instance.
                views = admin.Clone(IMetricsAdminPrx.Factory, facet: "Metrics").GetMetricsViewNames().ReturnValue;
                TestHelper.Assert(views.Length == 0);
            }
            Console.Out.WriteLine("ok");
        }
Example #3
0
 getPort(IPropertiesAdminPrx p)
 {
     return(TestHelper.getTestPort(p.Communicator.GetProperties(), 0).ToString());
 }
Example #4
0
    public static IMetricsPrx allTests(TestHelper helper, CommunicatorObserver obsv)
    {
        Communicator communicator = helper.communicator();

        string host        = helper.getTestHost();
        string port        = helper.getTestPort(0).ToString();
        string hostAndPort = host + ":" + port;
        string protocol    = helper.getTestProtocol();
        string endpoint    = protocol + " -h " + host + " -p " + port;
        string timeout     = communicator.GetProperty("Ice.Default.Timeout") ?? "60000";

        IMetricsPrx metrics    = IMetricsPrx.Parse($"metrics:{endpoint}", communicator);
        bool        collocated = metrics.GetConnection() == null;
        var         output     = helper.getWriter();

        output.Write("testing metrics admin facet checkedCast... ");
        output.Flush();
        IObjectPrx          admin       = communicator.GetAdmin();
        IPropertiesAdminPrx clientProps = IPropertiesAdminPrx.CheckedCast(admin.Clone(facet: "Properties"));

        IceMX.IMetricsAdminPrx clientMetrics = IceMX.IMetricsAdminPrx.CheckedCast(admin.Clone(facet: "Metrics"));
        test(clientProps != null && clientMetrics != null);

        admin = metrics.getAdmin();
        IPropertiesAdminPrx serverProps = IPropertiesAdminPrx.CheckedCast(admin.Clone(facet: "Properties"));

        IceMX.IMetricsAdminPrx serverMetrics = IceMX.IMetricsAdminPrx.CheckedCast(admin.Clone(facet: "Metrics"));
        test(serverProps != null && serverMetrics != null);

        UpdateCallbackI update = new UpdateCallbackI(serverProps);

        ((INativePropertiesAdmin)communicator.FindAdminFacet("Properties")).AddUpdateCallback(update.updated);

        output.WriteLine("ok");

        Dictionary <string, string> props = new Dictionary <string, string>();

        output.Write("testing group by none...");
        output.Flush();

        props.Add("IceMX.Metrics.View.GroupBy", "none");
        updateProps(clientProps, serverProps, update, props, "");
        Dictionary <string, IceMX.Metrics[]> view = clientMetrics.GetMetricsView("View").ReturnValue;

        if (!collocated)
        {
            test(view["Connection"].Length == 1 && view["Connection"][0].Current == 1 &&
                 view["Connection"][0].Total == 1);
        }
        test(view["Thread"].Length == 1 && view["Thread"][0].Current == 5 && view["Thread"][0].Total == 5);
        output.WriteLine("ok");

        output.Write("testing group by id...");
        output.Flush();

        props["IceMX.Metrics.View.GroupBy"] = "id";
        updateProps(clientProps, serverProps, update, props, "");

        metrics.IcePing();
        metrics.IcePing();
        metrics.Clone(connectionId: "Con1").IcePing();
        metrics.Clone(connectionId: "Con1").IcePing();
        metrics.Clone(connectionId: "Con1").IcePing();

        waitForCurrent(clientMetrics, "View", "Invocation", 0);
        waitForCurrent(serverMetrics, "View", "Dispatch", 0);

        view = clientMetrics.GetMetricsView("View").ReturnValue;
        test(view["Thread"].Length == 5);
        if (!collocated)
        {
            test(view["Connection"].Length == 2);
        }
        test(view["Invocation"].Length == 1);

        IceMX.InvocationMetrics invoke = (IceMX.InvocationMetrics)view["Invocation"][0];

        test(invoke.Id.IndexOf("[ice_ping]") > 0 && invoke.Current == 0 && invoke.Total == 5);
        if (!collocated)
        {
            test(invoke.Remotes.Length == 2);
            test(invoke.Remotes[0].Total >= 2 && invoke.Remotes[1].Total >= 2);
            test((invoke.Remotes[0].Total + invoke.Remotes[1].Total) == 5);
        }
        else
        {
            test(invoke.Collocated.Length == 1);
            test(invoke.Collocated[0].Total == 5);
        }

        view = serverMetrics.GetMetricsView("View").ReturnValue;
        // With Ice for .NET, a new dispatching thread isn't necessarily created.
        //test(view["Thread"].Length > 5);
        if (!collocated)
        {
            test(view["Connection"].Length == 2);
        }
        test(view["Dispatch"].Length == 1);
        test(view["Dispatch"][0].Current == 0 && view["Dispatch"][0].Total == 5);
        test(view["Dispatch"][0].Id.IndexOf("[ice_ping]") > 0);

        if (!collocated)
        {
            metrics.GetConnection().Close(ConnectionClose.GracefullyWithWait);
            metrics.Clone(connectionId: "Con1").GetConnection().Close(ConnectionClose.GracefullyWithWait);

            waitForCurrent(clientMetrics, "View", "Connection", 0);
            waitForCurrent(serverMetrics, "View", "Connection", 0);
        }

        clearView(clientProps, serverProps, update);

        output.WriteLine("ok");

        string type     = "";
        string isSecure = "";

        if (!collocated)
        {
            Ice.EndpointInfo endpointInfo = metrics.GetConnection().Endpoint.GetInfo();
            type     = endpointInfo.Type().ToString();
            isSecure = endpointInfo.Secure() ? "True" : "False";
        }

        Dictionary <string, IceMX.Metrics> map;

        if (!collocated)
        {
            output.Write("testing connection metrics... ");
            output.Flush();

            props["IceMX.Metrics.View.Map.Connection.GroupBy"] = "none";
            updateProps(clientProps, serverProps, update, props, "Connection");

            test(clientMetrics.GetMetricsView("View").ReturnValue["Connection"].Length == 0);
            test(serverMetrics.GetMetricsView("View").ReturnValue["Connection"].Length == 0);

            metrics.IcePing();

            IceMX.ConnectionMetrics cm1, sm1, cm2, sm2;
            cm1 = (IceMX.ConnectionMetrics)clientMetrics.GetMetricsView("View").ReturnValue["Connection"][0];
            sm1 = getServerConnectionMetrics(serverMetrics, 25);

            metrics.IcePing();

            cm2 = (IceMX.ConnectionMetrics)clientMetrics.GetMetricsView("View").ReturnValue["Connection"][0];
            sm2 = getServerConnectionMetrics(serverMetrics, 50);

            test(cm2.SentBytes - cm1.SentBytes == 45);         // 45 for IcePing request
            test(cm2.ReceivedBytes - cm1.ReceivedBytes == 25); // 25 bytes for IcePing response
            test(sm2.ReceivedBytes - sm1.ReceivedBytes == 45);
            test(sm2.SentBytes - sm1.SentBytes == 25);

            cm1 = cm2;
            sm1 = sm2;

            byte[] bs = new byte[0];
            metrics.opByteS(bs);

            cm2 = (IceMX.ConnectionMetrics)clientMetrics.GetMetricsView("View").ReturnValue["Connection"][0];
            sm2 = getServerConnectionMetrics(serverMetrics, sm1.SentBytes + cm2.ReceivedBytes - cm1.ReceivedBytes);
            long requestSz = cm2.SentBytes - cm1.SentBytes;
            long replySz   = cm2.ReceivedBytes - cm1.ReceivedBytes;

            cm1 = cm2;
            sm1 = sm2;

            bs = new byte[456];
            metrics.opByteS(bs);

            cm2 = (IceMX.ConnectionMetrics)clientMetrics.GetMetricsView("View").ReturnValue["Connection"][0];
            sm2 = getServerConnectionMetrics(serverMetrics, sm1.SentBytes + replySz);

            test(cm2.SentBytes - cm1.SentBytes == requestSz + bs.Length + 4); // 4 is for the seq variable size
            test(cm2.ReceivedBytes - cm1.ReceivedBytes == replySz);
            test(sm2.ReceivedBytes - sm1.ReceivedBytes == requestSz + bs.Length + 4);
            test(sm2.SentBytes - sm1.SentBytes == replySz);

            cm1 = cm2;
            sm1 = sm2;

            bs = new byte[1024 * 1024 * 10]; // Try with large amount of data which should be sent in several chunks
            metrics.opByteS(bs);

            cm2 = (IceMX.ConnectionMetrics)clientMetrics.GetMetricsView("View").ReturnValue["Connection"][0];
            sm2 = getServerConnectionMetrics(serverMetrics, sm1.SentBytes + replySz);

            test((cm2.SentBytes - cm1.SentBytes) == (requestSz + bs.Length + 4)); // 4 is for the seq variable size
            test((cm2.ReceivedBytes - cm1.ReceivedBytes) == replySz);
            test((sm2.ReceivedBytes - sm1.ReceivedBytes) == (requestSz + bs.Length + 4));
            test((sm2.SentBytes - sm1.SentBytes) == replySz);

            props["IceMX.Metrics.View.Map.Connection.GroupBy"] = "state";
            updateProps(clientProps, serverProps, update, props, "Connection");

            map = toMap(serverMetrics.GetMetricsView("View").ReturnValue["Connection"]);

            test(map["active"].Current == 1);

            IControllerPrx controller = IControllerPrx.Parse($"controller:{helper.getTestEndpoint(1)}", communicator);
            controller.hold();

            map = toMap(clientMetrics.GetMetricsView("View").ReturnValue["Connection"]);
            test(map["active"].Current == 1);
            map = toMap(serverMetrics.GetMetricsView("View").ReturnValue["Connection"]);
            test(map["holding"].Current == 1);

            metrics.GetConnection().Close(Ice.ConnectionClose.GracefullyWithWait);

            map = toMap(clientMetrics.GetMetricsView("View").ReturnValue["Connection"]);
            test(map["closing"].Current == 1);
            map = toMap(serverMetrics.GetMetricsView("View").ReturnValue["Connection"]);
            test(map["holding"].Current == 1);

            controller.resume();

            map = toMap(serverMetrics.GetMetricsView("View").ReturnValue["Connection"]);
            test(map["holding"].Current == 0);

            props["IceMX.Metrics.View.Map.Connection.GroupBy"] = "none";
            updateProps(clientProps, serverProps, update, props, "Connection");

            metrics.GetConnection().Close(Ice.ConnectionClose.GracefullyWithWait);

            metrics.Clone(connectionTimeout: 500).IcePing();
            controller.hold();
            try
            {
                metrics.Clone(connectionTimeout: 500).opByteS(new byte[10000000]);
                test(false);
            }
            catch (Ice.TimeoutException)
            {
            }
            controller.resume();

            cm1 = (IceMX.ConnectionMetrics)clientMetrics.GetMetricsView("View").ReturnValue["Connection"][0];
            while (true)
            {
                sm1 = (IceMX.ConnectionMetrics)serverMetrics.GetMetricsView("View").ReturnValue["Connection"][0];
                if (sm1.Failures >= 2)
                {
                    break;
                }
                Thread.Sleep(10);
            }
            test(cm1.Failures == 2 && sm1.Failures >= 2);

            checkFailure(clientMetrics, "Connection", cm1.Id, "::Ice::TimeoutException", 1, output);
            checkFailure(clientMetrics, "Connection", cm1.Id, "::Ice::ConnectTimeoutException", 1, output);
            checkFailure(serverMetrics, "Connection", sm1.Id, "::Ice::ConnectionLostException", 0, output);

            IMetricsPrx m = metrics.Clone(connectionTimeout: 500, connectionId: "Con1");
            m.IcePing();

            testAttribute(clientMetrics, clientProps, update, "Connection", "parent", "Communicator", output);
            //testAttribute(clientMetrics, clientProps, update, "Connection", "id", "");
            testAttribute(clientMetrics, clientProps, update, "Connection", "endpoint",
                          endpoint + " -t 500", output);

            testAttribute(clientMetrics, clientProps, update, "Connection", "endpointType", type, output);
            testAttribute(clientMetrics, clientProps, update, "Connection", "endpointIsDatagram", "False", output);
            testAttribute(clientMetrics, clientProps, update, "Connection", "endpointIsSecure", isSecure, output);
            testAttribute(clientMetrics, clientProps, update, "Connection", "endpointTimeout", "500", output);
            testAttribute(clientMetrics, clientProps, update, "Connection", "endpointCompress", "False", output);
            testAttribute(clientMetrics, clientProps, update, "Connection", "endpointHost", host, output);
            testAttribute(clientMetrics, clientProps, update, "Connection", "endpointPort", port, output);

            testAttribute(clientMetrics, clientProps, update, "Connection", "incoming", "False", output);
            testAttribute(clientMetrics, clientProps, update, "Connection", "adapterName", "", output);
            testAttribute(clientMetrics, clientProps, update, "Connection", "connectionId", "Con1", output);
            testAttribute(clientMetrics, clientProps, update, "Connection", "localHost", host, output);
            //testAttribute(clientMetrics, clientProps, update, "Connection", "localPort", "", output);
            testAttribute(clientMetrics, clientProps, update, "Connection", "remoteHost", host, output);
            testAttribute(clientMetrics, clientProps, update, "Connection", "remotePort", port, output);
            testAttribute(clientMetrics, clientProps, update, "Connection", "mcastHost", "", output);
            testAttribute(clientMetrics, clientProps, update, "Connection", "mcastPort", "", output);

            m.GetConnection().Close(Ice.ConnectionClose.GracefullyWithWait);

            waitForCurrent(clientMetrics, "View", "Connection", 0);
            waitForCurrent(serverMetrics, "View", "Connection", 0);

            output.WriteLine("ok");

            output.Write("testing connection establishment metrics... ");
            output.Flush();

            props["IceMX.Metrics.View.Map.ConnectionEstablishment.GroupBy"] = "id";
            updateProps(clientProps, serverProps, update, props, "ConnectionEstablishment");
            test(clientMetrics.GetMetricsView("View").ReturnValue["ConnectionEstablishment"].Length == 0);

            metrics.IcePing();

            test(clientMetrics.GetMetricsView("View").ReturnValue["ConnectionEstablishment"].Length == 1);
            IceMX.Metrics m1 = clientMetrics.GetMetricsView("View").ReturnValue["ConnectionEstablishment"][0];
            test(m1.Current == 0 && m1.Total == 1 && m1.Id.Equals(hostAndPort));

            metrics.GetConnection().Close(Ice.ConnectionClose.GracefullyWithWait);
            controller.hold();
            try
            {
                IObjectPrx.Parse($"test:tcp -h 127.0.0.1 -p {port}", communicator).Clone(connectionTimeout: 10).IcePing();
                test(false);
            }
            catch (Ice.ConnectTimeoutException)
            {
            }
            catch (Ice.LocalException)
            {
                test(false);
            }
            controller.resume();
            test(clientMetrics.GetMetricsView("View").ReturnValue["ConnectionEstablishment"].Length == 1);
            m1 = clientMetrics.GetMetricsView("View").ReturnValue["ConnectionEstablishment"][0];
            test(m1.Id.Equals(hostAndPort) && m1.Total == 3 && m1.Failures == 2);

            checkFailure(clientMetrics, "ConnectionEstablishment", m1.Id, "::Ice::ConnectTimeoutException", 2, output);

            System.Action c = () => { connect(metrics); };
            testAttribute(clientMetrics, clientProps, update, "ConnectionEstablishment", "parent", "Communicator", c, output);
            testAttribute(clientMetrics, clientProps, update, "ConnectionEstablishment", "id", hostAndPort, c, output);
            testAttribute(clientMetrics, clientProps, update, "ConnectionEstablishment", "endpoint",
                          endpoint + " -t " + timeout, c, output);

            testAttribute(clientMetrics, clientProps, update, "ConnectionEstablishment", "endpointType", type, c, output);
            testAttribute(clientMetrics, clientProps, update, "ConnectionEstablishment", "endpointIsDatagram", "False",
                          c, output);
            testAttribute(clientMetrics, clientProps, update, "ConnectionEstablishment", "endpointIsSecure", isSecure,
                          c, output);
            testAttribute(clientMetrics, clientProps, update, "ConnectionEstablishment", "endpointTimeout", timeout, c, output);
            testAttribute(clientMetrics, clientProps, update, "ConnectionEstablishment", "endpointCompress", "False",
                          c, output);
            testAttribute(clientMetrics, clientProps, update, "ConnectionEstablishment", "endpointHost", host, c, output);
            testAttribute(clientMetrics, clientProps, update, "ConnectionEstablishment", "endpointPort", port, c, output);

            output.WriteLine("ok");

            output.Write("testing endpoint lookup metrics... ");
            output.Flush();

            props["IceMX.Metrics.View.Map.ConnectionEstablishment.GroupBy"] = "id";
            updateProps(clientProps, serverProps, update, props, "EndpointLookup");
            test(clientMetrics.GetMetricsView("View").ReturnValue["EndpointLookup"].Length == 0);

            var prx = IObjectPrx.Parse($"metrics:{protocol} -p {port} -h localhost -t 500", communicator);
            try
            {
                prx.IcePing();
                prx.GetConnection().Close(ConnectionClose.GracefullyWithWait);
            }
            catch (LocalException)
            {
            }

            test(clientMetrics.GetMetricsView("View").ReturnValue["EndpointLookup"].Length == 1);
            m1 = clientMetrics.GetMetricsView("View").ReturnValue["EndpointLookup"][0];
            test(m1.Current <= 1 && m1.Total == 1);

            bool dnsException = false;
            try
            {
                IObjectPrx.Parse($"test:tcp -t 500 -h unknownfoo.zeroc.com -p {port}", communicator).IcePing();
                test(false);
            }
            catch (DNSException)
            {
                dnsException = true;
            }
            catch (LocalException)
            {
                // Some DNS servers don't fail on unknown DNS names.
            }
            test(clientMetrics.GetMetricsView("View").ReturnValue["EndpointLookup"].Length == 2);
            m1 = clientMetrics.GetMetricsView("View").ReturnValue["EndpointLookup"][0];
            if (!m1.Id.Equals("tcp -h unknownfoo.zeroc.com -p " + port + " -t 500"))
            {
                m1 = clientMetrics.GetMetricsView("View").ReturnValue["EndpointLookup"][1];
            }
            test(m1.Id.Equals("tcp -h unknownfoo.zeroc.com -p " + port + " -t 500") && m1.Total == 2 &&
                 (!dnsException || m1.Failures == 2));
            if (dnsException)
            {
                checkFailure(clientMetrics, "EndpointLookup", m1.Id, "::Ice::DNSException", 2, output);
            }

            c = () => { connect(prx); };

            testAttribute(clientMetrics, clientProps, update, "EndpointLookup", "parent", "Communicator", c, output);
            testAttribute(clientMetrics, clientProps, update, "EndpointLookup", "id",
                          prx.GetConnection().Endpoint.ToString(), c, output);
            testAttribute(clientMetrics, clientProps, update, "EndpointLookup", "endpoint",
                          prx.GetConnection().Endpoint.ToString(), c, output);

            testAttribute(clientMetrics, clientProps, update, "EndpointLookup", "endpointType", type, c, output);
            testAttribute(clientMetrics, clientProps, update, "EndpointLookup", "endpointIsDatagram", "False", c, output);
            testAttribute(clientMetrics, clientProps, update, "EndpointLookup", "endpointIsSecure", isSecure, c, output);
            testAttribute(clientMetrics, clientProps, update, "EndpointLookup", "endpointTimeout", "500", c, output);
            testAttribute(clientMetrics, clientProps, update, "EndpointLookup", "endpointCompress", "False", c, output);
            testAttribute(clientMetrics, clientProps, update, "EndpointLookup", "endpointHost", "localhost", c, output);
            testAttribute(clientMetrics, clientProps, update, "EndpointLookup", "endpointPort", port, c, output);

            output.WriteLine("ok");
        }
        output.Write("testing dispatch metrics... ");
        output.Flush();

        props["IceMX.Metrics.View.Map.Dispatch.GroupBy"] = "operation";
        updateProps(clientProps, serverProps, update, props, "Dispatch");
        test(serverMetrics.GetMetricsView("View").ReturnValue["Dispatch"].Length == 0);

        metrics.op();
        try
        {
            metrics.opWithUserException();
            test(false);
        }
        catch (UserEx)
        {
        }
        try
        {
            metrics.opWithRequestFailedException();
            test(false);
        }
        catch (RequestFailedException)
        {
        }
        try
        {
            metrics.opWithLocalException();
            test(false);
        }
        catch (Ice.LocalException)
        {
        }
        try
        {
            metrics.opWithUnknownException();
            test(false);
        }
        catch (Ice.UnknownException)
        {
        }
        if (!collocated)
        {
            try
            {
                metrics.fail();
                test(false);
            }
            catch (Ice.ConnectionLostException)
            {
            }
        }

        map = toMap(serverMetrics.GetMetricsView("View").ReturnValue["Dispatch"]);
        test(collocated ? map.Count == 5 : map.Count == 6);

        IceMX.DispatchMetrics dm1;
        dm1 = (IceMX.DispatchMetrics)map["op"];
        test(dm1.Current <= 1 && dm1.Total == 1 && dm1.Failures == 0 && dm1.UserException == 0);
        test(dm1.Size == 21 && dm1.ReplySize == 7);

        dm1 = (IceMX.DispatchMetrics)map["opWithUserException"];
        test(dm1.Current <= 1 && dm1.Total == 1 && dm1.Failures == 0 && dm1.UserException == 1);
        test(dm1.Size == 38 && dm1.ReplySize == 23);

        dm1 = (IceMX.DispatchMetrics)map["opWithLocalException"];
        test(dm1.Current <= 1 && dm1.Total == 1 && dm1.Failures == 1 && dm1.UserException == 0);
        checkFailure(serverMetrics, "Dispatch", dm1.Id, "::Ice::SyscallException", 1, output);
        test(dm1.Size == 39 && dm1.ReplySize > 7); // Reply contains the exception stack depending on the OS.

        dm1 = (IceMX.DispatchMetrics)map["opWithRequestFailedException"];
        test(dm1.Current <= 1 && dm1.Total == 1 && dm1.Failures == 1 && dm1.UserException == 0);
        checkFailure(serverMetrics, "Dispatch", dm1.Id, "::Ice::ObjectNotExistException", 1, output);
        test(dm1.Size == 47 && dm1.ReplySize == 40);

        dm1 = (IceMX.DispatchMetrics)map["opWithUnknownException"];
        test(dm1.Current <= 1 && dm1.Total == 1 && dm1.Failures == 1 && dm1.UserException == 0);
        checkFailure(serverMetrics, "Dispatch", dm1.Id, "System.ArgumentOutOfRangeException", 1, output);
        test(dm1.Size == 41 && dm1.ReplySize > 7); // Reply contains the exception stack depending on the OS.

        System.Action op = () => { invokeOp(metrics); };
        testAttribute(serverMetrics, serverProps, update, "Dispatch", "parent", "TestAdapter", op, output);
        testAttribute(serverMetrics, serverProps, update, "Dispatch", "id", "metrics [op]", op, output);

        if (!collocated)
        {
            testAttribute(serverMetrics, serverProps, update, "Dispatch", "endpoint",
                          endpoint + " -t 60000", op, output);
            //testAttribute(serverMetrics, serverProps, update, "Dispatch", "connection", "", op);

            testAttribute(serverMetrics, serverProps, update, "Dispatch", "endpointType", type, op, output);
            testAttribute(serverMetrics, serverProps, update, "Dispatch", "endpointIsDatagram", "False", op, output);
            testAttribute(serverMetrics, serverProps, update, "Dispatch", "endpointIsSecure", isSecure, op, output);
            testAttribute(serverMetrics, serverProps, update, "Dispatch", "endpointTimeout", "60000", op, output);
            testAttribute(serverMetrics, serverProps, update, "Dispatch", "endpointCompress", "False", op, output);
            testAttribute(serverMetrics, serverProps, update, "Dispatch", "endpointHost", host, op, output);
            testAttribute(serverMetrics, serverProps, update, "Dispatch", "endpointPort", port, op, output);

            testAttribute(serverMetrics, serverProps, update, "Dispatch", "incoming", "True", op, output);
            testAttribute(serverMetrics, serverProps, update, "Dispatch", "adapterName", "TestAdapter", op, output);
            testAttribute(serverMetrics, serverProps, update, "Dispatch", "connectionId", "", op, output);
            testAttribute(serverMetrics, serverProps, update, "Dispatch", "localHost", host, op, output);
            testAttribute(serverMetrics, serverProps, update, "Dispatch", "localPort", port, op, output);
            testAttribute(serverMetrics, serverProps, update, "Dispatch", "remoteHost", host, op, output);
            //testAttribute(serverMetrics, serverProps, update, "Dispatch", "remotePort", port, op, output);
            testAttribute(serverMetrics, serverProps, update, "Dispatch", "mcastHost", "", op, output);
            testAttribute(serverMetrics, serverProps, update, "Dispatch", "mcastPort", "", op, output);
        }

        testAttribute(serverMetrics, serverProps, update, "Dispatch", "operation", "op", op, output);
        testAttribute(serverMetrics, serverProps, update, "Dispatch", "identity", "metrics", op, output);
        testAttribute(serverMetrics, serverProps, update, "Dispatch", "facet", "", op, output);
        testAttribute(serverMetrics, serverProps, update, "Dispatch", "mode", "twoway", op, output);

        testAttribute(serverMetrics, serverProps, update, "Dispatch", "context.entry1", "test", op, output);
        testAttribute(serverMetrics, serverProps, update, "Dispatch", "context.entry2", "", op, output);
        testAttribute(serverMetrics, serverProps, update, "Dispatch", "context.entry3", "", op, output);

        output.WriteLine("ok");

        output.Write("testing invocation metrics... ");
        output.Flush();

        //
        // Tests for twoway
        //
        props["IceMX.Metrics.View.Map.Invocation.GroupBy"]                = "operation";
        props["IceMX.Metrics.View.Map.Invocation.Map.Remote.GroupBy"]     = "id";
        props["IceMX.Metrics.View.Map.Invocation.Map.Collocated.GroupBy"] = "id";
        updateProps(clientProps, serverProps, update, props, "Invocation");
        test(serverMetrics.GetMetricsView("View").ReturnValue["Invocation"].Length == 0);

        metrics.op();
        metrics.opAsync().Wait();

        try
        {
            metrics.opWithUserException();
            test(false);
        }
        catch (UserEx)
        {
        }

        try
        {
            metrics.opWithUserExceptionAsync().Wait();
            test(false);
        }
        catch (System.AggregateException ex)
        {
            test(ex.InnerException is UserEx);
        }

        try
        {
            metrics.opWithRequestFailedException();
            test(false);
        }
        catch (Ice.RequestFailedException)
        {
        }

        try
        {
            metrics.opWithRequestFailedExceptionAsync().Wait();
            test(false);
        }
        catch (System.AggregateException ex)
        {
            test(ex.InnerException is Ice.RequestFailedException);
        }

        try
        {
            metrics.opWithLocalException();
            test(false);
        }
        catch (Ice.LocalException)
        {
        }
        try
        {
            metrics.opWithLocalExceptionAsync().Wait();
            test(false);
        }
        catch (System.AggregateException ex)
        {
            test(ex.InnerException is Ice.LocalException);
        }

        try
        {
            metrics.opWithUnknownException();
            test(false);
        }
        catch (Ice.UnknownException)
        {
        }

        try
        {
            metrics.opWithUnknownExceptionAsync().Wait();
            test(false);
        }
        catch (System.AggregateException ex)
        {
            test(ex.InnerException is Ice.UnknownException);
        }

        if (!collocated)
        {
            try
            {
                metrics.fail();
                test(false);
            }
            catch (Ice.ConnectionLostException)
            {
            }

            try
            {
                metrics.failAsync().Wait();
                test(false);
            }
            catch (System.AggregateException ex)
            {
                test(ex.InnerException is Ice.ConnectionLostException);
            }
        }

        map = toMap(clientMetrics.GetMetricsView("View").ReturnValue["Invocation"]);
        test(map.Count == (collocated ? 5 : 6));

        IceMX.InvocationMetrics      im1;
        IceMX.ChildInvocationMetrics rim1;
        im1 = (IceMX.InvocationMetrics)map["op"];
        test(im1.Current <= 1 && im1.Total == 2 && im1.Failures == 0 && im1.Retry == 0);
        test(collocated ? im1.Collocated.Length == 1 : im1.Remotes.Length == 1);
        rim1 = (IceMX.ChildInvocationMetrics)(collocated ? im1.Collocated[0] : im1.Remotes[0]);
        test(rim1.Current == 0 && rim1.Total == 2 && rim1.Failures == 0);
        test(rim1.Size == 42 && rim1.ReplySize == 14);

        im1 = (IceMX.InvocationMetrics)map["opWithUserException"];
        test(im1.Current <= 1 && im1.Total == 2 && im1.Failures == 0 && im1.Retry == 0);
        test(collocated ? im1.Collocated.Length == 1 : im1.Remotes.Length == 1);
        rim1 = (IceMX.ChildInvocationMetrics)(collocated ? im1.Collocated[0] : im1.Remotes[0]);
        test(rim1.Current == 0 && rim1.Total == 2 && rim1.Failures == 0);
        test(rim1.Size == 76 && rim1.ReplySize == 46);
        test(im1.UserException == 2);

        im1 = (IceMX.InvocationMetrics)map["opWithLocalException"];
        test(im1.Current <= 1 && im1.Total == 2 && im1.Failures == 2 && im1.Retry == 0);
        test(collocated ? im1.Collocated.Length == 1 : im1.Remotes.Length == 1);
        rim1 = (IceMX.ChildInvocationMetrics)(collocated ? im1.Collocated[0] : im1.Remotes[0]);
        test(rim1.Current == 0 && rim1.Total == 2 && rim1.Failures == 0);
        test(rim1.Size == 78 && rim1.ReplySize > 7);
        checkFailure(clientMetrics, "Invocation", im1.Id, "::Ice::UnknownLocalException", 2, output);

        im1 = (IceMX.InvocationMetrics)map["opWithRequestFailedException"];
        test(im1.Current <= 1 && im1.Total == 2 && im1.Failures == 2 && im1.Retry == 0);
        test(collocated ? im1.Collocated.Length == 1 : im1.Remotes.Length == 1);
        rim1 = (IceMX.ChildInvocationMetrics)(collocated ? im1.Collocated[0] : im1.Remotes[0]);
        test(rim1.Current == 0 && rim1.Total == 2 && rim1.Failures == 0);
        test(rim1.Size == 94 && rim1.ReplySize == 80);
        checkFailure(clientMetrics, "Invocation", im1.Id, "::Ice::ObjectNotExistException", 2, output);

        im1 = (IceMX.InvocationMetrics)map["opWithUnknownException"];
        test(im1.Current <= 1 && im1.Total == 2 && im1.Failures == 2 && im1.Retry == 0);
        test(collocated ? im1.Collocated.Length == 1 : im1.Remotes.Length == 1);
        rim1 = (IceMX.ChildInvocationMetrics)(collocated ? im1.Collocated[0] : im1.Remotes[0]);
        test(rim1.Current == 0 && rim1.Total == 2 && rim1.Failures == 0);
        test(rim1.Size == 82 && rim1.ReplySize > 7);
        checkFailure(clientMetrics, "Invocation", im1.Id, "::Ice::UnknownException", 2, output);

        if (!collocated)
        {
            im1 = (IceMX.InvocationMetrics)map["fail"];
            test(im1.Current <= 1 && im1.Total == 2 && im1.Failures == 2 && im1.Retry == 2 && im1.Remotes.Length == 1);
            rim1 = (IceMX.ChildInvocationMetrics)(collocated ? im1.Collocated[0] : im1.Remotes[0]);
            test(rim1.Current == 0);
            test(rim1.Total == 4);
            test(rim1.Failures == 4);
            checkFailure(clientMetrics, "Invocation", im1.Id, "::Ice::ConnectionLostException", 2, output);
        }

        testAttribute(clientMetrics, clientProps, update, "Invocation", "parent", "Communicator", op, output);
        testAttribute(clientMetrics, clientProps, update, "Invocation", "id", "metrics -t -e 1.1 [op]", op, output);

        testAttribute(clientMetrics, clientProps, update, "Invocation", "operation", "op", op, output);
        testAttribute(clientMetrics, clientProps, update, "Invocation", "identity", "metrics", op, output);
        testAttribute(clientMetrics, clientProps, update, "Invocation", "facet", "", op, output);
        testAttribute(clientMetrics, clientProps, update, "Invocation", "encoding", "1.1", op, output);
        testAttribute(clientMetrics, clientProps, update, "Invocation", "mode", "twoway", op, output);
        testAttribute(clientMetrics, clientProps, update, "Invocation", "proxy",
                      "metrics -t -e 1.1:" + endpoint + " -t " + timeout, op, output);

        testAttribute(clientMetrics, clientProps, update, "Invocation", "context.entry1", "test", op, output);
        testAttribute(clientMetrics, clientProps, update, "Invocation", "context.entry2", "", op, output);
        testAttribute(clientMetrics, clientProps, update, "Invocation", "context.entry3", "", op, output);

        //
        // Oneway tests
        //
        clearView(clientProps, serverProps, update);
        props["IceMX.Metrics.View.Map.Invocation.GroupBy"]            = "operation";
        props["IceMX.Metrics.View.Map.Invocation.Map.Remote.GroupBy"] = "localPort";
        updateProps(clientProps, serverProps, update, props, "Invocation");

        IMetricsPrx metricsOneway = metrics.Clone(oneway: true);

        metricsOneway.op();
        metricsOneway.opAsync().Wait();

        map = toMap(clientMetrics.GetMetricsView("View").ReturnValue["Invocation"]);
        test(map.Count == 1);

        im1 = (IceMX.InvocationMetrics)map["op"];
        test(im1.Current <= 1 && im1.Total == 2 && im1.Failures == 0 && im1.Retry == 0);
        test(collocated ? (im1.Collocated.Length == 1) : (im1.Remotes.Length == 1));
        rim1 = (IceMX.ChildInvocationMetrics)(collocated ? im1.Collocated[0] : im1.Remotes[0]);
        test(rim1.Current <= 1 && rim1.Total == 2 && rim1.Failures == 0);
        test(rim1.Size == 42 && rim1.ReplySize == 0);

        testAttribute(clientMetrics, clientProps, update, "Invocation", "mode", "oneway",
                      () => { invokeOp(metricsOneway); }, output);

        output.Write("testing metrics view enable/disable...");
        output.Flush();

        props["IceMX.Metrics.View.GroupBy"]  = "none";
        props["IceMX.Metrics.View.Disabled"] = "0";
        updateProps(clientProps, serverProps, update, props, "Thread");
        test(clientMetrics.GetMetricsView("View").ReturnValue["Thread"].Length != 0);
        var(names, disabledViews) = clientMetrics.GetMetricsViewNames();
        test(names.Length == 1 && disabledViews.Length == 0);

        props["IceMX.Metrics.View.Disabled"] = "1";
        updateProps(clientProps, serverProps, update, props, "Thread");
        test(!clientMetrics.GetMetricsView("View").ReturnValue.ContainsKey("Thread"));
        (names, disabledViews) = clientMetrics.GetMetricsViewNames();
        test(names.Length == 0 && disabledViews.Length == 1);

        clientMetrics.EnableMetricsView("View");
        test(clientMetrics.GetMetricsView("View").ReturnValue["Thread"].Length != 0);
        (names, disabledViews) = clientMetrics.GetMetricsViewNames();
        test(names.Length == 1 && disabledViews.Length == 0);

        clientMetrics.DisableMetricsView("View");
        test(!clientMetrics.GetMetricsView("View").ReturnValue.ContainsKey("Thread"));
        (names, disabledViews) = clientMetrics.GetMetricsViewNames();
        test(names.Length == 0 && disabledViews.Length == 1);

        try
        {
            clientMetrics.EnableMetricsView("UnknownView");
        }
        catch (IceMX.UnknownMetricsView)
        {
        }

        output.WriteLine("ok");

        output.Write("testing instrumentation observer delegate... ");
        output.Flush();

        test(obsv.threadObserver.getTotal() > 0);
        if (!collocated)
        {
            test(obsv.connectionObserver.getTotal() > 0);
            test(obsv.connectionEstablishmentObserver.getTotal() > 0);
            test(obsv.endpointLookupObserver.getTotal() > 0);
            test(obsv.invocationObserver.remoteObserver.getTotal() > 0);
        }
        else
        {
            test(obsv.invocationObserver.collocatedObserver.getTotal() > 0);
        }

        test(obsv.dispatchObserver.getTotal() > 0);
        test(obsv.invocationObserver.getTotal() > 0);

        test(obsv.threadObserver.GetCurrent() > 0);
        if (!collocated)
        {
            test(obsv.connectionObserver.GetCurrent() > 0);
            test(obsv.connectionEstablishmentObserver.GetCurrent() == 0);
            test(obsv.endpointLookupObserver.GetCurrent() == 0);
            waitForObserverCurrent(obsv.invocationObserver.remoteObserver, 0);
            test(obsv.invocationObserver.remoteObserver.GetCurrent() == 0);
        }
        else
        {
            waitForObserverCurrent(obsv.invocationObserver.collocatedObserver, 0);
            test(obsv.invocationObserver.collocatedObserver.GetCurrent() == 0);
        }
        waitForObserverCurrent(obsv.dispatchObserver, 0);
        test(obsv.dispatchObserver.GetCurrent() == 0);
        waitForObserverCurrent(obsv.invocationObserver, 0);
        test(obsv.invocationObserver.GetCurrent() == 0);

        test(obsv.threadObserver.GetFailedCount() == 0);
        if (!collocated)
        {
            test(obsv.connectionObserver.GetFailedCount() > 0);
            test(obsv.connectionEstablishmentObserver.GetFailedCount() > 0);
            test(obsv.endpointLookupObserver.GetFailedCount() > 0);
            test(obsv.invocationObserver.remoteObserver.GetFailedCount() > 0);
        }
        //test(obsv.dispatchObserver.getFailedCount() > 0);
        test(obsv.invocationObserver.GetFailedCount() > 0);

        if (!collocated)
        {
            test(obsv.threadObserver.states > 0);
            test(obsv.connectionObserver.received > 0 && obsv.connectionObserver.sent > 0);
            test(obsv.invocationObserver.retriedCount > 0);
            test(obsv.invocationObserver.remoteObserver.replySize > 0);
        }
        else
        {
            test(obsv.invocationObserver.collocatedObserver.replySize > 0);
        }
        //test(obsv.dispatchObserver.userExceptionCount > 0);
        test(obsv.invocationObserver.userExceptionCount > 0);

        output.WriteLine("ok");
        return(metrics);
    }
Example #5
0
    public static void allTests(TestHelper helper)
    {
        Communicator communicator = helper.communicator();
        var          admin        = IObjectPrx.Parse("DemoIceBox/admin:default -p 9996 -t 10000", communicator);

        ITestFacetPrx facet;

        Console.Out.Write("testing custom facet... ");
        Console.Out.Flush();
        {
            //
            // Test: Verify that the custom facet is present.
            //
            facet = ITestFacetPrx.CheckedCast(admin.Clone(facet: "TestFacet", IObjectPrx.Factory));
            facet.IcePing();
        }
        Console.Out.WriteLine("ok");

        Console.Out.Write("testing properties facet... ");
        Console.Out.Flush();
        {
            var pa = IPropertiesAdminPrx.CheckedCast(
                admin.Clone(facet: "IceBox.Service.TestService.Properties", IObjectPrx.Factory));

            //
            // Test: PropertiesAdmin::getProperty()
            //
            test(pa.GetProperty("Prop1") == "1");
            test(pa.GetProperty("Bogus") == "");

            //
            // Test: PropertiesAdmin::getProperties()
            //
            Dictionary <string, string> pd = pa.GetPropertiesForPrefix("");
            test(pd.Count == 6);
            test(pd["Prop1"] == "1");
            test(pd["Prop2"] == "2");
            test(pd["Prop3"] == "3");
            test(pd["Ice.Config"] == "config.service");
            test(pd["Ice.ProgramName"] == "IceBox-TestService");
            test(pd["Ice.Admin.Enabled"] == "1");

            Dictionary <string, string> changes;

            //
            // Test: PropertiesAdmin::setProperties()
            //
            Dictionary <string, string> setProps = new Dictionary <string, string>();
            setProps.Add("Prop1", "10"); // Changed
            setProps.Add("Prop2", "20"); // Changed
            setProps.Add("Prop3", "");   // Removed
            setProps.Add("Prop4", "4");  // Added
            setProps.Add("Prop5", "5");  // Added
            pa.SetProperties(setProps);
            test(pa.GetProperty("Prop1") == "10");
            test(pa.GetProperty("Prop2") == "20");
            test(pa.GetProperty("Prop3") == "");
            test(pa.GetProperty("Prop4") == "4");
            test(pa.GetProperty("Prop5") == "5");
            changes = facet.getChanges();
            test(changes.Count == 5);
            test(changes["Prop1"] == "10");
            test(changes["Prop2"] == "20");
            test(changes["Prop3"] == "");
            test(changes["Prop4"] == "4");
            test(changes["Prop5"] == "5");
            pa.SetProperties(setProps);
            changes = facet.getChanges();
            test(changes.Count == 0);
        }
        Console.Out.WriteLine("ok");

        Console.Out.Write("testing metrics admin facet... ");
        Console.Out.Flush();
        {
            var ma = IceMX.IMetricsAdminPrx.CheckedCast(
                admin.Clone(facet: "IceBox.Service.TestService.Metrics", IObjectPrx.Factory));
            var pa = IPropertiesAdminPrx.CheckedCast(
                admin.Clone(facet: "IceBox.Service.TestService.Properties", IObjectPrx.Factory));

            string[] views;
            string[] disabledViews;
            views = ma.GetMetricsViewNames().ReturnValue;
            test(views.Length == 0);

            Dictionary <string, string> setProps = new Dictionary <string, string>();
            setProps.Add("IceMX.Metrics.Debug.GroupBy", "id");
            setProps.Add("IceMX.Metrics.All.GroupBy", "none");
            setProps.Add("IceMX.Metrics.Parent.GroupBy", "parent");
            pa.SetProperties(setProps);
            pa.SetProperties(new Dictionary <string, string>());

            views = ma.GetMetricsViewNames().ReturnValue;
            test(views.Length == 3);

            // Make sure that the IceBox communicator metrics admin is a separate instance.
            views = IceMX.IMetricsAdminPrx.
                    CheckedCast(admin.Clone(facet: "Metrics", IObjectPrx.Factory)).GetMetricsViewNames().ReturnValue;
            test(views.Length == 0);
        }
        Console.Out.WriteLine("ok");
    }
Example #6
0
        public static void allTests(global::Test.TestHelper helper)
        {
            Communicator communicator = helper.communicator();
            var          output       = helper.getWriter();

            output.Write("testing communicator operations... ");
            output.Flush();
            {
                //
                // Test: Exercise AddAdminFacet, FindAdminFacet, RemoveAdminFacet with a typical configuration.
                //
                var properties = new Dictionary <string, string>();
                properties["Ice.Admin.Endpoints"]    = "tcp -h 127.0.0.1";
                properties["Ice.Admin.InstanceName"] = "Test";
                var com = new Communicator(properties);
                testFacets(com, true, false);
                com.Destroy();
            }
            {
                //
                // Test: Verify that the operations work correctly in the presence of facet filters.
                //
                var properties = new Dictionary <string, string>();
                properties["Ice.Admin.Endpoints"]    = "tcp -h 127.0.0.1";
                properties["Ice.Admin.InstanceName"] = "Test";
                properties["Ice.Admin.Facets"]       = "Properties";
                Communicator com = new Communicator(properties);
                testFacets(com, false, true);
                com.Destroy();
            }
            {
                //
                // Test: Verify that the operations work correctly with the Admin object disabled.
                //
                var com = new Communicator();
                testFacets(com, false, false);
                com.Destroy();
            }
            {
                //
                // Test: Verify that the operations work correctly with Ice.Admin.Enabled=1
                //
                var properties = new Dictionary <string, string>()
                {
                    { "Ice.Admin.Enabled", "1" }
                };
                Communicator com = new Communicator(properties);
                test(com.GetAdmin() == null);
                Identity id = Identity.Parse("test-admin");
                try
                {
                    com.CreateAdmin(null, id);
                    test(false);
                }
                catch (InvalidConfigurationException)
                {
                }

                ObjectAdapter adapter = com.CreateObjectAdapter();
                test(com.CreateAdmin(adapter, id) != null);
                test(com.GetAdmin() != null);

                testFacets(com, true, false);
                com.Destroy();
            }
            {
                //
                // Test: Verify that the operations work correctly when creation of the Admin object is delayed.
                //
                var properties = new Dictionary <string, string>()
                {
                    { "Ice.Admin.Endpoints", "tcp -h 127.0.0.1" },
                    { "Ice.Admin.InstanceName", "Test" },
                    { "Ice.Admin.DelayCreation", "1" }
                };

                Communicator com = new Communicator(properties);
                testFacets(com, true, false);
                com.GetAdmin();
                testFacets(com, true, false);
                com.Destroy();
            }
            output.WriteLine("ok");

            var factory = IRemoteCommunicatorFactoryPrx.Parse($"factory:{helper.getTestEndpoint(0)} -t 10000",
                                                              communicator);

            output.Write("testing process facet... ");
            output.Flush();
            {
                //
                // Test: Verify that Process::shutdown() operation shuts down the communicator.
                //
                Dictionary <string, string> props = new Dictionary <string, string>();
                props.Add("Ice.Admin.Endpoints", "tcp -h 127.0.0.1");
                props.Add("Ice.Admin.InstanceName", "Test");
                var         com  = factory.createCommunicator(props);
                IObjectPrx  obj  = com.getAdmin();
                IProcessPrx proc = obj.Clone("Process", IProcessPrx.Factory);
                proc.Shutdown();
                com.waitForShutdown();
                com.destroy();
            }
            output.WriteLine("ok");

            output.Write("testing properties facet... ");
            output.Flush();
            {
                Dictionary <string, string> props = new Dictionary <string, string>();
                props.Add("Ice.Admin.Endpoints", "tcp -h 127.0.0.1");
                props.Add("Ice.Admin.InstanceName", "Test");
                props.Add("Prop1", "1");
                props.Add("Prop2", "2");
                props.Add("Prop3", "3");
                var                 com = factory.createCommunicator(props);
                IObjectPrx          obj = com.getAdmin();
                IPropertiesAdminPrx pa  = obj.Clone("Properties", IPropertiesAdminPrx.Factory);

                //
                // Test: PropertiesAdmin::getProperty()
                //
                test(pa.GetProperty("Prop2") == "2");
                test(pa.GetProperty("Bogus") == "");

                //
                // Test: PropertiesAdmin::getProperties()
                //
                Dictionary <string, string> pd = pa.GetPropertiesForPrefix("");
                test(pd.Count == 6);
                test(pd["Ice.ProgramName"] == "server");
                test(pd["Ice.Admin.Endpoints"] == "tcp -h 127.0.0.1");
                test(pd["Ice.Admin.InstanceName"] == "Test");
                test(pd["Prop1"] == "1");
                test(pd["Prop2"] == "2");
                test(pd["Prop3"] == "3");

                Dictionary <string, string> changes;

                //
                // Test: PropertiesAdmin::setProperties()
                //
                Dictionary <string, string> setProps = new Dictionary <string, string>();
                setProps.Add("Prop1", "10"); // Changed
                setProps.Add("Prop2", "20"); // Changed
                setProps.Add("Prop3", "");   // Removed
                setProps.Add("Prop4", "4");  // Added
                setProps.Add("Prop5", "5");  // Added
                pa.SetProperties(setProps);
                test(pa.GetProperty("Prop1").Equals("10"));
                test(pa.GetProperty("Prop2").Equals("20"));
                test(pa.GetProperty("Prop3").Equals(""));
                test(pa.GetProperty("Prop4").Equals("4"));
                test(pa.GetProperty("Prop5").Equals("5"));
                changes = com.getChanges();
                test(changes.Count == 5);
                test(changes["Prop1"].Equals("10"));
                test(changes["Prop2"].Equals("20"));
                test(changes["Prop3"].Equals(""));
                test(changes["Prop4"].Equals("4"));
                test(changes["Prop5"].Equals("5"));
                pa.SetProperties(setProps);
                changes = com.getChanges();
                test(changes.Count == 0);

                com.destroy();
            }
            output.WriteLine("ok");

            output.Write("testing logger facet... ");
            output.Flush();
            {
                var props = new Dictionary <string, string>();
                props.Add("Ice.Admin.Endpoints", "tcp -h 127.0.0.1");
                props.Add("Ice.Admin.InstanceName", "Test");
                props.Add("NullLogger", "1");
                var com = factory.createCommunicator(props);

                com.trace("testCat", "trace");
                com.warning("warning");
                com.error("error");
                com.print("print");

                IObjectPrx obj    = com.getAdmin();
                var        logger = obj.Clone("Logger", ILoggerAdminPrx.Factory);
                test(logger != null);

                //
                // Get all
                //
                var(logMessages, prefix) = logger.GetLog(Array.Empty <LogMessageType>(), Array.Empty <string>(), -1);

                test(logMessages.Length == 4);
                test(prefix.Equals("NullLogger"));
                test(logMessages[0].TraceCategory.Equals("testCat") && logMessages[0].Message.Equals("trace"));
                test(logMessages[1].Message.Equals("warning"));
                test(logMessages[2].Message.Equals("error"));
                test(logMessages[3].Message.Equals("print"));

                //
                // Get only errors and warnings
                //
                com.error("error2");
                com.print("print2");
                com.trace("testCat", "trace2");
                com.warning("warning2");

                LogMessageType[] messageTypes = { LogMessageType.ErrorMessage, LogMessageType.WarningMessage };

                (logMessages, prefix) = logger.GetLog(messageTypes, Array.Empty <string>(), -1);

                test(logMessages.Length == 4);
                test(prefix.Equals("NullLogger"));

                foreach (LogMessage msg in logMessages)
                {
                    test(msg.Type == LogMessageType.ErrorMessage || msg.Type == LogMessageType.WarningMessage);
                }

                //
                // Get only errors and traces with Cat = "testCat"
                //
                com.trace("testCat2", "A");
                com.trace("testCat", "trace3");
                com.trace("testCat2", "B");

                messageTypes = new LogMessageType[] { LogMessageType.ErrorMessage, LogMessageType.TraceMessage };
                string[] categories = { "testCat" };
                (logMessages, prefix) = logger.GetLog(messageTypes, categories, -1);
                test(logMessages.Length == 5);
                test(prefix.Equals("NullLogger"));

                foreach (var msg in logMessages)
                {
                    test(msg.Type == LogMessageType.ErrorMessage ||
                         (msg.Type == LogMessageType.TraceMessage && msg.TraceCategory.Equals("testCat")));
                }

                //
                // Same, but limited to last 2 messages(trace3 + error3)
                //
                com.error("error3");

                (logMessages, prefix) = logger.GetLog(messageTypes, categories, 2);
                test(logMessages.Length == 2);
                test(prefix.Equals("NullLogger"));

                test(logMessages[0].Message.Equals("trace3"));
                test(logMessages[1].Message.Equals("error3"));

                //
                // Now, test RemoteLogger
                //
                ObjectAdapter adapter =
                    communicator.CreateObjectAdapterWithEndpoints("RemoteLoggerAdapter", "tcp -h localhost");

                var remoteLogger = new RemoteLogger();

                IRemoteLoggerPrx myProxy = adapter.AddWithUUID(remoteLogger, IRemoteLoggerPrx.Factory);

                adapter.Activate();

                //
                // No filtering
                //
                (logMessages, prefix) = logger.GetLog(Array.Empty <LogMessageType>(), Array.Empty <string>(), -1);

                logger.AttachRemoteLogger(myProxy, Array.Empty <LogMessageType>(), Array.Empty <string>(), -1);
                remoteLogger.Wait(1);

                foreach (var m in logMessages)
                {
                    remoteLogger.CheckNextInit(prefix, m.Type, m.Message, m.TraceCategory);
                }

                com.trace("testCat", "rtrace");
                com.warning("rwarning");
                com.error("rerror");
                com.print("rprint");

                remoteLogger.Wait(4);

                remoteLogger.CheckNextLog(LogMessageType.TraceMessage, "rtrace", "testCat");
                remoteLogger.CheckNextLog(LogMessageType.WarningMessage, "rwarning", "");
                remoteLogger.CheckNextLog(LogMessageType.ErrorMessage, "rerror", "");
                remoteLogger.CheckNextLog(LogMessageType.PrintMessage, "rprint", "");

                test(logger.DetachRemoteLogger(myProxy));
                test(!logger.DetachRemoteLogger(myProxy));

                //
                // Use Error + Trace with "traceCat" filter with 4 limit
                //
                (logMessages, prefix) = logger.GetLog(messageTypes, categories, 4);
                test(logMessages.Length == 4);

                logger.AttachRemoteLogger(myProxy, messageTypes, categories, 4);
                remoteLogger.Wait(1);

                foreach (var m in logMessages)
                {
                    remoteLogger.CheckNextInit(prefix, m.Type, m.Message, m.TraceCategory);
                }

                com.warning("rwarning2");
                com.trace("testCat", "rtrace2");
                com.warning("rwarning3");
                com.error("rerror2");
                com.print("rprint2");

                remoteLogger.Wait(2);

                remoteLogger.CheckNextLog(LogMessageType.TraceMessage, "rtrace2", "testCat");
                remoteLogger.CheckNextLog(LogMessageType.ErrorMessage, "rerror2", "");

                //
                // Attempt reconnection with slightly different proxy
                //
                try
                {
                    logger.AttachRemoteLogger(myProxy.Clone(oneway: true), messageTypes, categories, 4);
                    test(false);
                }
                catch (RemoteLoggerAlreadyAttachedException)
                {
                    // expected
                }

                com.destroy();
            }
            output.WriteLine("ok");

            output.Write("testing custom facet... ");
            output.Flush();
            {
                //
                // Test: Verify that the custom facet is present.
                //
                Dictionary <string, string> props = new Dictionary <string, string>();
                props.Add("Ice.Admin.Endpoints", "tcp -h 127.0.0.1");
                props.Add("Ice.Admin.InstanceName", "Test");
                var        com = factory.createCommunicator(props);
                IObjectPrx obj = com.getAdmin();
                var        tf  = obj.Clone("TestFacet", ITestFacetPrx.Factory);
                tf.op();
                com.destroy();
            }
            output.WriteLine("ok");

            output.Write("testing facet filtering... ");
            output.Flush();
            {
                //
                // Test: Set Ice.Admin.Facets to expose only the Properties facet,
                // meaning no other facet is available.
                //
                Dictionary <string, string> props = new Dictionary <string, string>();
                props.Add("Ice.Admin.Endpoints", "tcp -h 127.0.0.1");
                props.Add("Ice.Admin.InstanceName", "Test");
                props.Add("Ice.Admin.Facets", "Properties");
                var        com = factory.createCommunicator(props);
                IObjectPrx obj = com.getAdmin();
                try
                {
                    IProcessPrx.CheckedCast(obj.Clone(facet: "Process", IObjectPrx.Factory));
                    test(false);
                }
                catch (ObjectNotExistException)
                {
                }

                try
                {
                    ITestFacetPrx.CheckedCast(obj.Clone(facet: "TestFacet", IObjectPrx.Factory));
                    test(false);
                }
                catch (ObjectNotExistException)
                {
                }
                com.destroy();
            }
            {
                //
                // Test: Set Ice.Admin.Facets to expose only the Process facet,
                // meaning no other facet is available.
                //
                Dictionary <string, string> props = new Dictionary <string, string>();
                props.Add("Ice.Admin.Endpoints", "tcp -h 127.0.0.1");
                props.Add("Ice.Admin.InstanceName", "Test");
                props.Add("Ice.Admin.Facets", "Process");
                var        com = factory.createCommunicator(props);
                IObjectPrx obj = com.getAdmin();
                try
                {
                    IPropertiesAdminPrx.CheckedCast(obj.Clone(facet: "Properties", IObjectPrx.Factory));
                    test(false);
                }
                catch (ObjectNotExistException)
                {
                }

                try
                {
                    ITestFacetPrx.CheckedCast(obj.Clone(facet: "TestFacet", IObjectPrx.Factory));
                    test(false);
                }
                catch (ObjectNotExistException)
                {
                }
                com.destroy();
            }
            {
                //
                // Test: Set Ice.Admin.Facets to expose only the TestFacet facet,
                // meaning no other facet is available.
                //
                Dictionary <string, string> props = new Dictionary <string, string>();
                props.Add("Ice.Admin.Endpoints", "tcp -h 127.0.0.1");
                props.Add("Ice.Admin.InstanceName", "Test");
                props.Add("Ice.Admin.Facets", "TestFacet");
                var        com = factory.createCommunicator(props);
                IObjectPrx obj = com.getAdmin();
                try
                {
                    IPropertiesAdminPrx.CheckedCast(obj.Clone(facet: "Properties", IObjectPrx.Factory));
                    test(false);
                }
                catch (ObjectNotExistException)
                {
                }

                try
                {
                    IProcessPrx.CheckedCast(obj.Clone(facet: "Process", IObjectPrx.Factory));
                    test(false);
                }
                catch (ObjectNotExistException)
                {
                }
                com.destroy();
            }
            {
                //
                // Test: Set Ice.Admin.Facets to expose two facets. Use whitespace to separate the
                // facet names.
                //
                Dictionary <string, string> props = new Dictionary <string, string>();
                props.Add("Ice.Admin.Endpoints", "tcp -h 127.0.0.1");
                props.Add("Ice.Admin.InstanceName", "Test");
                props.Add("Ice.Admin.Facets", "Properties TestFacet");
                var                 com = factory.createCommunicator(props);
                IObjectPrx          obj = com.getAdmin();
                IPropertiesAdminPrx pa  = obj.Clone("Properties", IPropertiesAdminPrx.Factory);
                test(pa.GetProperty("Ice.Admin.InstanceName").Equals("Test"));
                var tf = ITestFacetPrx.CheckedCast(obj.Clone(facet: "TestFacet", IObjectPrx.Factory));
                tf !.op();
                try
                {
                    IProcessPrx.CheckedCast(obj.Clone(facet: "Process", IObjectPrx.Factory));
                    test(false);
                }
                catch (ObjectNotExistException)
                {
                }
                com.destroy();
            }
            {
                //
                // Test: Set Ice.Admin.Facets to expose two facets. Use a comma to separate the
                // facet names.
                //
                Dictionary <string, string> props = new Dictionary <string, string>();
                props.Add("Ice.Admin.Endpoints", "tcp -h 127.0.0.1");
                props.Add("Ice.Admin.InstanceName", "Test");
                props.Add("Ice.Admin.Facets", "TestFacet, Process");
                var        com = factory.createCommunicator(props);
                IObjectPrx obj = com.getAdmin();
                try
                {
                    IPropertiesAdminPrx.CheckedCast(obj.Clone(facet: "Properties", IObjectPrx.Factory));
                    test(false);
                }
                catch (ObjectNotExistException)
                {
                }
                var tf = ITestFacetPrx.CheckedCast(obj.Clone(facet: "TestFacet", IObjectPrx.Factory));
                tf.op();
                IProcessPrx proc = IProcessPrx.CheckedCast(obj.Clone(facet: "Process", IObjectPrx.Factory));
                proc.Shutdown();
                com.waitForShutdown();
                com.destroy();
            }
            output.WriteLine("ok");

            factory.shutdown();
        }