Example #1
0
        /// <inheritdoc />
        public async Task <BoolResult> StartupAsync(Context context)
        {
            StartupStarted = true;
            BoolResult result = BoolResult.Success;

            context.Debug("Starting service process");

            await Task.Run(() =>
            {
                AbsolutePath appExeDirPath = new AbsolutePath(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
                var appExePath             = appExeDirPath / (OperatingSystemHelper.IsUnixOS ? "ContentStoreApp" : "ContentStoreApp.exe");

                _args = _configuration.GetCommandLineArgs(scenario: _scenario);

                context.Debug($"Running cmd=[{appExePath} {_args}]");

                const bool CreateNoWindow = true;
                _process = new ProcessUtility(appExePath.Path, _args, CreateNoWindow);

                _process.Start();

                string processOutput;
                if (_process == null)
                {
                    processOutput = "[Process could not start]";
                    result        = new BoolResult(processOutput);
                }
                else if (CreateNoWindow)
                {
                    if (_process.HasExited)
                    {
                        if (_process.WaitForExit(5000))
                        {
                            throw new InvalidOperationException(_process.GetLogs());
                        }
                        else
                        {
                            throw new InvalidOperationException("Process or either wait handle timed out. " + _process.GetLogs());
                        }
                    }
                    else
                    {
                        processOutput = $"[Process {_process.Id} is still running]";
                    }
                }

                context.Debug("Process output: " + processOutput);
            });

            if (result.Succeeded && !LocalContentServer.EnsureRunning(context, _scenario, _waitForServerReadyTimeoutMs))
            {
                result = new BoolResult($"Failed to detect server ready in separate process for scenario {_scenario}. Process has {(_process.HasExited ? string.Empty : "not")} exited.");
            }

            StartupCompleted = true;
            return(result);
        }
Example #2
0
 /// <summary>
 /// <see cref="ProcessUtility.GetLogs"/>
 /// </summary>
 public string?GetLogs()
 {
     return(_process?.GetLogs());
 }
Example #3
0
        private void StartRedisServerIfNeeded()
        {
            // Can reuse an existing process only when this instance successfully created a connection to it.
            // Otherwise the test will fail with NRE.
            if (_process != null && _connectionMultiplexer != null)
            {
                _logger.Debug("Redis process is already running. Reusing an existing instance.");
                return;
            }

            _logger.Debug("Starting a redis server.");

            var    redisName       = OperatingSystemHelper.IsWindowsOS ? "redis-server.exe" : "redis-server";
            string redisServerPath = Path.GetFullPath(Path.Combine("redisServer", redisName));

            if (!File.Exists(redisServerPath))
            {
                throw new InvalidOperationException($"Could not find {redisName} at {redisServerPath}");
            }

            int portNumber = 0;

            const int maxRetries = 10;

            for (int i = 0; i < maxRetries; i++)
            {
                var fileName            = _tempDirectory.CreateRandomFileName();
                var redisServerLogsPath = _tempDirectory.CreateRandomFileName();
                _fileSystem.CreateDirectory(redisServerLogsPath);
                portNumber = PortExtensions.GetNextAvailablePort();
                string newConfig = $@"
timeout 0
tcp-keepalive 0
dir {redisServerLogsPath}
port {portNumber}";

                File.WriteAllText(fileName.Path, newConfig);

                var args = $" {fileName}";
                _logger.Debug($"Running cmd=[{redisServerPath} {args}]");

                const bool createNoWindow = true;
                _process = new ProcessUtility(redisServerPath, args, createNoWindow, workingDirectory: Path.GetDirectoryName(redisServerPath));

                _process.Start();

                string processOutput;
                if (_process == null)
                {
                    processOutput = "[Process could not start]";
                    throw new InvalidOperationException(processOutput);
                }

                if (createNoWindow)
                {
                    if (_process.HasExited)
                    {
                        if (_process.WaitForExit(5000))
                        {
                            throw new InvalidOperationException(_process.GetLogs());
                        }

                        throw new InvalidOperationException("Process or either wait handle timed out. " + _process.GetLogs());
                    }

                    processOutput = $"[Process {_process.Id} is still running]";
                }

                _logger.Debug("Process output: " + processOutput);

                ConnectionString = $"localhost:{portNumber}";
                ConfigurationOptions options = ConfigurationOptions.Parse(ConnectionString);
                options.ConnectTimeout = 2000;
                options.SyncTimeout    = 2000;
                try
                {
                    _connectionMultiplexer = ConnectionMultiplexer.Connect(options);
                    break;
                }
                catch (RedisConnectionException ex)
                {
                    SafeKillProcess();
                    _logger.Debug($"Retrying for exception connecting to redis process {_process.Id} with port {portNumber}: {ex.ToString()}. Has process exited {_process.HasExited} with output {_process.GetLogs()}");

                    if (i != maxRetries - 1)
                    {
                        Thread.Sleep(300);
                    }
                    else
                    {
                        throw;
                    }
                }
                catch (Exception ex)
                {
                    SafeKillProcess();
                    _logger.Error(
                        $"Exception connecting to redis process {_process.Id} with port {portNumber}: {ex.ToString()}. Has process exited {_process.HasExited} with output {_process.GetLogs()}");
                    throw;
                }
            }

            _logger.Debug($"Redis server {_process.Id} is up and running at port {portNumber}.");
        }
        private void Start()
        {
            // Can reuse an existing process only when this instance successfully created a connection to it.
            // Otherwise the test will fail with NRE.
            if (_process != null)
            {
                _logger.Debug("Storage process is already running. Reusing an existing instance.");
                return;
            }

            _logger.Debug("Starting a storage server.");


            var storageName = (OperatingSystemHelper.IsWindowsOS ? "tools/win-x64/blob.exe"
                : (OperatingSystemHelper.IsLinuxOS ? "tools/linux-x64/blob"
                : "tools/osx-x64/blob"));
            string storageServerPath = Path.GetFullPath(Path.Combine("azurite", storageName));

            if (!File.Exists(storageServerPath))
            {
                throw new InvalidOperationException($"Could not find {storageName} at {storageServerPath}");
            }

            _portNumber = 0;

            const int maxRetries = 10;

            for (int i = 0; i < maxRetries; i++)
            {
                var storageServerWorkspacePath = _tempDirectory.CreateRandomFileName();
                _fileSystem.CreateDirectory(storageServerWorkspacePath);
                _portNumber = PortExtensions.GetNextAvailablePort();

                var args = $"--blobPort {_portNumber} --location {storageServerWorkspacePath}";
                _logger.Debug($"Running cmd=[{storageServerPath} {args}]");

                _process = new ProcessUtility(storageServerPath, args, createNoWindow: true, workingDirectory: Path.GetDirectoryName(storageServerPath));

                _process.Start();

                string processOutput;
                if (_process == null)
                {
                    processOutput = "[Process could not start]";
                    throw new InvalidOperationException(processOutput);
                }

                if (_process.HasExited)
                {
                    if (_process.WaitForExit(5000))
                    {
                        throw new InvalidOperationException(_process.GetLogs());
                    }

                    throw new InvalidOperationException("Process or either wait handle timed out. " + _process.GetLogs());
                }

                processOutput = $"[Process {_process.Id} is still running]";

                _logger.Debug("Process output: " + processOutput);

                ConnectionString = $"DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://127.0.0.1:{_portNumber}/devstoreaccount1;";

                AzureBlobStorageCredentials creds = new AzureBlobStorageCredentials(ConnectionString);

                var client = creds.CreateCloudBlobClient();
                try
                {
                    bool exists = client.GetContainerReference("test").ExistsAsync(DefaultBlobStorageRequestOptions, null).GetAwaiter().GetResult();
                    break;
                }
                catch (StorageException ex)
                {
                    SafeKillProcess();
                    _logger.Debug($"Retrying for exception connecting to storage process {_process.Id} with port {_portNumber}: {ex.ToString()}. Has process exited {_process.HasExited} with output {_process.GetLogs()}");

                    if (i != maxRetries - 1)
                    {
                        Thread.Sleep(300);
                    }
                    else
                    {
                        throw;
                    }
                }
                catch (Exception ex)
                {
                    SafeKillProcess();
                    _logger.Error(
                        $"Exception connecting to storage process {_process.Id} with port {_portNumber}: {ex.ToString()}. Has process exited {_process.HasExited} with output {_process.GetLogs()}");
                    throw;
                }
            }

            _logger.Debug($"Storage server {_process.Id} is up and running at port {_portNumber}.");
        }
        /// <nodoc />
        public void Dispose(bool close)
        {
            if (close)
            {
                // Closing the instance and not returning it back to the pool.
                Close();
                return;
            }

            if (_disposed)
            {
                // The type should be safe for double dispose.
                return;
            }

            try
            {
                // Clear the containers in the storage account to allow reuse
                ClearAsync().GetAwaiter().GetResult();
            }
            catch (Exception ex)
            {
                _logger.Error(
                    $"Exception connecting to clear storage process {_process.Id} with port {_portNumber}: {ex.ToString()}. Has process exited {_process.HasExited} with output {_process.GetLogs()}");
                Close();
            }

            _logger.Debug($"Returning database to pool in fixture '{_storageFixture.Id}'");
            _storageFixture.EmulatorPool.PutInstance(this);
            _disposed = true;
        }