Esempio n. 1
0
 /// <summary>
 /// Print program usage information
 /// </summary>
 ///
 static void Usage()
 {
     EventHandlerPipeline.Raise(new ProgramUsageEvent()
     {
         Lines = ArgumentParser.GetUsage()
     });
 }
Esempio n. 2
0
        /// <summary>
        /// 4. Parse arguments and take action
        /// </summary>
        ///
        static int Main4(string[] args)
        {
            ArgumentParser.Parse(args);

            switch (ArgumentParser.OutputFormat)
            {
            case OutputFormats.Human:
                EventHandlerPipeline.Append(new HumanOutputEventHandler());
                break;

            case OutputFormats.Machine:
                EventHandlerPipeline.Append(new MachineOutputEventHandler());
                break;

            default:
                throw new Exception($"Unrecognised <outputformat> from parser {ArgumentParser.OutputFormat}");
            }

            if (!ArgumentParser.Success)
            {
                throw ArgumentParseError();
            }

            if (ArgumentParser.Help)
            {
                return(Help());
            }

            if (ArgumentParser.InProc)
            {
                return(InProc(ArgumentParser.TestFiles[0]));
            }

            return(Main5(ArgumentParser.TestFiles));
        }
Esempio n. 3
0
        /// <summary>
        /// Reinvoke testrunner to run an individual test file in its own process
        /// </summary>
        ///
        static bool Reinvoke(string testFile)
        {
            var exitCode =
                ProcessExtensions.ExecuteDotnet(
                    ProgramPath,
                    $"--inproc --outputformat machine \"{testFile}\"",
                    (proc, line) => {
                var e = MachineReadableEventSerializer.TryDeserialize(line);
                EventHandlerPipeline.Raise(
                    e ??
                    new StandardOutputEvent()
                {
                    ProcessId = proc.Id,
                    Message   = line,
                });
            },
                    (proc, line) => {
                EventHandlerPipeline.Raise(
                    new ErrorOutputEvent()
                {
                    ProcessId = proc.Id,
                    Message   = line,
                });
            });

            return(exitCode == 0);
        }
Esempio n. 4
0
 /// <summary>
 /// Handle user-facing error
 /// </summary>
 ///
 static void HandleUserException(UserException ue)
 {
     EventHandlerPipeline.Raise(new ProgramUserErrorEvent()
     {
         Message = ue.Message
     });
 }
Esempio n. 5
0
 /// <summary>
 /// 2. Set up required event handlers
 /// </summary>
 ///
 static int Main2(string[] args)
 {
     EventHandlerPipeline.Append(new MethodResultEventHandler());
     EventHandlerPipeline.Append(new TestResultEventHandler());
     EventHandlerPipeline.Append(new TestClassResultEventHandler());
     EventHandlerPipeline.Append(new TestAssemblyResultEventHandler());
     EventHandlerPipeline.Append(new TestContextEventHandler());
     return(Main3(args));
 }
Esempio n. 6
0
        /// <summary>
        /// Run tests in a [TestClass]
        /// </summary>
        ///
        static public void Run(TestClass testClass)
        {
            Guard.NotNull(testClass, nameof(testClass));

            EventHandlerPipeline.Raise(new TestClassBeginEvent()
            {
                FullName = testClass.FullName
            });

            do
            {
                //
                // Handle exclusion from the command line
                //
                if (!ArgumentParser.ClassShouldRun(testClass.FullName))
                {
                    EventHandlerPipeline.Raise(new TestClassIgnoredEvent()
                    {
                        IgnoredFromCommandLine = true
                    });
                    break;
                }

                //
                // Handle [Ignored] [TestClass]
                //
                if (testClass.IsIgnored)
                {
                    EventHandlerPipeline.Raise(new TestClassIgnoredEvent());
                    break;
                }

                //
                // Run [ClassInitialize] method
                //
                if (!MethodRunner.RunClassInitializeMethod(testClass))
                {
                    break;
                }

                //
                // Run [TestMethod]s
                //
                foreach (var testMethod in testClass.TestMethods)
                {
                    TestMethodRunner.Run(testMethod);
                }

                //
                // Run [ClassCleanup] method
                //
                MethodRunner.RunClassCleanupMethod(testClass);
            }while (false);

            EventHandlerPipeline.Raise(new TestClassEndEvent());
        }
