コード例 #1
0
        public async Task OomScoreAdjIsWriten_Default()
        {
            // 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();
                        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\"", null, false, null, false, null, false, false,
                                                                         highPriorityProcess : false,
                                                                         cancellationToken : tokenSource.Token);

                            Assert.Equal(oomScoreAdj, 500);
                        }
                        catch (OperationCanceledException)
                        {
                            trace.Info("Caught expected OperationCanceledException");
                        }
                    }
            }
        }
コード例 #2
0
        public async Task TestCancel()
        {
            const int SecondsToRun = 20;

            using (TestHostContext hc = new TestHostContext(this))
                using (var tokenSource = new CancellationTokenSource())
                {
                    Tracing trace          = hc.GetTrace();
                    var     processInvoker = new ProcessInvokerWrapper();
                    processInvoker.Initialize(hc);
                    Stopwatch watch = Stopwatch.StartNew();
#if OS_WINDOWS
                    Task execTask = processInvoker.ExecuteAsync("", "cmd.exe", $"/c \"choice /T {SecondsToRun} /D y\"", null, tokenSource.Token);
#endif
#if (OS_OSX || OS_LINUX)
                    Task execTask = processInvoker.ExecuteAsync("", "bash", $"-c \"sleep {SecondsToRun}s\"", null, tokenSource.Token);
#endif
                    await Task.Delay(500);

                    tokenSource.Cancel();
                    await Task.WhenAny(execTask);

                    Assert.True(execTask.IsCompleted);
                    Assert.True(!execTask.IsFaulted);
                    Assert.True(execTask.IsCanceled);
                    watch.Stop();
                    var elapsedSeconds = watch.ElapsedMilliseconds / 1000;
                    //if cancellation fails, then execution time is more than 10 seconds
                    Assert.True(elapsedSeconds < SecondsToRun / 2, $"cancellation failed, because task took too long to run. {elapsedSeconds}");
                }
        }
コード例 #3
0
        public async void TestSelfUpdateAsync_ValidateHash()
        {
            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());

                _runnerServer.Setup(x => x.GetPackageAsync("agent", BuildConstants.RunnerPackage.PackageName, "2.299.0", true, It.IsAny <CancellationToken>()))
                .Returns(Task.FromResult(new PackageMetadata()
                {
                    Platform = BuildConstants.RunnerPackage.PackageName, Version = new PackageVersion("2.299.0"), DownloadUrl = _packageUrl, HashValue = "bad_hash"
                }));

                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()));


                var ex = await Assert.ThrowsAsync <Exception>(() => updater.SelfUpdate(_refreshMessage, _jobDispatcher.Object, true, hc.RunnerShutdownToken));

                Assert.Contains("did not match expected Runner Hash", ex.Message);
            }
        }
コード例 #4
0
        public async Task EnableWorkerCommandsByDefault()
        {
            using (TestHostContext hc = new TestHostContext(this))
            {
                Tracing trace = hc.GetTrace();

                Int32         exitCode = -1;
                List <string> stdout   = new List <string>();

                var processInvoker = new ProcessInvokerWrapper();
                processInvoker.OutputDataReceived += (object sender, ProcessDataReceivedEventArgs e) =>
                {
                    stdout.Add(e.Data);
                };
                processInvoker.Initialize(hc);
                exitCode = (TestUtil.IsWindows())
                    ? await processInvoker.ExecuteAsync("", "powershell.exe", $@"-NoLogo -Sta -NoProfile -NonInteractive -ExecutionPolicy Unrestricted -Command ""Write-Host '##vso somecommand'""", null, CancellationToken.None)
                    : await processInvoker.ExecuteAsync("", "bash", "-c \"echo '##vso somecommand'\"", null, CancellationToken.None);

                trace.Info("Exit Code: {0}", exitCode);
                Assert.Equal(0, exitCode);

                Assert.True(stdout.Contains("##vso somecommand"), "##vso commands should not be escaped.");
            }
        }
