Skip to content

Commit

Permalink
SILKIT-1220: make data and rpc info available for dashboard (#552)
Browse files Browse the repository at this point in the history
for data publisher and subscriber: topic, media type and labels
for data subscriber internal: data publisher uuid
for rpc client and server: function name, media type and labels
for rpc server internal: rpc client uuid
  • Loading branch information
NadegeNag authored and GitHub Enterprise committed Mar 20, 2023
1 parent 00322e6 commit 8ff311e
Show file tree
Hide file tree
Showing 30 changed files with 1,074 additions and 473 deletions.
136 changes: 73 additions & 63 deletions SilKit/IntegrationTests/ITest_Dashboard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class DashboardTestHarness : public ITest_SimTestHarness
}

SilKit::Dashboard::TestResult CreateExpectedTestResult(
std::map<std::string, std::set<SilKit::Dashboard::Service>> servicesByParticipant)
std::map<std::string, std::map<uint64_t, SilKit::Dashboard::Service>> servicesByParticipant)
{
std::set<std::string> expectedStates{"servicescreated",
"communicationinitializing",
Expand Down Expand Up @@ -125,57 +125,49 @@ void CheckMatchingLabel(MatchingLabel actual, MatchingLabel expected, const std:
void CheckService(SilKit::Dashboard::Service actual, SilKit::Dashboard::Service expected,
const std::string& participantName)
{
if (expected.serviceType == "datapublisher")
ASSERT_EQ(actual.parentServiceId, expected.parentServiceId)
<< "Unexpected parent service id for " << participantName << "!";
ASSERT_EQ(actual.serviceType, expected.serviceType) << "Unexpected service type for " << participantName << "!";
if (expected.serviceType == "datapublisher" || expected.serviceType == "datasubscriber")
{
ASSERT_EQ(actual.serviceType, expected.serviceType)
<< "Unexpected controller type for " << participantName << "!";
ASSERT_EQ(actual.serviceName, expected.serviceName) << "Unexpected service name for " << participantName << "!";
ASSERT_EQ(actual.topic, expected.topic) << "Unexpected topic for " << participantName << "!";
for (auto i = 0u; i < expected.labels.size(); i++)
ASSERT_EQ(actual.spec.topic, expected.spec.topic) << "Unexpected topic for " << participantName << "!";
for (auto i = 0u; i < expected.spec.labels.size(); i++)
{
CheckMatchingLabel(actual.labels.at(i), expected.labels.at(i), participantName);
CheckMatchingLabel(actual.spec.labels.at(i), expected.spec.labels.at(i), participantName);
}
return;
}
if (expected.serviceType == "datasubscriber")
if (expected.serviceType == "datasubscriberinternal")
{
ASSERT_EQ(actual.serviceType, expected.serviceType)
<< "Unexpected controller type for " << participantName << "!";
return;
}
if (expected.serviceType == "rpcclient")
if (expected.serviceType == "rpcclient" || expected.serviceType == "rpcserver")
{
ASSERT_EQ(actual.serviceType, expected.serviceType)
<< "Unexpected controller type for " << participantName << "!";
ASSERT_EQ(actual.serviceName, expected.serviceName) << "Unexpected service name for " << participantName << "!";
ASSERT_EQ(actual.functionName, expected.functionName)
ASSERT_EQ(actual.spec.functionName, expected.spec.functionName)
<< "Unexpected functionName for " << participantName << "!";
for (auto i = 0u; i < expected.labels.size(); i++)
for (auto i = 0u; i < expected.spec.labels.size(); i++)
{
CheckMatchingLabel(actual.labels.at(i), expected.labels.at(i), participantName);
CheckMatchingLabel(actual.spec.labels.at(i), expected.spec.labels.at(i), participantName);
}
return;
}
if (expected.serviceType == "rpcserver")
if (expected.serviceType == "rpcserverinternal")
{
ASSERT_EQ(actual.serviceType, expected.serviceType)
<< "Unexpected controller type for " << participantName << "!";
return;
}
ASSERT_EQ(actual.serviceType, expected.serviceType) << "Unexpected controller type for " << participantName << "!";
ASSERT_EQ(actual.serviceName, expected.serviceName) << "Unexpected service name for " << participantName << "!";
ASSERT_EQ(actual.networkName, expected.networkName) << "Unexpected network name for " << participantName << "!";
}

void CheckServices(std::set<SilKit::Dashboard::Service> actual, std::set<SilKit::Dashboard::Service> expected,
const std::string& participantName)
void CheckServices(std::map<uint64_t, SilKit::Dashboard::Service> actual,
std::map<uint64_t, SilKit::Dashboard::Service> expected, const std::string& participantName)
{
ASSERT_EQ(actual.size(), expected.size()) << "Wrong number of services for " << participantName << "!";
for (auto&& service : expected)
for (auto i = expected.begin(); i != expected.end(); ++i)
{
ASSERT_TRUE(actual.find(service) != actual.end())
<< "Service " << service.serviceName << " " << service.serviceType << " not found!";
CheckService(*(actual.find(service)), service, participantName);
CheckService(actual[i->first], i->second, participantName);
}
}

Expand Down Expand Up @@ -248,8 +240,8 @@ TEST_F(DashboardTestHarness, dashboard_can)
auto ok = _simTestHarness->Run(5s);
ASSERT_TRUE(ok) << "SimTestHarness should terminate without timeout";
});
SilKit::Dashboard::Service expectedService = {"cancontroller", "CanController1", "CAN1", "IGNORED", "IGNORED", {}};
CheckTestResult(testResult, CreateExpectedTestResult({{"CanWriter", {expectedService}}}));
CheckTestResult(testResult, CreateExpectedTestResult(
{{"CanWriter", {{4, {"", "cancontroller", "CanController1", "CAN1", {}}}}}}));
}

