예제 #1
0
        private string GetTestHarnessTemplatePath(IFrameworkDefinition definition, ChutzpahTestSettingsFile chutzpahTestSettings)
        {
            string templatePath = null;

            if (!string.IsNullOrEmpty(chutzpahTestSettings.CustomTestHarnessPath))
            {
                // If CustomTestHarnessPath is absolute path then Path.Combine just returns it
                var harnessPath = Path.Combine(chutzpahTestSettings.SettingsFileDirectory, chutzpahTestSettings.CustomTestHarnessPath);
                var fullPath    = fileProbe.FindFilePath(harnessPath);
                if (fullPath != null)
                {
                    ChutzpahTracer.TraceInformation("Using Custom Test Harness from {0}", fullPath);
                    templatePath = fullPath;
                }
                else
                {
                    ChutzpahTracer.TraceError("Cannot find Custom Test Harness at {0}", chutzpahTestSettings.CustomTestHarnessPath);
                }
            }

            if (templatePath == null)
            {
                templatePath = fileProbe.GetPathInfo(Path.Combine(Constants.TestFileFolder, definition.GetTestHarness(chutzpahTestSettings))).FullPath;

                ChutzpahTracer.TraceInformation("Using builtin Test Harness from {0}", templatePath);
            }
            return(templatePath);
        }
예제 #2
0
        public virtual void TestFinished(TestCase testCase)
        {
            switch (testCase.TestOutcome)
            {
            case TestOutcome.Passed:
                ChutzpahTracer.TraceInformation("File {0}, Test {1} passed", testCase.InputTestFile, testCase.TestName);
                TestPassed(testCase);
                break;

            case TestOutcome.Failed:
                ChutzpahTracer.TraceInformation("File {0}, Test {1} failed", testCase.InputTestFile, testCase.TestName);
                TestFailed(testCase);
                break;

            case TestOutcome.Skipped:
                ChutzpahTracer.TraceInformation("File {0}, Test {1} skipped", testCase.InputTestFile, testCase.TestName);
                TestSkipped(testCase);
                break;

            default:
                break;
            }

            TestComplete(testCase);
        }
예제 #3
0
        public ProcessResult <T> RunExecutableAndProcessOutput <T>(string exePath, string arguments, Func <ProcessStream, T> streamProcessor) where T : class
        {
            var p = new Process();

            p.StartInfo.UseShellExecute        = false;
            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.CreateNoWindow         = true;
            p.StartInfo.FileName  = exePath;
            p.StartInfo.Arguments = arguments;
            p.StartInfo.StandardOutputEncoding = Encoding.UTF8;
            p.Start();

            ChutzpahTracer.TraceInformation("Started headless browser: {0} with PID: {1} using args: {2}", exePath, p.Id, arguments);

            // Output will be null if the stream reading times out
            var processStream = new ProcessStream(new ProcessWrapper(p), p.StandardOutput);
            var output        = streamProcessor(processStream);

            p.WaitForExit(5000);



            ChutzpahTracer.TraceInformation("Ended headless browser: {0} with PID: {1} using args: {2}", exePath, p.Id, arguments);

            return(new ProcessResult <T>(processStream.TimedOut ? (int)TestProcessExitCode.Timeout : p.ExitCode, output));
        }
예제 #4
0
        private IEnumerable <PathInfo> FindTestFiles(IEnumerable <string> testPaths, TestOptions options)
        {
            IEnumerable <PathInfo> scriptPaths = Enumerable.Empty <PathInfo>();

            // If the path list contains only chutzpah.json files then use those files for getting the list of test paths
            var testPathList = testPaths.Distinct(StringComparer.OrdinalIgnoreCase).ToList();

            if (testPathList.All(testPath => Path.GetFileName(testPath).Equals(Constants.SettingsFileName, StringComparison.OrdinalIgnoreCase)))
            {
                ChutzpahTracer.TraceInformation("Using Chutzpah.json files to find tests");
                foreach (var path in testPathList)
                {
                    var chutzpahJsonPath = fileProbe.FindFilePath(path);
                    if (chutzpahJsonPath == null)
                    {
                        ChutzpahTracer.TraceWarning("Supplied chutzpah.json path {0} does not exist", path);
                    }

                    var settingsFile = testSettingsService.FindSettingsFile(chutzpahJsonPath, options.ChutzpahSettingsFileEnvironments);
                    var pathInfos    = fileProbe.FindScriptFiles(settingsFile);
                    scriptPaths = scriptPaths.Concat(pathInfos);
                }
            }
            else
            {
                scriptPaths = fileProbe.FindScriptFiles(testPathList);
            }
            return(scriptPaths
                   .Where(x => x.FullPath != null)
                   .ToList());;
        }
