Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 3f8175f

Browse files
author
Lakshmi Priya Sekar
committed
Address PR feedback to Process Tests.
Conflicts: src/System.Diagnostics.Process/tests/System.Diagnostics.Process.Tests/ProcessTests.cs
1 parent b1fede3 commit 3f8175f

File tree

8 files changed

+435
-60
lines changed

8 files changed

+435
-60
lines changed

src/Common/tests/System/Diagnostics/AssertWithCallerAttributes.cs

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -201,17 +201,20 @@ public static bool Equals(object a, object b,
201201
catch (Exception e) { throw WrapException(e, path, line); }
202202
}
203203

204-
public static void False(bool condition,
204+
public static void False(bool condition, string userMessage = null,
205205
[CallerFilePath] string path = null, [CallerLineNumber] int line = 0)
206206
{
207-
try { Xunit.Assert.False(condition); }
208-
catch (Exception e) { throw WrapException(e, path, line); }
209-
}
210-
211-
public static void False(bool condition, string userMessage,
212-
[CallerFilePath] string path = null, [CallerLineNumber] int line = 0)
213-
{
214-
try { Xunit.Assert.False(condition, userMessage); }
207+
try
208+
{
209+
if (userMessage == null)
210+
{
211+
Xunit.Assert.False(condition);
212+
}
213+
else
214+
{
215+
Xunit.Assert.False(condition, userMessage);
216+
}
217+
}
215218
catch (Exception e) { throw WrapException(e, path, line); }
216219
}
217220

@@ -604,7 +607,7 @@ private static XunitException WrapException(Exception e, string callerFilePath,
604607
// so to use it we derive a custom exception type
605608
internal sealed class WrapperXunitException : XunitException
606609
{
607-
internal WrapperXunitException(string message, Exception innerException) :
610+
internal WrapperXunitException(string message, Exception innerException) :
608611
base(message, innerException)
609612
{
610613
}

src/System.Diagnostics.Process/tests/System.Diagnostics.Process.Tests/Interop.cs

Lines changed: 89 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
33

44
using Microsoft.Win32.SafeHandles;
5+
using System.ComponentModel;
56
using System.Runtime.InteropServices;
7+
using System.Security.Principal;
68

79
namespace System.Diagnostics.ProcessTests
810
{
@@ -23,15 +25,35 @@ public struct PROCESS_MEMORY_COUNTERS
2325
public uint PeakPagefileUsage;
2426
}
2527

26-
[DllImport("api-ms-win-core-memory-l1-1-1.dll")]
27-
public static extern bool GetProcessWorkingSetSizeEx(SafeProcessHandle hProcess, out IntPtr lpMinimumWorkingSetSize, out IntPtr lpMaximumWorkingSetSize, out uint flags);
28+
[StructLayout(LayoutKind.Sequential)]
29+
internal struct USER_INFO_1
30+
{
31+
public string usri1_name;
32+
public string usri1_password;
33+
public uint usri1_password_age;
34+
public uint usri1_priv;
35+
public string usri1_home_dir;
36+
public string usri1_comment;
37+
public uint usri1_flags;
38+
public string usri1_script_path;
39+
}
2840

29-
[DllImport("api-ms-win-core-processthreads-l1-1-0", CharSet = System.Runtime.InteropServices.CharSet.Unicode, SetLastError = true)]
30-
public static extern int GetPriorityClass(SafeProcessHandle handle);
41+
[StructLayout(LayoutKind.Sequential)]
42+
public struct TOKEN_USER
43+
{
44+
public SID_AND_ATTRIBUTES User;
45+
}
3146

32-
[DllImport("kernel32.dll", CharSet = System.Runtime.InteropServices.CharSet.Ansi, SetLastError = true)]
33-
public static extern SafeProcessHandle GetCurrentProcess();
47+
[StructLayout(LayoutKind.Sequential)]
48+
public struct SID_AND_ATTRIBUTES
49+
{
50+
public IntPtr Sid;
51+
public int Attributes;
52+
}
3453

54+
[DllImport("api-ms-win-core-memory-l1-1-1.dll")]
55+
public static extern bool GetProcessWorkingSetSizeEx(SafeProcessHandle hProcess, out IntPtr lpMinimumWorkingSetSize, out IntPtr lpMaximumWorkingSetSize, out uint flags);
56+
3557
[DllImport("api-ms-win-core-processthreads-l1-1-0.dll")]
3658
internal static extern int GetCurrentProcessId();
3759

@@ -58,5 +80,66 @@ public struct PROCESS_MEMORY_COUNTERS
5880

5981
[DllImport("api-ms-win-core-console-l1-1-0.dll")]
6082
internal extern static int SetConsoleOutputCP(int codePage);
83+
84+
[DllImport("netapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
85+
internal extern static uint NetUserAdd(string servername, uint level, ref USER_INFO_1 buf, out uint parm_err);
86+
87+
[DllImport("netapi32.dll")]
88+
internal extern static uint NetUserDel(string servername, string username);
89+
90+
[DllImport("advapi32.dll")]
91+
internal static extern bool OpenProcessToken(SafeProcessHandle ProcessHandle, uint DesiredAccess, out SafeProcessHandle TokenHandle);
92+
93+
[DllImport("advapi32.dll")]
94+
internal static extern bool GetTokenInformation(SafeProcessHandle TokenHandle, uint TokenInformationClass, IntPtr TokenInformation, int TokenInformationLength, ref int ReturnLength);
95+
96+
internal static bool NetUserAdd(string username, string password)
97+
{
98+
USER_INFO_1 userInfo = new USER_INFO_1();
99+
userInfo.usri1_name = username;
100+
userInfo.usri1_password = password;
101+
userInfo.usri1_priv = 1;
102+
103+
uint parm_err;
104+
uint result = NetUserAdd(null, 1, ref userInfo, out parm_err);
105+
106+
if (result != 0)
107+
{
108+
throw new Win32Exception();
109+
}
110+
111+
return true;
112+
}
113+
114+
internal static bool ProcessTokenToSid(SafeProcessHandle token, out SecurityIdentifier sid)
115+
{
116+
bool ret = false;
117+
sid = null;
118+
IntPtr tu = IntPtr.Zero;
119+
try
120+
{
121+
TOKEN_USER tokUser;
122+
const int bufLength = 256;
123+
124+
tu = Marshal.AllocHGlobal(bufLength);
125+
int cb = bufLength;
126+
ret = GetTokenInformation(token, 1, tu, cb, ref cb);
127+
if (ret)
128+
{
129+
tokUser = Marshal.PtrToStructure<TOKEN_USER>(tu);
130+
sid = new SecurityIdentifier(tokUser.User.Sid);
131+
}
132+
return ret;
133+
}
134+
catch (Exception)
135+
{
136+
return false;
137+
}
138+
finally
139+
{
140+
if (tu != IntPtr.Zero)
141+
Marshal.FreeHGlobal(tu);
142+
}
143+
}
61144
}
62145
}

src/System.Diagnostics.Process/tests/System.Diagnostics.Process.Tests/ProcessStartInfoTests.cs

Lines changed: 104 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,12 @@
33

44
using System.Collections.Generic;
55
using System.Security;
6+
using System.Security.Principal;
7+
using Microsoft.Win32;
68
using System.IO;
79
using Xunit;
10+
using Microsoft.Win32.SafeHandles;
11+
using System.Linq;
812

913
namespace System.Diagnostics.ProcessTests
1014
{
@@ -197,18 +201,21 @@ public void TestArgumentsProperty()
197201

198202
psi = new ProcessStartInfo("filename", "-arg1 -arg2");
199203
Assert.Equal("-arg1 -arg2", psi.Arguments);
204+
205+
psi.Arguments = "-arg3 -arg4";
206+
Assert.Equal("-arg3 -arg4", psi.Arguments);
200207
}
201208

202-
[Fact]
203-
public void TestCreateNoWindowProperty()
209+
[Theory, InlineData(true), InlineData(false)]
210+
public void TestCreateNoWindowProperty(bool value)
204211
{
205212
Process testProcess = CreateProcessInfinite();
206213
try
207214
{
208-
testProcess.StartInfo.CreateNoWindow = true;
215+
testProcess.StartInfo.CreateNoWindow = value;
209216
testProcess.Start();
210217

211-
Assert.True(testProcess.StartInfo.CreateNoWindow);
218+
Assert.Equal(value, testProcess.StartInfo.CreateNoWindow);
212219
}
213220
finally
214221
{
@@ -219,14 +226,52 @@ public void TestCreateNoWindowProperty()
219226
}
220227
}
221228

222-
[Fact, PlatformSpecific(PlatformID.Windows)]
229+
[Fact, PlatformSpecific(PlatformID.Windows), OuterLoop] // Requires admin privileges
223230
public void TestUserCredentialsPropertiesOnWindows()
224231
{
225-
// test the defaults here.
226-
Assert.Equal(string.Empty, _process.StartInfo.Domain);
227-
Assert.Equal(string.Empty, _process.StartInfo.UserName);
228-
Assert.Equal(default(SecureString), _process.StartInfo.Password);
229-
Assert.False(_process.StartInfo.LoadUserProfile);
232+
string username = "test", password = "PassWord123!!";
233+
234+
if (Interop.NetUserAdd(username, password))
235+
{
236+
Process p = CreateProcessInfinite();
237+
238+
p.StartInfo.LoadUserProfile = true;
239+
p.StartInfo.UserName = username;
240+
p.StartInfo.Password = GetSecureString(password);
241+
242+
SafeProcessHandle handle = null;
243+
try
244+
{
245+
p.Start();
246+
if (Interop.OpenProcessToken(p.SafeHandle, 0x8u, out handle))
247+
{
248+
SecurityIdentifier sid;
249+
if (Interop.ProcessTokenToSid(handle, out sid))
250+
{
251+
string actualUserName = sid.Translate(typeof(NTAccount)).ToString();
252+
int indexOfDomain = actualUserName.IndexOf('\\');
253+
if (indexOfDomain != -1)
254+
actualUserName = actualUserName.Substring(indexOfDomain + 1);
255+
256+
bool isProfileLoaded = GetNamesOfUserProfiles().Any(profile => profile.Equals(username));
257+
258+
Assert.Equal(username, actualUserName);
259+
Assert.True(isProfileLoaded);
260+
}
261+
}
262+
}
263+
finally
264+
{
265+
if (handle != null)
266+
handle.Dispose();
267+
268+
if (!p.HasExited)
269+
p.Kill();
270+
271+
Interop.NetUserDel(null, username);
272+
Assert.True(p.WaitForExit(WaitInMS));
273+
}
274+
}
230275
}
231276

232277
[Fact, PlatformSpecific(PlatformID.AnyUnix)]
@@ -238,9 +283,57 @@ public void TestUserCredentialsPropertiesOnUnix()
238283
Assert.Throws<PlatformNotSupportedException>(() => _process.StartInfo.LoadUserProfile);
239284
}
240285

286+
[Fact]
241287
public void TestWorkingDirectoryProperty()
242288
{
243-
Assert.Equal(Directory.GetCurrentDirectory(), _process.StartInfo.WorkingDirectory);
289+
// check defaults
290+
Assert.Equal(string.Empty, _process.StartInfo.WorkingDirectory);
291+
292+
Process p = CreateProcessInfinite();
293+
p.StartInfo.WorkingDirectory = Directory.GetCurrentDirectory();
294+
295+
try
296+
{
297+
p.Start();
298+
Assert.Equal(Directory.GetCurrentDirectory(), p.StartInfo.WorkingDirectory);
299+
}
300+
finally
301+
{
302+
if (!p.HasExited)
303+
p.Kill();
304+
305+
Assert.True(p.WaitForExit(WaitInMS));
306+
}
307+
}
308+
309+
private unsafe SecureString GetSecureString(string password)
310+
{
311+
fixed (char* p = password)
312+
return new SecureString(p, password.Length);
313+
}
314+
315+
private static List<string> GetNamesOfUserProfiles()
316+
{
317+
List<string> userNames = new List<string>();
318+
319+
string[] names = Registry.Users.GetSubKeyNames();
320+
for (int i = 1; i < names.Length; i++)
321+
{
322+
try
323+
{
324+
SecurityIdentifier sid = new SecurityIdentifier(names[i]);
325+
string userName = sid.Translate(typeof(NTAccount)).ToString();
326+
int indexofDomain = userName.IndexOf('\\');
327+
if (indexofDomain != -1)
328+
{
329+
userName = userName.Substring(indexofDomain + 1);
330+
userNames.Add(userName);
331+
}
332+
}
333+
catch (Exception) { }
334+
}
335+
336+
return userNames;
244337
}
245338
}
246339
}