TEST_F(DashboardTestHarness, dashboard_ethernet)
Expand All @@ -273,9 +265,9 @@ TEST_F(DashboardTestHarness, dashboard_ethernet)
auto ok = _simTestHarness->Run(5s);
ASSERT_TRUE(ok) << "SimTestHarness should terminate without timeout";
});
SilKit::Dashboard::Service expectedService = {
"ethernetcontroller", "EthernetController1", "ETH1", "IGNORED", "IGNORED", {}};
CheckTestResult(testResult, CreateExpectedTestResult({{"EthernetWriter", {expectedService}}}));
CheckTestResult(testResult,
CreateExpectedTestResult(
{{"EthernetWriter", {{4, {"", "ethernetcontroller", "EthernetController1", "ETH1", {}}}}}}));
}

TEST_F(DashboardTestHarness, dashboard_flexray)
Expand All @@ -299,9 +291,8 @@ TEST_F(DashboardTestHarness, dashboard_flexray)
auto ok = _simTestHarness->Run(5s);
ASSERT_TRUE(ok) << "SimTestHarness should terminate without timeout";
});
SilKit::Dashboard::Service expectedService = {
"flexraycontroller", "FlexrayController1", "FR1", "IGNORED", "IGNORED", {}};
CheckTestResult(testResult, CreateExpectedTestResult({{"Node", {expectedService}}}));
CheckTestResult(testResult, CreateExpectedTestResult(
{{"Node", {{4, {"", "flexraycontroller", "FlexrayController1", "FR1", {}}}}}}));
}

TEST_F(DashboardTestHarness, dashboard_lin)
Expand All @@ -325,16 +316,16 @@ TEST_F(DashboardTestHarness, dashboard_lin)
auto ok = _simTestHarness->Run(5s);
ASSERT_TRUE(ok) << "SimTestHarness should terminate without timeout";
});
SilKit::Dashboard::Service expectedService = {"lincontroller", "LinController1", "LIN1", "IGNORED", "IGNORED", {}};
CheckTestResult(testResult, CreateExpectedTestResult({{"LinMaster", {expectedService}}}));
CheckTestResult(testResult, CreateExpectedTestResult(
{{"LinMaster", {{4, {"", "lincontroller", "LinController1", "LIN1", {}}}}}}));
}

