From 72a737f32be4e48d02220706116085476a7abeeb Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Thu, 14 Sep 2023 17:19:10 -0600 Subject: [PATCH] Share more boilerplate code in tests --- .../COMTests.cs | 90 +++++-------------- .../ConstantsTests.cs | 5 +- .../DelegateTests.cs | 5 +- .../ExternMethodTests.cs | 38 +++----- .../FriendlyOverloadTests.cs | 15 +--- .../GeneratorTestBase.cs | 18 ++-- .../GeneratorTests.cs | 34 ++----- .../HandleTests.cs | 32 ++----- .../StructTests.cs | 34 ++----- 9 files changed, 68 insertions(+), 203 deletions(-) diff --git a/test/Microsoft.Windows.CsWin32.Tests/COMTests.cs b/test/Microsoft.Windows.CsWin32.Tests/COMTests.cs index e32d9939..c466049c 100644 --- a/test/Microsoft.Windows.CsWin32.Tests/COMTests.cs +++ b/test/Microsoft.Windows.CsWin32.Tests/COMTests.cs @@ -16,10 +16,7 @@ public COMTests(ITestOutputHelper logger) public void FriendlyOverloadOfCOMInterfaceRemovesParameter() { const string ifaceName = "IEnumDebugPropertyInfo"; - this.generator = this.CreateGenerator(); - Assert.True(this.generator.TryGenerate(ifaceName, CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi(ifaceName); Assert.Contains(this.FindGeneratedMethod("Next"), m => m.ParameterList.Parameters.Count == 3 && m.ParameterList.Parameters[0].Modifiers.Any(SyntaxKind.ThisKeyword)); } @@ -27,10 +24,7 @@ public void FriendlyOverloadOfCOMInterfaceRemovesParameter() public void IDispatchDerivedInterface() { const string ifaceName = "IInkRectangle"; - this.generator = this.CreateGenerator(); - Assert.True(this.generator.TryGenerate(ifaceName, CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi(ifaceName); #pragma warning disable CS0618 // Type or member is obsolete Assert.Contains(this.FindGeneratedType(ifaceName), t => t.BaseList is null && t.AttributeLists.Any(al => al.Attributes.Any(a => a.Name is IdentifierNameSyntax { Identifier: { ValueText: "InterfaceType" } } && a.ArgumentList?.Arguments[0].Expression is MemberAccessExpressionSyntax { Name: IdentifierNameSyntax { Identifier: { ValueText: nameof(ComInterfaceType.InterfaceIsIDispatch) } } }))); #pragma warning restore CS0618 // Type or member is obsolete @@ -40,10 +34,7 @@ public void IDispatchDerivedInterface() public void IInpectableDerivedInterface() { const string ifaceName = "IUserConsentVerifierInterop"; - this.generator = this.CreateGenerator(); - Assert.True(this.generator.TryGenerate(ifaceName, CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi(ifaceName); Assert.Contains(this.FindGeneratedType(ifaceName), t => t.BaseList is null && ((InterfaceDeclarationSyntax)t).Members.Count == 1 && t.AttributeLists.Any(al => al.Attributes.Any(a => a.Name is IdentifierNameSyntax { Identifier: { ValueText: "InterfaceType" } } && a.ArgumentList?.Arguments[0].Expression is MemberAccessExpressionSyntax { Name: IdentifierNameSyntax { Identifier: { ValueText: nameof(ComInterfaceType.InterfaceIsIInspectable) } } }))); // Make sure the WinRT marshaler was not brought in @@ -55,9 +46,7 @@ public void COMPropertiesAreGeneratedAsInterfaceProperties(bool allowMarshaling) { const string ifaceName = "IADsClass"; this.generator = this.CreateGenerator(DefaultTestGeneratorOptions with { AllowMarshaling = allowMarshaling }); - Assert.True(this.generator.TryGenerate(ifaceName, CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi(ifaceName); InterfaceDeclarationSyntax ifaceSyntax; if (allowMarshaling) { @@ -83,9 +72,7 @@ public void COMPropertiesAreGeneratedAsInterfaceProperties_NonConsecutiveAccesso { const string ifaceName = "IUIAutomationProxyFactoryEntry"; this.generator = this.CreateGenerator(DefaultTestGeneratorOptions with { AllowMarshaling = allowMarshaling }); - Assert.True(this.generator.TryGenerate(ifaceName, CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi(ifaceName); InterfaceDeclarationSyntax ifaceSyntax; if (allowMarshaling) { @@ -107,9 +94,7 @@ public void COMPropertiesAreGeneratedAsStructProperties() { const string ifaceName = "IADsClass"; this.generator = this.CreateGenerator(DefaultTestGeneratorOptions with { AllowMarshaling = false }); - Assert.True(this.generator.TryGenerate(ifaceName, CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi(ifaceName); StructDeclarationSyntax structSyntax = Assert.Single(this.FindGeneratedType(ifaceName).OfType()); // Check a property where we expect just a getter. @@ -126,9 +111,7 @@ public void COMPropertiesAreGeneratedAsStructProperties_NonConsecutiveAccessors( { const string ifaceName = "IUIAutomationProxyFactoryEntry"; this.generator = this.CreateGenerator(DefaultTestGeneratorOptions with { AllowMarshaling = false }); - Assert.True(this.generator.TryGenerate(ifaceName, CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi(ifaceName); StructDeclarationSyntax structSyntax = Assert.Single(this.FindGeneratedType(ifaceName).OfType()); // Check for a property where the interface declares the getter and setter in non-consecutive rows of the VMT. @@ -151,9 +134,7 @@ public void COMPropertiesAreGeneratedAsStructProperties_NonConsecutiveAccessors( public void COMPropertiesAreGeneratedAsStructProperties_NonConsecutiveAccessors_IPicture() { this.generator = this.CreateGenerator(DefaultTestGeneratorOptions with { AllowMarshaling = false }); - Assert.True(this.generator.TryGenerate("IPicture", CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi("IPicture"); } [Theory, PairwiseData] @@ -161,9 +142,7 @@ public void COMPropertiesAreGeneratedAsMethodsWhenTheirReturnTypesDiffer([Combin { const string ifaceName = "IHTMLImgElement"; this.generator = this.CreateGenerator(DefaultTestGeneratorOptions with { AllowMarshaling = marshaling > 0, ComInterop = new GeneratorOptions.ComInteropOptions { UseIntPtrForComOutPointers = marshaling == 1 } }); - Assert.True(this.generator.TryGenerate(ifaceName, CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi(ifaceName); InterfaceDeclarationSyntax ifaceSyntax; if (marshaling > 0) { @@ -208,10 +187,7 @@ public void WinRTInterfaceWithWinRTOutObjectUsesMarshaler() const string WinRTInteropInterfaceName = "ICompositorDesktopInterop"; const string WinRTClassName = "Windows.UI.Composition.Desktop.DesktopWindowTarget"; - this.generator = this.CreateGenerator(); - Assert.True(this.generator.TryGenerate(WinRTInteropInterfaceName, CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi(WinRTInteropInterfaceName); InterfaceDeclarationSyntax interfaceDeclaration = (InterfaceDeclarationSyntax)Assert.Single(this.FindGeneratedType(WinRTInteropInterfaceName)); MethodDeclarationSyntax method = (MethodDeclarationSyntax)interfaceDeclaration.Members.First(); @@ -243,10 +219,7 @@ public void MethodWithHRParameter() [Fact] public void AssociatedEnumOnMethodParameters() { - this.generator = this.CreateGenerator(); - Assert.True(this.generator.TryGenerate("IShellFolderView", CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi("IShellFolderView"); InterfaceDeclarationSyntax ifaceSyntax = Assert.Single(this.FindGeneratedType("IShellFolderView").OfType()); MethodDeclarationSyntax methodSyntax = Assert.Single(ifaceSyntax.Members.OfType(), m => m.Identifier.ValueText == "Select"); @@ -266,9 +239,7 @@ public void InterestingUnmarshaledComInterfaces( { this.compilation = this.starterCompilations[tfm]; this.generator = this.CreateGenerator(DefaultTestGeneratorOptions with { AllowMarshaling = false }); - Assert.True(this.generator.TryGenerate(api, CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi(api); } [Theory] @@ -289,9 +260,7 @@ public void InterestingComInterfaces( { this.compilation = this.starterCompilations["net6.0"]; this.generator = this.CreateGenerator(DefaultTestGeneratorOptions with { AllowMarshaling = allowMarshaling }); - Assert.True(this.generator.TryGenerate(api, CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi(api); } [Fact] @@ -314,10 +283,7 @@ public void EnvironmentFailFast() public void ComOutPtrTypedAsOutObject() { const string methodName = "CoCreateInstance"; - this.generator = this.CreateGenerator(); - Assert.True(this.generator.TryGenerate(methodName, CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi(methodName); Assert.Contains(this.FindGeneratedMethod(methodName), m => m.ParameterList.Parameters.Last() is { } last && last.Modifiers.Any(SyntaxKind.OutKeyword) && last.Type is PredefinedTypeSyntax { Keyword: { RawKind: (int)SyntaxKind.ObjectKeyword } }); } @@ -326,9 +292,7 @@ public void ComOutPtrTypedAsIntPtr() { const string methodName = "CoCreateInstance"; this.generator = this.CreateGenerator(new GeneratorOptions { ComInterop = new() { UseIntPtrForComOutPointers = true } }); - Assert.True(this.generator.TryGenerate(methodName, CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi(methodName); Assert.Contains(this.FindGeneratedMethod(methodName), m => m.ParameterList.Parameters.Last() is { } last && last.Modifiers.Any(SyntaxKind.OutKeyword) && last.Type is IdentifierNameSyntax { Identifier: { ValueText: "IntPtr" } }); } @@ -338,9 +302,7 @@ public void NonCOMInterfaceReferences(bool allowMarshaling) var options = DefaultTestGeneratorOptions with { AllowMarshaling = allowMarshaling }; this.generator = this.CreateGenerator(options); const string methodName = "D3DCompile"; // A method whose signature references non-COM interface ID3DInclude - Assert.True(this.generator.TryGenerate(methodName, CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi(methodName); // The generated methods MUST reference the "interface" (which must actually be generated as a struct) by pointer. Assert.Contains(this.FindGeneratedType("ID3DInclude"), t => t is StructDeclarationSyntax); @@ -353,9 +315,7 @@ public void COMInterfaceWithSupportedOSPlatform(bool net60, bool allowMarshaling this.compilation = this.starterCompilations[net60 ? "net6.0" : "netstandard2.0"]; const string typeName = "IInkCursors"; this.generator = this.CreateGenerator(DefaultTestGeneratorOptions with { AllowMarshaling = allowMarshaling }); - Assert.True(this.generator.TryGenerateType(typeName)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi(typeName); var iface = this.FindGeneratedType(typeName).Single(); @@ -375,9 +335,7 @@ public void IStream_ProducesPopulateVTable() this.compilation = this.starterCompilations["net6.0"]; const string typeName = "IStream"; this.generator = this.CreateGenerator(DefaultTestGeneratorOptions with { AllowMarshaling = false }); - Assert.True(this.generator.TryGenerateType(typeName)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi(typeName); var iface = (StructDeclarationSyntax)this.FindGeneratedType(typeName).Single(); Assert.Single(iface.Members.OfType(), m => m.Identifier.ValueText == "PopulateVTable"); } @@ -388,9 +346,7 @@ public void IPersistFile_DerivesFromIComIID() this.compilation = this.starterCompilations["net7.0"]; const string typeName = "IPersistFile"; this.generator = this.CreateGenerator(DefaultTestGeneratorOptions with { AllowMarshaling = false }); - Assert.True(this.generator.TryGenerateType(typeName)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi(typeName); var iface = (StructDeclarationSyntax)this.FindGeneratedType(typeName).Single(); Assert.NotNull(iface.BaseList); Assert.Single(iface.BaseList.Types, bt => bt.Type.ToString().Contains("IComIID")); @@ -401,9 +357,7 @@ public void ITypeNameBuilder_ToStringOverload(bool allowMarshaling) { const string typeName = "ITypeNameBuilder"; this.generator = this.CreateGenerator(DefaultTestGeneratorOptions with { AllowMarshaling = allowMarshaling }); - Assert.True(this.generator.TryGenerateType(typeName)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi(typeName); } [Theory] @@ -417,9 +371,7 @@ public void COMInterfaceIIDInterfaceOnAppropriateTFMs( this.compilation = this.starterCompilations[tfm]; this.parseOptions = this.parseOptions.WithLanguageVersion(langVersion); this.generator = this.CreateGenerator(DefaultTestGeneratorOptions with { AllowMarshaling = allowMarshaling }); - Assert.True(this.generator.TryGenerate(structName, CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi(structName); BaseTypeDeclarationSyntax type = this.FindGeneratedType(structName).Single(); IEnumerable actual = type.BaseList?.Types ?? Enumerable.Empty(); diff --git a/test/Microsoft.Windows.CsWin32.Tests/ConstantsTests.cs b/test/Microsoft.Windows.CsWin32.Tests/ConstantsTests.cs index 3683886e..2a99c300 100644 --- a/test/Microsoft.Windows.CsWin32.Tests/ConstantsTests.cs +++ b/test/Microsoft.Windows.CsWin32.Tests/ConstantsTests.cs @@ -23,9 +23,6 @@ public ConstantsTests(ITestOutputHelper logger) public void InterestingConstants(string name) { this.compilation = this.compilation.WithOptions(this.compilation.Options.WithPlatform(Platform.X64)); - this.generator = this.CreateGenerator(); - Assert.True(this.generator.TryGenerate(name, CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi(name); } } diff --git a/test/Microsoft.Windows.CsWin32.Tests/DelegateTests.cs b/test/Microsoft.Windows.CsWin32.Tests/DelegateTests.cs index 182c5665..f256f0e9 100644 --- a/test/Microsoft.Windows.CsWin32.Tests/DelegateTests.cs +++ b/test/Microsoft.Windows.CsWin32.Tests/DelegateTests.cs @@ -20,9 +20,6 @@ public void InterestingDelegates( { AllowMarshaling = allowMarshaling, }; - this.generator = this.CreateGenerator(options); - Assert.True(this.generator.TryGenerate(name, CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi(name); } } diff --git a/test/Microsoft.Windows.CsWin32.Tests/ExternMethodTests.cs b/test/Microsoft.Windows.CsWin32.Tests/ExternMethodTests.cs index 461ebde0..33183661 100644 --- a/test/Microsoft.Windows.CsWin32.Tests/ExternMethodTests.cs +++ b/test/Microsoft.Windows.CsWin32.Tests/ExternMethodTests.cs @@ -11,13 +11,7 @@ public ExternMethodTests(ITestOutputHelper logger) [Fact] public void AssociatedEnumOnParameter() { - const string Method = "SHObjectProperties"; - this.generator = this.CreateGenerator(); - Assert.True(this.generator.TryGenerate(Method, CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); - - MethodDeclarationSyntax method = Assert.Single(this.FindGeneratedMethod(Method), IsOrContainsExternMethod); + MethodDeclarationSyntax method = Assert.Single(this.GenerateMethod("SHObjectProperties"), IsOrContainsExternMethod); ParameterSyntax enumParam = method.ParameterList.Parameters[1]; Assert.Equal("SHOP_TYPE", Assert.IsType(enumParam.Type).Right.Identifier.ValueText); } @@ -25,24 +19,14 @@ public void AssociatedEnumOnParameter() [Fact] public void AssociatedEnumOnReturnValue() { - const string Method = "PathCleanupSpec"; - this.generator = this.CreateGenerator(); - Assert.True(this.generator.TryGenerate(Method, CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); - - MethodDeclarationSyntax method = Assert.Single(this.FindGeneratedMethod(Method), IsOrContainsExternMethod); + MethodDeclarationSyntax method = Assert.Single(this.GenerateMethod("PathCleanupSpec"), IsOrContainsExternMethod); Assert.Equal("PCS_RET", Assert.IsType(method.ReturnType).Right.Identifier.ValueText); } [Fact] public void AssociatedEnumOnParameterWithVoidReturn() { - const string Method = "SHChangeNotify"; - this.generator = this.CreateGenerator(); - Assert.True(this.generator.TryGenerate(Method, CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateMethod("SHChangeNotify"); } /// @@ -51,11 +35,7 @@ public void AssociatedEnumOnParameterWithVoidReturn() [Fact] public void WdkMethod_NtCreateFile() { - const string Method = "NtCreateFile"; - this.generator = this.CreateGenerator(); - Assert.True(this.generator.TryGenerate(Method, CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateMethod("NtCreateFile"); } [Theory, CombinatorialData] @@ -65,9 +45,7 @@ public void SetLastError_ByMarshaling( { this.compilation = this.starterCompilations[tfm]; this.generator = this.CreateGenerator(DefaultTestGeneratorOptions with { AllowMarshaling = allowMarshaling }); - Assert.True(this.generator.TryGenerate("GetVersionEx", CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi("GetVersionEx"); bool expectMarshalingAttribute = allowMarshaling || tfm is "net472" or "netstandard2.0"; MethodDeclarationSyntax originalMethod = this.FindGeneratedMethod("GetVersionEx").Single(m => m.ParameterList.Parameters[0].Type is PointerTypeSyntax); @@ -77,4 +55,10 @@ public void SetLastError_ByMarshaling( static AttributeSyntax? FindDllImportAttribute(SyntaxList attributeLists) => attributeLists.SelectMany(al => al.Attributes).FirstOrDefault(a => a.Name.ToString() == "DllImport"); } + + private IEnumerable GenerateMethod(string methodName) + { + this.GenerateApi(methodName); + return this.FindGeneratedMethod(methodName); + } } diff --git a/test/Microsoft.Windows.CsWin32.Tests/FriendlyOverloadTests.cs b/test/Microsoft.Windows.CsWin32.Tests/FriendlyOverloadTests.cs index 55da02ad..46b68837 100644 --- a/test/Microsoft.Windows.CsWin32.Tests/FriendlyOverloadTests.cs +++ b/test/Microsoft.Windows.CsWin32.Tests/FriendlyOverloadTests.cs @@ -31,10 +31,7 @@ public void SHGetFileInfo() public void SpecializedRAIIFree_ReturnValue() { const string Method = "CreateActCtx"; - this.generator = this.CreateGenerator(); - Assert.True(this.generator.TryGenerate(Method, CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi(Method); MethodDeclarationSyntax method = Assert.Single(this.FindGeneratedMethod(Method), m => !IsOrContainsExternMethod(m)); Assert.Equal("ReleaseActCtxSafeHandle", Assert.IsType(method.ReturnType).Identifier.ValueText); @@ -44,10 +41,7 @@ public void SpecializedRAIIFree_ReturnValue() public void SpecializedRAIIFree_OutParameter() { const string Method = "DsGetDcOpen"; - this.generator = this.CreateGenerator(); - Assert.True(this.generator.TryGenerate(Method, CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi(Method); MethodDeclarationSyntax method = Assert.Single(this.FindGeneratedMethod(Method), m => !IsOrContainsExternMethod(m)); Assert.Equal("DsGetDcCloseWSafeHandle", Assert.IsType(method.ParameterList.Parameters.Last().Type).Identifier.ValueText); @@ -56,9 +50,6 @@ public void SpecializedRAIIFree_OutParameter() private void Generate(string name) { this.compilation = this.compilation.WithOptions(this.compilation.Options.WithPlatform(Platform.X64)); - this.generator = this.CreateGenerator(); - Assert.True(this.generator.TryGenerate(name, CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi(name); } } diff --git a/test/Microsoft.Windows.CsWin32.Tests/GeneratorTestBase.cs b/test/Microsoft.Windows.CsWin32.Tests/GeneratorTestBase.cs index fefce5fb..280f80b0 100644 --- a/test/Microsoft.Windows.CsWin32.Tests/GeneratorTestBase.cs +++ b/test/Microsoft.Windows.CsWin32.Tests/GeneratorTestBase.cs @@ -146,6 +146,14 @@ protected static bool IsOrContainsExternMethod(MethodDeclarationSyntax method) protected static IEnumerable FindAttribute(SyntaxList attributeLists, string name) => attributeLists.SelectMany(al => al.Attributes).Where(a => a.Name.ToString() == name); + protected void GenerateApi(string methodName) + { + this.generator ??= this.CreateGenerator(); + Assert.True(this.generator.TryGenerate(methodName, CancellationToken.None)); + this.CollectGeneratedCode(this.generator); + this.AssertNoDiagnostics(); + } + protected CSharpCompilation AddGeneratedCode(CSharpCompilation compilation, IGenerator generator) { var compilationUnits = generator.GetCompilationUnits(CancellationToken.None).ToList(); @@ -270,10 +278,7 @@ protected void LogGeneratedCode(SyntaxTree tree) protected void AssertGeneratedType(string apiName, string expectedSyntax, string? expectedExtensions = null) { - this.generator = this.CreateGenerator(); - Assert.True(this.generator.TryGenerate(apiName, CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi(apiName); BaseTypeDeclarationSyntax syntax = Assert.Single(this.FindGeneratedType(apiName)); Assert.Equal(TestUtils.NormalizeToExpectedLineEndings(expectedSyntax), TestUtils.NormalizeToExpectedLineEndings(syntax.ToFullString())); @@ -293,10 +298,7 @@ protected void AssertGeneratedType(string apiName, string expectedSyntax, string protected void AssertGeneratedMember(string apiName, string memberName, string expectedSyntax) { - this.generator = this.CreateGenerator(); - Assert.True(this.generator.TryGenerate(apiName, CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi(apiName); BaseTypeDeclarationSyntax typeSyntax = Assert.Single(this.FindGeneratedType(apiName)); var semanticModel = this.compilation.GetSemanticModel(typeSyntax.SyntaxTree, ignoreAccessibility: false); var member = Assert.Single(semanticModel.GetDeclaredSymbol(typeSyntax, CancellationToken.None)!.GetMembers(memberName)); diff --git a/test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs b/test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs index 9a83d58b..488eedb2 100644 --- a/test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs +++ b/test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs @@ -14,9 +14,7 @@ public GeneratorTests(ITestOutputHelper logger) public void AssemblyAttributeGenerated(bool emitSingleFile) { this.generator = this.CreateGenerator(DefaultTestGeneratorOptions with { EmitSingleFile = emitSingleFile }); - Assert.True(this.generator.TryGenerate("GetTickCount", CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi("GetTickCount"); IEnumerable assemblyMetadataAttributes = from tree in this.compilation.SyntaxTrees from attributeList in tree.GetCompilationUnitRoot().AttributeLists @@ -551,10 +549,7 @@ public void GenerateByNamespace(bool correctCase) [Fact] public void BOOL_FieldRemainsBOOL() { - this.generator = this.CreateGenerator(); - Assert.True(this.generator.TryGenerate("ICONINFO", CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi("ICONINFO"); var theStruct = (StructDeclarationSyntax)this.FindGeneratedType("ICONINFO").Single(); VariableDeclarationSyntax field = theStruct.Members.OfType().Select(m => m.Declaration).Single(d => d.Variables.Any(v => v.Identifier.ValueText == "fIcon")); Assert.Equal("BOOL", Assert.IsType(field.Type).Right.Identifier.ValueText); @@ -563,20 +558,14 @@ public void BOOL_FieldRemainsBOOL() [Fact] public void TypeNameCollisionsDoNotCauseTooMuchCodeGen() { - this.generator = this.CreateGenerator(); - Assert.True(this.generator.TryGenerate("TYPEDESC", CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi("TYPEDESC"); Assert.Empty(this.FindGeneratedType("D3DMATRIX")); } [Fact] public void Const_PWSTR_Becomes_PCWSTR_and_String() { - this.generator = this.CreateGenerator(); - Assert.True(this.generator.TryGenerate("StrCmpLogical", CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi("StrCmpLogical"); bool foundPCWSTROverload = false; bool foundStringOverload = false; @@ -776,10 +765,7 @@ public void InOutPWSTRGetsRefSpanCharFriendlyOverload() public void UnicodeExtenMethodsGetCharSet() { const string MethodName = "VkKeyScan"; - this.generator = this.CreateGenerator(); - Assert.True(this.generator.TryGenerate(MethodName, CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi(MethodName); MethodDeclarationSyntax generatedMethod = this.FindGeneratedMethod(MethodName).Single(); Assert.Contains( generatedMethod.AttributeLists.SelectMany(al => al.Attributes), @@ -986,10 +972,7 @@ public void MiniDumpWriteDump_AllOptionalPointerParametersAreOptional(string tfm { // We split on TFMs because the generated code is slightly different depending on TFM. this.compilation = this.starterCompilations[tfm].WithOptions(this.compilation.Options.WithPlatform(Platform.X64)); - this.generator = this.CreateGenerator(); - Assert.True(this.generator.TryGenerate("MiniDumpWriteDump", CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi("MiniDumpWriteDump"); MethodDeclarationSyntax externMethod = Assert.Single(this.FindGeneratedMethod("MiniDumpWriteDump"), m => !m.Modifiers.Any(SyntaxKind.ExternKeyword)); Assert.All(externMethod.ParameterList.Parameters.Reverse().Take(3), p => Assert.IsType(p.Type)); @@ -1070,10 +1053,7 @@ public void ParametersIncludeSizeParamIndex() [Fact] public void SeekOriginEnumPreferred() { - this.generator = this.CreateGenerator(); - Assert.True(this.generator.TryGenerateType("IStream")); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi("IStream"); MethodDeclarationSyntax seekMethod = Assert.Single(this.FindGeneratedMethod("Seek")); QualifiedNameSyntax seekParamType = Assert.IsType(seekMethod.ParameterList.Parameters[1].Type); diff --git a/test/Microsoft.Windows.CsWin32.Tests/HandleTests.cs b/test/Microsoft.Windows.CsWin32.Tests/HandleTests.cs index 15644287..cba5875e 100644 --- a/test/Microsoft.Windows.CsWin32.Tests/HandleTests.cs +++ b/test/Microsoft.Windows.CsWin32.Tests/HandleTests.cs @@ -12,10 +12,7 @@ public HandleTests(ITestOutputHelper logger) public void BSTR_FieldsDoNotBecomeSafeHandles(bool allowMarshaling) { var options = DefaultTestGeneratorOptions with { AllowMarshaling = allowMarshaling }; - this.generator = this.CreateGenerator(options); - Assert.True(this.generator.TryGenerate("DebugPropertyInfo", CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi("DebugPropertyInfo"); StructDeclarationSyntax structDecl = Assert.IsType(this.FindGeneratedType("DebugPropertyInfo").Single()); var bstrField = structDecl.Members.OfType().First(m => m.Declaration.Variables.Any(v => v.Identifier.ValueText == "m_bstrName")); Assert.Equal("BSTR", Assert.IsType(bstrField.Declaration.Type).Right.Identifier.ValueText); @@ -24,20 +21,14 @@ public void BSTR_FieldsDoNotBecomeSafeHandles(bool allowMarshaling) [Fact] public void NamespaceHandleGetsNoSafeHandle() { - this.generator = this.CreateGenerator(); - Assert.True(this.generator.TryGenerate("CreatePrivateNamespace", CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi("CreatePrivateNamespace"); Assert.Empty(this.FindGeneratedType("ClosePrivateNamespaceSafeHandle")); } [Fact] public void CreateFileUsesSafeHandles() { - this.generator = this.CreateGenerator(); - Assert.True(this.generator.TryGenerate("CreateFile", CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi("CreateFile"); Assert.Contains( this.FindGeneratedMethod("CreateFile"), @@ -67,9 +58,7 @@ public void OutHandleParameterBecomesSafeHandle() public void AvoidSafeHandles() { this.generator = this.CreateGenerator(DefaultTestGeneratorOptions with { UseSafeHandles = false }); - Assert.True(this.generator.TryGenerate("GetExitCodeThread", CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi("GetExitCodeThread"); MethodDeclarationSyntax friendlyOverload = Assert.Single(this.FindGeneratedMethod("GetExitCodeThread"), m => m.ParameterList.Parameters[^1].Modifiers.Any(SyntaxKind.OutKeyword)); Assert.Equal("HANDLE", Assert.IsType(friendlyOverload.ParameterList.Parameters[0].Type).Right.Identifier.ValueText); } @@ -78,9 +67,7 @@ public void AvoidSafeHandles() public void SafeHandleInWDK() { this.generator = this.CreateGenerator(DefaultTestGeneratorOptions); - Assert.True(this.generator.TryGenerate("OROpenHive", CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi("OROpenHive"); } /// @@ -91,9 +78,7 @@ public void SafeHandleInWDK() public void MSIHANDLE_BecomesSafeHandle() { this.generator = this.CreateGenerator(); - Assert.True(this.generator.TryGenerate("MsiGetLastErrorRecord", CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi("MsiGetLastErrorRecord"); Assert.Contains( this.FindGeneratedMethod("MsiGetLastErrorRecord"), @@ -146,10 +131,7 @@ public void HandleTypeDefsUseIntPtrAsFieldType(string handleType) [Fact] public void ReleaseMethodGeneratedWithHandleStruct() { - this.generator = this.CreateGenerator(); - Assert.True(this.generator.TryGenerate("HANDLE", CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi("HANDLE"); Assert.True(this.IsMethodGenerated("CloseHandle")); } } diff --git a/test/Microsoft.Windows.CsWin32.Tests/StructTests.cs b/test/Microsoft.Windows.CsWin32.Tests/StructTests.cs index bcb0eb7d..9f3e9e53 100644 --- a/test/Microsoft.Windows.CsWin32.Tests/StructTests.cs +++ b/test/Microsoft.Windows.CsWin32.Tests/StructTests.cs @@ -92,10 +92,7 @@ internal enum FILE_CREATE_FLAGS } "; this.compilation = this.compilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText(test, this.parseOptions, "test.cs")); - this.generator = this.CreateGenerator(); - Assert.True(this.generator.TryGenerate("CreateFile", CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi("CreateFile"); } [Fact] @@ -105,10 +102,7 @@ public void PartialStructsAllowUserContributions() this.compilation = this.compilation.AddSyntaxTrees( CSharpSyntaxTree.ParseText("namespace Microsoft.Windows.Sdk { partial struct HRESULT { void Foo() { } } }", this.parseOptions, "myHRESULT.cs")); - this.generator = this.CreateGenerator(); - Assert.True(this.generator.TryGenerate(structName, CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi(structName); bool hasFooMethod = false; bool hasValueProperty = false; @@ -125,10 +119,7 @@ public void PartialStructsAllowUserContributions() [Fact] public void PROC_GeneratedAsStruct() { - this.generator = this.CreateGenerator(); - Assert.True(this.generator.TryGenerate("PROC", CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi("PROC"); BaseTypeDeclarationSyntax type = Assert.Single(this.FindGeneratedType("PROC")); Assert.IsType(type); @@ -139,10 +130,7 @@ public void PROC_GeneratedAsStruct() public void FARPROC_GeneratedAsStruct(string tfm) { this.compilation = this.starterCompilations[tfm]; - this.generator = this.CreateGenerator(); - Assert.True(this.generator.TryGenerate("FARPROC", CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi("FARPROC"); BaseTypeDeclarationSyntax type = Assert.Single(this.FindGeneratedType("FARPROC")); Assert.IsType(type); @@ -151,10 +139,7 @@ public void FARPROC_GeneratedAsStruct(string tfm) [Fact] public void PointerFieldIsDeclaredAsPointer() { - this.generator = this.CreateGenerator(); - Assert.True(this.generator.TryGenerate("PROCESS_BASIC_INFORMATION", CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi("PROCESS_BASIC_INFORMATION"); var type = (StructDeclarationSyntax)Assert.Single(this.FindGeneratedType("PROCESS_BASIC_INFORMATION")); FieldDeclarationSyntax field = Assert.Single(type.Members.OfType(), m => m.Declaration.Variables.Any(v => v.Identifier.ValueText == "PebBaseAddress")); @@ -164,10 +149,7 @@ public void PointerFieldIsDeclaredAsPointer() [Fact] public void FieldWithAssociatedEnum() { - this.generator = this.CreateGenerator(); - Assert.True(this.generator.TryGenerate("SHDESCRIPTIONID", CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi("SHDESCRIPTIONID"); var type = (StructDeclarationSyntax)Assert.Single(this.FindGeneratedType("SHDESCRIPTIONID")); PropertyDeclarationSyntax property = Assert.Single(type.Members.OfType(), m => m.Identifier.ValueText == "dwDescriptionId"); @@ -203,8 +185,6 @@ public void InterestingStructs( AllowMarshaling = allowMarshaling, }; this.generator = this.CreateGenerator(options); - Assert.True(this.generator.TryGenerate(name, CancellationToken.None)); - this.CollectGeneratedCode(this.generator); - this.AssertNoDiagnostics(); + this.GenerateApi(name); } }