src/System.Diagnostics.Process/tests/System.Diagnostics.Process.Tests/ProcessTests.cs

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -361,20 +361,36 @@ public void TestProcessorTime()
361361
{
362362
Assert.True(_process.UserProcessorTime.TotalSeconds >= 0);
363363
Assert.True(_process.PrivilegedProcessorTime.TotalSeconds >= 0);
364-
Assert.True(_process.TotalProcessorTime.TotalSeconds >= 0);
364+
365+
double processorTimeBeforeSpin = Process.GetCurrentProcess().TotalProcessorTime.TotalSeconds;
366+
double processorTimeAtHalfSpin = 0;
367+
// Perform loop to occupy cpu, takes less than a second.
368+
int i = int.MaxValue / 16;
369+
while (i > 0)
370+
{
371+
i--;
372+
if (i == int.MaxValue / 32)
373+
processorTimeAtHalfSpin = Process.GetCurrentProcess().TotalProcessorTime.TotalSeconds;
374+
}
375+
376+
Assert.InRange(processorTimeAtHalfSpin, processorTimeBeforeSpin, Process.GetCurrentProcess().TotalProcessorTime.TotalSeconds);
365377
}
366378

367379
[Fact]
368380
public void TestProcessStartTime()
369381
{
382+
DateTime timeBeforeCreatingProcess = DateTime.UtcNow;
370383
Process p = CreateProcessInfinite();
371384
try
372385
{
373386
p.Start();
374387

375-
// Ensure process has been started, should not throw.
376-
Process accessProcessFromMachine = Process.GetProcessById(p.Id);
377-
Assert.True(p.StartTime.ToUniversalTime() <= DateTime.UtcNow, string.Format("Process StartTime is larger than later time."));
388+
// Time in unix, is measured in jiffies, which is incremented by one for every timer interrupt since the boot time.
389+
// Thus, because there are HZ timer interrupts in a second, there are HZ jiffies in a second. Hence 1\HZ, will
390+
// be the resolution of system timer. The lowest value of HZ on unix is 100, hence the timer resolution is 10 ms.
391+
// Allowing for error in 10 ms.
392+
long beforeTicks = timeBeforeCreatingProcess.Ticks - new TimeSpan(0, 0, 0, 0, 10).Ticks;
393+
Assert.InRange(p.StartTime.ToUniversalTime().Ticks, beforeTicks, DateTime.UtcNow.Ticks);
378394
}
379395
finally
380396
{
@@ -581,15 +597,6 @@ public void TestStartInfo()
581597
}
582598
}
583599

584-
[Fact]
585-
public void TestThreadCount()
586-
{
587-
Assert.True(_process.Threads.Count > 0);
588-
using (Process p = Process.GetCurrentProcess())
589-
{
590-
Assert.True(p.Threads.Count > 0);
591-
}
592-
}
593600

594601
// [Fact] // uncomment for diagnostic purposes to list processes to console
595602
public void TestDiagnosticsWithConsoleWriteLine()

0 commit comments

Comments
 (0)