예제 #5
0
        private void ProcessServerSettings(ChutzpahTestSettingsFile settings, IDictionary <string, string> chutzpahVariables)
        {
            if (settings.Engine.GetValueOrDefault() != Engine.Phantom)
            {
                if (settings.Server == null)
                {
                    settings.Server = new ForcedChutzpahWebServerConfiguration();
                }
                else
                {
                    settings.Server.Enabled = true;
                }
            }

            if (settings.Server != null)
            {
                settings.Server.FileCachingEnabled = settings.Server.FileCachingEnabled ?? true;

                settings.Server.DefaultPort = settings.Server.DefaultPort ?? Constants.DefaultWebServerPort;

                string rootPath = null;
                if (!string.IsNullOrEmpty(settings.Server.RootPath))
                {
                    rootPath = settings.Server.RootPath;
                }
                else
                {
                    ChutzpahTracer.TraceInformation("Defaulting the RootPath to the drive root of the chutzpah.json file");
                    rootPath = Path.GetPathRoot(settings.SettingsFileDirectory);
                }

                settings.Server.RootPath = ResolveFolderPath(settings, ExpandVariable(chutzpahVariables, rootPath));
            }
        }
예제 #6
0
        private void BuildTestContexts(
            TestOptions options,
            IEnumerable <PathInfo> scriptPaths,
            ParallelOptions parallelOptions,
            CancellationTokenSource cancellationSource,
            int resultCount,
            ConcurrentBag <TestContext> testContexts,
            ITestMethodRunnerCallback callback,
            TestCaseSummary overallSummary)
        {
            Parallel.ForEach(scriptPaths, parallelOptions, testFile =>
            {
                ChutzpahTracer.TraceInformation("Building test context for {0}", testFile.FullPath);

                try
                {
                    if (cancellationSource.IsCancellationRequested)
                    {
                        return;
                    }
                    TestContext testContext;

                    resultCount++;
                    if (testContextBuilder.TryBuildContext(testFile, options, out testContext))
                    {
                        testContexts.Add(testContext);
                    }
                    else
                    {
                        ChutzpahTracer.TraceWarning("Unable to build test context for {0}", testFile.FullPath);
                    }

                    // Limit the number of files we can scan to attempt to build a context for
                    // This is important in the case of folder scanning where many JS files may not be
                    // test files.
                    if (resultCount >= options.FileSearchLimit)
                    {
                        ChutzpahTracer.TraceError("File search limit hit!!!");
                        cancellationSource.Cancel();
                    }
                }
                catch (Exception e)
                {
                    var error = new TestError
                    {
                        InputTestFile = testFile.FullPath,
                        Message       = e.ToString()
                    };

                    overallSummary.Errors.Add(error);
                    callback.FileError(error);

                    ChutzpahTracer.TraceError(e, "Error during building test context for {0}", testFile.FullPath);
                }
                finally
                {
                    ChutzpahTracer.TraceInformation("Finished building test context for {0}", testFile.FullPath);
                }
            });
        }
예제 #7
0
        private IEnumerable <PathInfo> FindTestFiles(IEnumerable <string> testPaths, TestOptions options)
        {
            IEnumerable <PathInfo> scriptPaths = Enumerable.Empty <PathInfo>();

            // If the path list contains only chutzpah.json files then use those files for getting the list of test paths
            var testPathList = testPaths.ToList();

            if (testPathList.All(testPath => Path.GetFileName(testPath).Equals(Constants.SettingsFileName, StringComparison.OrdinalIgnoreCase)))
            {
                ChutzpahTracer.TraceInformation("Using Chutzpah.json files to find tests");
                foreach (var path in testPathList)
                {
                    var chutzpahJsonPath = fileProbe.FindFilePath(path);
                    if (chutzpahJsonPath == null)
                    {
                        ChutzpahTracer.TraceWarning("Supplied chutzpah.json path {0} does not exist", path);
                    }

                    // The FindSettingsFile api takes the directory of the file since it caches this for use in later test runs
                    // this could be cleaned up to have two APIS one which lets you give the direct file
                    var settingsFile = testSettingsService.FindSettingsFile(Path.GetDirectoryName(chutzpahJsonPath));
                    var pathInfos    = fileProbe.FindScriptFiles(settingsFile);
                    scriptPaths = scriptPaths.Concat(pathInfos);
                }
            }
            else
            {
                scriptPaths = fileProbe.FindScriptFiles(testPathList, options.TestingMode);
            }
            return(scriptPaths);
        }