Esempio n. 7
0
        /// <summary>
        /// --inproc: Run an individual test file in-process
        /// </summary>
        ///
        static int InProc(string testFile)
        {
            var eventHandler = new ResultAccumulatingEventHandler();

            using (EventHandlerPipeline.Append(eventHandler))
            {
                TestAssemblyRunner.Run(testFile);
            }
            return(eventHandler.TestAssemblyResults.Last().Success ? 0 : 1);
        }
Esempio n. 8
0
        /// <summary>
        /// Switch to using a specified assembly .config file (if present)
        /// </summary>
        ///
        static public void SwitchTo(string configPath)
        {
            if (!File.Exists(configPath))
            {
                return;
            }

            #if NET461
            AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", configPath);

            //
            // The following hackery forces the new config file to take effect
            //
            // See http://stackoverflow.com/questions/6150644/change-default-app-config-at-runtime/6151688#6151688
            //
            var initStateField =
                typeof(ConfigurationManager).GetField("s_initState", BindingFlags.NonPublic | BindingFlags.Static);
            if (initStateField != null)
            {
                initStateField.SetValue(null, 0);
            }

            var configSystemField =
                typeof(ConfigurationManager).GetField("s_configSystem", BindingFlags.NonPublic | BindingFlags.Static);
            if (configSystemField != null)
            {
                configSystemField.SetValue(null, null);
            }

            var clientConfigPathsType =
                typeof(ConfigurationManager)
                .Assembly
                .GetTypes()
                .FirstOrDefault(x => x.FullName == "System.Configuration.ClientConfigPaths");
            var currentField =
                clientConfigPathsType != null
                    ? clientConfigPathsType.GetField("s_current", BindingFlags.NonPublic | BindingFlags.Static)
                    : null;

            if (currentField != null)
            {
                currentField.SetValue(null, null);
            }

            EventHandlerPipeline.Raise(new TestAssemblyConfigFileSwitchedEvent()
            {
                Path = configPath
            });
            #endif
        }
        /// <summary>
        /// Run a test method (plus its intialize and cleanup methods, if present)
        /// </summary>
        ///
        /// <remarks>
        /// If the test method is decorated with [Ignore], nothing is run
        /// </remarks>
        ///
        static public void Run(TestMethod testMethod)
        {
            EventHandlerPipeline.Raise(new TestBeginEvent()
            {
                Name = testMethod.Name
            });

            do
            {
                //
                // Handle [Ignored] [TestMethod]
                //
                if (testMethod.IsIgnored)
                {
                    EventHandlerPipeline.Raise(new TestIgnoredEvent());
                    break;
                }

                //
                // Create instance of [TestClass]
                //
                var instance = Activator.CreateInstance(testMethod.TestClass.Type);

                //
                // Set TestContext property (if present)
                //
                MethodRunner.RunTestContextSetter(testMethod.TestClass, instance);

                //
                // Run [TestInitialize] method
                //
                if (!MethodRunner.RunTestInitializeMethod(testMethod.TestClass, instance))
                {
                    break;
                }

                //
                // Run [TestMethod]
                //
                MethodRunner.RunTestMethod(testMethod, instance);

                //
                // Run [TestCleanup] method
                //
                MethodRunner.RunTestCleanupMethod(testMethod.TestClass, instance);
            }while (false);

            EventHandlerPipeline.Raise(new TestEndEvent());
        }
Esempio n. 10
0
        /// <summary>
        /// Print program name, version, and copyright banner
        /// </summary>
        ///
        static void Banner()
        {
            var name      = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).ProductName;
            var version   = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).ProductVersion;
            var copyright = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).LegalCopyright;

            EventHandlerPipeline.Raise(
                new ProgramBannerEvent()
            {
                Lines = new[] {
                    $"{name} v{version}",
                    copyright,
                },
            });
        }
Esempio n. 11
0
        static public void RunTestContextSetter(TestClass testClass, object instance)
        {
            Guard.NotNull(testClass, nameof(testClass));
            Guard.NotNull(instance, nameof(instance));
            var method = testClass.TestContextSetter;

            if (method == null)
            {
                return;
            }
            EventHandlerPipeline.Raise(new TestContextSetterBeginEvent()
            {
                MethodName = method.Name
            });
            var success = Run(method, instance, true, null, false);

            EventHandlerPipeline.Raise(new TestContextSetterEndEvent());
        }
