public async Task ComputedPerformanceTest() { if (TestRunnerInfo.IsBuildAgent()) { return; // Shouldn't run this test on build agents } var users = Services.GetRequiredService <IUserService>(); var plainUsers = Services.GetRequiredService <UserService>(); var useImdb = Options.UseInMemoryDatabase; var opCountPerCore = 2_000_000; var readersPerCore = 4; var readerCount = HardwareInfo.GetProcessorCountFactor(readersPerCore); var cachingIterationCount = opCountPerCore / readersPerCore; var nonCachingIterationCount = cachingIterationCount / (useImdb ? 1000 : 10_000); var withoutSerialization = (Action <User>)(u => { }); var withSerialization = (Action <User>)(u => JsonConvert.SerializeObject(u)); Out.WriteLine($"Database: {(useImdb ? "In-memory" : "Sqlite")}"); Out.WriteLine("With Stl.Fusion:"); await Test("Standard test", users, withoutSerialization, readerCount, cachingIterationCount); await Test("Standard test + serialization", users, withSerialization, readerCount, cachingIterationCount / 3); Out.WriteLine("Without Stl.Fusion:"); await Test("Standard test", plainUsers, withoutSerialization, readerCount, nonCachingIterationCount); await Test("Standard test + serialization", plainUsers, withSerialization, readerCount, nonCachingIterationCount); }
public async Task TestNoKeepAlive() { if (TestRunnerInfo.IsBuildAgent()) { // TODO: Fix intermittent failures on GitHub return; } var services = CreateProviderFor <Service>(); var service = services.GetRequiredService <Service>(); service.CallCount = 0; await service.Multiply(1, 1); service.CallCount.Should().Be(1); await service.Multiply(1, 1); service.CallCount.Should().Be(1); await GCCollect(); await service.Multiply(1, 1); service.CallCount.Should().Be(2); }
public async Task BasicTest() { if (TestRunnerInfo.IsBuildAgent()) { return; // No Redis on build agent for now } var sw = new Stopwatch(); sw.Start(); var pub1 = GetRedisDb().GetPub <string>("pub-1"); var pub2 = GetRedisDb().GetPub <string>("pub-2"); var sub = GetRedisDb().GetTaskSub <string>("pub-*"); await using var _ = sub.ConfigureAwait(false); await sub.WhenSubscribed.ConfigureAwait(false); Out.WriteLine($"{sw.ElapsedMilliseconds}: <- 1"); var messageTask = sub.NextMessage(); await pub1.Publish("1"); Out.WriteLine($"{sw.ElapsedMilliseconds}: -> {await messageTask}"); Out.WriteLine($"{sw.ElapsedMilliseconds}: <- 2"); messageTask = sub.NextMessage(); await pub2.Publish("2"); Out.WriteLine($"{sw.ElapsedMilliseconds}: -> {await messageTask}"); }
public async void TestKeepAlive() { if (TestRunnerInfo.IsBuildAgent()) { // TODO: Fix intermittent failures on GitHub return; } var services = CreateProviderFor <Service>(); var service = services.GetRequiredService <Service>(); service.CallCount = 0; await service.SumAsync(1, 1); service.CallCount.Should().Be(1); await service.SumAsync(1, 1); service.CallCount.Should().Be(1); await Task.Delay(250); await GCCollectAsync(); await service.SumAsync(1, 1); service.CallCount.Should().Be(1); await Task.Delay(1000); await GCCollectAsync(); await service.SumAsync(1, 1); service.CallCount.Should().Be(2); }
public async Task BasicTest() { if (TestRunnerInfo.IsBuildAgent()) { return; // No Redis on build agent for now } var hash = GetRedisDb().GetHash("hash"); await hash.Clear(); (await hash.GetAll()).Length.Should().Be(0); (await hash.Increment("a")).Should().Be(1); (await hash.Increment("a")).Should().Be(2); (await hash.Set("a", "10")).Should().Be(false); (await hash.Increment("a")).Should().Be(11); (await hash.GetAll()).Length.Should().Be(1); (await hash.Increment("b")).Should().Be(1); (await hash.Increment("a")).Should().Be(12); (await hash.GetAll()).Length.Should().Be(2); (await hash.Remove("a")).Should().BeTrue(); (await hash.GetAll()).Length.Should().Be(1); await hash.Clear(); (await hash.GetAll()).Length.Should().Be(0); }
public async Task ComputedPerformanceTest() { if (TestRunnerInfo.IsBuildAgent()) { return; // Shouldn't run this test on build agents } var users = Services.GetRequiredService <IUserService>(); var plainUsers = Services.GetRequiredService <UserService>(); var opCountPerCore = 4_000_000; var readersPerCore = 5; var readerCount = HardwareInfo.GetProcessorCountFactor(readersPerCore); var cachingIterationCount = opCountPerCore / readersPerCore; var nonCachingIterationCount = cachingIterationCount / 2000; var withoutSerialization = (Action <User>)(u => { }); var withSerialization = (Action <User>)(u => JsonSerializer.Serialize(u)); // STJ serializer Out.WriteLine($".NET: {RuntimeInfo.DotNetCore.VersionString}"); Out.WriteLine($"Database: {Options.DbType}"); Out.WriteLine("With Stl.Fusion:"); await Test("Standard test", users, withoutSerialization, readerCount, cachingIterationCount); await Test("Standard test + serialization", users, withSerialization, readerCount, cachingIterationCount / 3); Out.WriteLine("Without Stl.Fusion:"); await Test("Standard test", plainUsers, withoutSerialization, readerCount, nonCachingIterationCount); await Test("Standard test + serialization", plainUsers, withSerialization, readerCount, nonCachingIterationCount); }
public async Task BasicTest() { var epsilon = TimeSpan.FromSeconds(TestRunnerInfo.IsBuildAgent() ? 5 : 1); var epsilon10 = epsilon.Multiply(10); using var clock = new TestClock().SpeedupBy(10).OffsetBy(1000); var realStart = SystemClock.Now; var clockStart = clock.Now; ShouldEqual(realStart, DateTime.Now.ToMoment(), epsilon); ShouldEqual(realStart, clock.ToRealTime(clockStart), epsilon); ShouldEqual(clockStart, clock.ToLocalTime(realStart), epsilon10); ShouldEqual(clockStart, realStart + TimeSpan.FromSeconds(1), epsilon); await clock.Delay(TimeSpan.FromSeconds(5)); ShouldEqual(realStart + TimeSpan.FromSeconds(0.5), SystemClock.Now, epsilon); ShouldEqual(clockStart + TimeSpan.FromSeconds(5), clock.Now, epsilon10); Out.WriteLine(clock.Now.ToString()); clock.OffsetBy(1000); ShouldEqual(clockStart + TimeSpan.FromSeconds(6), clock.Now, epsilon10); clock.SpeedupBy(0.1); await clock.Delay(TimeSpan.FromSeconds(0.5)); ShouldEqual(realStart + TimeSpan.FromSeconds(1), SystemClock.Now, epsilon); ShouldEqual(clockStart + TimeSpan.FromSeconds(6.5), clock.Now, epsilon10); }
public async void BasicTest() { if (TestRunnerInfo.IsBuildAgent()) { // TODO: Fix intermittent failures on GitHub return; } var services = CreateServiceProviderFor <Service>(); var swapService = services.GetRequiredService <SwapService>(); var service = services.GetRequiredService <Service>(); var clock = Timeouts.Clock; service.CallCount = 0; var a = "a"; var v = await service.SameValueAsync(a); service.CallCount.Should().Be(1); swapService.LoadCallCount.Should().Be(0); swapService.StoreCallCount.Should().Be(0); swapService.RenewCallCount.Should().Be(0); v.Should().BeSameAs(a); await DelayAsync(1.4); swapService.LoadCallCount.Should().Be(0); swapService.RenewCallCount.Should().Be(1); swapService.StoreCallCount.Should().Be(1); v = await service.SameValueAsync(a); service.CallCount.Should().Be(1); swapService.LoadCallCount.Should().Be(1); swapService.RenewCallCount.Should().Be(1); swapService.StoreCallCount.Should().Be(1); v.Should().Be(a); v.Should().NotBeSameAs(a); // We accessed the value, so we need to wait for // SwapTime + KeepAliveTime to make sure it's // available for GC await DelayAsync(1.9); swapService.LoadCallCount.Should().Be(1); swapService.RenewCallCount.Should().Be(2); swapService.StoreCallCount.Should().Be(1); while (service.CallCount == 1) { GCCollect(); v = await service.SameValueAsync(a); } service.CallCount.Should().Be(2); swapService.LoadCallCount.Should().Be(1); swapService.RenewCallCount.Should().Be(2); swapService.StoreCallCount.Should().Be(1); v.Should().Be(a); v.Should().BeSameAs(a); }
public async Task BasicTest() { if (TestRunnerInfo.IsBuildAgent()) { return; // No Redis on build agent for now } var db = GetRedisDb(); var started = TaskSource.New <Unit>(true); var streamer = db.GetStreamer <int>("s"); await streamer.Remove(); var streamerCopy = db.GetStreamer <int>("s"); var writeTask = streamer.Write( Delays(new[] { 0.1, 0.2, 0.3, 0.1 }), _ => started.SetResult(default));
public async Task Test2() { var epsilon = TimeSpan.FromSeconds(0.5); if (TestRunnerInfo.IsBuildAgent()) { epsilon *= 2; } await using var serving = await WebSocketHost.ServeAsync(); var service = Services.GetRequiredService <IClientTimeService>(); for (int i = 0; i < 20; i++) { var time = await service.GetTimeAsync(); (DateTime.Now - time).Should().BeLessThan(epsilon); await Task.Delay(TimeSpan.FromSeconds(0.1)); } }
public async Task BasicTest() { if (TestRunnerInfo.IsBuildAgent()) { return; // No Redis on build agent for now } await using var queue = await CreateQueue <string>("q", true).ConfigureAwait(false); var sw = new Stopwatch(); sw.Start(); Out.WriteLine($"{sw.ElapsedMilliseconds}: <- 1"); await queue.Enqueue("1"); Out.WriteLine($"{sw.ElapsedMilliseconds}: -> {await queue.Dequeue()}"); Out.WriteLine($"{sw.ElapsedMilliseconds}: <- 2"); await queue.Enqueue("2"); Out.WriteLine($"{sw.ElapsedMilliseconds}: -> {await queue.Dequeue()}"); }
public void BasicTest() { var holder = new RefHolder(); var count = TestRunnerInfo.IsBuildAgent() ? 100 : 1000; var objects = Enumerable.Range(0, count).Select(i => i.ToString()).ToArray(); var holds = new HashSet <IDisposable>(); foreach (var o in objects) { holds.Add(holder.Hold(o)); } holder.IsEmpty.Should().BeFalse(); // HashSet randomizes the order of disposal foreach (var hold in holds) { hold.Dispose(); } holder.IsEmpty.Should().BeTrue(); }
public async Task BasicTest() { if (TestRunnerInfo.IsBuildAgent()) { return; // No Redis on build agent for now } var set = GetRedisDb().GetSequenceSet("seq", 250); await set.Clear(); (await set.Next("a")).Should().Be(1); (await set.Next("a")).Should().Be(2); (await set.Next("a", 500)).Should().Be(501); (await set.Next("a", 300)).Should().Be(502); (await set.Next("a", 200)).Should().Be(201); (await set.Next("a")).Should().Be(202); (await set.Next("a", 1000_000_000).WithTimeout(TimeSpan.FromMilliseconds(100))) .Should().Be(Option.Some(1000_000_001L)); // Auto-reset test await set.Reset("a", 10); (await set.Next("a", 5)).Should().Be(11); }
public async Task ComputedPerformanceTest() { if (TestRunnerInfo.IsBuildAgent()) { return; // Shouldn't run this test on build agents } var users = Services.GetRequiredService <IUserService>(); var useImdb = Options.UseInMemoryDatabase; var opCountPerCore = 2_000_000; var readersPerCore = 4; var readerCount = HardwareInfo.ProcessorCount * readersPerCore; var cachingIterationCount = opCountPerCore / readersPerCore; var nonCachingIterationCount = cachingIterationCount / (useImdb ? 1000 : 10_000); var cachingProviderPool = new ConcurrentPool <IUserService>(() => users); var nonCachingProviderPool = new ConcurrentPool <IUserService>(() => { var scope = Services.CreateScope(); return(scope.ServiceProvider.GetRequiredService <UserService>()); // No scope disposal, but it's fine for the test, I guess }); var withoutSerialization = (Action <User>)(u => { }); var withSerialization = (Action <User>)(u => JsonConvert.SerializeObject(u)); Out.WriteLine($"Database: {(useImdb ? "In-memory" : "Sqlite")}"); Out.WriteLine("With Stl.Fusion:"); await Test("Standard test", cachingProviderPool, withoutSerialization, readerCount, cachingIterationCount); await Test("Standard test + serialization", cachingProviderPool, withSerialization, readerCount, cachingIterationCount / 3); Out.WriteLine("Without Stl.Fusion:"); await Test("Standard test", nonCachingProviderPool, withoutSerialization, readerCount, nonCachingIterationCount); await Test("Standard test + serialization", nonCachingProviderPool, withSerialization, readerCount, nonCachingIterationCount); }
public async Task DropReconnectTest() { if (TestRunnerInfo.IsBuildAgent()) { // TODO: Fix intermittent failures on GitHub return; } var serving = await WebSocketHost.ServeAsync(); var tp = Services.GetRequiredService <ITimeService>(); Debug.WriteLine("0"); var pub = await Publisher.PublishAsync(_ => tp.GetTimeAsync()); var rep = Replicator.GetOrAdd <DateTime>(pub.Ref); Debug.WriteLine("1"); await rep.RequestUpdateAsync().AsAsyncFunc() .Should().CompleteWithinAsync(TimeSpan.FromMinutes(1)); Debug.WriteLine("2"); var state = Replicator.GetPublisherConnectionState(pub.Publisher.Id); state.Computed.IsConsistent().Should().BeTrue(); Debug.WriteLine("3"); await state.Computed.UpdateAsync(false); Debug.WriteLine("4"); state.Should().Be(Replicator.GetPublisherConnectionState(pub.Publisher.Id)); state.Value.Should().BeTrue(); Debug.WriteLine("WebServer: stopping."); await serving.DisposeAsync(); Debug.WriteLine("WebServer: stopped."); // First try -- should fail w/ WebSocketException or ChannelClosedException Debug.WriteLine("5"); await rep.RequestUpdateAsync().AsAsyncFunc() .Should().ThrowAsync <Exception>(); Debug.WriteLine("6"); state.Should().Be(Replicator.GetPublisherConnectionState(pub.Publisher.Id)); await state.Computed.UpdateAsync(false); Debug.WriteLine("7"); state.Should().Be(Replicator.GetPublisherConnectionState(pub.Publisher.Id)); state.Error.Should().BeAssignableTo <Exception>(); // Second try -- should fail w/ WebSocketException Debug.WriteLine("8"); await rep.Computed.UpdateAsync(false).AsAsyncFunc() .Should().ThrowAsync <WebSocketException>(); Debug.WriteLine("9"); rep.UpdateError.Should().BeOfType <WebSocketException>(); await state.Computed.UpdateAsync(false); Debug.WriteLine("10"); state.Error.Should().BeOfType <WebSocketException>(); Debug.WriteLine("WebServer: starting."); serving = await WebSocketHost.ServeAsync(); await Task.Delay(1000); Debug.WriteLine("WebServer: started."); Debug.WriteLine("11"); await rep.RequestUpdateAsync().AsAsyncFunc() .Should().CompleteWithinAsync(TimeSpan.FromMinutes(1)); Debug.WriteLine("12"); await state.Computed.UpdateAsync(false); Debug.WriteLine("13"); state.Value.Should().BeTrue(); Debug.WriteLine("100"); await serving.DisposeAsync(); Debug.WriteLine("101"); }
public async Task DropReconnectTest() { if (TestRunnerInfo.IsBuildAgent()) { // TODO: Fix intermittent failures on GitHub return; } var serving = await WebHost.Serve(false); var replicator = ClientServices.GetRequiredService <IReplicator>(); var kvsClient = ClientServices.GetRequiredService <IKeyValueServiceClient <string> >(); Debug.WriteLine("0"); var kvs = WebServices.GetRequiredService <IKeyValueService <string> >(); await kvs.Set("a", "b"); var c = (ReplicaMethodComputed <string>) await Computed.Capture(_ => kvsClient.Get("a")); c.Value.Should().Be("b"); c.IsConsistent().Should().BeTrue(); Debug.WriteLine("1"); await c.Replica !.RequestUpdate().AsAsyncFunc() .Should().CompleteWithinAsync(TimeSpan.FromSeconds(5)); c.IsConsistent().Should().BeTrue(); Debug.WriteLine("2"); var cs = replicator.GetPublisherConnectionState(c.Replica.PublicationRef.PublisherId); cs.Value.Should().BeTrue(); cs.Computed.IsConsistent().Should().BeTrue(); await cs.Recompute(); Debug.WriteLine("3"); cs.Value.Should().BeTrue(); cs.Computed.IsConsistent().Should().BeTrue(); var cs1 = replicator.GetPublisherConnectionState(c.Replica.PublicationRef.PublisherId); cs1.Should().BeSameAs(cs); Debug.WriteLine("WebServer: stopping."); await serving.DisposeAsync(); Debug.WriteLine("WebServer: stopped."); // First try -- should fail w/ WebSocketException or ChannelClosedException c.IsConsistent().Should().BeTrue(); c.Value.Should().Be("b"); Debug.WriteLine("4"); await cs.Update(); cs.Error.Should().BeAssignableTo <Exception>(); cs.Computed.IsConsistent().Should().BeTrue(); var updateTask = c.Replica.RequestUpdate(); updateTask.IsCompleted.Should().BeFalse(); Debug.WriteLine("5"); await kvs.Set("a", "c"); await Delay(0.1); c.IsConsistent().Should().BeTrue(); c.Value.Should().Be("b"); Debug.WriteLine("6"); Debug.WriteLine("WebServer: starting."); serving = await WebHost.Serve(); await Delay(1); Debug.WriteLine("WebServer: started."); await TestExt.WhenMet( () => cs.Error.Should().BeNull(), TimeSpan.FromSeconds(30)); Debug.WriteLine("7"); await Delay(1); updateTask.IsCompleted.Should().BeTrue(); c = (ReplicaMethodComputed <string>) await c.Update(); c.IsConsistent().Should().BeTrue(); c.Value.Should().Be("c"); await serving.DisposeAsync(); }
public async Task DropReconnectTest() { if (TestRunnerInfo.IsBuildAgent()) { // TODO: Fix intermittent failures on GitHub return; } var serving = await WebHost.Serve(); var publisher = WebServices.GetRequiredService <IPublisher>(); var replicator = ClientServices.GetRequiredService <IReplicator>(); var tp = Services.GetRequiredService <ITimeService>(); Debug.WriteLine("0"); var pub = await publisher.Publish(_ => tp.GetTime()); var rep = replicator.GetOrAdd <DateTime>(pub.Ref); Debug.WriteLine("1"); await rep.RequestUpdate().AsAsyncFunc() .Should().CompleteWithinAsync(TimeSpan.FromMinutes(1)); Debug.WriteLine("2"); var state = replicator.GetPublisherConnectionState(pub.Publisher.Id); state.Computed.IsConsistent().Should().BeTrue(); Debug.WriteLine("3"); await state.Computed.Update(false); Debug.WriteLine("4"); state.Should().Be(replicator.GetPublisherConnectionState(pub.Publisher.Id)); state.Value.Should().BeTrue(); Debug.WriteLine("WebServer: stopping."); await serving.DisposeAsync(); Debug.WriteLine("WebServer: stopped."); // First try -- should fail w/ WebSocketException or ChannelClosedException Debug.WriteLine("5"); await rep.RequestUpdate().AsAsyncFunc() .Should().ThrowAsync <Exception>(); Debug.WriteLine("6"); state.Should().Be(replicator.GetPublisherConnectionState(pub.Publisher.Id)); await state.Computed.Update(false); Debug.WriteLine("7"); state.Should().Be(replicator.GetPublisherConnectionState(pub.Publisher.Id)); state.Error.Should().BeAssignableTo <Exception>(); // Second try -- should fail w/ WebSocketException Debug.WriteLine("8"); await rep.Computed.Update(false).AsAsyncFunc() .Should().ThrowAsync <WebSocketException>(); Debug.WriteLine("9"); rep.UpdateError.Should().BeOfType <WebSocketException>(); await state.Computed.Update(false); Debug.WriteLine("10"); state.Error.Should().BeOfType <WebSocketException>(); // The remaining part of this test shouldn't work: // since the underlying web host is actually re-created on // every ServeAsync call, its endpoints change, // and moreover, IPublisher, etc. dies there, // so reconnect won't happen in this case. // // TODO: Add similar test relying on Replica Services. /* * Debug.WriteLine("WebServer: starting."); * serving = await WebHost.ServeAsync(); * await Task.Delay(1000); * Debug.WriteLine("WebServer: started."); * * Debug.WriteLine("11"); * await rep.RequestUpdateAsync().AsAsyncFunc() * .Should().CompleteWithinAsync(TimeSpan.FromMinutes(1)); * Debug.WriteLine("12"); * await state.Computed.UpdateAsync(false); * Debug.WriteLine("13"); * state.Value.Should().BeTrue(); * * Debug.WriteLine("100"); * await serving.DisposeAsync(); * Debug.WriteLine("101"); */ }
public async Task DistributionTest() { if (TestRunnerInfo.IsBuildAgent()) { return; // No Redis on build agent for now } var queueName = "iq"; await using var queue = await CreateQueue <int>(queueName, true).ConfigureAwait(false); var itemCount = 10_000; var writerCount = 4; var readerCount = 8; async Task Writer(int writerIndex) { await using var q = await CreateQueue <int>(queueName).ConfigureAwait(false); var rnd = new Random(); for (var i = writerIndex; i < itemCount; i += writerCount) { await q.Enqueue(i).ConfigureAwait(false); var delay = rnd.Next(10); if (delay < 3) { await Task.Delay(delay); } } } var writeTasks = Enumerable.Range(0, writerCount) .Select(i => Task.Run(() => Writer(i))) .ToArray(); var writeTask = Task.WhenAll(writeTasks); async Task <List <int> > Reader() { await using var q = await CreateQueue <int>(queueName).ConfigureAwait(false); var rnd = new Random(); var list = new List <int>(); while (true) { var valueOpt = await q.Dequeue() .WithTimeout(TimeSpan.FromSeconds(1)) .ConfigureAwait(false); if (!valueOpt.IsSome(out var value)) { writeTask.IsCompleted.Should().BeTrue(); break; } list.Add(value); var delay = rnd.Next(10); if (delay < 2) { await Task.Delay(delay); } } return(list); } var sw = new Stopwatch(); sw.Start(); var readTasks = Enumerable.Range(0, readerCount) .Select(_ => Task.Run(Reader)) .ToArray(); var lists = await Task.WhenAll(readTasks).ConfigureAwait(false); Out.WriteLine($"{sw.Elapsed}: completed"); var items = lists.SelectMany(i => i).ToImmutableHashSet(); items.Count.Should().Be(itemCount); }