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(); }
/// <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); } }