예제 #8
0
        public bool RunExecutableAndProcessOutput(string exePath, string arguments, IDictionary <string, string> environmentVars, out string standardOutput, out string standardError)
        {
            Process p = InvokeProcess(exePath, arguments, environmentVars);

            ChutzpahTracer.TraceInformation("Started executable: {0} with PID: {1} using args: {2}", exePath, p.Id, arguments);


            p.WaitForExit(120 * 1000);


            standardOutput = null;
            StringBuilder output = new StringBuilder();

            while (!p.StandardOutput.EndOfStream)
            {
                string line = p.StandardOutput.ReadLine();
                output.AppendLine(line);
            }
            standardOutput = output.ToString();

            standardError = null;
            StringBuilder error = new StringBuilder();

            while (!p.StandardError.EndOfStream)
            {
                string line = p.StandardError.ReadLine();
                error.AppendLine(line);
            }
            standardError = error.ToString();

            ChutzpahTracer.TraceInformation("Ended executable: {0} with PID: {1} using args: {2}", exePath, p.Id, arguments);

            return(p.ExitCode == 0);
        }
예제 #9
0
        private ICoverageEngine SetupCodeCoverageEngine(
            TestOptions options,
            ChutzpahTestSettingsFile chutzpahTestSettings,
            IFrameworkDefinition definition,
            List <ReferencedFile> referencedFiles)
        {
            ICoverageEngine coverageEngine = GetConfiguredCoverageEngine(options, chutzpahTestSettings);

            if (coverageEngine != null)
            {
                var deps = coverageEngine.GetFileDependencies(definition, chutzpahTestSettings);

                foreach (string item in deps)
                {
                    string sourcePath = Path.Combine(fileProbe.BuiltInDependencyDirectory, item);
                    ChutzpahTracer.TraceInformation(
                        "Added code coverage dependency '{0}' to referenced files",
                        sourcePath);
                    referencedFiles.Add(
                        new ReferencedFile
                    {
                        IsLocal = true,
                        IsCodeCoverageDependency = true,
                        Path = sourcePath,
                        IncludeInTestHarness = true
                    });
                }
            }
            return(coverageEngine);
        }
예제 #10
0
        private ChutzpahTestSettingsFile FindSettingsFile(string directory, ChutzpahSettingsFileEnvironment environment)
        {
            if (string.IsNullOrEmpty(directory))
            {
                return(ChutzpahTestSettingsFile.Default);
            }

            directory = directory.TrimEnd('/', '\\');

            ChutzpahTestSettingsFile settings;

            if (!ChutzpahSettingsFileCache.TryGetValue(directory, out settings))
            {
                var testSettingsFilePath = fileProbe.FindTestSettingsFile(directory);
                if (string.IsNullOrEmpty(testSettingsFilePath))
                {
                    ChutzpahTracer.TraceInformation("Chutzpah.json file not found given starting directoy {0}", directory);
                    settings = ChutzpahTestSettingsFile.Default;
                }
                else if (!ChutzpahSettingsFileCache.TryGetValue(Path.GetDirectoryName(testSettingsFilePath), out settings))
                {
                    ChutzpahTracer.TraceInformation("Chutzpah.json file found at {0} given starting directoy {1}", testSettingsFilePath, directory);
                    settings = serializer.DeserializeFromFile <ChutzpahTestSettingsFile>(testSettingsFilePath);

                    if (settings == null)
                    {
                        settings = ChutzpahTestSettingsFile.Default;
                    }
                    else
                    {
                        settings.IsDefaultSettings = false;
                    }

                    settings.SettingsFileDirectory = Path.GetDirectoryName(testSettingsFilePath);

                    var chutzpahVariables = BuildChutzpahReplacementVariables(testSettingsFilePath, environment, settings);

                    ResolveTestHarnessDirectory(settings, chutzpahVariables);

                    ResolveAMDBaseUrl(settings, chutzpahVariables);

                    ResolveBatchCompileConfiguration(settings, chutzpahVariables);

                    ProcessPathSettings(settings, chutzpahVariables);

                    ProcessInheritance(environment, settings, chutzpahVariables);

                    // Add a mapping in the cache for the directory that contains the test settings file
                    ChutzpahSettingsFileCache.TryAdd(settings.SettingsFileDirectory, settings);
                }

                // Add mapping in the cache for the original directory tried to skip needing to traverse the tree again
                ChutzpahSettingsFileCache.TryAdd(directory, settings);
            }



            return(settings);
        }
