public static void SendTimeout_Zero_Throws_TimeoutException_Immediately()
    {
        TimeSpan         serviceOperationTimeout = TimeSpan.FromMilliseconds(5000);
        BasicHttpBinding binding = new BasicHttpBinding();

        binding.SendTimeout = TimeSpan.FromMilliseconds(0);
        ChannelFactory <IWcfService> factory = new ChannelFactory <IWcfService>(binding, new EndpointAddress(Endpoints.HttpBaseAddress_Basic));

        Stopwatch watch = new Stopwatch();

        try
        {
            var exception = Assert.Throws <TimeoutException>(() =>
            {
                IWcfService proxy = factory.CreateChannel();
                watch.Start();
                proxy.EchoWithTimeout("Hello", serviceOperationTimeout);
            });
        }
        finally
        {
            watch.Stop();
        }

        // want to assert that this completed in < 2 s as an upper bound since the SendTimeout is 0 sec
        // (usual case is around 1 - 3 ms)
        Assert.InRange <long>(watch.ElapsedMilliseconds, 0, 2000);
    }
Example #2
0
    public static void TimeoutTest_SendTimeout0Seconds()
    {
        bool exceptionThrown = false;

        try
        {
            BasicHttpBinding binding = new BasicHttpBinding();
            binding.SendTimeout = TimeSpan.FromMilliseconds(0);
            ChannelFactory <IWcfService> factory = new ChannelFactory <IWcfService>(binding, new EndpointAddress(Endpoints.HttpBaseAddress_Basic));
            IWcfService proxy = factory.CreateChannel();
            proxy.EchoWithTimeout("Hello");
        }
        catch (TimeoutException)
        {
            exceptionThrown = true;
        }
        catch (Exception ex)
        {
            Assert.True(false, String.Format("Unexpected exception caught: {0}", ex.ToString()));
        }

        if (!exceptionThrown)
        {
            Assert.True(false, "Expected TimeoutException was not thrown nor was any other exception thrown.");
        }
    }
    public static void NetTcp_TransportSecurity_Streamed_TimeOut_Long_Running_Operation()
    {
        string        testString = "Hello";
        NetTcpBinding binding    = null;
        TimeSpan      serviceOperationTimeout = TimeSpan.FromMilliseconds(10000);
        ChannelFactory <IWcfService> factory  = null;
        IWcfService serviceProxy = null;

        try
        {
            // *** SETUP *** \\
            binding = new NetTcpBinding(SecurityMode.Transport);
            binding.TransferMode = TransferMode.Streamed;
            binding.SendTimeout  = TimeSpan.FromMilliseconds(5000);
            factory      = new ChannelFactory <IWcfService>(binding, new EndpointAddress(Endpoints.Tcp_Transport_Security_Streamed_Address));
            serviceProxy = factory.CreateChannel();
            ((ICommunicationObject)serviceProxy).Open();
            Stopwatch watch = new Stopwatch();
            watch.Start();

            // *** EXECUTE *** \\
            try
            {
                Assert.Throws <TimeoutException>(() =>
                {
                    string returnString = serviceProxy.EchoWithTimeout(testString, serviceOperationTimeout);
                });
            }
            finally
            {
                watch.Stop();

                // *** CLEANUP *** \\
                ((ICommunicationObject)serviceProxy).Close();
                factory.Close();
            }

            // *** VALIDATE *** \\
            // want to assert that this completed in > 5 s as an upper bound since the SendTimeout is 5 sec
            // (usual case is around 5001-5005 ms)
            Assert.True(watch.ElapsedMilliseconds >= 4985 && watch.ElapsedMilliseconds < 6000,
                        String.Format("Expected timeout was {0}ms but actual was {1}ms",
                                      serviceOperationTimeout.TotalMilliseconds,
                                      watch.ElapsedMilliseconds));
        }
        finally
        {
            // *** ENSURE CLEANUP *** \\
            ScenarioTestHelpers.CloseCommunicationObjects((ICommunicationObject)serviceProxy, factory);
        }
    }
    public static void SendTimeout_For_Long_Running_Operation_Throws_TimeoutException()
    {
        TimeSpan                     serviceOperationTimeout = TimeSpan.FromMilliseconds(10000);
        BasicHttpBinding             binding         = null;
        EndpointAddress              endpointAddress = null;
        ChannelFactory <IWcfService> factory         = null;
        IWcfService                  serviceProxy    = null;
        Stopwatch                    watch           = null;
        int lowRange  = 4985;
        int highRange = 6000;

        // *** VALIDATE *** \\
        TimeoutException exception = Assert.Throws <TimeoutException>(() =>
        {
            // *** SETUP *** \\
            binding             = new BasicHttpBinding();
            binding.SendTimeout = TimeSpan.FromMilliseconds(5000);
            endpointAddress     = new EndpointAddress(Endpoints.HttpBaseAddress_Basic_Text);
            factory             = new ChannelFactory <IWcfService>(binding, endpointAddress);
            serviceProxy        = factory.CreateChannel();
            watch = new Stopwatch();

            // *** EXECUTE *** \\
            try
            {
                watch = new Stopwatch();
                watch.Start();
                serviceProxy.EchoWithTimeout("Hello", serviceOperationTimeout);
            }
            finally
            {
                // *** ENSURE CLEANUP *** \\
                watch.Stop();
                ScenarioTestHelpers.CloseCommunicationObjects((ICommunicationObject)serviceProxy, factory);
            }
        });

        // *** ADDITIONAL VALIDATION *** \\
        // want to assert that this completed in > 5 s as an upper bound since the SendTimeout is 5 sec
        // (usual case is around 5001-5005 ms)
        Assert.True((watch.ElapsedMilliseconds >= lowRange && watch.ElapsedMilliseconds <= highRange),
                    String.Format("Expected elapsed time to be >= to {0} and <= to {1}\nActual elapsed time was: {2}", lowRange, highRange, watch.ElapsedMilliseconds));
    }
