public void Test()
        {
            LogManager.Adapter = new Common.Logging.Simple.DebugLoggerFactoryAdapter(LogLevel.Info, true, true, true, "dd.MM 'UTC'z HH:mm:ss");

            var caCert         = new X509Certificate2(ReadEmbedded("ca.crt"));
            var serverPrivCert = new X509Certificate2(ReadEmbedded("server.pfx"));
            var serverCerts    = new[] { serverPrivCert };

            var clientCertBundle = new X509Certificate2Collection();

            clientCertBundle.Import(ReadEmbedded("client.pfx"));
            var clientPrivCert = clientCertBundle[0];

            var certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);

            certStore.Open(OpenFlags.ReadWrite);
            for (var n = 1; n < clientCertBundle.Count; n++)
            {
                certStore.Add(clientCertBundle[n]);
            }
            certStore.Close();

            MagicProxySettings.TypeSearchAssemblies.Add(typeof(LolClass).Assembly);

            var logger = LogManager.GetLogger("ProxyServer");

            var impl   = new FullBackendImpl();
            var server = new MagicProxyServer <IBackend, FullBackendImpl, ConnectionFlags>(() => impl, new IPEndPoint(IPAddress.Any, _port), logger, serverCerts, caCert);
            var client = new MagicProxyClient <IBackend, ConnectionFlags>("localhost", _port, caCert, clientPrivCert);

            server.StartServer();
            Thread.Sleep(100);
            client.ConnectAsync().Wait();
            var connected = client.Connected;
            var state0    = client.ConnectionState;

            client.Proxy.ClientUpdateRequired(77).Wait();
            var state1 = client.ConnectionState;

            client.Proxy.ClientUpdateRequired(717).Wait();
            var state2 = client.ConnectionState;

            client.Proxy.ClientUpdateRequired(77).Wait();
            var state3 = client.ConnectionState;

            var success = client.Proxy.Authenticate("foo", "bar").Result;
            var state4  = client.ConnectionState;

            client.Proxy.Logout().Wait();
            var state5 = client.ConnectionState;

            success = client.Proxy.Authenticate("foo", "bar").Result;
            var state6 = client.ConnectionState;

            var secureProxy = client.Proxy;

            secureProxy.SimpleAction().Wait();
            secureProxy.DoBar(11).Wait();
            var ret = secureProxy.Foo(42).Result;

            var raw = secureProxy.GetRaw(0x5000).Result;

            Assert.AreEqual(raw[0], 0x55);
            Assert.AreEqual(raw[0x4FFF], 0x66);
            var aa = secureProxy.GetFromDb <Guid>(123).Result;
            var bb = secureProxy.GetFromDb <LolClass>(123).Result;

            bb.Member = "aBC";
            secureProxy.Update(bb).Wait();
            var nst = secureProxy.Nested <LolClass>().Result;
            var der = secureProxy.Nested <LolDerived>().Result;

            Assert.ThrowsExceptionAsync <ServerSideException>(() => secureProxy.SimpleThrows()).Wait();

            impl.Count = 0;
            Console.WriteLine("\nBenchmark...");
            const int cnt = 10000;
            var       sw  = new Stopwatch();

            sw.Start();
            for (var n = cnt; n > 0; n--)
            {
                secureProxy.Foo(n).Wait();
            }
            sw.Stop();
            Console.WriteLine($"{cnt / sw.Elapsed.TotalSeconds:F0} ops per second");
            Console.WriteLine($"{1000d * sw.ElapsedMilliseconds / cnt:F1}us per op");

            Console.WriteLine(impl.Count);
            impl.Count = 0;


            sw.Restart();
            for (var n = 10; n > 0; n--)
            {
                secureProxy.GetRaw(10 * 1024 * 1024).Wait();
            }
            sw.Stop();
            Console.WriteLine($"{100d / sw.Elapsed.TotalSeconds:F0} MB/s");

            Task ClientInstance(int repeats)
            {
                return(Task.Run(async() =>
                {
                    var proxy = new MagicProxyClient <IBackend, ConnectionFlags>("localhost", _port, caCert, clientPrivCert);
                    await proxy.ConnectAsync();
                    for (var n = repeats; n > 0; n--)
                    {
                        await proxy.Proxy.Foo(n);
                    }

                    await proxy.DisconnectAsync();
                }));
            }

            var para = 10;

            Console.WriteLine($"\n{para} parallel clients...");
            sw.Restart();
            var tasks = Enumerable.Repeat(1, 10).Select(_ => ClientInstance(cnt)).ToArray();

            Task.WaitAll(tasks);
            sw.Stop();
            Console.WriteLine($"{para * cnt / sw.Elapsed.TotalSeconds:F0} ops per second");
            Console.WriteLine($"{1000d * sw.ElapsedMilliseconds / cnt / para:F1}us per op");

            Console.WriteLine(impl.Count);
        }
        public void Test()
        {
            MagicProxySettings.TypeSearchAssemblies.Add(typeof(LolClass).Assembly);
            MagicProxySettings.TypeSearchAssemblies.Add(typeof(Stopwatch).Assembly);

            var impl = new FullBackendImpl();
            var mock = new MagicProxyMockConnection <IBackend, ConnectionFlags>(impl);

            //display line data
            mock.WireSniffer = (req, err, resp) =>
            {
                Console.Write(req + " => ");
                Console.WriteLine(err == null ? Encoding.UTF8.GetString(resp) : $"err: {err}");
            };
            mock.ConnectAsync().Wait();
            var state0 = mock.ConnectionState;

            mock.Proxy.ClientUpdateRequired(77).Wait();
            var state1 = mock.ConnectionState;

            mock.Proxy.ClientUpdateRequired(717).Wait();
            var state2 = mock.ConnectionState;

            mock.Proxy.ClientUpdateRequired(77).Wait();
            var state3 = mock.ConnectionState;

            mock.Proxy.Authenticate("foo", "bar").Wait();
            var state4 = mock.ConnectionState;
            var proxy  = mock.Proxy;

            proxy.SimpleAction().Wait();
            proxy.DoBar(11).Wait();

            var dt        = new DateTime(2018, 1, 1, 10, 0, 0, DateTimeKind.Local);
            var dto       = new DateTimeOffset(2018, 2, 2, 10, 0, 0, 0, TimeSpan.FromHours(4));
            var roundtrip = proxy.DateTest(dt, dto).Result;

            var isNull = proxy.GetNull <Stopwatch>().Result;
            var ret    = proxy.Foo(42).Result;
            var raw    = proxy.GetRaw(0x5000).Result;
            var aa     = proxy.GetFromDb <Guid>(123).Result;
            var bb     = proxy.GetFromDb <LolClass>(123).Result;

            bb.Member = "aBC";
            proxy.Update(bb).Wait();
            var nst = proxy.Nested <LolClass>().Result;
            var der = proxy.Nested <LolDerived>().Result;

            Assert.ThrowsExceptionAsync <ServerSideException>(() => proxy.SimpleThrows()).Wait();

            Console.WriteLine("\nBenchmark...");
            mock.WireSniffer = null;
            const int cnt = 100000;
            var       sw  = new Stopwatch();

            sw.Start();
            for (var n = cnt; n >= 0; n--)
            {
                proxy.Foo(n).Wait();
            }
            sw.Stop();
            Console.WriteLine($"{cnt / sw.Elapsed.TotalSeconds:F0} ops per second");
            Console.WriteLine($"{1000d * sw.ElapsedMilliseconds / cnt:F1}us per op");
        }