Skip to content

Commit e0610a6

Browse files
RakeshwarKRakeshwar Reddy Kambaiahgari
andauthored
Enabled windows ProcessorAffinity support (#629)
* Init Commit * Update tests * Update tests * commit changes * Windows Changes * Added Doccu * Format Doc * Update profile * commit changes --------- Co-authored-by: Rakeshwar Reddy Kambaiahgari <rkambaiahgar@microsoft.com>
1 parent ca6bab4 commit e0610a6

12 files changed

Lines changed: 1002 additions & 4 deletions

File tree

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
namespace VirtualClient.Actions
5+
{
6+
using System;
7+
using System.Collections.Generic;
8+
using System.Linq;
9+
using System.Runtime.InteropServices;
10+
using System.Threading;
11+
using System.Threading.Tasks;
12+
using NUnit.Framework;
13+
using VirtualClient.Common;
14+
using VirtualClient.Contracts;
15+
16+
[TestFixture]
17+
[Category("Functional")]
18+
public class ExampleWorkloadWithAffinityProfileTests
19+
{
20+
private DependencyFixture mockFixture;
21+
22+
[OneTimeSetUp]
23+
public void SetupFixture()
24+
{
25+
this.mockFixture = new DependencyFixture();
26+
ComponentTypeCache.Instance.LoadComponentTypes(TestDependencies.TestDirectory);
27+
}
28+
29+
[Test]
30+
[TestCase("PERF-CPU-EXAMPLE-AFFINITY.json", PlatformID.Unix, Architecture.X64)]
31+
[TestCase("PERF-CPU-EXAMPLE-AFFINITY.json", PlatformID.Unix, Architecture.Arm64)]
32+
public void ExampleWorkloadProfileParametersAreInlinedCorrectly_Linux(string profile, PlatformID platform, Architecture architecture)
33+
{
34+
this.mockFixture.Setup(platform, architecture);
35+
using (ProfileExecutor executor = TestDependencies.CreateProfileExecutor(profile, this.mockFixture.Dependencies))
36+
{
37+
WorkloadAssert.ParameterReferencesInlined(executor.Profile);
38+
}
39+
}
40+
41+
[Test]
42+
[Platform(Exclude = "Unix,Linux,MacOsX")]
43+
[TestCase("PERF-CPU-EXAMPLE-AFFINITY.json", PlatformID.Win32NT, Architecture.X64)]
44+
[TestCase("PERF-CPU-EXAMPLE-AFFINITY.json", PlatformID.Win32NT, Architecture.Arm64)]
45+
public void ExampleWorkloadProfileParametersAreInlinedCorrectly_Windows(string profile, PlatformID platform, Architecture architecture)
46+
{
47+
this.mockFixture.Setup(platform, architecture);
48+
using (ProfileExecutor executor = TestDependencies.CreateProfileExecutor(profile, this.mockFixture.Dependencies))
49+
{
50+
WorkloadAssert.ParameterReferencesInlined(executor.Profile);
51+
}
52+
}
53+
54+
[Test]
55+
[TestCase("PERF-CPU-EXAMPLE-AFFINITY.json", PlatformID.Unix)]
56+
public async Task ExampleWorkloadProfileInstallsTheExpectedDependenciesOnLinuxPlatform(string profile, PlatformID platform)
57+
{
58+
this.mockFixture.Setup(platform);
59+
60+
using (ProfileExecutor executor = TestDependencies.CreateProfileExecutor(profile, this.mockFixture.Dependencies, dependenciesOnly: true))
61+
{
62+
await executor.ExecuteAsync(ProfileTiming.OneIteration(), CancellationToken.None).ConfigureAwait(false);
63+
64+
// Workload dependency package should be installed
65+
WorkloadAssert.WorkloadPackageInstalled(this.mockFixture, "exampleworkload");
66+
}
67+
}
68+
69+
[Test]
70+
[Platform(Exclude = "Unix,Linux,MacOsX")]
71+
[TestCase("PERF-CPU-EXAMPLE-AFFINITY.json", PlatformID.Win32NT)]
72+
public async Task ExampleWorkloadProfileInstallsTheExpectedDependenciesOnWindowsPlatform(string profile, PlatformID platform)
73+
{
74+
this.mockFixture.Setup(platform);
75+
76+
using (ProfileExecutor executor = TestDependencies.CreateProfileExecutor(profile, this.mockFixture.Dependencies, dependenciesOnly: true))
77+
{
78+
await executor.ExecuteAsync(ProfileTiming.OneIteration(), CancellationToken.None).ConfigureAwait(false);
79+
80+
// Workload dependency package should be installed
81+
WorkloadAssert.WorkloadPackageInstalled(this.mockFixture, "exampleworkload");
82+
}
83+
}
84+
85+
[Test]
86+
[TestCase("PERF-CPU-EXAMPLE-AFFINITY.json", PlatformID.Unix)]
87+
public async Task ExampleWorkloadProfileExecutesTheExpectedWorkloadWithAffinityOnLinux(string profile, PlatformID platform)
88+
{
89+
this.mockFixture.Setup(platform);
90+
this.mockFixture.SetupPackage("exampleworkload", expectedFiles: "linux-x64/ExampleWorkload");
91+
92+
this.mockFixture.ProcessManager.OnCreateProcess = (command, arguments, workingDir) =>
93+
{
94+
IProcessProxy process = this.mockFixture.CreateProcess(command, arguments, workingDir);
95+
if (command.Contains("bash") && arguments.Contains("numactl"))
96+
{
97+
// Verify numactl wrapper is used for CPU affinity on Linux
98+
process.StandardOutput.Append("{ \"metric1\": 100, \"metric2\": 200 }");
99+
}
100+
101+
return process;
102+
};
103+
104+
using (ProfileExecutor executor = TestDependencies.CreateProfileExecutor(profile, this.mockFixture.Dependencies))
105+
{
106+
await executor.ExecuteAsync(ProfileTiming.OneIteration(), CancellationToken.None).ConfigureAwait(false);
107+
108+
// Verify numactl was used for CPU affinity
109+
WorkloadAssert.CommandsExecuted(this.mockFixture, "\"numactl -C");
110+
}
111+
}
112+
113+
[Test]
114+
[Platform(Exclude = "Unix,Linux,MacOsX")]
115+
[TestCase("PERF-CPU-EXAMPLE-AFFINITY.json", PlatformID.Win32NT)]
116+
public async Task ExampleWorkloadProfileExecutesTheExpectedWorkloadWithAffinityOnWindows(string profile, PlatformID platform)
117+
{
118+
this.mockFixture.Setup(platform);
119+
this.mockFixture.SetupPackage("exampleworkload", expectedFiles: "win-x64/ExampleWorkload.exe");
120+
121+
this.mockFixture.ProcessManager.OnCreateProcess = (command, arguments, workingDir) =>
122+
{
123+
InMemoryProcess process = this.mockFixture.CreateProcess(command, arguments, workingDir);
124+
if (command.Contains("ExampleWorkload"))
125+
{
126+
// Set HasExited to false initially, true after "wait"
127+
bool hasExited = false;
128+
process.OnHasExited = () => hasExited;
129+
process.OnStart = () =>
130+
{
131+
hasExited = false;
132+
return true;
133+
};
134+
135+
process.OnApplyAffinity = (mask) =>
136+
{
137+
// Verify affinity mask is set while process is running
138+
Assert.IsFalse(hasExited, "Affinity should be applied while process is running");
139+
Assert.Greater(mask.ToInt64(), 0);
140+
};
141+
142+
// Simulate process completion when WaitForExitAsync is called
143+
process.WaitForExitAsync(CancellationToken.None);
144+
process.StandardOutput.Append("{ \"metric1\": 100, \"metric2\": 200 }");
145+
hasExited = true;
146+
}
147+
148+
return process;
149+
};
150+
151+
using (ProfileExecutor executor = TestDependencies.CreateProfileExecutor(profile, this.mockFixture.Dependencies))
152+
{
153+
await executor.ExecuteAsync(ProfileTiming.OneIteration(), CancellationToken.None).ConfigureAwait(false);
154+
155+
// Verify the process was executed
156+
WorkloadAssert.CommandsExecuted(this.mockFixture, "ExampleWorkload");
157+
}
158+
}
159+
160+
[Test]
161+
[TestCase("PERF-CPU-EXAMPLE-AFFINITY.json")]
162+
public void ExampleWorkloadProfileActionsWillNotBeExecutedIfTheWorkloadPackageDoesNotExist(string profile)
163+
{
164+
this.mockFixture.Setup(PlatformID.Unix);
165+
166+
// Ensure the workload package does not exist
167+
this.mockFixture.PackageManager.Clear();
168+
169+
using (ProfileExecutor executor = TestDependencies.CreateProfileExecutor(profile, this.mockFixture.Dependencies))
170+
{
171+
executor.ExecuteDependencies = false;
172+
173+
DependencyException error = Assert.ThrowsAsync<DependencyException>(() => executor.ExecuteAsync(ProfileTiming.OneIteration(), CancellationToken.None));
174+
Assert.AreEqual(ErrorReason.WorkloadDependencyMissing, error.Reason);
175+
}
176+
}
177+
}
178+
}

0 commit comments

Comments
 (0)