Skip to content

Commit

Permalink
feat: added generator tests
Browse files Browse the repository at this point in the history
  • Loading branch information
TimothyMakkison committed Jul 25, 2024
1 parent 3415304 commit b7cc243
Show file tree
Hide file tree
Showing 11 changed files with 422 additions and 0 deletions.
95 changes: 95 additions & 0 deletions Refit.GeneratorTests/Fixture.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
using System.Reflection;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Refit.Generator;

namespace Refit.GeneratorTests;

public static class Fixture
{
static readonly MetadataReference RefitAssembly = MetadataReference.CreateFromFile(
typeof(GetAttribute).Assembly.Location,
documentation: XmlDocumentationProvider.CreateFromFile(
Path.ChangeExtension(typeof(GetAttribute).Assembly.Location, ".xml")
)
);

private static readonly Type[] ImportantAssemblies = {
typeof(Binder),
typeof(GetAttribute),
typeof(System.Reactive.Unit),
typeof(Enumerable),
typeof(Newtonsoft.Json.JsonConvert),
typeof(FactAttribute),
typeof(HttpContent),
typeof(Attribute)
};

private static Assembly[] AssemblyReferencesForCodegen =>
AppDomain.CurrentDomain
.GetAssemblies()
.Concat(ImportantAssemblies.Select(x=>x.Assembly))
.Distinct()
.Where(a => !a.IsDynamic)
.ToArray();

public static Task VerifyForBody(string body)
{
var source =
$$"""
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Refit;
namespace RefitGeneratorTest;
public interface IGeneratedClient
{
{{body}}
}
""";

return VerifyGenerator(source);
}

private static CSharpCompilation CreateLibrary(params string[] source)
{
var references = new List<MetadataReference>();
var assemblies = AssemblyReferencesForCodegen;
foreach (var assembly in assemblies)
{
if (!assembly.IsDynamic)
{
references.Add(MetadataReference.CreateFromFile(assembly.Location));
}
}

references.Add(RefitAssembly);
var compilation = CSharpCompilation.Create(
"compilation",
source.Select(s => CSharpSyntaxTree.ParseText(s)),
references,
new CSharpCompilationOptions(OutputKind.ConsoleApplication)
);

return compilation;
}

private static Task<VerifyResult> VerifyGenerator(string source)
{
var compilation = CreateLibrary(source);

var generator = new InterfaceStubGenerator();
var driver = CSharpGeneratorDriver.Create(generator);

var ranDriver = driver.RunGenerators(compilation);
var settings = new VerifySettings();
var verify = VerifyXunit.Verifier.Verify(ranDriver, settings);
return verify.ToTask();
}
}
19 changes: 19 additions & 0 deletions Refit.GeneratorTests/ModuleInitializer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System.Runtime.CompilerServices;
using VerifyTests.DiffPlex;

namespace Refit.GeneratorTests;

public static class ModuleInitializer
{
// ModuleInitializer should only be used in apps
#pragma warning disable CA2255
[ModuleInitializer]
#pragma warning restore CA2255
public static void Init()
{
DerivePathInfo((file, _, type, method) => new(Path.Combine(Path.GetDirectoryName(file), "_snapshots"), type.Name, method.Name));

VerifySourceGenerators.Initialize();
VerifyDiffPlex.Initialize(OutputType.Compact);
}
}
46 changes: 46 additions & 0 deletions Refit.GeneratorTests/Refit.GeneratorTests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<Project Sdk="Microsoft.NET.Sdk">

<Import Project="..\Refit\targets\refit.props" />

