From 6a74ac95fa31328f305a73c4953eeeb53c1f3d69 Mon Sep 17 00:00:00 2001 From: tpodolak Date: Sat, 29 Sep 2018 00:30:37 +0200 Subject: [PATCH] [GH-38] - Adding tests for external sources --- ...stituteForInternalMemberCodeFixProvider.cs | 2 +- .../CSharpCodeFixVerifier.cs | 35 +---- ...uteForInternalMemberCodeFixActionsTests.cs | 134 ++++++++++++++++++ ...ForInternalMemberCodeFixActionsVerifier.cs | 13 ++ ...uteForInternalMemberCodeFixActionsTests.cs | 126 ++++++++++++++++ 5 files changed, 275 insertions(+), 35 deletions(-) create mode 100644 tests/NSubstitute.Analyzers.Tests.CSharp/CodeFixProviderTests/SubstituteForInternalMemberCodeFixProviderTests/SubstituteForInternalMemberCodeFixActionsTests.cs create mode 100644 tests/NSubstitute.Analyzers.Tests.Shared/CodeFixProviders/ISubstituteForInternalMemberCodeFixActionsVerifier.cs create mode 100644 tests/NSubstitute.Analyzers.Tests.VisualBasic/CodeFixProvidersTests/SubstituteForInternalMemberCodeFixProviderTests/SubstituteForInternalMemberCodeFixActionsTests.cs diff --git a/src/NSubstitute.Analyzers.Shared/CodeFixProviders/AbstractSubstituteForInternalMemberCodeFixProvider.cs b/src/NSubstitute.Analyzers.Shared/CodeFixProviders/AbstractSubstituteForInternalMemberCodeFixProvider.cs index bb508d75..84564db4 100644 --- a/src/NSubstitute.Analyzers.Shared/CodeFixProviders/AbstractSubstituteForInternalMemberCodeFixProvider.cs +++ b/src/NSubstitute.Analyzers.Shared/CodeFixProviders/AbstractSubstituteForInternalMemberCodeFixProvider.cs @@ -48,7 +48,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) return; } - var codeAction = CodeAction.Create("my name", token => CreateChangedDocument(token, compilationUnitSyntax, document), nameof(AbstractSubstituteForInternalMemberCodeFixProvider)); + var codeAction = CodeAction.Create("Append InternalsVisibleTo attribute", token => CreateChangedDocument(token, compilationUnitSyntax, document), nameof(AbstractSubstituteForInternalMemberCodeFixProvider)); context.RegisterCodeFix(codeAction, diagnostic); } diff --git a/tests/NSubstitute.Analyzers.Tests.CSharp/CodeFixProviderTests/CSharpCodeFixVerifier.cs b/tests/NSubstitute.Analyzers.Tests.CSharp/CodeFixProviderTests/CSharpCodeFixVerifier.cs index 0ceb4c2d..72b377a1 100644 --- a/tests/NSubstitute.Analyzers.Tests.CSharp/CodeFixProviderTests/CSharpCodeFixVerifier.cs +++ b/tests/NSubstitute.Analyzers.Tests.CSharp/CodeFixProviderTests/CSharpCodeFixVerifier.cs @@ -1,6 +1,4 @@ -using System.Collections.Generic; -using System.IO; -using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using NSubstitute.Analyzers.Tests.Shared.CodeFixProviders; @@ -14,36 +12,5 @@ protected override CompilationOptions GetCompilationOptions() { return new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary); } - - protected override IEnumerable GetAdditionalMetadataReferences() - { - return new MetadataReference[] - { - Foo() - }; - } - - private static PortableExecutableReference Foo() - { - var syntaxTree = CSharpSyntaxTree.ParseText(@" -namespace ExternalNamespace -{ - internal class InternalFoo - { - } -}"); - - var references = new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) }; - var compilationOptions = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary); - var compilation = CSharpCompilation.Create("Internal", new[] { syntaxTree }, references: references, options: compilationOptions); - - using (var ms = new MemoryStream()) - { - var result = compilation.Emit(ms); - - ms.Seek(0, SeekOrigin.Begin); - return MetadataReference.CreateFromStream(ms); - } - } } } \ No newline at end of file diff --git a/tests/NSubstitute.Analyzers.Tests.CSharp/CodeFixProviderTests/SubstituteForInternalMemberCodeFixProviderTests/SubstituteForInternalMemberCodeFixActionsTests.cs b/tests/NSubstitute.Analyzers.Tests.CSharp/CodeFixProviderTests/SubstituteForInternalMemberCodeFixProviderTests/SubstituteForInternalMemberCodeFixActionsTests.cs new file mode 100644 index 00000000..c48a6ca4 --- /dev/null +++ b/tests/NSubstitute.Analyzers.Tests.CSharp/CodeFixProviderTests/SubstituteForInternalMemberCodeFixProviderTests/SubstituteForInternalMemberCodeFixActionsTests.cs @@ -0,0 +1,134 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.Diagnostics; +using NSubstitute.Analyzers.CSharp.CodeFixProviders; +using NSubstitute.Analyzers.CSharp.DiagnosticAnalyzers; +using NSubstitute.Analyzers.Tests.Shared.CodeFixProviders; +using Xunit; + +namespace NSubstitute.Analyzers.Tests.CSharp.CodeFixProviderTests.SubstituteForInternalMemberCodeFixProviderTests +{ + public class SubstituteForInternalMemberCodeFixActionsTests : CSharpCodeFixActionsVerifier, ISubstituteForInternalMemberCodeFixActionsVerifier + { + [Fact] + public async Task CreatesCorrectCodeFixActions_WhenSourceForInternalType_IsAvailable() + { + var source = @"using NSubstitute.Core; +namespace MyNamespace +{ + namespace MyInnerNamespace + { + internal class Foo + { + } + + public class FooTests + { + public void Test() + { + var substitute = SubstitutionContext.Current.SubstituteFactory.CreatePartial(new[] {typeof(Foo)}, null); + } + } + } +}"; + await VerifyCodeActions(source, "Append InternalsVisibleTo attribute"); + } + + [Fact] + public async Task Does_Not_CreateCodeFixActions_WhenType_IsNotInternal() + { + var source = @"using NSubstitute.Core; +namespace MyNamespace +{ + namespace MyInnerNamespace + { + public class Foo + { + } + + public class FooTests + { + public void Test() + { + var substitute = SubstitutionContext.Current.SubstituteFactory.CreatePartial(new[] {typeof(Foo)}, null); + } + } + } +}"; + await VerifyCodeActions(source); + } + + [Fact] + public async Task Does_Not_CreateCodeFixActions_WhenSourceForInternalType_IsNotAvailable() + { + var source = @"using NSubstitute.Core; +using ExternalNamespace; +namespace MyNamespace +{ + namespace MyInnerNamespace + { + public class FooTests + { + public void Test() + { + var substitute = SubstitutionContext.Current.SubstituteFactory.CreatePartial(new[] {typeof(InternalFoo)}, null); + } + } + } +}"; + await VerifyCodeActions(source); + } + + protected override DiagnosticAnalyzer GetDiagnosticAnalyzer() + { + return new SubstituteAnalyzer(); + } + + protected override CodeFixProvider GetCodeFixProvider() + { + return new SubstituteForInternalMemberCodeFixProvider(); + } + + protected override IEnumerable GetAdditionalMetadataReferences() + { + return new[] { GetInternalLibraryMetadataReference() }; + } + + private static PortableExecutableReference GetInternalLibraryMetadataReference() + { + var syntaxTree = CSharpSyntaxTree.ParseText($@" +using System.Runtime.CompilerServices; +[assembly: InternalsVisibleTo(""{TestProjectName}"")] +namespace ExternalNamespace +{{ + internal class InternalFoo + {{ + }} +}}"); + + var references = new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) }; + var compilationOptions = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary); + var compilation = CSharpCompilation.Create("Internal", new[] { syntaxTree }, references, compilationOptions); + + using (var ms = new MemoryStream()) + { + var result = compilation.Emit(ms); + + if (result.Success == false) + { + var errors = result.Diagnostics.Where(diag => diag.IsWarningAsError || diag.Severity == DiagnosticSeverity.Error); + throw new InvalidOperationException($"Internal library compilation failed: {string.Join(",", errors)}"); + } + + ms.Seek(0, SeekOrigin.Begin); + return MetadataReference.CreateFromStream(ms); + } + } + } +} \ No newline at end of file diff --git a/tests/NSubstitute.Analyzers.Tests.Shared/CodeFixProviders/ISubstituteForInternalMemberCodeFixActionsVerifier.cs b/tests/NSubstitute.Analyzers.Tests.Shared/CodeFixProviders/ISubstituteForInternalMemberCodeFixActionsVerifier.cs new file mode 100644 index 00000000..d757f437 --- /dev/null +++ b/tests/NSubstitute.Analyzers.Tests.Shared/CodeFixProviders/ISubstituteForInternalMemberCodeFixActionsVerifier.cs @@ -0,0 +1,13 @@ +using System.Threading.Tasks; + +namespace NSubstitute.Analyzers.Tests.Shared.CodeFixProviders +{ + public interface ISubstituteForInternalMemberCodeFixActionsVerifier + { + Task CreatesCorrectCodeFixActions_WhenSourceForInternalType_IsAvailable(); + + Task Does_Not_CreateCodeFixActions_WhenType_IsNotInternal(); + + Task Does_Not_CreateCodeFixActions_WhenSourceForInternalType_IsNotAvailable(); + } +} \ No newline at end of file diff --git a/tests/NSubstitute.Analyzers.Tests.VisualBasic/CodeFixProvidersTests/SubstituteForInternalMemberCodeFixProviderTests/SubstituteForInternalMemberCodeFixActionsTests.cs b/tests/NSubstitute.Analyzers.Tests.VisualBasic/CodeFixProvidersTests/SubstituteForInternalMemberCodeFixProviderTests/SubstituteForInternalMemberCodeFixActionsTests.cs new file mode 100644 index 00000000..295dbb5f --- /dev/null +++ b/tests/NSubstitute.Analyzers.Tests.VisualBasic/CodeFixProvidersTests/SubstituteForInternalMemberCodeFixProviderTests/SubstituteForInternalMemberCodeFixActionsTests.cs @@ -0,0 +1,126 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.VisualBasic; +using NSubstitute.Analyzers.Tests.Shared.CodeFixProviders; +using NSubstitute.Analyzers.VisualBasic.CodeFixProviders; +using NSubstitute.Analyzers.VisualBasic.DiagnosticAnalyzers; +using Xunit; + +namespace NSubstitute.Analyzers.Tests.VisualBasic.CodeFixProvidersTests.SubstituteForInternalMemberCodeFixProviderTests +{ + public class SubstituteForInternalMemberCodeFixActionsTests : VisualBasicCodeFixActionsVerifier, ISubstituteForInternalMemberCodeFixActionsVerifier + { + [Fact] + public async Task CreatesCorrectCodeFixActions_WhenSourceForInternalType_IsAvailable() + { + var source = @"Imports NSubstitute.Core + +Namespace MyNamespace + Namespace MyInnerNamespace + Friend Class Foo + End Class + + Public Class FooTests + Public Sub Test() + Dim substitute = SubstitutionContext.Current.SubstituteFactory.CreatePartial({GetType(Foo)}, Nothing) + End Sub + End Class + End Namespace +End Namespace +"; + await VerifyCodeActions(source, "Append InternalsVisibleTo attribute"); + } + + [Fact] + public async Task Does_Not_CreateCodeFixActions_WhenType_IsNotInternal() + { + var source = @"Imports NSubstitute.Core + +Namespace MyNamespace + Namespace MyInnerNamespace + Public Class Foo + End Class + + Public Class FooTests + Public Sub Test() + Dim substitute = SubstitutionContext.Current.SubstituteFactory.CreatePartial({GetType(Foo)}, Nothing) + End Sub + End Class + End Namespace +End Namespace +"; + await VerifyCodeActions(source); + } + + [Fact] + public async Task Does_Not_CreateCodeFixActions_WhenSourceForInternalType_IsNotAvailable() + { + var source = @"Imports NSubstitute.Core +Imports ExternalNamespace + +Namespace MyNamespace + Namespace MyInnerNamespace + Public Class FooTests + Public Sub Test() + Dim substitute = SubstitutionContext.Current.SubstituteFactory.CreatePartial({GetType(InternalFoo)}, Nothing) + End Sub + End Class + End Namespace +End Namespace +"; + await VerifyCodeActions(source); + } + + protected override DiagnosticAnalyzer GetDiagnosticAnalyzer() + { + return new SubstituteAnalyzer(); + } + + protected override CodeFixProvider GetCodeFixProvider() + { + return new SubstituteForInternalMemberCodeFixProvider(); + } + + protected override IEnumerable GetAdditionalMetadataReferences() + { + return new[] { GetInternalLibraryMetadataReference() }; + } + + private static PortableExecutableReference GetInternalLibraryMetadataReference() + { + var syntaxTree = VisualBasicSyntaxTree.ParseText($@" +Imports System.Runtime.CompilerServices + + +Namespace ExternalNamespace + Friend Class InternalFoo + End Class +End Namespace +"); + + var references = new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) }; + var compilationOptions = new VisualBasicCompilationOptions(OutputKind.DynamicallyLinkedLibrary); + var compilation = VisualBasicCompilation.Create("Internal", new[] { syntaxTree }, references, compilationOptions); + + using (var ms = new MemoryStream()) + { + var result = compilation.Emit(ms); + + if (result.Success == false) + { + var errors = result.Diagnostics.Where(diag => diag.IsWarningAsError || diag.Severity == DiagnosticSeverity.Error); + throw new InvalidOperationException($"Internal library compilation failed: {string.Join(",", errors)}"); + } + + ms.Seek(0, SeekOrigin.Begin); + return MetadataReference.CreateFromStream(ms); + } + } + } +} \ No newline at end of file