private void RunProcess(ObservableProcess process, Action <LineOut> onLine = null)
        {
            var capturedLines       = new List <string>();
            ExceptionDispatchInfo e = null;

            process.SubscribeLines(line =>
            {
                capturedLines.Add(line.Line);
                onLine?.Invoke(line);
            },
                                   exception => e = ExceptionDispatchInfo.Capture(exception));

            var completed = process.WaitForCompletion(_defaultTimeout);

            if (!completed)
            {
                process.Dispose();
                throw new TerraformResourceException(
                          $"terraform {_resourceDirectory} timed out after {_defaultTimeout}", -1, capturedLines);
            }

            if (e != null)
            {
                throw new TerraformResourceException(
                          $"terraform {_resourceDirectory} did not succeed", e.SourceException);
            }

            if (process.ExitCode != 0)
            {
                throw new TerraformResourceException(
                          $"terraform {_resourceDirectory} did not succeed", process.ExitCode.Value, capturedLines);
            }
        }
Exemple #2
0
        public void SingleLine()
        {
            var seen    = new List <string>();
            var process = new ObservableProcess(TestCaseArguments(nameof(SingleLine)));

            process.SubscribeLines(c => seen.Add(c.Line), e => throw e);
            process.WaitForCompletion(WaitTimeout);

            seen.Should().NotBeEmpty().And.HaveCount(1, string.Join(Environment.NewLine, seen));
            seen[0].Should().Be(nameof(SingleLine));
        }
Exemple #3
0
        /// <summary>
        /// Starts the sample application and returns the <see cref="Uri" /> on which the application
        /// can be reached.
        /// </summary>
        /// <param name="targetFramework">
        /// The target framework under which to run the profiled app. Must be a version supported in
        /// the TargetFrameworks of the profiled app
        /// </param>
        /// <param name="timeout">A timeout to wait for the process to complete.</param>
        /// <param name="environmentVariables">
        /// The environment variables to start the sample app with. The profiler
        /// environment variables will be added.
        /// </param>
        /// <param name="msBuildProperties">
        ///	MsBuild properties passed to dotnet publish when compiling the sample app.
        /// Appended to dotnet publish with the form <code>-p:{key}={value}</code>
        /// </param>
        /// <param name="onNext">delegate to call when line is received</param>
        /// <param name="onException">delegate to call when exception occurs</param>
        /// <returns></returns>
        public void Start(
            string targetFramework,
            TimeSpan timeout,
            IDictionary <string, string> environmentVariables = null,
            IDictionary <string, string> msBuildProperties    = null,
            Action <LineOut> onNext        = null,
            Action <Exception> onException = null,
            bool doNotWaitForCompletion    = false,
            bool useLocalhostHttp5000      = false
            )
        {
            var properties       = CreateMsBuildProperties(msBuildProperties);
            var outputDirectory  = GetPublishOutputDirectory(targetFramework, properties);
            var workingDirectory = Path.Combine(_projectDirectory, _publishDirectory, outputDirectory);

            Publish(targetFramework, workingDirectory, properties);

            environmentVariables ??= new Dictionary <string, string>();
            environmentVariables["CORECLR_ENABLE_PROFILING"] = "1";
            environmentVariables["CORECLR_PROFILER"]         = ProfilerClassId;
            environmentVariables["CORECLR_PROFILER_PATH"]    = _profilerPath;

            environmentVariables["COR_ENABLE_PROFILING"] = "1";
            environmentVariables["COR_PROFILER"]         = ProfilerClassId;
            environmentVariables["COR_PROFILER_PATH"]    = _profilerPath;

            environmentVariables["ELASTIC_APM_PROFILER_HOME"] =
                Path.Combine(SolutionPaths.Root, "src", "Elastic.Apm.Profiler.Managed", "bin", "Release");
            environmentVariables["ELASTIC_APM_PROFILER_INTEGRATIONS"] =
                Path.Combine(SolutionPaths.Root, "src", "Elastic.Apm.Profiler.Managed", "integrations.yml");

            environmentVariables["ELASTIC_APM_PROFILER_LOG"] = "trace";
            // log to relative logs directory for managed loader
            environmentVariables["ELASTIC_APM_PROFILER_LOG_DIR"] = Path.Combine(SolutionPaths.Root, "logs");

            //environmentVariables["ELASTIC_APM_PROFILER_LOG_TARGETS"] = "file;stdout";
            //environmentVariables["ELASTIC_APM_PROFILER_LOG_IL"] = "true";

            // use the .exe for net461
            var arguments = targetFramework == "net461"
                                ? new StartArguments(Path.Combine(workingDirectory, $"{_projectName}.exe"))
                                : useLocalhostHttp5000 ? new StartArguments("dotnet", $"{_projectName}.dll", "--urls", "http://localhost:5000") : new StartArguments("dotnet", $"{_projectName}.dll");

            arguments.Environment      = environmentVariables;
            arguments.WorkingDirectory = workingDirectory;

            _process = new ObservableProcess(arguments);
            _process.SubscribeLines(onNext ?? (_ => { }), onException ?? (_ => { }));

            if (!doNotWaitForCompletion)
            {
                _process.WaitForCompletion(timeout);
            }
        }
