Пример #1
0
        public static IMyObjectPrx Run(TestHelper helper)
        {
            bool ice2 = helper.Protocol == Protocol.Ice2;
            var  prx  = IMyObjectPrx.Parse(helper.GetTestProxy("test"), helper.Communicator !);

            System.IO.TextWriter output = helper.Output;

            output.Write("testing retry... ");
            output.Flush();
            TestHelper.Assert(prx.AddWithRetry(33, 12) == 45);
            output.WriteLine("ok");

            output.Write("testing remote exception... ");
            output.Flush();
            try
            {
                prx.BadAdd(33, 12);
                TestHelper.Assert(false);
            }
            catch (InvalidInputException)
            {
                // expected
            }
            output.WriteLine("ok");

            output.Write("testing ONE... ");
            output.Flush();
            try
            {
                prx.NotExistAdd(33, 12);
                TestHelper.Assert(false);
            }
            catch (ObjectNotExistException)
            {
                // expected
            }
            output.WriteLine("ok");

            output.Write("testing exceptions raised by the interceptor... ");
            output.Flush();
            var exceptions = new List <(string operation, string kind)>
            {
                ("raiseBeforeDispatch", "invalidInput"),
                ("raiseBeforeDispatch", "notExist"),
                ("raiseAfterDispatch", "invalidInput"),
                ("raiseAfterDispatch", "notExist")
            };

            foreach ((string operation, string kind) in exceptions)
            {
                var ctx = new Dictionary <string, string>
                {
                    { operation, kind }
                };

                try
                {
                    prx.IcePing(ctx);
                    TestHelper.Assert(false);
                }
                catch (InvalidInputException) when(kind == "invalidInput")
                {
                }
                catch (ObjectNotExistException) when(kind == "notExist")
                {
                }
            }
            output.WriteLine("ok");

            output.Write("testing invocation interceptors... ");
            output.Flush();
            {
                var tasks             = new List <Task>();
                var invocationContext = new AsyncLocal <int>();
                using var communicator = new Communicator(
                          prx.Communicator.GetProperties(),
                          invocationInterceptors: new InvocationInterceptor[]
                {
                    (target, request, next, cancel) =>
                    {
                        if (ice2)
                        {
                            request.ContextOverride["interceptor-1"] = "interceptor-1";
                            request.AddBinaryContextEntry(110, 110, (ostr, v) => ostr.WriteInt(v));
                        }
                        return(next(target, request, cancel));
                    },
                    async(target, request, next, cancel) =>
                    {
                        if (ice2)
                        {
                            TestHelper.Assert(request.Context["interceptor-1"] == "interceptor-1");
                            request.ContextOverride["interceptor-2"] = "interceptor-2";
                            request.AddBinaryContextEntry(120, 120, (ostr, v) => ostr.WriteInt(v));
                        }
                        IncomingResponseFrame response = await next(target, request, cancel);
                        TestHelper.Assert(invocationContext.Value == int.Parse(request.Context["local-user"]));
                        if (ice2)
                        {
                            TestHelper.Assert(response.BinaryContext.ContainsKey(110));
                            TestHelper.Assert(response.BinaryContext[110].Read(istr => istr.ReadInt()) == 110);
                            TestHelper.Assert(response.BinaryContext.ContainsKey(120));
                            TestHelper.Assert(response.BinaryContext[120].Read(istr => istr.ReadInt()) == 120);
                        }
                        return(response);
                    }
                });

                for (int i = 0; i < 10; ++i)
                {
                    invocationContext.Value = i;
                    var  prx1 = IMyObjectPrx.Parse(prx.ToString() !, communicator);
                    Task t    = prx1.Op1Async(new Dictionary <string, string> {
                        { "local-user", $"{i}" }
                    });
                    tasks.Add(t);
                }
                Task.WaitAll(tasks.ToArray());
            }

            {
                IncomingResponseFrame?response = null;
                int invocations = 0;
                // An interceptor can stop the chain and directly return a response without calling next,
                // the first invocation calls next and subsequent invocations reuse the first response.
                using var communicator = new Communicator(
                          prx.Communicator.GetProperties(),
                          invocationInterceptors: new InvocationInterceptor[]
                {
                    (target, request, next, cancel) =>
                    {
                        if (ice2)
                        {
                            request.ContextOverride["interceptor-1"] = "interceptor-1";
                        }
                        return(next(target, request, cancel));
                    },
                    async(target, request, next, cancel) =>
                    {
                        if (response == null)
                        {
                            response = await next(target, request, cancel);
                        }
                        return(response);
                    },
                    (target, request, next, cancel) =>
                    {
                        invocations++;
                        TestHelper.Assert(response == null);
                        return(next(target, request, cancel));
                    }
                });

                var prx1 = IMyObjectPrx.Parse(prx.ToString() !, communicator);
                prx1.Op1(new Dictionary <string, string> {
                    { "local-user", "10" }
                });
                prx1.Op1(new Dictionary <string, string> {
                    { "local-user", "11" }
                });
                prx1.Op1(new Dictionary <string, string> {
                    { "local-user", "12" }
                });
                TestHelper.Assert(invocations == 1);
            }

            {
                // throwing from an interceptor stops the interceptor chain
                using var communicator = new Communicator(
                          prx.Communicator.GetProperties(),
                          invocationInterceptors: new InvocationInterceptor[]
                {
                    (target, request, next, cancel) =>
                    {
                        request.ContextOverride["interceptor-1"] = "interceptor-1";
                        return(next(target, request, cancel));
                    },
                    (target, request, next, cancel) =>
                    {
                        TestHelper.Assert(request.Context["interceptor-1"] == "interceptor-1");
                        throw new InvalidOperationException("stop interceptor chain");
                    },
                    (target, request, next, cancel) =>
                    {
                        TestHelper.Assert(false);
                        return(next(target, request, cancel));
                    }
                });

                var prx1 = IMyObjectPrx.Parse(prx.ToString() !, communicator);
                try
                {
                    prx1.Op1();
                    TestHelper.Assert(false);
                }
                catch (InvalidOperationException)
                {
                }
            }
            output.WriteLine("ok");

            output.Write("testing binary context... ");
            output.Flush();

            if (ice2)
            {
                for (int size = 128; size < 4096; size *= 2)
                {
                    var token   = new Token(1, "mytoken", Enumerable.Range(0, size).Select(i => (byte)2).ToArray());
                    var request = OutgoingRequestFrame.WithArgs(prx,
                                                                "opWithBinaryContext",
                                                                idempotent: false,
                                                                compress: false,
                                                                format: default,
Пример #2
0
        public static IMyObjectPrx Run(TestHelper helper)
        {
            bool ice2 = helper.Protocol == Protocol.Ice2;
            var  prx  = IMyObjectPrx.Parse(helper.GetTestProxy("test"), helper.Communicator !);

            System.IO.TextWriter output = helper.Output;

            output.Write("testing retry... ");
            output.Flush();
            TestHelper.Assert(prx.AddWithRetry(33, 12) == 45);
            output.WriteLine("ok");

            output.Write("testing remote exception... ");
            output.Flush();
            try
            {
                prx.BadAdd(33, 12);
                TestHelper.Assert(false);
            }
            catch (InvalidInputException)
            {
                // expected
            }
            output.WriteLine("ok");

            output.Write("testing ONE... ");
            output.Flush();
            try
            {
                prx.NotExistAdd(33, 12);
                TestHelper.Assert(false);
            }
            catch (ObjectNotExistException)
            {
                // expected
            }
            output.WriteLine("ok");

            output.Write("testing exceptions raised by the interceptor... ");
            output.Flush();
            var exceptions = new List <(string operation, string kind)>
            {
                ("raiseBeforeDispatch", "invalidInput"),
                ("raiseBeforeDispatch", "notExist"),
                ("raiseAfterDispatch", "invalidInput"),
                ("raiseAfterDispatch", "notExist")
            };

            foreach ((string operation, string kind) in exceptions)
            {
                var ctx = new Dictionary <string, string>
                {
                    { operation, kind }
                };

                try
                {
                    prx.IcePing(ctx);
                    TestHelper.Assert(false);
                }
                catch (InvalidInputException) when(kind == "invalidInput")
                {
                }
                catch (ObjectNotExistException) when(kind == "notExist")
                {
                }
            }
            output.WriteLine("ok");

            output.Write("testing invocation interceptors... ");
            output.Flush();
            {
                var tasks             = new List <Task>();
                var invocationContext = new AsyncLocal <int>();
                using var communicator = new Communicator(prx.Communicator.GetProperties());

                communicator.DefaultInvocationInterceptors = ImmutableList.Create <InvocationInterceptor>(
                    (target, request, next, cancel) =>
                {
                    request.WritableContext["interceptor-1"] = "interceptor-1";
                    if (ice2)
                    {
                        request.BinaryContextOverride.Add(110, ostr => ostr.WriteInt(110));
                    }
                    return(next(target, request, cancel));
                },
                    async(target, request, next, cancel) =>
                {
                    TestHelper.Assert(request.Context["interceptor-1"] == "interceptor-1");
                    request.WritableContext["interceptor-2"] = "interceptor-2";
                    if (ice2)
                    {
                        request.BinaryContextOverride.Add(120, ostr => ostr.WriteInt(120));
                    }
                    IncomingResponseFrame response = await next(target, request, cancel);
                    TestHelper.Assert(invocationContext.Value == int.Parse(request.Context["local-user"]));
                    if (ice2)
                    {
                        TestHelper.Assert(response.BinaryContext.ContainsKey(110));
                        TestHelper.Assert(response.BinaryContext[110].Read(istr => istr.ReadInt()) == 110);
                        TestHelper.Assert(response.BinaryContext.ContainsKey(120));
                        TestHelper.Assert(response.BinaryContext[120].Read(istr => istr.ReadInt()) == 120);
                    }
                    return(response);
                });

                communicator.ActivateAsync().GetAwaiter().GetResult();

                for (int i = 0; i < 10; ++i)
                {
                    invocationContext.Value = i;
                    var  prx1 = IMyObjectPrx.Parse(prx.ToString() !, communicator);
                    Task t    = prx1.Op1Async(new Dictionary <string, string> {
                        { "local-user", $"{i}" }
                    });
                    tasks.Add(t);
                }
                Task.WaitAll(tasks.ToArray());
            }

            {
                IncomingResponseFrame?response = null;
                int invocations = 0;
                // An interceptor can stop the chain and directly return a response without calling next,
                // the first invocation calls next and subsequent invocations reuse the first response.
                using var communicator = new Communicator(prx.Communicator.GetProperties());

                communicator.DefaultInvocationInterceptors = ImmutableList.Create <InvocationInterceptor>(
                    (target, request, next, cancel) =>
                {
                    request.WritableContext["interceptor-1"] = "interceptor-1";
                    return(next(target, request, cancel));
                },
                    async(target, request, next, cancel) =>
                {
                    if (response == null)
                    {
                        response = await next(target, request, cancel);
                    }
                    return(response);
                },
                    (target, request, next, cancel) =>
                {
                    invocations++;
                    TestHelper.Assert(response == null);
                    return(next(target, request, cancel));
                });

                TestHelper.Assert(communicator.DefaultInvocationInterceptors.Count == 3);
                communicator.ActivateAsync().GetAwaiter().GetResult();
                TestHelper.Assert(communicator.DefaultInvocationInterceptors.Count == 4);

                var prx1 = IMyObjectPrx.Parse(prx.ToString() !, communicator);

                // Truly reference equal
                TestHelper.Assert(prx1.InvocationInterceptors == communicator.DefaultInvocationInterceptors);

                prx1.Op1(new Dictionary <string, string> {
                    { "local-user", "10" }
                });
                prx1.Op1(new Dictionary <string, string> {
                    { "local-user", "11" }
                });
                prx1.Op1(new Dictionary <string, string> {
                    { "local-user", "12" }
                });
                TestHelper.Assert(invocations == 1);
            }

            {
                // throwing from an interceptor stops the interceptor chain
                using var communicator = new Communicator(prx.Communicator.GetProperties());
                communicator.DefaultInvocationInterceptors = ImmutableList.Create <InvocationInterceptor>(
                    (target, request, next, cancel) =>
                {
                    request.WritableContext["interceptor-1"] = "interceptor-1";
                    return(next(target, request, cancel));
                },
                    (target, request, next, cancel) =>
                {
                    TestHelper.Assert(request.Context["interceptor-1"] == "interceptor-1");
                    throw new InvalidOperationException("stop interceptor chain");
                },
                    (target, request, next, cancel) =>
                {
                    TestHelper.Assert(false);
                    return(next(target, request, cancel));
                });
                communicator.ActivateAsync().GetAwaiter().GetResult();

                var prx1 = IMyObjectPrx.Parse(prx.ToString() !, communicator);
                try
                {
                    prx1.Op1();
                    TestHelper.Assert(false);
                }
                catch (InvalidOperationException)
                {
                }
            }
            output.WriteLine("ok");

            output.Write("testing binary context... ");
            output.Flush();

            if (ice2)
            {
                for (int size = 128; size < 4096; size *= 2)
                {
                    var token = new Token(1, "mytoken", Enumerable.Range(0, size).Select(i => (byte)2).ToArray());

                    {
                        using var request = OutgoingRequestFrame.WithArgs(prx,
                                                                          "opWithBinaryContext",
                                                                          idempotent: false,
                                                                          compress: false,
                                                                          format: default,
                                                                          context: null,
                                                                          token,
                                                                          Token.IceWriter);
                        request.BinaryContextOverride.Add(1, ostr => ostr.WriteStruct(token));
                        request.BinaryContextOverride.Add(3, ostr => ostr.WriteShort((short)size));
                        request.BinaryContextOverride.Add(
                            2,
                            ostr => ostr.WriteSequence(
                                Enumerable.Range(0, 10).Select(i => $"string-{i}").ToArray(),
                                (ostr, s) => ostr.WriteString(s)));

                        using IncomingResponseFrame response = prx.InvokeAsync(request).Result;
                    }

                    {
                        // repeat with compressed frame
                        using OutgoingRequestFrame request = OutgoingRequestFrame.WithArgs(prx,
                                                                                           "opWithBinaryContext",
                                                                                           idempotent: false,
                                                                                           compress: false,
                                                                                           format: default,
                                                                                           context: null,
                                                                                           token,
                                                                                           Token.IceWriter);
                        request.BinaryContextOverride.Add(1, ostr => ostr.WriteStruct(token));
                        request.BinaryContextOverride.Add(3, ostr => ostr.WriteShort((short)size));
                        request.BinaryContextOverride.Add(
                            2,
                            ostr => ostr.WriteSequence(
                                Enumerable.Range(0, 10).Select(i => $"string-{i}").ToArray(),
                                (ostr, s) => ostr.WriteString(s)));

                        TestHelper.Assert(request.CompressPayload() == CompressionResult.Success);
                        using IncomingResponseFrame response = prx.InvokeAsync(request).Result;
                    }

                    {
                        // repeat compressed the frame before writing the context
                        using OutgoingRequestFrame request = OutgoingRequestFrame.WithArgs(prx,
                                                                                           "opWithBinaryContext",
                                                                                           idempotent: false,
                                                                                           compress: false,
                                                                                           format: default,
                                                                                           context: null,
                                                                                           token,
                                                                                           Token.IceWriter);

                        TestHelper.Assert(request.CompressPayload() == CompressionResult.Success);

                        request.BinaryContextOverride.Add(1, ostr => ostr.WriteStruct(token));
                        request.BinaryContextOverride.Add(3, ostr => ostr.WriteShort((short)size));
                        request.BinaryContextOverride.Add(
                            2,
                            ostr => ostr.WriteSequence(
                                Enumerable.Range(0, 10).Select(i => $"string-{i}").ToArray(),
                                (ostr, s) => ostr.WriteString(s)));

                        using IncomingResponseFrame response = prx.InvokeAsync(request).Result;
                    }
                }
            }
            else
            {
                var token = new Token(1, "mytoken", Enumerable.Range(0, 256).Select(i => (byte)2).ToArray());
                using var request = OutgoingRequestFrame.WithArgs(prx,
                                                                  "opWithBinaryContext",
                                                                  idempotent: false,
                                                                  compress: false,
                                                                  format: default,
                                                                  context: null,
                                                                  token,
                                                                  Token.IceWriter);
                try
                {
                    request.BinaryContextOverride.Add(1, ostr => ostr.WriteStruct(token));
                    TestHelper.Assert(false);
                }
                catch (NotSupportedException)
                {
                }
                using IncomingResponseFrame response = prx.InvokeAsync(request).Result;
            }
            output.WriteLine("ok");

            output.Write("testing per proxy invocation interceptors... ");
            output.Flush();
            {
                var communicator = helper.Communicator !;

                SortedDictionary <string, string>?context = prx.Op2();
                TestHelper.Assert(context["context1"] == "plug-in");
                TestHelper.Assert(context["context2"] == "plug-in");
                TestHelper.Assert(!context.ContainsKey("context3"));
                prx = prx.Clone(invocationInterceptors: ImmutableList.Create <InvocationInterceptor>(
                                    (target, request, next, cancel) =>
                {
                    request.WritableContext["context2"] = "proxy";
                    request.WritableContext["context3"] = "proxy";
                    return(next(target, request, cancel));
                }).AddRange(communicator.DefaultInvocationInterceptors));
                context = prx.Op2();
                TestHelper.Assert(context["context1"] == "plug-in");
                TestHelper.Assert(context["context2"] == "plug-in");
                TestHelper.Assert(context["context3"] == "proxy");

                // Calling next twice doesn't change the result
                prx = prx.Clone(invocationInterceptors: ImmutableList.Create <InvocationInterceptor>(
                                    (target, request, next, cancel) =>
                {
                    request.WritableContext["context2"] = "proxy";
                    request.WritableContext["context3"] = "proxy";
                    _ = next(target, request, cancel);
                    return(next(target, request, cancel));
                }).AddRange(communicator.DefaultInvocationInterceptors));
                context = prx.Op2();
                TestHelper.Assert(context["context1"] == "plug-in");
                TestHelper.Assert(context["context2"] == "plug-in");
                TestHelper.Assert(context["context3"] == "proxy");

                // Cloning the proxy preserve its interceptors
                prx     = prx.Clone(invocationTimeout: TimeSpan.FromSeconds(10));
                context = prx.Op2();
                TestHelper.Assert(context["context1"] == "plug-in");
                TestHelper.Assert(context["context2"] == "plug-in");
                TestHelper.Assert(context["context3"] == "proxy");

                // The server increments the result with each call when using the invocation interceptor we
                // return a cached response, and we will see the same result with each call.
                IncomingResponseFrame?response = null;
                prx = prx.Clone(invocationInterceptors: ImmutableList.Create <InvocationInterceptor>(
                                    async(target, request, next, cancel) =>
                {
                    response ??= await next(target, request, cancel);
                    return(response);
                }).AddRange(communicator.DefaultInvocationInterceptors));
                TestHelper.Assert(prx.Op3() == 0);
                TestHelper.Assert(prx.Op3() == 0);

                // After clearing the invocation interceptors we should see the result increase with each call
                prx = prx.Clone(invocationInterceptors: communicator.DefaultInvocationInterceptors);
                TestHelper.Assert(prx.Op3() == 1);
                TestHelper.Assert(prx.Op3() == 2);
            }
            output.WriteLine("ok");
            return(prx);
        }