PROFINET IO Controller Stack 1.0.0
Modern C++ implementation of a PROFINET IO Controller stack
Loading...
Searching...
No Matches
test_alarms.cpp
Go to the documentation of this file.
1
23
24#include <gtest/gtest.h>
25
26#include "profinet/alarms.h"
27
28using namespace profinet;
29using namespace profinet::wire;
30using namespace profinet;
31
32namespace
33{
34class AlarmItemTest : public ::testing::Test
35{
36};
37} // namespace
38 //
40TEST_F(AlarmItemTest, ParseChannelDiagnosis)
41{
42 Bytes data;
43 PutU16(data, static_cast<std::uint16_t>(Usi::ChannelDiagnosis));
44 PutU16(data, 0x8005); // channel_number: accumulative bit set, value 5
45 PutU16(data, 0x0001); // channel_properties
46 PutU16(data, 0x0002); // channel_error_type
47
48 auto [item, Offset] = ParseAlarmItem(data, 0);
49
50 EXPECT_EQ(Offset, data.size());
51
52 auto* diag = std::get_if<DiagnosisItem>(&item);
53 ASSERT_NE(diag, nullptr);
54
55 EXPECT_EQ(diag->ChannelNumberValue(), static_cast<std::uint16_t>(5));
56 EXPECT_TRUE(diag->IsAccumulative());
57 EXPECT_FALSE(diag->IsExtended());
58 EXPECT_EQ(diag->UsiName(), "Channel Diagnosis");
59}
60
62TEST_F(AlarmItemTest, ParseExtChannelDiagnosis)
63{
64 Bytes data;
65 PutU16(data, static_cast<std::uint16_t>(Usi::ExtendedChannelDiagnosis));
66 PutU16(data, 1);
67 PutU16(data, 2);
68 PutU16(data, 3);
69 PutU16(data, 0x1234); // ext_channel_error_type
70 PutU32(data, 0xDEADBEEF); // ext_channel_add_value
71
72 auto [item, Offset] = ParseAlarmItem(data, 0);
73
74 EXPECT_EQ(Offset, data.size());
75
76 auto* diag = std::get_if<DiagnosisItem>(&item);
77 ASSERT_NE(diag, nullptr);
78
79 EXPECT_TRUE(diag->IsExtended());
80
81 EXPECT_EQ(diag->extChannelErrorType, static_cast<std::uint16_t>(0x1234));
82
83 EXPECT_EQ(diag->extChannelAddValue, static_cast<std::uint32_t>(0xDEADBEEF));
84}
85
87TEST_F(AlarmItemTest, ParsePEAlarmItem)
88{
89 Bytes data;
90 PutU16(data, static_cast<std::uint16_t>(Usi::PeAlarm));
91 PutU16(data, 0x8310); // block_type
92 PutU16(data, 3); // block_length
93 data.push_back(0x01); // ver_high
94 data.push_back(0x00); // ver_low
95 data.push_back(0xF0); // pe_operational_mode = Operate
96
97 auto [item, Offset] = ParseAlarmItem(data, 0);
98
99 EXPECT_EQ(Offset, data.size());
100
101 auto* pe = std::get_if<PEAlarmItem>(&item);
102 ASSERT_NE(pe, nullptr);
103
104 EXPECT_EQ(pe->ModeName(), "PE_Operate");
105}
106
108TEST_F(AlarmItemTest, ParseUnknownUSI)
109{
110 Bytes data;
111 PutU16(data, 0x1234); // manufacturer-specific range
112 data.push_back(0xAA);
113 data.push_back(0xBB);
114
115 auto [item, Offset] = ParseAlarmItem(data, 0);
116
117 EXPECT_EQ(Offset, data.size());
118
119 auto* generic = std::get_if<AlarmItem>(&item);
120 ASSERT_NE(generic, nullptr);
121
122 EXPECT_EQ(generic->rawData, Bytes({0xAA, 0xBB}));
123
124 EXPECT_EQ(generic->UsiName().rfind("Manufacturer Specific", 0), 0U);
125}
126
128TEST_F(AlarmItemTest, RejectsTruncatedData)
129{
130 EXPECT_THROW(ParseAlarmItem({0x80}, 0), std::exception);
131}
132
133TEST_F(AlarmItemTest, ParseAlarmNotificationParsesHeaderAndItems)
134{
135 Bytes data;
136
137 // BlockHeader: type + block length + block version.
138 PutU16(data, static_cast<std::uint16_t>(BlockType::AlarmNotificationHigh));
139
140 // BlockLength counts everything after the BlockLength field:
141 // BlockVersion (2) + AlarmNotification fixed body (20)
142 // + ChannelDiagnosis item (8) = 30 bytes.
143 PutU16(data, 30);
144
145 PutU8(data, 0x01);
146 PutU8(data, 0x00);
147
148 // AlarmNotification fixed body (20 bytes).
149 PutU16(data, 0x0001); // alarm_type = Diagnosis
150 PutU32(data, 0); // api
151 PutU16(data, 1); // slot
152 PutU16(data, 1); // subslot
153 PutU32(data, 0); // module_ident
154 PutU32(data, 0); // submodule_ident
155 PutU16(data, 0x0805); // sequence=5, channel diagnosis bit
156
157 // One ChannelDiagnosis item (8 bytes).
158 PutU16(data, static_cast<std::uint16_t>(Usi::ChannelDiagnosis));
159 PutU16(data, 1);
160 PutU16(data, 2);
161 PutU16(data, 3);
162
164
165 ASSERT_TRUE(n.IsHighPriority());
166 EXPECT_EQ(n.AlarmTypeName(), "Diagnosis");
167 EXPECT_EQ(n.alarmSequenceNumber, static_cast<std::uint16_t>(5));
168 ASSERT_TRUE(n.channelDiagnosis);
169 EXPECT_EQ(n.Location(), "0:1:0x0001");
170
171 ASSERT_EQ(n.items.size(), static_cast<std::size_t>(1));
172 EXPECT_NE(std::get_if<DiagnosisItem>(&n.items[0]), nullptr);
173}
174
175TEST_F(AlarmItemTest, ParseAlarmNotificationRejectsTooShortData)
176{
177 EXPECT_THROW(ParseAlarmNotification(Bytes(10, 0)), std::exception);
178}
Declares PROFINET alarm, diagnosis, maintenance, and USI payload types and parsers.
void PutU8(std::vector< std::uint8_t > &out, std::uint8_t value)
Append a single byte to a buffer.
Definition wire.h:89
void PutU16(std::vector< std::uint8_t > &out, std::uint16_t value)
Append a 16-bit value to a buffer in big-endian order.
Definition wire.h:97
void PutU32(std::vector< std::uint8_t > &out, std::uint32_t value)
Append a 32-bit value to a buffer in big-endian order.
Definition wire.h:105
TEST_F(AlarmListenerTests, InitializesWithEndpoint)
std::pair< AlarmItemVariant, std::size_t > ParseAlarmItem(const Bytes &data, std::size_t offset=0)
Parse a single alarm item starting at an offset.
Definition alarms.cpp:191
AlarmNotification ParseAlarmNotification(const Bytes &data)
Parse a complete AlarmNotification PDU (BlockHeader + body + items).
Definition alarms.cpp:245
std::vector< std::uint8_t > Bytes
Generic byte buffer alias used throughout the library for raw wire data.
Definition protocol.h:55
Complete parsed AlarmNotification PDU: header fields + parsed items.
Definition alarms.h:356
std::vector< AlarmItemVariant > items
Parsed alarm items carried by this notification.
Definition alarms.h:397
std::uint16_t alarmSequenceNumber
Sequence number extracted from the alarm specifier.
Definition alarms.h:382
std::string Location() const
Location string identifying where the alarm originated.
Definition alarms.cpp:240
bool IsHighPriority() const
Whether this is a high-priority notification.
Definition alarms.h:404
bool channelDiagnosis
Whether the alarm specifier indicates channel diagnosis is present.
Definition alarms.h:385
std::string AlarmTypeName() const
Human-readable name for AlarmType.
Definition alarms.h:418