/// <summary> /// Removes the cached runner for the specified run and configuration. /// </summary> /// <param name="run">The run.</param> /// <param name="configurationSubstitutions">The configuration substitutions.</param> public void Remove(TestRun run, DistributedConfigurationSubstitutions configurationSubstitutions = null) { ConcurrentDictionary<int, TestRunnerMetadata> byParametersCache; if (configurationSubstitutions == null ? cache.TryRemove(GetKey(run), out byParametersCache) : cache.TryGetValue(GetKey(run), out byParametersCache)) { IEnumerable<TestRunnerMetadata> toFree = new TestRunnerMetadata[0]; if (configurationSubstitutions != null) { TestRunnerMetadata metadata; if (byParametersCache.TryRemove(GetKeyForSubstitutions(configurationSubstitutions), out metadata)) { toFree = new[] { metadata }; } } else toFree = byParametersCache.Values; foreach (var metadata in toFree) { metadata.Runner.Unload(); metadata.Runner.Dispose(); } } }
/// <summary> /// Removes the specified request. /// </summary> /// <param name="testRun"></param> public TestRunRequest GetBy(TestRun testRun) { TestRunRequest value; if (!requests.TryGetValue(testRun.Id, out value)) return null; return value; }
/// <summary> /// Gets the completed result. /// </summary> /// <param name="testRun">The run.</param> /// <returns></returns> public TestResult GetCompletedResult(TestRun testRun) { RunResultsCollection result; results.TryGetValue(testRun.Id, out result); if (result != null) return null; // the run has not completed yet var locker = GetLocker(testRun); try { locker.EnterReadLock(); var binaryFile = GetBinaryFileName(testRun); if (!File.Exists(binaryFile)) return null; return serializer.ReadBinary(new FileStream(binaryFile, FileMode.Open, FileAccess.Read)); } finally { locker.ExitReadLock(); } }
/// <summary> /// Initializes a new instance of the <see cref="TestUnitWithMetadata"/> class. /// </summary> /// <param name="testRun">The test run.</param> /// <param name="test"></param> /// <param name="assemblyName">Name of the assembly.</param> /// <param name="children">The children.</param> public TestUnitWithMetadata(TestRun testRun, ITest test, string assemblyName, List<TestUnitWithMetadata> children = null) { Children = children ?? new List<TestUnitWithMetadata>(); Test = new TestUnit(test, testRun, assemblyName); Results = new List<TestResult>(); AttachedData = new TestUnitAttachedData(); }
/// <summary> /// Gets the or load. /// </summary> /// <param name="testRun">The test run.</param> /// <param name="substitutions"></param> /// <param name="loadRunner">The action.</param> /// <returns></returns> public NDistribUnitProcessRunner GetOrLoad(TestRun testRun, DistributedConfigurationSubstitutions substitutions, Func<NDistribUnitProcessRunner> loadRunner) { var key = GetKey(testRun); //var timeSpan = TimeSpan.FromHours(4); var cacheByParameters = cache.GetOrAdd(key, guid => new ConcurrentDictionary<int, TestRunnerMetadata>()); int hashCode = GetKeyForSubstitutions(substitutions); var metadata = cacheByParameters.GetOrAdd(hashCode, hash => { var runner = loadRunner(); // var timer = new Timer(obj=> // { // TestRunnerMetadata removed; // if (cacheByParameters.TryRemove(hashCode, out removed)) // removed.Runner.Unload(); // }, null, timeSpan, TimeSpan.FromMilliseconds(-1)); return new TestRunnerMetadata { Runner = runner, // Timer = timer }; }); // metadata.Timer.Change(timeSpan, TimeSpan.FromMilliseconds(-1)); return metadata.Runner; }
/// <summary> /// Initializes a new instance of the <see cref="TestRunRequest"/> class. /// </summary> /// <param name="testRun">The test run.</param> public TestRunRequest(TestRun testRun) { TestRun = testRun; RequestTime = DateTime.UtcNow; PipeToClient = new CrossThreadPipe<TestResult>(TimeSpan.FromSeconds(5), list => { for (int i = list.Count - 1; i > 0; i--) { new TestResultsProcessor().Merge(list[i], list[0]); } }); Statistics = new RequestStatistics(); }
/// <summary> /// Adds the request. /// </summary> /// <param name="testRun">The test run.</param> /// <returns></returns> public TestRunRequest AddOrUpdate(TestRun testRun) { var exists = true; var addedRequest = requests.GetOrAdd(testRun.Id, guid => { exists = false; return new TestRunRequest(testRun); }); if (!exists) { addedRequest.Status = TestRunRequestStatus.Received; Added.SafeInvoke(this, addedRequest); } //pingable.Add(addedRequest); return addedRequest; }
/// <summary> /// Unloads the specified test run. /// </summary> /// <param name="testRun">The test run.</param> public void Unload(TestRun testRun) { runnerCache.Remove(testRun); }
public bool HasProject(TestRun run) { throw new CommunicationException(); }
public TestUnitsFixture(TestRun testRun) { this.testRun = testRun; }
public void Init() { testRun = new TestRun { Parameters = new TestRunParameters { MaximumAgentsCount = 1000, SpecialHandlings = new List<TestRunFailureSpecialHandling>() } }; unitsFixture = new TestUnitsFixture(testRun); resultsfactory = new TestResultsFixture(); collectionMock = Substitute.For<ITestUnitsCollection>(); reprocessor = new TestReprocessor(collectionMock, new ConsoleLog(), null); }
/// <summary> /// Determines whether [is any available for] [the specified test run]. /// </summary> /// <param name="testRun">The test run.</param> /// <returns> /// <c>true</c> if [is any available for] [the specified test run]; otherwise, <c>false</c>. /// </returns> public bool IsAnyAvailableFor(TestRun testRun) { Func<TestUnitWithMetadata, bool> belongsToSameTestRun = t => t.Test.Run.Id.Equals(testRun.Id); return available.Any(belongsToSameTestRun) || running.Any(belongsToSameTestRun); }
/// <summary> /// Determines, whether the specified instance has a project for the given run. /// </summary> /// <param name="run">The run.</param> /// <returns> /// <c>true</c> if the specified instance has a project for the given run; otherwise, <c>false</c>. /// </returns> public bool HasProject(TestRun run) { log.BeginActivity(string.Format("Checking for project '{0}'...", run)); bool result = projects.HasProject(run); log.EndActivity(result ? "Project is available" : "Project was not found on server"); return result; }
/// <summary> /// Receives the project. /// </summary> /// <param name="run">The run.</param> /// <returns> /// <c>true</c> if the specified agent has a project for the given run; otherwise, <c>false</c>. /// </returns> public bool HasProject(TestRun run) { if (IsStarted) return TestRunner.HasProject(run); throw new CommunicationException("Agent seems to be not available"); }
private static void FindTestUnits(ITest test, ITestFilter filter, List<TestUnitWithMetadata> result, TestRun testRun, string assemblyName = null) { var assembly = test as TestAssembly; if (assembly != null) assemblyName = assembly.TestName.FullName; if (filter.Pass(test)) { var isTestSuiteWithAtLeastOneTestMethod = (test.IsSuite && test.Tests != null && test.Tests.Count != 0 && !((ITest) test.Tests[0]).IsSuite); if (!test.IsSuite || isTestSuiteWithAtLeastOneTestMethod) { List<TestUnitWithMetadata> subTests = null; if (test.IsSuite && test.Tests != null) { subTests = new List<TestUnitWithMetadata>(); foreach (ITest child in test.Tests) { FindTestUnits(child, filter, subTests, testRun, assemblyName); } } var testUnitWithMetadata = new TestUnitWithMetadata(testRun, test, assemblyName, subTests); result.Add(testUnitWithMetadata); } else if ((test.Tests != null && test.Tests.Count > 0)) { foreach (ITest child in test.Tests) { FindTestUnits(child, filter, result, testRun, assemblyName); } } } }
/// <summary> /// Stores the specified result. /// </summary> /// <param name="testRun">The test run.</param> /// <param name="mergedResult"></param> protected virtual void Store(TestRun testRun, TestResult mergedResult) { var folder = GetResultsStorageFolderName(testRun); if (!Directory.Exists(folder)) Directory.CreateDirectory(folder); var locker = GetLocker(testRun); try { locker.EnterWriteLock(); var xmlFile = GetXmlFileName(testRun); var xml = serializer.GetXml(mergedResult); var xmlStream = new StreamWriter(xmlFile, false); xmlStream.Write(xml); xmlStream.Close(); var binaryFile = GetBinaryFileName(testRun); var dataStream = new FileStream(binaryFile, FileMode.Create); serializer.WriteBinary(mergedResult, dataStream); dataStream.Close(); } finally { locker.ExitWriteLock(); } }
private RunResultsCollection GetCollection(TestRun testRun) { return results.GetOrAdd(testRun.Id, guid => { var runResultsCollection = new RunResultsCollection(processor, log); runResultsCollection.AllItemsMerged += (sender, args) => Store(testRun, args.Data); return runResultsCollection; }); }
/// <summary> /// Stores as completed. /// </summary> /// <param name="testRun">The test run.</param> /// <returns></returns> public TestResult StoreAsCompleted(TestRun testRun) { var resultsForTestRun = GetCollection(testRun); RunResultsCollection temp; results.TryRemove(testRun.Id, out temp); var result = resultsForTestRun.Close(); try { Store(testRun, resultsForTestRun.MergedResult); } catch (Exception ex) { log.Error("Exception while saving tests:", ex); } return result; }
/// <summary> /// Runs this instance. /// </summary> public int Run() { var server = connectionProvider.GetConnection<IServer>(new EndpointAddress(options.ServerUri)); testRun = new TestRun { NUnitParameters = options.NUnitParameters, Alias = options.Alias }; //TODO: load saved state here log.Info(string.Format("Test run was given the following unqiue identifier: '{0}'", testRun.Id)); if (options.NUnitParameters.AssembliesToTest == null || options.NUnitParameters.AssembliesToTest.Count != 1 /*|| !NUnitProject.IsNUnitProjectFile(options.AssembliesToTest[0])*/) throw new InvalidOperationException("Please specify single NUnit project file"); string parametersFileName = Path.ChangeExtension(options.NUnitParameters.AssembliesToTest[0], ".ndistribunit"); testRun.Parameters = File.Exists(parametersFileName) ? parametersReader.Read(parametersFileName) : TestRunParameters.Default; try { log.BeginActivity("Checking project existence on server..."); bool hasProject = server.HasProject(testRun); if (!hasProject) { log.EndActivity("Project is absent on server"); log.BeginActivity("Packaging project..."); Stream packageStream = packager.GetPackage(testRun.NUnitParameters.AssembliesToTest); log.EndActivity("Project packaging completed."); using (packageStream) { log.BeginActivity("Sending project to server..."); server.ReceiveProject(new ProjectMessage { Project = packageStream, TestRun = testRun }); log.EndActivity("Project was successfully sent to server"); } } else { log.EndActivity("Project is already on server"); } } catch (EndpointNotFoundException) { log.Error("It seems, that the server is not available"); //TODO: Save a failed test run here return (int) ReturnCodes.ServerNotAvailable; } catch (CommunicationException ex) { log.Error("There was an error, when trying to send the package to client", ex); //TODO: Save a failed test run here return (int) ReturnCodes.NetworkConnectivityError; } var testRunningTask = Task.Factory.StartNew( () => { try { log.BeginActivity("Started running tests..."); TestResult tempResult; while ((tempResult = server.RunTests(testRun)) != null) { if (tempResult.IsFinal()) { result = tempResult; log.Info("Running all tests completed!"); break; } if (result == null) result = tempResult; else resultsProcessor.Merge(tempResult, result); SaveResult(result); PrintSummaryInfoForResult(tempResult); } log.EndActivity("Finished running tests"); } catch (Exception ex) { log.Error("An error occurred while running tests", ex); } }); var updateTask = Task.Factory.StartNew( () => { try { log.BeginActivity("Checking for updates..."); var updatePackage = server.GetUpdatePackage( new UpdateRequest { Version = versionProvider.GetVersion() }); if (updatePackage.IsAvailable) { log.EndActivity("Update package available"); log.BeginActivity(string.Format("Receiving update to {0}...", updatePackage.Version)); updateReceiver.SaveUpdatePackage(updatePackage); log.EndActivity(string.Format("Update {0} was successfully received", updatePackage.Version)); } else log.EndActivity("No updates available."); } catch (Exception ex) { log.Warning("There was an exception when trying to get an update", ex); } }); try { Task.WaitAll(new[] {testRunningTask, updateTask}); } catch (AggregateException ex) { foreach (var innerException in ex.InnerExceptions) { log.Error("Error:", innerException); } throw; } catch (Exception ex) { log.Error("Error while running tests", ex); throw; } SaveResult(result); if (result == null) { log.Info("Result is not available. Maybe not all tests were run?"); return (int) ReturnCodes.NoTestsAvailable; } var summary = PrintSummaryInfoForResult(result, false); return summary.ErrorsAndFailures; }
public void ReleaseResources(TestRun testRun) { if (IsStarted) TestRunner.ReleaseResources(testRun); else throw new CommunicationException("Agent seems to be not available"); }
public void ReleaseResources(TestRun testRun) { throw new CommunicationException(); }
/// <summary> /// Initializes a new instance of the <see cref="TestUnit"/> class. /// </summary> /// <param name="test"></param> /// <param name="testRun">The test run.</param> /// <param name="assemblyName">Name of the assembly.</param> public TestUnit(ITest test, TestRun testRun, string assemblyName) { Run = testRun; AssemblyName = assemblyName; Info = new TestInfo(test); }
public IList<TestUnitWithMetadata> Get(TestPackage package, TestRun testRun) { new NUnitInitializer().Initialize(); var builder = new TestSuiteBuilder(); TestSuite testSuite = builder.Build(package); var filter = new NUnitTestsFilter(testRun.NUnitParameters.IncludeCategories, testRun.NUnitParameters.ExcludeCategories, testRun.NUnitParameters.TestToRun); return ToTestUnitList(testSuite, filter, testRun); }
private string GetXmlFileName(TestRun testRun) { return Path.Combine(GetResultsStorageFolderName(testRun), string.Format("results.xml")); }
private IList<TestUnitWithMetadata> ToTestUnitList(ITest test, ITestFilter filter, TestRun testRun) { var result = new List<TestUnitWithMetadata>(); FindTestUnits(test, filter, result, testRun); return result; }
/// <summary> /// Adds the specified result. /// </summary> /// <param name="result">The result.</param> /// <param name="testRun"> </param> public void Add(TestResult result, TestRun testRun) { var resultsForTestRun = GetCollection(testRun); resultsForTestRun.AddUnmerged(result); }
private ReaderWriterLockSlim GetLocker(TestRun testRun) { return lockers.GetOrAdd(testRun.Id, guid => new ReaderWriterLockSlim()); }
/// <summary> /// Runs tests from client /// </summary> /// <param name="run"></param> public TestResult RunTests(TestRun run) { if (run == null) throw new ArgumentNullException("run"); TestRunRequest request; if ((request = requests.GetBy(run)) == null) { var result = resultsStorage.GetCompletedResult(run); if (result != null) return result.SetFinal(); } request = request ?? requests.AddOrUpdate(run); IList<TestResult> availableResults = request.PipeToClient.GetAvailableResults(); return availableResults == null ? null : availableResults[0]; }
private static string GetKey(TestRun testRun) { return /*string.IsNullOrEmpty(testRun.Alias) ?*/ testRun.Id.ToString() /*: testRun.Alias*/; }
private string GetResultsStorageFolderName(TestRun testRun) { //var now = DateTime.Now; //var dateFolderName = now.ToString("yyyy-MM-dd"); //var leafFolderName = PathUtilities.EscapeFileName(string.Format("{0}-{1}{2}", now.ToString("HH-mm-ss"), testRun.Id, !string.IsNullOrEmpty(testRun.Alias) ? "-"+testRun.Alias : string.Empty)); return Path.Combine(parameters.RootFolder, folderName, testRun.Id.ToString()/*dateFolderName, leafFolderName*/); }