forked from planetarium/libplanet
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request planetarium#3935 from planetarium/exp/sdk/action-l…
…oader Action loader from external assembly
- Loading branch information
Showing
33 changed files
with
493 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
57 changes: 57 additions & 0 deletions
57
sdk/node/Libplanet.Node.Tests/Services/ActionServiceTest.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
using Libplanet.Action; | ||
using Libplanet.Action.Loader; | ||
using Libplanet.Node.Options; | ||
using Libplanet.Node.Services; | ||
using Microsoft.Extensions.DependencyInjection; | ||
|
||
namespace Libplanet.Node.Tests.Services; | ||
|
||
public class ActionServiceTest(TempDirectoryFixture tempDirectoryFixture) | ||
: IClassFixture<TempDirectoryFixture> | ||
{ | ||
private readonly TempDirectoryFixture _tempDirectoryFixture = tempDirectoryFixture; | ||
|
||
[Fact] | ||
public void Base_Test() | ||
{ | ||
var serviceProvider = TestUtility.CreateServiceProvider(); | ||
var actionService = serviceProvider.GetRequiredService<IActionService>(); | ||
|
||
Assert.IsType<AggregateTypedActionLoader>(actionService.ActionLoader); | ||
Assert.IsType<PolicyActionsRegistry>(actionService.PolicyActionsRegistry); | ||
} | ||
|
||
[Fact] | ||
public void Base_WithModulePath_Test() | ||
{ | ||
var actionLoaderType = "Libplanet.Node.DumbActions.DumbActionLoader"; | ||
var policyActionRegistryType = "Libplanet.Node.DumbActions.DumbActionPolicyActionsRegistry"; | ||
var codePath = "Libplanet.Node.Tests.Services.ActionServiceTestSource.cs"; | ||
var codeStream = typeof(ActionServiceTest).Assembly.GetManifestResourceStream(codePath) | ||
?? throw new FileNotFoundException($"Resource '{codePath}' not found."); | ||
using var reader = new StreamReader(codeStream); | ||
var code = reader.ReadToEnd(); | ||
var assemblyName = Path.GetRandomFileName(); | ||
var assemblyPath = $"{_tempDirectoryFixture.GetRandomFileName()}.dll"; | ||
|
||
var settings = new Dictionary<string, string?> | ||
{ | ||
[$"{ActionOptions.Position}:{nameof(ActionOptions.ModulePath)}"] | ||
= assemblyPath, | ||
[$"{ActionOptions.Position}:{nameof(ActionOptions.ActionLoaderType)}"] | ||
= actionLoaderType, | ||
[$"{ActionOptions.Position}:{nameof(ActionOptions.PolicyActionRegistryType)}"] | ||
= policyActionRegistryType, | ||
}; | ||
|
||
RuntimeCompiler.CompileCode(code, assemblyName, assemblyPath); | ||
|
||
var serviceProvider = TestUtility.CreateServiceProvider(settings); | ||
var actionService = serviceProvider.GetRequiredService<IActionService>(); | ||
|
||
Assert.Equal(actionLoaderType, actionService.ActionLoader.GetType().FullName); | ||
Assert.Equal( | ||
expected: policyActionRegistryType, | ||
actual: actionService.PolicyActionsRegistry.GetType().FullName); | ||
} | ||
} |
63 changes: 63 additions & 0 deletions
63
sdk/node/Libplanet.Node.Tests/Services/ActionServiceTestSource.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// This code does not compile because it is used by ActionServiceTest test. | ||
#pragma warning disable MEN008 // A file's name should match or include the name of the main type it contains. | ||
using System.Collections.Immutable; | ||
using Bencodex.Types; | ||
using Libplanet.Action; | ||
using Libplanet.Action.Loader; | ||
using Libplanet.Action.State; | ||
using Libplanet.Action.Sys; | ||
|
||
namespace Libplanet.Node.DumbActions; | ||
|
||
public class DumbAction : IAction | ||
{ | ||
public IValue PlainValue => Dictionary.Empty; | ||
|
||
public void LoadPlainValue(IValue plainValue) | ||
{ | ||
// Do nothing. | ||
} | ||
|
||
public IWorld Execute(IActionContext context) => | ||
context.PreviousState; | ||
} | ||
|
||
public sealed class DumbBeginAction : DumbAction | ||
{ | ||
} | ||
|
||
public sealed class DumbEndAction : DumbAction | ||
{ | ||
} | ||
|
||
public sealed class DumbBeginTxAction : DumbAction | ||
{ | ||
} | ||
|
||
public sealed class DumbEndTxAction : DumbAction | ||
{ | ||
} | ||
|
||
public sealed class DumbActionLoader : IActionLoader | ||
{ | ||
public IAction LoadAction(long index, IValue value) | ||
{ | ||
if (Registry.IsSystemAction(value)) | ||
{ | ||
return Registry.Deserialize(value); | ||
} | ||
|
||
return new DumbAction(); | ||
} | ||
} | ||
|
||
public sealed class DumbActionPolicyActionsRegistry : IPolicyActionsRegistry | ||
{ | ||
public ImmutableArray<IAction> BeginBlockActions => [new DumbBeginAction()]; | ||
|
||
public ImmutableArray<IAction> EndBlockActions => [new DumbEndAction()]; | ||
|
||
public ImmutableArray<IAction> BeginTxActions => [new DumbBeginTxAction()]; | ||
|
||
public ImmutableArray<IAction> EndTxActions => [new DumbEndTxAction()]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
using System.Reflection; | ||
using System.Runtime.InteropServices; | ||
using System.Text; | ||
using Bencodex.Types; | ||
using Libplanet.Action; | ||
using Microsoft.CodeAnalysis; | ||
using Microsoft.CodeAnalysis.CSharp; | ||
|
||
namespace Libplanet.Node.Tests.Services; | ||
|
||
internal static class RuntimeCompiler | ||
{ | ||
public static void CompileCode(string code, string assemblyName, string assemblyPath) | ||
{ | ||
var syntaxTree = CSharpSyntaxTree.ParseText(code); | ||
var references = new MetadataReference[] | ||
{ | ||
MetadataReference.CreateFromFile(typeof(object).Assembly.Location), | ||
MetadataReference.CreateFromFile(typeof(IAction).Assembly.Location), | ||
MetadataReference.CreateFromFile(typeof(IValue).Assembly.Location), | ||
MetadataReference.CreateFromFile(GetRuntimeLibraryPath("netstandard.dll")), | ||
MetadataReference.CreateFromFile(GetRuntimeLibraryPath("System.Runtime.dll")), | ||
MetadataReference.CreateFromFile( | ||
GetRuntimeLibraryPath("System.Collections.Immutable.dll")), | ||
}; | ||
|
||
var options = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary); | ||
var compilation = CSharpCompilation.Create( | ||
assemblyName, [syntaxTree], references, options); | ||
|
||
// 어셈블리 스트림 생성 | ||
using var fs = new FileStream(assemblyPath, FileMode.Create); | ||
var result = compilation.Emit(fs); | ||
|
||
if (!result.Success) | ||
{ | ||
var sb = new StringBuilder(); | ||
sb.AppendLine("Compilation failed."); | ||
foreach (var diagnostic in result.Diagnostics) | ||
{ | ||
sb.AppendLine(diagnostic.ToString()); | ||
} | ||
|
||
throw new InvalidOperationException(sb.ToString()); | ||
} | ||
|
||
fs.Close(); | ||
} | ||
|
||
private static string GetRuntimeLibraryPath(string name) | ||
=> Path.Combine(RuntimeEnvironment.GetRuntimeDirectory(), name); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
namespace Libplanet.Node.Tests; | ||
|
||
public sealed class TempDirectoryFixture : IDisposable | ||
{ | ||
public TempDirectoryFixture() | ||
{ | ||
TempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); | ||
Directory.CreateDirectory(TempDirectory); | ||
} | ||
|
||
public string TempDirectory { get; } | ||
|
||
public string GetRandomFileName() | ||
{ | ||
if (!Directory.Exists(TempDirectory)) | ||
{ | ||
Directory.CreateDirectory(TempDirectory); | ||
} | ||
|
||
return Path.Combine(TempDirectory, Path.GetRandomFileName()); | ||
} | ||
|
||
public void Dispose() | ||
{ | ||
if (Directory.Exists(TempDirectory)) | ||
{ | ||
try | ||
{ | ||
Directory.Delete(TempDirectory, true); | ||
} | ||
catch (UnauthorizedAccessException) | ||
{ | ||
// ignore | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
using System.Reflection; | ||
using System.Runtime.Loader; | ||
|
||
namespace Libplanet.Node.Actions; | ||
|
||
internal sealed class PluginLoadContext(string pluginPath) : AssemblyLoadContext | ||
{ | ||
private readonly AssemblyDependencyResolver _resolver = new(pluginPath); | ||
|
||
protected override Assembly? Load(AssemblyName assemblyName) | ||
{ | ||
var assemblyPath = _resolver.ResolveAssemblyToPath(assemblyName); | ||
if (assemblyPath is not null) | ||
{ | ||
return LoadFromAssemblyPath(assemblyPath); | ||
} | ||
|
||
return null; | ||
} | ||
|
||
protected override IntPtr LoadUnmanagedDll(string unmanagedDllName) | ||
{ | ||
var libraryPath = _resolver.ResolveUnmanagedDllToPath(unmanagedDllName); | ||
if (libraryPath is not null) | ||
{ | ||
return LoadUnmanagedDllFromPath(libraryPath); | ||
} | ||
|
||
return IntPtr.Zero; | ||
} | ||
} |
Oops, something went wrong.