コード例 #5
0
ファイル: ProcessInvokerL0.cs プロジェクト: hraverkar/runner
        public async Task RedirectSTDINKeepStreamOpen()
        {
            using (TestHostContext hc = new TestHostContext(this))
            {
                Tracing trace = hc.GetTrace();
                CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
                Int32            exitCode      = -1;
                Channel <string> redirectSTDIN = Channel.CreateUnbounded <string>(new UnboundedChannelOptions()
                {
                    SingleReader = true, SingleWriter = true
                });
                List <string> stdout = new List <string>();
                redirectSTDIN.Writer.TryWrite("Single line of STDIN");

                var processInvoker = new ProcessInvokerWrapper();
                processInvoker.OutputDataReceived += (object sender, ProcessDataReceivedEventArgs e) =>
                {
                    stdout.Add(e.Data);
                };

                processInvoker.Initialize(hc);
#if OS_WINDOWS
                var proc = processInvoker.ExecuteAsync("", "cmd.exe", "/c more", null, false, null, false, redirectSTDIN, false, true, cancellationTokenSource.Token);
#else
                var proc = processInvoker.ExecuteAsync("", "bash", "-c \"read input; echo $input; read input; echo $input; read input; echo $input;\"", null, false, null, false, redirectSTDIN, false, true, cancellationTokenSource.Token);
#endif
                redirectSTDIN.Writer.TryWrite("More line of STDIN");
                redirectSTDIN.Writer.TryWrite("More line of STDIN");
                await Task.Delay(100);

                redirectSTDIN.Writer.TryWrite("More line of STDIN");
                redirectSTDIN.Writer.TryWrite("More line of STDIN");
                await Task.Delay(100);

                redirectSTDIN.Writer.TryWrite("More line of STDIN");
                cancellationTokenSource.CancelAfter(100);

                try
                {
                    exitCode = await proc;
                    trace.Info("Exit Code: {0}", exitCode);
                }
                catch (Exception ex)
                {
                    trace.Error(ex);
                }

                trace.Info("STDOUT: {0}", string.Join(Environment.NewLine, stdout));
                Assert.True(stdout.Contains("More line of STDIN"), "STDIN should keep open and accept more inputs after first input line.");
            }
        }
コード例 #6
0
        public async Task RedirectSTDINCloseStream()
        {
            using (TestHostContext hc = new TestHostContext(this))
                using (var redirectSTDIN = new InputQueue <string>())
                {
                    Tracing       trace    = hc.GetTrace();
                    Int32         exitCode = -1;
                    List <string> stdout   = new List <string>();
                    redirectSTDIN.Enqueue("Single line of STDIN");

                    using (var cancellationTokenSource = new CancellationTokenSource())
                        using (var processInvoker = new ProcessInvokerWrapper())
                        {
                            processInvoker.OutputDataReceived += (object sender, ProcessDataReceivedEventArgs e) =>
                            {
                                stdout.Add(e.Data);
                            };

                            processInvoker.Initialize(hc);
                            var proc = (TestUtil.IsWindows())
                        ? processInvoker.ExecuteAsync("", "cmd.exe", "/c more", null, false, null, false, redirectSTDIN, false, false, cancellationTokenSource.Token)
                        : processInvoker.ExecuteAsync("", "bash", "-c \"read input; echo $input; read input; echo $input; read input; echo $input;\"", null, false, null, false, redirectSTDIN, false, false, cancellationTokenSource.Token);

                            redirectSTDIN.Enqueue("More line of STDIN");
                            redirectSTDIN.Enqueue("More line of STDIN");
                            await Task.Delay(100);

                            redirectSTDIN.Enqueue("More line of STDIN");
                            redirectSTDIN.Enqueue("More line of STDIN");
                            await Task.Delay(100);

                            redirectSTDIN.Enqueue("More line of STDIN");
                            cancellationTokenSource.CancelAfter(100);

                            try
                            {
                                exitCode = await proc;
                                trace.Info("Exit Code: {0}", exitCode);
                            }
                            catch (Exception ex)
                            {
                                trace.Error(ex);
                            }

                            trace.Info("STDOUT: {0}", string.Join(Environment.NewLine, stdout));
                            Assert.False(stdout.Contains("More line of STDIN"), "STDIN should be closed after first input line.");
                        }
                }
        }
