Browse Source

- Make all tests async.

- Use custom test runner for correctness tests.
- Use .NET 6.0 framework for all Roslyn compiler tests.
- Disabled tests involving new string interpolation patterns.
pull/2642/head
Siegfried Pammer 3 years ago
parent
commit
e4b63f7a35
  1. 12
      ICSharpCode.Decompiler.TestRunner/ICSharpCode.Decompiler.TestRunner.csproj
  2. 43
      ICSharpCode.Decompiler.TestRunner/Program.cs
  3. 192
      ICSharpCode.Decompiler.Tests/CorrectnessTestRunner.cs
  4. 10
      ICSharpCode.Decompiler.Tests/DisassemblerPrettyTestRunner.cs
  5. 115
      ICSharpCode.Decompiler.Tests/Helpers/RoslynToolset.cs
  6. 54
      ICSharpCode.Decompiler.Tests/Helpers/Tester.VB.cs
  7. 411
      ICSharpCode.Decompiler.Tests/Helpers/Tester.cs
  8. 4
      ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
  9. 143
      ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs
  10. 345
      ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs
  11. 168
      ICSharpCode.Decompiler.Tests/RoundtripAssembly.cs
  12. 9
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/DeconstructionTests.cs
  13. 3
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/QueryExpressions.cs
  14. 2
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/StringInterpolation.cs
  15. 13
      ICSharpCode.Decompiler.Tests/TestTraceListener.cs
  16. 43
      ICSharpCode.Decompiler.Tests/UglyTestRunner.cs
  17. 31
      ICSharpCode.Decompiler.Tests/VBPrettyTestRunner.cs
  18. 9
      ILSpy.sln

12
ICSharpCode.Decompiler.TestRunner/ICSharpCode.Decompiler.TestRunner.csproj

@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<PlatformTarget>x64</PlatformTarget>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<OutputPath>..\ICSharpCode.Decompiler.Tests\bin\$(Configuration)\$(TargetFramework)\win-x64\</OutputPath>
</PropertyGroup>
</Project>

43
ICSharpCode.Decompiler.TestRunner/Program.cs

@ -0,0 +1,43 @@ @@ -0,0 +1,43 @@
using System;
using System.Reflection;
using System.Runtime.Loader;
namespace ICSharpCode.Decompiler.TestRunner;
public static class Program
{
static int Main(string[] args)
{
AssemblyLoadContext context = new("TestRunner", isCollectible: true);
context.Resolving += ContextResolving;
try
{
var mainAssembly = context.LoadFromAssemblyPath(args[0]);
int paramCount = mainAssembly.EntryPoint!.GetParameters().Length;
object? result = mainAssembly.EntryPoint!.Invoke(null, paramCount == 0 ? new object[0] : new object[1] { new string[0] });
return result is int i ? i : 0;
}
catch (Exception ex)
{
Console.Error.WriteLine("TestRunner crashed:");
Console.Error.WriteLine(ex.ToString());
return -1;
}
finally
{
context.Unload();
context.Resolving -= ContextResolving;
}
}
private static Assembly? ContextResolving(AssemblyLoadContext context, AssemblyName name)
{
return null;
}
}

192
ICSharpCode.Decompiler.Tests/CorrectnessTestRunner.cs