예제 #11
0
        public IList <TestFileSummary> Read(ProcessStream processStream, TestOptions testOptions, TestContext testContext, ITestMethodRunnerCallback callback, bool debugEnabled)
        {
            if (processStream == null)
            {
                throw new ArgumentNullException("processStream");
            }
            if (testOptions == null)
            {
                throw new ArgumentNullException("testOptions");
            }
            if (testContext == null)
            {
                throw new ArgumentNullException("testContext");
            }

            lastTestEvent = DateTime.Now;
            var timeout = (testContext.TestFileSettings.TestFileTimeout ?? testOptions.TestFileTimeoutMilliseconds) + 500; // Add buffer to timeout to account for serialization

            var codeCoverageEnabled = (!testContext.TestFileSettings.EnableCodeCoverage.HasValue && testOptions.CoverageOptions.Enabled) ||
                                      (testContext.TestFileSettings.EnableCodeCoverage.HasValue && testContext.TestFileSettings.EnableCodeCoverage.Value);

            var streamingTestFileContexts = testContext.ReferencedFiles
                                            .Where(x => x.IsFileUnderTest)
                                            .Select(x => new StreamingTestFileContext(x, testContext, codeCoverageEnabled))
                                            .ToList();

            var deferredEvents = new List <Action <StreamingTestFileContext> >();

            var readerTask = Task <IList <TestFileSummary> > .Factory.StartNew(() => ReadFromStream(processStream.StreamReader, testContext, testOptions, streamingTestFileContexts, deferredEvents, callback, debugEnabled));

            while (readerTask.Status == TaskStatus.WaitingToRun ||
                   (readerTask.Status == TaskStatus.Running && (DateTime.Now - lastTestEvent).TotalMilliseconds < timeout))
            {
                Thread.Sleep(100);
            }

            if (readerTask.IsCompleted)
            {
                ChutzpahTracer.TraceInformation("Finished reading stream from test file '{0}'", testContext.FirstInputTestFile);
                return(readerTask.Result);
            }
            else
            {
                // Since we times out make sure we play the deferred events so we do not lose errors
                // We will just attach these events to the first test context at this point since we do
                // not know where they belong
                PlayDeferredEvents(streamingTestFileContexts.FirstOrDefault(), deferredEvents);

                // We timed out so kill the process and return an empty test file summary
                ChutzpahTracer.TraceError("Test file '{0}' timed out after running for {1} milliseconds", testContext.FirstInputTestFile, (DateTime.Now - lastTestEvent).TotalMilliseconds);

                processStream.TimedOut = true;
                processStream.KillProcess();
                return(testContext.ReferencedFiles.Where(x => x.IsFileUnderTest).Select(file => new TestFileSummary(file.Path)).ToList());
            }
        }
예제 #12
0
 private void AddTestFrameworkDependencies(IEnumerable <string> deps, List <ReferencedFile> referencedFiles)
 {
     foreach (string item in deps.Reverse())
     {
         string sourcePath = Path.Combine(fileProbe.BuiltInDependencyDirectory, item);
         ChutzpahTracer.TraceInformation("Added framework dependency '{0}' to referenced files", sourcePath);
         referencedFiles.Insert(0, new ReferencedFile {
             IsLocal = true, IsTestFrameworkFile = true, Path = sourcePath, IncludeInTestHarness = true, IsBuiltInDependency = true
         });
     }
 }
예제 #13
0
 private void AddTestFrameworkDependencies(IEnumerable <string> deps, List <ReferencedFile> referencedFiles)
 {
     foreach (string item in deps.Reverse())
     {
         string sourcePath = fileProbe.GetPathInfo(Path.Combine(Constants.TestFileFolder, item)).FullPath;
         ChutzpahTracer.TraceInformation("Added framework dependency '{0}' to referenced files", sourcePath);
         referencedFiles.Insert(0, new ReferencedFile {
             IsLocal = true, IsTestFrameworkFile = true, Path = sourcePath, IncludeInTestHarness = true
         });
     }
 }
예제 #14
0
        private void FireTestFinished(ITestMethodRunnerCallback callback, StreamingTestFileContext testFileContext, JsRunnerOutput jsRunnerOutput, int testIndex)
        {
            var jsTestCase = jsRunnerOutput as JsTestCase;

            jsTestCase.TestCase.InputTestFile = testFileContext.ReferencedFile.Path;
            AddLineNumber(testFileContext.ReferencedFile, testIndex, jsTestCase);
            callback.TestFinished(jsTestCase.TestCase);
            testFileContext.TestFileSummary.AddTestCase(jsTestCase.TestCase);

            ChutzpahTracer.TraceInformation("Test Case Finished:'{0}'", jsTestCase.TestCase.GetDisplayName());
        }
예제 #15
0
        private void FireLogOutput(ITestMethodRunnerCallback callback, TestFileContext testFileContext, JsRunnerOutput jsRunnerOutput)
        {
            var log = jsRunnerOutput as JsLog;

            // This is an internal log message
            if (log.Log.Message.StartsWith(internalLogPrefix))
            {
                ChutzpahTracer.TraceInformation("Phantom Log - {0}", log.Log.Message.Substring(internalLogPrefix.Length).Trim());
                return;
            }

            log.Log.InputTestFile = testFileContext.ReferencedFile.Path;
            callback.FileLog(log.Log);
            testFileContext.TestFileSummary.Logs.Add(log.Log);
        }
