/// <summary> /// Bucketize and run through groups of matching support file needs. /// </summary> private static void ExecuteTestSupportFileGroups(ExecutionSettings settings, List <TestRecord> stateManagementGroup, ExecutionGroupRecord stateGroupRecord, int stateGroupIndex, ExecutionComponents components) { int supportFileGroupIndex = 0; //Bucketize // NOTE: Hash method for SupportFiles is order sensitive. IEnumerable <List <TestRecord> > testGroups = ExecutionGrouper.Bucketize( stateManagementGroup, ExecutionGroupingLevel.SharedSupportFiles, x => HashSupportFileGroup(x)); foreach (List <TestRecord> supportFileGroup in testGroups) { Stack <ICleanableCommand> filecleanupCommands = new Stack <ICleanableCommand>(); ExecutionGroupRecord supportFileGroupRecord = ExecutionGroupRecord.Begin(ExecutionGroupType.Files, stateGroupRecord.Area); stateGroupRecord.ExecutionGroupRecords.Add(supportFileGroupRecord); DirectoryInfo executionDirectory = settings.DetermineTestExecutionDirectory(settings.DetermineGroupPath(stateGroupIndex, supportFileGroupIndex)); DirectoryInfo logDirectory = settings.DetermineTestLogDirectory(settings.DetermineGroupPath(stateGroupIndex, supportFileGroupIndex)); PrepLogDirectory(logDirectory);//HACK: Ideally logging can guarantee this in final configuration. if (GetCachedExecutionResult(settings, supportFileGroup, logDirectory, components)) { ExecutionEventLog.RecordStatus("Successfully retrieved previously stored execution result. "); } else { ExecutionEventLog.RecordStatus("Applying Support Files and Executing."); ExecutionGroupLogCommand command = ExecutionGroupLogCommand.Apply("SupportFiles", logDirectory, components.LoggingMediator); filecleanupCommands.Push(command); filecleanupCommands.Push(DesktopSnapshotCommand.Apply(logDirectory)); // Create temporary directory, but if we are using a fixed test execution directory, don't delete it if it was pre-existing. filecleanupCommands.Push(TemporaryDirectoryCommand.Apply(executionDirectory, settings.FixedTestExecutionDirectory != null)); filecleanupCommands.Push(SupportFileCommand.Apply(supportFileGroup, settings.TestBinariesDirectory, executionDirectory)); filecleanupCommands.Push(BackupRecordsCommand.Apply(supportFileGroup, logDirectory)); filecleanupCommands.Push(ProcessLogsCommand.Apply(supportFileGroup, components.LoggingMediator)); try { ExecuteUniformTestGroup(settings, supportFileGroup, supportFileGroupRecord, stateGroupIndex, supportFileGroupIndex, components); } catch (Exception e) { ExecutionEventLog.RecordException(e); } finally { Cleanup(filecleanupCommands); } } supportFileGroupRecord.End(); supportFileGroupIndex++; } }
/// <summary> /// Executes Tests /// </summary> public static void Execute(ExecutionSettings settings) { Stack <ICleanableCommand> cleanupCommands = new Stack <ICleanableCommand>(); try { //Elevation Service is hitting Error #5 "Access Denied" in XP - We don't have run time dependencies on it right now, so disabling. //cleanupCommands.Push(ElevationServiceCommand.Apply(infraBinariesDirectory)); cleanupCommands.Push(LogDirectoryCommand.Apply(settings.LogFilesPath, settings.SkipDxDiag)); ExecutionComponents executionComponents = new ExecutionComponents(); executionComponents.DebuggingEngine = DebuggingEngineCommand.Apply(settings.InfraBinariesDirectory, settings.JitDebuggerCommand); cleanupCommands.Push(executionComponents.DebuggingEngine); ExecutionEventLog.RecordStatus("Creating LoggingMediator."); executionComponents.LoggingMediator = new LoggingMediator(settings.DebugTests); //Consider using dispose pattern. executionComponents.LoggingMediator.StartService(executionComponents.DebuggingEngine, settings.Tests.TestCollection.Count(record => record.ExecutionEnabled)); // cleanupCommands.Push(ExecutionGroupLogCommand.Apply("InfraExecution", settings.LogFilesPath, executionComponents.LoggingMediator)); if (settings.CodeCoverageEnabled) { cleanupCommands.Push(MergeCodeCoverageDataCommand.Apply(settings.LogFilesPath)); } cleanupCommands.Push(TemporaryDirectoryCommand.Apply(settings.ExecutionRootDirectory)); cleanupCommands.Push(MoveWindowCommand.Apply()); cleanupCommands.Push(ExecutionEventLog.Apply(settings.LogFilesPath, !settings.ContinueExecution)); try { ExecuteTestStateGroups(settings, executionComponents); } catch (Exception e) { ExecutionEventLog.RecordException(e); } finally { ExecutionEventLog.RecordStatus("Ending Test Sequence."); ExecutionEventLog.RecordStatus("Shutting down test logging system."); executionComponents.LoggingMediator.StopService(); } } finally { Cleanup(cleanupCommands); Console.WriteLine("Test Execution has finished.\n"); } }
static internal void LogFile(string filename) { LoggingServer service = LoggingServer.Instance; if (service != null) { service.LoggingNormalizer.LogFile(filename); } if (!hasTests && executionLoggers.Count > 0) { ExecutionGroupLogCommand groupLogger = executionLoggers.Peek(); if (groupLogger != null) { groupLogger.LogFile(filename); } } }
/// <summary> /// Bucketize collection of tests by matching State management needs, and run through each group. /// Notion of Execution group + a tracking counter variable seem to be critical elements. /// This (and supportfiles one) can likely get generalized+factored well to the ExecutionGroup class with some thought. /// </summary> private static void ExecuteTestStateGroups(ExecutionSettings settings, ExecutionComponents executionComponents) { ExecutionEventLog.RecordStatus("Running Test Sequence."); List <TestRecord> enabledTests = new List <TestRecord>(settings.Tests.TestCollection.Where(test => (test.ExecutionEnabled == true))); int stateGroupIndex = 0; // NOTE: Hash method for Deployments is order sensitive. IEnumerable <List <TestRecord> > testGroups = ExecutionGrouper.Bucketize(enabledTests, ExecutionGroupingLevel.SharedStateManagement, x => x.TestInfo.Area + x.TestInfo.Deployments.ToCommaSeparatedList()); foreach (List <TestRecord> stateManagementGroup in testGroups) { ExecutionEventLog.RecordStatus("Running State Group # " + stateGroupIndex + " of " + testGroups.Count()); Stack <ICleanableCommand> stateCleanupCommands = new Stack <ICleanableCommand>(); ExecutionGroupRecord stateGroupRecord = ExecutionGroupRecord.Begin(ExecutionGroupType.State, stateManagementGroup[0].TestInfo.Area); try { settings.Tests.ExecutionGroupRecords.Add(stateGroupRecord); DirectoryInfo stateLogPath = settings.DetermineTestLogDirectory(settings.DetermineGroupPath(stateGroupIndex)); ExecutionGroupLogCommand command = ExecutionGroupLogCommand.Apply("StateManagement", stateLogPath, executionComponents.LoggingMediator); stateCleanupCommands.Push(command); stateCleanupCommands.Push(ExecutionStateCommand.Apply(stateManagementGroup.First(), settings.TestBinariesDirectory)); ExecuteTestSupportFileGroups(settings, stateManagementGroup, stateGroupRecord, stateGroupIndex, executionComponents); } catch (Exception e) { ExecutionEventLog.RecordException(e); } finally { Cleanup(stateCleanupCommands); stateGroupRecord.End(); stateGroupIndex++; } } }
/// <summary> /// Notifies Mediator to push a Logging subscriber onto the stack /// </summary> internal void PushListener(ExecutionGroupLogCommand command) { executionLoggers.Push(command); }