TEST_F(DashboardTestHarness, dashboard_pubsub)
{
SetupFromParticipantList({"Publisher", "Subscriber"});
auto testResult = SilKit::Dashboard::RunDashboardTest(_participantConfig, _registryUri, _dashboardUri, [this]() {
PubSub::PubSubSpec dataSpec{"Topic", "A"};
dataSpec.AddLabel({"Key", "Value", MatchingLabel::Kind::Mandatory});
PubSub::PubSubSpec dataPublisherSpec{"Topic", "A"};
dataPublisherSpec.AddLabel({"Key", "Value", MatchingLabel::Kind::Optional});
{
/////////////////////////////////////////////////////////////////////////
// Publisher
Expand All @@ -344,8 +335,10 @@ TEST_F(DashboardTestHarness, dashboard_pubsub)
auto&& participant = simParticipant->Participant();
(void)simParticipant->GetOrCreateLifecycleService();
(void)simParticipant->GetOrCreateTimeSyncService();
(void)participant->CreateDataPublisher("PubCtrl", dataSpec, 1);
(void)participant->CreateDataPublisher("PubCtrl", dataPublisherSpec, 1);
}
PubSub::PubSubSpec dataSubscriberSpec{"Topic", "A"};
dataSubscriberSpec.AddLabel({"Key", "Value", MatchingLabel::Kind::Mandatory});
{
/////////////////////////////////////////////////////////////////////////
// Subscriber
Expand All @@ -355,7 +348,7 @@ TEST_F(DashboardTestHarness, dashboard_pubsub)
auto&& participant = simParticipant->Participant();
auto&& lifecycleService = simParticipant->GetOrCreateLifecycleService();
auto&& timeSyncService = simParticipant->GetOrCreateTimeSyncService();
(void)participant->CreateDataSubscriber("SubCtrl", dataSpec, [](auto, const auto&) {
(void)participant->CreateDataSubscriber("SubCtrl", dataSubscriberSpec, [](auto, const auto&) {
});

timeSyncService->SetSimulationStepHandler(CreateSimulationStepHandler(participantName, lifecycleService),
Expand All @@ -364,24 +357,31 @@ TEST_F(DashboardTestHarness, dashboard_pubsub)
auto ok = _simTestHarness->Run(5s);
ASSERT_TRUE(ok) << "SimTestHarness should terminate without timeout";
});
CheckTestResult(testResult,
CreateExpectedTestResult(
{{"Publisher",
{{"datapublisher",
"PubCtrl",
"IGNORED",
"Topic",
"IGNORED",
{{"Key", "Value", MatchingLabel::Kind::Mandatory}}}}},
{"Subscriber", {{"datasubscriber", "IGNORED", "IGNORED", "IGNORED", "IGNORED", {}}}}}));
CheckTestResult(
testResult,
CreateExpectedTestResult({{"Publisher",
{{4,
{"",
"datapublisher",
"PubCtrl",
"IGNORED",
{"Topic", "IGNORED", "A", {{"Key", "Value", MatchingLabel::Kind::Optional}}}}}}},
{"Subscriber",
{{4,
{"",
"datasubscriber",
"SubCtrl",
"IGNORED",
{"Topic", "IGNORED", "A", {{"Key", "Value", MatchingLabel::Kind::Mandatory}}}}},
{5, {"4", "datasubscriberinternal", "IGNORED", "IGNORED", {}}}}}}));
}

TEST_F(DashboardTestHarness, dashboard_rpc)
{
SetupFromParticipantList({"Client", "Server"});
auto testResult = SilKit::Dashboard::RunDashboardTest(_participantConfig, _registryUri, _dashboardUri, [this]() {
Rpc::RpcSpec dataSpec{"func", "A"};
dataSpec.AddLabel({"Key", "Value", MatchingLabel::Kind::Mandatory});
Rpc::RpcSpec rpcClientSpec{"func", "A"};
rpcClientSpec.AddLabel({"Key", "Value", MatchingLabel::Kind::Mandatory});
{
/////////////////////////////////////////////////////////////////////////
// Client
Expand All @@ -391,9 +391,11 @@ TEST_F(DashboardTestHarness, dashboard_rpc)
auto&& participant = simParticipant->Participant();
(void)simParticipant->GetOrCreateLifecycleService();
(void)simParticipant->GetOrCreateTimeSyncService();
(void)participant->CreateRpcClient("ClientCtrl", dataSpec, [](auto, const auto&) {
(void)participant->CreateRpcClient("ClientCtrl", rpcClientSpec, [](auto, const auto&) {
});
}
Rpc::RpcSpec rpcServerSpec{"func", "A"};
rpcServerSpec.AddLabel({"Key", "Value", MatchingLabel::Kind::Optional});
{
/////////////////////////////////////////////////////////////////////////
// Server
Expand All @@ -403,7 +405,7 @@ TEST_F(DashboardTestHarness, dashboard_rpc)
auto&& participant = simParticipant->Participant();
auto&& lifecycleService = simParticipant->GetOrCreateLifecycleService();
auto&& timeSyncService = simParticipant->GetOrCreateTimeSyncService();
(void)participant->CreateRpcServer("ServerCtrl", dataSpec, [](auto, const auto&) {
(void)participant->CreateRpcServer("ServerCtrl", rpcServerSpec, [](auto, const auto&) {
});

timeSyncService->SetSimulationStepHandler(CreateSimulationStepHandler(participantName, lifecycleService),
Expand All @@ -412,15 +414,23 @@ TEST_F(DashboardTestHarness, dashboard_rpc)
auto ok = _simTestHarness->Run(5s);
ASSERT_TRUE(ok) << "SimTestHarness should terminate without timeout";
});
CheckTestResult(testResult, CreateExpectedTestResult(
{{"Client",
{{"rpcclient",
"ClientCtrl",
"IGNORED",
"IGNORED",
"func",
{{"Key", "Value", MatchingLabel::Kind::Mandatory}}}}},
{"Server", {{"rpcserver", "IGNORED", "IGNORED", "IGNORED", "IGNORED", {}}}}}));
CheckTestResult(
testResult,
CreateExpectedTestResult({{"Client",
{{4,
{"",
"rpcclient",
"ClientCtrl",
"IGNORED",
{"IGNORED", "func", "A", {{"Key", "Value", MatchingLabel::Kind::Mandatory}}}}}}},
{"Server",
{{4,
{"",
"rpcserver",
"ServerCtrl",
"IGNORED",
{"IGNORED", "func", "A", {{"Key", "Value", MatchingLabel::Kind::Optional}}}}},
{5, {"4", "rpcserverinternal", "IGNORED", "IGNORED", {}}}}}}));
}

TEST_F(DashboardTestHarness, dashboard_netsim)
Expand Down
5 changes: 5 additions & 0 deletions SilKit/source/core/internal/ServiceConfigKeys.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,11 @@ const std::string supplKeyDataPublisherMediaType = "PubSub::pubMediaType";
const std::string supplKeyDataPublisherPubLabels = "PubSub::pubLabels";

const std::string controllerTypeDataSubscriber = "DataSubscriber";
const std::string supplKeyDataSubscriberTopic = "PubSub::topic";
const std::string supplKeyDataSubscriberMediaType = "PubSub::subMediaType";
const std::string supplKeyDataSubscriberSubLabels = "PubSub::subLabels";
const std::string controllerTypeDataSubscriberInternal = "DataSubscriberInternal";
const std::string supplKeyDataSubscriberInternalParentServiceID = "PubSub::subIntParentServiceId";

// RPC types
const std::string controllerTypeRpcServer = "RpcServer";
Expand All @@ -64,6 +68,7 @@ const std::string supplKeyRpcClientUUID = "Rpc::client::UUID";

const std::string controllerTypeRpcServerInternal = "RpcServerInternal";
const std::string supplKeyRpcServerInternalClientUUID = "Rpc::serverinternal::clientUUID";
const std::string supplKeyRpcServerInternalParentServiceID = "Rpc::serverinternal::parentServiceId";

// Internal types. These variables are also used for the (internal) controller names.
const std::string controllerTypeLoggerSender = "LoggerSender";
Expand Down
25 changes: 22 additions & 3 deletions SilKit/source/core/participant/Participant_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -367,8 +367,14 @@ auto Participant<SilKitConnectionT>::CreateDataSubscriberInternal(const std::str
-> Services::PubSub::DataSubscriberInternal*
{
Core::SupplementalData supplementalData;
supplementalData[SilKit::Core::Discovery::controllerType] = SilKit::Core::Discovery::controllerTypeDataSubscriberInternal;

supplementalData[SilKit::Core::Discovery::controllerType] =
SilKit::Core::Discovery::controllerTypeDataSubscriberInternal;
auto parentDataSubscriber = dynamic_cast<Services::PubSub::DataSubscriber*>(parent);
if (parentDataSubscriber)
{
supplementalData[SilKit::Core::Discovery::supplKeyDataSubscriberInternalParentServiceID] =
std::to_string(parentDataSubscriber->GetServiceDescriptor().GetServiceId());
}
SilKit::Config::DataSubscriber controllerConfig;

// Use a unique name to avoid collisions of several subscribers on same topic on one participant
Expand Down Expand Up @@ -501,6 +507,10 @@ auto Participant<SilKitConnectionT>::CreateDataSubscriber(

Core::SupplementalData supplementalData;
supplementalData[SilKit::Core::Discovery::controllerType] = SilKit::Core::Discovery::controllerTypeDataSubscriber;
supplementalData[SilKit::Core::Discovery::supplKeyDataSubscriberTopic] = configuredDataNodeSpec.Topic();
supplementalData[SilKit::Core::Discovery::supplKeyDataSubscriberMediaType] = configuredDataNodeSpec.MediaType();
auto labelStr = SilKit::Config::Serialize<std::decay_t<decltype(labels)>>(labels);
supplementalData[SilKit::Core::Discovery::supplKeyDataSubscriberSubLabels] = labelStr;

auto controller = CreateController<SilKit::Config::DataSubscriber, Services::PubSub::DataSubscriber>(
controllerConfig, network, Core::ServiceType::Controller, std::move(supplementalData), true, &_timeProvider,
Expand Down Expand Up @@ -545,7 +555,12 @@ auto Participant<SilKitConnectionT>::CreateRpcServerInternal(const std::string&
Core::SupplementalData supplementalData;
supplementalData[SilKit::Core::Discovery::controllerType] = SilKit::Core::Discovery::controllerTypeRpcServerInternal;
supplementalData[SilKit::Core::Discovery::supplKeyRpcServerInternalClientUUID] = clientUUID;

auto parentRpcServer = dynamic_cast<Services::Rpc::RpcServer*>(parent);
if (parentRpcServer)
{
supplementalData[SilKit::Core::Discovery::supplKeyRpcServerInternalParentServiceID] =
std::to_string(parentRpcServer->GetServiceDescriptor().GetServiceId());
}
return CreateController<SilKit::Config::RpcServer, Services::Rpc::RpcServerInternal>(
controllerConfig, network, Core::ServiceType::Controller, std::move(supplementalData), true, &_timeProvider,
functionName, mediaType, clientLabels, clientUUID, handler, parent);
Expand Down Expand Up @@ -614,6 +629,10 @@ auto Participant<SilKitConnectionT>::CreateRpcServer(const std::string& canonica
supplementalData[SilKit::Core::Discovery::controllerType] = SilKit::Core::Discovery::controllerTypeRpcServer;
// Needed for RpcServer discovery in tests
supplementalData[SilKit::Core::Discovery::supplKeyRpcServerFunctionName] = controllerConfig.functionName.value();
supplementalData[SilKit::Core::Discovery::supplKeyRpcServerMediaType] = dataSpec.MediaType();
const auto& labels = dataSpec.Labels();
auto labelStr = SilKit::Config::Serialize<std::decay_t<decltype(labels)>>(labels);
supplementalData[SilKit::Core::Discovery::supplKeyRpcServerLabels] = labelStr;

SilKit::Services::Rpc::RpcSpec configuredDataSpec{controllerConfig.functionName.value(),
dataSpec.MediaType()};
Expand Down
4 changes: 4 additions & 0 deletions SilKit/source/dashboard/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,13 @@ if(SILKIT_BUILD_DASHBOARD)
Client/SendCoroutine.hpp

Dto/DataPublisherDto.hpp
Dto/DataSpecDto.hpp
Dto/DataSubscriberDto.hpp
Dto/MatchingLabelDto.hpp
Dto/ParticipantStatusDto.hpp
Dto/RpcClientDto.hpp
Dto/RpcServerDto.hpp
Dto/RpcSpecDto.hpp
Dto/ServiceDto.hpp
Dto/SimulationConfigurationDto.hpp
Dto/SimulationCreationRequestDto.hpp
Expand Down
Loading

0 comments on commit 8ff311e

Please sign in to comment.