예제 #16
0
        /// <summary>
        /// If the reference path is rooted (e.g. /some/path) and the user chose to adjust it then change it
        /// </summary>
        /// <returns></returns>
        private static string AdjustPathIfRooted(ChutzpahTestSettingsFile chutzpahTestSettings, string referencePath)
        {
            if (chutzpahTestSettings.RootReferencePathMode == RootReferencePathMode.SettingsFileDirectory &&
                (referencePath.StartsWith("/") || referencePath.StartsWith("\\")))
            {
                ChutzpahTracer.TraceInformation(
                    "Changing reference '{0}' to be rooted from settings directory '{1}'",
                    referencePath,
                    chutzpahTestSettings.SettingsFileDirectory);

                referencePath = chutzpahTestSettings.SettingsFileDirectory + referencePath;
            }

            return(referencePath);
        }
예제 #17
0
 private void ProcessProxy(ChutzpahTestSettingsFile settings, IDictionary <string, string> chutzpahVariables)
 {
     if (!string.IsNullOrEmpty(settings.Proxy))
     {
         if (!ValidationHelper.IsValidProxySetting(settings.Proxy))
         {
             settings.Proxy = string.Empty;
             ChutzpahTracer.TraceInformation("invalid proxy, must be in format of address:port");
         }
         else
         {
             ChutzpahTracer.TraceInformation(string.Format("Proxy setting:{0}", settings.Proxy));
         }
     }
 }
예제 #18
0
        public bool IsTestFile(string file, ChutzpahSettingsFileEnvironments environments = null)
        {
            ChutzpahTracer.TraceInformation("Determining if {0} might be a test file", file);
            if (string.IsNullOrWhiteSpace(file))
            {
                return(false);
            }

            var testFilePath = fileProbe.FindFilePath(file);

            if (testFilePath == null)
            {
                ChutzpahTracer.TraceInformation("Rejecting '{0}' since either it doesnt exist", file);
                return(false);
            }

            var chutzpahTestSettings = settingsService.FindSettingsFile(testFilePath, environments);

            if (!IsTestPathIncluded(testFilePath, chutzpahTestSettings))
            {
                ChutzpahTracer.TraceInformation("Excluded test file '{0}' given chutzpah.json settings", testFilePath);
                return(false);
            }

            // If the framework or tests filters are set in the settings file then no need to check for
            // test framework
            if (!string.IsNullOrEmpty(chutzpahTestSettings.Framework) || chutzpahTestSettings.Tests.Any())
            {
                return(true);
            }
            else
            {
                string testFileText = fileSystem.GetText(testFilePath);

                IFrameworkDefinition definition;
                var info = new PathInfo {
                    Path = file, FullPath = testFilePath, Type = FileProbe.GetFilePathType(testFilePath)
                };
                var frameworkDetetected = TryDetectFramework(info, chutzpahTestSettings, out definition);

                if (frameworkDetetected)
                {
                    ChutzpahTracer.TraceInformation("Assuming '{0}' is a test file", file);
                }

                return(frameworkDetetected);
            }
        }
예제 #19
0
        private IList <ReferencedFile> GetReferencedFiles(
            HashSet <string> discoveredPaths,
            IFrameworkDefinition definition,
            string textToParse,
            string currentFilePath,
            ChutzpahTestSettingsFile chutzpahTestSettings)
        {
            var referencedFiles = new List <ReferencedFile>();

            Regex regex = RegexPatterns.JsReferencePathRegex;

            foreach (Match match in regex.Matches(textToParse))
            {
                if (!ShouldIncludeReference(match))
                {
                    continue;
                }

                string referencePath = match.Groups["Path"].Value;

                ProcessFilePathAsReference(
                    discoveredPaths,
                    definition,
                    currentFilePath,
                    chutzpahTestSettings,
                    referencePath,
                    referencedFiles,
                    new ReferencePathSettings());
            }

            foreach (Match match in RegexPatterns.JsTemplatePathRegex.Matches(textToParse))
            {
                string referencePath = match.Groups["Path"].Value;

                referencePath = AdjustPathIfRooted(chutzpahTestSettings, referencePath);
                string relativeReferencePath = Path.Combine(Path.GetDirectoryName(currentFilePath), referencePath);
                string absoluteFilePath      = fileProbe.FindFilePath(relativeReferencePath);
                if (referencedFiles.All(r => r.Path != absoluteFilePath))
                {
                    ChutzpahTracer.TraceInformation("Added html template '{0}' to referenced files", absoluteFilePath);
                    referencedFiles.Add(new ReferencedFile {
                        Path = absoluteFilePath, IsLocal = false, IncludeInTestHarness = true
                    });
                }
            }

            return(referencedFiles);
        }
