Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion aelf.tools/AElf.Tools.Test/AElf.Tools.Test.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

Expand All @@ -22,6 +22,7 @@
<PackageReference Include="coverlet.collector" Version="3.1.2" />
<PackageReference Include="Moq" Version="4.8.3" />
<PackageReference Include="NUnitLite" Version="3.13.3" />
<PackageReference Include="protobuf-net" Version="3.2.30" />
</ItemGroup>

</Project>
154 changes: 154 additions & 0 deletions aelf.tools/AElf.Tools.Test/ProtobufNetGeneratorTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
using NUnit.Framework;
using ProtoBuf;
using System.IO;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Moq;
using System;
using System.Collections.Generic;

namespace AElf.Tools.Test
{
public class ProtobufNetGeneratorTest
{
private Mock<IBuildEngine> _mockEngine;
private Mock<ITask> _mockTask;
private TaskLoggingHelper _logger;

[SetUp]
public void Setup()
{
_mockEngine = new Mock<IBuildEngine>();
_mockTask = new Mock<ITask>();
_mockTask.Setup(t => t.BuildEngine).Returns(_mockEngine.Object);

_logger = new TaskLoggingHelper(_mockTask.Object);

if (!Directory.Exists("output"))
{
Directory.CreateDirectory("output");
}
}

[Test]
public void GenerateCode_ValidProtoFile_GeneratesValidCSharp()
{
// Arrange
var protoContent = @"
syntax = ""proto3"";
package test;
message TestMessage {
string name = 1;
int32 id = 2;
}";
var protoFile = "test.proto";
File.WriteAllText(protoFile, protoContent);

// Act
var generator = new ProtoGenerator(_logger);
var result = generator.GenerateCode(protoFile, "output");

// Assert
Assert.That(result, Is.True, "Code generation should succeed");
var generatedCode = File.ReadAllText("output/test.generated.cs");
Assert.That(generatedCode, Does.Contain("public class TestMessage"));
Assert.That(generatedCode, Does.Contain("public string Name"));
Assert.That(generatedCode, Does.Contain("public int Id"));
}

[Test]
public void GenerateCode_WithNestedMessage_GeneratesNestedClasses()
{
// Arrange
var protoContent = @"
syntax = ""proto3"";
package test;
message Outer {
message Inner {
string name = 1;
}
Inner inner = 1;
}";
var protoFile = "nested.proto";
File.WriteAllText(protoFile, protoContent);

// Act
var generator = new ProtoGenerator(_logger);
var result = generator.GenerateCode(protoFile, "output");

// Assert
Assert.That(result, Is.True, "Code generation should succeed");
var generatedCode = File.ReadAllText("output/nested.generated.cs");
Assert.That(generatedCode, Does.Contain("public class Outer"));
Assert.That(generatedCode, Does.Contain("public class Inner"));
Assert.That(generatedCode, Does.Contain("public Inner InnerMessage"));
}

[Test]
public void GenerateCode_WithService_GeneratesServiceInterface()
{
// Arrange
var protoContent = @"
syntax = ""proto3"";
package test;
message Request { string data = 1; }
message Response { string result = 1; }
service TestService {
rpc TestMethod (Request) returns (Response);
}";
var protoFile = "service.proto";
File.WriteAllText(protoFile, protoContent);

// Capture logs
var loggedMessages = new List<string>();
var loggedErrors = new List<string>();
_mockEngine.Setup(e => e.LogMessageEvent(It.IsAny<BuildMessageEventArgs>()))
.Callback<BuildMessageEventArgs>(e => loggedMessages.Add(e.Message));
_mockEngine.Setup(e => e.LogErrorEvent(It.IsAny<BuildErrorEventArgs>()))
.Callback<BuildErrorEventArgs>(e => loggedErrors.Add(e.Message));

// Act
var generator = new ProtoGenerator(_logger);
var result = generator.GenerateCode(protoFile, "output");

foreach (var msg in loggedMessages)
{
Console.WriteLine($" {msg}");
}
Console.WriteLine("Logged Errors:");
foreach (var err in loggedErrors)
{
Console.WriteLine($" {err}");
}

// Assert
Assert.That(result, Is.True, $"Code generation failed. Errors: {string.Join(Environment.NewLine, loggedErrors)}");
var generatedCode = File.ReadAllText("output/service.generated.cs");
Assert.That(generatedCode, Does.Contain("public interface ITestService"));
Assert.That(generatedCode, Does.Contain("Task<Response> TestMethodAsync"));
}

[TearDown]
public void Cleanup()
{
// Clean up test proto files
var testFiles = new[] { "test.proto", "nested.proto", "enum.proto", "service.proto" };
foreach (var file in testFiles)
{
if (File.Exists(file))
{
File.Delete(file);
}
var generatedFile = Path.Combine("output", Path.GetFileNameWithoutExtension(file) + ".generated.cs");
if (File.Exists(generatedFile))
{
File.Delete(generatedFile);
}
}
if (Directory.Exists("output"))
{
Directory.Delete("output", true);
}
}
}
}
73 changes: 73 additions & 0 deletions aelf.tools/AElf.Tools.Test/ProtobufNetSerializationTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
using NUnit.Framework;
using ProtoBuf;
using System.IO;

