diff --git a/.github/workflows/ci_standard.yaml b/.github/workflows/ci_standard.yaml index 83c0e84b..e81f809a 100644 --- a/.github/workflows/ci_standard.yaml +++ b/.github/workflows/ci_standard.yaml @@ -114,17 +114,22 @@ jobs: flag-name: coverage-windows-${{ join(matrix.*, '-') }} fail-on-error: false + - name: Add lib folders to path + shell: pwsh + run: | + $env:PATH = "${{ github.workspace }}\ext\OpenDDS_${{ matrix.BuildPlatform }}\lib;${{ github.workspace }}\ext\OpenDDS_${{ matrix.BuildPlatform }}\ACE_wrappers\lib;$env:PATH" + echo "PATH=$env:PATH" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append + - name: Latency Performance Test shell: cmd run: | - set PATH="${{ github.workspace }}\ext\OpenDDS_${{ matrix.BuildPlatform }}\lib;${{ github.workspace }}\ext\OpenDDS_${{ matrix.BuildPlatform }}\ACE_wrappers\lib;%PATH%" dotnet clean ${{ github.workspace }}\Tests\TestIdlCdr\TestIdlCdr.csproj dotnet clean ${{ github.workspace }}\Tests\BenchmarkPerformance\BenchmarkPerformance.csproj dotnet restore ${{ github.workspace }}\Tests\TestIdlCdr\TestIdlCdr.csproj dotnet restore ${{ github.workspace }}\Tests\BenchmarkPerformance\BenchmarkPerformance.csproj dotnet build -m:1 ${{ github.workspace }}\Tests\TestIdlCdr\TestIdlCdr.csproj --configuration Release --runtime win-${{ matrix.BuildPlatform }} dotnet build -m:1 ${{ github.workspace }}\Tests\BenchmarkPerformance\BenchmarkPerformance.csproj --configuration Release --runtime win-${{ matrix.BuildPlatform }} - dotnet run ${{ github.workspace }}\Tests\BenchmarkPerformance\BenchmarkPerformance.csproj 1 --configuration Release --runtime win-${{ matrix.BuildPlatform }} + dotnet run ${{ github.workspace }}\Tests\BenchmarkPerformance\BenchmarkPerformance.csproj -1 --configuration Release --runtime win-${{ matrix.BuildPlatform }} env: DDS_ROOT: "${{ github.workspace }}\\ext\\OpenDDS_${{ matrix.BuildPlatform }}" ACE_ROOT: "${{ github.workspace }}\\ext\\OpenDDS_${{ matrix.BuildPlatform }}\\ACE_wrappers" @@ -228,21 +233,6 @@ jobs: ACE_ROOT: "${{ github.workspace }}/ext/OpenDDS_Linux/ACE_wrappers" TAO_ROOT: "${{ github.workspace }}/ext/OpenDDS_Linux/ACE_wrappers/TAO" - - name: Latency Performance Test - shell: bash - run: | - dotnet build ${{ github.workspace }}/Tests/TestIdlCdr/TestIdlCdr.csproj --configuration Release --runtime linux-x64 - dotnet build ${{ github.workspace }}/Tests/BenchmarkPerformance/BenchmarkPerformance.csproj --configuration Release --runtime linux-x64 - dotnet publish ${{ github.workspace }}/Tests/BenchmarkPerformance/BenchmarkPerformance.csproj --configuration Release --runtime linux-x64 - cd ${{ github.workspace }}/Tests/BenchmarkPerformance/bin/Release/net8.0/linux-x64/publish - sudo LD_LIBRARY_PATH=".:$LD_LIBRARY_PATH" ${{ github.workspace }}/Tests/BenchmarkPerformance/bin/Release/net8.0/linux-x64/publish/BenchmarkPerformance 1 - working-directory: ${{ github.workspace }} - env: - DDS_ROOT: "${{ github.workspace }}/ext/OpenDDS_Linux" - ACE_ROOT: "${{ github.workspace }}/ext/OpenDDS_Linux/ACE_wrappers" - TAO_ROOT: "${{ github.workspace }}/ext/OpenDDS_Linux/ACE_wrappers/TAO" - LD_LIBRARY_PATH: "${{ github.workspace }}/ext/OpenDDS_Linux/lib:${{ github.workspace }}/ext/OpenDDS_Linux/ACE_wrappers/lib:." - - name: Test OpenDDSharp shell: bash run: dotnet test ${{ github.workspace }}/Tests/OpenDDSharp.UnitTest/OpenDDSharp.UnitTest.csproj --no-build --no-restore --verbosity detailed --configuration ${{ env.BuildConfiguration }} --runtime linux-x64 --collect "XPlat code coverage" --logger "trx;LogFileName=test-results.trx" --logger "console;verbosity=detailed""console;verbosity=detailed" --settings ${{ github.workspace }}/Tests.runsettings --test-adapter-path "${{ github.workspace }}/packages/coverlet.collector/6.0.2/build/netstandard2.0/" @@ -276,6 +266,20 @@ jobs: flag-name: coverage-linux-x64-Release fail-on-error: false + - name: Latency Performance Test + shell: bash + run: | + dotnet build ${{ github.workspace }}/Tests/TestIdlCdr/TestIdlCdr.csproj --configuration Release --runtime linux-x64 + dotnet build ${{ github.workspace }}/Tests/BenchmarkPerformance/BenchmarkPerformance.csproj --configuration Release --runtime linux-x64 + dotnet publish ${{ github.workspace }}/Tests/BenchmarkPerformance/BenchmarkPerformance.csproj --configuration Release --runtime linux-x64 + cd ${{ github.workspace }}/Tests/BenchmarkPerformance/bin/Release/net8.0/linux-x64/publish + sudo LD_LIBRARY_PATH=".:$LD_LIBRARY_PATH" ${{ github.workspace }}/Tests/BenchmarkPerformance/bin/Release/net8.0/linux-x64/publish/BenchmarkPerformance -1 + working-directory: ${{ github.workspace }} + env: + DDS_ROOT: "${{ github.workspace }}/ext/OpenDDS_Linux" + ACE_ROOT: "${{ github.workspace }}/ext/OpenDDS_Linux/ACE_wrappers" + TAO_ROOT: "${{ github.workspace }}/ext/OpenDDS_Linux/ACE_wrappers/TAO" + build_macos_x64: runs-on: macos-13 @@ -414,7 +418,7 @@ jobs: sudo env DYLD_LIBRARY_PATH="./:$DYLD_LIBRARY_PATH" sudo env DYLD_FALLBACK_LIBRARY_PATH="./:$DYLD_FALLBACK_LIBRARY_PATH" cd ${{ github.workspace }}/Tests/BenchmarkPerformance/bin/Release/net8.0/osx-x64/publish - sudo -E ${{ github.workspace }}/Tests/BenchmarkPerformance/bin/Release/net8.0/osx-x64/publish/BenchmarkPerformance 1 + sudo -E ${{ github.workspace }}/Tests/BenchmarkPerformance/bin/Release/net8.0/osx-x64/publish/BenchmarkPerformance -1 working-directory: ${{ github.workspace }} build_macos_arm64: @@ -555,7 +559,7 @@ jobs: sudo env DYLD_LIBRARY_PATH="./:$DYLD_LIBRARY_PATH" sudo env DYLD_FALLBACK_LIBRARY_PATH="./:$DYLD_FALLBACK_LIBRARY_PATH" cd ${{ github.workspace }}/Tests/BenchmarkPerformance/bin/Release/net8.0/osx-arm64/publish - sudo -E ${{ github.workspace }}/Tests/BenchmarkPerformance/bin/Release/net8.0/osx-arm64/publish/BenchmarkPerformance 1 + sudo -E ${{ github.workspace }}/Tests/BenchmarkPerformance/bin/Release/net8.0/osx-arm64/publish/BenchmarkPerformance -1 working-directory: ${{ github.workspace }} publish_coveralls: diff --git a/Native/OpenDDSharp.IdlGenerator/csharp_cdr_generator.cpp b/Native/OpenDDSharp.IdlGenerator/csharp_cdr_generator.cpp index 031fc1f5..7ed11fd3 100644 --- a/Native/OpenDDSharp.IdlGenerator/csharp_cdr_generator.cpp +++ b/Native/OpenDDSharp.IdlGenerator/csharp_cdr_generator.cpp @@ -1196,7 +1196,7 @@ csharp_cdr_generator::implement_to_cdr_field(AST_Type *field_type, std::string f break; } case AST_Decl::NT_array: { - AST_Array *arr_type = dynamic_cast(field_type); + auto *arr_type = dynamic_cast(field_type); AST_Type *base_type = arr_type->base_type(); AST_Expression **dims = arr_type->dims(); AST_Decl::NodeType base_node_type = arr_type->base_type()->node_type(); @@ -1497,6 +1497,8 @@ csharp_cdr_generator::implement_to_cdr_field(AST_Type *field_type, std::string f ret.append(indent); ret.append(" }\n"); + } else { + ret.append(write_cdr_struct_multi_array(field_name, struct_type, dims, total_dim, indent)); } break; } @@ -2079,7 +2081,7 @@ csharp_cdr_generator::implement_from_cdr_field(AST_Type *field_type, std::string ret.append(indent); ret.append(" }\n"); } else { - ret.append(read_cdr_multi_array(field_name, replaceString(std::string(base_type->full_name()), std::string("::"), std::string(".")), "FromCDR", dims, total_dim, indent)); + ret.append(read_cdr_struct_multi_array(field_name, replaceString(std::string(base_type->full_name()), std::string("::"), std::string(".")), dims, total_dim, indent)); } break; } @@ -2162,9 +2164,13 @@ csharp_cdr_generator::read_cdr_multi_array(std::string name, std::string csharp_ ret.append("]["); } } - ret.append("] = reader."); - ret.append(read_method); - ret.append("();\n"); + if (read_method == "FromCDR") { + ret.append("].FromCDR(reader);\n"); + } else { + ret.append("] = reader."); + ret.append(read_method); + ret.append("();\n"); + } for (ACE_UINT32 i = 0; i < total_dim; i++) { loop_indent.erase(0, 4); @@ -2253,6 +2259,95 @@ csharp_cdr_generator::read_cdr_enum_multi_array(std::string name, std::string cs return ret; } +std::string +csharp_cdr_generator::read_cdr_struct_multi_array(std::string name, std::string csharp_base_type, AST_Expression **dims, int total_dim, std::string indent) +{ + std::string ret(" "); + + ret.append(name); + ret.append(" = new "); + ret.append(csharp_base_type); + ret.append("["); + ret.append(std::to_string(dims[0]->ev()->u.ulval)); + ret.append("]"); + for (unsigned int i = 1; i < total_dim; ++i) { + ret.append("[]"); + } + ret.append(";\n"); + + indent.append(" "); + std::string loop_indent(indent); + for (ACE_UINT32 i = 0; i < total_dim; i++) { + ret.append(loop_indent); + ret.append("for (int i"); + ret.append(std::to_string(i)); + ret.append(" = 0; i"); + ret.append(std::to_string(i)); + ret.append(" < "); + ret.append(std::to_string(dims[i]->ev()->u.ulval)); + ret.append("; ++i"); + ret.append(std::to_string(i)); + ret.append(") {\n"); + + loop_indent.append(" "); + + if (i + 1 < total_dim) { + ret.append(loop_indent); + ret.append(name); + for (unsigned int j = 0; j < i + 1; ++j) { + + ret.append("[i"); + ret.append(std::to_string(j)); + ret.append("]"); + } + ret.append(" = new "); + ret.append(csharp_base_type); + ret.append("["); + ret.append(std::to_string(dims[i + 1]->ev()->u.ulval)); + ret.append("]"); + for (unsigned int j = i + 2; j < total_dim; ++j) { + ret.append("[]"); + } + ret.append(";\n"); + } + } + + ret.append(loop_indent); + ret.append(name); + ret.append("["); + for (ACE_UINT32 i = 0; i < total_dim; i++) { + ret.append("i"); + ret.append(std::to_string(i)); + if (i + 1 < total_dim) { + ret.append("]["); + } + } + ret.append("] = new "); + ret.append(csharp_base_type); + ret.append("();\n"); + + + ret.append(loop_indent); + ret.append(name); + ret.append("["); + for (ACE_UINT32 i = 0; i < total_dim; i++) { + ret.append("i"); + ret.append(std::to_string(i)); + if (i + 1 < total_dim) { + ret.append("]["); + } + } + ret.append("].FromCDR(reader);\n"); + + for (ACE_UINT32 i = 0; i < total_dim; i++) { + loop_indent.erase(0, 4); + ret.append(loop_indent); + ret.append("}\n"); + } + + return ret; +} + std::string csharp_cdr_generator::write_cdr_multi_array(std::string name, std::string csharp_base_type, std::string write_method, AST_Expression **dims, int total_dim, std::string indent) { @@ -2342,5 +2437,79 @@ csharp_cdr_generator::write_cdr_enum_multi_array(std::string name, std::string c ret.append("}\n"); } + return ret; +} + +std::string +csharp_cdr_generator::write_cdr_struct_multi_array(std::string name, std::string csharp_base_type, AST_Expression **dims, int total_dim, std::string indent) +{ + std::string ret; + + indent.append(" "); + std::string loop_indent(indent); + for (ACE_UINT32 i = 0; i < total_dim; i++) { + ret.append(loop_indent); + ret.append("for (int i"); + ret.append(std::to_string(i)); + ret.append(" = 0; i"); + ret.append(std::to_string(i)); + ret.append(" < "); + ret.append(std::to_string(dims[i]->ev()->u.ulval)); + ret.append("; ++i"); + ret.append(std::to_string(i)); + ret.append(") {\n"); + + loop_indent.append(" "); + } + + ret.append(loop_indent); + ret.append("if ("); + ret.append(name); + for (ACE_UINT32 i = 0; i < total_dim; i++) { + ret.append("[i"); + ret.append(std::to_string(i)); + ret.append("]"); + } + ret.append(" == null)\n"); + + ret.append(loop_indent); + ret.append("{\n"); + + loop_indent.append(" "); + + ret.append(loop_indent); + ret.append(name); + for (ACE_UINT32 i = 0; i < total_dim; i++) { + ret.append("[i"); + ret.append(std::to_string(i)); + ret.append("]"); + } + ret.append(" = new "); + ret.append(csharp_base_type); + ret.append("();\n"); + + loop_indent.erase(0, 4); + + ret.append(loop_indent); + ret.append("}\n"); + + ret.append(loop_indent); + ret.append(name); + ret.append("["); + for (ACE_UINT32 i = 0; i < total_dim; i++) { + ret.append("i"); + ret.append(std::to_string(i)); + if (i + 1 < total_dim) { + ret.append("]["); + } + } + ret.append("].ToCDR(writer);\n"); + + for (ACE_UINT32 i = 0; i < total_dim; i++) { + loop_indent.erase(0, 4); + ret.append(loop_indent); + ret.append("}\n"); + } + return ret; } \ No newline at end of file diff --git a/Native/OpenDDSharp.IdlGenerator/csharp_cdr_generator.h b/Native/OpenDDSharp.IdlGenerator/csharp_cdr_generator.h index db29d2fb..4ff9358c 100644 --- a/Native/OpenDDSharp.IdlGenerator/csharp_cdr_generator.h +++ b/Native/OpenDDSharp.IdlGenerator/csharp_cdr_generator.h @@ -70,9 +70,13 @@ class csharp_cdr_generator : public dds_generator { std::string read_cdr_enum_multi_array(std::string name, std::string csharp_base_type, std::string read_method, AST_Expression **dims, int total_dim, std::string indent); + std::string read_cdr_struct_multi_array(std::string name, std::string csharp_base_type, AST_Expression **dims, int total_dim, std::string indent); + std::string write_cdr_multi_array(std::string name, std::string csharp_base_type, std::string write_method, AST_Expression **dims, int total_dim, std::string indent); std::string write_cdr_enum_multi_array(std::string name, std::string csharp_base_type, std::string write_method, AST_Expression **dims, int total_dim, std::string indent); + + std::string write_cdr_struct_multi_array(std::string name, std::string csharp_base_type, AST_Expression **dims, int total_dim, std::string indent); }; #endif diff --git a/Tests/BenchmarkPerformance/Program.cs b/Tests/BenchmarkPerformance/Program.cs index c8b049c3..eb32e0cb 100644 --- a/Tests/BenchmarkPerformance/Program.cs +++ b/Tests/BenchmarkPerformance/Program.cs @@ -61,14 +61,15 @@ Ace.Fini(); - var test1 = new RtiConnextLatencyTest(1000, 100, 2048); - stopwatch.Reset(); - stopwatch.Start(); - test1.Run(); - stopwatch.Stop(); - test1.Dispose(); - - Console.WriteLine($"RTI Connext Latency Test {stopwatch.Elapsed.TotalSeconds}"); + // // Requires RTI Connext DDS valid license. + // var test1 = new RtiConnextLatencyTest(1000, 100, 2048); + // stopwatch.Reset(); + // stopwatch.Start(); + // test1.Run(); + // stopwatch.Stop(); + // test1.Dispose(); + // + // Console.WriteLine($"RTI Connext Latency Test {stopwatch.Elapsed.TotalSeconds}"); break; case "1": { diff --git a/Tests/OpenDDSharp.UnitTest/CodeGeneratorCdrWrapperTest.cs b/Tests/OpenDDSharp.UnitTest/CodeGeneratorCdrWrapperTest.cs index 38aaab75..55477cda 100644 --- a/Tests/OpenDDSharp.UnitTest/CodeGeneratorCdrWrapperTest.cs +++ b/Tests/OpenDDSharp.UnitTest/CodeGeneratorCdrWrapperTest.cs @@ -2085,6 +2085,165 @@ public void TestGeneratedStructureArrays() } } + /// + /// Test the code generated for the multi-array of structures. + /// + [TestMethod] + [TestCategory(TEST_CATEGORY)] + public void TestGeneratedStructureMultiArrays() + { + using var evt = new ManualResetEventSlim(false); + + var typeSupport = new TestStructMultiArrayTypeSupport(); + var typeName = typeSupport.GetTypeName(); + var ret = typeSupport.RegisterType(_participant, typeName); + Assert.AreEqual(ReturnCode.Ok, ret); + + _topic = _participant.CreateTopic(TestContext.TestName, typeName); + Assert.IsNotNull(_topic); + + var drQos = new DataReaderQos + { + Reliability = + { + Kind = ReliabilityQosPolicyKind.ReliableReliabilityQos, + }, + }; + var dr = _subscriber.CreateDataReader(_topic, drQos); + Assert.IsNotNull(dr); + var dataReader = new TestStructMultiArrayDataReader(dr); + + var dw = _publisher.CreateDataWriter(_topic); + Assert.IsNotNull(dw); + var dataWriter = new TestStructMultiArrayDataWriter(dw); + + Assert.IsTrue(dataWriter.WaitForSubscriptions(1, 5000)); + Assert.IsTrue(dataReader.WaitForPublications(1, 5000)); + + var statusCondition = dr.StatusCondition; + Assert.IsNotNull(statusCondition); + statusCondition.EnabledStatuses = StatusKind.DataAvailableStatus; + TestHelper.CreateWaitSetThread(evt, statusCondition); + + var defaultStruct = new TestStructMultiArray(); + + var data = new TestStructMultiArray + { + StructMultiArrayField = new[] + { + new[] + { + new[] + { + new NestedStruct{ Id = 1, Message = "01" }, + new NestedStruct{ Id = 2, Message = "02" }, + }, + new[] + { + new NestedStruct { Id = 3, Message = "03" }, + new NestedStruct { Id = 4, Message = "04" }, + }, + new[] + { + new NestedStruct { Id = 5, Message = "05" }, + new NestedStruct { Id = 6, Message = "06" }, + }, + new[] + { + new NestedStruct { Id = 7, Message = "07" }, + new NestedStruct { Id = 8, Message = "08" }, + }, + }, + new[] + { + new[] + { + new NestedStruct { Id = 9, Message = "09" }, + new NestedStruct { Id = 10, Message = "10" }, + }, + new[] + { + new NestedStruct { Id = 11, Message = "11" }, + new NestedStruct { Id = 12, Message = "12" }, + }, + new[] + { + new NestedStruct { Id = 13, Message = "13" }, + new NestedStruct { Id = 14, Message = "14" }, + }, + new[] + { + new NestedStruct { Id = 15, Message = "15" }, + new NestedStruct{ Id = 16, Message = "16" }, + }, + }, + new[] + { + new[] + { + new NestedStruct{ Id = 17, Message = "17" }, + new NestedStruct{ Id = 18, Message = "18" }, + }, + new[] + { + new NestedStruct{ Id = 19, Message = "19" }, + new NestedStruct{ Id = 20, Message = "20" }, + }, + new[] + { + new NestedStruct{ Id = 21, Message = "21" }, + new NestedStruct{ Id = 22, Message = "22" }, + }, + new[] + { + new NestedStruct{ Id = 23, Message = "23" }, + new NestedStruct{ Id = 24, Message = "24" }, + }, + }, + }, + }; + + ret = dataWriter.Write(data); + Assert.AreEqual(ReturnCode.Ok, ret); + + ret = dataWriter.WaitForAcknowledgments(new Duration { Seconds = 5 }); + Assert.AreEqual(ReturnCode.Ok, ret); + + Assert.IsTrue(evt.Wait(1_500)); + + var received = new TestStructMultiArray(); + var sampleInfo = new SampleInfo(); + ret = dataReader.ReadNextSample(received, sampleInfo); + Assert.AreEqual(ReturnCode.Ok, ret); + + for (var i0 = 0; i0 < 3; i0++) + { + for (var i1 = 0; i1 < 4; i1++) + { + for (var i2 = 0; i2 < 2; i2++) + { + Assert.AreEqual(data.StructMultiArrayField[i0][i1][i2].Id, + received.StructMultiArrayField[i0][i1][i2].Id); + Assert.AreEqual(data.StructMultiArrayField[i0][i1][i2].Message, + received.StructMultiArrayField[i0][i1][i2].Message); + } + } + } + + Assert.AreEqual(typeof(NestedStruct[][][]), data.StructMultiArrayField.GetType()); + + for (var i0 = 0; i0 < 3; i0++) + { + for (var i1 = 0; i1 < 4; i1++) + { + for (var i2 = 0; i2 < 2; i2++) + { + Assert.IsNotNull(defaultStruct.StructMultiArrayField[i0][i1][i2]); + } + } + } + } + /// /// Test the code generated for the constants. /// diff --git a/Tests/TestIdlCdr/IDL/Test.idl b/Tests/TestIdlCdr/IDL/Test.idl index b443ab8b..e591f60b 100644 --- a/Tests/TestIdlCdr/IDL/Test.idl +++ b/Tests/TestIdlCdr/IDL/Test.idl @@ -144,6 +144,11 @@ module CdrWrapper { StructArrayType StructArrayField; }; + @topic + struct TestStructMultiArray { + StructMultiArrayType StructMultiArrayField; + }; + @topic struct TestPrimitive { boolean BoolField;