PROFINET IO Controller Stack 1.0.0
Modern C++ implementation of a PROFINET IO Controller stack
Loading...
Searching...
No Matches
test_indices.cpp
Go to the documentation of this file.
1
10
11#include <gtest/gtest.h>
12
13#include <cstdint>
14#include <format>
15#include <string>
16#include <utility>
17#include <vector>
18
19#include "profinet/indices.h"
20#include "profinet/util.h"
21
22namespace profinet
23{
24
25class IndicesTest : public ::testing::Test
26{
27 protected:
29 void ExpectBlockTypeNames(const std::vector<std::pair<BlockType, std::string>>& values)
30 {
31 for (const auto& [blockType, expectedName] : values)
32 {
33 EXPECT_EQ(GetBlockTypeName(blockType), expectedName) << "BlockType value: " << static_cast<std::uint16_t>(blockType);
34 }
35 }
36
38 void ExpectAlarmTypeNames(const std::vector<std::pair<AlarmType, std::string>>& values)
39 {
40 for (const auto& [alarmType, expectedName] : values)
41 {
42 EXPECT_EQ(GetAlarmTypeName(alarmType), expectedName) << "AlarmType value: " << static_cast<std::uint16_t>(alarmType);
43 }
44 }
45
47 void ExpectIocrTypeNames(const std::vector<std::pair<IocrType, std::string>>& values)
48 {
49 for (const auto& [iocrType, expectedName] : values)
50 {
51 EXPECT_EQ(GetIocrTypeName(iocrType), expectedName) << "IocrType value: " << static_cast<std::uint16_t>(iocrType);
52 }
53 }
54
56 void ExpectIocrRtClassNames(const std::vector<std::pair<IocrRtClass, std::string>>& values)
57 {
58 for (const auto& [rtClass, expectedName] : values)
59 {
60 EXPECT_EQ(GetIocrRtClassName(rtClass), expectedName) << "IocrRtClass value: " << static_cast<std::uint8_t>(rtClass);
61 }
62 }
63
65 void ExpectUsiNames(const std::vector<std::pair<Usi, std::string>>& values)
66 {
67 for (const auto& [usi, expectedName] : values)
68 {
69 EXPECT_EQ(GetUsiName(usi), expectedName) << "Usi value: " << static_cast<std::uint16_t>(usi);
70 }
71 }
72
74 void ExpectIndexNames(const std::vector<std::pair<std::uint16_t, std::string>>& values)
75 {
76 for (const auto& [index, expectedName] : values)
77 {
78 EXPECT_EQ(GetIndexName(index), expectedName) << "Index value: " << index;
79 }
80 }
81
83 void ExpectScopes(const std::vector<std::pair<std::uint16_t, std::string>>& values)
84 {
85 for (const auto& [index, expectedScope] : values)
86 {
87 EXPECT_EQ(GetScope(index), expectedScope) << "Index value: " << index;
88 }
89 }
90
92 void ExpectModuleStates(const std::vector<std::pair<std::uint16_t, std::string>>& values)
93 {
94 for (const auto& [state, expectedName] : values)
95 {
96 EXPECT_EQ(GetModuleStateName(state), expectedName) << "State value: " << state;
97 }
98 }
99
101 void ExpectSubmoduleStates(const std::vector<std::pair<std::uint16_t, std::string>>& values)
102 {
103 for (const auto& [state, expectedName] : values)
104 {
105 EXPECT_EQ(GetSubmoduleStateName(state), expectedName) << "State value: " << state;
106 }
107 }
108
110 void ExpectPeModes(const std::vector<std::pair<std::uint8_t, std::string>>& values)
111 {
112 for (const auto& [mode, expectedName] : values)
113 {
114 EXPECT_EQ(GetPeModeName(mode), expectedName) << "Mode value: " << static_cast<unsigned int>(mode);
115 }
116 }
117
119 void ExpectIndexTable(const IndexNamePairs& actual, const IndexNamePairs& expected)
120 {
121 ASSERT_EQ(actual.size(), expected.size());
122
123 for (std::size_t i = 0; i < expected.size(); ++i)
124 {
125 EXPECT_EQ(actual[i].first, expected[i].first) << "Unexpected index at table position " << i;
126 EXPECT_EQ(actual[i].second, expected[i].second) << "Unexpected name at table position " << i;
127 }
128 }
129};
130
132TEST_F(IndicesTest, GetBlockTypeNameResolvesEveryKnownBlockType)
133{
134 ExpectBlockTypeNames({
135 {BlockType::DiagnosisData, "Diagnosis Data"},
136 {BlockType::ExpectedIdentificationData, "Expected Identification Data"},
137 {BlockType::RealIdentificationData, "Real Identification Data"},
154 {BlockType::AlarmNotificationHigh, "Alarm Notification High"},
155 {BlockType::AlarmAcknowledgementHigh, "Alarm Acknowledgement High"},
156 {BlockType::AlarmNotificationLow, "Alarm Notification Low"},
157 {BlockType::AlarmAcknowledgementLow, "Alarm Acknowledgement Low"},
158 {BlockType::IoDataWriteRequest, "IO Data Write Request Header"},
159 {BlockType::IoDataWriteResponse, "IO Data Write Response Header"},
160 {BlockType::IoDataReadRequest, "IO Data Read Request Header"},
161 {BlockType::IoDataReadResponse, "IO Data Read Response Header"},
162 {BlockType::ApplicationRelationData, "Application Relation Data"},
163 {BlockType::LogData, "Log Data"},
164 {BlockType::ApiData, "API Data"},
165 {BlockType::SrlData, "SRL Data"},
166 {BlockType::ApplicationRelationRequest, "Application Relation Request"},
167 {BlockType::ApplicationRelationResponse, "Application Relation Response"},
168 {BlockType::IoCrRequest, "IOCR Request"},
169 {BlockType::IoCrResponse, "IOCR Response"},
170 {BlockType::AlarmCrRequest, "Alarm CR Request"},
171 {BlockType::AlarmCrResponse, "Alarm CR Response"},
172 {BlockType::ExpectedSubmoduleRequest, "Expected Submodule Request"},
173 {BlockType::ModuleDifference, "Module Difference"},
174 {BlockType::ControlPrmEndRequest, "Control Parameter End Request"},
175 {BlockType::ControlPrmEndResponse, "Control Parameter End Response"},
176 {BlockType::ControlApplicationReadyRequest, "Control Application Ready Request"},
177 {BlockType::ControlApplicationReadyResponse, "Control Application Ready Response"},
178 {BlockType::ReleaseRequest, "Release Request"},
179 {BlockType::ReleaseResponse, "Release Response"},
180 {BlockType::ControlRtClass3Request, "Control RT Class 3 Request"},
181 {BlockType::ControlRtClass3Response, "Control RT Class 3 Response"},
182 {BlockType::ParameterizationBeginRequest, "Parameterization Begin Request"},
183 {BlockType::ParameterizationBeginResponse, "Parameterization Begin Response"},
184 {BlockType::SubmoduleList, "Submodule List"},
185 {BlockType::PortDataCheck, "Port Data Check"},
186 {BlockType::PortDataAdjust, "Port Data Adjust"},
187 {BlockType::PortDataReal, "Port Data Real"},
188 {BlockType::InterfaceMrpDataAdjust, "Interface MRP Data Adjust"},
189 {BlockType::InterfaceMrpDataReal, "Interface MRP Data Real"},
190 {BlockType::PortMrpDataReal, "Port MRP Data Real"},
191 {BlockType::MrpRingStateData, "MRP Ring State Data"},
192 {BlockType::PortFoDataReal, "Port FO Data Real"},
193 {BlockType::PortFoDataCheck, "Port FO Data Check"},
194 {BlockType::PortFoDataAdjust, "Port FO Data Adjust"},
195 {BlockType::PortDataRealExtended, "Port Data Real Extended"},
196 {BlockType::PortDataInterfaceDataReal, "Interface Data Real"},
197 {BlockType::PortStatistics, "Port Statistics"},
198 {BlockType::MultipleHeader, "Multiple Header"},
199 {BlockType::ContainerContent, "Container Content"},
200 {BlockType::ApplicationRelationServer, "Application Relation Server"},
201 {BlockType::RealProcessData, "Real Process Data"},
202 {BlockType::ExpectedProcessData, "Expected Process Data"},
203 {BlockType::RealIdentificationDataApi, "Real Identification Data API"},
204 });
205}
206
208TEST_F(IndicesTest, GetBlockTypeNameFallsBackForUnknownTypes)
209{
210 EXPECT_EQ(GetBlockTypeName(static_cast<BlockType>(0x9999)), "Unknown (0x9999)");
211}
212
214TEST_F(IndicesTest, GetAlarmTypeNameResolvesEveryKnownAlarmType)
215{
216 ExpectAlarmTypeNames({
217 {AlarmType::Diagnosis, "Diagnosis"},
218 {AlarmType::Process, "Process"},
219 {AlarmType::Pull, "Pull"},
220 {AlarmType::Plug, "Plug"},
221 {AlarmType::Status, "Status"},
222 {AlarmType::Update, "Update"},
223 {AlarmType::Redundancy, "Redundancy"},
224 {AlarmType::ControlledBySupervisor, "Controlled By Supervisor"},
225 {AlarmType::Released, "Released"},
226 {AlarmType::PlugWrongSubmodule, "Plug Wrong Submodule"},
227 {AlarmType::ReturnOfSubmodule, "Return Of Submodule"},
228 {AlarmType::DiagnosisDisappears, "Diagnosis Disappears"},
229 {AlarmType::MulticastMismatch, "Multicast Mismatch"},
230 {AlarmType::PortDataChange, "Port Data Change"},
231 {AlarmType::SyncDataChanged, "Sync Data Changed"},
232 {AlarmType::IsochronousModeProblem, "Isochronous Mode Problem"},
233 {AlarmType::NetworkComponentProblem, "Network Component Problem"},
234 {AlarmType::TimeDataChanged, "Time Data Changed"},
235 {AlarmType::DfpProblem, "DFP Problem"},
236 {AlarmType::UploadRetrieval, "Upload Retrieval"},
237 {AlarmType::PullModule, "Pull Module"},
238 });
239}
240
242TEST_F(IndicesTest, GetAlarmTypeNameFallsBackForUnknownType)
243{
244 EXPECT_EQ(GetAlarmTypeName(static_cast<AlarmType>(0x9999)), "Unknown");
245}
246
248TEST_F(IndicesTest, GetIocrTypeNameResolvesEveryKnownType)
249{
250 ExpectIocrTypeNames({
251 {IocrType::Input, "Input"},
252 {IocrType::Output, "Output"},
253 {IocrType::MulticastProvider, "Multicast Provider"},
254 {IocrType::MulticastConsumer, "Multicast Consumer"},
255 });
256}
257
259TEST_F(IndicesTest, GetIocrTypeNameFallsBackForUnknownType)
260{
261 EXPECT_EQ(GetIocrTypeName(static_cast<IocrType>(0x9999)), "Unknown (0x9999)");
262}
263
265TEST_F(IndicesTest, GetIocrRtClassNameResolvesUdp)
266{
267 EXPECT_EQ(GetIocrRtClassName(IocrRtClass::Udp), "RT_CLASS_UDP");
268}
269
271TEST_F(IndicesTest, GetIocrRtClassNameFallsBackForUnknownType)
272{
273 EXPECT_EQ(GetIocrRtClassName(static_cast<IocrRtClass>(0x99)), "Unknown (0x99)");
274}
275
277TEST_F(IndicesTest, GetUsiNameResolvesEveryKnownUsi)
278{
279 ExpectUsiNames({
280 {Usi::ChannelDiagnosis, "Channel Diagnosis"},
281 {Usi::MultipleDiagnosis, "Multiple Diagnosis"},
282 {Usi::ExtendedChannelDiagnosis, "Extended Channel Diagnosis"},
283 {Usi::QualifiedChannelDiagnosis, "Qualified Channel Diagnosis"},
284 {Usi::Maintenance, "Maintenance Item"},
285 {Usi::Upload, "Upload Record"},
286 {Usi::IParameter, "iParameter Item"},
287 {Usi::RsAlarmLow, "RS Alarm Item (Low)"},
288 {Usi::RsAlarmHigh, "RS Alarm Item (High)"},
289 {Usi::RsAlarmSubmodule, "RS Alarm Item (Submodule)"},
290 {Usi::PeAlarm, "PE Alarm Item"},
291 {Usi::PralAlarm, "PRAL Alarm Item"},
292 });
293}
294
296TEST_F(IndicesTest, GetUsiNameClassifiesManufacturerSpecificValues)
297{
298 ExpectUsiNames({
299 {static_cast<Usi>(0x0000), "Manufacturer Specific (0x0000)"},
300 {static_cast<Usi>(0x0001), "Manufacturer Specific (0x0001)"},
301 {static_cast<Usi>(0x7FFF), "Manufacturer Specific (0x7FFF)"},
302 });
303}
304
306TEST_F(IndicesTest, GetUsiNameClassifiesProfileSpecificValues)
307{
308 ExpectUsiNames({
309 {static_cast<Usi>(0x8400), "Profile Specific (0x8400)"},
310 {static_cast<Usi>(0x8500), "Profile Specific (0x8500)"},
311 {static_cast<Usi>(0x8FFF), "Profile Specific (0x8FFF)"},
312 });
313}
314
316TEST_F(IndicesTest, GetUsiNameClassifiesReservedValues)
317{
318 ExpectUsiNames({
319 {static_cast<Usi>(0x8004), "Reserved (0x8004)"},
320 {static_cast<Usi>(0x83FF), "Reserved (0x83FF)"},
321 {static_cast<Usi>(0x9000), "Reserved (0x9000)"},
322 {static_cast<Usi>(0xFFFF), "Reserved (0xFFFF)"},
323 });
324}
325
327TEST_F(IndicesTest, GetModuleStateNameResolvesEveryKnownState)
328{
329 ExpectModuleStates({
330 {MODULE_STATE_NO_MODULE, "NoModule"},
331 {MODULE_STATE_WRONG_MODULE, "WrongModule"},
332 {MODULE_STATE_PROPER_MODULE, "ProperModule"},
333 {MODULE_STATE_SUBSTITUTE_MODULE, "SubstituteModule"},
334 });
335}
336
338TEST_F(IndicesTest, GetModuleStateNameFallsBackForUnknownState)
339{
340 EXPECT_EQ(GetModuleStateName(0x9999), "Unknown(0x9999)");
341}
342
344TEST_F(IndicesTest, GetSubmoduleStateNameResolvesEveryKnownState)
345{
346 ExpectSubmoduleStates({
347 {SUBMODULE_STATE_NO_SUBMODULE, "NoSubmodule"},
348 {SUBMODULE_STATE_WRONG_SUBMODULE, "WrongSubmodule"},
349 {SUBMODULE_STATE_LOCKED_BY_SUPERVISOR, "LockedBySupervisor"},
350 {SUBMODULE_STATE_APPLICATION_READY_PENDING, "ApplicationReadyPending"},
351 {SUBMODULE_STATE_OK, "OK"},
352 });
353}
354
356TEST_F(IndicesTest, GetSubmoduleStateNameFallsBackForUnknownState)
357{
358 EXPECT_EQ(GetSubmoduleStateName(0x9999), "Unknown(0x9999)");
359}
360
362TEST_F(IndicesTest, GetPeModeNameResolvesFixedModes)
363{
364 ExpectPeModes({
365 {PE_MODE_POWER_OFF, "PE_PowerOff"},
366 {PE_MODE_OPERATE, "PE_Operate"},
367 {PE_MODE_SLEEP_MODE_WOL, "PE_SleepModeWOL"},
368 {PE_MODE_READY_TO_OPERATE, "PE_ReadyToOperate"},
369 });
370}
371
373TEST_F(IndicesTest, GetPeModeNameResolvesEnergySavingRange)
374{
375 for (std::uint8_t mode = PE_MODE_ENERGY_SAVING_MIN; mode <= PE_MODE_ENERGY_SAVING_MAX; ++mode)
376 {
377 EXPECT_EQ(GetPeModeName(mode), "PE_EnergySavingMode_" + std::to_string(mode) + "(" + Hex2(mode) + ")");
378 }
379}
380
382TEST_F(IndicesTest, GetPeModeNameReturnsReservedForValueBetweenEnergySavingAndOperate)
383{
384 EXPECT_EQ(GetPeModeName(0x20), "PE_Reserved(0x20)");
385}
386
388TEST_F(IndicesTest, GetPeModeNameReturnsReservedForValueBetweenOperateAndSleepMode)
389{
390 EXPECT_EQ(GetPeModeName(0xF1), "PE_Reserved(0xF1)");
391}
392
394TEST_F(IndicesTest, GetPeModeNameReturnsReservedForValueBetweenSleepModeAndReadyToOperate)
395{
396 EXPECT_EQ(GetPeModeName(0x1F), "PE_EnergySavingMode_31(" + Hex2(PE_MODE_ENERGY_SAVING_MAX) + ")");
397 EXPECT_EQ(GetPeModeName(0xF0), "PE_Operate");
398
399 for (uint16_t mode = 0x20; mode <= 0xEF; ++mode)
400 {
401 const auto byteMode = static_cast<uint8_t>(mode);
402 EXPECT_EQ(GetPeModeName(byteMode), "PE_Reserved(" + Hex2(byteMode) + ")");
403 }
404}
405
407TEST_F(IndicesTest, DiagnosisIndicesReturnsSubslotTable)
408{
409 const IndexNamePairs expected = {
410 {DIAG_CHANNEL_SUBSLOT, "DiagnosisChannel"},
411 {DIAG_ALL_SUBSLOT, "DiagnosisAll"},
412 {DIAG_MAINTENANCE_SUBSLOT, "DiagnosisMaintenance"},
413 };
414
415 ExpectIndexTable(DiagnosisIndices("subslot"), expected);
416}
417
419TEST_F(IndicesTest, DiagnosisIndicesReturnsSlotTable)
420{
421 const IndexNamePairs expected = {
422 {DIAG_CHANNEL_SLOT, "DiagnosisChannel"},
423 {DIAG_ALL_SLOT, "DiagnosisAll"},
424 {DIAG_MAINTENANCE_SLOT, "DiagnosisMaintenance"},
425 };
426
427 ExpectIndexTable(DiagnosisIndices("slot"), expected);
428}
429
431TEST_F(IndicesTest, DiagnosisIndicesReturnsArTable)
432{
433 const IndexNamePairs expected = {
434 {DIAG_CHANNEL_AR, "DiagnosisChannel"},
435 {DIAG_ALL_AR, "DiagnosisAll"},
436 {DIAG_MAINTENANCE_AR, "DiagnosisMaintenance"},
437 };
438
439 ExpectIndexTable(DiagnosisIndices("ar"), expected);
440}
441
443TEST_F(IndicesTest, DiagnosisIndicesReturnsApiTable)
444{
445 const IndexNamePairs expected = {
446 {DIAG_CHANNEL_API, "DiagnosisChannel"},
447 {DIAG_ALL_API, "DiagnosisAll"},
448 {DIAG_MAINTENANCE_API, "DiagnosisMaintenance"},
449 };
450
451 ExpectIndexTable(DiagnosisIndices("api"), expected);
452}
453
455TEST_F(IndicesTest, DiagnosisIndicesReturnsDeviceTable)
456{
457 const IndexNamePairs expected = {
458 {DIAG_DEVICE, "DeviceDiagnosis"},
459 };
460
461 ExpectIndexTable(DiagnosisIndices("device"), expected);
462}
463
465TEST_F(IndicesTest, DiagnosisIndicesReturnsEmptyTableForUnknownScopes)
466{
467 EXPECT_TRUE(DiagnosisIndices("").empty());
468 EXPECT_TRUE(DiagnosisIndices("unknown").empty());
469 EXPECT_TRUE(DiagnosisIndices("SUBSLOT").empty());
470}
471
473TEST_F(IndicesTest, CriticalIndicesReturnsExpectedEntries)
474{
475 const IndexNamePairs expected = {
476 {IM0, "I&M0 (mandatory)"},
477 {IM0_FILTER_DATA, "I&M0FilterData"},
478 {DIAG_DEVICE, "Device Diagnosis"},
479 {MODULE_DIFF_BLOCK, "ModuleDiffBlock"},
480 {PD_REAL_DATA, "PDRealData"},
481 {AR_DATA, "ARData"},
482 {LOG_DATA, "LogData"},
483 };
484
485 ExpectIndexTable(CriticalIndices(), expected);
486}
487
489TEST_F(IndicesTest, ImIndicesReturnsAllImEntries)
490{
491 const auto& indices = ImIndices();
492
493 ASSERT_EQ(indices.size(), 16U);
494
495 for (std::size_t i = 0; i < indices.size(); ++i)
496 {
497 EXPECT_EQ(indices[i].first, static_cast<std::uint16_t>(IM0 + i));
498 EXPECT_EQ(indices[i].second, "I&M" + std::to_string(i));
499 }
500}
501
503TEST_F(IndicesTest, PortIndicesReturnsExpectedEntries)
504{
505 const IndexNamePairs expected = {
506 {PD_PORT_DATA_REAL, "PDPortDataReal"},
507 {PD_PORT_DATA_CHECK, "PDPortDataCheck"},
508 {PD_PORT_DATA_ADJUST, "PDPortDataAdjust"},
509 {PD_PORT_STATISTIC, "PDPortStatistic"},
510 {PD_PORT_MRP_DATA_REAL, "PDPortMrpDataReal"},
511 };
512
513 ExpectIndexTable(PortIndices(), expected);
514}
515
517TEST_F(IndicesTest, InterfaceIndicesReturnsExpectedEntries)
518{
519 const IndexNamePairs expected = {
520 {PD_INTERFACE_DATA_REAL, "PDInterfaceDataReal"},
521 {PD_INTERFACE_MRP_DATA_REAL, "PDInterfaceMrpDataReal"},
522 {PD_NC_DATA_CHECK, "PDNCDataCheck"},
523 };
524
525 ExpectIndexTable(InterfaceIndices(), expected);
526}
527
529TEST_F(IndicesTest, DeviceIndicesReturnsExpectedEntries)
530{
531 const IndexNamePairs expected = {
532 {AR_DATA, "ARData"},
533 {API_DATA, "APIData"},
534 {PDEV_DATA, "PDevData"},
535 {PD_REAL_DATA, "PDRealData"},
536 {PD_EXPECTED_DATA, "PDExpectedData"},
537 {LOG_DATA, "LogData"},
538 {AUTO_CONFIG, "AutoConfiguration"},
539 };
540
541 ExpectIndexTable(DeviceIndices(), expected);
542}
543
545TEST_F(IndicesTest, AllStandardIndicesContainsAllStandardCategories)
546{
547 const auto& indices = AllStandardIndices();
548
549 EXPECT_FALSE(indices.empty());
550
551 EXPECT_NE(std::ranges::find_if(indices.begin(), indices.end(), [](const auto& entry)
552 { return entry.first == IM0; }),
553 indices.end());
554 EXPECT_NE(std::ranges::find_if(indices.begin(), indices.end(), [](const auto& entry)
555 { return entry.first == DIAG_CHANNEL_SUBSLOT; }),
556 indices.end());
557 EXPECT_NE(std::ranges::find_if(indices.begin(), indices.end(), [](const auto& entry)
558 { return entry.first == DIAG_DEVICE; }),
559 indices.end());
560 EXPECT_NE(std::ranges::find_if(indices.begin(), indices.end(), [](const auto& entry)
561 { return entry.first == PD_PORT_DATA_REAL; }),
562 indices.end());
563 EXPECT_NE(std::ranges::find_if(indices.begin(), indices.end(), [](const auto& entry)
564 { return entry.first == PD_INTERFACE_DATA_REAL; }),
565 indices.end());
566 EXPECT_NE(std::ranges::find_if(indices.begin(), indices.end(), [](const auto& entry)
567 { return entry.first == AR_DATA; }),
568 indices.end());
569 EXPECT_NE(std::ranges::find_if(indices.begin(), indices.end(), [](const auto& entry)
570 { return entry.first == EXPECTED_ID_SUBSLOT; }),
571 indices.end());
572 EXPECT_NE(std::ranges::find_if(indices.begin(), indices.end(), [](const auto& entry)
573 { return entry.first == REAL_ID_SUBSLOT; }),
574 indices.end());
575 EXPECT_NE(std::ranges::find_if(indices.begin(), indices.end(), [](const auto& entry)
576 { return entry.first == MODULE_DIFF_BLOCK; }),
577 indices.end());
578 EXPECT_NE(std::ranges::find_if(indices.begin(), indices.end(), [](const auto& entry)
579 { return entry.first == SUBSTITUTE_VALUES; }),
580 indices.end());
581 EXPECT_NE(std::ranges::find_if(indices.begin(), indices.end(), [](const auto& entry)
582 { return entry.first == RECORD_INPUT_DATA; }),
583 indices.end());
584 EXPECT_NE(std::ranges::find_if(indices.begin(), indices.end(), [](const auto& entry)
585 { return entry.first == RECORD_OUTPUT_DATA; }),
586 indices.end());
587}
588
590TEST_F(IndicesTest, GetIndexNameResolvesAllStandardCategories)
591{
592 ExpectIndexNames({
593 {IM0, "I&M0"},
594 {IM15, "I&M15"},
595 {DIAG_CHANNEL_SUBSLOT, "DiagnosisChannel"},
596 {DIAG_ALL_SUBSLOT, "DiagnosisAll"},
597 {DIAG_MAINTENANCE_SUBSLOT, "DiagnosisMaintenance"},
598 {DIAG_DEVICE, "DeviceDiagnosis"},
599 {PD_PORT_DATA_REAL, "PDPortDataReal"},
600 {PD_PORT_DATA_CHECK, "PDPortDataCheck"},
601 {PD_PORT_DATA_ADJUST, "PDPortDataAdjust"},
602 {PD_PORT_STATISTIC, "PDPortStatistic"},
603 {PD_PORT_MRP_DATA_REAL, "PDPortMrpDataReal"},
604 {PD_INTERFACE_DATA_REAL, "PDInterfaceDataReal"},
605 {PD_INTERFACE_MRP_DATA_REAL, "PDInterfaceMrpDataReal"},
606 {PD_NC_DATA_CHECK, "PDNCDataCheck"},
607 {AR_DATA, "ARData"},
608 {API_DATA, "APIData"},
609 {PDEV_DATA, "PDevData"},
610 {PD_REAL_DATA, "PDRealData"},
611 {PD_EXPECTED_DATA, "PDExpectedData"},
612 {LOG_DATA, "LogData"},
613 {AUTO_CONFIG, "AutoConfiguration"},
614 {EXPECTED_ID_SUBSLOT, "ExpectedIdentificationData"},
615 {REAL_ID_SUBSLOT, "RealIdentificationData"},
616 {MODULE_DIFF_BLOCK, "ModuleDiffBlock"},
617 {SUBSTITUTE_VALUES, "SubstituteValues"},
618 {RECORD_INPUT_DATA, "RecordInputData"},
619 {RECORD_OUTPUT_DATA, "RecordOutputData"},
620 });
621}
622
624TEST_F(IndicesTest, GetIndexNameClassifiesUserSpecificIndices)
625{
626 ExpectIndexNames({
627 {0x0000, "User-specific (0x0000)"},
628 {0x0001, "User-specific (0x0001)"},
629 {0x7FFF, "User-specific (0x7FFF)"},
630 });
631}
632
634TEST_F(IndicesTest, GetIndexNameClassifiesUnregisteredImIndices)
635{
636 ExpectIndexNames({
637 {0xAFF6, "I&M6"},
638 {0xAFF7, "I&M7"},
639 {0xAFFE, "I&M14"},
640 });
641}
642
644TEST_F(IndicesTest, GetIndexNameClassifiesUnregisteredSubslotIndices)
645{
646 ExpectIndexNames({
647 {0x8004, "Subslot data (0x8004)"},
648 {0x80FF, "Subslot data (0x80FF)"},
649 {0x8FFF, "Subslot data (0x8FFF)"},
650 });
651}
652
654TEST_F(IndicesTest, GetIndexNameClassifiesUnregisteredSlotIndices)
655{
656 ExpectIndexNames({
657 {0xC100, "Slot data (0xC100)"},
658 {0xCFFF, "Slot data (0xCFFF)"},
659 });
660}
661
663TEST_F(IndicesTest, GetIndexNameClassifiesUnregisteredArIndices)
664{
665 ExpectIndexNames({
666 {0xE100, "AR data (0xE100)"},
667 {0xEFFF, "AR data (0xEFFF)"},
668 });
669}
670
672TEST_F(IndicesTest, GetIndexNameClassifiesUnregisteredApiIndices)
673{
674 ExpectIndexNames({
675 {0xF100, "API data (0xF100)"},
676 {0xF7FF, "API data (0xF7FF)"},
677 });
678}
679
681TEST_F(IndicesTest, GetIndexNameClassifiesUnregisteredDeviceIndices)
682{
683 ExpectIndexNames({
684 {0xF900, "Device data (0xF900)"},
685 {0xFBFF, "Device data (0xFBFF)"},
686 });
687}
688
690TEST_F(IndicesTest, GetIndexNameReturnsUnknownForUnclassifiedIndices)
691{
692 ExpectIndexNames({
693 {0x9000, "Unknown (0x9000)"},
694 {0x9FFF, "Unknown (0x9FFF)"},
695 {0xB000, "Unknown (0xB000)"},
696 {0xFFFF, "Unknown (0xFFFF)"},
697 });
698}
699
701TEST_F(IndicesTest, GetScopeClassifiesAllSupportedScopes)
702{
703 ExpectScopes({
704 {0x0000, "user"},
705 {0x7FFF, "user"},
706 {0x8000, "subslot"},
707 {0x8FFF, "subslot"},
708 {0xA000, "slot"},
709 {0xAFFF, "slot"},
710 {0xC000, "slot"},
711 {0xCFFF, "slot"},
712 {0xE000, "ar"},
713 {0xEFFF, "ar"},
714 {0xF000, "api"},
715 {0xF7FF, "api"},
716 {0xF800, "device"},
717 {0xFBFF, "device"},
718 });
719}
720
722TEST_F(IndicesTest, GetScopeReturnsUnknownForUnclassifiedRanges)
723{
724 ExpectScopes({
725 {0x9000, "unknown"},
726 {0x9FFF, "unknown"},
727 {0xB000, "unknown"},
728 {0xFFFF, "unknown"},
729 });
730}
731
732} // namespace profinet
void ExpectIndexNames(const std::vector< std::pair< std::uint16_t, std::string > > &values)
Verifies that every supplied index resolves to its expected name.
void ExpectIocrTypeNames(const std::vector< std::pair< IocrType, std::string > > &values)
Verifies that every supplied IocrType resolves to its expected name.
void ExpectScopes(const std::vector< std::pair< std::uint16_t, std::string > > &values)
Verifies that every supplied index resolves to its expected scope.
void ExpectModuleStates(const std::vector< std::pair< std::uint16_t, std::string > > &values)
Verifies that every supplied state value resolves to its expected name.
void ExpectIndexTable(const IndexNamePairs &actual, const IndexNamePairs &expected)
Verifies that an index table contains exactly the supplied entries.
void ExpectSubmoduleStates(const std::vector< std::pair< std::uint16_t, std::string > > &values)
Verifies that every supplied submodule state value resolves to its expected name.
void ExpectIocrRtClassNames(const std::vector< std::pair< IocrRtClass, std::string > > &values)
Verifies that every supplied IocrRtClass resolves to its expected name.
void ExpectUsiNames(const std::vector< std::pair< Usi, std::string > > &values)
Verifies that every supplied USI resolves to its expected name.
void ExpectBlockTypeNames(const std::vector< std::pair< BlockType, std::string > > &values)
Verifies that every supplied BlockType resolves to its expected name.
void ExpectAlarmTypeNames(const std::vector< std::pair< AlarmType, std::string > > &values)
Verifies that every supplied AlarmType resolves to its expected name.
void ExpectPeModes(const std::vector< std::pair< std::uint8_t, std::string > > &values)
Verifies that every supplied PROFIenergy mode resolves to its expected name.
PROFINET record-data indices, block types, and protocol enumerations.
std::string Hex2(std::uint8_t value)
Format an 8-bit unsigned integer as a 2-digit hexadecimal string.
Definition util.cpp:49
constexpr std::uint16_t PD_PORT_DATA_REAL
PD Port Data Real.
Definition indices.h:830
constexpr std::uint16_t AR_DATA
AR Data.
Definition indices.h:809
constexpr std::uint16_t DIAG_DEVICE
DIAG Device.
Definition indices.h:770
BlockType
PROFINET block types.
Definition indices.h:89
@ PortDataRealExtended
PD Port Data Real Extended block.
@ MrpRingStateData
MRP Ring State Data block.
@ IoCrRequest
IOCR block request.
@ SubmoduleList
Submodule list block.
@ PortDataCheck
PD Port Data Check block.
@ IdentificationMaintenance2
I&M2 block.
@ ExpectedProcessData
PD Expected Data block.
@ IdentificationMaintenance4
I&M4 block.
@ ControlPrmEndRequest
IOD Control Prm End request.
@ RealIdentificationDataApi
Real Identification Data API block.
@ InterfaceMrpDataAdjust
PD Interface MRP Data Adjust block.
@ AlarmAcknowledgementLow
Alarm acknowledgement low block.
@ IoDataReadResponse
IOD read response block.
@ PortFoDataReal
PD Port FO Data Real block.
@ ApplicationRelationRequest
AR block request.
@ IdentificationMaintenance14
I&M14 block.
@ AlarmAcknowledgementHigh
Alarm acknowledgement high block.
@ IdentificationMaintenance13
I&M13 block.
@ ControlPrmEndResponse
IOD Control Prm End response.
@ IdentificationMaintenance10
I&M10 block.
@ PortMrpDataReal
PD Port MRP Data Real block.
@ PortStatistics
PD Port Statistic block.
@ AlarmNotificationHigh
Alarm notification high block.
@ ModuleDifference
Module difference block.
@ ReleaseResponse
IOD Release response.
@ IdentificationMaintenance11
I&M11 block.
@ ControlRtClass3Request
IOD Control RT Class 3 request.
@ IdentificationMaintenance7
I&M7 block.
@ LogData
LogData block.
@ ExpectedIdentificationData
Expected identification data block.
@ PortFoDataCheck
PD Port FO Data Check block.
@ IdentificationMaintenance6
I&M6 block.
@ PortDataReal
PD Port Data Real block.
@ ExpectedSubmoduleRequest
Expected submodule block request.
@ AlarmCrRequest
AlarmCR block request.
@ ReleaseRequest
IOD Release request.
@ IdentificationMaintenance3
I&M3 block.
@ ContainerContent
CO Container Content block.
@ AlarmCrResponse
AlarmCR block response.
@ DiagnosisData
Diagnosis data block.
@ IdentificationMaintenance8
I&M8 block.
@ ControlApplicationReadyRequest
IOD Control Application Ready request.
@ ApplicationRelationServer
AR Server Block.
@ IdentificationMaintenance1
I&M1 block.
@ IdentificationMaintenance12
I&M12 block.
@ ApplicationRelationResponse
AR block response.
@ RealProcessData
PD Real Data block.
@ IoCrResponse
IOCR block response.
@ ParameterizationBeginRequest
Parameterization Begin request.
@ IoDataWriteResponse
IOD write response block.
@ ApiData
API data block.
@ ParameterizationBeginResponse
Parameterization Begin response.
@ ApplicationRelationData
ARData block.
@ InterfaceMrpDataReal
PD Interface MRP Data Real block.
@ IoDataWriteRequest
IOD write request block.
@ ControlApplicationReadyResponse
IOD Control Application Ready response.
@ RealIdentificationData
Real identification data block.
@ IoDataReadRequest
IOD read request block.
@ PortDataAdjust
PD Port Data Adjust block.
@ PortDataInterfaceDataReal
PD Interface Data Real block.
@ IdentificationMaintenance15
I&M15 block.
@ PortFoDataAdjust
PD Port FO Data Adjust block.
@ MultipleHeader
Multiple Header block.
@ SrlData
SRL data block.
@ IdentificationMaintenance0
I&M0 block.
@ ControlRtClass3Response
IOD Control RT Class 3 response.
@ AlarmNotificationLow
Alarm notification low block.
@ IdentificationMaintenance9
I&M9 block.
@ IdentificationMaintenance5
I&M5 block.
constexpr std::uint16_t DIAG_ALL_API
DIAG All API.
Definition indices.h:765
const IndexNamePairs & DiagnosisIndices(const std::string &scope)
Diagnosis indices for a given addressing scope.
Definition indices.cpp:532
TEST_F(AlarmListenerTests, InitializesWithEndpoint)
constexpr std::uint8_t PE_MODE_ENERGY_SAVING_MAX
PE Mode Energy Saving Max.
Definition indices.h:681
const IndexNamePairs & CriticalIndices()
Critical indices that should always be tested.
Definition indices.cpp:495
constexpr std::uint16_t SUBSTITUTE_VALUES
Substitute Values.
Definition indices.h:916
std::string GetIocrRtClassName(IocrRtClass rtClass)
Get the human-readable name for an IOCR real-time class.
Definition indices.cpp:373
std::string GetScope(std::uint16_t index)
Get the addressing scope for an index.
Definition indices.cpp:683
std::string GetSubmoduleStateName(std::uint16_t state)
Get the human-readable name for a submodule state.
Definition indices.cpp:457
constexpr std::uint8_t PE_MODE_POWER_OFF
PE Mode Power Off.
Definition indices.h:677
std::string GetModuleStateName(std::uint16_t state)
Get the human-readable name for a module state.
Definition indices.cpp:445
constexpr std::uint16_t PD_REAL_DATA
PD Real Data.
Definition indices.h:815
constexpr std::uint16_t SUBMODULE_STATE_APPLICATION_READY_PENDING
Submodule State Application Ready Pending.
Definition indices.h:656
constexpr std::uint16_t DIAG_ALL_AR
DIAG All AR.
Definition indices.h:758
constexpr std::uint16_t MODULE_DIFF_BLOCK
Module Diff Block.
Definition indices.h:803
std::string GetBlockTypeName(BlockType blockType)
Get the human-readable name for a block type.
Definition indices.cpp:38
AlarmType
PROFINET Alarm Types used in AlarmNotification blocks.
Definition indices.h:382
@ Update
Update alarm.
@ IsochronousModeProblem
Isochronous mode problem alarm.
@ MulticastMismatch
Multicast mismatch alarm.
@ PlugWrongSubmodule
Plug wrong submodule alarm.
@ DfpProblem
DFP problem alarm.
@ Plug
Plug alarm.
@ ReturnOfSubmodule
Return of submodule alarm.
@ Diagnosis
Diagnosis alarm.
@ PortDataChange
Port data change alarm.
@ SyncDataChanged
Sync data changed alarm.
@ Pull
Pull alarm.
@ ControlledBySupervisor
Controlled by supervisor alarm.
@ NetworkComponentProblem
Network component problem alarm.
@ Process
Process alarm.
@ Released
Released alarm.
@ TimeDataChanged
Time data changed alarm.
@ Status
Status alarm.
@ Redundancy
Redundancy alarm.
@ PullModule
Pull module alarm.
@ UploadRetrieval
Upload retrieval alarm.
@ DiagnosisDisappears
Diagnosis disappears alarm.
constexpr std::uint16_t DIAG_MAINTENANCE_SUBSLOT
DIAG Maintenance Subslot.
Definition indices.h:746
constexpr std::uint16_t SUBMODULE_STATE_NO_SUBMODULE
Submodule State No Submodule.
Definition indices.h:650
const IndexNamePairs & AllStandardIndices()
Union of every standard index category.
Definition indices.cpp:618
std::string GetUsiName(Usi usi)
Get the human-readable name for a User Structure Identifier.
Definition indices.cpp:386
IocrType
PROFINET IOCR types.
Definition indices.h:463
@ MulticastConsumer
Multicast consumer IOCR.
@ Output
Output IOCR.
@ Input
Input IOCR.
@ MulticastProvider
Multicast provider IOCR.
std::string GetPeModeName(std::uint8_t mode)
Get the human-readable name for a PROFIenergy operational mode.
Definition indices.cpp:470
constexpr std::uint16_t IM0
I&M0.
Definition indices.h:701
constexpr std::uint16_t PD_PORT_MRP_DATA_REAL
PD Port MRP Data Real.
Definition indices.h:888
std::vector< std::pair< std::uint16_t, std::string > > IndexNamePairs
(index, name) pairs, e.g. for building a "try each of these" scan.
Definition indices.h:1001
constexpr std::uint16_t SUBMODULE_STATE_WRONG_SUBMODULE
Submodule State Wrong Submodule.
Definition indices.h:652
constexpr std::uint16_t DIAG_CHANNEL_API
DIAG Channel API.
Definition indices.h:763
constexpr std::uint16_t EXPECTED_ID_SUBSLOT
Expected ID Subslot.
Definition indices.h:794
constexpr std::uint16_t DIAG_CHANNEL_SLOT
DIAG Channel Slot.
Definition indices.h:749
constexpr std::uint16_t DIAG_ALL_SLOT
DIAG All Slot.
Definition indices.h:751
constexpr std::uint8_t PE_MODE_SLEEP_MODE_WOL
PE Mode Sleep Mode WOL.
Definition indices.h:685
constexpr std::uint16_t IM15
I&M15.
Definition indices.h:731
std::string GetIocrTypeName(IocrType iocrType)
Get the human-readable name for an IOCR type.
Definition indices.cpp:350
constexpr std::uint16_t DIAG_MAINTENANCE_AR
DIAG Maintenance AR.
Definition indices.h:760
constexpr std::uint16_t MODULE_STATE_SUBSTITUTE_MODULE
Module State Substitute Module.
Definition indices.h:647
constexpr std::uint16_t MODULE_STATE_PROPER_MODULE
Module State Proper Module.
Definition indices.h:645
constexpr std::uint16_t DIAG_CHANNEL_AR
DIAG Channel AR.
Definition indices.h:756
const IndexNamePairs & DeviceIndices()
Device-level indices.
Definition indices.cpp:604
constexpr std::uint16_t RECORD_INPUT_DATA
Record Input Data.
Definition indices.h:918
constexpr std::uint16_t LOG_DATA
Log Data.
Definition indices.h:821
const IndexNamePairs & ImIndices()
I&M0-I&M15 indices.
Definition indices.cpp:509
constexpr std::uint16_t AUTO_CONFIG
Auto Config.
Definition indices.h:819
constexpr std::uint16_t DIAG_MAINTENANCE_API
DIAG Maintenance API.
Definition indices.h:767
constexpr std::uint16_t SUBMODULE_STATE_OK
Submodule State Ok.
Definition indices.h:658
constexpr std::uint16_t IM0_FILTER_DATA
I&M0 Filter Data.
Definition indices.h:733
Usi
PROFINET User Structure Identifiers (USI).
Definition indices.h:526
@ Maintenance
Maintenance item.
@ MultipleDiagnosis
Multiple diagnosis.
@ IParameter
iParameter item.
@ PralAlarm
PRAL alarm item.
@ Upload
Upload record.
@ ExtendedChannelDiagnosis
Extended channel diagnosis.
@ PeAlarm
PE alarm item.
@ ChannelDiagnosis
Channel diagnosis.
@ RsAlarmHigh
RS alarm item for high alarm.
@ RsAlarmSubmodule
RS alarm item for submodule.
@ RsAlarmLow
RS alarm item for low alarm.
@ QualifiedChannelDiagnosis
Qualified channel diagnosis.
constexpr std::uint16_t DIAG_MAINTENANCE_SLOT
DIAG Maintenance Slot.
Definition indices.h:753
constexpr std::uint16_t PDEV_DATA
Pdev Data.
Definition indices.h:813
constexpr std::uint16_t PD_INTERFACE_DATA_REAL
PD Interface Data Real.
Definition indices.h:853
constexpr std::uint16_t PD_EXPECTED_DATA
PD Expected Data.
Definition indices.h:817
constexpr std::uint16_t DIAG_ALL_SUBSLOT
DIAG All Subslot.
Definition indices.h:744
constexpr std::uint16_t PD_PORT_DATA_CHECK
PD Port Data Check.
Definition indices.h:832
constexpr std::uint16_t MODULE_STATE_NO_MODULE
Module State No Module.
Definition indices.h:641
constexpr std::uint16_t PD_NC_DATA_CHECK
PD NC Data Check.
Definition indices.h:849
constexpr std::uint8_t PE_MODE_ENERGY_SAVING_MIN
PE Mode Energy Saving Min.
Definition indices.h:679
constexpr std::uint16_t REAL_ID_SUBSLOT
Real ID Subslot.
Definition indices.h:796
constexpr std::uint16_t API_DATA
API Data.
Definition indices.h:811
constexpr std::uint8_t PE_MODE_READY_TO_OPERATE
PE Mode Ready To Operate.
Definition indices.h:687
const IndexNamePairs & InterfaceIndices()
Interface-level indices.
Definition indices.cpp:594
std::string GetIndexName(std::uint16_t index)
Get the human-readable name for a record data index.
Definition indices.cpp:642
std::string GetAlarmTypeName(AlarmType alarmType)
Get the human-readable name for an alarm type.
Definition indices.cpp:278
const IndexNamePairs & PortIndices()
Port-level indices.
Definition indices.cpp:582
constexpr std::uint8_t PE_MODE_OPERATE
PE Mode Operate.
Definition indices.h:683
constexpr std::uint16_t RECORD_OUTPUT_DATA
Record Output Data.
Definition indices.h:920
constexpr std::uint16_t MODULE_STATE_WRONG_MODULE
Module State Wrong Module.
Definition indices.h:643
constexpr std::uint16_t PD_PORT_DATA_ADJUST
PD Port Data Adjust.
Definition indices.h:838
constexpr std::uint16_t DIAG_CHANNEL_SUBSLOT
DIAG Channel Subslot.
Definition indices.h:742
constexpr std::uint16_t PD_PORT_STATISTIC
PD Port Statistic.
Definition indices.h:840
IocrRtClass
PROFINET IOCR real-time classes.
Definition indices.h:490
@ Udp
UDP real-time class.
constexpr std::uint16_t PD_INTERFACE_MRP_DATA_REAL
PD Interface MRP Data Real.
Definition indices.h:879
constexpr std::uint16_t SUBMODULE_STATE_LOCKED_BY_SUPERVISOR
Submodule State Locked By Supervisor.
Definition indices.h:654
Declares Linux Ethernet, addressing, timing, and utility helpers used by the PROFINET stack.