예제 #20
0
        public virtual void TestFinished(TestCase testCase)
        {
            if (testCase.Passed)
            {
                ChutzpahTracer.TraceInformation("File {0}, Test {1} passed", testCase.InputTestFile, testCase.TestName);
                TestPassed(testCase);
            }

            if (!testCase.Passed)
            {
                ChutzpahTracer.TraceInformation("File {0}, Test {1} failed", testCase.InputTestFile, testCase.TestName);
                TestFailed(testCase);
            }

            TestComplete(testCase);
        }
예제 #21
0
        /// <summary>
        /// Iterates over filegenerators letting the generators decide if they handle any files
        /// </summary>
        private void ProcessForFilesGeneration(List <ReferencedFile> referencedFiles, List <string> temporaryFiles, ChutzpahTestSettingsFile chutzpahTestSettings)
        {
            if (chutzpahTestSettings.Compile != null)
            {
                ChutzpahTracer.TraceInformation("Ignoring old style file compilation since we detected the new compile setting");
                return;
            }
            ChutzpahTracer.TraceInformation("Starting legacy file compilation/generation");

            foreach (var fileGenerator in fileGenerators)
            {
                fileGenerator.Generate(referencedFiles, temporaryFiles, chutzpahTestSettings);
            }

            ChutzpahTracer.TraceInformation("Finished legacy file compilation/generation");
        }
예제 #22
0
        public IEnumerable <PathInfo> FindScriptFiles(ChutzpahTestSettingsFile chutzpahTestSettings)
        {
            if (chutzpahTestSettings == null)
            {
                yield break;
            }

            foreach (var pathSettings in chutzpahTestSettings.Tests.Where(x => x != null))
            {
                var includePatterns = pathSettings.Includes.Select(x => UrlBuilder.NormalizeFilePath(x)).ToList();
                var excludePatterns = pathSettings.Excludes.Select(x => UrlBuilder.NormalizeFilePath(x)).ToList();


                // The path we assume default to the chuzpah.json directory if the Path property is not set
                var testPath = string.IsNullOrEmpty(pathSettings.Path) ? pathSettings.SettingsFileDirectory : pathSettings.Path;
                testPath = UrlBuilder.NormalizeFilePath(testPath);
                testPath = testPath != null?Path.Combine(pathSettings.SettingsFileDirectory, testPath) : null;

                // If a file path is given just return that file
                var filePath = FindFilePath(testPath);
                if (filePath != null)
                {
                    ChutzpahTracer.TraceInformation("Found file  {0} from chutzpah.json", filePath);
                    yield return(GetPathInfo(filePath));
                }

                // If a folder path is given enumerate that folder (recursively) with the optional include/exclude paths
                var folderPath = FindFolderPath(testPath);
                if (folderPath != null)
                {
                    var childFiles = fileSystem.GetFiles(UrlBuilder.NormalizeFilePath(folderPath, false), "*.*", SearchOption.AllDirectories);
                    var validFiles = from file in childFiles
                                     let normalizedFile = UrlBuilder.NormalizeFilePath(file)
                                                          where !IsTemporaryChutzpahFile(normalizedFile) &&
                                                          (!includePatterns.Any() || includePatterns.Any(pat => NativeImports.PathMatchSpec(normalizedFile, pat))) &&
                                                          (!excludePatterns.Any() || !excludePatterns.Any(pat => NativeImports.PathMatchSpec(normalizedFile, pat)))
                                                          select file;


                    foreach (var item in validFiles)
                    {
                        yield return(GetPathInfo(item));
                    }
                }
            }
        }
예제 #23
0
        public ProcessResult <TestCaseStreamReadResult> RunExecutableAndProcessOutput(string exePath, string arguments, Func <ProcessStreamStringSource, TestCaseStreamReadResult> streamProcessor, int streamTimeout, IDictionary <string, string> environmentVars)
        {
            Process p = InvokeProcess(exePath, arguments, environmentVars);

            ChutzpahTracer.TraceInformation("Started headless browser: {0} with PID: {1} using args: {2}", exePath, p.Id, arguments);

            // Output will be null if the stream reading times out
            var processStream = new ProcessStreamStringSource(new ProcessWrapper(p), p.StandardOutput, streamTimeout);
            var output        = streamProcessor(processStream);

            p.WaitForExit(5000);



            ChutzpahTracer.TraceInformation("Ended headless browser: {0} with PID: {1} using args: {2}", exePath, p.Id, arguments);

            return(new ProcessResult <TestCaseStreamReadResult>(output.TimedOut ? (int)TestProcessExitCode.Timeout : p.ExitCode, output));
        }
