using System.Text.Json; using w4c_workflows.Services.Execution; using Xunit; namespace w4c_workflows.Tests; public class CSharpScriptExecutorTests { private readonly CSharpScriptExecutor _executor = new(); [Fact] public async Task Executes_program_with_string_input() { using var dir = new TempDir(); dir.Write("Program.cs", """ using System.Text.Json; public static class Program { public static object Main(string input) { using var doc = JsonDocument.Parse(input); var n = doc.RootElement.GetProperty("n").GetInt32(); return new { squared = n * n }; } } """); var result = await _executor.ExecuteAsync( Invocation.For("csharp", "Program.cs", "{\"n\":5}", dir.Path), default); Assert.True(result.Success, result.Error); Assert.NotNull(result.Output); using var output = JsonDocument.Parse(result.Output!); Assert.Equal(25, output.RootElement.GetProperty("squared").GetInt32()); } [Fact] public async Task Executes_multi_file_program() { using var dir = new TempDir(); dir.Write("Helper.cs", """ public static class Helper { public static int Add(int a, int b) => a + b; } """); dir.Write("Program.cs", """ using System.Text.Json; public static class Program { public static object Main(string input) { using var doc = JsonDocument.Parse(input); var a = doc.RootElement.GetProperty("a").GetInt32(); var b = doc.RootElement.GetProperty("b").GetInt32(); return new { sum = Helper.Add(a, b) }; } } """); var result = await _executor.ExecuteAsync( Invocation.For("csharp", "Program.cs", "{\"a\":2,\"b\":3}", dir.Path), default); Assert.True(result.Success, result.Error); using var output = JsonDocument.Parse(result.Output!); Assert.Equal(5, output.RootElement.GetProperty("sum").GetInt32()); } [Fact] public async Task Supports_custom_entry_function_name() { using var dir = new TempDir(); dir.Write("Program.cs", """ public static class Program { public static object Transform(string input) => new { echo = input }; } """); var result = await _executor.ExecuteAsync( Invocation.For("csharp", "Program.cs", "{\"x\":1}", dir.Path, entryFunction: "Transform"), default); Assert.True(result.Success, result.Error); using var output = JsonDocument.Parse(result.Output!); Assert.Equal("{\"x\":1}", output.RootElement.GetProperty("echo").GetString()); } [Fact] public async Task Supports_async_entry() { using var dir = new TempDir(); dir.Write("Program.cs", """ using System.Threading.Tasks; public static class Program { public static async Task Main(string input) { await Task.Yield(); return new { ok = true }; } } """); var result = await _executor.ExecuteAsync( Invocation.For("csharp", "Program.cs", "{}", dir.Path), default); Assert.True(result.Success, result.Error); Assert.Contains("\"ok\":true", result.Output); } [Fact] public async Task Fails_with_compile_error() { using var dir = new TempDir(); dir.Write("Program.cs", "public static class Program { public static object Main(string input) { return ; } }"); var result = await _executor.ExecuteAsync( Invocation.For("csharp", "Program.cs", "{}", dir.Path), default); Assert.False(result.Success); Assert.Contains("compilation failed", result.Error, StringComparison.OrdinalIgnoreCase); } [Fact] public async Task Fails_when_entry_method_missing() { using var dir = new TempDir(); dir.Write("Program.cs", "public static class Program { public static int NotTheEntry() => 1; }"); var result = await _executor.ExecuteAsync( Invocation.For("csharp", "Program.cs", "{}", dir.Path), default); Assert.False(result.Success); Assert.Contains("no static entry method", result.Error); } }