/// <summary> /// Initializes a new instance of the <see cref="EnvironmentState"/> class. /// </summary> /// <param name="testState">The current state of the test.</param> public EnvironmentState(TestExecutionState testState) { TestState = testState; }
/// <summary> /// Processes the given test step. /// </summary> /// <param name="test">The test step that should be processed.</param> /// <param name="environmentParameters">The collection that provides the parameters for the environment.</param> /// <returns>The state of the test after the test step has been executed.</returns> /// <exception cref="ArgumentNullException"> /// Thrown if <paramref name="test"/> is <see langword="null" />. /// </exception> /// <exception cref="ArgumentException"> /// Thrown if <paramref name="test"/> is not a <see cref="XCopyTestStep"/>. /// </exception> public override TestExecutionState Process(TestStep test, IEnumerable<InputParameter> environmentParameters) { { Lokad.Enforce.Argument(() => test); Lokad.Enforce.With<ArgumentException>( test is XCopyTestStep, Resources.Exceptions_Messages_InvalidTestStep); } var testStep = test as XCopyTestStep; if (!m_FileSystem.Directory.Exists(testStep.Destination)) { try { m_FileSystem.Directory.CreateDirectory(testStep.Destination); } catch (IOException) { var errorMessage = string.Format( CultureInfo.InvariantCulture, "Failed to create test directory at location: {0}", testStep.Destination); Diagnostics.Log(LevelToLog.Error, XCopyDeployConstants.LogPrefix, errorMessage); m_SectionBuilder.AddErrorMessage(errorMessage); return TestExecutionState.Failed; } } var directory = TestFileLocationFor(testStep.Order); m_CurrentState = TestExecutionState.Running; m_SectionBuilder.Initialize("X-copy installer."); try { try { var installerFiles = m_FileSystem.Directory.GetFiles(directory, "*.*", SearchOption.AllDirectories); foreach (var installerFile in installerFiles) { var relativePath = installerFile.Substring(directory.Length).TrimStart(Path.DirectorySeparatorChar); var destination = Path.Combine(testStep.Destination, relativePath); try { var destinationDirectory = Path.GetDirectoryName(destination); if (!m_FileSystem.Directory.Exists(destinationDirectory)) { m_FileSystem.Directory.CreateDirectory(destinationDirectory); } } catch (IOException e) { var errorMessage = string.Format( CultureInfo.CurrentCulture, "Failed to install {0}. Error while creating directory: {1}", installerFile, e); Diagnostics.Log(LevelToLog.Error, XCopyDeployConstants.LogPrefix, errorMessage); m_SectionBuilder.AddErrorMessage(errorMessage); m_CurrentState = TestExecutionState.Failed; break; } try { var copyInformation = string.Format( CultureInfo.InvariantCulture, "Copying from: {0}; To: {1}", installerFile, destination); Diagnostics.Log( LevelToLog.Debug, XCopyDeployConstants.LogPrefix, copyInformation); m_SectionBuilder.AddInformationMessage(copyInformation); m_FileSystem.File.Copy(installerFile, destination); } catch (IOException e) { var errorMessage = string.Format( CultureInfo.CurrentCulture, "Failed to install {0}. Error: {1}", installerFile, e); Diagnostics.Log(LevelToLog.Error, XCopyDeployConstants.LogPrefix, errorMessage); m_SectionBuilder.AddErrorMessage(errorMessage); m_CurrentState = TestExecutionState.Failed; break; } var informationMessage = string.Format( CultureInfo.CurrentCulture, "Installed: {0}.", installerFile); Diagnostics.Log(LevelToLog.Info, XCopyDeployConstants.LogPrefix, informationMessage); m_SectionBuilder.AddInformationMessage(informationMessage); } m_CurrentState = TestExecutionState.Passed; } finally { TransferReportFiles(m_SectionBuilder, testStep); } } finally { m_SectionBuilder.FinalizeAndStore(m_CurrentState == TestExecutionState.Passed); } return m_CurrentState; }
/// <summary> /// Runs a single test. /// </summary> /// <param name="executeCallback"> A callback which can execute a script and /// return <c>null</c> if it succeeded or an exception otherwise. </param> /// <param name="executionState"> Information about how the test is executed. </param> private void RunTest(Func<string, Exception> executeCallback, TestExecutionState executionState) { // Run the test script. Exception ex = executeCallback(executionState.Test.Script); if (ex == null) { if (executionState.Test.IsNegativeTest) { // The test succeeded but was expected to fail. Interlocked.Increment(ref this.failedTestCount); TestFinished(this, new TestEventArgs(TestRunStatus.Failed, executionState.Test, executionState.RunInStrictMode, new InvalidOperationException("Expected failure but the test succeeded."))); } else { // The test succeeded and was expected to succeed. Interlocked.Increment(ref this.successfulTestCount); TestFinished(this, new TestEventArgs(TestRunStatus.Success, executionState.Test, executionState.RunInStrictMode)); } } else if (ex is JavaScriptException) { if (executionState.Test.IsNegativeTest) { // The test was expected to fail. if (executionState.Test.NegativeErrorPattern == null) { // The test succeeded. Interlocked.Increment(ref this.successfulTestCount); TestFinished(this, new TestEventArgs(TestRunStatus.Success, executionState.Test, executionState.RunInStrictMode)); } else { // Check if the exception had the name we expected. var errorObject = ((JavaScriptException)ex).ErrorObject; if (errorObject is ObjectInstance && System.Text.RegularExpressions.Regex.IsMatch(TypeConverter.ToString(((ObjectInstance)errorObject)["name"]), executionState.Test.NegativeErrorPattern)) { // The test succeeded. Interlocked.Increment(ref this.successfulTestCount); TestFinished(this, new TestEventArgs(TestRunStatus.Success, executionState.Test, executionState.RunInStrictMode)); } else { // The type of error was wrong. Interlocked.Increment(ref this.failedTestCount); TestFinished(this, new TestEventArgs(TestRunStatus.Failed, executionState.Test, executionState.RunInStrictMode, ex)); } } } else { // The test shouldn't have thrown an exception. Interlocked.Increment(ref this.failedTestCount); TestFinished(this, new TestEventArgs(TestRunStatus.Failed, executionState.Test, executionState.RunInStrictMode, ex)); } } else { // .NET exceptions are always bad. Interlocked.Increment(ref this.failedTestCount); TestFinished(this, new TestEventArgs(TestRunStatus.Failed, executionState.Test, executionState.RunInStrictMode, ex)); } }
/// <summary> /// Runs a single test. /// </summary> /// <param name="executeCallback"> A callback which can execute a script and /// return <c>null</c> if it succeeded or an exception otherwise. </param> /// <param name="executionState"> Information about how the test is executed. </param> private void RunTest(Func <string, Exception> executeCallback, TestExecutionState executionState) { // Run the test script. Exception ex = executeCallback(executionState.Test.Script); if (ex == null) { if (executionState.Test.IsNegativeTest) { // The test succeeded but was expected to fail. Interlocked.Increment(ref this.failedTestCount); TestFinished(this, new TestEventArgs(TestRunStatus.Failed, executionState.Test, executionState.RunInStrictMode, new InvalidOperationException("Expected failure but the test succeeded."))); } else { // The test succeeded and was expected to succeed. Interlocked.Increment(ref this.successfulTestCount); TestFinished(this, new TestEventArgs(TestRunStatus.Success, executionState.Test, executionState.RunInStrictMode)); } } else if (ex is JavaScriptException) { if (executionState.Test.IsNegativeTest) { // The test was expected to fail. if (executionState.Test.NegativeErrorPattern == null) { // The test succeeded. Interlocked.Increment(ref this.successfulTestCount); TestFinished(this, new TestEventArgs(TestRunStatus.Success, executionState.Test, executionState.RunInStrictMode)); } else { // Check if the exception had the name we expected. var errorObject = ((JavaScriptException)ex).ErrorObject; if (errorObject is ObjectInstance && System.Text.RegularExpressions.Regex.IsMatch(TypeConverter.ToString(((ObjectInstance)errorObject)["name"]), executionState.Test.NegativeErrorPattern)) { // The test succeeded. Interlocked.Increment(ref this.successfulTestCount); TestFinished(this, new TestEventArgs(TestRunStatus.Success, executionState.Test, executionState.RunInStrictMode)); } else { // The type of error was wrong. Interlocked.Increment(ref this.failedTestCount); TestFinished(this, new TestEventArgs(TestRunStatus.Failed, executionState.Test, executionState.RunInStrictMode, ex)); } } } else { // The test shouldn't have thrown an exception. Interlocked.Increment(ref this.failedTestCount); TestFinished(this, new TestEventArgs(TestRunStatus.Failed, executionState.Test, executionState.RunInStrictMode, ex)); } } else { // .NET exceptions are always bad. Interlocked.Increment(ref this.failedTestCount); TestFinished(this, new TestEventArgs(TestRunStatus.Failed, executionState.Test, executionState.RunInStrictMode, ex)); } }
/// <summary> /// Processes the given test step. /// </summary> /// <param name="test">The test step that should be processed.</param> /// <param name="environmentParameters">The collection that provides the parameters for the environment.</param> /// <returns>The state of the test after the test step has been executed.</returns> /// <exception cref="ArgumentNullException"> /// Thrown if <paramref name="test"/> is <see langword="null" />. /// </exception> /// <exception cref="ArgumentException"> /// Thrown if <paramref name="test"/> is not a <see cref="ScriptExecuteTestStep"/>. /// </exception> public override TestExecutionState Process(TestStep test, IEnumerable<InputParameter> environmentParameters) { { Lokad.Enforce.Argument(() => test); Lokad.Enforce.With<ArgumentException>( test is ConsoleExecuteTestStep, Resources.Exceptions_Messages_InvalidTestStep); } var testStep = test as ConsoleExecuteTestStep; m_CurrentState = TestExecutionState.Running; m_SectionBuilder.Initialize("Application execution"); try { try { var parameters = testStep.Parameters .OrderBy(p => int.Parse(p.Key, CultureInfo.InvariantCulture)) .Select(p => p.Value) .ToList(); int returnCode = RunApplication(testStep.ExecutableFilePath, parameters); if (returnCode != 0) { var errorMessage = string.Format( CultureInfo.CurrentCulture, "Failed to execute {0} {1}.", m_FileSystem.Path.GetFileName(testStep.ExecutableFilePath), string.Join(" ", parameters)); Diagnostics.Log(LevelToLog.Error, ConsoleExecuteConstants.LogPrefix, errorMessage); m_SectionBuilder.AddErrorMessage(errorMessage); m_CurrentState = TestExecutionState.Failed; } else { var informationMessage = string.Format( CultureInfo.CurrentCulture, "Executed: {0} {1}.", m_FileSystem.Path.GetFileName(testStep.ExecutableFilePath), string.Join(" ", parameters)); Diagnostics.Log(LevelToLog.Info, ConsoleExecuteConstants.LogPrefix, informationMessage); m_SectionBuilder.AddInformationMessage(informationMessage); m_CurrentState = TestExecutionState.Passed; } } finally { TransferReportFiles(m_SectionBuilder, testStep); } } finally { m_SectionBuilder.FinalizeAndStore(m_CurrentState == TestExecutionState.Passed); } return m_CurrentState; }
private string CreateLogPath() { var tempPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); if (!Directory.Exists(tempPath)) { try { Directory.CreateDirectory(tempPath); } catch (IOException) { Diagnostics.Log( LevelToLog.Error, XCopyDeployConstants.LogPrefix, string.Format( CultureInfo.InvariantCulture, "Failed to create MSI log directory at location: {0}", tempPath)); m_CurrentState = TestExecutionState.Failed; } } return tempPath; }
/// <summary> /// Processes the given test step. /// </summary> /// <param name="test">The test step that should be processed.</param> /// <param name="environmentParameters">The collection that provides the parameters for the environment.</param> /// <returns>The state of the test after the test step has been executed.</returns> /// <exception cref="ArgumentNullException"> /// Thrown if <paramref name="test"/> is <see langword="null" />. /// </exception> /// <exception cref="ArgumentException"> /// Thrown if <paramref name="test"/> is not a <see cref="MsiInstallTestStep"/>. /// </exception> public override TestExecutionState Process(TestStep test, IEnumerable<InputParameter> environmentParameters) { { Lokad.Enforce.Argument(() => test); Lokad.Enforce.With<ArgumentException>( test is MsiInstallTestStep, Resources.Exceptions_Messages_InvalidTestStep); } m_CurrentState = TestExecutionState.Running; var testStep = test as MsiInstallTestStep; var directory = TestFileLocationFor(testStep.Order); var tempPath = CreateLogPath(); if (m_CurrentState != TestExecutionState.Running) { return m_CurrentState; } m_SectionBuilder.Initialize("MSI install"); try { var logFiles = new List<string>(); try { var installerFiles = m_FileSystem.Directory.GetFiles(directory, "*.msi", SearchOption.TopDirectoryOnly); if (!installerFiles.Any()) { const string noFilesFoundMessage = "No installer files found."; Diagnostics.Log(LevelToLog.Error, ScriptExecuteConstants.LogPrefix, noFilesFoundMessage); m_SectionBuilder.AddErrorMessage(noFilesFoundMessage); m_CurrentState = TestExecutionState.Failed; } foreach (var installerFile in installerFiles) { // Log everything to the default log file. var logFile = Path.Combine(tempPath, Path.GetFileNameWithoutExtension(installerFile) + ".log"); logFiles.Add(logFile); var arguments = new List<string> { QuietSwitch, string.Format(CultureInfo.InvariantCulture, LogSwitch, logFile), string.Format(CultureInfo.InvariantCulture, InstallSwitch, installerFile), }; var environmentTestStepParameters = environmentParameters.Select( e => new TestStepParameter { Key = e.Key, Value = e.Value }); foreach (var parameterSet in testStep.Parameters.Concat(environmentTestStepParameters)) { var parameterInfo = string.Format( CultureInfo.InvariantCulture, "Adding installer parameter {0} with value {1}", parameterSet.Key, parameterSet.Value); Diagnostics.Log(LevelToLog.Debug, MsiDeployConstants.LogPrefix, parameterInfo); m_SectionBuilder.AddInformationMessage(parameterInfo); arguments.Add( string.Format( CultureInfo.InvariantCulture, ParameterSwitch, parameterSet.Key, parameterSet.Value)); } int returnCode = RunInstaller(arguments, installerFile); if (returnCode != 0) { var errorMessage = string.Format( CultureInfo.CurrentCulture, "Failed to install {0}.", installerFile); Diagnostics.Log(LevelToLog.Error, MsiDeployConstants.LogPrefix, errorMessage); m_SectionBuilder.AddErrorMessage(errorMessage); m_CurrentState = TestExecutionState.Failed; } else { var informationMessage = string.Format( CultureInfo.CurrentCulture, "Installed: {0}.", installerFile); Diagnostics.Log(LevelToLog.Info, MsiDeployConstants.LogPrefix, informationMessage); m_SectionBuilder.AddInformationMessage(informationMessage); m_CurrentState = TestExecutionState.Passed; } } } finally { TransferReportFiles( m_SectionBuilder, testStep, testStep.ReportIncludesSystemLog ? logFiles : null); } } finally { m_SectionBuilder.FinalizeAndStore(m_CurrentState == TestExecutionState.Passed); } return m_CurrentState; }
/// <summary> /// Processes the given test step. /// </summary> /// <param name="test">The test step that should be processed.</param> /// <param name="environmentParameters">The collection that provides the parameters for the environment.</param> /// <returns>The state of the test after the test step has been executed.</returns> /// <exception cref="ArgumentNullException"> /// Thrown if <paramref name="test"/> is <see langword="null" />. /// </exception> /// <exception cref="ArgumentException"> /// Thrown if <paramref name="test"/> is not a <see cref="ScriptExecuteTestStep"/>. /// </exception> public override TestExecutionState Process(TestStep test, IEnumerable<InputParameter> environmentParameters) { { Lokad.Enforce.Argument(() => test); Lokad.Enforce.With<ArgumentException>( test is ScriptExecuteTestStep, Resources.Exceptions_Messages_InvalidTestStep); } var testStep = test as ScriptExecuteTestStep; var directory = TestFileLocationFor(testStep.Order); m_CurrentState = TestExecutionState.Running; m_SectionBuilder.Initialize("Script execution"); try { try { var logText = string.Format( CultureInfo.InvariantCulture, "Executing script of type: {0}", testStep.ScriptLanguage); Diagnostics.Log( LevelToLog.Debug, ScriptExecuteConstants.LogPrefix, logText); m_SectionBuilder.AddInformationMessage(logText); switch (testStep.ScriptLanguage) { case ScriptLanguage.Powershell: m_CurrentState = ProcessPowershellScript(testStep, environmentParameters, directory); break; default: Diagnostics.Log( LevelToLog.Error, ScriptExecuteConstants.LogPrefix, string.Format( CultureInfo.InvariantCulture, "Unknown script language: {0}", testStep.ScriptLanguage)); m_SectionBuilder.AddErrorMessage("Unknown test script language."); m_CurrentState = TestExecutionState.Failed; break; } } finally { TransferReportFiles(m_SectionBuilder, testStep); } } catch (Exception e) { var errorMessage = string.Format( CultureInfo.CurrentCulture, "Failed to run script. Error: {0}", e); Diagnostics.Log(LevelToLog.Error, ScriptExecuteConstants.LogPrefix, errorMessage); m_SectionBuilder.AddErrorMessage(errorMessage); m_CurrentState = TestExecutionState.Failed; } finally { m_SectionBuilder.FinalizeAndStore(m_CurrentState == TestExecutionState.Passed); } return m_CurrentState; }