/// <summary> /// Pretty much encapsulates the Round Trip invocation of the <see cref="Main"/> method /// exposed in the Code Generation Tooling. This is as comprehensive an integration test /// as there is short of calling out to the Command Line Process itself, never mind wiring /// up the Microsoft Build targets. /// </summary> /// <param name="bundleVisitor"></param> /// <param name="paramsVisitor"></param> /// <param name="registrySet"></param> /// <returns></returns> internal virtual int VerifyWithOperators( TestCaseBundleOperator bundleVisitor , ToolingParameterOperator paramsVisitor , out GeneratedSyntaxTreeRegistry registrySet) { bundleVisitor?.Invoke(Bundle); var builder = new ToolingParameterBuilder { Project = $"{Bundle.ProjectName}" } .AddReferenceToTypeAssembly <object>() .AddTypeAssemblyLocationBasedReferences <object>("netstandard.dll", "System.Runtime.dll") .AddReferenceToTypeAssembly <ImplementBuzInterfaceAttribute>() ; paramsVisitor?.Invoke(builder); var verified = Verify(builder.ToArray()); // Using the default surrogate implicit type conversion. TryLoad(Combine(builder.Output, builder.Generated), out registrySet , GeneratedSyntaxTreeRegistryJsonConverter.Converter) .AssertEqual(registrySet?.Any() == true) ; return(verified); }
// TODO: TBD: we think that this must be the case after every pass... // TODO: TBD: that is to say, we must be able to verify the integrity of the CG registries after each CG pass. public static GeneratedSyntaxTreeRegistry VerifyRegistry(this GeneratedSyntaxTreeRegistry actualRegistry , string expectedOutputDirectory, int?expectedCount = null) { // Not so much Asserting the Collection, as it is leaving it potentially Open Ended. void VerifyGenerated(GeneratedSyntaxTreeDescriptor x) { var sourceLastWritten = File.GetLastWriteTimeUtc(x.SourceFilePath.AssertFileExists()); var generatedPaths = x.GeneratedAssetKeys .Select(y => $"{Combine(expectedOutputDirectory, $"{y:D}.g.cs").AssertFileExists()}") .ToArray(); var allGeneratedLastWritten = generatedPaths.Select(File.GetLastWriteTimeUtc).ToArray(); allGeneratedLastWritten.All(y => y >= sourceLastWritten).AssertTrue(); } // TODO: TBD: it is probably fair to say this should be the case ALWAYS, regardless of the scenario. actualRegistry.AssertNotNull().OutputDirectory.AssertNotNull().AssertEqual(expectedOutputDirectory); if (expectedCount.HasValue) { actualRegistry.Count.AssertEqual(expectedCount.Value); } actualRegistry.ToList().ForEach(VerifyGenerated); return(actualRegistry); }
private void VerifySecondPass(ModuleKind module, ModuleKind modules , string expectedOutputDirectory, string expectedResponsePath , out GeneratedSyntaxTreeRegistry registrySet , bool usingResponseFile = DoNotUseResponseFile) { // Do a little Fact checking of the parameters. module.Distinct().ToArray().AssertTrue(x => x.Length == 1); modules.Distinct().ToArray().AssertTrue(x => x.Length >= 0); VerifyWithOperators( bundle => bundle.AddClassAnnotation <ImplementCloneableInterfaceAttribute>(module) , args => { /* Should add all of the modules that would ordinarily be discovered * on the heels of analyzing for the Code Generation Attribute(s). */ args.AddSources($"{Bundle.GetFilePath(module)}"); args.AddSources(modules.Distinct().Select(x => $"{Bundle.GetFilePath(x)}").ToArray()); args.AddDefines("DEBUG"); if (usingResponseFile) { args.UsingResponseFile = true; } // Ditto immediate verification. args.UsingResponseFile.AssertTrue(x => x == usingResponseFile); } , out registrySet).AssertEqual(DefaultErrorLevel); registrySet .VerifyRegistry(expectedOutputDirectory, 2) .VerifyResponseFile(expectedOutputDirectory, expectedResponsePath) ; }
private void VerifySinglePass(ModuleKind modules, ModuleKind module , string expectedOutputDirectory, string expectedResponsePath , out GeneratedSyntaxTreeRegistry registrySet , bool usingResponseFile = DoNotUseResponseFile) { // Do a little Fact checking of the parameters. modules.Distinct().ToArray().AssertTrue(x => x.Length > 1); module.Distinct().ToArray().AssertTrue(x => x.Length == 1); // TODO: TBD: some amount of this is "fixturing" I think... // TODO: TBD: but how much of it truly? VerifyWithOperators( bundle => { bundle.Extrapolate(modules); bundle.AddClassAnnotation <ImplementBuzInterfaceAttribute>(module); } , args => { args.AddSources($"{Bundle.GetFilePath(module)}"); args.AddDefines("DEBUG"); if (usingResponseFile) { args.UsingResponseFile = true; } // And do an immediate verification that we set it correctly. args.UsingResponseFile.AssertTrue(x => x == usingResponseFile); } , out registrySet).AssertEqual(DefaultErrorLevel); registrySet .VerifyRegistry(expectedOutputDirectory, 1) .VerifyResponseFile(expectedOutputDirectory, expectedResponsePath) ; }
public static GeneratedSyntaxTreeRegistry VerifyResponseFile( this GeneratedSyntaxTreeRegistry expectedRegistry , string expectedOutputDirectory, string expectedResponsePath) { var actualPaths = File.ReadLines(expectedResponsePath.AssertFileExists()).ToArray(); string CombineBaseDirectory(string fileName) => Combine(expectedOutputDirectory, fileName); var expectedPaths = expectedRegistry.SelectMany(d => d.GeneratedAssetKeys.Select(x => $"{x:D}.g.cs")) .Select(CombineBaseDirectory).ToArray(); // ReSharper disable CommentTypo // Make sure that the Actuals are Actuals, same for Expected. actualPaths.Length.AssertEqual(expectedPaths.Length); // In no particular order so long as all of the Paths are present and accounted for. foreach (var expectedPath in expectedPaths) { actualPaths.AssertContainsAll(expectedPath); } // ReSharper restore CommentTypo return(expectedRegistry); }