コード例 #7
0
        public async Task TestCancel()
        {
            const int SecondsToRun = 20;

            using (TestHostContext hc = new TestHostContext(this))
                using (var tokenSource = new CancellationTokenSource())
                {
                    Tracing trace          = hc.GetTrace();
                    var     processInvoker = new ProcessInvokerWrapper();
                    processInvoker.Initialize(hc);
                    Stopwatch watch = Stopwatch.StartNew();
                    Task      execTask;
#if OS_WINDOWS
                    execTask = processInvoker.ExecuteAsync("", "cmd.exe", $"/c \"choice /T {SecondsToRun} /D y\"", null, tokenSource.Token);
#else
                    execTask = processInvoker.ExecuteAsync("", "bash", $"-c \"sleep {SecondsToRun}s\"", null, tokenSource.Token);
#endif
                    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 ARM
                    // if cancellation fails, then execution time is more than 15 seconds
                    // longer time to compensate for a slower ARM environment (e.g. Raspberry Pi)
                    long expectedSeconds = (SecondsToRun * 3) / 4;
#else
                    // if cancellation fails, then execution time is more than 10 seconds
                    long expectedSeconds = SecondsToRun / 2;
#endif

                    Assert.True(elapsedSeconds <= expectedSeconds, $"cancellation failed, because task took too long to run. {elapsedSeconds}");
                }
        }
コード例 #8
0
        public async Task SuccessExitsWithCodeZero()
        {
            using (TestHostContext hc = new TestHostContext(this))
            {
                Tracing trace = hc.GetTrace();

                Int32 exitCode       = -1;
                var   processInvoker = new ProcessInvokerWrapper();
                processInvoker.Initialize(hc);
                exitCode = (TestUtil.IsWindows())
                    ? await processInvoker.ExecuteAsync("", "cmd.exe", "/c \"dir >nul\"", null, CancellationToken.None)
                    : await processInvoker.ExecuteAsync("", "bash", "-c echo .", null, CancellationToken.None);

                trace.Info("Exit Code: {0}", exitCode);
                Assert.Equal(0, exitCode);
            }
        }
コード例 #9
0
        public async Task SetCIEnv()
        {
            using (TestHostContext hc = new TestHostContext(this))
            {
                var existingCI = Environment.GetEnvironmentVariable("CI");
                try
                {
                    // Clear out CI and make sure process invoker sets it.
                    Environment.SetEnvironmentVariable("CI", null);

                    Tracing trace = hc.GetTrace();

                    Int32 exitCode       = -1;
                    var   processInvoker = new ProcessInvokerWrapper();
                    processInvoker.Initialize(hc);
                    var stdout = new List <string>();
                    var stderr = new List <string>();
                    processInvoker.OutputDataReceived += (object sender, ProcessDataReceivedEventArgs e) =>
                    {
                        trace.Info(e.Data);
                        stdout.Add(e.Data);
                    };
                    processInvoker.ErrorDataReceived += (object sender, ProcessDataReceivedEventArgs e) =>
                    {
                        trace.Info(e.Data);
                        stderr.Add(e.Data);
                    };
#if OS_WINDOWS
                    exitCode = await processInvoker.ExecuteAsync("", "cmd.exe", "/c \"echo %CI%\"", null, CancellationToken.None);
#else
                    exitCode = await processInvoker.ExecuteAsync("", "bash", "-c \"echo $CI\"", null, CancellationToken.None);
#endif

                    trace.Info("Exit Code: {0}", exitCode);
                    Assert.Equal(0, exitCode);

                    Assert.Equal("true", stdout.First(x => !string.IsNullOrWhiteSpace(x)));
                }
                finally
                {
                    Environment.SetEnvironmentVariable("CI", existingCI);
                }
            }
        }
コード例 #10
0
        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);
#endif
#if (OS_OSX || OS_LINUX)
                exitCode = await processInvoker.ExecuteAsync("", "bash", "-c echo .", null, CancellationToken.None);
#endif

                trace.Info("Exit Code: {0}", exitCode);
                Assert.Equal(0, exitCode);
            }
        }
コード例 #11
0
        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 'ç'"));
            }
        }
コード例 #12
0
        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);
            }
        }
コード例 #13
0
        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}");
                    }
                }
        }
コード例 #14
0
        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);
                }
            }
        }