예제 #24
0
        /// <summary>
        /// Decides whether a reference match should be included.
        /// </summary>
        /// <param name="match">The reference match.</param>
        /// <returns>
        /// <c>true</c> if the reference should be included, otherwise <c>false</c>.
        /// </returns>
        private static bool ShouldIncludeReference(Match match)
        {
            if (match.Success)
            {
                var exclude = match.Groups["Exclude"].Value;

                if (string.IsNullOrWhiteSpace(exclude) ||
                    exclude.Equals("false", StringComparison.OrdinalIgnoreCase) ||
                    exclude.Equals("no", StringComparison.OrdinalIgnoreCase))
                {
                    // The exclude flag is empty or negative
                    return(true);
                }
            }

            ChutzpahTracer.TraceInformation("Excluding reference file because it contains a postitive chutzpah-exclude attribute");

            return(false);
        }
예제 #25
0
        private void ProcessServerSettings(ChutzpahTestSettingsFile settings, IDictionary <string, string> chutzpahVariables)
        {
            if (settings.Server != null)
            {
                settings.Server.DefaultPort = settings.Server.DefaultPort ?? Constants.DefaultWebServerPort;

                string rootPath = null;
                if (!string.IsNullOrEmpty(settings.Server.RootPath))
                {
                    rootPath = settings.Server.RootPath;
                }
                else
                {
                    ChutzpahTracer.TraceInformation("Defaulting the RootPath to the drive root of the chutzpah.json file");
                    rootPath = Path.GetPathRoot(settings.SettingsFileDirectory);
                }

                settings.Server.RootPath = ResolveFolderPath(settings, ExpandVariable(chutzpahVariables, rootPath));
            }
        }
예제 #26
0
        private void ProcessInheritance(ChutzpahSettingsFileEnvironment environment, ChutzpahTestSettingsFile settings, IDictionary <string, string> chutzpahVariables)
        {
            if (settings.InheritFromParent || !string.IsNullOrEmpty(settings.InheritFromPath))
            {
                if (string.IsNullOrEmpty(settings.InheritFromPath))
                {
                    ChutzpahTracer.TraceInformation("Searching for parent Chutzpah.json to inherit from");
                    settings.InheritFromPath = Path.GetDirectoryName(settings.SettingsFileDirectory);
                }
                else
                {
                    ChutzpahTracer.TraceInformation("Searching for Chutzpah.json to inherit from at {0}", settings.InheritFromPath);

                    string settingsToInherit = ExpandVariable(chutzpahVariables, settings.InheritFromPath);
                    if (settingsToInherit.EndsWith(Constants.SettingsFileName, StringComparison.OrdinalIgnoreCase))
                    {
                        settingsToInherit = Path.GetDirectoryName(settingsToInherit);
                    }

                    settingsToInherit = ResolveFolderPath(settings, settingsToInherit);

                    settings.InheritFromPath = settingsToInherit;
                }

                // If we have any environment properties do not use cached
                // parents and re-evaluate using current environment
                var forceFresh = environment != null && environment.Properties.Any();

                var parentSettingsFile = ProcessSettingsFile(settings.InheritFromPath, environment, forceFresh);

                if (!parentSettingsFile.IsDefaultSettings)
                {
                    ChutzpahTracer.TraceInformation("Found parent Chutzpah.json in directory {0}", parentSettingsFile.SettingsFileDirectory);
                    settings.InheritFrom(parentSettingsFile);
                }
                else
                {
                    ChutzpahTracer.TraceInformation("Could not find a parent Chutzpah.json");
                }
            }
        }
예제 #27
0
        private ReferencedFile VisitReferencedFile(
            string absoluteFilePath,
            IFrameworkDefinition definition,
            HashSet <string> discoveredPaths,
            ICollection <ReferencedFile> referencedFiles,
            ChutzpahTestSettingsFile chutzpahTestSettings,
            ReferencePathSettings pathSettings)
        {
            // If the file doesn't exit exist or we have seen it already then return
            if (discoveredPaths.Contains(absoluteFilePath))
            {
                return(null);
            }

            var referencedFile = new ReferencedFile
            {
                Path                 = absoluteFilePath,
                IsLocal              = true,
                IsTestFrameworkFile  = pathSettings.IsTestFrameworkFile,
                IncludeInTestHarness = pathSettings.IncludeInTestHarness || chutzpahTestSettings.TestHarnessReferenceMode == TestHarnessReferenceMode.Normal,
                TemplateOptions      = pathSettings.TemplateOptions
            };

            ChutzpahTracer.TraceInformation(
                "Added file '{0}' to referenced files. Local: {1}, IncludeInTestHarness: {2}",
                referencedFile.Path,
                referencedFile.IsLocal,
                referencedFile.IncludeInTestHarness);

            referencedFiles.Add(referencedFile);
            discoveredPaths.Add(referencedFile.Path); // Remmember this path to detect reference loops


            ChutzpahTracer.TraceInformation("Processing referenced file '{0}' for expanded references", absoluteFilePath);
            if (pathSettings.ExpandReferenceComments)
            {
                referencedFile.ReferencedFiles = ExpandNestedReferences(discoveredPaths, definition, absoluteFilePath, chutzpahTestSettings);
            }

            return(referencedFile);
        }
