Skip to content

Commit

Permalink
test compilation of a simple global function
Browse files Browse the repository at this point in the history
  • Loading branch information
jakubmisek committed Jun 15, 2024
1 parent de11a45 commit e26c914
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 2 deletions.
14 changes: 13 additions & 1 deletion src/Peachpie.Library.Scripting/Context.Script.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,23 @@

namespace Peachpie.Library.Scripting
{
/// <summary>
/// Represents a script created by <see cref="ScriptingProvider"/>.
/// </summary>
[PhpHidden]
public interface IScript : Context.IScript
{
/// <summary>
/// Assembly byte content.
/// </summary>
ImmutableArray<byte> Image { get; }
}

/// <summary>
/// Script representing a compiled submission.
/// </summary>
[DebuggerDisplay("Script ({AssemblyName.Name})")]
sealed class Script : Context.IScript
sealed class Script : IScript
{
#region Fields & Properties

Expand Down
2 changes: 1 addition & 1 deletion src/Peachpie.Runtime/Attributes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ public TargetPhpLanguageAttribute(string langVersion, bool shortOpenTag)
/// <summary>
/// Marks public declarations that won't be visible in the PHP context.
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Enum | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Enum | AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)]
public sealed class PhpHiddenAttribute : Attribute
{
}
Expand Down
90 changes: 90 additions & 0 deletions src/Tests/Peachpie.App.Tests/CompiledILTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Pchp.Core;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.CSharp;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Metadata;
using Peachpie.Library.Scripting;
using System.Reflection.PortableExecutable;
using System.Reflection.Metadata;
using ICSharpCode.Decompiler.CSharp.Syntax;


namespace Peachpie.App.Tests
{
[TestClass]
public class CompiledILTest
{
static IScript Compile(string code)
{
using (var ctx = Context.CreateConsole(string.Empty))
{
return (IScript)Context.DefaultScriptingProvider.CreateScript(new Context.ScriptOptions()
{
Context = ctx,
Location = new Location(Path.Combine(Directory.GetCurrentDirectory(), "fake.php"), 0, 0),
EmitDebugInformation = true,
IsSubmission = false,
AdditionalReferences = new string[] {
typeof(CompiledILTest).Assembly.Location,
},
}, code);
}
}

static CSharpDecompiler Decompile(IScript script)
{
var fileName = "fake.dll";
var file = new PEFile(fileName, new PEReader(script.Image));

var resolver = new UniversalAssemblyResolver(
fileName,
false,
file.DetectTargetFrameworkId(),
file.DetectRuntimePack(),
PEStreamOptions.PrefetchMetadata,
MetadataReaderOptions.None
);

return new CSharpDecompiler(new DecompilerTypeSystem(file, resolver), new DecompilerSettings() { });
}

static bool DecompileFunction(IScript script, string fnname, out IMethod method, out AstNode ast)
{
var minfo = script.GetGlobalRoutineHandle(fnname).Single();

var decompiler = Decompile(script);
var mainType = decompiler.TypeSystem.FindType(new FullTypeName(minfo.DeclaringType.FullName)).GetDefinition();

method = mainType.Methods.Single(m => m.Name == minfo.Name);
ast = decompiler.Decompile(method.MetadataToken).LastChild;

return true;
}

[TestMethod]
public void TestSimpleFunction()
{
var script = Compile(@"<?php
function test() { return 1; }
");
var testAst = DecompileFunction(script, "test", out var method, out var ast);

Assert.IsTrue(method.ReturnType.FullName == typeof(long).FullName);

var bodyCode = ast.LastChild.ToString().Trim();

Assert.IsTrue(
// method body
"{\r\n\treturn 1L;\r\n}" == bodyCode
);
}
}
}
1 change: 1 addition & 0 deletions src/Tests/Peachpie.App.Tests/Peachpie.App.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="ICSharpCode.Decompiler" Version="8.2.0.7535" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.3.0" />
<PackageReference Include="MSTest.TestAdapter" Version="2.0.0" />
<PackageReference Include="MSTest.TestFramework" Version="2.0.0" />
Expand Down

0 comments on commit e26c914

Please sign in to comment.