Task ITestDiscoverer.AnalyzeDocumentAsync(DocumentTestDiscoveryContext context) { if (context.CancellationToken.IsCancellationRequested) { return(Task.FromCanceled(context.CancellationToken)); } using (var discoverySink = new TestDiscoveryVisitor()) using (var xunit2 = new Xunit2Discoverer( AppDomainSupport.Denied, sourceInformationProvider: DummySourceInformationProvider.Instance, assemblyInfo: new SourceAssemblyInfo(context), xunitExecutionAssemblyPath: XunitExecutionAssemblyPath.Value, verifyAssembliesOnDisk: false)) { xunit2.Find(includeSourceInformation: false, messageSink: discoverySink, discoveryOptions: TestFrameworkOptions.ForDiscovery()); while (!discoverySink.Finished.WaitOne(50)) { if (context.CancellationToken.IsCancellationRequested) { break; } TrySendDiscoveredTestCases(context, discoverySink); } TrySendDiscoveredTestCases(context, discoverySink); } return(context.CancellationToken.IsCancellationRequested ? Task.FromCanceled(context.CancellationToken) : Task.CompletedTask); }
public static IEnumerable <ITestCase> Find(this Xunit2Discoverer discoverer, Type type) { using (var sink = new SpyMessageSink <IDiscoveryCompleteMessage>()) { discoverer.Find(type.FullName, false, sink, TestFrameworkOptions.ForDiscovery()); sink.Finished.WaitOne(); return(sink.Messages.OfType <ITestCaseDiscoveryMessage>().Select(message => message.TestCase).ToList()); } }
public static IEnumerable <ITestCase> Find(this Xunit2Discoverer discoverer, Type type) { #pragma warning disable IDE0063 // 'using' statement can be simplified using (var sink = new SpyMessageSink <IDiscoveryCompleteMessage>()) { discoverer.Find(type.FullName, false, sink, TestFrameworkOptions.ForDiscovery()); sink.Finished.WaitOne(); return(sink.Messages.OfType <ITestCaseDiscoveryMessage>() .Select(message => message.TestCase).ToArray()); } #pragma warning restore IDE0063 // 'using' statement can be simplified }
public static IEnumerable <ITestCase> Find(this Xunit2Discoverer discoverer, string collectionName) { using (var sink = new SpyMessageSink <IDiscoveryCompleteMessage>()) { discoverer.Find(false, sink, TestFrameworkOptions.ForDiscovery()); sink.Finished.WaitOne(); return(sink.Messages.OfType <ITestCaseDiscoveryMessage>() .Select(message => message.TestCase) .Where(message => message.TestMethod.TestClass.TestCollection.DisplayName == collectionName) .ToList()); } }
public static Queue <ITestCase> Find(this Xunit2Discoverer discoverer, Type type, TestAssemblyConfiguration testAssemblyConfiguration) { using (var sink = new SpyMessageSink <IDiscoveryCompleteMessage>()) { discoverer.Find(type.FullName, false, sink, TestFrameworkOptions.ForDiscovery(testAssemblyConfiguration)); sink.Finished.Wait(); return(new Queue <ITestCase>( sink.Messages.OfType <ITestCaseDiscoveryMessage>() .Select(message => message.TestCase))); } }
public static Queue <ITestCase> Find(this Xunit2Discoverer discoverer, string collectionName, TestAssemblyConfiguration testAssemblyConfiguration) { using (var sink = new SpyMessageSink <IDiscoveryCompleteMessage>()) { discoverer.Find(false, sink, TestFrameworkOptions.ForDiscovery(testAssemblyConfiguration)); sink.Finished.Wait(); return(new Queue <ITestCase>( sink.Messages.OfType <ITestCaseDiscoveryMessage>() .Select(message => message.TestCase) .Where(testCase => testCase.TestMethod.TestClass.TestCollection.DisplayName == collectionName))); } }
static int Main(string[] args) { if (args.Length < 3) { Console.WriteLine("Usage: <outfile> <corefx dir> <test assembly filename> <xunit console options>"); return(1); } var outfile_name = args [0]; var sdkdir = args [1] + "/artifacts/bin/runtime/netcoreapp-OSX-Debug-x64"; args = args.Skip(2).ToArray(); // Despite a lot of effort, couldn't get dotnet to load these assemblies from the sdk dir, so copy them to our binary dir File.Copy($"{sdkdir}/Microsoft.DotNet.PlatformAbstractions.dll", AppContext.BaseDirectory, true); File.Copy($"{sdkdir}/CoreFx.Private.TestUtilities.dll", AppContext.BaseDirectory, true); File.Copy($"{sdkdir}/Microsoft.DotNet.XUnitExtensions.dll", AppContext.BaseDirectory, true); var cmdline = CommandLine.Parse(args); // Ditto File.Copy(cmdline.Project.Assemblies.First().AssemblyFilename, AppContext.BaseDirectory, true); var assembly = Assembly.LoadFrom(Path.Combine(AppContext.BaseDirectory, Path.GetFileName(cmdline.Project.Assemblies.First().AssemblyFilename))); var msg_sink = new MsgSink(); var xunit2 = new Xunit2Discoverer(AppDomainSupport.Denied, new NullSourceInformationProvider(), new ReflectionAssemblyInfo(assembly), null, null, msg_sink); var sink = new TestDiscoverySink(); var config = new TestAssemblyConfiguration() { DiagnosticMessages = true, InternalDiagnosticMessages = true, PreEnumerateTheories = false }; xunit2.Find(false, sink, TestFrameworkOptions.ForDiscovery(config)); sink.Finished.WaitOne(); foreach (XunitTestCase tc in sink.TestCases) { ComputeTraits(assembly, tc); } var w = File.CreateText(outfile_name); w.WriteLine("using System;"); w.WriteLine("using System.Reflection;"); w.WriteLine("public class RunTests {"); w.WriteLine("\tpublic static int Main () {"); w.WriteLine("\t\tint nrun = 0;"); w.WriteLine("\t\tint nfailed = 0;"); var filters = cmdline.Project.Filters; foreach (XunitTestCase tc in sink.TestCases) { var m = ((ReflectionMethodInfo)tc.Method).MethodInfo; //Console.WriteLine ("" + m.ReflectedType + " " + m + " " + (tc.TestMethodArguments == null)); if (tc.TestMethodArguments != null || m.GetParameters().Length > 0) { continue; } var t = m.ReflectedType; if (t.IsGenericType) { continue; } /* * foreach (var trait in tc.Traits) { * foreach (var s in trait.Value) * Console.WriteLine (m.Name + " " + trait.Key + " " + s); * } */ if (!filters.Filter(tc)) { //Console.WriteLine ("FILTERED: " + m); continue; } string typename = GetTypeName(t); w.WriteLine($"Console.WriteLine (\"{typename}:{m.Name}...\");"); w.WriteLine("\t\tnrun ++;"); w.WriteLine("\t\ttry {"); if (m.IsStatic) { if (!m.IsPublic) { w.WriteLine($"\t\ttypeof({typename}).GetMethod (\"{m.Name}\", BindingFlags.Static|BindingFlags.NonPublic).Invoke(null, null);"); } else { w.WriteLine($"\t\t{typename}.{m.Name} ();"); } } else { if (typeof(IDisposable).IsAssignableFrom(t)) { w.WriteLine($"\t\tusing (var o = new {typename} ()) {{"); } else { w.WriteLine("\t\t{"); w.WriteLine($"\t\t\tvar o = new {typename} ();"); } w.WriteLine($"\t\t\to.{m.Name} ();"); w.WriteLine("\t\t}"); } w.WriteLine("\t\t} catch (Exception ex) { nfailed ++; Console.WriteLine (\"FAILED: \" + ex); }"); if (cmdline.StopOnFail) { w.WriteLine("\t\tif (nfailed > 0) return 1;"); } } w.WriteLine("\t\tConsole.WriteLine (\"RUN: \" + nrun + \", FAILED: \" + nfailed);"); w.WriteLine("\t\treturn 0;"); w.WriteLine("\t}"); w.WriteLine("}"); w.Close(); return(0); }
static int Main(string[] args) { if (args.Length < 3) { Console.WriteLine("Usage: <out-dir> <corefx dir> <test assembly filename> <xunit console options>"); return(1); } var testAssemblyName = Path.GetFileNameWithoutExtension(args [2]); var testAssemblyFull = Path.GetFullPath(args[2]); var outdir_name = Path.Combine(args [0], testAssemblyName); var sdkdir = args [1] + "/artifacts/bin/runtime/netcoreapp-OSX-Debug-x64"; args = args.Skip(2).ToArray(); // Response file support var extra_args = new List <string> (); for (int i = 0; i < args.Length; ++i) { var arg = args [i]; if (arg [0] == '@') { foreach (var line in File.ReadAllLines(arg.Substring(1))) { if (line.Length == 0 || line [0] == '#') { continue; } extra_args.AddRange(line.Split(' ')); } args [i] = ""; } } args = args.Where(s => s != String.Empty).Concat(extra_args).ToArray(); // Despite a lot of effort, couldn't get dotnet to load these assemblies from the sdk dir, so copy them to our binary dir // File.Copy ($"{sdkdir}/Microsoft.DotNet.PlatformAbstractions.dll", AppContext.BaseDirectory, true); File.Copy($"{sdkdir}/CoreFx.Private.TestUtilities.dll", AppContext.BaseDirectory, true); File.Copy($"{sdkdir}/Microsoft.DotNet.XUnitExtensions.dll", AppContext.BaseDirectory, true); var cmdline = CommandLine.Parse(args); // Ditto File.Copy(cmdline.Project.Assemblies.First().AssemblyFilename, AppContext.BaseDirectory, true); var assembly = Assembly.LoadFrom(Path.Combine(AppContext.BaseDirectory, Path.GetFileName(cmdline.Project.Assemblies.First().AssemblyFilename))); var msg_sink = new MsgSink(); var xunit2 = new Xunit2Discoverer(AppDomainSupport.Denied, new NullSourceInformationProvider(), new ReflectionAssemblyInfo(assembly), null, null, msg_sink); var sink = new TestDiscoverySink(); var config = new TestAssemblyConfiguration() { DiagnosticMessages = true, InternalDiagnosticMessages = true, PreEnumerateTheories = false }; xunit2.Find(false, sink, TestFrameworkOptions.ForDiscovery(config)); sink.Finished.WaitOne(); foreach (XunitTestCase tc in sink.TestCases) { ComputeTraits(assembly, tc); } // Compute testcase data var tc_data = new Dictionary <XunitTestCase, List <CaseData> > (); foreach (XunitTestCase tc in sink.TestCases) { var m = ((ReflectionMethodInfo)tc.Method).MethodInfo; var t = m.ReflectedType; var cases = new List <CaseData> (); if (m.GetParameters().Length > 0) { foreach (var cattr in m.GetCustomAttributes(true)) { if (cattr is InlineDataAttribute) { var data = ((InlineDataAttribute)cattr).GetData(null).First(); if (data == null) { data = new object [m.GetParameters().Length]; } if (data.Length != m.GetParameters().Length) { throw new Exception(); } bool unhandled = false; foreach (var val in data) { if (val is float || val is double) { unhandled = true; } if (val is Type) { var type = val as Type; if (!type.IsVisible) { unhandled = true; } } if (val is Enum) { if (!val.GetType().IsPublic) { unhandled = true; } } } if (!unhandled) { cases.Add(new CaseData() { Values = data }); } } } } else { cases.Add(new CaseData()); } tc_data [tc] = cases; } #if FALSE //w.WriteLine ($"\t\ttypeof({typename}).GetMethod (\"{m.Name}\", BindingFlags.Static|BindingFlags.NonPublic).Invoke(null, null);"); //w.WriteLine ($"\t\tusing (var o = new {typename} ()) {{"); //if (cmdline.StopOnFail) //w.WriteLine ("\t\tif (nfailed > 0) return 1;"); //w.WriteLine ("\t\tConsole.WriteLine (\"RUN: \" + nrun + \", FAILED: \" + nfailed);"); #endif var cu = new CodeCompileUnit(); var ns = new CodeNamespace(""); cu.Namespaces.Add(ns); ns.Imports.Add(new CodeNamespaceImport("System")); ns.Imports.Add(new CodeNamespaceImport("System.Reflection")); var code_class = new CodeTypeDeclaration("RunTests"); ns.Types.Add(code_class); var code_main = new CodeEntryPointMethod(); code_main.ReturnType = new CodeTypeReference("System.Int32"); code_class.Members.Add(code_main); var statements = code_main.Statements; statements.Add(new CodeVariableDeclarationStatement(typeof(int), "nrun", new CodePrimitiveExpression(0))); statements.Add(new CodeVariableDeclarationStatement(typeof(int), "nfailed", new CodePrimitiveExpression(0))); int nskipped = 0; var filters = cmdline.Project.Filters; foreach (XunitTestCase tc in sink.TestCases) { var m = ((ReflectionMethodInfo)tc.Method).MethodInfo; //Console.WriteLine ("" + m.ReflectedType + " " + m + " " + (tc.TestMethodArguments == null)); var t = m.ReflectedType; if (t.IsGenericType) { nskipped++; continue; } if (!filters.Filter(tc)) { nskipped++; continue; } var cases = tc_data [tc]; int caseindex = 0; foreach (var test in cases) { string typename = GetTypeName(t); string msg; if (cases.Count > 1) { msg = $"{typename}.{m.Name}[{caseindex}] ..."; } else { msg = $"{typename}.{m.Name} ..."; } caseindex++; statements.Add(new CodeMethodInvokeExpression(new CodeTypeReferenceExpression("Console"), "WriteLine", new CodeExpression [] { new CodePrimitiveExpression(msg) })); statements.Add(new CodeAssignStatement(new CodeVariableReferenceExpression("nrun"), new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression("nrun"), CodeBinaryOperatorType.Add, new CodePrimitiveExpression(1)))); var try1 = new CodeTryCatchFinallyStatement(); statements.Add(try1); if (!m.IsStatic) { // FIXME: Disposable try1.TryStatements.Add(new CodeVariableDeclarationStatement("var", "o", new CodeObjectCreateExpression(t, new CodeExpression[] {}))); } if (!m.IsPublic) { // FIXME: nskipped++; } else { CodeMethodInvokeExpression call; if (m.IsStatic) { call = new CodeMethodInvokeExpression(new CodeTypeReferenceExpression(t), m.Name, new CodeExpression [] {}); } else { call = new CodeMethodInvokeExpression(new CodeVariableReferenceExpression("o"), m.Name, new CodeExpression [] {}); } if (test.Values != null) { var parameters = m.GetParameters(); for (var index = 0; index < test.Values.Length; index++) { var val = test.Values [index]; call.Parameters.Add(EncodeValue(val, parameters [index].ParameterType)); } } try1.TryStatements.Add(call); } var catch1 = new CodeCatchClause("ex", new CodeTypeReference("System.Exception")); catch1.Statements.Add(new CodeAssignStatement(new CodeVariableReferenceExpression("nfailed"), new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression("nfailed"), CodeBinaryOperatorType.Add, new CodePrimitiveExpression(1)))); catch1.Statements.Add(new CodeMethodInvokeExpression(new CodeTypeReferenceExpression("Console"), "WriteLine", new CodeExpression [] { new CodeBinaryOperatorExpression( new CodePrimitiveExpression("FAILED: "), CodeBinaryOperatorType.Add, new CodeVariableReferenceExpression("ex")) })); try1.CatchClauses.Add(catch1); } } statements.Add(new CodeMethodInvokeExpression(new CodeTypeReferenceExpression("Console"), "WriteLine", new CodeExpression [] { new CodeBinaryOperatorExpression( new CodePrimitiveExpression("RUN: "), CodeBinaryOperatorType.Add, new CodeVariableReferenceExpression("nrun")) })); statements.Add(new CodeMethodInvokeExpression(new CodeTypeReferenceExpression("Console"), "WriteLine", new CodeExpression [] { new CodeBinaryOperatorExpression( new CodePrimitiveExpression("FAILURES: "), CodeBinaryOperatorType.Add, new CodeVariableReferenceExpression("nfailed")) })); statements.Add(new CodeMethodInvokeExpression(new CodeTypeReferenceExpression("Console"), "WriteLine", new CodeExpression [] { new CodeBinaryOperatorExpression( new CodePrimitiveExpression("SKIPPED: "), CodeBinaryOperatorType.Add, new CodePrimitiveExpression(nskipped)) })); statements.Add(new CodeMethodReturnStatement(new CodePrimitiveExpression(0))); Directory.CreateDirectory(outdir_name); var outfile_name = Path.Combine(outdir_name, "runner.cs"); var provider = new CSharpCodeProvider(); using (var w2 = File.CreateText(outfile_name)) { provider.GenerateCodeFromCompileUnit(cu, w2, new CodeGeneratorOptions()); } var csproj_template = File.ReadAllText("gen-test.csproj.template"); csproj_template = csproj_template.Replace("#XUNIT_LOCATION#", sdkdir); csproj_template = csproj_template.Replace("#TEST_ASSEMBLY#", testAssemblyName); csproj_template = csproj_template.Replace("#TEST_ASSEMBLY_LOCATION#", testAssemblyFull); File.WriteAllText(Path.Combine(outdir_name, testAssemblyName + "-runner.csproj"), csproj_template); return(0); }
static int Main(string[] args) { if (args.Length < 3) { Console.WriteLine("Usage: <out-dir> <corefx dir> <test assembly filename> <xunit console options>"); return(1); } var testAssemblyName = Path.GetFileNameWithoutExtension(args [2]); var testAssemblyFull = Path.GetFullPath(args[2]); var outdir_name = Path.Combine(args [0], testAssemblyName); var sdkdir = args [1] + "/artifacts/bin/runtime/netcoreapp-OSX-Debug-x64"; args = args.Skip(2).ToArray(); // Response file support var extra_args = new List <string> (); for (int i = 0; i < args.Length; ++i) { var arg = args [i]; if (arg [0] == '@') { foreach (var line in File.ReadAllLines(arg.Substring(1))) { if (line.Length == 0 || line [0] == '#') { continue; } extra_args.AddRange(line.Split(' ')); } args [i] = ""; } } args = args.Where(s => s != String.Empty).Concat(extra_args).ToArray(); // Despite a lot of effort, couldn't get dotnet to load these assemblies from the sdk dir, so copy them to our binary dir // File.Copy ($"{sdkdir}/Microsoft.DotNet.PlatformAbstractions.dll", AppContext.BaseDirectory, true); File.Copy($"{sdkdir}/CoreFx.Private.TestUtilities.dll", AppContext.BaseDirectory, true); File.Copy($"{sdkdir}/Microsoft.DotNet.XUnitExtensions.dll", AppContext.BaseDirectory, true); var cmdline = CommandLine.Parse(args); // Ditto File.Copy(cmdline.Project.Assemblies.First().AssemblyFilename, AppContext.BaseDirectory, true); var assembly = Assembly.LoadFrom(Path.Combine(AppContext.BaseDirectory, Path.GetFileName(cmdline.Project.Assemblies.First().AssemblyFilename))); var msg_sink = new MsgSink(); var xunit2 = new Xunit2Discoverer(AppDomainSupport.Denied, new NullSourceInformationProvider(), new ReflectionAssemblyInfo(assembly), null, null, msg_sink); var sink = new TestDiscoverySink(); var config = new TestAssemblyConfiguration() { DiagnosticMessages = true, InternalDiagnosticMessages = true, PreEnumerateTheories = false }; xunit2.Find(false, sink, TestFrameworkOptions.ForDiscovery(config)); sink.Finished.WaitOne(); foreach (XunitTestCase tc in sink.TestCases) { ComputeTraits(assembly, tc); } // Compute testcase data var tc_data = new Dictionary <XunitTestCase, List <TcCase> > (); foreach (XunitTestCase tc in sink.TestCases) { var m = ((ReflectionMethodInfo)tc.Method).MethodInfo; var t = m.ReflectedType; var cases = new List <TcCase> (); if (m.GetParameters().Length > 0) { foreach (var cattr in m.GetCustomAttributes(true)) { if (cattr is InlineDataAttribute) { var data = ((InlineDataAttribute)cattr).GetData(null).First(); if (data == null) { data = new object [m.GetParameters().Length]; } if (data.Length != m.GetParameters().Length) { throw new Exception(); } bool unhandled = false; foreach (var val in data) { if (val is float || val is double) { unhandled = true; } if (val is Type) { var type = val as Type; if (!type.IsVisible) { unhandled = true; } } if (val is Enum) { if (!val.GetType().IsPublic) { unhandled = true; } } } if (!unhandled) { cases.Add(new TcCase() { Values = data }); } } else if (cattr is MemberDataAttribute memberData && memberData.Parameters.Length == 0) { MethodInfo testDataMethod = m.DeclaringType.GetMethod(memberData.MemberName); if (testDataMethod == null) { continue; } cases.Add(new TcCase { MemberDataMethod = testDataMethod }); } } } else { cases.Add(new TcCase()); } tc_data [tc] = cases; } var filters = cmdline.Project.Filters; // // Generate code using the roslyn syntax apis // Creating syntax nodes one-by-one is very cumbersome, so use // CSharpSyntaxTree.ParseText () to create them and ReplaceNode () to insert them into syntax trees. // var blocks = new List <BlockSyntax> (); foreach (XunitTestCase tc in sink.TestCases) { var m = ((ReflectionMethodInfo)tc.Method).MethodInfo; //Console.WriteLine ("" + m.ReflectedType + " " + m + " " + (tc.TestMethodArguments == null)); var t = m.ReflectedType; if (t.IsGenericType) { nskipped++; continue; } if (!filters.Filter(tc)) { nskipped++; continue; } var cases = tc_data [tc]; int caseindex = 0; foreach (var test in cases) { string typename = GetTypeName(t); string msg; if (cases.Count > 1) { msg = $"{typename}.{m.Name}[{caseindex}] ..."; } else { msg = $"{typename}.{m.Name} ..."; } caseindex++; var block = ParseText <BlockSyntax> (case_template .Replace("#MSG#", msg) .Replace("#NRUN#", test.MemberDataMethod == null ? "1" : ((IEnumerable)test.MemberDataMethod.Invoke(null, null)).Cast <object> ().Count().ToString())); // Obtain the node for the CALL () line var try_body_node = block.DescendantNodes().OfType <ExpressionStatementSyntax> ().Skip(2).First().Parent; // Replace with the generated call code var stmts = GenerateTcCall(t, test, m); blocks.Add(block.ReplaceNode(try_body_node, Block(stmts.ToArray()))); } } var cu = CSharpSyntaxTree.ParseText(runner_template.Replace("#NSKIPPED#", nskipped.ToString())).GetRoot(); // Replace the body of the Run () method with the generated body var run_body = cu.DescendantNodes().OfType <MethodDeclarationSyntax> ().First().DescendantNodes().OfType <BlockSyntax> ().First(); cu = cu.ReplaceNode(run_body, Block(blocks.ToArray())); // Create runner.cs Directory.CreateDirectory(outdir_name); var outfile_name = Path.Combine(outdir_name, "runner.cs"); File.WriteAllText(outfile_name, cu.NormalizeWhitespace().ToString()); // Generate csproj file var csproj_template = File.ReadAllText("gen-test.csproj.template"); csproj_template = csproj_template.Replace("#XUNIT_LOCATION#", sdkdir); csproj_template = csproj_template.Replace("#TEST_ASSEMBLY#", testAssemblyName); csproj_template = csproj_template.Replace("#TEST_ASSEMBLY_LOCATION#", testAssemblyFull); File.WriteAllText(Path.Combine(outdir_name, testAssemblyName + "-runner.csproj"), csproj_template); return(0); }