/// <summary> /// After a project is loaded or unloaded either add or remove from the file watcher /// all test potential items inside that project /// </summary> private void UpdateTestContainersAndFileWatchers(IEnumerable <TestFileCandidate> files, bool isAdd) { ChutzpahTracer.TraceInformation("Begin UpdateTestContainersAndFileWatchers"); Parallel.ForEach(files, file => { try { if (isAdd) { ChutzpahTracer.TraceInformation("Adding watch on {0}", file.Path); testFilesUpdateWatcher.AddWatch(file.Path); AddTestContainerIfTestFile(file); } else { ChutzpahTracer.TraceInformation("Removing watch on {0}", file.Path); testFilesUpdateWatcher.RemoveWatch(file.Path); RemoveTestContainer(file); } } catch (Exception e) { ChutzpahTracer.TraceError(e, "Failed in UpdateTestContainersAndFileWatchers"); } }); ChutzpahTracer.TraceInformation("End UpdateTestContainersAndFileWatchers"); }
private string GetOutputPath(string filePath, BatchCompileConfiguration compileConfiguration) { foreach (var pathMap in compileConfiguration.Paths) { if (filePath.IndexOf(pathMap.SourcePath, StringComparison.OrdinalIgnoreCase) >= 0) { // If the configured sourcePath is a full file path we just assume the fileName is the relative name // Otherwise we calculate the relative path from the configured sourcePath to the current file var relativePath = pathMap.SourcePathIsFile ? Path.GetFileName(pathMap.SourcePath) : FileProbe.GetRelativePath(pathMap.SourcePath, filePath); string outputPath = pathMap.OutputPath; if (!pathMap.OutputPathIsFile) { // If output path is not a file we calculate the file path using the input filePath's relative location compared // to the output directory outputPath = Path.Combine(outputPath, relativePath); outputPath = Path.ChangeExtension(outputPath, ".js"); } return(outputPath); } } ChutzpahTracer.TraceError("Can't find location for generated path on {0}", filePath); return(null); }
private ChutzpahWebServerHost BuildHost(string rootPath, int defaultPort, string builtInDependencyFolder) { var attemptLimit = Constants.WebServerCreationAttemptLimit; var success = false; do { // We can try multiple times to build the webserver. The reason is there is a possible race condition where // between when we find a free port and when we start the server that port may have been taken. To mitigate this we // can retry to hopefully avoid this issue. attemptLimit--; var port = FindFreePort(defaultPort); try { ChutzpahTracer.TraceInformation("Creating Web Server Host at path {0} and port {1}", rootPath, port); var host = new WebHostBuilder() .UseUrls($"http://localhost:{port}") .UseContentRoot(rootPath) .UseWebRoot("") .UseKestrel() .Configure((app) => { var env = (IHostingEnvironment)app.ApplicationServices.GetService(typeof(IHostingEnvironment)); app.UseStaticFiles(new StaticFileOptions { OnPrepareResponse = AddFileCacheHeaders, ServeUnknownFileTypes = true, FileProvider = new ChutzpahServerFileProvider(env.ContentRootPath, builtInDependencyFolder) }); app.Run(async(context) => { if (context.Request.Path == "/") { await context.Response.WriteAsync($"Chutzpah Web Server (Version { Assembly.GetEntryAssembly().GetName().Version})"); } else { context.Response.StatusCode = (int)HttpStatusCode.NotFound; } }); }) .Build(); host.Start(); success = true; return(ChutzpahWebServerHost.Create(host, rootPath, port)); } catch (Exception ex) when(attemptLimit > 0) { ChutzpahTracer.TraceError(ex, "Unable to create web server host at path {0} and port {1}. Trying again...", rootPath, port); } }while (!success && attemptLimit > 0); throw new ChutzpahException("Failed to create web server. This should never be hit!"); }
public void Dispose() { try { ChutzpahTracer.TraceInformation("Tearing down Web Server Host at path {0} and port {1}", RootPath, Port); IsRunning = false; WebHost.Dispose(); } catch (Exception e) { ChutzpahTracer.TraceError(e, "Error tearing down Web Server Host at path {0} and port {1}", RootPath, Port); } }
private bool IsTestFile(string path) { try { return(HasTestFileExtension(path) && testRunner.IsTestFile(path, settingsMapper.Settings.ChutzpahSettingsFileEnvironmentsWrapper)); } catch (Exception e) { ChutzpahTracer.TraceError(e, "ChutzpahTestContainerDiscoverer::Error when detecting a test file"); logger.Log("Error when detecting a test file", "ChutzpahTestContainerDiscoverer", e); } return(false); }
private void SerializeObject(string name, ConcurrentDictionary <string, Tuple <DateTime, string> > objectToSerialize) { try { using (var stream = filesystem.Open(name, FileMode.Create, FileAccess.Write)) { binarySerializer.Serialize(stream, objectToSerialize); } } catch (IOException e) { ChutzpahTracer.TraceError(e, "Failed to save compiler cache"); } }
private void RunBatchCompile(ChutzpahTestSettingsFile testSettings) { try { var result = processHelper.RunBatchCompileProcess(testSettings.Compile); if (result.ExitCode > 0) { throw new ChutzpahCompilationFailedException(result.StandardError, testSettings.SettingsFileName); } } catch (Exception e) { ChutzpahTracer.TraceError(e, "Error during batch compile of {0}", testSettings.SettingsFileName); throw new ChutzpahCompilationFailedException(e.Message, testSettings.SettingsFileName, e); } }
public void Dispose() { try { ChutzpahTracer.TraceInformation("Tearing down Web Server Host at path {0} and port {1}", RootPath, Port); NancyHost.Dispose(); } catch (Exception e) { ChutzpahTracer.TraceError(e, "Error tearing down Web Server Host at path {0} and port {1}", RootPath, Port); } finally { // Set active server to null Interlocked.Exchange(ref activeWebServer, null); } }
public static string GetBrowserPath(string browserName) { var browserPath = string.Empty; try { if (!string.IsNullOrEmpty(browserName)) { browserPath = GetBrowserPathFromRegistry(browserName); } if (string.IsNullOrEmpty(browserPath)) { browserPath = GetSystemDefaultBrowser(); } } catch (Exception e) { ChutzpahTracer.TraceError(e, "Unable to read browser path from registry"); } return(browserPath); }
public void Compile(IEnumerable <TestContext> testContexts) { // Group the test contexts by test settings to run batch aware settings like compile // For each test settings file that defines a compile step we will run it and update // testContexts reference files accordingly. var groupedTestContexts = testContexts.GroupBy(x => x.TestFileSettings); foreach (var contextGroup in groupedTestContexts) { var testSettings = contextGroup.Key; // If there is no compile setting then nothing to do here if (testSettings.Compile == null) { continue; } // Build the mapping from source to output files and gather properties about them var filePropeties = ( from file in contextGroup.SelectMany(x => x.ReferencedFiles).Distinct() where testSettings.Compile.Extensions.Any(x => file.Path.EndsWith(x, StringComparison.OrdinalIgnoreCase)) let sourceProperties = GetFileProperties(file.Path) let sourceHasOutput = !testSettings.Compile.ExtensionsWithNoOutput.Any(x => file.Path.EndsWith(x, StringComparison.OrdinalIgnoreCase)) let outputPath = GetOutputPath(file.Path, testSettings.Compile) let outputProperties = sourceHasOutput ? GetFileProperties(outputPath) : null select new SourceCompileInfo { SourceProperties = sourceProperties, OutputProperties = outputProperties, SourceHasOutput = sourceHasOutput }).ToList(); var outputPathMap = filePropeties .Where(x => x.SourceHasOutput) .ToDictionary(x => x.SourceProperties.Path, x => x.OutputProperties.Path, StringComparer.OrdinalIgnoreCase); // Check if the batch compile is needed var shouldCompile = CheckIfCompileIsNeeded(testSettings, filePropeties); // Run the batch compile if necessary if (shouldCompile) { if (testSettings.Compile.Mode == BatchCompileMode.Executable) { RunBatchCompile(testSettings); } else if (testSettings.Compile.Mode == BatchCompileMode.External) { ChutzpahTracer.TraceError("Chutzpah determined generated .js files are missing but the compile mode is External so Chutzpah can't compile them. Test results may be wrong."); } } else { ChutzpahTracer.TraceInformation("Skipping batch compile since all files are supdate to date for {0}", testSettings.SettingsFileName); } // Now that compile finished set generated path on all files who match the compiled extensions var filesToUpdate = contextGroup.SelectMany(x => x.ReferencedFiles) .Where(x => outputPathMap.ContainsKey(x.Path)); foreach (var file in filesToUpdate) { var outputPath = outputPathMap[file.Path]; if (outputPath != null && fileSystem.FileExists(outputPath)) { file.GeneratedFilePath = outputPath; ChutzpahTracer.TraceInformation("Found generated path for {0} at {1}", file.Path, outputPath); } else { ChutzpahTracer.TraceWarning("Couldn't find generated path for {0} at {1}", file.Path, outputPath); } if (!string.IsNullOrWhiteSpace(file.GeneratedFilePath)) { file.SourceMapFilePath = testSettings.Compile.UseSourceMaps ? sourceMapDiscoverer.FindSourceMap(file.GeneratedFilePath) : null; } } } }
public void Compile(IEnumerable <TestContext> testContexts, ITestMethodRunnerCallback callback = null) { // Group the test contexts by test settings to run batch aware settings like compile // For each test settings file that defines a compile step we will run it and update // testContexts reference files accordingly. var groupedTestContexts = testContexts.GroupBy(x => x.TestFileSettings); foreach (var contextGroup in groupedTestContexts) { var testSettings = contextGroup.Key; // If there is no compile setting then nothing to do here if (testSettings.Compile == null) { continue; } // Build the mapping from source to output files and gather properties about them var filePropeties = ( from file in contextGroup.SelectMany(x => x.ReferencedFiles).Where(x => !x.IsBuiltInDependency).Distinct() where testSettings.Compile.Extensions.Any(x => file.Path.EndsWith(x, StringComparison.OrdinalIgnoreCase)) let sourceProperties = GetFileProperties(file.Path) let sourceHasOutput = !testSettings.Compile.ExtensionsWithNoOutput.Any(x => file.Path.EndsWith(x, StringComparison.OrdinalIgnoreCase)) let outputPath = GetOutputPath(file.Path, testSettings.Compile) let outputProperties = sourceHasOutput ? GetFileProperties(outputPath) : null select new SourceCompileInfo { SourceProperties = sourceProperties, OutputProperties = outputProperties, SourceHasOutput = sourceHasOutput }).ToList(); var outputPathMap = filePropeties .Where(x => x.SourceHasOutput) .ToDictionary(x => x.SourceProperties.Path, x => x.OutputProperties.Path, StringComparer.OrdinalIgnoreCase); // Check if the batch compile is needed var shouldCompile = CheckIfCompileIsNeeded(testSettings, filePropeties); // Run the batch compile if necessary if (shouldCompile) { if (testSettings.Compile.Mode == BatchCompileMode.Executable) { RunBatchCompile(testSettings); } else { ChutzpahTracer.TraceWarning("Chutzpah determined generated .js files are missing but the compile mode is External so Chutzpah can't compile them. Test results may be wrong."); } } else { ChutzpahTracer.TraceInformation("Skipping batch compile since all files are update to date for {0}", testSettings.SettingsFileName); } // Now that compile finished set generated path on all files who match the compiled extensions var filesToUpdate = contextGroup.SelectMany(x => x.ReferencedFiles) .Where(x => outputPathMap.ContainsKey(x.Path)); foreach (var file in filesToUpdate) { var outputPath = outputPathMap[file.Path]; if (outputPath != null && fileSystem.FileExists(outputPath)) { file.GeneratedFilePath = outputPath; ChutzpahTracer.TraceInformation("Found generated path for {0} at {1}", file.Path, outputPath); } else { // If we could not find the file at the configured path attempt to see if it co-located ChutzpahTracer.TraceInformation("Unable to find generated path at configured location so attempting to see if generated file is co-located."); var coLocatedOutputPath = Path.ChangeExtension(file.Path, ".js"); if (fileSystem.FileExists(coLocatedOutputPath)) { file.GeneratedFilePath = coLocatedOutputPath; ChutzpahTracer.TraceInformation("Found generated path for {0} at {1}", file.Path, coLocatedOutputPath); } else { var error = string.Format("Couldn't find generated path for {0} at {1} or at {2}", file.Path, outputPath, coLocatedOutputPath); ChutzpahTracer.TraceError(error); if (!testSettings.Compile.IgnoreMissingFiles.GetValueOrDefault()) { // Throw and fail here since if we cant find the file we cannot be sure anything will run var exception = new FileNotFoundException(error, outputPath); callback.ExceptionThrown(exception, outputPath); } } } if (!string.IsNullOrWhiteSpace(file.GeneratedFilePath)) { file.SourceMapFilePath = testSettings.Compile.UseSourceMaps.GetValueOrDefault() ? sourceMapDiscoverer.FindSourceMap(file.GeneratedFilePath) : null; } } } }