Example #5
0
    public static void Abort_During_Implicit_Open_Closes_Sync_Waiters()
    {
        // This test is a regression test of an issue with CallOnceManager.
        // When a single proxy is used to make several service calls without
        // explicitly opening it, the CallOnceManager queues up all the requests
        // that happen while it is opening the channel (or handling previously
        // queued service calls.  If the channel was closed or faulted during
        // the handling of any queued requests, it caused a pathological worst
        // case where every queued request waited for its complete SendTimeout
        // before failing.
        //
        // This test operates by making multiple concurrent synchronous service
        // calls, but stalls the Opening event to allow them to be queued before
        // any of them are allowed to proceed.  It then aborts the channel when
        // the first service operation is allowed to proceed.  This causes the
        // CallOnce manager to deal with all its queued operations and cause
        // them to complete other than by timing out.

        BasicHttpBinding             binding = null;
        ChannelFactory <IWcfService> factory = null;
        IWcfService serviceProxy             = null;
        int         timeoutMs        = 20000;
        long        operationsQueued = 0;
        int         operationCount   = 5;

        Task <string>[] tasks               = new Task <string> [operationCount];
        Exception[]     exceptions          = new Exception[operationCount];
        string[]        results             = new string[operationCount];
        bool            isClosed            = false;
        DateTime        endOfOpeningStall   = DateTime.Now;
        int             serverDelayMs       = 100;
        TimeSpan        serverDelayTimeSpan = TimeSpan.FromMilliseconds(serverDelayMs);
        string          testMessage         = "testMessage";

        try
        {
            // *** SETUP *** \\
            binding = new BasicHttpBinding(BasicHttpSecurityMode.None);
            binding.TransferMode = TransferMode.Streamed;
            // SendTimeout is the timeout used for implicit opens
            binding.SendTimeout = TimeSpan.FromMilliseconds(timeoutMs);
            factory             = new ChannelFactory <IWcfService>(binding, new EndpointAddress(Endpoints.HttpBaseAddress_Basic));
            serviceProxy        = factory.CreateChannel();

            // Force the implicit open to stall until we have multiple concurrent calls pending.
            // This forces the CallOnceManager to have a queue of waiters it will need to notify.
            ((ICommunicationObject)serviceProxy).Opening += (s, e) =>
            {
                // Wait until we see sync calls have been queued
                DateTime startOfOpeningStall = DateTime.Now;
                while (true)
                {
                    endOfOpeningStall = DateTime.Now;

                    // Don't wait forever -- if we stall longer than the SendTimeout, it means something
                    // is wrong other than what we are testing, so just fail early.
                    if ((endOfOpeningStall - startOfOpeningStall).TotalMilliseconds > timeoutMs)
                    {
                        Assert.True(false, "The Opening event timed out waiting for operations to queue, which was not expected for this test.");
                    }

                    // As soon as we have all our Tasks at least running, wait a little
                    // longer to allow them finish queuing up their waiters, then stop stalling the Opening
                    if (Interlocked.Read(ref operationsQueued) >= operationCount)
                    {
                        Task.Delay(500).Wait();
                        endOfOpeningStall = DateTime.Now;
                        return;
                    }

                    Task.Delay(100).Wait();
                }
            };

            // Each task will make a synchronous service call, which will cause all but the
            // first to be queued for the implicit open.  The first call to complete then closes
            // the channel so that it is forced to deal with queued waiters.
            Func <string> callFunc = () =>
            {
                // We increment the # ops queued before making the actual sync call, which is
                // technically a short race condition in the test.  But reversing the order would
                // timeout the implicit open and fault the channel.
                Interlocked.Increment(ref operationsQueued);

                // The call of the operation is what creates the entry in the CallOnceManager queue.
                // So as each Task below starts, it increments the count and adds a waiter to the
                // queue.  We ask for a small delay on the server side just to introduce a small
                // stall after the sync request has been made before it can complete.  Otherwise
                // fast machines can finish all the requests before the first one finishes the Close().
                string result = serviceProxy.EchoWithTimeout("test", serverDelayTimeSpan);
                lock (tasks)
                {
                    if (!isClosed)
                    {
                        try
                        {
                            isClosed = true;
                            ((ICommunicationObject)serviceProxy).Abort();
                        }
                        catch { }
                    }
                }
                return(result);
            };

            // *** EXECUTE *** \\

            DateTime startTime = DateTime.Now;
            for (int i = 0; i < operationCount; ++i)
            {
                tasks[i] = Task.Run(callFunc);
            }

            for (int i = 0; i < operationCount; ++i)
            {
                try
                {
                    results[i] = tasks[i].GetAwaiter().GetResult();
                }
                catch (Exception ex)
                {
                    exceptions[i] = ex;
                }
            }

            // *** VALIDATE *** \\
            double elapsedMs = (DateTime.Now - endOfOpeningStall).TotalMilliseconds;

            // Before validating that the issue was fixed, first validate that we received the exceptions or the
            // results we expected. This is to verify the fix did not introduce a behavioral change other than the
            // elimination of the long unnecessary timeouts after the channel was closed.
            int nFailures = 0;
            for (int i = 0; i < operationCount; ++i)
            {
                if (exceptions[i] == null)
                {
                    Assert.True((String.Equals("test", results[i])),
                                String.Format("Expected operation #{0} to return '{1}' but actual was '{2}'",
                                              i, testMessage, results[i]));
                }
                else
                {
                    ++nFailures;

                    TimeoutException toe = exceptions[i] as TimeoutException;
                    Assert.True(toe == null, String.Format("Task [{0}] should not have failed with TimeoutException", i));
                }
            }

            Assert.True(nFailures > 0,
                        String.Format("Expected at least one operation to throw an exception, but none did. Elapsed time = {0} ms.",
                                      elapsedMs));

            Assert.True(nFailures < operationCount,
                        String.Format("Expected at least one operation to succeed but none did. Elapsed time = {0} ms.",
                                      elapsedMs));

            // The original issue was that sync waiters in the CallOnceManager were not notified when
            // the channel became unusable and therefore continued to time out for the full amount.
            // Additionally, because they were executed sequentially, it was also possible for each one
            // to time out for the full amount.  Given that we closed the channel, we expect all the queued
            // waiters to have been immediately waked up and detected failure.
            int expectedElapsedMs = (operationCount * serverDelayMs) + timeoutMs / 2;
            Assert.True(elapsedMs < expectedElapsedMs,
                        String.Format("The {0} operations took {1} ms to complete which exceeds the expected {2} ms",
                                      operationCount, elapsedMs, expectedElapsedMs));

            // *** CLEANUP *** \\
            ((ICommunicationObject)serviceProxy).Close();
            factory.Close();
        }
        finally
        {
            // *** ENSURE CLEANUP *** \\
            ScenarioTestHelpers.CloseCommunicationObjects((ICommunicationObject)serviceProxy, factory);
        }
    }