@ -21,6 +21,7 @@ using System.CodeDom.Compiler; @@ -21,6 +21,7 @@ using System.CodeDom.Compiler;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using ICSharpCode.Decompiler.Tests.Helpers;
@ -110,19 +111,19 @@ namespace ICSharpCode.Decompiler.Tests @@ -110,19 +111,19 @@ namespace ICSharpCode.Decompiler.Tests
};
[Test]
public void Comparisons([ValueSource(nameof(defaultOptions))] CompilerOptions options)
public async Task Comparisons([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{
RunCS(options: options);
await RunCS(options: options);
}
[Test]
public void Conversions([ValueSource(nameof(defaultOptions))] CompilerOptions options)
public async Task Conversions([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{
RunCS(options: options);
await RunCS(options: options);
}
[Test]
public void FloatingPointArithmetic([ValueSource(nameof(noMonoOptions))] CompilerOptions options, [Values(32, 64)] int bits)
public async Task FloatingPointArithmetic([ValueSource(nameof(noMonoOptions))] CompilerOptions options, [Values(32, 64)] int bits)
{
// The behavior of the #1794 incorrect `(float)(double)val` cast only causes test failures
// for some runtime+compiler combinations.
@ -130,125 +131,125 @@ namespace ICSharpCode.Decompiler.Tests @@ -130,125 +131,125 @@ namespace ICSharpCode.Decompiler.Tests
options |= CompilerOptions.Force32Bit;
// Mono is excluded because we never use it for the second pass, so the test ends up failing
// due to some Mono vs. Roslyn compiler differences.
RunCS(options: options);
await RunCS(options: options);
}
[Test]
public void HelloWorld([ValueSource(nameof(defaultOptions))] CompilerOptions options)
public async Task HelloWorld([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{
RunCS(options: options);
await RunCS(options: options);
}
[Test]
public void ControlFlow([ValueSource(nameof(defaultOptions))] CompilerOptions options)
public async Task ControlFlow([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{
RunCS(options: options);
await RunCS(options: options);
}
[Test]
public void CompoundAssignment([ValueSource(nameof(defaultOptions))] CompilerOptions options)
public async Task CompoundAssignment([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{
RunCS(options: options);
await RunCS(options: options);
}
[Test]
public void PropertiesAndEvents([ValueSource(nameof(defaultOptions))] CompilerOptions options)
public async Task PropertiesAndEvents([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{
RunCS(options: options);
await RunCS(options: options);
}
[Test]
public void Switch([ValueSource(nameof(defaultOptions))] CompilerOptions options)
public async Task Switch([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{
RunCS(options: options);
await RunCS(options: options);
}
[Test]
public void Using([ValueSource(nameof(defaultOptions))] CompilerOptions options)
public async Task Using([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{
RunCS(options: options);
await RunCS(options: options);
}
[Test]
public void Loops([ValueSource(nameof(defaultOptions))] CompilerOptions options)
public async Task Loops([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{
RunCS(options: options);
await RunCS(options: options);
}
[Test]
public void NullableTests([ValueSource(nameof(defaultOptions))] CompilerOptions options)
public async Task NullableTests([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{
RunCS(options: options);
await RunCS(options: options);
}
[Test]
public void Generics([ValueSource(nameof(defaultOptions))] CompilerOptions options)
public async Task Generics([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{
RunCS(options: options);
await RunCS(options: options);
}
[Test]
public void ValueTypeCall([ValueSource(nameof(defaultOptions))] CompilerOptions options)
public async Task ValueTypeCall([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{
RunCS(options: options);
await RunCS(options: options);
}
[Test]
public void InitializerTests([ValueSource(nameof(defaultOptions))] CompilerOptions options)
public async Task InitializerTests([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{
RunCS(options: options);
await RunCS(options: options);
}
[Test]
public void DecimalFields([ValueSource(nameof(defaultOptions))] CompilerOptions options)
public async Task DecimalFields([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{
RunCS(options: options);
await RunCS(options: options);
}
[Test]
public void UndocumentedExpressions([ValueSource(nameof(noMonoOptions))] CompilerOptions options)
public async Task UndocumentedExpressions([ValueSource(nameof(noMonoOptions))] CompilerOptions options)
{
RunCS(options: options);
await RunCS(options: options);
}
[Test]
public void Uninit([ValueSource(nameof(noMonoOptions))] CompilerOptions options)
public async Task Uninit([ValueSource(nameof(noMonoOptions))] CompilerOptions options)
{
RunVB(options: options);
await RunVB(options: options);
}
[Test]
public void MemberLookup([ValueSource(nameof(defaultOptions))] CompilerOptions options)
public async Task MemberLookup([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{
RunCS(options: options);
await RunCS(options: options);
}
[Test]
public void OverloadResolution([ValueSource(nameof(defaultOptions))] CompilerOptions options)
public async Task OverloadResolution([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{
RunCS(options: options);
await RunCS(options: options);
}
[Test]
public void ExpressionTrees([ValueSource(nameof(defaultOptions))] CompilerOptions options)
public async Task ExpressionTrees([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{
RunCS(options: options);
await RunCS(options: options);
}
[Test]
public void NullPropagation([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions options)
public async Task NullPropagation([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions options)
{
RunCS(options: options);
await RunCS(options: options);
}
[Test]
public void DeconstructionTests([ValueSource(nameof(roslyn2OrNewerOptions))] CompilerOptions options)
public async Task DeconstructionTests([ValueSource(nameof(roslyn2OrNewerOptions))] CompilerOptions options)
{
RunCS(options: options);
await RunCS(options: options);
}
[Test]
public void BitNot([Values(false, true)] bool force32Bit)
public async Task BitNot([Values(false, true)] bool force32Bit)
{
CompilerOptions compiler = CompilerOptions.UseDebug;
AssemblerOptions asm = AssemblerOptions.None;
@ -257,23 +258,23 @@ namespace ICSharpCode.Decompiler.Tests @@ -257,23 +258,23 @@ namespace ICSharpCode.Decompiler.Tests
compiler |= CompilerOptions.Force32Bit;
asm |= AssemblerOptions.Force32Bit;
}
RunIL("BitNot.il", compiler, asm);
await RunIL("BitNot.il", compiler, asm);
}
[Test]
public void Jmp()
public async Task Jmp()
{
RunIL("Jmp.il");
await RunIL("Jmp.il");
}
[Test]
public void StackTests()
public async Task StackTests()
{
RunIL("StackTests.il");
await RunIL("StackTests.il");
}
[Test]
public void StackTypes([Values(false, true)] bool force32Bit)
public async Task StackTypes([Values(false, true)] bool force32Bit)
{
CompilerOptions compiler = CompilerOptions.UseRoslynLatest | CompilerOptions.UseDebug;
AssemblerOptions asm = AssemblerOptions.None;
@ -282,92 +283,94 @@ namespace ICSharpCode.Decompiler.Tests @@ -282,92 +283,94 @@ namespace ICSharpCode.Decompiler.Tests
compiler |= CompilerOptions.Force32Bit;
asm |= AssemblerOptions.Force32Bit;
}
RunIL("StackTypes.il", compiler, asm);
await RunIL("StackTypes.il", compiler, asm);
}
[Test]
public void UnsafeCode([ValueSource(nameof(defaultOptions))] CompilerOptions options)
public async Task UnsafeCode([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{
if (options.HasFlag(CompilerOptions.UseMcs2_6_4))
{
Assert.Ignore("Decompiler bug with mono!");
}
RunCS(options: options);
await RunCS(options: options);
}
[Test]
public void ConditionalAttr([ValueSource(nameof(defaultOptions))] CompilerOptions options)
public async Task ConditionalAttr([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{
RunCS(options: options);
await RunCS(options: options);
}
[Test]
public void TrickyTypes([ValueSource(nameof(defaultOptions))] CompilerOptions options)
public async Task TrickyTypes([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{
RunCS(options: options);
await RunCS(options: options);
}
[Test]
public void Capturing([ValueSource(nameof(defaultOptions))] CompilerOptions options)
public async Task Capturing([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{
RunCS(options: options);
await RunCS(options: options);
}
[Test]
public void YieldReturn([ValueSource(nameof(defaultOptions))] CompilerOptions options)
public async Task YieldReturn([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{
if ((options & CompilerOptions.UseMcsMask) != 0)
{
Assert.Ignore("Decompiler bug with mono!");
}
RunCS(options: options);
await RunCS(options: options);
}
[Test]
public void Async([ValueSource(nameof(noMonoOptions))] CompilerOptions options)
public async Task Async([ValueSource(nameof(noMonoOptions))] CompilerOptions options)
{
RunCS(options: options);
await RunCS(options: options);
}
[Test]
public void LINQRaytracer([ValueSource(nameof(defaultOptions))] CompilerOptions options)
public async Task LINQRaytracer([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{
RunCS(options: options);
await RunCS(options: options);
}
[Test]
public void StringConcat([ValueSource(nameof(defaultOptions))] CompilerOptions options)
public async Task StringConcat([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{
RunCS(options: options);
await RunCS(options: options);
}
[Test]
public void DynamicTests([ValueSource(nameof(noMonoOptions))] CompilerOptions options)
public async Task DynamicTests([ValueSource(nameof(noMonoOptions))] CompilerOptions options)
{
RunCS(options: options);
await RunCS(options: options);
}
[Test]
public void MiniJSON([ValueSource(nameof(defaultOptions))] CompilerOptions options)
public async Task MiniJSON([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{
if (options.HasFlag(CompilerOptions.UseMcs2_6_4))
{
Assert.Ignore("Decompiler bug with mono!");
}
RunCS(options: options);
await RunCS(options: options);
}
void RunCS([CallerMemberName] string testName = null, CompilerOptions options = CompilerOptions.UseDebug)
async Task RunCS([CallerMemberName] string testName = null, CompilerOptions options = CompilerOptions.UseDebug)
{
if ((options & CompilerOptions.UseRoslynMask) != 0)
options |= CompilerOptions.UseTestRunner;
string testFileName = testName + ".cs";
string testOutputFileName = testName + Tester.GetSuffix(options) + ".exe";
CompilerResults outputFile = null, decompiledOutputFile = null;
try
{
outputFile = Tester.CompileCSharp(Path.Combine(TestCasePath, testFileName), options,
outputFileName: Path.Combine(TestCasePath, testOutputFileName));
string decompiledCodeFile = Tester.DecompileCSharp(outputFile.PathToAssembly, Tester.GetSettings(options));
outputFile = await Tester.CompileCSharp(Path.Combine(TestCasePath, testFileName), options,
outputFileName: Path.Combine(TestCasePath, testOutputFileName)).ConfigureAwait(false);
string decompiledCodeFile = await Tester.DecompileCSharp(outputFile.PathToAssembly, Tester.GetSettings(options)).ConfigureAwait(false);
if ((options & CompilerOptions.UseMcsMask) != 0)
{
// For second pass, use roslyn instead of mcs.
@ -375,17 +378,11 @@ namespace ICSharpCode.Decompiler.Tests @@ -375,17 +378,11 @@ namespace ICSharpCode.Decompiler.Tests
// for example when there's unreachable code due to other compiler bugs in the first mcs run.
options &= ~CompilerOptions.UseMcsMask;
options |= CompilerOptions.UseRoslynLatest;
// Also, add an .exe.config so that we consistently use the .NET 4.x runtime.
File.WriteAllText(outputFile.PathToAssembly + ".config", @"<?xml version=""1.0"" encoding=""utf-8""?>
<configuration>
<startup>
<supportedRuntime version=""v4.0"" sku="".NETFramework,Version=v4.0,Profile=Client"" />
</startup>
</configuration>");
options |= CompilerOptions.UseTestRunner;
}
decompiledOutputFile = Tester.CompileCSharp(decompiledCodeFile, options);
decompiledOutputFile = await Tester.CompileCSharp(decompiledCodeFile, options).ConfigureAwait(false);
Tester.RunAndCompareOutput(testFileName, outputFile.PathToAssembly, decompiledOutputFile.PathToAssembly, decompiledCodeFile);
await Tester.RunAndCompareOutput(testFileName, outputFile.PathToAssembly, decompiledOutputFile.PathToAssembly, decompiledCodeFile, (options & CompilerOptions.UseTestRunner) != 0, (options & CompilerOptions.Force32Bit) != 0);
Tester.RepeatOnIOError(() => File.Delete(decompiledCodeFile));
Tester.RepeatOnIOError(() => File.Delete(decompiledOutputFile.PathToAssembly));
@ -399,21 +396,23 @@ namespace ICSharpCode.Decompiler.Tests @@ -399,21 +396,23 @@ namespace ICSharpCode.Decompiler.Tests
}
}
void RunVB([CallerMemberName] string testName = null, CompilerOptions options = CompilerOptions.UseDebug)
async Task RunVB([CallerMemberName] string testName = null, CompilerOptions options = CompilerOptions.UseDebug)
{
options |= CompilerOptions.ReferenceVisualBasic;
if ((options & CompilerOptions.UseRoslynMask) != 0)
options |= CompilerOptions.UseTestRunner;
string testFileName = testName + ".vb";
string testOutputFileName = testName + Tester.GetSuffix(options) + ".exe";
CompilerResults outputFile = null, decompiledOutputFile = null;
try
{
outputFile = Tester.CompileVB(Path.Combine(TestCasePath, testFileName), options,
outputFileName: Path.Combine(TestCasePath, testOutputFileName));
string decompiledCodeFile = Tester.DecompileCSharp(outputFile.PathToAssembly, Tester.GetSettings(options));
decompiledOutputFile = Tester.CompileCSharp(decompiledCodeFile, options);
outputFile = await Tester.CompileVB(Path.Combine(TestCasePath, testFileName), options,
outputFileName: Path.Combine(TestCasePath, testOutputFileName)).ConfigureAwait(false);
string decompiledCodeFile = await Tester.DecompileCSharp(outputFile.PathToAssembly, Tester.GetSettings(options)).ConfigureAwait(false);
decompiledOutputFile = await Tester.CompileCSharp(decompiledCodeFile, options).ConfigureAwait(false);
Tester.RunAndCompareOutput(testFileName, outputFile.PathToAssembly, decompiledOutputFile.PathToAssembly, decompiledCodeFile);
await Tester.RunAndCompareOutput(testFileName, outputFile.PathToAssembly, decompiledOutputFile.PathToAssembly, decompiledCodeFile, (options & CompilerOptions.UseTestRunner) != 0, (options & CompilerOptions.Force32Bit) != 0);
Tester.RepeatOnIOError(() => File.Delete(decompiledCodeFile));
Tester.RepeatOnIOError(() => File.Delete(decompiledOutputFile.PathToAssembly));
@ -427,18 +426,19 @@ namespace ICSharpCode.Decompiler.Tests @@ -427,18 +426,19 @@ namespace ICSharpCode.Decompiler.Tests
}
}
void RunIL(string testFileName, CompilerOptions options = CompilerOptions.UseDebug, AssemblerOptions asmOptions = AssemblerOptions.None)
async Task RunIL(string testFileName, CompilerOptions options = CompilerOptions.UseDebug, AssemblerOptions asmOptions = AssemblerOptions.None)
{
string outputFile = null;
CompilerResults decompiledOutputFile = null;
try
{
outputFile = Tester.AssembleIL(Path.Combine(TestCasePath, testFileName), asmOptions);
string decompiledCodeFile = Tester.DecompileCSharp(outputFile, Tester.GetSettings(options));
decompiledOutputFile = Tester.CompileCSharp(decompiledCodeFile, options);
options |= CompilerOptions.UseTestRunner;
outputFile = await Tester.AssembleIL(Path.Combine(TestCasePath, testFileName), asmOptions).ConfigureAwait(false);
string decompiledCodeFile = await Tester.DecompileCSharp(outputFile, Tester.GetSettings(options)).ConfigureAwait(false);
decompiledOutputFile = await Tester.CompileCSharp(decompiledCodeFile, options).ConfigureAwait(false);
Tester.RunAndCompareOutput(testFileName, outputFile, decompiledOutputFile.PathToAssembly, decompiledCodeFile);
await Tester.RunAndCompareOutput(testFileName, outputFile, decompiledOutputFile.PathToAssembly, decompiledCodeFile, (options & CompilerOptions.UseTestRunner) != 0, (options & CompilerOptions.Force32Bit) != 0).ConfigureAwait(false);
Tester.RepeatOnIOError(() => File.Delete(decompiledCodeFile));
Tester.RepeatOnIOError(() => File.Delete(decompiledOutputFile.PathToAssembly));

10
ICSharpCode.Decompiler.Tests/DisassemblerPrettyTestRunner.cs

@ -53,18 +53,18 @@ namespace ICSharpCode.Decompiler.Tests @@ -53,18 +53,18 @@ namespace ICSharpCode.Decompiler.Tests
}
[Test]
public void SecurityDeclarations()
public async Task SecurityDeclarations()
{
Run();
await Run();
}
void Run([CallerMemberName] string testName = null)
async Task Run([CallerMemberName] string testName = null)
{
var ilExpectedFile = Path.Combine(TestCasePath, testName + ".il");
var ilResultFile = Path.Combine(TestCasePath, testName + ".result.il");
var executable = Tester.AssembleIL(ilExpectedFile, AssemblerOptions.Library);
var disassembled = Tester.Disassemble(executable, ilResultFile, AssemblerOptions.UseOwnDisassembler);
var executable = await Tester.AssembleIL(ilExpectedFile, AssemblerOptions.Library).ConfigureAwait(false);
var disassembled = await Tester.Disassemble(executable, ilResultFile, AssemblerOptions.UseOwnDisassembler).ConfigureAwait(false);
CodeAssert.FilesAreEqual(ilExpectedFile, ilResultFile);
}

115
ICSharpCode.Decompiler.Tests/Helpers/RoslynToolset.cs

@ -18,12 +18,13 @@ @@ -18,12 +18,13 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using ICSharpCode.Decompiler.Util;
using NuGet.Common;
using NuGet.Packaging;
using NuGet.Protocol;
@ -32,63 +33,29 @@ using NuGet.Versioning; @@ -32,63 +33,29 @@ using NuGet.Versioning;
namespace ICSharpCode.Decompiler.Tests.Helpers
{
class RoslynToolset
abstract class AbstractToolset
{
readonly SourceCacheContext cache;
readonly SourceRepository repository;
readonly FindPackageByIdResource resource;
readonly string nugetDir;
readonly Dictionary<string, string> installedCompilers = new Dictionary<string, string> {
{ "legacy", Environment.ExpandEnvironmentVariables(@"%WINDIR%\Microsoft.NET\Framework\v4.0.30319") }
};
readonly object syncObj = new object();
protected readonly string baseDir;
public RoslynToolset()
public AbstractToolset(string baseDir)
{
this.cache = new SourceCacheContext();
this.repository = Repository.Factory.GetCoreV3("https://api.nuget.org/v3/index.json");
this.resource = repository.GetResource<FindPackageByIdResource>();
this.nugetDir = Path.Combine(Path.GetDirectoryName(typeof(RoslynToolset).Assembly.Location), "roslyn");
}
public string GetCSharpCompiler(string version)
{
return GetCompiler("csc.exe", version);
}
public string GetVBCompiler(string version)
{
return GetCompiler("vbc.exe", version);
}
string GetCompiler(string compiler, string version)
{
lock (syncObj)
{
if (installedCompilers.TryGetValue(version, out var path))
return Path.Combine(path, compiler);
string outputPath = Path.Combine(nugetDir, version);
path = Path.Combine(outputPath, "tools");
if (!Directory.Exists(path))
{
FetchPackage(version, outputPath).GetAwaiter().GetResult();
}
installedCompilers.Add(version, path);
return Path.Combine(path, compiler);
}
this.baseDir = baseDir;
}
async Task FetchPackage(string version, string outputPath)
protected async Task FetchPackage(string packageName, string version, string outputPath)
{
ILogger logger = NullLogger.Instance;
CancellationToken cancellationToken = CancellationToken.None;
using MemoryStream packageStream = new MemoryStream();
await resource.CopyNupkgToStreamAsync(
"Microsoft.Net.Compilers",
packageName,
NuGetVersion.Parse(version),
packageStream,
cache,
@ -96,9 +63,9 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -96,9 +63,9 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
cancellationToken);
using PackageArchiveReader packageReader = new PackageArchiveReader(packageStream);
NuspecReader nuspecReader = await packageReader.GetNuspecReaderAsync(cancellationToken);
NuspecReader nuspecReader = await packageReader.GetNuspecReaderAsync(cancellationToken).ConfigureAwait(false);
var files = await packageReader.GetFilesAsync(cancellationToken);
var files = await packageReader.GetFilesAsync(cancellationToken).ConfigureAwait(false);
files = files.Where(f => f.StartsWith("tools", StringComparison.OrdinalIgnoreCase));
await packageReader.CopyFilesAsync(outputPath, files,
(sourceFile, targetPath, fileStream) => {
@ -108,4 +75,66 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -108,4 +75,66 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
logger, cancellationToken);
}
}
class RoslynToolset : AbstractToolset
{
readonly Dictionary<string, string> installedCompilers = new Dictionary<string, string> {
{ "legacy", Environment.ExpandEnvironmentVariables(@"%WINDIR%\Microsoft.NET\Framework\v4.0.30319") }
};
public RoslynToolset()
: base(Path.Combine(AppContext.BaseDirectory, "roslyn"))
{
}
public async Task Fetch(string version)
{
string path = Path.Combine(baseDir, version, "tools");
if (!Directory.Exists(path))
{
await FetchPackage("Microsoft.Net.Compilers", version, Path.Combine(baseDir, version));
}
installedCompilers.Add(version, path);
}
public string GetCSharpCompiler(string version)
{
return GetCompiler("csc.exe", version);
}
public string GetVBCompiler(string version)
{
return GetCompiler("vbc.exe", version);
}
string GetCompiler(string compiler, string version)
{
if (installedCompilers.TryGetValue(version, out var path))
return Path.Combine(path, compiler);
throw new NotSupportedException($"Cannot find {compiler} {version}, please add it to the initialization.");
}
}
class VsWhereToolset : AbstractToolset
{
string vswherePath;
public VsWhereToolset()
: base(Path.Combine(AppContext.BaseDirectory, "vswhere"))
{
}
public async Task Fetch()
{
string path = Path.Combine(baseDir, "tools");
if (!Directory.Exists(path))
{
await FetchPackage("vswhere", "2.8.4", baseDir);
}
vswherePath = Path.Combine(path, "vswhere.exe");
}
public string GetVsWhere() => vswherePath;
}
}

54
ICSharpCode.Decompiler.Tests/Helpers/Tester.VB.cs

@ -21,16 +21,19 @@ using System.Collections.Generic; @@ -21,16 +21,19 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using CliWrap;
using NUnit.Framework;
namespace ICSharpCode.Decompiler.Tests.Helpers
{
partial class Tester
{
public static CompilerResults CompileVB(string sourceFileName, CompilerOptions flags = CompilerOptions.UseDebug, string outputFileName = null)
public static async Task<CompilerResults> CompileVB(string sourceFileName, CompilerOptions flags = CompilerOptions.UseDebug, string outputFileName = null)
{
List<string> sourceFileNames = new List<string> { sourceFileName };
foreach (Match match in Regex.Matches(File.ReadAllText(sourceFileName), @"#include ""([\w\d./]+)"""))
@ -50,7 +53,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -50,7 +53,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
CompilerOptions.UseRoslyn1_3_2 => ("1.3.2", "14"),
CompilerOptions.UseRoslyn2_10_0 => ("2.10.0", "latest"),
CompilerOptions.UseRoslyn3_11_0 => ("3.11.0", "latest"),
_ => (RoslynLatestVersion, flags.HasFlag(CompilerOptions.Preview) ? "preview" : "latest")
_ => (roslynLatestVersion, flags.HasFlag(CompilerOptions.Preview) ? "preview" : "latest")
};
var vbcPath = roslynToolset.GetVBCompiler(roslynVersion);
@ -58,29 +61,15 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -58,29 +61,15 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
IEnumerable<string> references;
if ((flags & CompilerOptions.UseRoslynMask) != 0)
{
if (flags.HasFlag(CompilerOptions.ReferenceCore))
{
references = coreDefaultReferences.Value.Select(r => "-r:\"" + r + "\"");
}
else
{
references = roslynDefaultReferences.Value.Select(r => "-r:\"" + r + "\"");
}
references = coreDefaultReferences.Select(r => "-r:\"" + r + "\"");
}
else
{
references = defaultReferences.Value.Select(r => "-r:\"" + r + "\"");
references = defaultReferences.Select(r => "-r:\"" + r + "\"");
}
if (flags.HasFlag(CompilerOptions.ReferenceVisualBasic))
{
if ((flags & CompilerOptions.UseRoslynMask) != 0)
{
references = references.Concat(visualBasic.Value.Select(r => "-r:\"" + r + "\""));
}
else
{
references = references.Concat(new[] { "-r:\"Microsoft.VisualBasic.dll\"" });
}
references = references.Concat(new[] { "-r:\"Microsoft.VisualBasic.dll\"" });
}
string otherOptions = $"-noconfig " +
"-optioninfer+ -optionexplicit+ " +
@ -125,25 +114,22 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -125,25 +114,22 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
otherOptions += " \"-d:" + string.Join(",", preprocessorSymbols.Select(kv => kv.Key + "=" + kv.Value)) + "\" ";
}
ProcessStartInfo info = new ProcessStartInfo(vbcPath);
info.Arguments = $"{otherOptions}{string.Join(" ", references)} -out:\"{Path.GetFullPath(results.PathToAssembly)}\" {string.Join(" ", sourceFileNames.Select(fn => '"' + Path.GetFullPath(fn) + '"'))}";
info.RedirectStandardError = true;
info.RedirectStandardOutput = true;
info.UseShellExecute = false;
Console.WriteLine($"\"{info.FileName}\" {info.Arguments}");
StringBuilder stderr = new();
StringBuilder stdout = new();
Process process = Process.Start(info);
var command = Cli.Wrap(vbcPath)
.WithArguments($"{otherOptions}{string.Join(" ", references)} -out:\"{Path.GetFullPath(results.PathToAssembly)}\" {string.Join(" ", sourceFileNames.Select(fn => '"' + Path.GetFullPath(fn) + '"'))}")
.WithStandardErrorPipe(PipeTarget.ToStringBuilder(stderr))
.WithStandardOutputPipe(PipeTarget.ToStringBuilder(stdout))
.WithValidation(CommandResultValidation.None);
Console.WriteLine($"\"{command.TargetFilePath}\" {command.Arguments}");
var outputTask = process.StandardOutput.ReadToEndAsync();
var errorTask = process.StandardError.ReadToEndAsync();
var result = await command.ExecuteAsync().ConfigureAwait(false);
Task.WaitAll(outputTask, errorTask);
process.WaitForExit();
Console.WriteLine("output: " + stdout);
Console.WriteLine("errors: " + stderr);
Assert.AreEqual(0, result.ExitCode, "vbc failed");
Console.WriteLine("output: " + outputTask.Result);
Console.WriteLine("errors: " + errorTask.Result);
Assert.AreEqual(0, process.ExitCode, "vbc failed");
return results;
}
else

411
ICSharpCode.Decompiler.Tests/Helpers/Tester.cs

@ -17,7 +17,6 @@ @@ -17,7 +17,6 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
@ -30,6 +29,8 @@ using System.Threading.Tasks; @@ -30,6 +29,8 @@ using System.Threading.Tasks;
using System.Xml.Linq;
using System.Xml.XPath;
using CliWrap;
using ICSharpCode.Decompiler.CSharp;
using ICSharpCode.Decompiler.CSharp.OutputVisitor;
using ICSharpCode.Decompiler.CSharp.Transforms;
@ -57,13 +58,15 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -57,13 +58,15 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
UseRoslyn1_3_2 = 0x10,
UseMcs2_6_4 = 0x20,
ReferenceVisualBasic = 0x40,
ReferenceCore = 0x80,
//ReferenceCore = 0x80,
GeneratePdb = 0x100,
Preview = 0x200,
UseRoslyn2_10_0 = 0x400,
UseRoslyn3_11_0 = 0x800,
UseRoslynLatest = 0x1000,
UseMcs5_23 = 0x2000,
UseTestRunner = 0x4000,
NullableEnable = 0x8000,
UseMcsMask = UseMcs2_6_4 | UseMcs5_23,
UseRoslynMask = UseRoslyn1_3_2 | UseRoslyn2_10_0 | UseRoslyn3_11_0 | UseRoslynLatest
}
@ -83,18 +86,35 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -83,18 +86,35 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
public static partial class Tester
{
public static readonly string TestCasePath = Path.Combine(
Path.GetDirectoryName(typeof(Tester).Assembly.Location),
"../../../TestCases");
public static readonly string TesterPath;
public static readonly string TestCasePath;
static readonly string PackagesPropsFile = Path.Combine(
Path.GetDirectoryName(typeof(Tester).Assembly.Location),
"../../../../packages.props");
static readonly string packagesPropsFile;
static readonly string roslynLatestVersion;
static readonly RoslynToolset roslynToolset;
static readonly VsWhereToolset vswhereToolset;
static readonly string RoslynLatestVersion = XDocument.Load(PackagesPropsFile)
.XPathSelectElement("//RoslynVersion").Value;
static Tester()
{
TesterPath = Path.GetDirectoryName(typeof(Tester).Assembly.Location);
TestCasePath = Path.Combine(TesterPath, "../../../../TestCases");
packagesPropsFile = Path.Combine(TesterPath, "../../../../../packages.props");
roslynLatestVersion = XDocument.Load(packagesPropsFile).XPathSelectElement("//RoslynVersion").Value;
roslynToolset = new RoslynToolset();
vswhereToolset = new VsWhereToolset();
}
public static string AssembleIL(string sourceFileName, AssemblerOptions options = AssemblerOptions.UseDebug)
internal static async Task Initialize()
{
await roslynToolset.Fetch("1.3.2");
await roslynToolset.Fetch("2.10.0");
await roslynToolset.Fetch("3.11.0");
await roslynToolset.Fetch(roslynLatestVersion);
await vswhereToolset.Fetch();
}
public static async Task<string> AssembleIL(string sourceFileName, AssemblerOptions options = AssemblerOptions.UseDebug)
{
string ilasmPath;
if (options.HasFlag(AssemblerOptions.UseLegacyAssembler))
@ -131,28 +151,25 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -131,28 +151,25 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
otherOptions += "/debug ";
}
ProcessStartInfo info = new ProcessStartInfo(ilasmPath);
info.Arguments = $"/nologo {otherOptions}/output=\"{outputFile}\" \"{sourceFileName}\"";
info.RedirectStandardError = true;
info.RedirectStandardOutput = true;
info.UseShellExecute = false;
StringBuilder stderr = new();
StringBuilder stdout = new();
Process process = Process.Start(info);
var command = Cli.Wrap(ilasmPath)
.WithArguments($"/nologo {otherOptions}/output=\"{outputFile}\" \"{sourceFileName}\"")
.WithStandardErrorPipe(PipeTarget.ToStringBuilder(stderr))
.WithStandardOutputPipe(PipeTarget.ToStringBuilder(stdout))
.WithValidation(CommandResultValidation.None);
var outputTask = process.StandardOutput.ReadToEndAsync();
var errorTask = process.StandardError.ReadToEndAsync();
var result = await command.ExecuteAsync().ConfigureAwait(false);
Task.WaitAll(outputTask, errorTask);
process.WaitForExit();
Console.WriteLine("output: " + outputTask.Result);
Console.WriteLine("errors: " + errorTask.Result);
Assert.AreEqual(0, process.ExitCode, "ilasm failed");
Console.WriteLine("output: " + stdout);
Console.WriteLine("errors: " + stderr);
Assert.AreEqual(0, result.ExitCode, "ilasm failed");
return outputFile;
}
public static string Disassemble(string sourceFileName, string outputFile, AssemblerOptions asmOptions)
public static async Task<string> Disassemble(string sourceFileName, string outputFile, AssemblerOptions asmOptions)
{
if (asmOptions.HasFlag(AssemblerOptions.UseOwnDisassembler))
{
@ -180,22 +197,20 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -180,22 +197,20 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
string ildasmPath = SdkUtility.GetSdkPath("ildasm.exe");
ProcessStartInfo info = new ProcessStartInfo(ildasmPath);
info.Arguments = $"/nobar /utf8 /out=\"{outputFile}\" \"{sourceFileName}\"";
info.RedirectStandardError = true;
info.RedirectStandardOutput = true;
info.UseShellExecute = false;
Process process = Process.Start(info);
StringBuilder stderr = new();
StringBuilder stdout = new();
var outputTask = process.StandardOutput.ReadToEndAsync();
var errorTask = process.StandardError.ReadToEndAsync();
var command = Cli.Wrap(ildasmPath)
.WithArguments($"/nobar /utf8 /out=\"{outputFile}\" \"{sourceFileName}\"")
.WithStandardErrorPipe(PipeTarget.ToStringBuilder(stderr))
.WithStandardOutputPipe(PipeTarget.ToStringBuilder(stdout))
.WithValidation(CommandResultValidation.None);
Task.WaitAll(outputTask, errorTask);
process.WaitForExit();
var result = await command.ExecuteAsync().ConfigureAwait(false);
Console.WriteLine("output: " + outputTask.Result);
Console.WriteLine("errors: " + errorTask.Result);
Console.WriteLine("output: " + stdout);
Console.WriteLine("errors: " + stderr);
Assert.AreEqual(0, result.ExitCode, "ildasm failed");
// Unlike the .imagebase directive (which is a fixed value when compiling with /deterministic),
// the image base comment still varies... ildasm putting a random number here?
@ -220,8 +235,6 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -220,8 +235,6 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
return Regex.Replace(il, @"'<PrivateImplementationDetails>\{[0-9A-F-]+\}'", "'<PrivateImplementationDetails>'");
}
static readonly RoslynToolset roslynToolset = new RoslynToolset();
static readonly string coreRefAsmPath = new DotNetCorePathFinder(TargetFrameworkIdentifier.NET,
new Version(6, 0), "Microsoft.NETCore.App")
.GetReferenceAssemblyPath(".NETCoreApp,Version=v6.0");
@ -229,33 +242,35 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -229,33 +242,35 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
static readonly string refAsmPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86),
@"Reference Assemblies\Microsoft\Framework\.NETFramework\v4.7.2");
static readonly Lazy<IEnumerable<string>> defaultReferences = new Lazy<IEnumerable<string>>(delegate {
return new[]
static readonly string[] defaultReferences = new[] {
"System.dll",
"System.Core.dll",
"System.Xml.dll",
"Microsoft.CSharp.dll"
};
static readonly string[] coreDefaultReferences = new[]
{
"netstandard.dll",
"mscorlib.dll",
"System.dll",
"System.Collections.dll",
"System.Console.dll",
"System.Core.dll",
"System.Linq.dll",
"System.Linq.Expressions.dll",
"System.Linq.Queryable.dll",
"System.IO.FileSystem.Watcher.dll",
"System.Threading.dll",
"System.Threading.Thread.dll",
"System.Runtime.dll",
"System.Runtime.InteropServices.dll",
"System.Xml.dll",
"Microsoft.CSharp.dll"
};
});
static readonly Lazy<IEnumerable<string>> roslynDefaultReferences = new Lazy<IEnumerable<string>>(delegate {
return new[]
{
Path.Combine(refAsmPath, "Facades\\netstandard.dll"),
Path.Combine(refAsmPath, "mscorlib.dll"),
Path.Combine(refAsmPath, "System.dll"),
Path.Combine(refAsmPath, "System.Core.dll"),
Path.Combine(refAsmPath, @"Facades\System.Runtime.dll"),
Path.Combine(refAsmPath, "System.Xml.dll"),
Path.Combine(refAsmPath, "Microsoft.CSharp.dll"),
typeof(ValueTuple).Assembly.Location,
typeof(ValueTask).Assembly.Location,
typeof(Span<>).Assembly.Location,
"System.Xml.ReaderWriter.dll",
"System.ValueTuple.dll",
"Microsoft.CSharp.dll",
"Microsoft.VisualBasic.dll",
};
});
static readonly Lazy<IEnumerable<string>> coreDefaultReferences = new Lazy<IEnumerable<string>>(GetDefaultReferences);
const string targetFrameworkAttributeSnippet = @"
@ -272,20 +287,6 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -272,20 +287,6 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
return tempFile;
}
static IEnumerable<string> GetDefaultReferences()
{
foreach (var reference in Directory.EnumerateFiles(coreRefAsmPath, "*.dll"))
{
yield return reference;
}
}
static readonly Lazy<IEnumerable<string>> visualBasic = new Lazy<IEnumerable<string>>(delegate {
return new[] {
Path.Combine(refAsmPath, "Microsoft.VisualBasic.dll")
};
});
public static List<string> GetPreprocessorSymbols(CompilerOptions flags)
{
var preprocessorSymbols = new List<string>();
@ -297,12 +298,9 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -297,12 +298,9 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
{
preprocessorSymbols.Add("OPT");
}
if (flags.HasFlag(CompilerOptions.ReferenceCore))
{
preprocessorSymbols.Add("NETCORE");
}
if ((flags & CompilerOptions.UseRoslynMask) != 0)
{
preprocessorSymbols.Add("NETCORE");
preprocessorSymbols.Add("ROSLYN");
preprocessorSymbols.Add("CS60");
preprocessorSymbols.Add("VB11");
@ -356,14 +354,14 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -356,14 +354,14 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
return preprocessorSymbols;
}
public static CompilerResults CompileCSharp(string sourceFileName, CompilerOptions flags = CompilerOptions.UseDebug, string outputFileName = null)
public static async Task<CompilerResults> CompileCSharp(string sourceFileName, CompilerOptions flags = CompilerOptions.UseDebug, string outputFileName = null)
{
List<string> sourceFileNames = new List<string> { sourceFileName };
foreach (Match match in Regex.Matches(File.ReadAllText(sourceFileName), @"#include ""([\w\d./]+)"""))
{
sourceFileNames.Add(Path.GetFullPath(Path.Combine(Path.GetDirectoryName(sourceFileName), match.Groups[1].Value)));
}
if (flags.HasFlag(CompilerOptions.ReferenceCore))
if ((flags & CompilerOptions.UseRoslynMask) != 0)
{
sourceFileNames.Add(targetFrameworkAttributeSnippetFile.Value);
}
@ -380,37 +378,26 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -380,37 +378,26 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
CompilerOptions.UseRoslyn1_3_2 => ("1.3.2", "6"),
CompilerOptions.UseRoslyn2_10_0 => ("2.10.0", "latest"),
CompilerOptions.UseRoslyn3_11_0 => ("3.11.0", "latest"),
_ => (RoslynLatestVersion, flags.HasFlag(CompilerOptions.Preview) ? "preview" : "latest")
_ => (roslynLatestVersion, flags.HasFlag(CompilerOptions.Preview) ? "preview" : "latest")
};
var cscPath = roslynToolset.GetCSharpCompiler(roslynVersion);
string libPath;
IEnumerable<string> references;
if ((flags & CompilerOptions.UseRoslynMask) != 0)
{
if (flags.HasFlag(CompilerOptions.ReferenceCore))
{
references = coreDefaultReferences.Value.Select(r => "-r:\"" + r + "\"");
}
else
{
references = roslynDefaultReferences.Value.Select(r => "-r:\"" + r + "\"");
}
libPath = "\"" + coreRefAsmPath + "\"";
references = coreDefaultReferences.Select(r => "-r:\"" + Path.Combine(coreRefAsmPath, r) + "\"");
}
else
{
references = defaultReferences.Value.Select(r => "-r:\"" + r + "\"");
libPath = "\"" + refAsmPath + "\",\"" + Path.Combine(refAsmPath, "Facades") + "\"";
references = defaultReferences.Select(r => "-r:\"" + Path.Combine(refAsmPath, r) + "\"");
}
if (flags.HasFlag(CompilerOptions.ReferenceVisualBasic))
{
if ((flags & CompilerOptions.UseRoslynMask) != 0)
{
references = references.Concat(visualBasic.Value.Select(r => "-r:\"" + r + "\""));
}
else
{
references = references.Concat(new[] { "-r:\"Microsoft.VisualBasic.dll\"" });
}
references = references.Concat(new[] { "-r:\"Microsoft.VisualBasic.dll\"" });
}
string otherOptions = $"-noconfig " +
$"-langversion:{languageVersion} " +
@ -421,6 +408,13 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -421,6 +408,13 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
if (roslynVersion != "legacy")
{
otherOptions += "/shared ";
if (Version.Parse(roslynVersion).Major > 2)
{
if (flags.HasFlag(CompilerOptions.NullableEnable))
otherOptions += "/nullable+ ";
else
otherOptions += "/nullable- ";
}
}
if (flags.HasFlag(CompilerOptions.Library))
@ -454,25 +448,22 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -454,25 +448,22 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
otherOptions += " \"-d:" + string.Join(";", preprocessorSymbols) + "\" ";
}
ProcessStartInfo info = new ProcessStartInfo(cscPath);
info.Arguments = $"{otherOptions}{string.Join(" ", references)} -out:\"{Path.GetFullPath(results.PathToAssembly)}\" {string.Join(" ", sourceFileNames.Select(fn => '"' + Path.GetFullPath(fn) + '"'))}";
info.RedirectStandardError = true;
info.RedirectStandardOutput = true;
info.UseShellExecute = false;
Console.WriteLine($"\"{info.FileName}\" {info.Arguments}");
StringBuilder stderr = new();
StringBuilder stdout = new();
Process process = Process.Start(info);
var command = Cli.Wrap(cscPath)
.WithArguments($"{otherOptions} -lib:{libPath} {string.Join(" ", references)} -out:\"{Path.GetFullPath(results.PathToAssembly)}\" {string.Join(" ", sourceFileNames.Select(fn => '"' + Path.GetFullPath(fn) + '"'))}")
.WithStandardErrorPipe(PipeTarget.ToStringBuilder(stderr))
.WithStandardOutputPipe(PipeTarget.ToStringBuilder(stdout))
.WithValidation(CommandResultValidation.None);
Console.WriteLine($"\"{command.TargetFilePath}\" {command.Arguments}");
var outputTask = process.StandardOutput.ReadToEndAsync();
var errorTask = process.StandardError.ReadToEndAsync();
var result = await command.ExecuteAsync().ConfigureAwait(false);
Task.WaitAll(outputTask, errorTask);
process.WaitForExit();
Console.WriteLine("output: " + stdout);
Console.WriteLine("errors: " + stderr);
Assert.AreEqual(0, result.ExitCode, "csc failed");
Console.WriteLine("output: " + outputTask.Result);
Console.WriteLine("errors: " + errorTask.Result);
Assert.AreEqual(0, process.ExitCode, "csc failed");
return results;
}
else
@ -518,25 +509,22 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -518,25 +509,22 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
otherOptions += " \"-d:" + string.Join(";", preprocessorSymbols) + "\" ";
}
ProcessStartInfo info = new ProcessStartInfo(mcsPath);
info.Arguments = $"{otherOptions}-out:\"{Path.GetFullPath(results.PathToAssembly)}\" {string.Join(" ", sourceFileNames.Select(fn => '"' + Path.GetFullPath(fn) + '"'))}";
info.RedirectStandardError = true;
info.RedirectStandardOutput = true;
info.UseShellExecute = false;
StringBuilder stderr = new();
StringBuilder stdout = new();
Console.WriteLine($"\"{info.FileName}\" {info.Arguments}");
var command = Cli.Wrap(mcsPath)
.WithArguments($"{otherOptions}-out:\"{Path.GetFullPath(results.PathToAssembly)}\" {string.Join(" ", sourceFileNames.Select(fn => '"' + Path.GetFullPath(fn) + '"'))}")
.WithStandardErrorPipe(PipeTarget.ToStringBuilder(stderr))
.WithStandardOutputPipe(PipeTarget.ToStringBuilder(stdout))
.WithValidation(CommandResultValidation.None);
Console.WriteLine($"\"{command.TargetFilePath}\" {command.Arguments}");
Process process = Process.Start(info);
var result = await command.ExecuteAsync().ConfigureAwait(false);
var outputTask = process.StandardOutput.ReadToEndAsync();
var errorTask = process.StandardError.ReadToEndAsync();
Console.WriteLine("output: " + stdout);
Console.WriteLine("errors: " + stderr);
Assert.AreEqual(0, result.ExitCode, "mcs failed");
Task.WaitAll(outputTask, errorTask);
process.WaitForExit();
Console.WriteLine("output: " + outputTask.Result);
Console.WriteLine("errors: " + errorTask.Result);
Assert.AreEqual(0, process.ExitCode, "mcs failed");
return results;
}
}
@ -551,10 +539,15 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -551,10 +539,15 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
CompilerOptions.UseRoslyn3_11_0 => CSharp.LanguageVersion.CSharp9_0,
_ => cscOptions.HasFlag(CompilerOptions.Preview) ? CSharp.LanguageVersion.Latest : CSharp.LanguageVersion.CSharp10_0,
};
return new DecompilerSettings(langVersion) {
DecompilerSettings settings = new(langVersion) {
// Never use file-scoped namespaces
FileScopedNamespaces = false
};
if (!cscOptions.HasFlag(CompilerOptions.NullableEnable))
{
settings.NullableReferenceTypes = false;
}
return settings;
}
else
{
@ -583,7 +576,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -583,7 +576,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
}
var compilation = CSharpCompilation.Create(Path.GetFileNameWithoutExtension(assemblyName),
syntaxTrees, roslynDefaultReferences.Value.Select(r => MetadataReference.CreateFromFile(r)),
syntaxTrees, coreDefaultReferences.Select(r => MetadataReference.CreateFromFile(Path.Combine(coreRefAsmPath, r))),
new CSharpCompilationOptions(
OutputKind.DynamicallyLinkedLibrary,
platform: Platform.AnyCpu,
@ -631,37 +624,101 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -631,37 +624,101 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
return suffix;
}
public static int Run(string assemblyFileName, out string output, out string error)
public static async Task<(int ExitCode, string Output, string Error)> Run(string assemblyFileName)
{
ProcessStartInfo info = new ProcessStartInfo(assemblyFileName);
info.RedirectStandardError = true;
info.RedirectStandardOutput = true;
info.UseShellExecute = false;
StringBuilder stderr = new();
StringBuilder stdout = new();
var command = Cli.Wrap(assemblyFileName)
.WithStandardErrorPipe(PipeTarget.ToStringBuilder(stderr))
.WithStandardOutputPipe(PipeTarget.ToStringBuilder(stdout))
.WithValidation(CommandResultValidation.None);
var result = await command.ExecuteAsync().ConfigureAwait(false);
Process process = Process.Start(info);
return (result.ExitCode, stdout.ToString(), stderr.ToString());
}
var outputTask = process.StandardOutput.ReadToEndAsync();
var errorTask = process.StandardError.ReadToEndAsync();
public static async Task<(int ExitCode, string Output, string Error)> RunWithTestRunner(string assemblyFileName, bool force32Bit)
{
StringBuilder stderr = new();
StringBuilder stdout = new();
Task.WaitAll(outputTask, errorTask);
process.WaitForExit();
string pathToRunner = force32Bit
? Path.Combine(TesterPath, "ICSharpCode.Decompiler.TestRunner32.exe")
: Path.Combine(TesterPath, "ICSharpCode.Decompiler.TestRunner.exe");
var command = Cli.Wrap(pathToRunner)
.WithArguments(assemblyFileName)
.WithStandardErrorPipe(PipeTarget.ToStringBuilder(stderr))
.WithStandardOutputPipe(PipeTarget.ToStringBuilder(stdout))
.WithValidation(CommandResultValidation.None);
output = outputTask.Result;
error = errorTask.Result;
var result = await command.ExecuteAsync().ConfigureAwait(false);
return process.ExitCode;
return (result.ExitCode, stdout.ToString(), stderr.ToString());
}
/*
public static int RunInContainer(string assemblyFileName, out string output, out string error)
{
AssemblyLoadContext context = new("RunInContainer", isCollectible: true);
context.Resolving += ContextResolving;
var (oldOut, newOut) = WrapOut();
var (oldError, newError) = WrapError();
int result;
try
{
var mainAssembly = context.LoadFromAssemblyPath(assemblyFileName);
var tmp = mainAssembly.EntryPoint!.Invoke(null, Array.Empty<object>());
result = tmp is int i ? i : 0;
}
finally
{
context.Unload();
context.Resolving -= ContextResolving;
Console.SetOut(oldOut);
Console.SetError(oldError);
}
output = newOut.ToString();
error = newError.ToString();
return result;
public static string DecompileCSharp(string assemblyFileName, DecompilerSettings settings = null)
static Assembly ContextResolving(AssemblyLoadContext context, AssemblyName name)
{
return null;
}
static (TextWriter oldWriter, StringBuilder newOutput) WrapOut()
{
var oldWriter = Console.Out;
var newOutput = new StringBuilder();
Console.SetOut(new StringWriter(newOutput));
return (oldWriter, newOutput);
}
static (TextWriter oldWriter, StringBuilder newOutput) WrapError()
{
var oldWriter = Console.Error;
var newOutput = new StringBuilder();
Console.SetError(new StringWriter(newOutput));
return (oldWriter, newOutput);
}
}
*/
public static Task<string> DecompileCSharp(string assemblyFileName, DecompilerSettings settings = null)
{
if (settings == null)
settings = new DecompilerSettings();
using (var file = new FileStream(assemblyFileName, FileMode.Open, FileAccess.Read))
{
var module = new PEFile(assemblyFileName, file, PEStreamOptions.PrefetchEntireImage);
string targetFramework = module.Reader.DetectTargetFrameworkId();
var resolver = new UniversalAssemblyResolver(assemblyFileName, false,
module.Reader.DetectTargetFrameworkId(), null, PEStreamOptions.PrefetchMetadata);
resolver.AddSearchDirectory(Path.GetDirectoryName(typeof(Span<>).Assembly.Location));
targetFramework, null, PEStreamOptions.PrefetchMetadata);
resolver.AddSearchDirectory(targetFramework.Contains(".NETFramework") ? refAsmPath : coreRefAsmPath);
var typeSystem = new DecompilerTypeSystem(module, resolver, settings);
CSharpDecompiler decompiler = new CSharpDecompiler(typeSystem, settings);
decompiler.AstTransforms.Insert(0, new RemoveEmbeddedAttributes());
@ -681,7 +738,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -681,7 +738,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
string fileName = Path.GetTempFileName();
File.WriteAllText(fileName, output.ToString());
return fileName;
return Task.FromResult(fileName);
}
}
@ -696,11 +753,21 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -696,11 +753,21 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
return formattingPolicy;
}
public static void RunAndCompareOutput(string testFileName, string outputFile, string decompiledOutputFile, string decompiledCodeFile = null)
public static async Task RunAndCompareOutput(string testFileName, string outputFile, string decompiledOutputFile, string decompiledCodeFile = null, bool useTestRunner = false, bool force32Bit = false)
{
string output1, output2, error1, error2;
int result1 = Tester.Run(outputFile, out output1, out error1);
int result2 = Tester.Run(decompiledOutputFile, out output2, out error2);
int result1, result2;
if (useTestRunner)
{
(result1, output1, error1) = await RunWithTestRunner(outputFile, force32Bit).ConfigureAwait(false);
(result2, output2, error2) = await RunWithTestRunner(decompiledOutputFile, force32Bit).ConfigureAwait(false);
}
else
{
(result1, output1, error1) = await Run(outputFile).ConfigureAwait(false);
(result2, output2, error2) = await Run(decompiledOutputFile).ConfigureAwait(false);
}
Assert.AreEqual(0, result1, "Exit code != 0; did the test case crash?" + Environment.NewLine + error1);
Assert.AreEqual(0, result2, "Exit code != 0; did the decompiled code crash?" + Environment.NewLine + error2);
@ -780,26 +847,38 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -780,26 +847,38 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
action();
}
public static void SignAssembly(string assemblyPath, string keyFilePath)
public static async Task SignAssembly(string assemblyPath, string keyFilePath)
{
string snPath = SdkUtility.GetSdkPath("sn.exe");
ProcessStartInfo info = new ProcessStartInfo(snPath);
info.Arguments = $"-R \"{assemblyPath}\" \"{keyFilePath}\"";
info.RedirectStandardError = true;
info.RedirectStandardOutput = true;
info.UseShellExecute = false;
StringBuilder stderr = new();
StringBuilder stdout = new();
Process process = Process.Start(info);
var command = Cli.Wrap(snPath)
.WithArguments($"-R \"{assemblyPath}\" \"{keyFilePath}\"")
.WithStandardErrorPipe(PipeTarget.ToStringBuilder(stderr))
.WithStandardOutputPipe(PipeTarget.ToStringBuilder(stdout))
.WithValidation(CommandResultValidation.None);
var outputTask = process.StandardOutput.ReadToEndAsync();
var errorTask = process.StandardError.ReadToEndAsync();
var result = await command.ExecuteAsync().ConfigureAwait(false);
Assert.AreEqual(0, result.ExitCode, "sn failed");
Task.WaitAll(outputTask, errorTask);
process.WaitForExit();
Console.WriteLine("output: " + stdout);
Console.WriteLine("errors: " + stderr);
}
Console.WriteLine("output: " + outputTask.Result);
Console.WriteLine("errors: " + errorTask.Result);
public static async Task<string> FindMSBuild()
{
string path = vswhereToolset.GetVsWhere();
StringBuilder stdout = new();
var result = await Cli.Wrap(path)
.WithArguments(@"-latest -requires Microsoft.Component.MSBuild -find MSBuild\**\Bin\MSBuild.exe")
.WithStandardOutputPipe(PipeTarget.ToStringBuilder(stdout))
.WithValidation(CommandResultValidation.None)
.ExecuteAsync().ConfigureAwait(false);
if (result.ExitCode != 0)
throw new InvalidOperationException("Could not find MSBuild");
return stdout.ToString().TrimEnd();
}
}

4
ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj

@ -42,7 +42,7 @@ @@ -42,7 +42,7 @@
<ItemGroup>
<PackageReference Include="DiffLib" Version="$(DiffLibVersion)" />
<PackageReference Include="Microsoft.Build.Locator" Version="1.4.1" />
<PackageReference Include="CliWrap" Version="3.4.1" />
<PackageReference Include="NuGet.Protocol" Version="6.0.0" />
<PackageReference Include="System.Collections.Immutable" Version="$(SystemCollectionsImmutableVersion)" />
<PackageReference Include="System.Reflection.Metadata" Version="$(SystemReflectionMetadataVersion)" />
@ -224,7 +224,7 @@ @@ -224,7 +224,7 @@
<Compile Include="TestCases\Correctness\NullPropagation.cs" />
<Compile Include="TestCases\ILPretty\Issue982.cs" />
<Compile Include="TestCases\Pretty\CS72_PrivateProtected.cs" />
<Compile Include="TestCases\Pretty\CS6_StringInterpolation.cs" />
<Compile Include="TestCases\Pretty\StringInterpolation.cs" />
<Compile Include="TestCases\Pretty\ExpressionTrees.cs" />
<Compile Include="TestCases\Pretty\NullPropagation.cs" />
<Compile Include="TestCases\Pretty\VariableNaming.cs" />

143
ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs

@ -20,6 +20,7 @@ using System; @@ -20,6 +20,7 @@ using System;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using ICSharpCode.Decompiler.Tests.Helpers;
@ -51,212 +52,212 @@ namespace ICSharpCode.Decompiler.Tests @@ -51,212 +52,212 @@ namespace ICSharpCode.Decompiler.Tests
}
[Test, Ignore("Need to decide how to represent virtual methods without 'newslot' flag")]
public void Issue379()
public async Task Issue379()
{
Run();
await Run();
}
[Test]
public void Issue646()
public async Task Issue646()
{
Run();
await Run();
}
[Test]
public void Issue684()
public async Task Issue684()
{
Run();
await Run();
}
[Test]
public void Issue959()
public async Task Issue959()
{
Run();
await Run();
}
[Test]
public void Issue982()
public async Task Issue982()
{
Run();
await Run();
}
[Test]
public void Issue1038()
public async Task Issue1038()
{
Run();
await Run();
}
[Test]
public void Issue1047()
public async Task Issue1047()
{
Run();
await Run();
}
[Test]
public void Issue1389()
public async Task Issue1389()
{
Run();
await Run();
}
[Test]
public void Issue1918()
public async Task Issue1918()
{
Run();
await Run();
}
[Test]
public void Issue1922()
public async Task Issue1922()
{
Run();
await Run();
}
[Test]
public void FSharpUsing_Debug()
public async Task FSharpUsing_Debug()
{
Run(settings: new DecompilerSettings { RemoveDeadStores = true, UseEnhancedUsing = false, FileScopedNamespaces = false });
await Run(settings: new DecompilerSettings { RemoveDeadStores = true, UseEnhancedUsing = false, FileScopedNamespaces = false });
}
[Test]
public void FSharpUsing_Release()
public async Task FSharpUsing_Release()
{
Run(settings: new DecompilerSettings { RemoveDeadStores = true, UseEnhancedUsing = false, FileScopedNamespaces = false });
await Run(settings: new DecompilerSettings { RemoveDeadStores = true, UseEnhancedUsing = false, FileScopedNamespaces = false });
}
[Test]
public void DirectCallToExplicitInterfaceImpl()
public async Task DirectCallToExplicitInterfaceImpl()
{
Run();
await Run();
}
[Test]
public void EvalOrder()
public async Task EvalOrder()
{
Run();
await Run();
}
[Test]
public void CS1xSwitch_Debug()
public async Task CS1xSwitch_Debug()
{
Run(settings: new DecompilerSettings { SwitchExpressions = false, FileScopedNamespaces = false });
await Run(settings: new DecompilerSettings { SwitchExpressions = false, FileScopedNamespaces = false });
}
[Test]
public void CS1xSwitch_Release()
public async Task CS1xSwitch_Release()
{
Run(settings: new DecompilerSettings { SwitchExpressions = false, FileScopedNamespaces = false });
await Run(settings: new DecompilerSettings { SwitchExpressions = false, FileScopedNamespaces = false });
}
[Test]
public void UnknownTypes()
public async Task UnknownTypes()
{
Run();
await Run();
}
[Test]
public void Issue1145()
public async Task Issue1145()
{
Run();
await Run();
}
[Test]
public void Issue1157()
public async Task Issue1157()
{
Run();
await Run();
}
[Test]
public void Issue1256()
public async Task Issue1256()
{
Run();
await Run();
}
[Test]
public void Issue1323()
public async Task Issue1323()
{
Run();
await Run();
}
[Test]
public void Issue1325()
public async Task Issue1325()
{
Run();
await Run();
}
[Test]
public void Issue1681()
public async Task Issue1681()
{
Run();
await Run();
}
[Test]
public void Issue1454()
public async Task Issue1454()
{
Run();
await Run();
}
[Test]
public void Issue2104()
public async Task Issue2104()
{
Run();
await Run();
}
[Test]
public void Issue2443()
public async Task Issue2443()
{
Run();
await Run();
}
[Test]
public void Issue2260SwitchString()
public async Task Issue2260SwitchString()
{
Run();
await Run();
}
[Test]
public void ConstantBlobs()
public async Task ConstantBlobs()
{
Run();
await Run();
}
[Test]
public void SequenceOfNestedIfs()
public async Task SequenceOfNestedIfs()
{
Run();
await Run();
}
[Test]
public void Unsafe()
public async Task Unsafe()
{
Run(assemblerOptions: AssemblerOptions.Library | AssemblerOptions.UseLegacyAssembler);
await Run(assemblerOptions: AssemblerOptions.Library | AssemblerOptions.UseLegacyAssembler);
}
[Test]
public void CallIndirect()
public async Task CallIndirect()
{
Run();
await Run();
}
[Test]
public void FSharpLoops_Debug()
public async Task FSharpLoops_Debug()
{
CopyFSharpCoreDll();
Run(settings: new DecompilerSettings { RemoveDeadStores = true, FileScopedNamespaces = false });
await Run(settings: new DecompilerSettings { RemoveDeadStores = true, FileScopedNamespaces = false });
}
[Test]
public void FSharpLoops_Release()
public async Task FSharpLoops_Release()
{
CopyFSharpCoreDll();
Run(settings: new DecompilerSettings { RemoveDeadStores = true, FileScopedNamespaces = false });
await Run(settings: new DecompilerSettings { RemoveDeadStores = true, FileScopedNamespaces = false });
}
[Test]
public void WeirdEnums()
public async Task WeirdEnums()
{
Run();
await Run();
}
void Run([CallerMemberName] string testName = null, DecompilerSettings settings = null,
async Task Run([CallerMemberName] string testName = null, DecompilerSettings settings = null,
AssemblerOptions assemblerOptions = AssemblerOptions.Library)
{
if (settings == null)
@ -267,8 +268,8 @@ namespace ICSharpCode.Decompiler.Tests @@ -267,8 +268,8 @@ namespace ICSharpCode.Decompiler.Tests
var ilFile = Path.Combine(TestCasePath, testName + ".il");
var csFile = Path.Combine(TestCasePath, testName + ".cs");
var executable = Tester.AssembleIL(ilFile, assemblerOptions);
var decompiled = Tester.DecompileCSharp(executable, settings);
var executable = await Tester.AssembleIL(ilFile, assemblerOptions).ConfigureAwait(false);
var decompiled = await Tester.DecompileCSharp(executable, settings).ConfigureAwait(false);
CodeAssert.FilesAreEqual(csFile, decompiled);
}

345
ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs

@ -21,6 +21,7 @@ using System.CodeDom.Compiler; @@ -21,6 +21,7 @@ using System.CodeDom.Compiler;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using ICSharpCode.Decompiler.Tests.Helpers;
@ -93,14 +94,6 @@ namespace ICSharpCode.Decompiler.Tests @@ -93,14 +94,6 @@ namespace ICSharpCode.Decompiler.Tests
CompilerOptions.Optimize | CompilerOptions.UseRoslynLatest,
};
static readonly CompilerOptions[] dotnetCoreOnlyOptions =
{
CompilerOptions.UseRoslyn3_11_0 | CompilerOptions.ReferenceCore,
CompilerOptions.Optimize | CompilerOptions.UseRoslyn3_11_0 | CompilerOptions.ReferenceCore,
CompilerOptions.UseRoslynLatest | CompilerOptions.ReferenceCore,
CompilerOptions.Optimize | CompilerOptions.UseRoslynLatest | CompilerOptions.ReferenceCore,
};
static readonly CompilerOptions[] defaultOptions =
{
CompilerOptions.None,
@ -134,50 +127,50 @@ namespace ICSharpCode.Decompiler.Tests @@ -134,50 +127,50 @@ namespace ICSharpCode.Decompiler.Tests
};
[Test]
public void HelloWorld()
public async Task HelloWorld()
{
RunForLibrary();
RunForLibrary(asmOptions: AssemblerOptions.UseDebug);
await RunForLibrary();
await RunForLibrary(asmOptions: AssemblerOptions.UseDebug);
}
[Test]
public void IndexRangeTest([ValueSource(nameof(dotnetCoreOnlyOptions))] CompilerOptions cscOptions)
public async Task IndexRangeTest([ValueSource(nameof(roslyn3OrNewerOptions))] CompilerOptions cscOptions)
{
if (cscOptions.HasFlag(CompilerOptions.UseRoslynLatest))
{
Assert.Ignore("See https://github.com/icsharpcode/ILSpy/issues/2540");
}
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void InlineAssignmentTest([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
public async Task InlineAssignmentTest([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void CompoundAssignmentTest([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
public async Task CompoundAssignmentTest([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void ShortCircuit([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
public async Task ShortCircuit([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void CustomShortCircuitOperators([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
public async Task CustomShortCircuitOperators([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void ExceptionHandling([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
public async Task ExceptionHandling([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions, decompilerSettings: new DecompilerSettings {
await RunForLibrary(cscOptions: cscOptions, decompilerSettings: new DecompilerSettings {
NullPropagation = false,
// legacy csc generates a dead store in debug builds
RemoveDeadStores = (cscOptions == CompilerOptions.None),
@ -186,9 +179,9 @@ namespace ICSharpCode.Decompiler.Tests @@ -186,9 +179,9 @@ namespace ICSharpCode.Decompiler.Tests
}
[Test]
public void Switch([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
public async Task Switch([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions, decompilerSettings: new DecompilerSettings {
await RunForLibrary(cscOptions: cscOptions, decompilerSettings: new DecompilerSettings {
// legacy csc generates a dead store in debug builds
RemoveDeadStores = (cscOptions == CompilerOptions.None),
SwitchExpressions = false,
@ -197,45 +190,45 @@ namespace ICSharpCode.Decompiler.Tests @@ -197,45 +190,45 @@ namespace ICSharpCode.Decompiler.Tests
}
[Test]
public void SwitchExpressions([ValueSource(nameof(roslynLatestOnlyOptions))] CompilerOptions cscOptions)
public async Task SwitchExpressions([ValueSource(nameof(roslynLatestOnlyOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void ReduceNesting([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
public async Task ReduceNesting([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void DelegateConstruction([ValueSource(nameof(defaultOptionsWithMcs))] CompilerOptions cscOptions)
public async Task DelegateConstruction([ValueSource(nameof(defaultOptionsWithMcs))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview);
await RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview);
}
[Test]
public void AnonymousTypes([ValueSource(nameof(defaultOptionsWithMcs))] CompilerOptions cscOptions)
public async Task AnonymousTypes([ValueSource(nameof(defaultOptionsWithMcs))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void Async([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
public async Task Async([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void Lock([ValueSource(nameof(defaultOptionsWithMcs))] CompilerOptions cscOptions)
public async Task Lock([ValueSource(nameof(defaultOptionsWithMcs))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void Using([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
public async Task Using([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
RunForLibrary(
await RunForLibrary(
cscOptions: cscOptions,
decompilerSettings: new DecompilerSettings {
UseEnhancedUsing = false,
@ -245,27 +238,27 @@ namespace ICSharpCode.Decompiler.Tests @@ -245,27 +238,27 @@ namespace ICSharpCode.Decompiler.Tests
}
[Test]
public void UsingVariables([ValueSource(nameof(dotnetCoreOnlyOptions))] CompilerOptions cscOptions)
public async Task UsingVariables([ValueSource(nameof(roslyn3OrNewerOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void LiftedOperators([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
public async Task LiftedOperators([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void Generics([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
public async Task Generics([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void Loops([ValueSource(nameof(defaultOptionsWithMcs))] CompilerOptions cscOptions)
public async Task Loops([ValueSource(nameof(defaultOptionsWithMcs))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions, decompilerSettings: new DecompilerSettings {
await RunForLibrary(cscOptions: cscOptions, decompilerSettings: new DecompilerSettings {
// legacy csc generates a dead store in debug builds
RemoveDeadStores = (cscOptions == CompilerOptions.None),
UseExpressionBodyForCalculatedGetterOnlyProperties = false,
@ -274,371 +267,383 @@ namespace ICSharpCode.Decompiler.Tests @@ -274,371 +267,383 @@ namespace ICSharpCode.Decompiler.Tests
}
[Test]
public void LocalFunctions([ValueSource(nameof(roslyn2OrNewerOptions))] CompilerOptions cscOptions)
public async Task LocalFunctions([ValueSource(nameof(roslyn2OrNewerOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview);
await RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview);
}
[Test]
public void PropertiesAndEvents([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
public async Task PropertiesAndEvents([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions | CompilerOptions.NullableEnable);
}
[Test]
public void AutoProperties([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions cscOptions)
public async Task AutoProperties([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void QueryExpressions([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
public async Task QueryExpressions([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void TypeAnalysisTests([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
public async Task TypeAnalysisTests([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void CheckedUnchecked([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
public async Task CheckedUnchecked([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void UnsafeCode([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
public async Task UnsafeCode([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void ConstructorInitializers([ValueSource(nameof(defaultOptionsWithMcs))] CompilerOptions cscOptions)
public async Task ConstructorInitializers([ValueSource(nameof(defaultOptionsWithMcs))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void PInvoke([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
public async Task PInvoke([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
// This tests needs our own disassembler; ildasm has a bug with marshalinfo.
RunForLibrary(cscOptions: cscOptions, asmOptions: AssemblerOptions.UseOwnDisassembler);
await RunForLibrary(cscOptions: cscOptions, asmOptions: AssemblerOptions.UseOwnDisassembler);
}
[Test]
public void OutVariables([ValueSource(nameof(roslyn2OrNewerOptions))] CompilerOptions cscOptions)
public async Task OutVariables([ValueSource(nameof(roslyn2OrNewerOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void PatternMatching([ValueSource(nameof(roslyn2OrNewerOptions))] CompilerOptions cscOptions)
public async Task PatternMatching([ValueSource(nameof(roslyn2OrNewerOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void InitializerTests([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
public async Task InitializerTests([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions | CompilerOptions.NullableEnable);
}
[Test]
public void DynamicTests([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
public async Task DynamicTests([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void ExpressionTrees([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
public async Task ExpressionTrees([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void FixProxyCalls([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
public async Task FixProxyCalls([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void ValueTypes([ValueSource(nameof(defaultOptionsWithMcs))] CompilerOptions cscOptions)
public async Task ValueTypes([ValueSource(nameof(defaultOptionsWithMcs))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void VariableNaming([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
public async Task VariableNaming([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions | CompilerOptions.GeneratePdb);
await RunForLibrary(cscOptions: cscOptions | CompilerOptions.GeneratePdb);
}
[Test]
public void VariableNamingWithoutSymbols([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
public async Task VariableNamingWithoutSymbols([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
var settings = Tester.GetSettings(cscOptions);
settings.UseDebugSymbols = false;
RunForLibrary(cscOptions: cscOptions, decompilerSettings: settings);
await RunForLibrary(cscOptions: cscOptions, decompilerSettings: settings);
}
[Test]
public void CS72_PrivateProtected([ValueSource(nameof(roslyn2OrNewerOptions))] CompilerOptions cscOptions)
public async Task CS72_PrivateProtected([ValueSource(nameof(roslyn2OrNewerOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void AsyncForeach([ValueSource(nameof(dotnetCoreOnlyOptions))] CompilerOptions cscOptions)
public async Task AsyncForeach([ValueSource(nameof(roslyn3OrNewerOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void AsyncMain([ValueSource(nameof(roslyn2OrNewerOptions))] CompilerOptions cscOptions)
public async Task AsyncMain([ValueSource(nameof(roslyn2OrNewerOptions))] CompilerOptions cscOptions)
{
Run(cscOptions: cscOptions);
await Run(cscOptions: cscOptions);
}
[Test]
public void AsyncStreams([ValueSource(nameof(dotnetCoreOnlyOptions))] CompilerOptions cscOptions)
public async Task AsyncStreams([ValueSource(nameof(roslyn3OrNewerOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void AsyncUsing([ValueSource(nameof(dotnetCoreOnlyOptions))] CompilerOptions cscOptions)
public async Task AsyncUsing([ValueSource(nameof(roslyn3OrNewerOptions))] CompilerOptions cscOptions)
{
RunForLibrary(
await RunForLibrary(
cscOptions: cscOptions,
decompilerSettings: new DecompilerSettings { UseEnhancedUsing = false, FileScopedNamespaces = false }
);
}
[Test]
public void CustomTaskType([ValueSource(nameof(roslyn2OrNewerOptions))] CompilerOptions cscOptions)
public async Task CustomTaskType([ValueSource(nameof(roslyn2OrNewerOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void NullableRefTypes([ValueSource(nameof(roslynLatestOnlyOptions))] CompilerOptions cscOptions)
public async Task NullableRefTypes([ValueSource(nameof(roslyn3OrNewerOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions | CompilerOptions.NullableEnable);
}
[Test]
public void NativeInts([ValueSource(nameof(roslynLatestOnlyOptions))] CompilerOptions cscOptions)
public async Task NativeInts([ValueSource(nameof(roslynLatestOnlyOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview);
await RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview);
}
[Test]
public void FileScopedNamespaces([ValueSource(nameof(roslynLatestOnlyOptions))] CompilerOptions cscOptions)
public async Task FileScopedNamespaces([ValueSource(nameof(roslynLatestOnlyOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions, decompilerSettings: new DecompilerSettings());
await RunForLibrary(cscOptions: cscOptions, decompilerSettings: new DecompilerSettings());
}
[Test]
public void Structs([ValueSource(nameof(defaultOptionsWithMcs))] CompilerOptions cscOptions)
public async Task Structs([ValueSource(nameof(defaultOptionsWithMcs))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void FunctionPointers([ValueSource(nameof(roslynLatestOnlyOptions))] CompilerOptions cscOptions)
public async Task FunctionPointers([ValueSource(nameof(roslynLatestOnlyOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview);
await RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview);
}
[Test]
public void Records([ValueSource(nameof(roslynLatestOnlyOptions))] CompilerOptions cscOptions)
public async Task Records([ValueSource(nameof(roslynLatestOnlyOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview);
await RunForLibrary(cscOptions: cscOptions | CompilerOptions.NullableEnable);
}
[Test]
public void NullPropagation([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions cscOptions)
public async Task NullPropagation([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void CS6_StringInterpolation([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions cscOptions)
public async Task StringInterpolation([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions cscOptions)
{
Run(cscOptions: cscOptions);
if (cscOptions.HasFlag(CompilerOptions.UseRoslynLatest))
{
Assert.Ignore("DefaultInterpolatedStringHandler is not yet supported!");
return;
}
await Run(cscOptions: cscOptions);
}
[Test]
public void CS73_StackAllocInitializers([ValueSource(nameof(roslyn3OrNewerOptions))] CompilerOptions cscOptions)
public async Task CS73_StackAllocInitializers([ValueSource(nameof(roslyn3OrNewerOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void RefLocalsAndReturns([ValueSource(nameof(roslyn2OrNewerOptions))] CompilerOptions cscOptions)
public async Task RefLocalsAndReturns([ValueSource(nameof(roslyn2OrNewerOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void ThrowExpressions([ValueSource(nameof(roslyn2OrNewerOptions))] CompilerOptions cscOptions)
public async Task ThrowExpressions([ValueSource(nameof(roslyn2OrNewerOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void WellKnownConstants([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
public async Task WellKnownConstants([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void QualifierTests([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
public async Task QualifierTests([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void TupleTests([ValueSource(nameof(roslyn2OrNewerOptions))] CompilerOptions cscOptions)
public async Task TupleTests([ValueSource(nameof(roslyn2OrNewerOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
if (cscOptions.HasFlag(CompilerOptions.UseRoslynLatest))
{
Assert.Ignore("DefaultInterpolatedStringHandler is not yet supported!");
return;
}
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void NamedArguments([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
public async Task NamedArguments([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void OptionalArguments([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
public async Task OptionalArguments([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview);
await RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview);
}
[Test]
public void ConstantsTests([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
public async Task ConstantsTests([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void Issue1080([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions cscOptions)
public async Task Issue1080([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions, decompilerSettings: new DecompilerSettings(CSharp.LanguageVersion.CSharp6));
await RunForLibrary(cscOptions: cscOptions, decompilerSettings: new DecompilerSettings(CSharp.LanguageVersion.CSharp6));
}
[Test]
public void AssemblyCustomAttributes([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
public async Task AssemblyCustomAttributes([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void CustomAttributes([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
public async Task CustomAttributes([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void CustomAttributes2([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
public async Task CustomAttributes2([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void CustomAttributeConflicts([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
public async Task CustomAttributeConflicts([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void CustomAttributeSamples([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
public async Task CustomAttributeSamples([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void MemberTests([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
public async Task MemberTests([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void MultidimensionalArray([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
public async Task MultidimensionalArray([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void EnumTests([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
public async Task EnumTests([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void InterfaceTests([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
public async Task InterfaceTests([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions | CompilerOptions.ReferenceCore);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void TypeMemberTests([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
public async Task TypeMemberTests([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void YieldReturn([ValueSource(nameof(defaultOptionsWithMcs))] CompilerOptions cscOptions)
public async Task YieldReturn([ValueSource(nameof(defaultOptionsWithMcs))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void UserDefinedConversions([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
public async Task UserDefinedConversions([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void Discards([ValueSource(nameof(roslyn2OrNewerOptions))] CompilerOptions cscOptions)
public async Task Discards([ValueSource(nameof(roslyn2OrNewerOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void DeconstructionTests([ValueSource(nameof(roslyn2OrNewerOptions))] CompilerOptions cscOptions)
public async Task DeconstructionTests([ValueSource(nameof(roslyn2OrNewerOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
await RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void CS9_ExtensionGetEnumerator([ValueSource(nameof(dotnetCoreOnlyOptions))] CompilerOptions cscOptions)
public async Task CS9_ExtensionGetEnumerator([ValueSource(nameof(roslyn3OrNewerOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview);
await RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview);
}
[Test]
public void CovariantReturns([ValueSource(nameof(dotnetCoreOnlyOptions))] CompilerOptions cscOptions)
public async Task CovariantReturns([ValueSource(nameof(roslyn3OrNewerOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview);
await RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview);
}
[Test]
public void StaticAbstractInterfaceMembers([ValueSource(nameof(roslynLatestOnlyOptions))] CompilerOptions cscOptions)
public async Task StaticAbstractInterfaceMembers([ValueSource(nameof(roslynLatestOnlyOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview | CompilerOptions.ReferenceCore);
await RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview);
}
void RunForLibrary([CallerMemberName] string testName = null, AssemblerOptions asmOptions = AssemblerOptions.None, CompilerOptions cscOptions = CompilerOptions.None, DecompilerSettings decompilerSettings = null)
async Task RunForLibrary([CallerMemberName] string testName = null, AssemblerOptions asmOptions = AssemblerOptions.None, CompilerOptions cscOptions = CompilerOptions.None, DecompilerSettings decompilerSettings = null)
{
Run(testName, asmOptions | AssemblerOptions.Library, cscOptions | CompilerOptions.Library, decompilerSettings);
await Run(testName, asmOptions | AssemblerOptions.Library, cscOptions | CompilerOptions.Library, decompilerSettings);
}
void Run([CallerMemberName] string testName = null, AssemblerOptions asmOptions = AssemblerOptions.None, CompilerOptions cscOptions = CompilerOptions.None, DecompilerSettings decompilerSettings = null)
async Task Run([CallerMemberName] string testName = null, AssemblerOptions asmOptions = AssemblerOptions.None, CompilerOptions cscOptions = CompilerOptions.None, DecompilerSettings decompilerSettings = null)
{
var csFile = Path.Combine(TestCasePath, testName + ".cs");
var exeFile = Path.Combine(TestCasePath, testName) + Tester.GetSuffix(cscOptions) + ".exe";
@ -651,7 +656,7 @@ namespace ICSharpCode.Decompiler.Tests @@ -651,7 +656,7 @@ namespace ICSharpCode.Decompiler.Tests
CompilerResults output = null;
try
{
output = Tester.CompileCSharp(csFile, cscOptions, exeFile);
output = await Tester.CompileCSharp(csFile, cscOptions, exeFile).ConfigureAwait(false);
}
finally
{
@ -660,7 +665,7 @@ namespace ICSharpCode.Decompiler.Tests @@ -660,7 +665,7 @@ namespace ICSharpCode.Decompiler.Tests
}
// 2. Decompile
var decompiled = Tester.DecompileCSharp(exeFile, decompilerSettings ?? Tester.GetSettings(cscOptions));
var decompiled = await Tester.DecompileCSharp(exeFile, decompilerSettings ?? Tester.GetSettings(cscOptions)).ConfigureAwait(false);
// 3. Compile
CodeAssert.FilesAreEqual(csFile, decompiled, Tester.GetPreprocessorSymbols(cscOptions).ToArray());

168
ICSharpCode.Decompiler.Tests/RoundtripAssembly.cs

@ -19,18 +19,18 @@ @@ -19,18 +19,18 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection.PortableExecutable;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using CliWrap;
using ICSharpCode.Decompiler.CSharp;
using ICSharpCode.Decompiler.CSharp.ProjectDecompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Tests.Helpers;
using Microsoft.Build.Locator;
using NUnit.Framework;
namespace ICSharpCode.Decompiler.Tests
@ -42,23 +42,23 @@ namespace ICSharpCode.Decompiler.Tests @@ -42,23 +42,23 @@ namespace ICSharpCode.Decompiler.Tests
static readonly string nunit = Path.Combine(TestDir, "nunit", "nunit3-console.exe");
[Test]
public void Cecil_net45()
public async Task Cecil_net45()
{
RunWithTest("Mono.Cecil-net45", "Mono.Cecil.dll", "Mono.Cecil.Tests.dll");
await RunWithTest("Mono.Cecil-net45", "Mono.Cecil.dll", "Mono.Cecil.Tests.dll");
}
[Test]
public void NewtonsoftJson_net45()
public async Task NewtonsoftJson_net45()
{
RunWithTest("Newtonsoft.Json-net45", "Newtonsoft.Json.dll", "Newtonsoft.Json.Tests.dll");
await RunWithTest("Newtonsoft.Json-net45", "Newtonsoft.Json.dll", "Newtonsoft.Json.Tests.dll");
}
[Test]
public void NewtonsoftJson_pcl_debug()
public async Task NewtonsoftJson_pcl_debug()
{
try
{
RunWithTest("Newtonsoft.Json-pcl-debug", "Newtonsoft.Json.dll", "Newtonsoft.Json.Tests.dll", useOldProjectFormat: true);
await RunWithTest("Newtonsoft.Json-pcl-debug", "Newtonsoft.Json.dll", "Newtonsoft.Json.Tests.dll", useOldProjectFormat: true);
}
catch (CompilationFailedException)
{
@ -67,89 +67,89 @@ namespace ICSharpCode.Decompiler.Tests @@ -67,89 +67,89 @@ namespace ICSharpCode.Decompiler.Tests
}
[Test]
public void NRefactory_CSharp()
public async Task NRefactory_CSharp()
{
RunWithTest("NRefactory", "ICSharpCode.NRefactory.CSharp.dll", "ICSharpCode.NRefactory.Tests.dll");
await RunWithTest("NRefactory", "ICSharpCode.NRefactory.CSharp.dll", "ICSharpCode.NRefactory.Tests.dll");
}
[Test]
public void ICSharpCode_Decompiler()
public async Task ICSharpCode_Decompiler()
{
RunOnly("ICSharpCode.Decompiler", "ICSharpCode.Decompiler.dll");
await RunOnly("ICSharpCode.Decompiler", "ICSharpCode.Decompiler.dll");
}
[Test]
public void ImplicitConversions()
public async Task ImplicitConversions()
{
RunWithOutput("Random Tests\\TestCases", "ImplicitConversions.exe");
await RunWithOutput("Random Tests\\TestCases", "ImplicitConversions.exe");
}
[Test]
public void ImplicitConversions_32()
public async Task ImplicitConversions_32()
{
RunWithOutput("Random Tests\\TestCases", "ImplicitConversions_32.exe");
await RunWithOutput("Random Tests\\TestCases", "ImplicitConversions_32.exe");
}
[Test]
public void ExplicitConversions()
public async Task ExplicitConversions()
{
RunWithOutput("Random Tests\\TestCases", "ExplicitConversions.exe", LanguageVersion.CSharp8_0);
await RunWithOutput("Random Tests\\TestCases", "ExplicitConversions.exe", LanguageVersion.CSharp8_0);
}
[Test]
public void ExplicitConversions_32()
public async Task ExplicitConversions_32()
{
RunWithOutput("Random Tests\\TestCases", "ExplicitConversions_32.exe", LanguageVersion.CSharp8_0);
await RunWithOutput("Random Tests\\TestCases", "ExplicitConversions_32.exe", LanguageVersion.CSharp8_0);
}
[Test]
public void ExplicitConversions_With_NativeInts()
public async Task ExplicitConversions_With_NativeInts()
{
RunWithOutput("Random Tests\\TestCases", "ExplicitConversions.exe", LanguageVersion.CSharp9_0);
await RunWithOutput("Random Tests\\TestCases", "ExplicitConversions.exe", LanguageVersion.CSharp9_0);
}
[Test]
public void ExplicitConversions_32_With_NativeInts()
public async Task ExplicitConversions_32_With_NativeInts()
{
RunWithOutput("Random Tests\\TestCases", "ExplicitConversions_32.exe", LanguageVersion.CSharp9_0);
await RunWithOutput("Random Tests\\TestCases", "ExplicitConversions_32.exe", LanguageVersion.CSharp9_0);
}
[Test]
public void Random_TestCase_1()
public async Task Random_TestCase_1()
{
RunWithOutput("Random Tests\\TestCases", "TestCase-1.exe", LanguageVersion.CSharp8_0);
await RunWithOutput("Random Tests\\TestCases", "TestCase-1.exe", LanguageVersion.CSharp8_0);
}
[Test]
[Ignore("See https://github.com/icsharpcode/ILSpy/issues/2541 - Waiting for https://github.com/dotnet/roslyn/issues/45929")]
public void Random_TestCase_1_With_NativeInts()
public async Task Random_TestCase_1_With_NativeInts()
{
RunWithOutput("Random Tests\\TestCases", "TestCase-1.exe", LanguageVersion.CSharp9_0);
await RunWithOutput("Random Tests\\TestCases", "TestCase-1.exe", LanguageVersion.CSharp9_0);
}
// Let's limit the roundtrip tests to C# 8.0 for now; because 9.0 is still in preview
// and the generated project doesn't build as-is.
const LanguageVersion defaultLanguageVersion = LanguageVersion.CSharp8_0;
void RunWithTest(string dir, string fileToRoundtrip, string fileToTest, LanguageVersion languageVersion = defaultLanguageVersion, string keyFile = null, bool useOldProjectFormat = false)
async Task RunWithTest(string dir, string fileToRoundtrip, string fileToTest, LanguageVersion languageVersion = defaultLanguageVersion, string keyFile = null, bool useOldProjectFormat = false)
{
RunInternal(dir, fileToRoundtrip, outputDir => RunTest(outputDir, fileToTest), languageVersion, snkFilePath: keyFile, useOldProjectFormat: useOldProjectFormat);
await RunInternal(dir, fileToRoundtrip, outputDir => RunTest(outputDir, fileToTest).GetAwaiter().GetResult(), languageVersion, snkFilePath: keyFile, useOldProjectFormat: useOldProjectFormat);
}
void RunWithOutput(string dir, string fileToRoundtrip, LanguageVersion languageVersion = defaultLanguageVersion)
async Task RunWithOutput(string dir, string fileToRoundtrip, LanguageVersion languageVersion = defaultLanguageVersion)
{
string inputDir = Path.Combine(TestDir, dir);
RunInternal(dir, fileToRoundtrip,
outputDir => Tester.RunAndCompareOutput(fileToRoundtrip, Path.Combine(inputDir, fileToRoundtrip), Path.Combine(outputDir, fileToRoundtrip)),
await RunInternal(dir, fileToRoundtrip,
outputDir => Tester.RunAndCompareOutput(fileToRoundtrip, Path.Combine(inputDir, fileToRoundtrip), Path.Combine(outputDir, fileToRoundtrip)).GetAwaiter().GetResult(),
languageVersion);
}
void RunOnly(string dir, string fileToRoundtrip, LanguageVersion languageVersion = defaultLanguageVersion)
async Task RunOnly(string dir, string fileToRoundtrip, LanguageVersion languageVersion = defaultLanguageVersion)
{
RunInternal(dir, fileToRoundtrip, outputDir => { }, languageVersion);
await RunInternal(dir, fileToRoundtrip, outputDir => { }, languageVersion);
}
void RunInternal(string dir, string fileToRoundtrip, Action<string> testAction, LanguageVersion languageVersion, string snkFilePath = null, bool useOldProjectFormat = false)
async Task RunInternal(string dir, string fileToRoundtrip, Action<string> testAction, LanguageVersion languageVersion, string snkFilePath = null, bool useOldProjectFormat = false)
{
if (!Directory.Exists(TestDir))
{
@ -214,7 +214,7 @@ namespace ICSharpCode.Decompiler.Tests @@ -214,7 +214,7 @@ namespace ICSharpCode.Decompiler.Tests
}
Assert.IsNotNull(projectFile, $"Could not find {fileToRoundtrip}");
Compile(projectFile, outputDir);
await Compile(projectFile, outputDir);
testAction(outputDir);
}
@ -244,73 +244,47 @@ namespace ICSharpCode.Decompiler.Tests @@ -244,73 +244,47 @@ namespace ICSharpCode.Decompiler.Tests
}
}
static string FindMSBuild()
{
string vsPath = MSBuildLocator.QueryVisualStudioInstances(new VisualStudioInstanceQueryOptions { DiscoveryTypes = DiscoveryType.VisualStudioSetup })
.OrderByDescending(i => i.Version)
.FirstOrDefault()
?.MSBuildPath;
if (vsPath == null)
throw new InvalidOperationException("Could not find MSBuild");
return Path.Combine(vsPath, "msbuild.exe");
}
static void Compile(string projectFile, string outputDir)
static async Task Compile(string projectFile, string outputDir)
{
var info = new ProcessStartInfo(FindMSBuild());
info.Arguments = $"/nologo /v:minimal /restore /p:OutputPath=\"{outputDir}\" \"{projectFile}\"";
info.CreateNoWindow = true;
info.UseShellExecute = false;
info.RedirectStandardOutput = true;
// Don't let environment variables (e.g. set by AppVeyor) influence the build.
info.EnvironmentVariables.Remove("Configuration");
info.EnvironmentVariables.Remove("Platform");
Console.WriteLine($"\"{info.FileName}\" {info.Arguments}");
using (var p = Process.Start(info))
Regex errorRegex = new Regex(@"^[\w\d.\\-]+\(\d+,\d+\):");
string suffix = $" [{projectFile}]";
var command = Cli.Wrap(await Tester.FindMSBuild())
.WithArguments($"/nologo /v:minimal /restore /p:OutputPath=\"{outputDir}\" \"{projectFile}\"")
.WithValidation(CommandResultValidation.None)
.WithStandardOutputPipe(PipeTarget.ToDelegate(PrintLine));
Console.WriteLine($"\"{command.TargetFilePath}\" {command.Arguments}");
var result = await command.ExecuteAsync().ConfigureAwait(false);
if (result.ExitCode != 0)
throw new CompilationFailedException($"Compilation of {Path.GetFileName(projectFile)} failed");
void PrintLine(string line)
{
Regex errorRegex = new Regex(@"^[\w\d.\\-]+\(\d+,\d+\):");
string suffix = $" [{projectFile}]";
string line;
while ((line = p.StandardOutput.ReadLine()) != null)
if (line.EndsWith(suffix, StringComparison.OrdinalIgnoreCase))
{
if (line.EndsWith(suffix, StringComparison.OrdinalIgnoreCase))
{
line = line.Substring(0, line.Length - suffix.Length);
}
Match m = errorRegex.Match(line);
if (m.Success)
{
// Make path absolute so that it gets hyperlinked
line = Path.GetDirectoryName(projectFile) + Path.DirectorySeparatorChar + line;
}
Console.WriteLine(line);
line = line.Substring(0, line.Length - suffix.Length);
}
Match m = errorRegex.Match(line);
if (m.Success)
{
// Make path absolute so that it gets hyperlinked
line = Path.GetDirectoryName(projectFile) + Path.DirectorySeparatorChar + line;
}
p.WaitForExit();
if (p.ExitCode != 0)
throw new CompilationFailedException($"Compilation of {Path.GetFileName(projectFile)} failed");
Console.WriteLine(line);
}
}
static void RunTest(string outputDir, string fileToTest)
static async Task RunTest(string outputDir, string fileToTest)
{
var info = new ProcessStartInfo(nunit);
info.WorkingDirectory = outputDir;
info.Arguments = $"\"{fileToTest}\"";
info.CreateNoWindow = true;
info.UseShellExecute = false;
info.RedirectStandardOutput = true;
Console.WriteLine($"\"{info.FileName}\" {info.Arguments}");
using (var p = Process.Start(info))
{
string line;
while ((line = p.StandardOutput.ReadLine()) != null)
{
Console.WriteLine(line);
}
p.WaitForExit();
if (p.ExitCode != 0)
throw new TestRunFailedException($"Test execution of {Path.GetFileName(fileToTest)} failed");
}
var command = Cli.Wrap(nunit)
.WithWorkingDirectory(outputDir)
.WithArguments($"\"{fileToTest}\"")
.WithValidation(CommandResultValidation.None)
.WithStandardOutputPipe(PipeTarget.ToDelegate(Console.WriteLine));
Console.WriteLine($"\"{command.TargetFilePath}\" {command.Arguments}");
var result = await command.ExecuteAsync().ConfigureAwait(false);
if (result.ExitCode != 0)
throw new TestRunFailedException($"Test execution of {Path.GetFileName(fileToTest)} failed");
}
class TestProjectDecompiler : WholeProjectDecompiler

9
ICSharpCode.Decompiler.Tests/TestCases/Pretty/DeconstructionTests.cs

@ -22,15 +22,6 @@ using System.Runtime.InteropServices; @@ -22,15 +22,6 @@ using System.Runtime.InteropServices;
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
public static class DeconstructionExt
{
public static void Deconstruct<K, V>(this KeyValuePair<K, V> pair, out K key, out V value)
{
key = pair.Key;
value = pair.Value;
}
}
internal class DeconstructionTests
{
[StructLayout(LayoutKind.Sequential, Size = 1)]

3
ICSharpCode.Decompiler.Tests/TestCases/Pretty/QueryExpressions.cs

@ -20,6 +20,9 @@ using System; @@ -20,6 +20,9 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
#if ROSLYN4
using System.Runtime.CompilerServices;
#endif
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{

2
ICSharpCode.Decompiler.Tests/TestCases/Pretty/CS6_StringInterpolation.cs → ICSharpCode.Decompiler.Tests/TestCases/Pretty/StringInterpolation.cs

@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
internal class CS6_StringInterpolation
internal class StringInterpolation
{
public static void Main(string[] args)
{

13
ICSharpCode.Decompiler.Tests/TestTraceListener.cs

@ -17,6 +17,9 @@ @@ -17,6 +17,9 @@
// DEALINGS IN THE SOFTWARE.
using System.Diagnostics;
using System.Threading.Tasks;
using ICSharpCode.Decompiler.Tests.Helpers;
using NUnit.Framework;
@ -42,4 +45,14 @@ namespace ICSharpCode.Decompiler.Tests @@ -42,4 +45,14 @@ namespace ICSharpCode.Decompiler.Tests
Assert.Fail(message + " " + detailMessage);
}
}
[SetUpFixture]
public class ToolsetSetup
{
[OneTimeSetUp]
public async Task RunBeforeAnyTests()
{
await Tester.Initialize();
}
}
}

43
ICSharpCode.Decompiler.Tests/UglyTestRunner.cs

@ -21,6 +21,7 @@ using System.CodeDom.Compiler; @@ -21,6 +21,7 @@ using System.CodeDom.Compiler;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using ICSharpCode.Decompiler.Tests.Helpers;
@ -72,67 +73,67 @@ namespace ICSharpCode.Decompiler.Tests @@ -72,67 +73,67 @@ namespace ICSharpCode.Decompiler.Tests
};
[Test]
public void NoArrayInitializers([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions cscOptions)
public async Task NoArrayInitializers([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions, decompilerSettings: new DecompilerSettings(CSharp.LanguageVersion.CSharp1) {
await RunForLibrary(cscOptions: cscOptions, decompilerSettings: new DecompilerSettings(CSharp.LanguageVersion.CSharp1) {
ArrayInitializers = false
});
}
[Test]
public void NoDecimalConstants([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions cscOptions)
public async Task NoDecimalConstants([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions, decompilerSettings: new DecompilerSettings(CSharp.LanguageVersion.CSharp1) {
await RunForLibrary(cscOptions: cscOptions, decompilerSettings: new DecompilerSettings(CSharp.LanguageVersion.CSharp1) {
DecimalConstants = false
});
}
[Test]
public void NoExtensionMethods([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions cscOptions)
public async Task NoExtensionMethods([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions, decompilerSettings: new DecompilerSettings(CSharp.LanguageVersion.CSharp9_0) {
await RunForLibrary(cscOptions: cscOptions, decompilerSettings: new DecompilerSettings(CSharp.LanguageVersion.CSharp9_0) {
ExtensionMethods = false
});
}
[Test]
public void NoForEachStatement([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
public async Task NoForEachStatement([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions, decompilerSettings: new DecompilerSettings(CSharp.LanguageVersion.CSharp1) {
await RunForLibrary(cscOptions: cscOptions, decompilerSettings: new DecompilerSettings(CSharp.LanguageVersion.CSharp1) {
ForEachStatement = false,
UseEnhancedUsing = false,
});
}
[Test]
public void NoLocalFunctions([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions cscOptions)
public async Task NoLocalFunctions([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions, decompilerSettings: new DecompilerSettings(CSharp.LanguageVersion.CSharp1));
await RunForLibrary(cscOptions: cscOptions, decompilerSettings: new DecompilerSettings(CSharp.LanguageVersion.CSharp1));
}
[Test]
public void NoPropertiesAndEvents([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
public async Task NoPropertiesAndEvents([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions, decompilerSettings: new DecompilerSettings(CSharp.LanguageVersion.CSharp1) {
await RunForLibrary(cscOptions: cscOptions, decompilerSettings: new DecompilerSettings(CSharp.LanguageVersion.CSharp1) {
AutomaticEvents = false,
AutomaticProperties = false,
});
}
[Test]
public void AggressiveScalarReplacementOfAggregates([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions cscOptions)
public async Task AggressiveScalarReplacementOfAggregates([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions, decompilerSettings: new DecompilerSettings(CSharp.LanguageVersion.CSharp3) {
await RunForLibrary(cscOptions: cscOptions, decompilerSettings: new DecompilerSettings(CSharp.LanguageVersion.CSharp3) {
AggressiveScalarReplacementOfAggregates = true
});
}
void RunForLibrary([CallerMemberName] string testName = null, AssemblerOptions asmOptions = AssemblerOptions.None, CompilerOptions cscOptions = CompilerOptions.None, DecompilerSettings decompilerSettings = null)
async Task RunForLibrary([CallerMemberName] string testName = null, AssemblerOptions asmOptions = AssemblerOptions.None, CompilerOptions cscOptions = CompilerOptions.None, DecompilerSettings decompilerSettings = null)
{
Run(testName, asmOptions | AssemblerOptions.Library, cscOptions | CompilerOptions.Library, decompilerSettings);
await Run(testName, asmOptions | AssemblerOptions.Library, cscOptions | CompilerOptions.Library, decompilerSettings);
}
void Run([CallerMemberName] string testName = null, AssemblerOptions asmOptions = AssemblerOptions.None, CompilerOptions cscOptions = CompilerOptions.None, DecompilerSettings decompilerSettings = null)
async Task Run([CallerMemberName] string testName = null, AssemblerOptions asmOptions = AssemblerOptions.None, CompilerOptions cscOptions = CompilerOptions.None, DecompilerSettings decompilerSettings = null)
{
var ilFile = Path.Combine(TestCasePath, testName) + Tester.GetSuffix(cscOptions) + ".il";
var csFile = Path.Combine(TestCasePath, testName + ".cs");
@ -144,8 +145,8 @@ namespace ICSharpCode.Decompiler.Tests @@ -144,8 +145,8 @@ namespace ICSharpCode.Decompiler.Tests
CompilerResults output = null;
try
{
output = Tester.CompileCSharp(csFile, cscOptions);
Tester.Disassemble(output.PathToAssembly, ilFile, asmOptions);
output = await Tester.CompileCSharp(csFile, cscOptions).ConfigureAwait(false);
await Tester.Disassemble(output.PathToAssembly, ilFile, asmOptions).ConfigureAwait(false);
}
finally
{
@ -154,8 +155,8 @@ namespace ICSharpCode.Decompiler.Tests @@ -154,8 +155,8 @@ namespace ICSharpCode.Decompiler.Tests
}
}
var executable = Tester.AssembleIL(ilFile, asmOptions);
var decompiled = Tester.DecompileCSharp(executable, decompilerSettings);
var executable = await Tester.AssembleIL(ilFile, asmOptions).ConfigureAwait(false);
var decompiled = await Tester.DecompileCSharp(executable, decompilerSettings).ConfigureAwait(false);
CodeAssert.FilesAreEqual(expectedFile, decompiled, Tester.GetPreprocessorSymbols(cscOptions).ToArray());
}

31
ICSharpCode.Decompiler.Tests/VBPrettyTestRunner.cs

@ -20,6 +20,7 @@ using System; @@ -20,6 +20,7 @@ using System;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using ICSharpCode.Decompiler.Tests.Helpers;
@ -73,42 +74,42 @@ namespace ICSharpCode.Decompiler.Tests @@ -73,42 +74,42 @@ namespace ICSharpCode.Decompiler.Tests
};
[Test, Ignore("Implement VB async/await")]
public void Async([ValueSource(nameof(defaultOptions))] CompilerOptions options)
public async Task Async([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{
Run(options: options);
await Run(options: options);
}
[Test] // TODO: legacy VB compound assign
public void VBCompoundAssign([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions options)
public async Task VBCompoundAssign([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions options)
{
Run(options: options | CompilerOptions.Library);
await Run(options: options | CompilerOptions.Library);
}
[Test]
public void Select([ValueSource(nameof(defaultOptions))] CompilerOptions options)
public async Task Select([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{
Run(options: options | CompilerOptions.Library);
await Run(options: options | CompilerOptions.Library);
}
[Test]
public void Issue1906([ValueSource(nameof(defaultOptions))] CompilerOptions options)
public async Task Issue1906([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{
Run(options: options | CompilerOptions.Library);
await Run(options: options | CompilerOptions.Library);
}
[Test]
public void Issue2192([ValueSource(nameof(defaultOptions))] CompilerOptions options)
public async Task Issue2192([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{
Run(options: options | CompilerOptions.Library);
await Run(options: options | CompilerOptions.Library);
}
[Test]
public void VBPropertiesTest([ValueSource(nameof(defaultOptions))] CompilerOptions options)
public async Task VBPropertiesTest([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{
Run(options: options | CompilerOptions.Library);
await Run(options: options | CompilerOptions.Library);
}
void Run([CallerMemberName] string testName = null, CompilerOptions options = CompilerOptions.UseDebug, DecompilerSettings settings = null)
async Task Run([CallerMemberName] string testName = null, CompilerOptions options = CompilerOptions.UseDebug, DecompilerSettings settings = null)
{
var vbFile = Path.Combine(TestCasePath, testName + ".vb");
var csFile = Path.Combine(TestCasePath, testName + ".cs");
@ -118,8 +119,8 @@ namespace ICSharpCode.Decompiler.Tests @@ -118,8 +119,8 @@ namespace ICSharpCode.Decompiler.Tests
exeFile = Path.ChangeExtension(exeFile, ".dll");
}
var executable = Tester.CompileVB(vbFile, options | CompilerOptions.ReferenceVisualBasic, exeFile);
var decompiled = Tester.DecompileCSharp(executable.PathToAssembly, settings);
var executable = await Tester.CompileVB(vbFile, options | CompilerOptions.ReferenceVisualBasic, exeFile).ConfigureAwait(false);
var decompiled = await Tester.DecompileCSharp(executable.PathToAssembly, settings).ConfigureAwait(false);
CodeAssert.FilesAreEqual(csFile, decompiled, Tester.GetPreprocessorSymbols(options).ToArray());
}

9
ILSpy.sln

@ -20,6 +20,9 @@ EndProject @@ -20,6 +20,9 @@ EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ICSharpCode.Decompiler", "ICSharpCode.Decompiler\ICSharpCode.Decompiler.csproj", "{984CC812-9470-4A13-AFF9-CC44068D666C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ICSharpCode.Decompiler.Tests", "ICSharpCode.Decompiler.Tests\ICSharpCode.Decompiler.Tests.csproj", "{FEC0DA52-C4A6-4710-BE36-B484A20C5E22}"
ProjectSection(ProjectDependencies) = postProject
{4FBB470F-69EB-4C8B-8961-8B4DF4EBB999} = {4FBB470F-69EB-4C8B-8961-8B4DF4EBB999}
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestPlugin", "TestPlugin\TestPlugin.csproj", "{F32EBCC8-0E53-4421-867E-05B3D6E10C70}"
EndProject
@ -58,6 +61,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILSpy.Installer", "ILSpy.In @@ -58,6 +61,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILSpy.Installer", "ILSpy.In
{1E85EFF9-E370-4683-83E4-8A3D063FF791} = {1E85EFF9-E370-4683-83E4-8A3D063FF791}
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ICSharpCode.Decompiler.TestRunner", "ICSharpCode.Decompiler.TestRunner\ICSharpCode.Decompiler.TestRunner.csproj", "{4FBB470F-69EB-4C8B-8961-8B4DF4EBB999}"
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
ILSpy.AddIn.Shared\ILSpy.AddIn.Shared.projitems*{09a03980-d14a-4705-a38c-741ad7166dee}*SharedItemsImports = 5
@ -129,6 +134,10 @@ Global @@ -129,6 +134,10 @@ Global
{A4BA0771-DA4A-4A94-A5EC-5BA10B52816F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A4BA0771-DA4A-4A94-A5EC-5BA10B52816F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A4BA0771-DA4A-4A94-A5EC-5BA10B52816F}.Release|Any CPU.Build.0 = Release|Any CPU
{4FBB470F-69EB-4C8B-8961-8B4DF4EBB999}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4FBB470F-69EB-4C8B-8961-8B4DF4EBB999}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4FBB470F-69EB-4C8B-8961-8B4DF4EBB999}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4FBB470F-69EB-4C8B-8961-8B4DF4EBB999}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

Loading…
Cancel
Save