int GetNextAvailablePort(int port)
        {
            while (!IsPortOpen(port))
            {
                ChutzpahTracer.TraceWarning("Unable to get port {0} so trying next one", port);
                port++;
            }

            return(port);
        }
Example #2
0
        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);
        }
Example #3
0
        /// <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);
        }
Example #5
0
        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;
                    }
                }
            }
        }