diff --git a/.gitignore b/.gitignore index 7d9d34c..68471a8 100644 --- a/.gitignore +++ b/.gitignore @@ -351,4 +351,6 @@ MigrationBackup/ .idea/ -.DS_Store \ No newline at end of file +.DS_Store + +*.received.txt diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..3d7e69f --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,25 @@ +Contributor Guide +================= + +Prerequisites +------------- +.NET SDK 7.0 is required to build and run the project. + +Building +-------- +To build the project, execute the following shell command: +```console +$ cd src && dotnet build +``` + +Tests +----- +To run the tests, execute the following shell command: +```console +$ cd src && dotnet test +``` + +If you made changes and want to update the test data, run the following shell command (PowerShell Core is required): +```console +$ pwsh ./scripts/Approve-TestResults.ps1 +``` diff --git a/README.md b/README.md index b4d69a5..177932d 100644 --- a/README.md +++ b/README.md @@ -57,3 +57,10 @@ will generate FrameworkList for all passed DLL files with root tag ## Links * [Reference assembly specs](https://docs.microsoft.com/en-us/dotnet/standard/assembly/reference-assemblies) + +## Documentation +- [Contributor Guide][docs.contributing] +- [License (Apache-2.0)][docs.license] + +[docs.contributing]: CONTRIBUTING.md +[docs.license]: LICENSE diff --git a/scripts/Approve-TestResults.ps1 b/scripts/Approve-TestResults.ps1 new file mode 100644 index 0000000..345e6e3 --- /dev/null +++ b/scripts/Approve-TestResults.ps1 @@ -0,0 +1,17 @@ +param ( + $SolutionRoot = "$PSScriptRoot/.." +) + +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' + +if (-Not $PSScriptRoot) { + Write-Error "\`$PSScriptRoot variable isn't set. Do you run this code as a script? Please, follow instructions at https://github.com/ForNeVeR/Cesium/blob/main/docs/tests.md" +} +else { + Get-ChildItem -Recurse $SolutionRoot -Filter "*.received.txt" | ForEach-Object { + $receivedTestResult = $_.FullName + $approvedTestResult = $receivedTestResult.Replace('.received.txt', '.verified.txt') + Move-Item -Force -LiteralPath $receivedTestResult $approvedTestResult + } +} diff --git a/src/RefasmerTestAssembly/RefasmerTestAssembly.csproj b/src/RefasmerTestAssembly/RefasmerTestAssembly.csproj index 9b1871f..b3cc109 100644 --- a/src/RefasmerTestAssembly/RefasmerTestAssembly.csproj +++ b/src/RefasmerTestAssembly/RefasmerTestAssembly.csproj @@ -1,7 +1,7 @@ - net5.0;net6.0;net7.0;netstandard2.0;netstandard2.1 + net6.0 Latest true diff --git a/tests/Refasmer.Tests/IntegrationTests.cs b/tests/Refasmer.Tests/IntegrationTests.cs new file mode 100644 index 0000000..2940e47 --- /dev/null +++ b/tests/Refasmer.Tests/IntegrationTests.cs @@ -0,0 +1,68 @@ +using System.Text; +using Medallion.Shell; +using Mono.Cecil; + +namespace JetBrains.Refasmer.Tests; + +public class IntegrationTests +{ + [TestCase("RefasmerTestAssembly.PublicClassWithPrivateFields")] + [TestCase("RefasmerTestAssembly.PublicStructWithPrivateFields")] + [TestCase("RefasmerTestAssembly.UnsafeClassWithFunctionPointer")] + public async Task CheckRefasmedType(string typeName) + { + var assemblyPath = await BuildTestAssembly(); + var resultAssembly = RefasmTestAssembly(assemblyPath); + await VerifyTypeContent(resultAssembly, typeName); + } + + private static async Task BuildTestAssembly() + { + var root = FindSourceRoot(); + var testProject = Path.Combine(root, "src/RefasmerTestAssembly/RefasmerTestAssembly.csproj"); + Console.WriteLine($"Building project {testProject}…"); + var result = await Command.Run("dotnet", "build", testProject, "--configuration", "Release").Task; + + Assert.That( + result.ExitCode, + Is.EqualTo(0), + $"Failed to build test assembly, exit code {result.ExitCode}. StdOut:\n{result.StandardOutput}\nStdErr: {result.StandardError}"); + + return Path.Combine(root, "src/RefasmerTestAssembly/bin/Release/net6.0/RefasmerTestAssembly.dll"); + } + + private static string FindSourceRoot() + { + var current = Directory.GetCurrentDirectory(); + while (current != null) + { + if (File.Exists(Path.Combine(current, "README.md"))) + return current; + current = Path.GetDirectoryName(current); + } + throw new Exception("Cannot find source root."); + } + + private static string RefasmTestAssembly(string assemblyPath) + { + var tempLocation = Path.GetTempFileName(); + var exitCode = Program.Main(new[] { $"-v", $"--output={tempLocation}", assemblyPath }); + Assert.That(exitCode, Is.EqualTo(0)); + + return tempLocation; + } + + private static Task VerifyTypeContent(string assemblyPath, string typeName) + { + var assembly = AssemblyDefinition.ReadAssembly(assemblyPath); + var type = assembly.MainModule.GetType(typeName); + var printout = new StringBuilder(); + Printer.PrintType(type, printout); + + var verifySettings = new VerifySettings(); + verifySettings.DisableDiff(); + verifySettings.UseDirectory("data"); + verifySettings.UseParameters(typeName); + return Verify(printout, verifySettings); + } +} \ No newline at end of file diff --git a/tests/Refasmer.Tests/Printer.cs b/tests/Refasmer.Tests/Printer.cs new file mode 100644 index 0000000..673ebd2 --- /dev/null +++ b/tests/Refasmer.Tests/Printer.cs @@ -0,0 +1,44 @@ +using System.Text; +using Mono.Cecil; + +namespace JetBrains.Refasmer.Tests; + +public static class Printer +{ + public static void PrintType(TypeDefinition type, StringBuilder printout) + { + printout.AppendLine($"type: {type.FullName}"); + if (type.HasFields) + { + printout.AppendLine("fields:"); + foreach (var field in type.Fields) + { + printout.AppendLine($"- {field.Name}: {field.FieldType}"); + } + } + + if (type.HasMethods) + { + printout.AppendLine("methods:"); + foreach (var method in type.Methods) + { + printout.Append($"- {method.Name}("); + var parameters = method.Parameters; + for (var i = 0; i < parameters.Count; i++) + { + printout.Append($"{parameters[i].ParameterType} {parameters[i].Name}"); + if (i < parameters.Count - 1) + { + printout.Append(", "); + } + } + + printout.AppendLine($"): {method.ReturnType}:"); + foreach (var instruction in method.Body.Instructions) + { + printout.AppendLine($" - {instruction}"); + } + } + } + } +} diff --git a/tests/Refasmer.Tests/Refasmer.Tests.csproj b/tests/Refasmer.Tests/Refasmer.Tests.csproj index 6d81cfe..8eee6c4 100644 --- a/tests/Refasmer.Tests/Refasmer.Tests.csproj +++ b/tests/Refasmer.Tests/Refasmer.Tests.csproj @@ -1,6 +1,7 @@ + JetBrains.Refasmer.Tests net6.0 enable enable @@ -9,11 +10,16 @@ + - - + + - + + + + + diff --git a/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedType_typeName=RefasmerTestAssembly.PublicClassWithPrivateFields.verified.txt b/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedType_typeName=RefasmerTestAssembly.PublicClassWithPrivateFields.verified.txt new file mode 100644 index 0000000..3f76c25 --- /dev/null +++ b/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedType_typeName=RefasmerTestAssembly.PublicClassWithPrivateFields.verified.txt @@ -0,0 +1,5 @@ +type: RefasmerTestAssembly.PublicClassWithPrivateFields +fields: +- PublicInt: System.Int32 +methods: +- .ctor(): System.Void: diff --git a/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedType_typeName=RefasmerTestAssembly.PublicStructWithPrivateFields.verified.txt b/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedType_typeName=RefasmerTestAssembly.PublicStructWithPrivateFields.verified.txt new file mode 100644 index 0000000..cbff474 --- /dev/null +++ b/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedType_typeName=RefasmerTestAssembly.PublicStructWithPrivateFields.verified.txt @@ -0,0 +1,5 @@ +type: RefasmerTestAssembly.PublicStructWithPrivateFields +fields: +- PrivateInt: System.Int32 +- PrivateInt2: System.Int32 +- PublicInt: System.Int32 diff --git a/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedType_typeName=RefasmerTestAssembly.UnsafeClassWithFunctionPointer.verified.txt b/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedType_typeName=RefasmerTestAssembly.UnsafeClassWithFunctionPointer.verified.txt new file mode 100644 index 0000000..f9eb906 --- /dev/null +++ b/tests/Refasmer.Tests/data/IntegrationTests.CheckRefasmedType_typeName=RefasmerTestAssembly.UnsafeClassWithFunctionPointer.verified.txt @@ -0,0 +1,4 @@ +type: RefasmerTestAssembly.UnsafeClassWithFunctionPointer +methods: +- MethodWithFunctionPointer(method System.Void *() functionPointer): System.Void: +- .ctor(): System.Void: