/// <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>
 /// Runs tests on agent
 /// </summary>
 /// <param name="test">The test.</param>
 /// <param name="configurationSubstitutions">The configuration substitutions.</param>
 /// <returns></returns>
 public TestResult RunTests(TestUnit test, DistributedConfigurationSubstitutions configurationSubstitutions)
 {
     throw new CommunicationException();
 }
        /// <summary>
        /// Gets the NUnit test result.
        /// </summary>
        /// <param name="test">The test.</param>
        /// <param name="project">The project.</param>
        /// <param name="configurationSubstitutions">The configuration substitutions.</param>
        /// <param name="isChild">if set to <c>true</c> [is child].</param>
        /// <returns></returns>
        public TestResult GetNUnitTestResult(TestUnit test, TestProject project, DistributedConfigurationSubstitutions configurationSubstitutions, bool isChild = false)
        {
            var nativeRunner = runnerCache.GetOrLoad(test.Run, configurationSubstitutions,
                                                     () =>
                                                         {
                                                             initializer.Initialize();

                                                             string configurationFileName =
                                                                 configurationOperator.GetSubstitutedConfigurationFile(project,
                                                                                                            test.Run.
                                                                                                                NUnitParameters,
                                                                                                            configurationSubstitutions);

                                                             var mappedAssemblyFile = Path.Combine(project.Path,
                                                                                                   Path.GetFileName(
                                                                                                       test.Run.NUnitParameters.
                                                                                                           AssembliesToTest[0]));

                                                             TestPackage package;
                                                             if (!NUnitProject.IsNUnitProjectFile(mappedAssemblyFile))
                                                                 package = new TestPackage(mappedAssemblyFile);
                                                             else
                                                             {
                                                                 var nunitProject = new NUnitProject(mappedAssemblyFile);
                                                                 nunitProject.Load();
                                                                 if (!string.IsNullOrEmpty(test.Run.NUnitParameters.Configuration))
                                                                     nunitProject.SetActiveConfig(test.Run.NUnitParameters.Configuration);

                                                                 package = nunitProject.ActiveConfig.MakeTestPackage();
                                                             }

                                                             package.Settings["ShadowCopyFiles"] = true;
                                                             package.AutoBinPath = true;
                                                             if (!string.IsNullOrEmpty(configurationFileName))
                                                             {
                                                                 package.ConfigurationFile = configurationFileName;
                                                             }

                                                             var nativeTestRunner = new NDistribUnitProcessRunner(log);
                                                             nativeTestRunner.Load(package);
                                                             return nativeTestRunner;
                                                         });

            var testOptions = test.Run.NUnitParameters;
            TestResult testResult = null;

            try
            {
                Action runTest = ()=>
                                     {
                                         try
                                         {
                                             testResult = nativeRunner.Run(new NullListener(),
                                                                           new NUnitTestsFilter(
                                                                               testOptions.IncludeCategories,
                                                                               testOptions.ExcludeCategories,
                                                                               test.UniqueTestId).NativeFilter);
                                             nativeRunner.CleanupAfterRun();
                                         }
                                         //TODO: remove this. This is for tracking purposes only
                                         catch(AppDomainUnloadedException ex)
                                         {
                                             log.Warning("AppDomainUnloadedException is still being thrown", ex);
                                             if (!isChild)
                                             {
                                                 runnerCache.Remove(test.Run, configurationSubstitutions);
                                                 testResult = GetNUnitTestResult(test, project,
                                                                                 configurationSubstitutions,
                                                                                 isChild: true);
                                             }
                                             else
                                                 throw;
                                         }
                                     };

                if (Thread.CurrentThread.GetApartmentState() != ApartmentState.STA
                    && !Thread.CurrentThread.TrySetApartmentState(ApartmentState.STA))
                {
                    var thread = new Thread(()=> exceptionCatcher.Run(runTest));
                    thread.SetApartmentState(ApartmentState.STA);
                    thread.Start();
                    thread.Join();
                }
                else
                {
                    runTest();
                }
            }
            catch (Exception ex)
            {
                log.Error("Error while running test on agent", ex);
                throw;
            }
            return testResult;
        }
        /// <summary>
        /// Runs the specified test.
        /// </summary>
        /// <param name="test">The test.</param>
        /// <param name="configurationSubstitutions"></param>
        /// <returns></returns>
        public TestResult Run(TestUnit test, DistributedConfigurationSubstitutions configurationSubstitutions)
        {
            var project = projects.Get(test.Run);
            if (project == null)
            {
                log.Info("Project file was not found. Throwing exception");
                return TestResultFactory.GetProjectRetrievalFailure(test);
            }

            log.BeginActivity("Starting test execution...");
            var nUnitTestResult = GetNUnitTestResult(test, project, configurationSubstitutions);
            log.EndActivity("Test execution was finished");

            return nUnitTestResult;
        }
        /// <summary>
        /// Runs tests on agent
        /// </summary>
        /// <param name="test">The test.</param>
        /// <param name="configurationSubstitutions">The configuration substitutions.</param>
        /// <returns></returns>
        public TestResult RunTests(TestUnit test, DistributedConfigurationSubstitutions configurationSubstitutions)
        {
            if (IsStarted)
                return TestRunner.RunTests(test, configurationSubstitutions);

            throw new CommunicationException("Agent seems to be not available");
        }
 /// <summary>
 /// Gets the project retrieval failure.
 /// </summary>
 /// <param name="test">The test.</param>
 /// <param name="exception">The exception.</param>
 /// <returns></returns>
 public static TestResult GetProjectRetrievalFailure(TestUnit test, Exception exception = null)
 {
     return GetResultForTest(test, exception);
 }
        internal static TestResult GetResultForTest(TestUnit test, Exception exception)
        {
            var description = string.Format("There was an error, when running '{0}'", test.UniqueTestId);

            var projectResult = GetResult(exception, description, TestType.Project, string.Empty);
            var assemblyResult = GetResult(exception, description, TestType.Assembly, test.AssemblyName);
            projectResult.AddResult(assemblyResult);

            var previous = assemblyResult;
            var splittedTestName = test.UniqueTestId.Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries);

            // Add namespace parts
            int position;
            for (position = 0; position < splittedTestName.Length - (test.Info.IsSuite ? 1: 2); position++)
            {
                var namespacePart = GetResult(exception, description, TestType.Namespace, string.Join(".", splittedTestName, 0, position + 1));

                previous.AddResult(namespacePart);
                previous = namespacePart;
            }

            // Add test suite
            TestResult suiteResult = GetResult(exception, description, TestType.TestFixture, string.Join(".", splittedTestName, 0, position + 1));
            previous.AddResult(suiteResult);

            // Add test case, if it is not a suite
            if (!test.Info.IsSuite)
                suiteResult.AddResult(GetResult(exception, description, TestType.TestMethod, test.UniqueTestId, false));

            return projectResult;
        }