Exemple #4
0
        public void DelayedWriter()
        {
            var seen         = new List <string>();
            var process      = new ObservableProcess(TestCaseArguments(nameof(DelayedWriter)));
            var subscription = process.SubscribeLines(c => seen.Add(c.Line));

            subscription.Dispose();
            process.WaitForCompletion(WaitTimeout);

            //disposing the subscription did not kill the process
            process.ExitCode.Should().Be(20);
            seen.Should().BeEmpty(string.Join(Environment.NewLine, seen));
        }
        public void SubscribeLinesSeesAllLines()
        {
            var args = TestCaseArguments("TrailingLines");
            var o    = new ObservableProcess(args);
            var seen = new List <LineOut>();

            o.SubscribeLines(l => seen.Add(l));
            o.WaitForCompletion(WaitTimeout);
            seen.Should().NotBeEmpty().And.HaveCount(_expected.Count(c => c == '\n'));
            for (var i = 0; i < seen.Count; i++)
            {
                seen[i].Line.Should().Be(_expectedLines[i], i.ToString());
            }
        }
Exemple #6
0
        public void SubscribeLinesSeesAllLines()
        {
            var args = TestCaseArguments("MoreText");
            var o    = new ObservableProcess(args);
            var seen = new List <LineOut>();

            o.SubscribeLines(l => seen.Add(l));
            o.WaitForCompletion(WaitTimeout);
            seen.Should().NotBeEmpty().And.HaveCount(_expectedLines.Length, string.Join("\r\n", seen.Select(s => s.Line)));
            for (var i = 0; i < seen.Count; i++)
            {
                seen[i].Line.Should().Be(_expectedLines[i], i.ToString());
            }
        }
Exemple #7
0
        public void DelayedWriterStopWaitToShort()
        {
            var seen = new List <string>();
            var args = TestCaseArguments(nameof(DelayedWriter));

            args.WaitForExit = TimeSpan.FromMilliseconds(200);
            var process = new ObservableProcess(args);

            process.SubscribeLines(c => seen.Add(c.Line));
            process.Dispose();

            process.ExitCode.Should().NotHaveValue();
            seen.Should().BeEmpty(string.Join(Environment.NewLine, seen));
        }
Exemple #8
0
        public void DelayedWriterRunsToCompletion()
        {
            var       seen         = new List <string>();
            Exception ex           = null;
            var       process      = new ObservableProcess(TestCaseArguments(nameof(DelayedWriter)));
            var       subscription = process.SubscribeLines(c => seen.Add(c.Line), e => ex = e);

            process.WaitForCompletion(WaitTimeout);

            process.ExitCode.Should().Be(20);
            ex.Should().BeNull();

            seen.Should().NotBeEmpty().And.HaveCount(1, string.Join(Environment.NewLine, seen));
            seen[0].Should().Be(nameof(DelayedWriter));
        }
Exemple #9
0
        public void DelayedWriterStopNoWaitDispose()
        {
            var seen = new List <string>();
            var args = TestCaseArguments(nameof(DelayedWriter));

            args.WaitForExit = null;             //never wait for exit
            var process = new ObservableProcess(args);

            process.SubscribeLines(c => seen.Add(c.Line));
            process.Dispose();

            //disposing the process itself will stop the underlying Process
            process.ExitCode.Should().NotHaveValue();
            seen.Should().BeEmpty(string.Join(Environment.NewLine, seen));
        }
Exemple #10
0
        public void ReadKeyFirst()
        {
            var seen    = new List <string>();
            var process = new ObservableProcess(TestCaseArguments(nameof(ReadKeyFirst)));

            process.ProcessStarted += (standardInput) =>
            {
                //this particular program does not output anything and expect user input immediatly
                //OnNext on the observable is only called on output so we need to write on the started event
                process.StandardInput.Write("y");
            };
            process.SubscribeLines(c => seen.Add(c.Line));
            process.WaitForCompletion(WaitTimeout);

            seen.Should().NotBeEmpty().And.HaveCount(1, string.Join(Environment.NewLine, seen));
            seen[0].Should().Be($"y{nameof(ReadKeyFirst)}");
        }
Exemple #11
0
        public static int Main()
        {
            var tessCase = TestBinary.TestCaseArguments("ControlC");
            var process  = new ObservableProcess(tessCase);

            process.SubscribeLines(c =>
            {
                //if (c.Line.EndsWith("4"))
                {
                    process.SendControlC();
                }
                Console.WriteLine(c.Line);
            }, e => Console.Error.WriteLine(e));

            process.WaitForCompletion(TimeSpan.FromSeconds(20));
            return(0);
        }
