// ========================================================================== // Squidex Headless CMS // ========================================================================== // Copyright (c) Squidex UG (haftungsbeschraenkt) // All rights reserved. Licensed under the MIT license. // ========================================================================== using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; namespace TestSuite.LoadTests { public static class Run { public static async Task Parallel(int numUsers, int numIterationsPerUser, Func action, int expectedAvg = 100, ITestOutputHelper testOutput = null) { await action(); var elapsedMs = new ConcurrentBag(); var errors = 0; async Task RunAsync() { for (var i = 0; i < numIterationsPerUser; i++) { try { var watch = Stopwatch.StartNew(); await action(); watch.Stop(); elapsedMs.Add(watch.ElapsedMilliseconds); } catch { Interlocked.Increment(ref errors); } } } var tasks = new List(); for (var i = 0; i < numUsers; i++) { tasks.Add(Task.Run(RunAsync)); } await Task.WhenAll(tasks); var count = elapsedMs.Count; var avg = elapsedMs.Average(); if (testOutput != null) { testOutput.WriteLine("Total Errors: {0}/{1}", errors, numUsers * numIterationsPerUser); testOutput.WriteLine("Total Count: {0}/{1}", count, numUsers * numIterationsPerUser); testOutput.WriteLine(string.Empty); testOutput.WriteLine("Performance Average: {0}", avg); testOutput.WriteLine("Performance Max: {0}", elapsedMs.Max()); testOutput.WriteLine("Performance Min: {0}", elapsedMs.Min()); } Assert.InRange(avg, 0, expectedAvg); } } }