253 lines
6.8 KiB
C#
253 lines
6.8 KiB
C#
using FluentAssertions;
|
|
using MarketAlly.IronGo;
|
|
using MarketAlly.IronGo.AST;
|
|
using MarketAlly.IronGo.Serialization;
|
|
using System.Text.Json;
|
|
using Xunit;
|
|
|
|
namespace MarketAlly.IronGo.Tests.SerializationTests;
|
|
|
|
public class JsonSerializationTests
|
|
{
|
|
[Fact]
|
|
public void ToJson_ShouldSerializeSimpleAST()
|
|
{
|
|
// Arrange
|
|
const string source = @"
|
|
package main
|
|
|
|
func hello() {
|
|
println(""Hello, World!"")
|
|
}";
|
|
|
|
var ast = IronGoParser.Parse(source);
|
|
|
|
// Act
|
|
var json = ast.ToJson();
|
|
|
|
// Assert
|
|
json.Should().NotBeNullOrWhiteSpace();
|
|
json.Should().Contain("\"Type\": \"SourceFile\"");
|
|
json.Should().Contain("\"Package\":");
|
|
json.Should().Contain("\"Name\": \"main\"");
|
|
json.Should().Contain("\"Declarations\":");
|
|
json.Should().Contain("\"Type\": \"FunctionDeclaration\"");
|
|
json.Should().Contain("\"Name\": \"hello\"");
|
|
}
|
|
|
|
[Fact]
|
|
public void ToJsonCompact_ShouldProduceCompactJson()
|
|
{
|
|
// Arrange
|
|
const string source = "package main";
|
|
var ast = IronGoParser.Parse(source);
|
|
|
|
// Act
|
|
var compact = ast.ToJsonCompact();
|
|
var pretty = ast.ToJsonPretty();
|
|
|
|
// Assert
|
|
compact.Should().NotContain("\n");
|
|
compact.Should().NotContain(" ");
|
|
pretty.Should().Contain("\n");
|
|
pretty.Should().Contain(" ");
|
|
compact.Length.Should().BeLessThan(pretty.Length);
|
|
}
|
|
|
|
[Fact]
|
|
public void SerializeExpression_ShouldHandleComplexExpressions()
|
|
{
|
|
// Arrange
|
|
const string source = @"
|
|
package main
|
|
|
|
func test() {
|
|
result := (a + b) * c / d
|
|
}";
|
|
|
|
var ast = IronGoParser.Parse(source);
|
|
var function = ast.Declarations[0] as FunctionDeclaration;
|
|
var statement = function!.Body!.Statements[0] as ShortVariableDeclaration;
|
|
var expression = statement!.Values[0];
|
|
|
|
// Act
|
|
var json = expression.ToJson();
|
|
var doc = JsonDocument.Parse(json);
|
|
|
|
// Assert
|
|
doc.RootElement.GetProperty("Type").GetString().Should().Be("BinaryExpression");
|
|
doc.RootElement.GetProperty("Operator").GetString().Should().Be("Divide");
|
|
doc.RootElement.GetProperty("Left").GetProperty("Type").GetString().Should().Be("BinaryExpression");
|
|
}
|
|
|
|
[Fact]
|
|
public void SerializeTypes_ShouldHandleAllTypeVariants()
|
|
{
|
|
// Arrange
|
|
const string source = @"
|
|
package main
|
|
|
|
type (
|
|
Int int
|
|
Ptr *int
|
|
Slice []string
|
|
Array [10]byte
|
|
Map map[string]int
|
|
Chan chan int
|
|
Func func(int) error
|
|
Struct struct { X, Y int }
|
|
Interface interface { Method() }
|
|
)";
|
|
|
|
var ast = IronGoParser.Parse(source);
|
|
|
|
// Act
|
|
var json = ast.ToJson();
|
|
|
|
// Assert
|
|
json.Should().Contain("\"Type\": \"IdentifierType\"");
|
|
json.Should().Contain("\"Type\": \"PointerType\"");
|
|
json.Should().Contain("\"Type\": \"SliceType\"");
|
|
json.Should().Contain("\"Type\": \"ArrayType\"");
|
|
json.Should().Contain("\"Type\": \"MapType\"");
|
|
json.Should().Contain("\"Type\": \"ChannelType\"");
|
|
json.Should().Contain("\"Type\": \"FunctionType\"");
|
|
json.Should().Contain("\"Type\": \"StructType\"");
|
|
json.Should().Contain("\"Type\": \"InterfaceType\"");
|
|
}
|
|
|
|
[Fact]
|
|
public void SerializeStatements_ShouldHandleAllStatementTypes()
|
|
{
|
|
// Arrange
|
|
const string source = @"
|
|
package main
|
|
|
|
func test() {
|
|
x := 10
|
|
var y int
|
|
if x > 5 { }
|
|
for i := 0; i < 10; i++ { }
|
|
switch x { case 1: }
|
|
defer cleanup()
|
|
go process()
|
|
return x
|
|
break
|
|
continue
|
|
}";
|
|
|
|
var ast = IronGoParser.Parse(source);
|
|
var function = ast.Declarations[0] as FunctionDeclaration;
|
|
|
|
// Act
|
|
var json = function!.Body!.ToJson();
|
|
|
|
// Assert
|
|
json.Should().Contain("\"Type\": \"ShortVariableDeclaration\"");
|
|
json.Should().Contain("\"Type\": \"DeclarationStatement\"");
|
|
json.Should().Contain("\"Type\": \"IfStatement\"");
|
|
json.Should().Contain("\"Type\": \"ForStatement\"");
|
|
json.Should().Contain("\"Type\": \"SwitchStatement\"");
|
|
json.Should().Contain("\"Type\": \"DeferStatement\"");
|
|
json.Should().Contain("\"Type\": \"GoStatement\"");
|
|
json.Should().Contain("\"Type\": \"ReturnStatement\"");
|
|
json.Should().Contain("\"Type\": \"BranchStatement\"");
|
|
}
|
|
|
|
[Fact]
|
|
public void SerializeLiterals_ShouldPreserveValues()
|
|
{
|
|
// Arrange
|
|
const string source = @"
|
|
package main
|
|
|
|
func test() {
|
|
s := ""hello""
|
|
i := 42
|
|
f := 3.14
|
|
b := true
|
|
r := 'x'
|
|
}";
|
|
|
|
var ast = IronGoParser.Parse(source);
|
|
|
|
// Act
|
|
var json = ast.ToJson();
|
|
var doc = JsonDocument.Parse(json);
|
|
|
|
// Assert
|
|
json.Should().Contain("\"Value\": \"hello\"");
|
|
json.Should().Contain("\"Value\": \"42\"");
|
|
json.Should().Contain("\"Value\": \"3.14\"");
|
|
json.Should().Contain("\"Value\": \"true\"");
|
|
json.Should().Contain("\"Value\": \"x\"");
|
|
}
|
|
|
|
[Fact]
|
|
public void SerializePosition_ShouldIncludePositionInfo()
|
|
{
|
|
// Arrange
|
|
const string source = "package main";
|
|
var ast = IronGoParser.Parse(source);
|
|
|
|
// Act
|
|
var json = ast.Package!.ToJson();
|
|
var doc = JsonDocument.Parse(json);
|
|
|
|
// Assert
|
|
doc.RootElement.TryGetProperty("Start", out _).Should().BeTrue();
|
|
doc.RootElement.TryGetProperty("End", out _).Should().BeTrue();
|
|
|
|
var start = doc.RootElement.GetProperty("Start");
|
|
start.GetProperty("Line").GetInt32().Should().Be(1);
|
|
start.GetProperty("Column").GetInt32().Should().Be(1);
|
|
}
|
|
|
|
[Fact]
|
|
public void SerializeComments_ShouldIncludeComments()
|
|
{
|
|
// Arrange
|
|
const string source = @"
|
|
package main
|
|
|
|
// HelloWorld prints a greeting
|
|
func HelloWorld() {
|
|
// Print to stdout
|
|
println(""Hello, World!"")
|
|
}";
|
|
|
|
var ast = IronGoParser.Parse(source);
|
|
var function = ast.Declarations[0] as FunctionDeclaration;
|
|
|
|
// Act
|
|
var json = function!.ToJson();
|
|
|
|
// Assert
|
|
// Comments would be included if properly parsed
|
|
json.Should().Contain("HelloWorld");
|
|
}
|
|
|
|
[Fact]
|
|
public void RoundTrip_ShouldProduceSameJson()
|
|
{
|
|
// Arrange
|
|
const string source = @"
|
|
package main
|
|
|
|
import ""fmt""
|
|
|
|
func main() {
|
|
fmt.Println(""test"")
|
|
}";
|
|
|
|
// Act
|
|
var ast1 = IronGoParser.Parse(source);
|
|
var json1 = ast1.ToJson();
|
|
|
|
var ast2 = IronGoParser.Parse(source);
|
|
var json2 = ast2.ToJson();
|
|
|
|
// Assert
|
|
json1.Should().Be(json2);
|
|
}
|
|
} |