예제 #28
0
        public IList <TestFileSummary> Read(ProcessStream processStream, TestOptions testOptions, TestContext testContext, ITestMethodRunnerCallback callback, bool debugEnabled)
        {
            if (processStream == null)
            {
                throw new ArgumentNullException("processStream");
            }
            if (testOptions == null)
            {
                throw new ArgumentNullException("testOptions");
            }
            if (testContext == null)
            {
                throw new ArgumentNullException("testContext");
            }

            lastTestEvent = DateTime.Now;
            var timeout    = (testContext.TestFileSettings.TestFileTimeout ?? testOptions.TestFileTimeoutMilliseconds) + 500; // Add buffer to timeout to account for serialization
            var readerTask = Task <IList <TestFileSummary> > .Factory.StartNew(() => ReadFromStream(processStream.StreamReader, testContext, testOptions, callback, debugEnabled));

            while (readerTask.Status == TaskStatus.WaitingToRun ||
                   (readerTask.Status == TaskStatus.Running && (DateTime.Now - lastTestEvent).TotalMilliseconds < timeout))
            {
                Thread.Sleep(100);
            }

            if (readerTask.IsCompleted)
            {
                ChutzpahTracer.TraceInformation("Finished reading stream from test file '{0}'", testContext.FirstInputTestFile);
                return(readerTask.Result);
            }
            else
            {
                // We timed out so kill the process and return an empty test file summary
                ChutzpahTracer.TraceError("Test file '{0}' timed out after running for {1} milliseconds", testContext.FirstInputTestFile, (DateTime.Now - lastTestEvent).TotalMilliseconds);

                processStream.TimedOut = true;
                processStream.KillProcess();
                return(testContext.ReferencedFiles.Where(x => x.IsFileUnderTest).Select(file => new TestFileSummary(file.Path)).ToList());
            }
        }
예제 #29
0
        private ICoverageEngine GetConfiguredCoverageEngine(TestOptions options, ChutzpahTestSettingsFile chutzpahTestSettings)
        {
            // Don't run code coverage if in discovery mode
            if (options.TestExecutionMode == TestExecutionMode.Discovery)
            {
                return(null);
            }

            var codeCoverageEnabled = (!chutzpahTestSettings.EnableCodeCoverage.HasValue && options.CoverageOptions.Enabled) ||
                                      (chutzpahTestSettings.EnableCodeCoverage.HasValue && chutzpahTestSettings.EnableCodeCoverage.Value);

            if (!codeCoverageEnabled)
            {
                return(null);
            }

            ChutzpahTracer.TraceInformation("Setting up code coverage in test context");
            mainCoverageEngine.ClearPatterns();
            mainCoverageEngine.AddIncludePatterns(chutzpahTestSettings.CodeCoverageIncludes.Concat(options.CoverageOptions.IncludePatterns));
            mainCoverageEngine.AddExcludePatterns(chutzpahTestSettings.CodeCoverageExcludes.Concat(options.CoverageOptions.ExcludePatterns));
            return(mainCoverageEngine);
        }
예제 #30
0
        public bool IsTestFile(string file)
        {
            ChutzpahTracer.TraceInformation("Determining if '{0}' might be a test file", file);
            if (string.IsNullOrWhiteSpace(file))
            {
                return(false);
            }

            PathInfo pathInfo     = fileProbe.GetPathInfo(file);
            PathType testFileKind = pathInfo.Type;
            string   testFilePath = pathInfo.FullPath;

            if (testFilePath == null || !IsValidTestPathType(testFileKind))
            {
                ChutzpahTracer.TraceInformation("Rejecting '{0}' since either it doesnt exist or does not have test extension", file);
                return(false);
            }

            var testFileDirectory    = Path.GetDirectoryName(testFilePath);
            var chutzpahTestSettings = settingsService.FindSettingsFile(testFileDirectory);

            if (!IsTestPathIncluded(testFilePath, chutzpahTestSettings))
            {
                ChutzpahTracer.TraceInformation("Excluded test file '{0}' given chutzpah.json settings", testFilePath);
                return(false);
            }

            string testFileText = fileSystem.GetText(testFilePath);

            IFrameworkDefinition definition;
            var frameworkDetetected = TryDetectFramework(testFileText, testFileKind, chutzpahTestSettings, out definition);

            if (frameworkDetetected)
            {
                ChutzpahTracer.TraceInformation("Assuming '{0}' is a test file", file);
            }

            return(frameworkDetetected);
        }