<PropertyGroup>
<TargetFrameworks>net6.0;net8.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
<NoWarn>$(NoWarn);CS1591;CA1819;CA2000;CA2007;CA1056;CA1707;CA1861;xUnit1031</NoWarn>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0"/>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0"/>
<PackageReference Include="xunit" Version="2.5.3"/>
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3"/>
<PackageReference Include="System.Collections.Immutable" Version="9.0.0-preview.5.24306.7" />
<PackageReference Include="Verify.DiffPlex" Version="2.3.0" />
<PackageReference Include="Verify.SourceGenerators" Version="2.2.0" />
<PackageReference Include="Verify.Xunit" Version="22.1.4" />
<PackageReference Include="System.Reactive" Version="6.0.1" />
<PackageReference Include="Microsoft.AspNetCore.WebUtilities" Version="2.2.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.9.2" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.SourceGenerators.Testing" Version="1.1.2-beta1.24314.1" />
<ProjectReference Include="..\Refit.Newtonsoft.Json\Refit.Newtonsoft.Json.csproj" />
<ProjectReference Include="..\Refit.Xml\Refit.Xml.csproj" />
<ProjectReference Include="..\InterfaceStubGenerator.Roslyn38\InterfaceStubGenerator.Roslyn38.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="true" />
<ProjectReference Include="..\InterfaceStubGenerator.Roslyn40\InterfaceStubGenerator.Roslyn40.csproj" />
<ProjectReference Include="..\Refit\Refit.csproj" />
</ItemGroup>

<ItemGroup>
<None Include="..\Refit.GeneratorTests\_snapshots\**">
<Link>%(RecursiveDir)\resources\%(Filename)%(Extension)</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<Using Include="Xunit"/>
</ItemGroup>

<ItemGroup>
<Folder Include="_snapshots\" />
</ItemGroup>
</Project>
25 changes: 25 additions & 0 deletions Refit.GeneratorTests/ReturnTypeTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
namespace Refit.GeneratorTests;

