diff --git a/src/VirtualClient/VirtualClient.Actions.UnitTests/Network/NTttcp/NTttcpExecutorTests.cs b/src/VirtualClient/VirtualClient.Actions.UnitTests/Network/NTttcp/NTttcpExecutorTests.cs index c5f4159db0..ba30670731 100644 --- a/src/VirtualClient/VirtualClient.Actions.UnitTests/Network/NTttcp/NTttcpExecutorTests.cs +++ b/src/VirtualClient/VirtualClient.Actions.UnitTests/Network/NTttcp/NTttcpExecutorTests.cs @@ -74,7 +74,10 @@ public void NTttcpExecutorThrowsOnUnsupportedOS() } [Test] - public async Task NTttcpExecutorClientExecutesAsExpected() + [TestCase(null)] + [TestCase(true)] + [TestCase(false)] + public async Task NTttcpExecutorClientExecutesAsExpected(bool? noSyncEnabled) { this.SetupTest(); @@ -118,6 +121,11 @@ public async Task NTttcpExecutorClientExecutesAsExpected() return process; }; + if (noSyncEnabled.HasValue) + { + this.mockFixture.Parameters["NoSyncEnabled"] = noSyncEnabled.Value; + } + TestNTttcpExecutor component = new TestNTttcpExecutor(this.mockFixture.Dependencies, this.mockFixture.Parameters); await component.ExecuteAsync(CancellationToken.None).ConfigureAwait(false); @@ -126,6 +134,58 @@ public async Task NTttcpExecutorClientExecutesAsExpected() Assert.AreEqual(2, processExecuted); } + [Test] + [TestCase(null)] + [TestCase(true)] + [TestCase(false)] + public async Task NTttcpExecutorClientExecutesAsExpectedInWindows(bool? noSyncEnabled) + { + this.SetupTest(); + + NetworkingWorkloadExecutorTests.TestNetworkingWorkloadExecutor networkingWorkloadExecutor = new NetworkingWorkloadExecutorTests.TestNetworkingWorkloadExecutor(this.mockFixture.Dependencies, this.mockFixture.Parameters); + await networkingWorkloadExecutor.OnInitialize.Invoke(EventContext.None, CancellationToken.None); + + int processExecuted = 0; + this.mockFixture.ProcessManager.OnCreateProcess = (file, arguments, workingDirectory) => + { + InMemoryProcess process = new InMemoryProcess() + { + StartInfo = new System.Diagnostics.ProcessStartInfo() + { + FileName = file, + Arguments = arguments, + }, + OnHasExited = () => true, + ExitCode = 0, + OnStart = () => true, + StandardOutput = new VirtualClient.Common.ConcurrentBuffer() + }; + + processExecuted++; + this.networkingWorkloadState.ToolState = NetworkingWorkloadToolState.Stopped; + var expectedStateItem = new Item(nameof(NetworkingWorkloadState), this.networkingWorkloadState); + + this.mockFixture.ApiClient.Setup(client => client.GetStateAsync(It.IsAny(), It.IsAny(), It.IsAny>())) + .ReturnsAsync(this.mockFixture.CreateHttpResponse(HttpStatusCode.OK, expectedStateItem)); + + return process; + }; + + if (noSyncEnabled.HasValue) + { + this.mockFixture.Parameters["NoSyncEnabled"] = noSyncEnabled.Value; + } + + this.mockFixture.SystemManagement.SetupGet(sm => sm.Platform).Returns(PlatformID.Win32NT); + + TestNTttcpExecutor component = new TestNTttcpExecutor(this.mockFixture.Dependencies, this.mockFixture.Parameters); + + await component.ExecuteAsync(CancellationToken.None).ConfigureAwait(false); + + //Process 1: Ntttcp, Process 2: Sysctl + Assert.AreEqual(1, processExecuted); + } + [Test] public async Task NTttcpExecutorClientWillNotExitOnCancellationRequestUntilTheResultsAreCaptured() { diff --git a/src/VirtualClient/VirtualClient.Actions.UnitTests/Network/NetworkingWorkloadExecutorTests.cs b/src/VirtualClient/VirtualClient.Actions.UnitTests/Network/NetworkingWorkloadExecutorTests.cs index 69129c7869..3b3d362f3f 100644 --- a/src/VirtualClient/VirtualClient.Actions.UnitTests/Network/NetworkingWorkloadExecutorTests.cs +++ b/src/VirtualClient/VirtualClient.Actions.UnitTests/Network/NetworkingWorkloadExecutorTests.cs @@ -58,7 +58,10 @@ public void SetupTest(PlatformID platformID, NetworkingWorkloadTool tool) } [Test] - public void NetworkingWorkloadStateInstancesAreJsonSerializable() + [TestCase(null)] + [TestCase(true)] + [TestCase(false)] + public void NetworkingWorkloadStateInstancesAreJsonSerializable(bool? noSyncEnabled) { NetworkingWorkloadState state = new NetworkingWorkloadState( "networking", @@ -87,6 +90,7 @@ public void NetworkingWorkloadStateInstancesAreJsonSerializable() "Profiling_Scenario_1", "00:00:30", "00:00:05", + noSyncEnabled, Guid.NewGuid()); SerializationAssert.IsJsonSerializable(state); @@ -122,6 +126,7 @@ public void NetworkingWorkloadStateInstancesAreJsonSerializable_2() "Profiling_Scenario_1", "00:00:30", "00:00:05", + false, Guid.NewGuid(), // // With Metadata @@ -169,6 +174,7 @@ public void NetworkingWorkloadStateInstancesAreJsonSerializable_3() "Profiling_Scenario_1", "00:00:30", "00:00:05", + false, Guid.NewGuid(), // // With Metadata diff --git a/src/VirtualClient/VirtualClient.Actions/Network/NetworkingWorkload/NTttcp/NTttcpExecutor.cs b/src/VirtualClient/VirtualClient.Actions/Network/NetworkingWorkload/NTttcp/NTttcpExecutor.cs index f2d79cbb40..5d8cc4d82e 100644 --- a/src/VirtualClient/VirtualClient.Actions/Network/NetworkingWorkload/NTttcp/NTttcpExecutor.cs +++ b/src/VirtualClient/VirtualClient.Actions/Network/NetworkingWorkload/NTttcp/NTttcpExecutor.cs @@ -185,6 +185,19 @@ public string Protocol } } + /// + /// NoSyncEnabled is only for client/sender role. + /// The NoSyncEnabled indicates that synchronization is disabled for the client. + /// + public bool? NoSyncEnabled + { + get + { + this.Parameters.TryGetValue(nameof(NetworkingWorkloadExecutor.NoSyncEnabled), out IConvertible noSyncEnabled); + return noSyncEnabled?.ToBoolean(CultureInfo.InvariantCulture); + } + } + /// /// The retry policy to apply to the startup of the NTttcp workload to handle /// transient issues. @@ -441,6 +454,7 @@ private string GetWindowsSpecificCommandLine() $"-p {this.Port} " + $"-xml {this.ResultsPath} " + $"{(this.Protocol.ToLowerInvariant() == "udp" ? "-u" : string.Empty)} " + + $"{((this.IsInClientRole && this.NoSyncEnabled == true) ? "-ns" : string.Empty)} " + $"{(this.IsInClientRole ? $"-nic {clientIPAddress}" : string.Empty)}".Trim(); } @@ -461,6 +475,7 @@ private string GetLinuxSpecificCommandLine() $"{((this.IsInServerRole && this.ReceiverMultiClientMode == true) ? "-M" : string.Empty)} " + $"{((this.IsInClientRole && this.ThreadsPerServerPort != null) ? $"-n {this.ThreadsPerServerPort}" : string.Empty)} " + $"{((this.IsInClientRole && this.ConnectionsPerThread != null) ? $"-l {this.ConnectionsPerThread}" : string.Empty)} " + + $"{((this.IsInClientRole && this.NoSyncEnabled == true) ? "-N" : string.Empty)} " + $"{((this.DevInterruptsDifferentiator != null) ? $"--show-dev-interrupts {this.DevInterruptsDifferentiator}" : string.Empty)}".Trim(); } } diff --git a/src/VirtualClient/VirtualClient.Actions/Network/NetworkingWorkload/NetworkingWorkloadExecutor.cs b/src/VirtualClient/VirtualClient.Actions/Network/NetworkingWorkload/NetworkingWorkloadExecutor.cs index 64140bfc6c..f2d50e1481 100644 --- a/src/VirtualClient/VirtualClient.Actions/Network/NetworkingWorkload/NetworkingWorkloadExecutor.cs +++ b/src/VirtualClient/VirtualClient.Actions/Network/NetworkingWorkload/NetworkingWorkloadExecutor.cs @@ -399,6 +399,23 @@ public double? ConfidenceLevel } } + /// + /// Parameter indicates that synchronization is disabled for the client. + /// + public bool? NoSyncEnabled + { + get + { + this.Parameters.TryGetValue(nameof(NetworkingWorkloadExecutor.NoSyncEnabled), out IConvertible noSyncEnabled); + return noSyncEnabled?.ToBoolean(CultureInfo.InvariantCulture); + } + + set + { + this.Parameters[nameof(NetworkingWorkloadExecutor.NoSyncEnabled)] = value; + } + } + /// /// Cancellation Token Source for Server. /// @@ -785,6 +802,7 @@ protected void OnInstructionsReceived(object sender, JObject instructions) this.ProfilingScenario = serverInstructions.ProfilingScenario; this.ProfilingPeriod = serverInstructions.ProfilingPeriod; this.ProfilingWarmUpPeriod = serverInstructions.ProfilingWarmUpPeriod; + this.NoSyncEnabled = serverInstructions.NoSyncEnabled; if (serverInstructions.Metadata?.Any() == true) { @@ -948,6 +966,7 @@ await this.ClientExecutionRetryPolicy.ExecuteAsync(async () => this.ProfilingScenario, this.ProfilingPeriod.ToString(), this.ProfilingWarmUpPeriod.ToString(), + this.NoSyncEnabled, requestId); Item instructions = new Item(nameof(NetworkingWorkloadState), workloadInstructions); diff --git a/src/VirtualClient/VirtualClient.Actions/Network/NetworkingWorkload/NetworkingWorkloadState.cs b/src/VirtualClient/VirtualClient.Actions/Network/NetworkingWorkload/NetworkingWorkloadState.cs index 5b30a15afe..cb8110c5cb 100644 --- a/src/VirtualClient/VirtualClient.Actions/Network/NetworkingWorkload/NetworkingWorkloadState.cs +++ b/src/VirtualClient/VirtualClient.Actions/Network/NetworkingWorkload/NetworkingWorkloadState.cs @@ -129,6 +129,7 @@ public NetworkingWorkloadState( string profilingScenario = null, string profilingPeriod = null, string profilingWarmUpPeriod = null, + bool? noSyncEnabled = null, Guid? clientRequestId = null, IDictionary metadata = null) { @@ -163,6 +164,7 @@ public NetworkingWorkloadState( this.Properties[nameof(this.ProfilingScenario)] = profilingScenario; this.Properties[nameof(this.ProfilingPeriod)] = profilingPeriod; this.Properties[nameof(this.ProfilingWarmUpPeriod)] = profilingWarmUpPeriod; + this.Properties[nameof(this.NoSyncEnabled)] = noSyncEnabled; this.ClientRequestId = clientRequestId; this.Metadata = new Dictionary(StringComparer.OrdinalIgnoreCase); @@ -492,6 +494,18 @@ public string DevInterruptsDifferentiator } } + /// + /// Parameter indicates that synchronization is disabled for the client (Parameter for Tools: NTttcp) + /// + public bool? NoSyncEnabled + { + get + { + this.Properties.TryGetValue(nameof(this.NoSyncEnabled), out IConvertible noSyncEnabled); + return noSyncEnabled?.ToBoolean(CultureInfo.InvariantCulture); + } + } + /// /// Number of Messages-Per-Second (Parameter for Tools: SockPerf). /// diff --git a/src/VirtualClient/VirtualClient.Controller.UnitTests/VirtualClientControllerComponentTests.cs b/src/VirtualClient/VirtualClient.Controller.UnitTests/VirtualClientControllerComponentTests.cs index 56a98bdb61..feaa02f5f8 100644 --- a/src/VirtualClient/VirtualClient.Controller.UnitTests/VirtualClientControllerComponentTests.cs +++ b/src/VirtualClient/VirtualClient.Controller.UnitTests/VirtualClientControllerComponentTests.cs @@ -30,7 +30,6 @@ public void SetupTest() [Test] [TestCase(10)] [TestCase(100)] - [TestCase(500)] public async Task VirtualClientControllerComponentSupportsConcurrentSshClientOperations(int concurrentExecutions) { List targetAgents = new List();