Esempio n. 12
0
        static public bool RunClassCleanupMethod(TestClass testClass)
        {
            Guard.NotNull(testClass, nameof(testClass));
            var method = testClass.ClassCleanupMethod;

            if (method == null)
            {
                return(true);
            }
            EventHandlerPipeline.Raise(new ClassCleanupMethodBeginEvent()
            {
                MethodName = method.Name
            });
            var success = Run(method, null, false, null, false);

            EventHandlerPipeline.Raise(new ClassCleanupMethodEndEvent());
            return(success);
        }
Esempio n. 13
0
        static public bool RunTestMethod(TestMethod testMethod, object instance)
        {
            Guard.NotNull(testMethod, nameof(testMethod));
            Guard.NotNull(instance, nameof(instance));
            EventHandlerPipeline.Raise(new TestMethodBeginEvent()
            {
                MethodName = testMethod.Name
            });
            var success = Run(
                testMethod.MethodInfo,
                instance,
                false,
                testMethod.ExpectedException,
                testMethod.AllowDerivedExpectedExceptionTypes);

            EventHandlerPipeline.Raise(new TestMethodEndEvent());
            return(success);
        }
Esempio n. 14
0
        /// <summary>
        /// Reinvoke testrunner to run an individual test file in its own process
        /// </summary>
        ///
        static bool Reinvoke(string testFile)
        {
            var args = new List <string>();

            args.Add("--inproc");
            args.Add("--outputformat machine");

            foreach (var @class in ArgumentParser.Classes)
            {
                args.Add($"--class {@class}");
            }

            foreach (var method in ArgumentParser.Methods)
            {
                args.Add($"--method {method}");
            }

            args.Add($"\"{testFile}\"");

            var exitCode =
                ProcessExtensions.ExecuteDotnet(
                    Assembly.GetExecutingAssembly().Location,
                    string.Join(" ", args),
                    (proc, line) => {
                var e = MachineReadableEventSerializer.TryDeserialize(line);
                EventHandlerPipeline.Raise(
                    e ??
                    new StandardOutputEvent()
                {
                    ProcessId = proc.Id,
                    Message   = line,
                });
            },
                    (proc, line) => {
                EventHandlerPipeline.Raise(
                    new ErrorOutputEvent()
                {
                    ProcessId = proc.Id,
                    Message   = line,
                });
            });

            return(exitCode == 0);
        }
Esempio n. 15
0
        static public bool RunTestInitializeMethod(TestClass testClass, object instance)
        {
            Guard.NotNull(testClass, nameof(testClass));
            Guard.NotNull(instance, nameof(instance));
            var method = testClass.TestInitializeMethod;

            if (method == null)
            {
                return(true);
            }
            EventHandlerPipeline.Raise(new TestInitializeMethodBeginEvent()
            {
                MethodName = method.Name
            });
            var success = Run(method, instance, false, null, false);

            EventHandlerPipeline.Raise(new TestInitializeMethodEndEvent());
            return(success);
        }
Esempio n. 16
0
        static public bool RunClassInitializeMethod(TestClass testClass)
        {
            Guard.NotNull(testClass, nameof(testClass));
            var method = testClass.ClassInitializeMethod;

            if (method == null)
            {
                return(true);
            }
            EventHandlerPipeline.Raise(
                new ClassInitializeMethodBeginEvent()
            {
                MethodName          = method.Name,
                FirstTestMethodName = testClass.TestMethods.First().Name,
            });
            var success = Run(method, null, true, null, false);

            EventHandlerPipeline.Raise(new ClassInitializeMethodEndEvent());
            return(success);
        }
Esempio n. 17
0
        /// <summary>
        /// Handle internal TestRunner error
        /// </summary>
        ///
        static void HandleInternalException(Exception e)
        {
            EventHandlerPipeline.Raise(
                new ProgramInternalErrorEvent()
            {
                Exception = new ExceptionInfo(e)
            });

            if (e is ReflectionTypeLoadException rtle)
            {
                foreach (var le in rtle.LoaderExceptions)
                {
                    EventHandlerPipeline.Raise(
                        new ProgramInternalErrorEvent()
                    {
                        Exception = new ExceptionInfo(le)
                    });
                }
            }
        }
