int GetNextAvailablePort(int port) { while (!IsPortOpen(port)) { ChutzpahTracer.TraceWarning("Unable to get port {0} so trying next one", port); port++; } return(port); }
private string GetOutputPath(string sourcePath, BatchCompileConfiguration compileConfiguration) { if (sourcePath.IndexOf(compileConfiguration.SourceDirectory, StringComparison.OrdinalIgnoreCase) >= 0) { var relativePath = FileProbe.GetRelativePath(compileConfiguration.SourceDirectory, sourcePath); var outputPath = Path.Combine(compileConfiguration.OutDirectory, relativePath); outputPath = Path.ChangeExtension(outputPath, ".js"); return(outputPath); } else { ChutzpahTracer.TraceWarning( "Can't find location for generated path on {0} since it is not inside of configured source dir {1}", sourcePath, compileConfiguration.SourceDirectory); } return(null); }
/// <summary> /// This will get called for the test file and all referenced files. /// If the referenced file can be handled it generate a .js file and sets to the reference files generatedfilepath and adds the new file path to the temporary file collection /// If it can't handle the file it does nothing /// </summary> public virtual void Generate(IEnumerable <ReferencedFile> referencedFiles, IList <string> temporaryFiles, ChutzpahTestSettingsFile chutzpahTestSettings) { // Filter down to just the referenced files this generator supports referencedFiles = referencedFiles.Where(CanHandleFile).ToList(); if (referencedFiles.Any()) { ChutzpahTracer.TraceWarning("Performing DEPRECATED old style Chutzpah TypeScript/CoffeeScript compilation. Please change to the newer method."); var compiledMap = GenerateCompiledSources(referencedFiles, chutzpahTestSettings); foreach (var referencedFile in referencedFiles) { if (!compiledMap.ContainsKey(referencedFile.Path)) { continue; } var jsText = compiledMap[referencedFile.Path]; WriteGeneratedReferencedFile(referencedFile, jsText, temporaryFiles); } } }
/// <summary> /// Merge a selection of settings from a parent file into the current one. /// This merge will work as follows /// 1. For basic properties the child's property wins if it is different than the default /// 2. For complex objects the child's property wins if it is not null /// 3. For lists the childs items get added to the parents /// </summary> /// <param name="parent"></param> public ChutzpahTestSettingsFile InheritFrom(ChutzpahTestSettingsFile parent) { if (parent == null || this.IsDefaultSettings) { return(this); } this.References = parent.References.Concat(this.References).ToList(); this.CodeCoverageIncludes = parent.CodeCoverageIncludes.Concat(this.CodeCoverageIncludes).ToList(); this.CodeCoverageExcludes = parent.CodeCoverageExcludes.Concat(this.CodeCoverageExcludes).ToList(); this.CodeCoverageIgnores = parent.CodeCoverageIgnores.Concat(this.CodeCoverageIgnores).ToList(); this.Transforms = parent.Transforms.Concat(this.Transforms).ToList(); foreach (var browserArgument in parent.BrowserArguments) { // We should only override the child if the child does not already define a value for a key if (this.BrowserArguments.ContainsKey(browserArgument.Key)) { continue; } this.BrowserArguments[browserArgument.Key] = browserArgument.Value; } if (this.Server == null) { this.Server = parent.Server; } else if (this.Server != null && parent.Server != null // Only allow override if the parent is a force configuration which is used for testing && !(parent.Server is ForcedChutzpahWebServerConfiguration) ) { ChutzpahTracer.TraceWarning("Ignoring Server setting in child settings file since it is already configured in parent"); this.Server = new ChutzpahWebServerConfiguration(parent.Server); } if (this.Compile == null) { this.Compile = parent.Compile; } else if (this.Compile != null && parent.Compile != null) { this.Compile.Arguments = this.Compile.Arguments ?? parent.Compile.Arguments; this.Compile.Executable = this.Compile.Executable ?? parent.Compile.Executable; this.Compile.Extensions = this.Compile.Extensions.Any() ? this.Compile.Extensions : parent.Compile.Extensions; this.Compile.ExtensionsWithNoOutput = this.Compile.ExtensionsWithNoOutput.Any() ? this.Compile.ExtensionsWithNoOutput : parent.Compile.ExtensionsWithNoOutput; this.Compile.Mode = this.Compile.Mode ?? parent.Compile.Mode; this.Compile.IgnoreMissingFiles = this.Compile.IgnoreMissingFiles ?? parent.Compile.IgnoreMissingFiles; this.Compile.UseSourceMaps = this.Compile.UseSourceMaps ?? parent.Compile.UseSourceMaps; this.Compile.SkipIfUnchanged = this.Compile.SkipIfUnchanged ?? parent.Compile.SkipIfUnchanged; this.Compile.WorkingDirectory = this.Compile.WorkingDirectory ?? parent.Compile.WorkingDirectory; this.Compile.Timeout = this.Compile.Timeout ?? parent.Compile.Timeout; this.Compile.Paths = this.Compile.Paths.Concat(parent.Compile.Paths).ToList(); } this.AMDBaseUrl = this.AMDBaseUrl ?? parent.AMDBaseUrl; this.AMDAppDirectory = this.AMDAppDirectory ?? parent.AMDAppDirectory; this.CodeCoverageSuccessPercentage = this.CodeCoverageSuccessPercentage ?? parent.CodeCoverageSuccessPercentage; this.CustomTestHarnessPath = this.CustomTestHarnessPath ?? parent.CustomTestHarnessPath; this.CodeCoverageExecutionMode = this.CodeCoverageExecutionMode ?? parent.CodeCoverageExecutionMode; this.Framework = this.Framework ?? parent.Framework; this.FrameworkVersion = this.FrameworkVersion ?? parent.FrameworkVersion; this.MochaInterface = this.MochaInterface ?? parent.MochaInterface; this.RootReferencePathMode = this.RootReferencePathMode ?? parent.RootReferencePathMode; this.TestFileTimeout = this.TestFileTimeout ?? parent.TestFileTimeout; this.TestHarnessReferenceMode = this.TestHarnessReferenceMode ?? parent.TestHarnessReferenceMode; this.TestPattern = this.TestPattern ?? parent.TestPattern; this.UserAgent = this.UserAgent ?? parent.UserAgent; this.EnableTestFileBatching = this.EnableTestFileBatching ?? parent.EnableTestFileBatching; this.IgnoreResourceLoadingErrors = this.IgnoreResourceLoadingErrors ?? parent.IgnoreResourceLoadingErrors; this.Parallelism = this.Parallelism ?? parent.Parallelism; this.EnableTracing = this.EnableTracing ?? parent.EnableTracing; this.TraceFilePath = this.TraceFilePath ?? parent.TraceFilePath; this.CodeCoverageTimeout = this.CodeCoverageTimeout ?? parent.CodeCoverageTimeout; this.Proxy = this.Proxy ?? parent.Proxy; this.CreateFailedTestForFileError = this.CreateFailedTestForFileError ?? parent.CreateFailedTestForFileError; // Deprecated this.AMDBasePath = this.AMDBasePath ?? parent.AMDBasePath; // We need to handle an inherited test harness location mode specially // If the parent set their mode to SettingsFileAdjacent and the current file has it set to null // Then we make the current file have a Custom mode with the parent files settings directory if (this.TestHarnessLocationMode == null) { if (parent.TestHarnessLocationMode == Chutzpah.Models.TestHarnessLocationMode.SettingsFileAdjacent && !parent.IsDefaultSettings) { this.TestHarnessLocationMode = Chutzpah.Models.TestHarnessLocationMode.Custom; this.TestHarnessDirectory = parent.SettingsFileDirectory; } else { this.TestHarnessDirectory = parent.TestHarnessDirectory; this.TestHarnessLocationMode = parent.TestHarnessLocationMode; } } return(this); }
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; } } } }