Ejemplo n.º 1
0
 public DivMockRpcConnection(bool enableReceivingCalls)
 {
     if (enableReceivingCalls)
     {
         // While running, create calculation tasks which the peer can receive
         Task.Run(async() => {
             ulong nextID = 0;
             while (isRunning && isReceivingMoreDivs)
             {
                 var div = Div.CreateNew(nextID++);
                 receiving.Enqueue(RpcMessage.Encode(div.ToMethod()));
                 await Task.Delay(50);
             }
         });
     }
 }
Ejemplo n.º 2
0
        public async Task Run_RetryUntilWorking()
        {
            var connection = new DivMockRpcConnection(enableReceivingCalls: false);
            var channel    = await RpcChannel.Create(new RpcPeerInfo(null, "localhost"),
                                                     connection, new DivMockRpcMethodExecutor(), backlog : null);

            _ = channel.Start();
            // Set remote execution time very high, so that the response can not be received
            // during the following asserts. Each call should fail because of timeout.
            connection.SetExecutionTimeMs(100_000);
            long startTime = TimeNowMs();
            var  callTask  = channel.Run(new RpcCall {
                Method        = Div.CreateNew(1000).ToMethod(),
                RetryStrategy = RpcRetryStrategy.Retry,
                TimeoutMs     = 100
            });
            await callTask;
            long  duration = TimeNowMs() - startTime;

            Assert.IsTrue(100 <= duration && duration < 200);
            Assert.AreEqual(RpcFailureType.Timeout, callTask.Result.Failure?.Type);
            // It should be repeated, but now we can not receive the result any more.
            // But we should observe the increasing number of sent attempts.
            int attempts = connection.SentDivs.Count;
            int newAttempts;

            for (int i = 0; i < 3; i++)
            {
                await Task.Delay(300);

                newAttempts = connection.SentDivs.Count;
                Assert.IsTrue(newAttempts > attempts && Math.Abs(newAttempts - attempts) <= 3,
                              $"Failed in step {i}, attempts = {attempts}, newAttempts = {newAttempts}");
                attempts = newAttempts;
            }
            // When we set the remote execution time down to 100, the call should be finished.
            attempts = connection.SentDivs.Count;
            connection.SetExecutionTimeMs(50);
            await Task.Delay(300);

            newAttempts = connection.SentDivs.Count;
            Assert.IsTrue(newAttempts == attempts + 1 || newAttempts == attempts + 2);
            channel.Stop();
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Sends, receives and processes lot of calls with a number division calculation task,
        /// using the <see cref="DivMockRpcConnection"/>.
        /// At the end, checks if each of the calls, in both directions, was correctly processed.
        /// </summary>
        /// <param name="useTimeouts">Iff true, all <see cref="Div"/>s are sent as retryable
        ///   calls and a timeout of 50 ms is set (the RPC peer is not fast enough
        ///   to process a calls without timeouts)</param>
        private async Task LoadTest(bool useTimeouts)
        {
            int callsCount     = 0;
            var connection     = new DivMockRpcConnection(enableReceivingCalls: true);
            var testDurationMs = 3000;
            // Start channel
            var channel = await RpcChannel.Create(new RpcPeerInfo(null, "localhost"),
                                                  connection, new DivMockRpcMethodExecutor(), backlog : null);

            _ = channel.Start();
            // For the time of the test, send calculations
            long testStartTime = TimeNowMs();

            _ = Task.Run(async() => {
                while (TimeNowMs() - testStartTime < testDurationMs)
                {
                    var div = Div.CreateNew((ulong)callsCount);
                    _       = channel.Run(new RpcCall {
                        Method        = div.ToMethod(),
                        RetryStrategy = useTimeouts ? RpcRetryStrategy.Retry : (RpcRetryStrategy?)null,
                        TimeoutMs     = 50
                    });
                    callsCount++;
                    if (callsCount % 5 == 0)
                    {
                        await Task.Delay(100);
                    }
                }
            });
            // When we test timeouts, let the first second respond very slowly
            if (useTimeouts)
            {
                connection.SetExecutionTimeMs(100);
                await Task.Delay(1000);

                testDurationMs -= 1000;
                connection.SetExecutionTimeMs(0);
            }
            // When the test time is over, tell the mock connection to stop receiving new div tasks
            await Task.Delay(testDurationMs);

            connection.StopReceivingDivs();
            // Wait a short moment to let ongoing computations complete
            await Task.Delay(Debugger.IsAttached? 2000 : 500);  // More time when debugging (much slower taks and/or logging)

            // Check results of sent and received calls
            var sentCallsWithTimeouts = connection.SentDivs.ToList();
            var sentCalls             = sentCallsWithTimeouts.Where((call, index) =>
                                                                    index == sentCallsWithTimeouts.FindLastIndex(it => it.methodID == call.methodID)).ToList(); // Filter out retried calls

            if (useTimeouts)
            {
                Assert.IsTrue(sentCallsWithTimeouts.Count > sentCalls.Count + 10);
            }
            else
            {
                Assert.AreEqual(sentCallsWithTimeouts.Count, sentCalls.Count);
            }
            Assert.AreEqual(callsCount, sentCalls.Count);
            for (int i = 0; i < sentCalls.Count; i++)
            {
                Assert.AreEqual(sentCalls[i].ComputeExpectedResult(), sentCalls[i].result);
            }
            var receivedCalls = connection.ReceivedDivs.ToList();

            Assert.IsTrue(receivedCalls.Count > testDurationMs / 100);
            for (int i = 0; i < receivedCalls.Count; i++)
            {
                Assert.AreEqual(receivedCalls[i].ComputeExpectedResult(), receivedCalls[i].result);
            }
        }