#include #include #include #include #include #include #include #include #include #include #include TEST(DataDispatchServiceTest, TransactionalTxSignalTransmission) { sdv::app::CAppControl appcontrol; bool bResult = appcontrol.Startup(""); EXPECT_TRUE(bResult); appcontrol.SetConfigMode(); sdv::core::EConfigProcessResult eResult = appcontrol.LoadConfig("test_dds_config.toml"); EXPECT_EQ(eResult, sdv::core::EConfigProcessResult::successful); // Register the signals sdv::core::CDispatchService dispatch; sdv::core::CSignal signal1 = dispatch.RegisterTxSignal("abc", 10); EXPECT_TRUE(signal1); sdv::core::CSignal signal2 = dispatch.RegisterTxSignal("def", 20); EXPECT_TRUE(signal2); sdv::core::CSignal signal3 = dispatch.RegisterTxSignal("ghi", 30); EXPECT_TRUE(signal3); sdv::core::CSignal signal4 = dispatch.RegisterTxSignal("jkl", 40); EXPECT_TRUE(signal4); sdv::core::CSignal signal5 = dispatch.RegisterTxSignal("mno", 50); EXPECT_TRUE(signal5); sdv::core::CSignal signal6 = dispatch.RegisterTxSignal("pqr", 60); EXPECT_TRUE(signal6); sdv::core::CSignal signal7 = dispatch.RegisterTxSignal("stu", 70); EXPECT_TRUE(signal7); // Add publisher for the signals sdv::core::CSignal signal8 = dispatch.AddPublisher("abc"); EXPECT_TRUE(signal8); sdv::core::CSignal signal9 = dispatch.AddPublisher("def"); EXPECT_TRUE(signal9); sdv::core::CSignal signal10 = dispatch.AddPublisher("ghi"); EXPECT_TRUE(signal10); sdv::core::CSignal signal11 = dispatch.AddPublisher("jkl"); EXPECT_TRUE(signal11); sdv::core::CSignal signal12 = dispatch.AddPublisher("mno"); EXPECT_TRUE(signal12); sdv::core::CSignal signal13 = dispatch.AddPublisher("pqr"); EXPECT_TRUE(signal13); sdv::core::CSignal signal14 = dispatch.AddPublisher("stu"); EXPECT_TRUE(signal14); appcontrol.SetRunningMode(); // Request data for transmission - should be default values EXPECT_EQ(signal1.Read().get(), 10); EXPECT_EQ(signal2.Read().get(), 20); EXPECT_EQ(signal3.Read().get(), 30); EXPECT_EQ(signal4.Read().get(), 40); EXPECT_EQ(signal5.Read().get(), 50); EXPECT_EQ(signal6.Read().get(), 60); EXPECT_EQ(signal7.Read().get(), 70); // Start read transaction sdv::core::CTransaction transaction = dispatch.CreateTransaction(); // Request data for transmission using the transaction - should be default values EXPECT_EQ(signal1.Read(transaction).get(), 10); EXPECT_EQ(signal2.Read(transaction).get(), 20); EXPECT_EQ(signal3.Read(transaction).get(), 30); EXPECT_EQ(signal4.Read(transaction).get(), 40); EXPECT_EQ(signal5.Read(transaction).get(), 50); EXPECT_EQ(signal6.Read(transaction).get(), 60); EXPECT_EQ(signal7.Read(transaction).get(), 70); // Send data through the publisher signal8.Write(100); signal9.Write(110); signal10.Write(120); signal11.Write(130); signal12.Write(140); signal13.Write(150); signal14.Write(160); // Request data for transmission using the transaction - should be default values EXPECT_EQ(signal1.Read(transaction).get(), 10); EXPECT_EQ(signal2.Read(transaction).get(), 20); EXPECT_EQ(signal3.Read(transaction).get(), 30); EXPECT_EQ(signal4.Read(transaction).get(), 40); EXPECT_EQ(signal5.Read(transaction).get(), 50); EXPECT_EQ(signal6.Read(transaction).get(), 60); EXPECT_EQ(signal7.Read(transaction).get(), 70); // Send data through the publisher signal8.Write(200); signal9.Write(210); signal10.Write(220); signal11.Write(230); signal12.Write(240); signal13.Write(250); signal14.Write(260); // Finalize the transaction transaction.Finish(); // Request data for transmission - should be new values EXPECT_EQ(signal1.Read().get(), 200); EXPECT_EQ(signal2.Read().get(), 210); EXPECT_EQ(signal3.Read().get(), 220); EXPECT_EQ(signal4.Read().get(), 230); EXPECT_EQ(signal5.Read().get(), 240); EXPECT_EQ(signal6.Read().get(), 250); EXPECT_EQ(signal7.Read().get(), 260); // Check once more... EXPECT_EQ(signal1.Read().get(), 200); EXPECT_EQ(signal2.Read().get(), 210); EXPECT_EQ(signal3.Read().get(), 220); EXPECT_EQ(signal4.Read().get(), 230); EXPECT_EQ(signal5.Read().get(), 240); EXPECT_EQ(signal6.Read().get(), 250); EXPECT_EQ(signal7.Read().get(), 260); appcontrol.SetConfigMode(); signal1.Reset(); signal2.Reset(); signal3.Reset(); signal4.Reset(); signal5.Reset(); signal6.Reset(); signal7.Reset(); signal8.Reset(); signal9.Reset(); signal10.Reset(); signal11.Reset(); signal12.Reset(); signal13.Reset(); signal14.Reset(); appcontrol.Shutdown(); } TEST(DataDispatchServiceTest, TransactionalRxSignalReceptionCallback) { sdv::app::CAppControl appcontrol; bool bResult = appcontrol.Startup(""); EXPECT_TRUE(bResult); appcontrol.SetConfigMode(); sdv::core::EConfigProcessResult eResult = appcontrol.LoadConfig("test_dds_config.toml"); EXPECT_EQ(eResult, sdv::core::EConfigProcessResult::successful); // Register the signals sdv::core::CDispatchService dispatch; sdv::core::CSignal signal1 = dispatch.RegisterRxSignal("abc"); EXPECT_TRUE(signal1); sdv::core::CSignal signal2 = dispatch.RegisterRxSignal("def"); EXPECT_TRUE(signal2); sdv::core::CSignal signal3 = dispatch.RegisterRxSignal("ghi"); EXPECT_TRUE(signal3); sdv::core::CSignal signal4 = dispatch.RegisterRxSignal("jkl"); EXPECT_TRUE(signal4); sdv::core::CSignal signal5 = dispatch.RegisterRxSignal("mno"); EXPECT_TRUE(signal5); sdv::core::CSignal signal6 = dispatch.RegisterRxSignal("pqr"); EXPECT_TRUE(signal6); sdv::core::CSignal signal7 = dispatch.RegisterRxSignal("stu"); EXPECT_TRUE(signal7); // Subscribe to the signals float f8 = 0.0f; sdv::core::CSignal signal8 = dispatch.Subscribe("abc", [&](sdv::any_t any) { f8 = any.get(); }); EXPECT_TRUE(signal8); int32_t i9 = 0; sdv::core::CSignal signal9 = dispatch.Subscribe("def", [&](sdv::any_t any) { i9 = any.get(); }); EXPECT_TRUE(signal9); double d10 = 0.0; sdv::core::CSignal signal10 = dispatch.Subscribe("ghi", [&](sdv::any_t any) { d10 = any.get(); }); EXPECT_TRUE(signal10); char c11 = '\0'; sdv::core::CSignal signal11 = dispatch.Subscribe("jkl", [&](sdv::any_t any) { c11 = any.get(); }); EXPECT_TRUE(signal11); uint64_t ui12 = 0ull; sdv::core::CSignal signal12 = dispatch.Subscribe("mno", [&](sdv::any_t any) { ui12 = any.get(); }); EXPECT_TRUE(signal12); char32_t c13 = U'\0'; sdv::core::CSignal signal13 = dispatch.Subscribe("pqr", [&](sdv::any_t any) { c13 = any.get(); }); EXPECT_TRUE(signal13); int16_t i14 = 0; sdv::core::CSignal signal14 = dispatch.Subscribe("stu", [&](sdv::any_t any) { i14 = any.get(); }); EXPECT_TRUE(signal14); appcontrol.SetRunningMode(); // Check values - should be default. EXPECT_EQ(f8, 0.0f); EXPECT_EQ(i9, 0); EXPECT_EQ(d10, 0.0); EXPECT_EQ(c11, '\0'); EXPECT_EQ(ui12, 0ull); EXPECT_EQ(c13, U'\0'); EXPECT_EQ(i14, 0); // Start write transaction sdv::core::CTransaction transaction = dispatch.CreateTransaction(); // Update the values signal1.Write(10.11f, transaction); signal2.Write(50, transaction); signal3.Write(101.202, transaction); signal4.Write('X', transaction); signal5.Write(1234567890ll, transaction); signal6.Write('x', transaction); signal7.Write(327, transaction); // Check values - should still be default. EXPECT_EQ(f8, 0.0f); EXPECT_EQ(i9, 0); EXPECT_EQ(d10, 0.0); EXPECT_EQ(c11, '\0'); EXPECT_EQ(ui12, 0ull); EXPECT_EQ(c13, U'\0'); EXPECT_EQ(i14, 0); // Update the values signal1.Write(20.11f, transaction); signal2.Write(60, transaction); signal3.Write(201.202, transaction); signal4.Write('Y', transaction); signal5.Write(2234567890ll, transaction); signal6.Write('y', transaction); signal7.Write(427, transaction); // Check values - should still be default. EXPECT_EQ(f8, 0.0f); EXPECT_EQ(i9, 0); EXPECT_EQ(d10, 0.0); EXPECT_EQ(c11, '\0'); EXPECT_EQ(ui12, 0ull); EXPECT_EQ(c13, U'\0'); EXPECT_EQ(i14, 0); // Finalize the transaction transaction.Finish(); // Check values - should be updated. EXPECT_EQ(f8, 20.11f); EXPECT_EQ(i9, 60); EXPECT_EQ(d10, 201.202); EXPECT_EQ(c11, 'Y'); EXPECT_EQ(ui12, 2234567890ull); EXPECT_EQ(c13, U'y'); EXPECT_EQ(i14, 427); // Update the values signal1.Write(30.11f); signal2.Write(70); signal3.Write(301.202); signal4.Write('Z'); signal5.Write(3234567890ll); signal6.Write('z'); signal7.Write(527); // Check values - should be updated. EXPECT_EQ(f8, 30.11f); EXPECT_EQ(i9, 70); EXPECT_EQ(d10, 301.202); EXPECT_EQ(c11, 'Z'); EXPECT_EQ(ui12, 3234567890ull); EXPECT_EQ(c13, U'z'); EXPECT_EQ(i14, 527); appcontrol.SetConfigMode(); signal1.Reset(); signal2.Reset(); signal3.Reset(); signal4.Reset(); signal5.Reset(); signal6.Reset(); signal7.Reset(); signal8.Reset(); signal9.Reset(); signal10.Reset(); signal11.Reset(); signal12.Reset(); signal13.Reset(); signal14.Reset(); appcontrol.Shutdown(); } TEST(DataDispatchServiceTest, TransactionalRxSignalReceptionData) { sdv::app::CAppControl appcontrol; bool bResult = appcontrol.Startup(""); EXPECT_TRUE(bResult); appcontrol.SetConfigMode(); sdv::core::EConfigProcessResult eResult = appcontrol.LoadConfig("test_dds_config.toml"); EXPECT_EQ(eResult, sdv::core::EConfigProcessResult::successful); // Register the signals sdv::core::CDispatchService dispatch; sdv::core::CSignal signal1 = dispatch.RegisterRxSignal("abc"); EXPECT_TRUE(signal1); sdv::core::CSignal signal2 = dispatch.RegisterRxSignal("def"); EXPECT_TRUE(signal2); sdv::core::CSignal signal3 = dispatch.RegisterRxSignal("ghi"); EXPECT_TRUE(signal3); sdv::core::CSignal signal4 = dispatch.RegisterRxSignal("jkl"); EXPECT_TRUE(signal4); sdv::core::CSignal signal5 = dispatch.RegisterRxSignal("mno"); EXPECT_TRUE(signal5); sdv::core::CSignal signal6 = dispatch.RegisterRxSignal("pqr"); EXPECT_TRUE(signal6); sdv::core::CSignal signal7 = dispatch.RegisterRxSignal("stu"); EXPECT_TRUE(signal7); // Subscribe to the signals std::atomic f8 = 0.0f; sdv::core::CSignal signal8 = dispatch.Subscribe("abc", f8); EXPECT_TRUE(signal8); std::atomic i9 = 0; sdv::core::CSignal signal9 = dispatch.Subscribe("def", i9); EXPECT_TRUE(signal9); std::atomic d10 = 0.0; sdv::core::CSignal signal10 = dispatch.Subscribe("ghi", d10); EXPECT_TRUE(signal10); std::atomic c11 = '\0'; sdv::core::CSignal signal11 = dispatch.Subscribe("jkl", c11); EXPECT_TRUE(signal11); std::atomic ui12 = 0ull; sdv::core::CSignal signal12 = dispatch.Subscribe("mno", ui12); EXPECT_TRUE(signal12); std::atomic c13 = U'\0'; sdv::core::CSignal signal13 = dispatch.Subscribe("pqr", c13); EXPECT_TRUE(signal13); std::atomic i14 = 0; sdv::core::CSignal signal14 = dispatch.Subscribe("stu", i14); EXPECT_TRUE(signal14); appcontrol.SetRunningMode(); // Check values - should be default. EXPECT_EQ(f8, 0.0f); EXPECT_EQ(i9, 0); EXPECT_EQ(d10, 0.0); EXPECT_EQ(c11, '\0'); EXPECT_EQ(ui12, 0ull); EXPECT_EQ(c13, U'\0'); EXPECT_EQ(i14, 0); // Start write transaction sdv::core::CTransaction transaction = dispatch.CreateTransaction(); // Update the values signal1.Write(10.11f, transaction); signal2.Write(50, transaction); signal3.Write(101.202, transaction); signal4.Write('X', transaction); signal5.Write(1234567890ll, transaction); signal6.Write('x', transaction); signal7.Write(327, transaction); // Check values - should still be default. EXPECT_EQ(f8, 0.0f); EXPECT_EQ(i9, 0); EXPECT_EQ(d10, 0.0); EXPECT_EQ(c11, '\0'); EXPECT_EQ(ui12, 0ull); EXPECT_EQ(c13, U'\0'); EXPECT_EQ(i14, 0); // Update the values signal1.Write(20.11f, transaction); signal2.Write(60, transaction); signal3.Write(201.202, transaction); signal4.Write('Y', transaction); signal5.Write(2234567890ll, transaction); signal6.Write('y', transaction); signal7.Write(427, transaction); // Check values - should still be default. EXPECT_EQ(f8, 0.0f); EXPECT_EQ(i9, 0); EXPECT_EQ(d10, 0.0); EXPECT_EQ(c11, '\0'); EXPECT_EQ(ui12, 0ull); EXPECT_EQ(c13, U'\0'); EXPECT_EQ(i14, 0); // Finalize the transaction transaction.Finish(); // Check values - should be updated. EXPECT_EQ(f8, 20.11f); EXPECT_EQ(i9, 60); EXPECT_EQ(d10, 201.202); EXPECT_EQ(c11, 'Y'); EXPECT_EQ(ui12, 2234567890ull); EXPECT_EQ(c13, U'y'); EXPECT_EQ(i14, 427); // Update the values signal1.Write(30.11f); signal2.Write(70); signal3.Write(301.202); signal4.Write('Z'); signal5.Write(3234567890ll); signal6.Write('z'); signal7.Write(527); // Check values - should be updated. EXPECT_EQ(f8, 30.11f); EXPECT_EQ(i9, 70); EXPECT_EQ(d10, 301.202); EXPECT_EQ(c11, 'Z'); EXPECT_EQ(ui12, 3234567890ull); EXPECT_EQ(c13, U'z'); EXPECT_EQ(i14, 527); appcontrol.SetConfigMode(); signal1.Reset(); signal2.Reset(); signal3.Reset(); signal4.Reset(); signal5.Reset(); signal6.Reset(); signal7.Reset(); signal8.Reset(); signal9.Reset(); signal10.Reset(); signal11.Reset(); signal12.Reset(); signal13.Reset(); signal14.Reset(); appcontrol.Shutdown(); } TEST(DataDispatchServiceTest, TransactionalSignalPublishing) { sdv::app::CAppControl appcontrol; bool bResult = appcontrol.Startup(""); EXPECT_TRUE(bResult); appcontrol.SetConfigMode(); sdv::core::EConfigProcessResult eResult = appcontrol.LoadConfig("test_dds_config.toml"); EXPECT_EQ(eResult, sdv::core::EConfigProcessResult::successful); // Register the signals sdv::core::CDispatchService dispatch; sdv::core::CSignal signal1 = dispatch.RegisterTxSignal("abc", 10); EXPECT_TRUE(signal1); sdv::core::CSignal signal2 = dispatch.RegisterTxSignal("def", 20); EXPECT_TRUE(signal2); sdv::core::CSignal signal3 = dispatch.RegisterTxSignal("ghi", 30); EXPECT_TRUE(signal3); sdv::core::CSignal signal4 = dispatch.RegisterTxSignal("jkl", 40); EXPECT_TRUE(signal4); sdv::core::CSignal signal5 = dispatch.RegisterTxSignal("mno", 50); EXPECT_TRUE(signal5); sdv::core::CSignal signal6 = dispatch.RegisterTxSignal("pqr", 60); EXPECT_TRUE(signal6); sdv::core::CSignal signal7 = dispatch.RegisterTxSignal("stu", 70); EXPECT_TRUE(signal7); // Add publisher for the signals sdv::core::CSignal signal8 = dispatch.AddPublisher("abc"); EXPECT_TRUE(signal8); sdv::core::CSignal signal9 = dispatch.AddPublisher("def"); EXPECT_TRUE(signal9); sdv::core::CSignal signal10 = dispatch.AddPublisher("ghi"); EXPECT_TRUE(signal10); sdv::core::CSignal signal11 = dispatch.AddPublisher("jkl"); EXPECT_TRUE(signal11); sdv::core::CSignal signal12 = dispatch.AddPublisher("mno"); EXPECT_TRUE(signal12); sdv::core::CSignal signal13 = dispatch.AddPublisher("pqr"); EXPECT_TRUE(signal13); sdv::core::CSignal signal14 = dispatch.AddPublisher("stu"); EXPECT_TRUE(signal14); appcontrol.SetRunningMode(); // Request data for transmission - should be default values EXPECT_EQ(signal1.Read().get(), 10); EXPECT_EQ(signal2.Read().get(), 20); EXPECT_EQ(signal3.Read().get(), 30); EXPECT_EQ(signal4.Read().get(), 40); EXPECT_EQ(signal5.Read().get(), 50); EXPECT_EQ(signal6.Read().get(), 60); EXPECT_EQ(signal7.Read().get(), 70); // Start write transaction sdv::core::CTransaction transaction = dispatch.CreateTransaction(); // Send data through the publisher using the transaction signal8.Write(100, transaction); signal9.Write(110, transaction); signal10.Write(120, transaction); signal11.Write(130, transaction); signal12.Write(140, transaction); signal13.Write(150, transaction); signal14.Write(160, transaction); // Request data for transmission using the transaction - should be default values EXPECT_EQ(signal1.Read().get(), 10); EXPECT_EQ(signal2.Read().get(), 20); EXPECT_EQ(signal3.Read().get(), 30); EXPECT_EQ(signal4.Read().get(), 40); EXPECT_EQ(signal5.Read().get(), 50); EXPECT_EQ(signal6.Read().get(), 60); EXPECT_EQ(signal7.Read().get(), 70); // Finalize the transaction transaction.Finish(); // Request data for transmission - should be new values EXPECT_EQ(signal1.Read().get(), 100); EXPECT_EQ(signal2.Read().get(), 110); EXPECT_EQ(signal3.Read().get(), 120); EXPECT_EQ(signal4.Read().get(), 130); EXPECT_EQ(signal5.Read().get(), 140); EXPECT_EQ(signal6.Read().get(), 150); EXPECT_EQ(signal7.Read().get(), 160); // Check once more... EXPECT_EQ(signal1.Read().get(), 100); EXPECT_EQ(signal2.Read().get(), 110); EXPECT_EQ(signal3.Read().get(), 120); EXPECT_EQ(signal4.Read().get(), 130); EXPECT_EQ(signal5.Read().get(), 140); EXPECT_EQ(signal6.Read().get(), 150); EXPECT_EQ(signal7.Read().get(), 160); appcontrol.SetConfigMode(); signal1.Reset(); signal2.Reset(); signal3.Reset(); signal4.Reset(); signal5.Reset(); signal6.Reset(); signal7.Reset(); signal8.Reset(); signal9.Reset(); signal10.Reset(); signal11.Reset(); signal12.Reset(); signal13.Reset(); signal14.Reset(); appcontrol.Shutdown(); } TEST(DataDispatchServiceTest, MultiTransactionalTxSignalTransmission) { sdv::app::CAppControl appcontrol; bool bResult = appcontrol.Startup(""); EXPECT_TRUE(bResult); appcontrol.SetConfigMode(); sdv::core::EConfigProcessResult eResult = appcontrol.LoadConfig("test_dds_config.toml"); EXPECT_EQ(eResult, sdv::core::EConfigProcessResult::successful); // Register the signals sdv::core::CDispatchService dispatch; sdv::core::CSignal signal1 = dispatch.RegisterTxSignal("abc", 10); EXPECT_TRUE(signal1); sdv::core::CSignal signal2 = dispatch.RegisterTxSignal("def", 20); EXPECT_TRUE(signal2); sdv::core::CSignal signal3 = dispatch.RegisterTxSignal("ghi", 30); EXPECT_TRUE(signal3); sdv::core::CSignal signal4 = dispatch.RegisterTxSignal("jkl", 40); EXPECT_TRUE(signal4); sdv::core::CSignal signal5 = dispatch.RegisterTxSignal("mno", 50); EXPECT_TRUE(signal5); sdv::core::CSignal signal6 = dispatch.RegisterTxSignal("pqr", 60); EXPECT_TRUE(signal6); sdv::core::CSignal signal7 = dispatch.RegisterTxSignal("stu", 70); EXPECT_TRUE(signal7); // Add publisher for the signals sdv::core::CSignal signal8 = dispatch.AddPublisher("abc"); EXPECT_TRUE(signal8); sdv::core::CSignal signal9 = dispatch.AddPublisher("def"); EXPECT_TRUE(signal9); sdv::core::CSignal signal10 = dispatch.AddPublisher("ghi"); EXPECT_TRUE(signal10); sdv::core::CSignal signal11 = dispatch.AddPublisher("jkl"); EXPECT_TRUE(signal11); sdv::core::CSignal signal12 = dispatch.AddPublisher("mno"); EXPECT_TRUE(signal12); sdv::core::CSignal signal13 = dispatch.AddPublisher("pqr"); EXPECT_TRUE(signal13); sdv::core::CSignal signal14 = dispatch.AddPublisher("stu"); EXPECT_TRUE(signal14); appcontrol.SetRunningMode(); // Request data for transmission - should be default values EXPECT_EQ(signal1.Read().get(), 10); EXPECT_EQ(signal2.Read().get(), 20); EXPECT_EQ(signal3.Read().get(), 30); EXPECT_EQ(signal4.Read().get(), 40); EXPECT_EQ(signal5.Read().get(), 50); EXPECT_EQ(signal6.Read().get(), 60); EXPECT_EQ(signal7.Read().get(), 70); // Start read transactions sdv::core::CTransaction transaction1 = dispatch.CreateTransaction(); sdv::core::CTransaction transaction2 = dispatch.CreateTransaction(); // Request data for transmission using the first transaction - should be default values EXPECT_EQ(signal1.Read(transaction1).get(), 10); EXPECT_EQ(signal2.Read(transaction1).get(), 20); EXPECT_EQ(signal3.Read(transaction1).get(), 30); EXPECT_EQ(signal4.Read(transaction1).get(), 40); EXPECT_EQ(signal5.Read(transaction1).get(), 50); EXPECT_EQ(signal6.Read(transaction1).get(), 60); EXPECT_EQ(signal7.Read(transaction1).get(), 70); // Request data for transmission using the second transaction - should be default values EXPECT_EQ(signal1.Read(transaction2).get(), 10); EXPECT_EQ(signal2.Read(transaction2).get(), 20); EXPECT_EQ(signal3.Read(transaction2).get(), 30); EXPECT_EQ(signal4.Read(transaction2).get(), 40); EXPECT_EQ(signal5.Read(transaction2).get(), 50); EXPECT_EQ(signal6.Read(transaction2).get(), 60); EXPECT_EQ(signal7.Read(transaction2).get(), 70); // Send data through the publisher signal8.Write(100); signal9.Write(110); signal10.Write(120); signal11.Write(130); signal12.Write(140); signal13.Write(150); signal14.Write(160); // Request data for transmission using the first transaction - should be default values EXPECT_EQ(signal1.Read(transaction1).get(), 10); EXPECT_EQ(signal2.Read(transaction1).get(), 20); EXPECT_EQ(signal3.Read(transaction1).get(), 30); EXPECT_EQ(signal4.Read(transaction1).get(), 40); EXPECT_EQ(signal5.Read(transaction1).get(), 50); EXPECT_EQ(signal6.Read(transaction1).get(), 60); EXPECT_EQ(signal7.Read(transaction1).get(), 70); // Request data for transmission using the second transaction - should be default values EXPECT_EQ(signal1.Read(transaction1).get(), 10); EXPECT_EQ(signal2.Read(transaction1).get(), 20); EXPECT_EQ(signal3.Read(transaction1).get(), 30); EXPECT_EQ(signal4.Read(transaction1).get(), 40); EXPECT_EQ(signal5.Read(transaction1).get(), 50); EXPECT_EQ(signal6.Read(transaction1).get(), 60); EXPECT_EQ(signal7.Read(transaction1).get(), 70); // Send data through the publisher signal8.Write(200); signal9.Write(210); signal10.Write(220); signal11.Write(230); signal12.Write(240); signal13.Write(250); signal14.Write(260); // Finalize the first transaction transaction1.Finish(); // Request data for transmission - should be new values EXPECT_EQ(signal1.Read().get(), 200); EXPECT_EQ(signal2.Read().get(), 210); EXPECT_EQ(signal3.Read().get(), 220); EXPECT_EQ(signal4.Read().get(), 230); EXPECT_EQ(signal5.Read().get(), 240); EXPECT_EQ(signal6.Read().get(), 250); EXPECT_EQ(signal7.Read().get(), 260); // Request data for transmission using the second transaction - should be default values EXPECT_EQ(signal1.Read(transaction2).get(), 10); EXPECT_EQ(signal2.Read(transaction2).get(), 20); EXPECT_EQ(signal3.Read(transaction2).get(), 30); EXPECT_EQ(signal4.Read(transaction2).get(), 40); EXPECT_EQ(signal5.Read(transaction2).get(), 50); EXPECT_EQ(signal6.Read(transaction2).get(), 60); EXPECT_EQ(signal7.Read(transaction2).get(), 70); // Finalize the second transaction transaction2.Finish(); // Request data for transmission - should be new value, except for signal 2, 4 and 6. They should have default value, since // they were requested before and reset after reading. EXPECT_EQ(signal1.Read().get(), 200); EXPECT_EQ(signal2.Read().get(), 210); EXPECT_EQ(signal3.Read().get(), 220); EXPECT_EQ(signal4.Read().get(), 230); EXPECT_EQ(signal5.Read().get(), 240); EXPECT_EQ(signal6.Read().get(), 250); EXPECT_EQ(signal7.Read().get(), 260); appcontrol.SetConfigMode(); signal1.Reset(); signal2.Reset(); signal3.Reset(); signal4.Reset(); signal5.Reset(); signal6.Reset(); signal7.Reset(); signal8.Reset(); signal9.Reset(); signal10.Reset(); signal11.Reset(); signal12.Reset(); signal13.Reset(); signal14.Reset(); appcontrol.Shutdown(); } TEST(DataDispatchServiceTest, MultiTransactionalRxSignalReceptionCallback) { sdv::app::CAppControl appcontrol; bool bResult = appcontrol.Startup(""); EXPECT_TRUE(bResult); appcontrol.SetConfigMode(); sdv::core::EConfigProcessResult eResult = appcontrol.LoadConfig("test_dds_config.toml"); EXPECT_EQ(eResult, sdv::core::EConfigProcessResult::successful); // Register the signals sdv::core::CDispatchService dispatch; sdv::core::CSignal signal1 = dispatch.RegisterRxSignal("abc"); EXPECT_TRUE(signal1); sdv::core::CSignal signal2 = dispatch.RegisterRxSignal("def"); EXPECT_TRUE(signal2); sdv::core::CSignal signal3 = dispatch.RegisterRxSignal("ghi"); EXPECT_TRUE(signal3); sdv::core::CSignal signal4 = dispatch.RegisterRxSignal("jkl"); EXPECT_TRUE(signal4); sdv::core::CSignal signal5 = dispatch.RegisterRxSignal("mno"); EXPECT_TRUE(signal5); sdv::core::CSignal signal6 = dispatch.RegisterRxSignal("pqr"); EXPECT_TRUE(signal6); sdv::core::CSignal signal7 = dispatch.RegisterRxSignal("stu"); EXPECT_TRUE(signal7); // Subscribe to the signals float f8 = 0.0f; sdv::core::CSignal signal8 = dispatch.Subscribe("abc", [&](sdv::any_t any) { f8 = any.get(); }); EXPECT_TRUE(signal8); int32_t i9 = 0; sdv::core::CSignal signal9 = dispatch.Subscribe("def", [&](sdv::any_t any) { i9 = any.get(); }); EXPECT_TRUE(signal9); double d10 = 0.0; sdv::core::CSignal signal10 = dispatch.Subscribe("ghi", [&](sdv::any_t any) { d10 = any.get(); }); EXPECT_TRUE(signal10); char c11 = '\0'; sdv::core::CSignal signal11 = dispatch.Subscribe("jkl", [&](sdv::any_t any) { c11 = any.get(); }); EXPECT_TRUE(signal11); uint64_t ui12 = 0ull; sdv::core::CSignal signal12 = dispatch.Subscribe("mno", [&](sdv::any_t any) { ui12 = any.get(); }); EXPECT_TRUE(signal12); char32_t c13 = U'\0'; sdv::core::CSignal signal13 = dispatch.Subscribe("pqr", [&](sdv::any_t any) { c13 = any.get(); }); EXPECT_TRUE(signal13); int16_t i14 = 0; sdv::core::CSignal signal14 = dispatch.Subscribe("stu", [&](sdv::any_t any) { i14 = any.get(); }); EXPECT_TRUE(signal14); appcontrol.SetRunningMode(); // Check values - should be default. EXPECT_EQ(f8, 0.0f); EXPECT_EQ(i9, 0); EXPECT_EQ(d10, 0.0); EXPECT_EQ(c11, '\0'); EXPECT_EQ(ui12, 0ull); EXPECT_EQ(c13, U'\0'); EXPECT_EQ(i14, 0); // Start write transactions sdv::core::CTransaction transaction1 = dispatch.CreateTransaction(); sdv::core::CTransaction transaction2 = dispatch.CreateTransaction(); // Update the values using the first transaction signal1.Write(10.11f, transaction1); signal2.Write(50, transaction1); signal3.Write(101.202, transaction1); signal4.Write('X', transaction1); signal5.Write(1234567890ll, transaction1); signal6.Write('x', transaction1); signal7.Write(327, transaction1); // Update the values using the second transaction signal1.Write(20.22f, transaction1); signal2.Write(60, transaction1); signal3.Write(202.303, transaction1); signal4.Write('Y', transaction1); signal5.Write(2234567890ll, transaction1); signal6.Write('y', transaction1); signal7.Write(427, transaction1); // Check values - should still be default. EXPECT_EQ(f8, 0.0f); EXPECT_EQ(i9, 0); EXPECT_EQ(d10, 0.0); EXPECT_EQ(c11, '\0'); EXPECT_EQ(ui12, 0ull); EXPECT_EQ(c13, U'\0'); EXPECT_EQ(i14, 0); // Update the values using the first transaction signal1.Write(40.44f, transaction1); signal2.Write(70, transaction1); signal3.Write(303.404, transaction1); signal4.Write('Z', transaction1); signal5.Write(3234567890ll, transaction1); signal6.Write('z', transaction1); signal7.Write(527, transaction1); // Update the values using the second transaction signal1.Write(50.55f, transaction2); signal2.Write(80, transaction2); signal3.Write(404.505, transaction2); signal4.Write('A', transaction2); signal5.Write(4234567890ll, transaction2); signal6.Write('a', transaction2); signal7.Write(627, transaction2); // Check values - should still be default. EXPECT_EQ(f8, 0.0f); EXPECT_EQ(i9, 0); EXPECT_EQ(d10, 0.0); EXPECT_EQ(c11, '\0'); EXPECT_EQ(ui12, 0ull); EXPECT_EQ(c13, U'\0'); EXPECT_EQ(i14, 0); // Finalize the first transaction transaction1.Finish(); // Check values - should be updated with values of first transaction EXPECT_EQ(f8, 40.44f); EXPECT_EQ(i9, 70); EXPECT_EQ(d10, 303.404); EXPECT_EQ(c11, 'Z'); EXPECT_EQ(ui12, 3234567890ull); EXPECT_EQ(c13, U'z'); EXPECT_EQ(i14, 527); // Update the values signal1.Write(60.66f); signal2.Write(90); signal3.Write(606.707); signal4.Write('B'); signal5.Write(5234567890ll); signal6.Write('b'); signal7.Write(727); // Check values - should be updated. EXPECT_EQ(f8, 60.66f); EXPECT_EQ(i9, 90); EXPECT_EQ(d10, 606.707); EXPECT_EQ(c11, 'B'); EXPECT_EQ(ui12, 5234567890ull); EXPECT_EQ(c13, U'b'); EXPECT_EQ(i14, 727); // Finalize the second transaction transaction2.Finish(); // Check values - should be updated with the values of second transaction. EXPECT_EQ(f8, 50.55f); EXPECT_EQ(i9, 80); EXPECT_EQ(d10, 404.505); EXPECT_EQ(c11, 'A'); EXPECT_EQ(ui12, 4234567890ull); EXPECT_EQ(c13, U'a'); EXPECT_EQ(i14, 627); appcontrol.SetConfigMode(); signal1.Reset(); signal2.Reset(); signal3.Reset(); signal4.Reset(); signal5.Reset(); signal6.Reset(); signal7.Reset(); signal8.Reset(); signal9.Reset(); signal10.Reset(); signal11.Reset(); signal12.Reset(); signal13.Reset(); signal14.Reset(); appcontrol.Shutdown(); } TEST(DataDispatchServiceTest, MultiTransactionalRxSignalReceptionData) { sdv::app::CAppControl appcontrol; bool bResult = appcontrol.Startup(""); EXPECT_TRUE(bResult); appcontrol.SetConfigMode(); sdv::core::EConfigProcessResult eResult = appcontrol.LoadConfig("test_dds_config.toml"); EXPECT_EQ(eResult, sdv::core::EConfigProcessResult::successful); // Register the signals sdv::core::CDispatchService dispatch; sdv::core::CSignal signal1 = dispatch.RegisterRxSignal("abc"); EXPECT_TRUE(signal1); sdv::core::CSignal signal2 = dispatch.RegisterRxSignal("def"); EXPECT_TRUE(signal2); sdv::core::CSignal signal3 = dispatch.RegisterRxSignal("ghi"); EXPECT_TRUE(signal3); sdv::core::CSignal signal4 = dispatch.RegisterRxSignal("jkl"); EXPECT_TRUE(signal4); sdv::core::CSignal signal5 = dispatch.RegisterRxSignal("mno"); EXPECT_TRUE(signal5); sdv::core::CSignal signal6 = dispatch.RegisterRxSignal("pqr"); EXPECT_TRUE(signal6); sdv::core::CSignal signal7 = dispatch.RegisterRxSignal("stu"); EXPECT_TRUE(signal7); // Subscribe to the signals std::atomic f8 = 0.0f; sdv::core::CSignal signal8 = dispatch.Subscribe("abc", f8); EXPECT_TRUE(signal8); std::atomic i9 = 0; sdv::core::CSignal signal9 = dispatch.Subscribe("def", i9); EXPECT_TRUE(signal9); std::atomic d10 = 0.0; sdv::core::CSignal signal10 = dispatch.Subscribe("ghi", d10); EXPECT_TRUE(signal10); std::atomic c11 = '\0'; sdv::core::CSignal signal11 = dispatch.Subscribe("jkl", c11); EXPECT_TRUE(signal11); std::atomic ui12 = 0ull; sdv::core::CSignal signal12 = dispatch.Subscribe("mno", ui12); EXPECT_TRUE(signal12); std::atomic c13 = U'\0'; sdv::core::CSignal signal13 = dispatch.Subscribe("pqr", c13); EXPECT_TRUE(signal13); std::atomic i14 = 0; sdv::core::CSignal signal14 = dispatch.Subscribe("stu", i14); EXPECT_TRUE(signal14); appcontrol.SetRunningMode(); // Check values - should be default. EXPECT_EQ(f8, 0.0f); EXPECT_EQ(i9, 0); EXPECT_EQ(d10, 0.0); EXPECT_EQ(c11, '\0'); EXPECT_EQ(ui12, 0ull); EXPECT_EQ(c13, U'\0'); EXPECT_EQ(i14, 0); // Start write transactions sdv::core::CTransaction transaction1 = dispatch.CreateTransaction(); sdv::core::CTransaction transaction2 = dispatch.CreateTransaction(); // Update the values using the first transaction signal1.Write(10.11f, transaction1); signal2.Write(50, transaction1); signal3.Write(101.202, transaction1); signal4.Write('X', transaction1); signal5.Write(1234567890ll, transaction1); signal6.Write('x', transaction1); signal7.Write(327, transaction1); // Update the values using the second transaction signal1.Write(20.22f, transaction1); signal2.Write(60, transaction1); signal3.Write(202.303, transaction1); signal4.Write('Y', transaction1); signal5.Write(2234567890ll, transaction1); signal6.Write('y', transaction1); signal7.Write(427, transaction1); // Check values - should still be default. EXPECT_EQ(f8, 0.0f); EXPECT_EQ(i9, 0); EXPECT_EQ(d10, 0.0); EXPECT_EQ(c11, '\0'); EXPECT_EQ(ui12, 0ull); EXPECT_EQ(c13, U'\0'); EXPECT_EQ(i14, 0); // Update the values using the first transaction signal1.Write(40.44f, transaction1); signal2.Write(70, transaction1); signal3.Write(303.404, transaction1); signal4.Write('Z', transaction1); signal5.Write(3234567890ll, transaction1); signal6.Write('z', transaction1); signal7.Write(527, transaction1); // Update the values using the second transaction signal1.Write(50.55f, transaction2); signal2.Write(80, transaction2); signal3.Write(404.505, transaction2); signal4.Write('A', transaction2); signal5.Write(4234567890ll, transaction2); signal6.Write('a', transaction2); signal7.Write(627, transaction2); // Check values - should still be default. EXPECT_EQ(f8, 0.0f); EXPECT_EQ(i9, 0); EXPECT_EQ(d10, 0.0); EXPECT_EQ(c11, '\0'); EXPECT_EQ(ui12, 0ull); EXPECT_EQ(c13, U'\0'); EXPECT_EQ(i14, 0); // Finalize the first transaction transaction1.Finish(); // Check values - should be updated with values of first transaction EXPECT_EQ(f8, 40.44f); EXPECT_EQ(i9, 70); EXPECT_EQ(d10, 303.404); EXPECT_EQ(c11, 'Z'); EXPECT_EQ(ui12, 3234567890ull); EXPECT_EQ(c13, U'z'); EXPECT_EQ(i14, 527); // Update the values signal1.Write(60.66f); signal2.Write(90); signal3.Write(606.707); signal4.Write('B'); signal5.Write(5234567890ll); signal6.Write('b'); signal7.Write(727); // Check values - should be updated. EXPECT_EQ(f8, 60.66f); EXPECT_EQ(i9, 90); EXPECT_EQ(d10, 606.707); EXPECT_EQ(c11, 'B'); EXPECT_EQ(ui12, 5234567890ull); EXPECT_EQ(c13, U'b'); EXPECT_EQ(i14, 727); // Finalize the second transaction transaction2.Finish(); // Check values - should be updated with the values of second transaction. EXPECT_EQ(f8, 50.55f); EXPECT_EQ(i9, 80); EXPECT_EQ(d10, 404.505); EXPECT_EQ(c11, 'A'); EXPECT_EQ(ui12, 4234567890ull); EXPECT_EQ(c13, U'a'); EXPECT_EQ(i14, 627); appcontrol.SetConfigMode(); signal1.Reset(); signal2.Reset(); signal3.Reset(); signal4.Reset(); signal5.Reset(); signal6.Reset(); signal7.Reset(); signal8.Reset(); signal9.Reset(); signal10.Reset(); signal11.Reset(); signal12.Reset(); signal13.Reset(); signal14.Reset(); appcontrol.Shutdown(); } TEST(DataDispatchServiceTest, MultiTransactionalSignalPublishing) { sdv::app::CAppControl appcontrol; bool bResult = appcontrol.Startup(""); EXPECT_TRUE(bResult); appcontrol.SetConfigMode(); sdv::core::EConfigProcessResult eResult = appcontrol.LoadConfig("test_dds_config.toml"); EXPECT_EQ(eResult, sdv::core::EConfigProcessResult::successful); // Register the signals sdv::core::CDispatchService dispatch; sdv::core::CSignal signal1 = dispatch.RegisterTxSignal("abc", 10); EXPECT_TRUE(signal1); sdv::core::CSignal signal2 = dispatch.RegisterTxSignal("def", 20); EXPECT_TRUE(signal2); sdv::core::CSignal signal3 = dispatch.RegisterTxSignal("ghi", 30); EXPECT_TRUE(signal3); sdv::core::CSignal signal4 = dispatch.RegisterTxSignal("jkl", 40); EXPECT_TRUE(signal4); sdv::core::CSignal signal5 = dispatch.RegisterTxSignal("mno", 50); EXPECT_TRUE(signal5); sdv::core::CSignal signal6 = dispatch.RegisterTxSignal("pqr", 60); EXPECT_TRUE(signal6); sdv::core::CSignal signal7 = dispatch.RegisterTxSignal("stu", 70); EXPECT_TRUE(signal7); // Add publisher for the signals sdv::core::CSignal signal8 = dispatch.AddPublisher("abc"); EXPECT_TRUE(signal8); sdv::core::CSignal signal9 = dispatch.AddPublisher("def"); EXPECT_TRUE(signal9); sdv::core::CSignal signal10 = dispatch.AddPublisher("ghi"); EXPECT_TRUE(signal10); sdv::core::CSignal signal11 = dispatch.AddPublisher("jkl"); EXPECT_TRUE(signal11); sdv::core::CSignal signal12 = dispatch.AddPublisher("mno"); EXPECT_TRUE(signal12); sdv::core::CSignal signal13 = dispatch.AddPublisher("pqr"); EXPECT_TRUE(signal13); sdv::core::CSignal signal14 = dispatch.AddPublisher("stu"); EXPECT_TRUE(signal14); appcontrol.SetRunningMode(); // Request data for transmission - should be default values EXPECT_EQ(signal1.Read().get(), 10); EXPECT_EQ(signal2.Read().get(), 20); EXPECT_EQ(signal3.Read().get(), 30); EXPECT_EQ(signal4.Read().get(), 40); EXPECT_EQ(signal5.Read().get(), 50); EXPECT_EQ(signal6.Read().get(), 60); EXPECT_EQ(signal7.Read().get(), 70); // Start write transactions sdv::core::CTransaction transaction1 = dispatch.CreateTransaction(); sdv::core::CTransaction transaction2 = dispatch.CreateTransaction(); // Send data through the publisher using the first transaction signal8.Write(100, transaction1); signal9.Write(110, transaction1); signal10.Write(120, transaction1); signal11.Write(130, transaction1); signal12.Write(140, transaction1); signal13.Write(150, transaction1); signal14.Write(160, transaction1); // Send data through the publisher using the first transaction signal8.Write(200, transaction2); signal9.Write(210, transaction2); signal11.Write(230, transaction2); signal12.Write(240, transaction2); signal13.Write(250, transaction2); signal14.Write(260, transaction2); signal10.Write(220, transaction2); // Request data for transmission using the transaction - should be default values EXPECT_EQ(signal1.Read().get(), 10); EXPECT_EQ(signal2.Read().get(), 20); EXPECT_EQ(signal3.Read().get(), 30); EXPECT_EQ(signal4.Read().get(), 40); EXPECT_EQ(signal5.Read().get(), 50); EXPECT_EQ(signal6.Read().get(), 60); EXPECT_EQ(signal7.Read().get(), 70); // Finalize the first transaction transaction1.Finish(); // Request data for transmission - should be new values from first transaction EXPECT_EQ(signal1.Read().get(), 100); EXPECT_EQ(signal2.Read().get(), 110); EXPECT_EQ(signal3.Read().get(), 120); EXPECT_EQ(signal4.Read().get(), 130); EXPECT_EQ(signal5.Read().get(), 140); EXPECT_EQ(signal6.Read().get(), 150); EXPECT_EQ(signal7.Read().get(), 160); // Check once more... EXPECT_EQ(signal1.Read().get(), 100); EXPECT_EQ(signal2.Read().get(), 110); EXPECT_EQ(signal3.Read().get(), 120); EXPECT_EQ(signal4.Read().get(), 130); EXPECT_EQ(signal5.Read().get(), 140); EXPECT_EQ(signal6.Read().get(), 150); EXPECT_EQ(signal7.Read().get(), 160); // Finalize the second transaction transaction2.Finish(); // Request data for transmission - should be new values from second transaction EXPECT_EQ(signal1.Read().get(), 200); EXPECT_EQ(signal2.Read().get(), 210); EXPECT_EQ(signal3.Read().get(), 220); EXPECT_EQ(signal4.Read().get(), 230); EXPECT_EQ(signal5.Read().get(), 240); EXPECT_EQ(signal6.Read().get(), 250); EXPECT_EQ(signal7.Read().get(), 260); // Check once more... EXPECT_EQ(signal1.Read().get(), 200); EXPECT_EQ(signal2.Read().get(), 210); EXPECT_EQ(signal3.Read().get(), 220); EXPECT_EQ(signal4.Read().get(), 230); EXPECT_EQ(signal5.Read().get(), 240); EXPECT_EQ(signal6.Read().get(), 250); EXPECT_EQ(signal7.Read().get(), 260); appcontrol.SetConfigMode(); signal1.Reset(); signal2.Reset(); signal3.Reset(); signal4.Reset(); signal5.Reset(); signal6.Reset(); signal7.Reset(); signal8.Reset(); signal9.Reset(); signal10.Reset(); signal11.Reset(); signal12.Reset(); signal13.Reset(); signal14.Reset(); appcontrol.Shutdown(); } TEST(DataDispatchServiceTest, TransactionalRxTxSignalCommunication) { sdv::app::CAppControl appcontrol; bool bResult = appcontrol.Startup(""); EXPECT_TRUE(bResult); appcontrol.SetConfigMode(); sdv::core::EConfigProcessResult eResult = appcontrol.LoadConfig("test_dds_config.toml"); EXPECT_EQ(eResult, sdv::core::EConfigProcessResult::successful); // Register the TX signals (receiving data from dispatch to be transmitted) sdv::core::CDispatchService dispatch; sdv::core::CSignal signal1 = dispatch.RegisterTxSignal("abc", 10.0f); EXPECT_TRUE(signal1); sdv::core::CSignal signal2 = dispatch.RegisterTxSignal("def", 20); EXPECT_TRUE(signal2); sdv::core::CSignal signal3 = dispatch.RegisterTxSignal("ghi", 30.0); EXPECT_TRUE(signal3); sdv::core::CSignal signal4 = dispatch.RegisterTxSignal("jkl", 'A'); EXPECT_TRUE(signal4); // Register the RX signals (sending received data to dispatch) sdv::core::CSignal signal5 = dispatch.RegisterRxSignal("mno"); EXPECT_TRUE(signal5); sdv::core::CSignal signal6 = dispatch.RegisterRxSignal("pqr"); EXPECT_TRUE(signal6); sdv::core::CSignal signal7 = dispatch.RegisterRxSignal("stu"); EXPECT_TRUE(signal7); sdv::core::CSignal signal8 = dispatch.RegisterRxSignal("vwx"); EXPECT_TRUE(signal8); // Add publishers for the TX signals sdv::core::CSignal signal9 = dispatch.AddPublisher("abc"); EXPECT_TRUE(signal9); sdv::core::CSignal signal10 = dispatch.AddPublisher("def"); EXPECT_TRUE(signal10); sdv::core::CSignal signal11 = dispatch.AddPublisher("ghi"); EXPECT_TRUE(signal11); sdv::core::CSignal signal12 = dispatch.AddPublisher("jkl"); EXPECT_TRUE(signal12); // Create the transactions sdv::core::CTransaction transactionRx = dispatch.CreateTransaction(); sdv::core::CTransaction transactionTx = dispatch.CreateTransaction(); sdv::core::CTransaction transactionPublish = dispatch.CreateTransaction(); // Add subscribers for the TX signals uint32_t uiPublishCnt = 0; sdv::core::CSignal signal13 = dispatch.Subscribe("mno", [&](sdv::any_t any) { uiPublishCnt++; signal9.Write(any, transactionPublish); }); EXPECT_TRUE(signal13); sdv::core::CSignal signal14 = dispatch.Subscribe("pqr", [&](sdv::any_t any) { uiPublishCnt++; signal10.Write(any, transactionPublish); }); EXPECT_TRUE(signal14); sdv::core::CSignal signal15 = dispatch.Subscribe("stu", [&](sdv::any_t any) { uiPublishCnt++; signal11.Write(any, transactionPublish); }); EXPECT_TRUE(signal15); sdv::core::CSignal signal16 = dispatch.Subscribe("vwx", [&](sdv::any_t any) { uiPublishCnt++; signal12.Write(any, transactionPublish); }); EXPECT_TRUE(signal16); appcontrol.SetRunningMode(); // Read the TX signals; should be the default EXPECT_EQ(signal1.Read(transactionTx).get(), 10.0f); EXPECT_EQ(signal2.Read(transactionTx).get(), 20); EXPECT_EQ(signal3.Read(transactionTx).get(), 30.0); EXPECT_EQ(signal4.Read(transactionTx).get(), 'A'); // The publish count should be 0 EXPECT_EQ(uiPublishCnt, 0ul); // Write the RX signals signal5.Write(10.11f, transactionRx); signal6.Write(50, transactionRx); signal7.Write(101.202, transactionRx); signal8.Write('X', transactionRx); // The publish count should be 0 EXPECT_EQ(uiPublishCnt, 0ul); // Read the TX signals; should be the default EXPECT_EQ(signal1.Read(transactionTx).get(), 10.0f); EXPECT_EQ(signal2.Read(transactionTx).get(), 20); EXPECT_EQ(signal3.Read(transactionTx).get(), 30.0); EXPECT_EQ(signal4.Read(transactionTx).get(), 'A'); // Finalize the RX transaction; all signals are written. transactionRx.Finish(); // The publish count should be 4 EXPECT_EQ(uiPublishCnt, 4ul); // Read the TX signals; should be the default EXPECT_EQ(signal1.Read(transactionTx).get(), 10.0f); EXPECT_EQ(signal2.Read(transactionTx).get(), 20); EXPECT_EQ(signal3.Read(transactionTx).get(), 30.0); EXPECT_EQ(signal4.Read(transactionTx).get(), 'A'); // Finalize the publish transaction; all signals are published transactionPublish.Finish(); // Read the TX signals; should be the default EXPECT_EQ(signal1.Read(transactionTx).get(), 10.0f); EXPECT_EQ(signal2.Read(transactionTx).get(), 20); EXPECT_EQ(signal3.Read(transactionTx).get(), 30.0); EXPECT_EQ(signal4.Read(transactionTx).get(), 'A'); // Finalize the TX transaction; all written signals are available. transactionTx.Finish(); // Read the TX signals; should be the written value EXPECT_EQ(signal1.Read().get(), 10.11f); EXPECT_EQ(signal2.Read().get(), 50); EXPECT_EQ(signal3.Read().get(), 101.202); EXPECT_EQ(signal4.Read().get(), 'X'); // Read the TX signals once more; signal 2 and 4 should be default, 1 and 3 the written value EXPECT_EQ(signal1.Read().get(), 10.11f); EXPECT_EQ(signal2.Read().get(), 50); EXPECT_EQ(signal3.Read().get(), 101.202); EXPECT_EQ(signal4.Read().get(), 'X'); appcontrol.SetConfigMode(); signal1.Reset(); signal2.Reset(); signal3.Reset(); signal4.Reset(); signal5.Reset(); signal6.Reset(); signal7.Reset(); signal8.Reset(); signal9.Reset(); signal10.Reset(); signal11.Reset(); signal12.Reset(); signal13.Reset(); signal14.Reset(); signal15.Reset(); signal16.Reset(); appcontrol.Shutdown(); } TEST(DataDispatchServiceTest, TransactionalRxTxSignalConcurrency) { sdv::app::CAppControl appcontrol; bool bResult = appcontrol.Startup(""); EXPECT_TRUE(bResult); appcontrol.SetConfigMode(); sdv::core::EConfigProcessResult eResult = appcontrol.LoadConfig("test_dds_config.toml"); EXPECT_EQ(eResult, sdv::core::EConfigProcessResult::successful); // Register the TX signals (receiving data from dispatch to be transmitted) sdv::core::CDispatchService dispatch; sdv::core::CSignal signalTx1a = dispatch.RegisterTxSignal("SigTx1a", 10); EXPECT_TRUE(signalTx1a); sdv::core::CSignal signalTx1b = dispatch.RegisterTxSignal("SigTx1b", 20); EXPECT_TRUE(signalTx1b); sdv::core::CSignal signalTx1c = dispatch.RegisterTxSignal("SigTx1c", 30); EXPECT_TRUE(signalTx1c); sdv::core::CSignal signalTx1d = dispatch.RegisterTxSignal("SigTx1d", 40); EXPECT_TRUE(signalTx1d); sdv::core::CSignal signalTx2a = dispatch.RegisterTxSignal("SigTx2a", 50); EXPECT_TRUE(signalTx2a); sdv::core::CSignal signalTx2b = dispatch.RegisterTxSignal("SigTx2b", 60); EXPECT_TRUE(signalTx2b); sdv::core::CSignal signalTx2c = dispatch.RegisterTxSignal("SigTx2c", 70); EXPECT_TRUE(signalTx2c); sdv::core::CSignal signalTx2d = dispatch.RegisterTxSignal("SigTx2d", 80); EXPECT_TRUE(signalTx2d); sdv::core::CSignal signalTx3a = dispatch.RegisterTxSignal("SigTx3a", 90); EXPECT_TRUE(signalTx3a); sdv::core::CSignal signalTx3b = dispatch.RegisterTxSignal("SigTx3b", 100); EXPECT_TRUE(signalTx3b); sdv::core::CSignal signalTx3c = dispatch.RegisterTxSignal("SigTx3c", 110); EXPECT_TRUE(signalTx3c); sdv::core::CSignal signalTx3d = dispatch.RegisterTxSignal("SigTx3d", 120); EXPECT_TRUE(signalTx3d); sdv::core::CSignal signalTx4a = dispatch.RegisterTxSignal("SigTx4a", 130); EXPECT_TRUE(signalTx4a); sdv::core::CSignal signalTx4b = dispatch.RegisterTxSignal("SigTx4b", 140); EXPECT_TRUE(signalTx4b); sdv::core::CSignal signalTx4c = dispatch.RegisterTxSignal("SigTx4c", 150); EXPECT_TRUE(signalTx4c); sdv::core::CSignal signalTx4d = dispatch.RegisterTxSignal("SigTx4d", 160); EXPECT_TRUE(signalTx4d); // Register the RX signals (sending received data to dispatch) sdv::core::CSignal signalRx1a = dispatch.RegisterRxSignal("SigRx1a"); EXPECT_TRUE(signalRx1a); sdv::core::CSignal signalRx1b = dispatch.RegisterRxSignal("SigRx1b"); EXPECT_TRUE(signalRx1b); sdv::core::CSignal signalRx1c = dispatch.RegisterRxSignal("SigRx1c"); EXPECT_TRUE(signalRx1c); sdv::core::CSignal signalRx1d = dispatch.RegisterRxSignal("SigRx1d"); EXPECT_TRUE(signalRx1d); sdv::core::CSignal signalRx2a = dispatch.RegisterRxSignal("SigRx2a"); EXPECT_TRUE(signalRx2a); sdv::core::CSignal signalRx2b = dispatch.RegisterRxSignal("SigRx2b"); EXPECT_TRUE(signalRx2b); sdv::core::CSignal signalRx2c = dispatch.RegisterRxSignal("SigRx2c"); EXPECT_TRUE(signalRx2c); sdv::core::CSignal signalRx2d = dispatch.RegisterRxSignal("SigRx2d"); EXPECT_TRUE(signalRx2d); sdv::core::CSignal signalRx3a = dispatch.RegisterRxSignal("SigRx3a"); EXPECT_TRUE(signalRx3a); sdv::core::CSignal signalRx3b = dispatch.RegisterRxSignal("SigRx3b"); EXPECT_TRUE(signalRx3b); sdv::core::CSignal signalRx3c = dispatch.RegisterRxSignal("SigRx3c"); EXPECT_TRUE(signalRx3c); sdv::core::CSignal signalRx3d = dispatch.RegisterRxSignal("SigRx3d"); EXPECT_TRUE(signalRx3d); sdv::core::CSignal signalRx4a = dispatch.RegisterRxSignal("SigRx4a"); EXPECT_TRUE(signalRx4a); sdv::core::CSignal signalRx4b = dispatch.RegisterRxSignal("SigRx4b"); EXPECT_TRUE(signalRx4b); sdv::core::CSignal signalRx4c = dispatch.RegisterRxSignal("SigRx4c"); EXPECT_TRUE(signalRx4c); sdv::core::CSignal signalRx4d = dispatch.RegisterRxSignal("SigRx4d"); EXPECT_TRUE(signalRx4d); std::atomic_uint64_t uiValueCnt = 1000; bool bShutdownPublisher = false, bShutdownConsumer = false; std::srand(static_cast(std::time(0))); // Thread sync std::shared_mutex mtxStart; std::atomic_uint32_t uiInitCnt = 0; // Publisher thread function auto fnPublisher = [&](uint32_t uiIndex) -> void { try { std::string ssSignalName = "SigTx" + std::to_string(uiIndex % 4 + 1); sdv::core::CSignal signalPubA = dispatch.AddPublisher(ssSignalName + "a"); EXPECT_TRUE(signalPubA); sdv::core::CSignal signalPubB = dispatch.AddPublisher(ssSignalName + "b"); EXPECT_TRUE(signalPubB); sdv::core::CSignal signalPubC = dispatch.AddPublisher(ssSignalName + "c"); EXPECT_TRUE(signalPubC); sdv::core::CSignal signalPubD = dispatch.AddPublisher(ssSignalName + "d"); EXPECT_TRUE(signalPubD); uiInitCnt++; std::shared_lock lock(mtxStart); while (!bShutdownPublisher) { sdv::core::CTransaction transaction = dispatch.CreateTransaction(); uint64_t uiValue = std::rand(); signalPubA.Write(uiValue, transaction); std::this_thread::sleep_for(std::chrono::milliseconds(std::rand() % 10)); signalPubB.Write(uiValue + 10, transaction); std::this_thread::sleep_for(std::chrono::milliseconds(std::rand() % 10)); signalPubC.Write(uiValue + 20, transaction); std::this_thread::sleep_for(std::chrono::milliseconds(std::rand() % 10)); signalPubD.Write(uiValue + 30, transaction); std::this_thread::sleep_for(std::chrono::milliseconds(std::rand() % 10)); transaction.Finish(); } } catch (...) { // Should not crash EXPECT_TRUE(false); } }; // Consumer thread function const size_t nConsumeThreads = 16; std::atomic uiA[nConsumeThreads], uiB[nConsumeThreads], uiC[nConsumeThreads], uiD[nConsumeThreads]; auto fnConsumer = [&](uint32_t uiIndex) -> void { try { std::string ssSignalName = "SigRx" + std::to_string(uiIndex % 4 + 1); sdv::core::CSignal signalConsA = dispatch.Subscribe(ssSignalName + "a", uiA[uiIndex % nConsumeThreads]); EXPECT_TRUE(signalConsA); sdv::core::CSignal signalConsB = dispatch.Subscribe(ssSignalName + "b", uiB[uiIndex % nConsumeThreads]); EXPECT_TRUE(signalConsB); sdv::core::CSignal signalConsC = dispatch.Subscribe(ssSignalName + "c", uiC[uiIndex % nConsumeThreads]); EXPECT_TRUE(signalConsC); sdv::core::CSignal signalConsD = dispatch.Subscribe(ssSignalName + "d", uiD[uiIndex % nConsumeThreads]); EXPECT_TRUE(signalConsD); uiInitCnt++; std::shared_lock lock(mtxStart); while (!bShutdownConsumer) { std::this_thread::sleep_for(std::chrono::milliseconds(10)); } signalConsA.Reset(); signalConsB.Reset(); signalConsC.Reset(); signalConsD.Reset(); } catch (...) { // Should not crash EXPECT_TRUE(false); } }; // Start the threads std::unique_lock lockStart(mtxStart); uint32_t uiCnt = 0; std::thread rgPublishThreads[16]; for (std::thread& rThread : rgPublishThreads) rThread = std::thread(fnPublisher, uiCnt++); std::thread rgConsumeThreads[nConsumeThreads]; for (std::thread& rThread :rgConsumeThreads) rThread = std::thread(fnConsumer, uiCnt++); // Trigger the "GO" while (uiInitCnt < 32) std::this_thread::sleep_for(std::chrono::milliseconds(10)); appcontrol.SetRunningMode(); lockStart.unlock(); // Send and receive data for 5 seconds const auto start = std::chrono::high_resolution_clock::now(); uint64_t uiTxA[4], uiTxB[4], uiTxC[4], uiTxD[4]; try { while (std::chrono::duration(std::chrono::high_resolution_clock::now() - start).count() < 2000) { sdv::core::CTransaction transaction = dispatch.CreateTransaction(); uiTxA[0] = signalTx1a.Read(transaction); uiTxB[0] = signalTx1b.Read(transaction); uiTxC[0] = signalTx1c.Read(transaction); uiTxD[0] = signalTx1d.Read(transaction); transaction.Finish(); transaction = dispatch.CreateTransaction(); uiTxA[1] = signalTx2a.Read(transaction); uiTxB[1] = signalTx2b.Read(transaction); uiTxC[1] = signalTx2c.Read(transaction); uiTxD[1] = signalTx2d.Read(transaction); transaction.Finish(); transaction = dispatch.CreateTransaction(); uiTxA[2] = signalTx3a.Read(transaction); uiTxB[2] = signalTx3b.Read(transaction); uiTxC[2] = signalTx3c.Read(transaction); uiTxD[2] = signalTx3d.Read(transaction); transaction.Finish(); transaction = dispatch.CreateTransaction(); uiTxA[3] = signalTx4a.Read(transaction); uiTxB[3] = signalTx4b.Read(transaction); uiTxC[3] = signalTx4c.Read(transaction); uiTxD[3] = signalTx4d.Read(transaction); transaction.Finish(); transaction = dispatch.CreateTransaction(); uint64_t uiValue = std::rand(); signalRx1a.Write(uiValue); signalRx1b.Write(uiValue + 10); signalRx1c.Write(uiValue + 20); signalRx1d.Write(uiValue + 30); transaction.Finish(); transaction = dispatch.CreateTransaction(); uiValue = std::rand(); signalRx2a.Write(uiValue); signalRx2b.Write(uiValue + 10); signalRx2c.Write(uiValue + 20); signalRx2d.Write(uiValue + 30); transaction.Finish(); transaction = dispatch.CreateTransaction(); uiValue = std::rand(); signalRx3a.Write(uiValue); signalRx3b.Write(uiValue + 10); signalRx3c.Write(uiValue + 20); signalRx3d.Write(uiValue + 30); transaction.Finish(); transaction = dispatch.CreateTransaction(); uiValue = std::rand(); signalRx4a.Write(uiValue); signalRx4b.Write(uiValue + 10); signalRx4c.Write(uiValue + 20); signalRx4d.Write(uiValue + 30); transaction.Finish(); } } catch (...) { // Should not crash EXPECT_TRUE(false); } // Wait for everything to finalize std::this_thread::sleep_for(std::chrono::milliseconds(1000)); // Wait for all threads to finalize appcontrol.SetConfigMode(); bShutdownPublisher = true; for (std::thread& rThread : rgPublishThreads) if (rThread.joinable()) rThread.join(); std::this_thread::sleep_for(std::chrono::milliseconds(1000)); bShutdownConsumer = true; for (std::thread& rThread : rgConsumeThreads) if (rThread.joinable()) rThread.join(); // Check consume ranges for (size_t nIndex = 0; nIndex < nConsumeThreads; nIndex++) { EXPECT_EQ(uiB[nIndex] - uiA[nIndex], 10u); EXPECT_EQ(uiC[nIndex] - uiA[nIndex], 20u); EXPECT_EQ(uiD[nIndex] - uiA[nIndex], 30u); } // Check Tx ranges for (size_t nIndex = 0; nIndex < 4; nIndex++) { EXPECT_EQ(uiTxB[nIndex] - uiTxA[nIndex], 10u); EXPECT_EQ(uiTxC[nIndex] - uiTxA[nIndex], 20u); EXPECT_EQ(uiTxD[nIndex] - uiTxA[nIndex], 30u); } signalTx1a.Reset(); signalTx1b.Reset(); signalTx1c.Reset(); signalTx1d.Reset(); signalTx2a.Reset(); signalTx2b.Reset(); signalTx2c.Reset(); signalTx2d.Reset(); signalTx3a.Reset(); signalTx3b.Reset(); signalTx3c.Reset(); signalTx3d.Reset(); signalTx4a.Reset(); signalTx4b.Reset(); signalTx4c.Reset(); signalTx4d.Reset(); signalRx1a.Reset(); signalRx1b.Reset(); signalRx1c.Reset(); signalRx1d.Reset(); signalRx2a.Reset(); signalRx2b.Reset(); signalRx2c.Reset(); signalRx2d.Reset(); signalRx3a.Reset(); signalRx3b.Reset(); signalRx3c.Reset(); signalRx3d.Reset(); signalRx4a.Reset(); signalRx4b.Reset(); signalRx4c.Reset(); signalRx4d.Reset(); appcontrol.Shutdown(); }