Skip to content

Commit

Permalink
Run processenvironment test in separate process. (#51022)
Browse files Browse the repository at this point in the history
  • Loading branch information
lateralusX authored Apr 12, 2021
1 parent 256729b commit 355eff5
Showing 1 changed file with 74 additions and 62 deletions.
136 changes: 74 additions & 62 deletions src/tests/tracing/eventpipe/processenvironment/processenvironment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,83 +13,95 @@
using Microsoft.Diagnostics.Tools.RuntimeClient;
using Microsoft.Diagnostics.Tracing;
using Tracing.Tests.Common;
using System.Reflection;

namespace Tracing.Tests.ProcessEnvironmentValidation
{
public class ProcessEnvironmentValidation
{
public static int Main(string[] args)
{
if (args.Length >= 1)
{
Console.Out.WriteLine("Subprocess started! Waiting for input...");
var input = Console.In.ReadLine(); // will block until data is sent across stdin
Console.Out.WriteLine($"Received '{input}'. Exiting...");
return 0;
}

Process currentProcess = Process.GetCurrentProcess();
int pid = currentProcess.Id;
Logger.logger.Log($"Test PID: {pid}");
var testEnvPairs = new Dictionary<string, string>
{
{ "TESTKEY1", "TESTVAL1" },
{ "TESTKEY2", "TESTVAL2" },
{ "TESTKEY3", "__TEST__VAL=;--3" }
};

foreach (var (key, val) in testEnvPairs)
System.Environment.SetEnvironmentVariable(key, val);

Stream stream = ConnectionHelper.GetStandardTransport(pid);

// 0x04 = ProcessCommandSet, 0x02 = ProcessInfo
var processInfoMessage = new IpcMessage(0x04, 0x02);
Logger.logger.Log($"Wrote: {processInfoMessage}");
Stream continuationStream = IpcClient.SendMessage(stream, processInfoMessage, out IpcMessage response);
Logger.logger.Log($"Received: {response}");

Utils.Assert(response.Header.CommandSet == 0xFF, $"Response must have Server command set. Expected: 0xFF, Received: 0x{response.Header.CommandSet:X2}"); // server
Utils.Assert(response.Header.CommandId == 0x00, $"Response must have OK command id. Expected: 0x00, Received: 0x{response.Header.CommandId:X2}"); // OK

UInt32 continuationSizeInBytes = BitConverter.ToUInt32(response.Payload[0..4]);
Logger.logger.Log($"continuation size: {continuationSizeInBytes} bytes");
UInt16 future = BitConverter.ToUInt16(response.Payload[4..]);
Logger.logger.Log($"future value: {future}");

using var memoryStream = new MemoryStream();
Logger.logger.Log($"Starting to copy continuation");
continuationStream.CopyTo(memoryStream);
Logger.logger.Log($"Finished copying continuation");
byte[] envBlock = memoryStream.ToArray();
Logger.logger.Log($"Total bytes in continuation: {envBlock.Length}");

Utils.Assert(envBlock.Length == continuationSizeInBytes, $"Continuation size must equal the reported size in the payload response. Expected: {continuationSizeInBytes} bytes, Received: {envBlock.Length} bytes");

// VALIDATE ENV
// env block is sent as Array<LPCWSTR> (length-prefixed array of length-prefixed wchar strings)
int start = 0;
int end = start + 4 /* sizeof(uint32_t) */;
UInt32 envCount = BitConverter.ToUInt32(envBlock[start..end]);
Logger.logger.Log($"envCount: {envCount}");

var env = new Dictionary<string,string>();
for (int i = 0; i < envCount; i++)
{
start = end;
end = start + 4 /* sizeof(uint32_t) */;
UInt32 pairLength = BitConverter.ToUInt32(envBlock[start..end]);

start = end;
end = start + ((int)pairLength * sizeof(char));
Utils.Assert(end <= envBlock.Length, $"String end can't exceed payload size. Expected: <{envBlock.Length}, Received: {end} (decoded length: {pairLength})");
string envPair = System.Text.Encoding.Unicode.GetString(envBlock[start..end]).TrimEnd('\0');
int equalsIndex = envPair.IndexOf('=');
env[envPair[0..equalsIndex]] = envPair[(equalsIndex+1)..];
}
Logger.logger.Log($"finished parsing env");


foreach (var (key, val) in testEnvPairs)
Utils.Assert(env.ContainsKey(key) && env[key].Equals(val), $"Did not find test environment pair in the environment block: '{key}' = '{val}'");
Logger.logger.Log($"Saw test values in env");

Utils.Assert(end == envBlock.Length, $"Full payload should have been read. Expected: {envBlock.Length}, Received: {end}");

return 100;
Task<bool> subprocessTask = Utils.RunSubprocess(
currentAssembly: Assembly.GetExecutingAssembly(),
environment: testEnvPairs,
duringExecution: (int pid) =>
{
Logger.logger.Log($"Test PID: {pid}");

Stream stream = ConnectionHelper.GetStandardTransport(pid);

// 0x04 = ProcessCommandSet, 0x02 = ProcessInfo
var processInfoMessage = new IpcMessage(0x04, 0x02);
Logger.logger.Log($"Wrote: {processInfoMessage}");
Stream continuationStream = IpcClient.SendMessage(stream, processInfoMessage, out IpcMessage response);
Logger.logger.Log($"Received: {response}");

Utils.Assert(response.Header.CommandSet == 0xFF, $"Response must have Server command set. Expected: 0xFF, Received: 0x{response.Header.CommandSet:X2}"); // server
Utils.Assert(response.Header.CommandId == 0x00, $"Response must have OK command id. Expected: 0x00, Received: 0x{response.Header.CommandId:X2}"); // OK

UInt32 continuationSizeInBytes = BitConverter.ToUInt32(response.Payload[0..4]);
Logger.logger.Log($"continuation size: {continuationSizeInBytes} bytes");
UInt16 future = BitConverter.ToUInt16(response.Payload[4..]);
Logger.logger.Log($"future value: {future}");

using var memoryStream = new MemoryStream();
Logger.logger.Log($"Starting to copy continuation");
continuationStream.CopyTo(memoryStream);
Logger.logger.Log($"Finished copying continuation");
byte[] envBlock = memoryStream.ToArray();
Logger.logger.Log($"Total bytes in continuation: {envBlock.Length}");

Utils.Assert(envBlock.Length == continuationSizeInBytes, $"Continuation size must equal the reported size in the payload response. Expected: {continuationSizeInBytes} bytes, Received: {envBlock.Length} bytes");

// VALIDATE ENV
// env block is sent as Array<LPCWSTR> (length-prefixed array of length-prefixed wchar strings)
int start = 0;
int end = start + 4 /* sizeof(uint32_t) */;
UInt32 envCount = BitConverter.ToUInt32(envBlock[start..end]);
Logger.logger.Log($"envCount: {envCount}");

var env = new Dictionary<string,string>();
for (int i = 0; i < envCount; i++)
{
start = end;
end = start + 4 /* sizeof(uint32_t) */;
UInt32 pairLength = BitConverter.ToUInt32(envBlock[start..end]);

start = end;
end = start + ((int)pairLength * sizeof(char));
Utils.Assert(end <= envBlock.Length, $"String end can't exceed payload size. Expected: <{envBlock.Length}, Received: {end} (decoded length: {pairLength})");
string envPair = System.Text.Encoding.Unicode.GetString(envBlock[start..end]).TrimEnd('\0');
int equalsIndex = envPair.IndexOf('=');
env[envPair[0..equalsIndex]] = envPair[(equalsIndex+1)..];
}
Logger.logger.Log($"finished parsing env");


foreach (var (key, val) in testEnvPairs)
Utils.Assert(env.ContainsKey(key) && env[key].Equals(val), $"Did not find test environment pair in the environment block: '{key}' = '{val}'");
Logger.logger.Log($"Saw test values in env");

Utils.Assert(end == envBlock.Length, $"Full payload should have been read. Expected: {envBlock.Length}, Received: {end}");
return Task.FromResult(true);
}
);

return subprocessTask.Result ? 100 : 0;
}
}
}

0 comments on commit 355eff5

Please sign in to comment.