Browse Source

Add PrettyTestRunner

pull/734/head
Siegfried Pammer 9 years ago
parent
commit
02022c7290
  1. 23
      ICSharpCode.Decompiler/Tests/CorrectnessTestRunner.cs
  2. 5
      ICSharpCode.Decompiler/Tests/Helpers/CodeAssert.cs
  3. 206
      ICSharpCode.Decompiler/Tests/Helpers/SdkUtility.cs
  4. 24
      ICSharpCode.Decompiler/Tests/Helpers/Tester.cs
  5. 6
      ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj
  6. 84
      ICSharpCode.Decompiler/Tests/PrettyTestRunner.cs
  7. 30
      ICSharpCode.Decompiler/Tests/TestCases/Pretty/HelloWorld.cs

23
ICSharpCode.Decompiler/Tests/CorrectnessTestRunner.cs

@ -1,10 +1,25 @@ @@ -1,10 +1,25 @@
using System;
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ICSharpCode.Decompiler.Tests.Helpers;
using NUnit.Framework;

5
ICSharpCode.Decompiler/Tests/Helpers/CodeAssert.cs

@ -10,6 +10,11 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -10,6 +10,11 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
{
public class CodeAssert
{
public static void FilesAreEqual(string fileName1, string fileName2)
{
AreEqual(File.ReadAllText(fileName1), File.ReadAllText(fileName2));
}
public static void AreEqual(string input1, string input2)
{
var diff = new StringWriter();

206
ICSharpCode.Decompiler/Tests/Helpers/SdkUtility.cs

@ -0,0 +1,206 @@ @@ -0,0 +1,206 @@
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.IO;
using System.Linq;
using Microsoft.Win32;
namespace ICSharpCode.Decompiler.Tests.Helpers
{
public static class SdkUtility
{
static string GetPathFromRegistry(string key, string valueName)
{
using (RegistryKey installRootKey = Registry.LocalMachine.OpenSubKey(key)) {
if (installRootKey != null) {
object o = installRootKey.GetValue(valueName);
if (o != null) {
string r = o.ToString();
if (!string.IsNullOrEmpty(r))
return r;
}
}
}
return null;
}
static string GetPathFromRegistryX86(string key, string valueName)
{
using (RegistryKey baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32)) {
using (RegistryKey installRootKey = baseKey.OpenSubKey(key)) {
if (installRootKey != null) {
object o = installRootKey.GetValue(valueName);
if (o != null) {
string r = o.ToString();
if (!string.IsNullOrEmpty(r))
return r;
}
}
}
}
return null;
}
#region InstallRoot Properties
static string netFrameworkInstallRoot = null;
/// <summary>
/// Gets the installation root of the .NET Framework (@"C:\Windows\Microsoft.NET\Framework\")
/// </summary>
public static string NetFrameworkInstallRoot {
get {
if (netFrameworkInstallRoot == null) {
netFrameworkInstallRoot = GetPathFromRegistry(@"SOFTWARE\Microsoft\.NETFramework", "InstallRoot") ?? string.Empty;
}
return netFrameworkInstallRoot;
}
}
static string netSdk20InstallRoot = null;
/// <summary>
/// Location of the .NET 2.0 SDK install root.
/// </summary>
public static string NetSdk20InstallRoot {
get {
if (netSdk20InstallRoot == null) {
netSdk20InstallRoot = GetPathFromRegistry(@"SOFTWARE\Microsoft\.NETFramework", "sdkInstallRootv2.0") ?? string.Empty;
}
return netSdk20InstallRoot;
}
}
static string windowsSdk60InstallRoot = null;
/// <summary>
/// Location of the .NET 3.0 SDK (Windows SDK 6.0) install root.
/// </summary>
public static string WindowsSdk60InstallRoot {
get {
if (windowsSdk60InstallRoot == null) {
windowsSdk60InstallRoot = GetPathFromRegistry(@"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v6.0", "InstallationFolder") ?? string.Empty;
}
return windowsSdk60InstallRoot;
}
}
static string windowsSdk60aInstallRoot = null;
/// <summary>
/// Location of the Windows SDK Components in Visual Studio 2008 (.NET 3.5; Windows SDK 6.0a).
/// </summary>
public static string WindowsSdk60aInstallRoot {
get {
if (windowsSdk60aInstallRoot == null) {
windowsSdk60aInstallRoot = GetPathFromRegistry(@"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v6.0a", "InstallationFolder") ?? string.Empty;
}
return windowsSdk60aInstallRoot;
}
}
static string windowsSdk61InstallRoot = null;
/// <summary>
/// Location of the .NET 3.5 SDK (Windows SDK 6.1) install root.
/// </summary>
public static string WindowsSdk61InstallRoot {
get {
if (windowsSdk61InstallRoot == null) {
windowsSdk61InstallRoot = GetPathFromRegistry(@"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v6.1", "InstallationFolder") ?? string.Empty;
}
return windowsSdk61InstallRoot;
}
}
static string windowsSdk70InstallRoot = null;
/// <summary>
/// Location of the .NET 3.5 SP1 SDK (Windows SDK 7.0) install root.
/// </summary>
public static string WindowsSdk70InstallRoot {
get {
if (windowsSdk70InstallRoot == null) {
windowsSdk70InstallRoot = GetPathFromRegistry(@"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0", "InstallationFolder") ?? string.Empty;
}
return windowsSdk70InstallRoot;
}
}
static string windowsSdk71InstallRoot = null;
/// <summary>
/// Location of the .NET 4.0 SDK (Windows SDK 7.1) install root.
/// </summary>
public static string WindowsSdk71InstallRoot {
get {
if (windowsSdk71InstallRoot == null) {
windowsSdk71InstallRoot = GetPathFromRegistry(@"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.1", "InstallationFolder") ?? string.Empty;
}
return windowsSdk71InstallRoot;
}
}
static string windowsSdk80InstallRoot = null;
/// <summary>
/// Location of the .NET 4.5 SDK (Windows SDK 8.0) install root.
/// </summary>
public static string WindowsSdk80NetFxTools {
get {
if (windowsSdk80InstallRoot == null) {
windowsSdk80InstallRoot = GetPathFromRegistryX86(@"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v8.0A\WinSDK-NetFx40Tools", "InstallationFolder") ?? string.Empty;
}
return windowsSdk80InstallRoot;
}
}
#endregion
/// <summary>
/// Searches all the .net sdk bin folders and return the path of the
/// exe from the latest sdk.
/// </summary>
/// <param name="exeName">The EXE to search for.</param>
/// <returns>The path of the executable, or null if the exe is not found.</returns>
public static string GetSdkPath(string exeName) {
string execPath;
if (!string.IsNullOrEmpty(WindowsSdk80NetFxTools)) {
execPath = Path.Combine(WindowsSdk80NetFxTools, exeName);
if (File.Exists(execPath)) { return execPath; }
}
if (!string.IsNullOrEmpty(WindowsSdk71InstallRoot)) {
execPath = Path.Combine(WindowsSdk71InstallRoot, "bin\\" + exeName);
if (File.Exists(execPath)) { return execPath; }
}
if (!string.IsNullOrEmpty(WindowsSdk70InstallRoot)) {
execPath = Path.Combine(WindowsSdk70InstallRoot, "bin\\" + exeName);
if (File.Exists(execPath)) { return execPath; }
}
if (!string.IsNullOrEmpty(WindowsSdk61InstallRoot)) {
execPath = Path.Combine(WindowsSdk61InstallRoot, "bin\\" + exeName);
if (File.Exists(execPath)) { return execPath; }
}
if (!string.IsNullOrEmpty(WindowsSdk60aInstallRoot)) {
execPath = Path.Combine(WindowsSdk60aInstallRoot, "bin\\" + exeName);
if (File.Exists(execPath)) { return execPath; }
}
if (!string.IsNullOrEmpty(WindowsSdk60InstallRoot)) {
execPath = Path.Combine(WindowsSdk60InstallRoot, "bin\\" + exeName);
if (File.Exists(execPath)) { return execPath; }
}
if (!string.IsNullOrEmpty(NetSdk20InstallRoot)) {
execPath = Path.Combine(NetSdk20InstallRoot, "bin\\" + exeName);
if (File.Exists(execPath)) { return execPath; }
}
return null;
}
}
}

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

@ -87,6 +87,30 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -87,6 +87,30 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
return outputFile;
}
public static string Disassemble(string sourceFileName, string outputFile)
{
string ildasmPath = SdkUtility.GetSdkPath("ildasm.exe");
ProcessStartInfo info = new ProcessStartInfo(ildasmPath);
info.Arguments = $"/out=\"{outputFile}\" \"{sourceFileName}\"";
info.RedirectStandardError = true;
info.RedirectStandardOutput = true;
info.UseShellExecute = false;
Process process = Process.Start(info);
var outputTask = process.StandardOutput.ReadToEndAsync();
var errorTask = process.StandardError.ReadToEndAsync();
Task.WaitAll(outputTask, errorTask);
process.WaitForExit();
Console.WriteLine("output: " + outputTask.Result);
Console.WriteLine("errors: " + errorTask.Result);
return outputFile;
}
public static CompilerResults CompileCSharp(string sourceFileName, CompilerOptions flags = CompilerOptions.UseDebug)
{
List<string> sourceFileNames = new List<string> { sourceFileName };

6
ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj

@ -112,10 +112,12 @@ @@ -112,10 +112,12 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Helpers\CodeAssert.cs" />
<Compile Include="Helpers\SdkUtility.cs" />
<Compile Include="Helpers\RemoveCompilerAttribute.cs" />
<Compile Include="Helpers\Tester.cs" />
<Compile Include="Helpers\TypeSystemHelper.cs" />
<Compile Include="Loops.cs" />
<Compile Include="PrettyTestRunner.cs" />
<Compile Include="RoundtripAssembly.cs" />
<Compile Include="TestCases\Correctness\CompoundAssignment.cs" />
<Compile Include="TestCases\Correctness\ControlFlow.cs" />
@ -132,6 +134,7 @@ @@ -132,6 +134,7 @@
<Compile Include="TestCases\Correctness\UnsafeCode.cs" />
<Compile Include="TestCases\Correctness\ValueTypeCall.cs" />
<Compile Include="CorrectnessTestRunner.cs" />
<Compile Include="TestCases\Pretty\HelloWorld.cs" />
<Compile Include="Util\IntervalTests.cs" />
<Compile Include="Util\LongSetTests.cs" />
<Compile Include="CustomAttributes\CustomAttributeTests.cs" />
@ -145,6 +148,9 @@ @@ -145,6 +148,9 @@
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<ItemGroup>
<None Include="TestCases\Pretty\HelloWorld.il">
<DependentUpon>HelloWorld.cs</DependentUpon>
</None>
<None Include="TestCases\Pretty\Readme.txt" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />

84
ICSharpCode.Decompiler/Tests/PrettyTestRunner.cs

@ -0,0 +1,84 @@ @@ -0,0 +1,84 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using ICSharpCode.Decompiler.Tests.Helpers;
using NUnit.Framework;
namespace ICSharpCode.Decompiler.Tests
{
public class PrettyTestRunner
{
const string TestCasePath = @"../../Tests/TestCases/Pretty";
[Test]
public void AllFilesHaveTests()
{
var testNames = typeof(PrettyTestRunner).GetMethods()
.Where(m => m.GetCustomAttributes(typeof(TestAttribute), false).Any())
.Select(m => m.Name)
.ToArray();
foreach (var file in new DirectoryInfo(TestCasePath).EnumerateFiles()) {
if (file.Extension == ".txt" || file.Extension == ".exe")
continue;
var testName = Path.GetFileNameWithoutExtension(file.Name);
Assert.Contains(testName, testNames);
}
}
[Test]
public void HelloWorld()
{
Run("HelloWorld");
Run("HelloWorld", AssemblerOptions.UseDebug);
}
void Run(string testName, AssemblerOptions asmOptions = AssemblerOptions.None)
{
var ilFile = Path.Combine(TestCasePath, testName + ".il");
var csFile = Path.Combine(TestCasePath, testName + ".cs");
EnsureSourceFilesExist(Path.Combine(TestCasePath, testName));
var executable = Tester.AssembleIL(ilFile, asmOptions);
var decompiled = Tester.DecompileCSharp(executable);
CodeAssert.FilesAreEqual(csFile, decompiled);
}
void EnsureSourceFilesExist(string fileName)
{
if (!File.Exists(fileName + ".il")) {
CompilerResults output = null;
try {
output = Tester.CompileCSharp(fileName + ".cs", CompilerOptions.None);
Tester.Disassemble(output.PathToAssembly, fileName + ".il");
} finally {
if (output != null)
output.TempFiles.Delete();
}
}
}
}
}

30
ICSharpCode.Decompiler/Tests/TestCases/Pretty/HelloWorld.cs

@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
namespace Pretty.HelloWorld
{
public class HelloWorld
{
public static void Main()
{
Console.WriteLine("Hello World!");
}
}
}
Loading…
Cancel
Save