Example #6
0
    public static void NetTcp_TransportSecurity_Streamed_TimeOut_Long_Running_Operation()
    {
#if FULLXUNIT_NOTSUPPORTED
        bool root_Certificate_Installed       = Root_Certificate_Installed();
        bool client_Certificate_Installed     = Client_Certificate_Installed();
        bool windows_Authentication_Available = Windows_Authentication_Available();
        bool ambient_Credentials_Available    = Ambient_Credentials_Available();

        if (!root_Certificate_Installed ||
            !client_Certificate_Installed ||
            !windows_Authentication_Available ||
            !ambient_Credentials_Available)
        {
            Console.WriteLine("---- Test SKIPPED --------------");
            Console.WriteLine("Attempting to run the test in ToF, a ConditionalFact evaluated as FALSE.");
            Console.WriteLine("Root_Certificate_Installed evaluated as {0}", root_Certificate_Installed);
            Console.WriteLine("Client_Certificate_Installed evaluated as {0}", client_Certificate_Installed);
            Console.WriteLine("Windows_Authentication_Available evaluated as {0}", windows_Authentication_Available);
            Console.WriteLine("Ambient_Credentials_Available evaluated as {0}", ambient_Credentials_Available);
            return;
        }
#endif
        string        testString = "Hello";
        NetTcpBinding binding    = null;
        TimeSpan      serviceOperationTimeout = TimeSpan.FromMilliseconds(10000);
        ChannelFactory <IWcfService> factory  = null;
        IWcfService serviceProxy = null;

        try
        {
            // *** SETUP *** \\
            binding = new NetTcpBinding(SecurityMode.Transport);
            binding.TransferMode = TransferMode.Streamed;
            binding.SendTimeout  = TimeSpan.FromMilliseconds(5000);
            factory      = new ChannelFactory <IWcfService>(binding, new EndpointAddress(Endpoints.Tcp_Transport_Security_Streamed_Address));
            serviceProxy = factory.CreateChannel();
            Stopwatch watch = new Stopwatch();
            watch.Start();

            // *** EXECUTE *** \\
            try
            {
                Assert.Throws <TimeoutException>(() =>
                {
                    string returnString = serviceProxy.EchoWithTimeout(testString, serviceOperationTimeout);
                });
            }
            finally
            {
                watch.Stop();

                // *** CLEANUP *** \\
                ((ICommunicationObject)serviceProxy).Close();
                factory.Close();
            }

            // *** VALIDATE *** \\
            // want to assert that this completed in > 5 s as an upper bound since the SendTimeout is 5 sec
            // (usual case is around 5001-5005 ms)
            Assert.True(watch.ElapsedMilliseconds >= 4985 && watch.ElapsedMilliseconds < 6000,
                        String.Format("Expected timeout was {0}ms but actual was {1}ms",
                                      serviceOperationTimeout.TotalMilliseconds,
                                      watch.ElapsedMilliseconds));
        }
        finally
        {
            // *** ENSURE CLEANUP *** \\
            ScenarioTestHelpers.CloseCommunicationObjects((ICommunicationObject)serviceProxy, factory);
        }
    }