public async Task SuccessExitsWithCodeZero() { using (TestHostContext hc = new TestHostContext(this)) { Tracing trace = hc.GetTrace(); Int32 exitCode = -1; var processInvoker = new ProcessInvokerWrapper(); processInvoker.Initialize(hc); #if OS_WINDOWS exitCode = await processInvoker.ExecuteAsync("", "cmd.exe", "/c \"dir >nul\"", null, CancellationToken.None); #else exitCode = await processInvoker.ExecuteAsync("", "bash", "-c echo .", null, CancellationToken.None); #endif trace.Info("Exit Code: {0}", exitCode); Assert.Equal(0, exitCode); } }
public async Task DefaultsToCurrentSystemOemEncoding() { // This test verifies that the additional code pages encoding provider is registered. // By default, only Unicode encodings, ASCII, and code page 28591 are supported. An // additional provider must be registered to support the full set of encodings that // were included in Full .NET prior to 4.6. // // For example, on an en-US box, this is required for loading the encoding for the // default console output code page '437'. Without loading the correct encoding for // code page IBM437, some characters cannot be translated correctly, e.g. write 'ç' // from powershell.exe. using (TestHostContext hc = new TestHostContext(this)) { Tracing trace = hc.GetTrace(); var processInvoker = new ProcessInvokerWrapper(); processInvoker.Initialize(hc); var stdout = new List <string>(); var stderr = new List <string>(); processInvoker.OutputDataReceived += (object sender, ProcessDataReceivedEventArgs e) => { stdout.Add(e.Data); }; processInvoker.ErrorDataReceived += (object sender, ProcessDataReceivedEventArgs e) => { stderr.Add(e.Data); }; await processInvoker.ExecuteAsync( workingDirectory : "", fileName : "powershell.exe", arguments : $@"-NoLogo -Sta -NoProfile -NonInteractive -ExecutionPolicy Unrestricted -Command ""Write-Host 'From STDOUT ''ç''' ; Write-Error 'From STDERR ''ç'''""", environment : null, requireExitCodeZero : false, cancellationToken : CancellationToken.None); Assert.Equal(1, stdout.Count); Assert.Equal("From STDOUT 'ç'", stdout[0]); Assert.True(stderr.Count > 0); Assert.True(stderr[0].Contains("From STDERR 'ç'")); } }
public async Task OomScoreAdjIsWriten_FromEnv() { // We are on a system that supports oom_score_adj in procfs as assumed by ProcessInvoker string testProcPath = $"/proc/{Process.GetCurrentProcess().Id}/oom_score_adj"; if (File.Exists(testProcPath)) { using (TestHostContext hc = new TestHostContext(this)) using (var tokenSource = new CancellationTokenSource()) { Tracing trace = hc.GetTrace(); using (var processInvoker = new ProcessInvokerWrapper()) { processInvoker.Initialize(hc); int oomScoreAdj = -9999; processInvoker.OutputDataReceived += (object sender, ProcessDataReceivedEventArgs e) => { oomScoreAdj = int.Parse(e.Data); tokenSource.Cancel(); }; try { var proc = await processInvoker.ExecuteAsync("", "bash", "-c \"cat /proc/$$/oom_score_adj\"", new Dictionary <string, string> { { "PIPELINE_JOB_OOMSCOREADJ", "1234" } }, false, null, false, null, false, false, highPriorityProcess : false, cancellationToken : tokenSource.Token); Assert.Equal(oomScoreAdj, 1234); } catch (OperationCanceledException) { trace.Info("Caught expected OperationCanceledException"); } } } } }
private static async Task CreateDirectoryReparsePoint(IHostContext context, string link, string target) { string fileName = (TestUtil.IsWindows()) ? Environment.GetEnvironmentVariable("ComSpec") : "/bin/ln"; string arguments = (TestUtil.IsWindows()) ? $@"/c ""mklink /J ""{link}"" {target}""""" : $@"-s ""{target}"" ""{link}"""; ArgUtil.File(fileName, nameof(fileName)); using (var processInvoker = new ProcessInvokerWrapper()) { processInvoker.Initialize(context); await processInvoker.ExecuteAsync( workingDirectory : context.GetDirectory(WellKnownDirectory.Bin), fileName : fileName, arguments : arguments, environment : null, requireExitCodeZero : true, cancellationToken : CancellationToken.None); } }
public async Task TestCancel() { const int SecondsToRun = 20; using (TestHostContext hc = new TestHostContext(this)) using (var tokenSource = new CancellationTokenSource()) { Tracing trace = hc.GetTrace(); using (var processInvoker = new ProcessInvokerWrapper()) { processInvoker.Initialize(hc); Stopwatch watch = Stopwatch.StartNew(); Task execTask = processInvoker.ExecuteAsync("", "bash", $"-c \"sleep {SecondsToRun}s\"", null, tokenSource.Token); await Task.Delay(500); tokenSource.Cancel(); try { await execTask; } catch (OperationCanceledException) { trace.Info("Get expected OperationCanceledException."); } Assert.True(execTask.IsCompleted); Assert.True(!execTask.IsFaulted); Assert.True(execTask.IsCanceled); watch.Stop(); long elapsedSeconds = watch.ElapsedMilliseconds / 1000; // if cancellation fails, then execution time is more than 15 seconds long expectedSeconds = (SecondsToRun * 3) / 4; Assert.True(elapsedSeconds <= expectedSeconds, $"cancellation failed, because task took too long to run. {elapsedSeconds}"); } } }
public async void TestSelfUpdateAsync() { using (var hc = new TestHostContext(this)) { //Arrange var updater = new Runner.Listener.SelfUpdater(); hc.SetSingleton <ITerminal>(_term.Object); hc.SetSingleton <IRunnerServer>(_runnerServer.Object); hc.SetSingleton <IConfigurationStore>(_configStore.Object); hc.SetSingleton <IHttpClientHandlerFactory>(new HttpClientHandlerFactory()); var p = new ProcessInvokerWrapper(); p.Initialize(hc); hc.EnqueueInstance <IProcessInvoker>(p); updater.Initialize(hc); _runnerServer.Setup(x => x.UpdateAgentUpdateStateAsync(1, 1, It.IsAny <string>(), It.IsAny <string>())) .Callback((int p, int a, string s, string t) => { hc.GetTrace().Info(t); }) .Returns(Task.FromResult(new TaskAgent())); try { var result = await updater.SelfUpdate(_refreshMessage, _jobDispatcher.Object, true, hc.RunnerShutdownToken); Assert.True(result); Assert.True(Directory.Exists(Path.Combine(hc.GetDirectory(WellKnownDirectory.Root), "bin.2.299.0"))); Assert.True(Directory.Exists(Path.Combine(hc.GetDirectory(WellKnownDirectory.Root), "externals.2.299.0"))); } finally { IOUtil.DeleteDirectory(Path.Combine(hc.GetDirectory(WellKnownDirectory.Root), "bin.2.299.0"), CancellationToken.None); IOUtil.DeleteDirectory(Path.Combine(hc.GetDirectory(WellKnownDirectory.Root), "externals.2.299.0"), CancellationToken.None); } } }
public async Task SuccessReadProcessEnv() { using (TestHostContext hc = new TestHostContext(this)) { Tracing trace = hc.GetTrace(); string envName = Guid.NewGuid().ToString(); string envValue = Guid.NewGuid().ToString(); Process sleep = null; try { // TODO: this was formerly skipped on Windows - why? using (var processInvoker = new ProcessInvokerWrapper()) { hc.EnqueueInstance <IProcessInvoker>(processInvoker); // sleep 15 seconds string sleepCmd = (TestUtil.IsWindows()) ? "powershell" : "sleep"; string sleepArgs = (TestUtil.IsWindows()) ? "-Command \"Start-Sleep -s 15\"" : "15s"; var startInfo = new ProcessStartInfo(sleepCmd, sleepArgs); startInfo.Environment[envName] = envValue; sleep = Process.Start(startInfo); var timeout = Process.GetProcessById(sleep.Id); while (timeout == null) { await Task.Delay(1500); timeout = Process.GetProcessById(sleep.Id); } try { trace.Info($"Read env from {timeout.Id}"); int retries = 5; while (retries >= 0) { try { var value = timeout.GetEnvironmentVariable(hc, envName); Assert.True(string.Equals(value, envValue, StringComparison.OrdinalIgnoreCase), "Expected environment '" + envValue + "' did not match actual '" + value + "'"); break; } catch (Exception ex) { retries--; if (retries < 0) { throw; } trace.Info($"Unable to get the environment variable, will retry. {retries} retries remaining"); await Task.Delay(2000); } } } catch (Exception ex) { trace.Error(ex); Assert.True(false, "Fail to retrive process environment variable due to exception: " + ex.Message + "\n" + ex.StackTrace); } } } finally { try { sleep?.Kill(); } catch { } } } }