namespace AElf.Tools.Test
{
[ProtoContract]
public class TestProtoMessage
{
[ProtoMember(1)]
public string Name { get; set; }

[ProtoMember(2)]
public int Id { get; set; }
}

public class ProtobufNetSerializationTest
{
[Test]
public void Serialize_ValidMessage_CanBeDeserialized()
{
// Arrange
var message = new TestProtoMessage
{
Name = "Test",
Id = 123
};

// Act
byte[] serialized;
using (var ms = new MemoryStream())
{
Serializer.Serialize(ms, message);
serialized = ms.ToArray();
}

TestProtoMessage deserialized;
using (var ms = new MemoryStream(serialized))
{
deserialized = Serializer.Deserialize<TestProtoMessage>(ms);
}

// Assert
Assert.That(deserialized.Name, Is.EqualTo("Test"));
Assert.That(deserialized.Id, Is.EqualTo(123));
}

[Test]
public void Serialize_EmptyMessage_CanBeDeserialized()
{
// Arrange
var message = new TestProtoMessage();

// Act
byte[] serialized;
using (var ms = new MemoryStream())
{
Serializer.Serialize(ms, message);
serialized = ms.ToArray();
}

TestProtoMessage deserialized;
using (var ms = new MemoryStream(serialized))
{
deserialized = Serializer.Deserialize<TestProtoMessage>(ms);
}

// Assert
Assert.That(deserialized.Name, Is.Null);
Assert.That(deserialized.Id, Is.EqualTo(0));
}
}
}
10 changes: 6 additions & 4 deletions aelf.tools/AElf.Tools/AElf.Tools.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
<PropertyGroup>
<AssemblyName>AElf.Tools</AssemblyName>
<VersionPrefix>$(AElfToolsVersion)</VersionPrefix>
<!-- If changing targets, change also paths in Google.Protobuf.Tools.targets. -->
<TargetFrameworks>net46;netstandard1.3</TargetFrameworks>
<!-- Update target frameworks to be compatible with protobuf-net -->
<TargetFrameworks>net462;netstandard2.0</TargetFrameworks>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<LangVersion>latest</LangVersion>
</PropertyGroup>

<PropertyGroup Condition=" '$(TargetFramework)' != 'net46' ">
<PropertyGroup Condition=" '$(TargetFramework)' != 'net462' ">
<DefineConstants>$(DefineConstants);NETCORE</DefineConstants>
</PropertyGroup>

Expand All @@ -32,6 +32,8 @@
<ItemGroup>
<PackageReference Include="Microsoft.Build.Framework" Version="15.6.85" />
<PackageReference Include="Microsoft.Build.Utilities.Core" Version="15.6.85" />
<PackageReference Include="protobuf-net" Version="3.2.30" />
<PackageReference Include="Google.Protobuf" Version="3.21.1" />
</ItemGroup>

<ItemGroup Label="NuGet package assets">
Expand All @@ -51,7 +53,7 @@
</None>
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'net46'">
<ItemGroup Condition="'$(TargetFramework)' == 'net462'">
<PackageReference Include="Mono.Cecil" Version="0.10.3" />
</ItemGroup>

Expand Down
38 changes: 14 additions & 24 deletions aelf.tools/AElf.Tools/ProtoCompile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
using System.Text.RegularExpressions;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using System.IO;

namespace AElf.Tools
{
Expand Down Expand Up @@ -608,34 +609,23 @@ protected override void LogEventsFromTextOutput(string singleLine, MessageImport
// Main task entry point.
public override bool Execute()
{
base.UseCommandProcessor = false;
var generator = new ProtoGenerator(Log);
bool success = true;

bool ok = base.Execute();
if (!ok)
{
return false;
}

// Read dependency output file from the compiler to retrieve the
// definitive list of created files. Report the dependency file
// itself as having been written to.
if (DependencyOut != null)
foreach (var proto in Protobuf)
{
string[] outputs = DepFileUtil.ReadDependencyOutputs(DependencyOut, Log);
if (HasLoggedErrors)
{
return false;
}

GeneratedFiles = new ITaskItem[outputs.Length];
for (int i = 0; i < outputs.Length; i++)
{
GeneratedFiles[i] = new TaskItem(outputs[i]);
}
AdditionalFileWrites = new ITaskItem[] { new TaskItem(DependencyOut) };
// Create output directory if it doesn't exist
Directory.CreateDirectory(OutputDir);

// Generate code using protobuf-net
success &= generator.GenerateCode(
proto.ItemSpec,
OutputDir,
Generator.ToLowerInvariant()
);
}

return true;
return success;
}

class ErrorListFilter
Expand Down
Loading