Esempio n. 18
0
        /// <summary>
        /// 5. Run test file(s)
        /// </summary>
        //
        static int Main5(IList <string> testFiles)
        {
            Banner();
            EventHandlerPipeline.Raise(new TestRunBeginEvent()
            {
            });
            bool success = true;

            foreach (var testFile in ArgumentParser.TestFiles)
            {
                if (!Reinvoke(testFile))
                {
                    success = false;
                }
            }
            EventHandlerPipeline.Raise(new TestRunEndEvent()
            {
                Result = new TestRunResult()
                {
                    Success = success
                }
            });
            return(success ? 0 : 1);
        }
        public static void Run(string assemblyPath)
        {
            Guard.NotNull(assemblyPath, nameof(assemblyPath));

            EventHandlerPipeline.Raise(new TestAssemblyBeginEvent()
            {
                Path = assemblyPath
            });

            do
            {
                //
                // Resolve full path to test assembly file
                //
                string fullAssemblyPath =
                    Path.IsPathRooted(assemblyPath)
                        ? assemblyPath
                        : Path.Combine(Environment.CurrentDirectory, assemblyPath);

                if (!File.Exists(fullAssemblyPath))
                {
                    EventHandlerPipeline.Raise(new TestAssemblyNotFoundEvent()
                    {
                        Path = fullAssemblyPath
                    });
                    break;
                }

                //
                // Load assembly
                //
                Assembly assembly;
                try
                {
                    assembly = Assembly.LoadFrom(fullAssemblyPath);
                }
                catch (BadImageFormatException)
                {
                    EventHandlerPipeline.Raise(new TestAssemblyNotDotNetEvent()
                    {
                        Path = fullAssemblyPath
                    });
                    break;
                }

                //
                // Interpret as test assembly
                //
                var testAssembly = TestAssembly.TryCreate(assembly);
                if (testAssembly == null)
                {
                    EventHandlerPipeline.Raise(new TestAssemblyNotTestEvent()
                    {
                        Path = fullAssemblyPath
                    });
                    break;
                }

                //
                // Activate the test assembly's .config file if present
                //
                ConfigFileSwitcher.SwitchTo(testAssembly.Assembly.Location + ".config");

                //
                // Run [AssemblyInitialize] method
                //
                if (!MethodRunner.RunAssemblyInitializeMethod(testAssembly))
                {
                    break;
                }

                //
                // Run tests in each [TestClass]
                //
                foreach (var testClass in testAssembly.TestClasses)
                {
                    TestClassRunner.Run(testClass);
                }

                //
                // Run [AssemblyCleanup] method
                //
                MethodRunner.RunAssemblyCleanupMethod(testAssembly);
            }while (false);

            EventHandlerPipeline.Raise(new TestAssemblyEndEvent());
        }
Esempio n. 20
0
        static bool Run(
            MethodInfo method,
            object instance,
            bool takesTestContext,
            Type expectedException,
            bool expectedExceptionAllowDerived)
        {
            Guard.NotNull(method, nameof(method));

            var parameters = takesTestContext ? new object[] { TestContextProxy.Proxy } : null;

            Exception exception            = null;
            bool      exceptionWasExpected = true;

            var traceListener = new EventTraceListener();

            Trace.Listeners.Add(traceListener);
            try
            {
                method.Invoke(instance, parameters);
            }
            catch (TargetInvocationException tie)
            {
                exception = tie.InnerException;
            }
            finally
            {
                Trace.Listeners.Remove(traceListener);
            }

            if (exception == null)
            {
                return(true);
            }

            var isExactExpectedException =
                expectedException != null &&
                exception.GetType() == expectedException;

            var isDerivedExpectedException =
                expectedException != null &&
                expectedExceptionAllowDerived &&
                exception.GetType().IsSubclassOf(expectedException);

            exceptionWasExpected = isExactExpectedException || isDerivedExpectedException;

            if (exceptionWasExpected)
            {
                EventHandlerPipeline.Raise(
                    new MethodExpectedExceptionEvent()
                {
                    ExpectedFullName = expectedException.FullName,
                    Exception        = new ExceptionInfo(exception),
                });
            }
            else
            {
                EventHandlerPipeline.Raise(
                    new MethodUnexpectedExceptionEvent()
                {
                    Exception = new ExceptionInfo(exception)
                });
            }

            return(exceptionWasExpected);
        }