[UsesVerify]
public class ReturnTypeTests
{
[Fact]
public Task GenericTaskShouldWork()
{
return Fixture.VerifyForBody(
"""
[Get("/users")]
Task<string> Get();
""");
}

[Fact]
public Task VoidTaskShouldWork()
{
return Fixture.VerifyForBody(
"""
[Post("/users")]
Task Post();
""");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//HintName: Generated.g.cs

#pragma warning disable
namespace Refit.Implementation
{

/// <inheritdoc />
[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
[global::System.Diagnostics.DebuggerNonUserCode]
[global::RefitInternalGenerated.PreserveAttribute]
[global::System.Reflection.Obfuscation(Exclude=true)]
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
internal static partial class Generated
{
#if NET5_0_OR_GREATER
[System.Runtime.CompilerServices.ModuleInitializer]
[System.Diagnostics.CodeAnalysis.DynamicDependency(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All, typeof(global::Refit.Implementation.Generated))]
public static void Initialize()
{
}
#endif
}
}
#pragma warning restore
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//HintName: IGeneratedClient.g.cs
#nullable disable
#pragma warning disable
namespace Refit.Implementation
{

partial class Generated
{

/// <inheritdoc />
[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
[global::System.Diagnostics.DebuggerNonUserCode]
[global::RefitInternalGenerated.PreserveAttribute]
[global::System.Reflection.Obfuscation(Exclude=true)]
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
partial class RefitGeneratorTestIGeneratedClient
: global::RefitGeneratorTest.IGeneratedClient

{
/// <inheritdoc />
public global::System.Net.Http.HttpClient Client { get; }
readonly global::Refit.IRequestBuilder requestBuilder;

/// <inheritdoc />
public RefitGeneratorTestIGeneratedClient(global::System.Net.Http.HttpClient client, global::Refit.IRequestBuilder requestBuilder)
{
Client = client;
this.requestBuilder = requestBuilder;
}



/// <inheritdoc />
public async global::System.Threading.Tasks.Task<string> Get()
{
var ______arguments = global::System.Array.Empty<object>();
var ______func = requestBuilder.BuildRestResultFuncForMethod("Get", global::System.Array.Empty<global::System.Type>() );
try
{
return await ((global::System.Threading.Tasks.Task<string>)______func(this.Client, ______arguments)).ConfigureAwait(false);
}
catch (global::System.Exception ______ex)
{
throw ______ex;
}
}

/// <inheritdoc />
async global::System.Threading.Tasks.Task<string> global::RefitGeneratorTest.IGeneratedClient.Get()
{
var ______arguments = global::System.Array.Empty<object>();
var ______func = requestBuilder.BuildRestResultFuncForMethod("Get", global::System.Array.Empty<global::System.Type>() );
try
{
return await ((global::System.Threading.Tasks.Task<string>)______func(this.Client, ______arguments)).ConfigureAwait(false);
}
catch (global::System.Exception ______ex)
{
throw ______ex;
}
}
}
}
}

#pragma warning restore
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//HintName: PreserveAttribute.g.cs

#pragma warning disable
namespace RefitInternalGenerated
{
[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
[global::System.AttributeUsage (global::System.AttributeTargets.Class | global::System.AttributeTargets.Struct | global::System.AttributeTargets.Enum | global::System.AttributeTargets.Constructor | global::System.AttributeTargets.Method | global::System.AttributeTargets.Property | global::System.AttributeTargets.Field | global::System.AttributeTargets.Event | global::System.AttributeTargets.Interface | global::System.AttributeTargets.Delegate)]
sealed class PreserveAttribute : global::System.Attribute
{
//
// Fields
//
public bool AllMembers;

public bool Conditional;
}
}
#pragma warning restore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//HintName: Generated.g.cs

#pragma warning disable
namespace Refit.Implementation
{

/// <inheritdoc />
[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
[global::System.Diagnostics.DebuggerNonUserCode]
[global::RefitInternalGenerated.PreserveAttribute]
[global::System.Reflection.Obfuscation(Exclude=true)]
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
internal static partial class Generated
{
#if NET5_0_OR_GREATER
[System.Runtime.CompilerServices.ModuleInitializer]
[System.Diagnostics.CodeAnalysis.DynamicDependency(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All, typeof(global::Refit.Implementation.Generated))]
public static void Initialize()
{
}
#endif
}
}
#pragma warning restore
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//HintName: IGeneratedClient.g.cs
#nullable disable
#pragma warning disable
namespace Refit.Implementation
{

partial class Generated
{

/// <inheritdoc />
[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
[global::System.Diagnostics.DebuggerNonUserCode]
[global::RefitInternalGenerated.PreserveAttribute]
[global::System.Reflection.Obfuscation(Exclude=true)]
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
partial class RefitGeneratorTestIGeneratedClient
: global::RefitGeneratorTest.IGeneratedClient

{
/// <inheritdoc />
public global::System.Net.Http.HttpClient Client { get; }
readonly global::Refit.IRequestBuilder requestBuilder;

/// <inheritdoc />
public RefitGeneratorTestIGeneratedClient(global::System.Net.Http.HttpClient client, global::Refit.IRequestBuilder requestBuilder)
{
Client = client;
this.requestBuilder = requestBuilder;
}



/// <inheritdoc />
public async global::System.Threading.Tasks.Task Post()
{
var ______arguments = global::System.Array.Empty<object>();
var ______func = requestBuilder.BuildRestResultFuncForMethod("Post", global::System.Array.Empty<global::System.Type>() );
try
{
await ((global::System.Threading.Tasks.Task)______func(this.Client, ______arguments)).ConfigureAwait(false);
}
catch (global::System.Exception ______ex)
{
throw ______ex;
}
}

/// <inheritdoc />
async global::System.Threading.Tasks.Task global::RefitGeneratorTest.IGeneratedClient.Post()
{
var ______arguments = global::System.Array.Empty<object>();
var ______func = requestBuilder.BuildRestResultFuncForMethod("Post", global::System.Array.Empty<global::System.Type>() );
try
{
await ((global::System.Threading.Tasks.Task)______func(this.Client, ______arguments)).ConfigureAwait(false);
}
catch (global::System.Exception ______ex)
{
throw ______ex;
}
}
}
}
}

#pragma warning restore
Loading

0 comments on commit b7cc243

Please sign in to comment.