Files
git.stella-ops.org/src/Concelier/__Tests/StellaOps.Concelier.Merge.Analyzers.Tests/MergeUsageAnalyzerTests.cs

172 lines
5.5 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Diagnostics;
using StellaOps.TestKit;
namespace StellaOps.Concelier.Merge.Analyzers.Tests;
public sealed class MergeUsageAnalyzerTests
{
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task ReportsDiagnostic_ForAdvisoryMergeServiceInstantiation()
{
const string source = """
using StellaOps.Concelier.Merge.Services;
namespace Sample.App;
public sealed class Demo
{
public void Run()
{
var merge = new AdvisoryMergeService();
}
}
""";
var diagnostics = await AnalyzeAsync(source, "Sample.App");
Assert.Contains(diagnostics, d => d.Id == MergeUsageAnalyzer.DiagnosticId && d.GetMessage().Contains("AdvisoryMergeService", StringComparison.Ordinal));
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task ReportsDiagnostic_ForAddMergeModuleInvocation()
{
const string source = """
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using StellaOps.Concelier.Merge;
namespace Sample.Services;
public static class Installer
{
public static void Configure(IServiceCollection services, IConfiguration configuration)
{
services.AddMergeModule(configuration);
}
}
""";
var diagnostics = await AnalyzeAsync(source, "Sample.Services");
Assert.Contains(diagnostics, d => d.Id == MergeUsageAnalyzer.DiagnosticId && d.GetMessage().Contains("AddMergeModule", StringComparison.Ordinal));
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task ReportsDiagnostic_ForFieldDeclaration()
{
const string source = """
using StellaOps.Concelier.Merge.Services;
namespace Sample.Library;
public sealed class Demo
{
private AdvisoryMergeService? _mergeService;
}
""";
var diagnostics = await AnalyzeAsync(source, "Sample.Library");
Assert.Contains(diagnostics, d => d.Id == MergeUsageAnalyzer.DiagnosticId);
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task DoesNotReportDiagnostic_InsideMergeAssembly()
{
const string source = """
using StellaOps.Concelier.Merge.Services;
namespace StellaOps.Concelier.Merge.Internal;
internal static class MergeDiagnostics
{
public static AdvisoryMergeService Create() => new AdvisoryMergeService();
}
""";
var diagnostics = await AnalyzeAsync(source, "StellaOps.Concelier.Merge");
Assert.DoesNotContain(diagnostics, d => d.Id == MergeUsageAnalyzer.DiagnosticId);
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task ReportsDiagnostic_ForTypeOfUsage()
{
const string source = """
using System;
using StellaOps.Concelier.Merge.Services;
namespace Sample.TypeOf;
public static class Demo
{
public static Type TargetType => typeof(AdvisoryMergeService);
}
""";
var diagnostics = await AnalyzeAsync(source, "Sample.TypeOf");
Assert.Contains(diagnostics, d => d.Id == MergeUsageAnalyzer.DiagnosticId);
}
private static async Task<ImmutableArray<Diagnostic>> AnalyzeAsync(string source, string assemblyName)
{
var compilation = CSharpCompilation.Create(
assemblyName,
new[]
{
CSharpSyntaxTree.ParseText(source),
CSharpSyntaxTree.ParseText(Stubs)
},
CreateMetadataReferences(),
new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
var analyzer = new MergeUsageAnalyzer();
var compilationWithAnalyzers = compilation.WithAnalyzers(ImmutableArray.Create<DiagnosticAnalyzer>(analyzer));
return await compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync();
}
private static IEnumerable<MetadataReference> CreateMetadataReferences()
{
yield return MetadataReference.CreateFromFile(typeof(object).GetTypeInfo().Assembly.Location);
yield return MetadataReference.CreateFromFile(typeof(Enumerable).GetTypeInfo().Assembly.Location);
}
private const string Stubs = """
namespace Microsoft.Extensions.DependencyInjection
{
public interface IServiceCollection { }
}
namespace Microsoft.Extensions.Configuration
{
public interface IConfiguration { }
}
namespace StellaOps.Concelier.Merge.Services
{
public sealed class AdvisoryMergeService { }
}
namespace StellaOps.Concelier.Merge
{
public static class MergeServiceCollectionExtensions
{
public static void AddMergeModule(
this Microsoft.Extensions.DependencyInjection.IServiceCollection services,
Microsoft.Extensions.Configuration.IConfiguration configuration)
{
}
}
}
""";
}