Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@ trim_trailing_whitespace = true
insert_final_newline = true
spelling_exclusion_path = spelling.dic

# Verify settings
[*.{received,verified}.{cs}]
charset = "utf-8-bom"
end_of_line = lf
indent_size = unset
indent_style = unset
insert_final_newline = false
tab_width = unset
trim_trailing_whitespace = false

[*.{cs,csx,cake}]
indent_size = 4
dotnet_sort_system_directives_first = true
Expand Down
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,6 @@
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain

# Verify.Xunit
*.verified.cs text eol=lf working-tree-encoding=UTF-8
21 changes: 21 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -515,3 +515,24 @@ jobs:
path: |
**/TestResults/*
**/logs/*
test-codegenerator:
name: Test Code Generator
runs-on: ${{ matrix.os }}
continue-on-error: true
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
framework: [net8.0]
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: |
8.0.x
- name: Test Code Generator
run: dotnet test
test/Orleans.CodeGenerator.Tests/Orleans.CodeGenerator.Tests.csproj
--framework ${{ matrix.framework }}
--logger "trx;LogFileName=test_results_${{ matrix.framework }}.trx"
--logger "GitHubActions;summary.includePassedTests=true;summary.includeSkippedTests=true;summary.includeNotFoundTests=false"
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -214,3 +214,9 @@ src/SetupTestScriptOutput.txt

# VS Code
.ionide/

# Verify.Xunit
*.received.*

# code coverage
*.cobertura.xml
3 changes: 3 additions & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,10 @@
<PackageVersion Include="CassandraCSharpDriver" Version="3.20.1" />
<!-- Test related packages -->
<PackageVersion Include="coverlet.collector" Version="6.0.2" />
<PackageVersion Include="coverlet.msbuild" Version="6.0.0" />
<PackageVersion Include="AwesomeAssertions" Version="8.0.2" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.SourceGenerators.Testing" Version="1.1.2" />
<PackageVersion Include="BenchmarkDotNet" Version="0.13.12" />
<PackageVersion Include="BenchmarkDotNet.Diagnostics.Windows" Version="0.13.12" />
<PackageVersion Include="Xunit.SkippableFact" Version="1.4.13" />
Expand All @@ -89,6 +91,7 @@
<PackageVersion Include="xunit.extensibility.core" Version="$(xUnitVersion)" />
<PackageVersion Include="xunit.extensibility.execution" Version="$(xUnitVersion)" />
<PackageVersion Include="xunit.runner.visualstudio" Version="$(xUnitRunnerVersion)" />
<PackageVersion Include="Verify.Xunit" Version="28.15.0" />
<PackageVersion Include="NodaTime" Version="3.1.10" />
<PackageVersion Include="Autofac.Extensions.DependencyInjection" Version="8.0.0" />
<PackageVersion Include="StructureMap.Microsoft.DependencyInjection" Version="2.0.0" />
Expand Down
7 changes: 7 additions & 0 deletions Orleans.sln
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orleans.Journaling.Tests",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orleans.Journaling.AzureStorage", "src\Azure\Orleans.Journaling.AzureStorage\Orleans.Journaling.AzureStorage.csproj", "{E613A10D-757D-44BA-97C1-3D06C22BDB2E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orleans.CodeGenerator.Tests", "test\Orleans.CodeGenerator.Tests\Orleans.CodeGenerator.Tests.csproj", "{AE0BB9EA-FC9C-428A-B8F1-501798CA4B50}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -690,6 +692,10 @@ Global
{E613A10D-757D-44BA-97C1-3D06C22BDB2E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E613A10D-757D-44BA-97C1-3D06C22BDB2E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E613A10D-757D-44BA-97C1-3D06C22BDB2E}.Release|Any CPU.Build.0 = Release|Any CPU
{AE0BB9EA-FC9C-428A-B8F1-501798CA4B50}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AE0BB9EA-FC9C-428A-B8F1-501798CA4B50}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AE0BB9EA-FC9C-428A-B8F1-501798CA4B50}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AE0BB9EA-FC9C-428A-B8F1-501798CA4B50}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -817,6 +823,7 @@ Global
{20EFDCFC-F3FE-5509-5950-516E90DE1E05} = {4CD3AA9E-D937-48CA-BB6C-158E12257D23}
{4A4D30F4-6D61-7A80-8352-D76BD29582E0} = {A6573187-FD0D-4DF7-91D1-03E07E470C0A}
{E613A10D-757D-44BA-97C1-3D06C22BDB2E} = {4C5D66BF-EE1C-4DD8-8551-D1B7F3768A34}
{AE0BB9EA-FC9C-428A-B8F1-501798CA4B50} = {A6573187-FD0D-4DF7-91D1-03E07E470C0A}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {7BFB3429-B5BB-4DB1-95B4-67D77A864952}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<OrleansBuildTimeCodeGen>true</OrleansBuildTimeCodeGen>
<TargetFrameworks>$(TestTargetFrameworks)</TargetFrameworks>
</PropertyGroup>

<PropertyGroup>
<CentralPackageTransitivePinningEnabled>false</CentralPackageTransitivePinningEnabled>
<xUnitVersion>2.9.3</xUnitVersion>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

due to the dependency on xunit.extensibility.execution see https://www.nuget.org/packages/Verify.Xunit/28.15.0#dependencies-body-tab

could we upgrade the xunit versions in this repo? (maybe separate PR)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we can upgrade xUnit - either in this PR or a separate PR

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a separate PR would be better, are we still supporting netcoreapp3.1? There are some conditions there, we'll discuss this in the new PR for xunit upgrades

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We support it just for the code generator... we will drop it at some point (maybe for the .NET 10 release). It's ok if tests don't cover it.

<CollectCoverage>true</CollectCoverage>
<CoverletOutputFormat>cobertura</CoverletOutputFormat>
<Include>[Orleans.CodeGenerator]*</Include>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.SourceGenerators.Testing" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" />
<PackageReference Include="xunit" />
<PackageReference Include="xunit.runner.visualstudio" />
<PackageReference Include="Microsoft.NET.Test.Sdk" />
</ItemGroup>

<ItemGroup>
<!-- due to Verify.Xunit requiring newer versions of these libraries -->
<PackageReference Include="coverlet.msbuild">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="System.IO.Hashing" VersionOverride="9.0.3" />
<PackageReference Include="System.CodeDom" VersionOverride="9.0.2" />
<PackageReference Include="Verify.Xunit" />
<Compile Remove="snapshots\**\*" />
<None Include="snapshots\**\*" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\Orleans.CodeGenerator\Orleans.CodeGenerator.csproj" />
<ProjectReference Include="..\..\src\Orleans.Sdk\Orleans.Sdk.csproj" />
<ProjectReference Include="..\..\src\Orleans.Runtime\Orleans.Runtime.csproj" />
</ItemGroup>



</Project>
72 changes: 72 additions & 0 deletions test/Orleans.CodeGenerator.Tests/OrleansSourceGeneratorTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Testing;
using Microsoft.Extensions.DependencyInjection;
using Orleans.Serialization;
using Xunit;

namespace Orleans.CodeGenerator.Tests;

public class OrleansSourceGeneratorTests
{
[Fact]
public async Task TestBasicClass()
{
var projectName = "TestProject";
var compilation = await CreateCompilation(
@"using Orleans;

namespace TestProject;

[Serializable, GenerateSerializer]
public class DemoData
{
[Id(0)]
public string Value { get; set; } = string.Empty;
}
", projectName);

var generator = new OrleansSerializationSourceGenerator();

GeneratorDriver driver = CSharpGeneratorDriver.Create(
generators: [generator],
driverOptions: new GeneratorDriverOptions(default));

// Run the generator
driver = driver.RunGenerators(compilation);

var result = driver.GetRunResult().Results.Single();
Assert.Empty(result.Diagnostics);

Assert.Single(result.GeneratedSources);
Assert.Equal($"{projectName}.orleans.g.cs", result.GeneratedSources[0].HintName);
var generatedSource = result.GeneratedSources[0].SourceText.ToString();

await Verify(generatedSource, extension: "cs").UseDirectory("snapshots");
}

private static async Task<CSharpCompilation> CreateCompilation(string sourceCode, string assemblyName = "TestProject")
{
var references = await ReferenceAssemblies.Net.Net80.ResolveAsync(LanguageNames.CSharp, default);

// Add the Orleans Orleans.Core.Abstractions assembly
references = references.AddRange(
// Orleans.Core.Abstractions
MetadataReference.CreateFromFile(typeof(GrainId).Assembly.Location),
// Orleans.Core
MetadataReference.CreateFromFile(typeof(IClusterClientLifecycle).Assembly.Location),
// Orleans.Runtime
MetadataReference.CreateFromFile(typeof(IGrainActivator).Assembly.Location),
// Orleans.Serialization
MetadataReference.CreateFromFile(typeof(Serializer).Assembly.Location),
// Orleans.Serialization.Abstractions
MetadataReference.CreateFromFile(typeof(GenerateFieldIds).Assembly.Location),
// Microsoft.Extensions.DependencyInjection.Abstractions
MetadataReference.CreateFromFile(typeof(ActivatorUtilitiesConstructorAttribute).Assembly.Location)
);

var syntaxTree = CSharpSyntaxTree.ParseText(sourceCode);

return CSharpCompilation.Create(assemblyName, [syntaxTree], references, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
#pragma warning disable CS1591, RS0016, RS0041
[assembly: global::Orleans.ApplicationPartAttribute("TestProject")]
[assembly: global::Orleans.ApplicationPartAttribute("Orleans.Core.Abstractions")]
[assembly: global::Orleans.ApplicationPartAttribute("Orleans.Serialization")]
[assembly: global::Orleans.ApplicationPartAttribute("Orleans.Core")]
[assembly: global::Orleans.ApplicationPartAttribute("Orleans.Runtime")]
[assembly: global::Orleans.Serialization.Configuration.TypeManifestProviderAttribute(typeof(OrleansCodeGen.TestProject.Metadata_TestProject))]
namespace OrleansCodeGen.TestProject
{
using global::Orleans.Serialization.Codecs;
using global::Orleans.Serialization.GeneratedCodeHelpers;

[global::System.CodeDom.Compiler.GeneratedCodeAttribute("OrleansCodeGen", "9.0.0.0"), global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never), global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute]
public sealed class Codec_DemoData : global::Orleans.Serialization.Codecs.IFieldCodec<global::TestProject.DemoData>, global::Orleans.Serialization.Serializers.IBaseCodec<global::TestProject.DemoData>
{
private readonly global::System.Type _codecFieldType = typeof(global::TestProject.DemoData);
[global::System.Runtime.CompilerServices.MethodImplAttribute(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public void Serialize<TBufferWriter>(ref global::Orleans.Serialization.Buffers.Writer<TBufferWriter> writer, global::TestProject.DemoData instance)
where TBufferWriter : global::System.Buffers.IBufferWriter<byte>
{
global::Orleans.Serialization.Codecs.StringCodec.WriteField(ref writer, 0U, instance.Value);
}

[global::System.Runtime.CompilerServices.MethodImplAttribute(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public void Deserialize<TReaderInput>(ref global::Orleans.Serialization.Buffers.Reader<TReaderInput> reader, global::TestProject.DemoData instance)
{
uint id = 0U;
global::Orleans.Serialization.WireProtocol.Field header = default;
while (true)
{
reader.ReadFieldHeader(ref header);
if (header.IsEndBaseOrEndObject)
break;
id += header.FieldIdDelta;
if (id == 0U)
{
instance.Value = global::Orleans.Serialization.Codecs.StringCodec.ReadValue(ref reader, header);
reader.ReadFieldHeader(ref header);
}

reader.ConsumeEndBaseOrEndObject(ref header);
break;
}
}

[global::System.Runtime.CompilerServices.MethodImplAttribute(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public void WriteField<TBufferWriter>(ref global::Orleans.Serialization.Buffers.Writer<TBufferWriter> writer, uint fieldIdDelta, global::System.Type expectedType, global::TestProject.DemoData @value)
where TBufferWriter : global::System.Buffers.IBufferWriter<byte>
{
if (@value is null || @value.GetType() == typeof(global::TestProject.DemoData))
{
if (ReferenceCodec.TryWriteReferenceField(ref writer, fieldIdDelta, expectedType, @value))
return;
writer.WriteStartObject(fieldIdDelta, expectedType, _codecFieldType);
Serialize(ref writer, @value);
writer.WriteEndObject();
}
else
writer.SerializeUnexpectedType(fieldIdDelta, expectedType, @value);
}

[global::System.Runtime.CompilerServices.MethodImplAttribute(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public global::TestProject.DemoData ReadValue<TReaderInput>(ref global::Orleans.Serialization.Buffers.Reader<TReaderInput> reader, global::Orleans.Serialization.WireProtocol.Field field)
{
if (field.IsReference)
return ReferenceCodec.ReadReference<global::TestProject.DemoData, TReaderInput>(ref reader, field);
field.EnsureWireTypeTagDelimited();
global::System.Type valueType = field.FieldType;
if (valueType is null || valueType == _codecFieldType)
{
var result = new global::TestProject.DemoData();
ReferenceCodec.RecordObject(reader.Session, result);
Deserialize(ref reader, result);
return result;
}

return reader.DeserializeUnexpectedType<TReaderInput, global::TestProject.DemoData>(ref field);
}
}

[global::System.CodeDom.Compiler.GeneratedCodeAttribute("OrleansCodeGen", "9.0.0.0"), global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never), global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute]
public sealed class Copier_DemoData : global::Orleans.Serialization.Cloning.IDeepCopier<global::TestProject.DemoData>, global::Orleans.Serialization.Cloning.IBaseCopier<global::TestProject.DemoData>
{
[global::System.Runtime.CompilerServices.MethodImplAttribute(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public global::TestProject.DemoData DeepCopy(global::TestProject.DemoData original, global::Orleans.Serialization.Cloning.CopyContext context)
{
if (context.TryGetCopy(original, out global::TestProject.DemoData existing))
return existing;
if (original.GetType() != typeof(global::TestProject.DemoData))
return context.DeepCopy(original);
var result = new global::TestProject.DemoData();
context.RecordCopy(original, result);
DeepCopy(original, result, context);
return result;
}

[global::System.Runtime.CompilerServices.MethodImplAttribute(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public void DeepCopy(global::TestProject.DemoData input, global::TestProject.DemoData output, global::Orleans.Serialization.Cloning.CopyContext context)
{
output.Value = input.Value;
}
}

[global::System.CodeDom.Compiler.GeneratedCodeAttribute("OrleansCodeGen", "9.0.0.0"), global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never), global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute]
internal sealed class Activator_DemoData : global::Orleans.Serialization.Activators.IActivator<global::TestProject.DemoData>
{
public global::TestProject.DemoData Create() => new global::TestProject.DemoData();
}

[global::System.CodeDom.Compiler.GeneratedCodeAttribute("OrleansCodeGen", "9.0.0.0"), global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never), global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute]
internal sealed class Metadata_TestProject : global::Orleans.Serialization.Configuration.TypeManifestProviderBase
{
protected override void ConfigureInner(global::Orleans.Serialization.Configuration.TypeManifestOptions config)
{
config.Serializers.Add(typeof(OrleansCodeGen.TestProject.Codec_DemoData));
config.Copiers.Add(typeof(OrleansCodeGen.TestProject.Copier_DemoData));
config.Activators.Add(typeof(OrleansCodeGen.TestProject.Activator_DemoData));
}
}
}
#pragma warning restore CS1591, RS0016, RS0041