Exemple #12
0
        [SkipOnNonWindowsFact] public void ControlC()
        {
            var args = TestCaseArguments(nameof(ControlC));

            args.SendControlCFirst = true;

            var process = new ObservableProcess(args);
            var seen    = new List <string>();

            process.SubscribeLines(c =>
            {
                seen.Add(c.Line);
            });
            process.WaitForCompletion(TimeSpan.FromSeconds(1));

            seen.Should().NotBeEmpty().And.HaveCount(2, string.Join(Environment.NewLine, seen));
            seen[0].Should().Be("Written before control+c");
            seen[1].Should().Be("Written after control+c");
        }
Exemple #13
0
        public void ControlCNoWait()
        {
            var args = TestCaseArguments(nameof(ControlCNoWait));

            args.SendControlCFirst = true;

            var process = new ObservableProcess(args);

            var seen = new List <string>();

            process.SubscribeLines(c =>
            {
                seen.Add(c.Line);
            });
            process.WaitForCompletion(TimeSpan.FromSeconds(1));

            //process exits before its control c handler is invoked
            seen.Should().NotBeEmpty().And.HaveCount(1, string.Join(Environment.NewLine, seen));
            seen[0].Should().Be("Written before control+c");
        }
Exemple #14
0
        public void SlowOutput()
        {
            var       args                    = TestCaseArguments(nameof(SlowOutput));
            var       process                 = new ObservableProcess(args);
            var       consoleOut              = new List <LineOut>();
            Exception seenException           = null;
            bool?     readingBeforeCancelling = null;
            bool?     readingAfterCancelling  = null;

            process.SubscribeLines(c =>
            {
                consoleOut.Add(c);
                if (!c.Line.EndsWith("3"))
                {
                    return;
                }

                readingBeforeCancelling = process.IsActivelyReading;

                process.CancelAsyncReads();
                Task.Run(async() =>
                {
                    await Task.Delay(TimeSpan.FromSeconds(2));

                    readingAfterCancelling = process.IsActivelyReading;
                    process.StartAsyncReads();
                });
            }, e => seenException = e);

            process.WaitForCompletion(TimeSpan.FromSeconds(20));

            process.ExitCode.Should().HaveValue().And.Be(121);
            seenException.Should().BeNull();
            consoleOut.Should().NotBeEmpty()
            .And.Contain(l => l.Line.EndsWith("9"));

            readingBeforeCancelling.Should().HaveValue().And.BeTrue();
            readingAfterCancelling.Should().HaveValue().And.BeFalse();
        }
        /// <summary>
        /// Starts the sample application and returns the <see cref="Uri"/> on which the application
        /// can be reached.
        /// </summary>
        /// <param name="targetFramework">The target framework under which to run the sample app. Must be a version supported in the TargetFrameworks of the sample app</param>
        /// <param name="environmentVariables">The environment variables to start the sample app with. The DOTNET_STARTUP_HOOKS environment variable will be added.</param>
        /// <returns></returns>
        public Uri Start(string targetFramework, IDictionary <string, string> environmentVariables = null)
        {
            var projectDirectory = Path.Combine(SolutionPaths.Root, "sample", ElasticApmStartuphookSampleProjectName);

            Publish(projectDirectory, targetFramework);

            var startupHookAssembly = UnzipStartupHook();

            environmentVariables ??= new Dictionary <string, string>();
            environmentVariables["DOTNET_STARTUP_HOOKS"] = startupHookAssembly;

            var arguments = new StartArguments("dotnet", $"{ElasticApmStartuphookSampleProjectName}.dll")
            {
                WorkingDirectory  = Path.Combine(projectDirectory, _publishDirectory, targetFramework),
                SendControlCFirst = true,
                Environment       = environmentVariables
            };

            var startHandle         = new ManualResetEvent(false);
            ExceptionDispatchInfo e = null;
            Uri uri = null;

            var capturedLines = new List <string>();
            var endpointRegex = new Regex(@"\s*Now listening on:\s*(?<endpoint>http\:[^\s]*)");

            _process = new ObservableProcess(arguments);
            _process.SubscribeLines(
                line =>
            {
                capturedLines.Add(line.Line);
                var match = endpointRegex.Match(line.Line);
                if (match.Success)
                {
                    try
                    {
                        var endpoint = match.Groups["endpoint"].Value.Trim();
                        uri          = new Uri(endpoint);
                    }
                    catch (Exception exception)
                    {
                        e = ExceptionDispatchInfo.Capture(exception);
                    }

                    startHandle.Set();
                }
            },
                exception => e = ExceptionDispatchInfo.Capture(exception));

            var timeout   = TimeSpan.FromMinutes(2);
            var signalled = startHandle.WaitOne(timeout);

            if (!signalled)
            {
                throw new Exception($"Could not start sample application within timeout {timeout}: "
                                    + string.Join(Environment.NewLine, capturedLines));
            }

            _process.CancelAsyncReads();
            e?.Throw();

            return(uri);
        }