PROFINET IO Controller Stack 1.0.0
Modern C++ implementation of a PROFINET IO Controller stack
Loading...
Searching...
No Matches
test_ethernetPacketBackend.cpp
Go to the documentation of this file.
1
8
9#include <chrono>
10#include <cstdint>
11#include <stdexcept>
12#include <vector>
13
15#include "profinet/exceptions.h"
16#include "profinet/protocol.h"
17#include "profinet/util.h"
18
19using namespace profinet;
20using namespace std::chrono_literals;
21
22namespace
23{
24constexpr std::uint16_t kTestEtherType = 0x88B5;
25
26const Bytes kUntaggedFrame{
27 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
28 0x02, 0x00, 0x00, 0x00, 0x00, 0x01,
29 0x88, 0xB5,
30 0x01, 0x02, 0x03, 0x04};
31
32const Bytes kSingleVlanFrame{
33 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
34 0x02, 0x00, 0x00, 0x00, 0x00, 0x02,
35 0x81, 0x00,
36 0x00, 0x64,
37 0x88, 0xB5,
38 0x05, 0x06, 0x07, 0x08};
39
40const Bytes kQinQFrame{
41 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
42 0x02, 0x00, 0x00, 0x00, 0x00, 0x03,
43 0x88, 0xA8,
44 0x00, 0x64,
45 0x81, 0x00,
46 0x00, 0x65,
47 0x88, 0xB5,
48 0x09, 0x0A, 0x0B, 0x0C};
49} // namespace
50
52TEST_F(EthernetPacketBackendTestFixture, ConstructorRejectsEmptyInterface)
53{
54 EXPECT_THROW(CreateBackend(""), SocketError);
55}
56
58TEST_F(EthernetPacketBackendTestFixture, ConstructorRejectsUnknownInterface)
59{
60 EXPECT_THROW(CreateBackend("this-interface-does-not-exist"), SocketError);
61}
62
64TEST_F(EthernetPacketBackendTestFixture, ConstructorAcceptsConfiguredInterface)
65{
66 const auto interfaceValue = GetTestInterface();
67 if (!interfaceValue.has_value())
68 {
69 GTEST_SKIP() << "Set PROFINET_TEST_INTERFACE to run live Ethernet backend tests";
70 }
71 const std::string& interface = *interfaceValue;
72
73 EXPECT_NO_THROW(CreateBackend(interface, kTestEtherType));
74}
75
77TEST_F(EthernetPacketBackendTestFixture, SendAcceptsMinimumEthernetFrame)
78{
79 const auto interfaceValue = GetTestInterface();
80 if (!interfaceValue.has_value())
81 {
82 GTEST_SKIP() << "Set PROFINET_TEST_INTERFACE to run live Ethernet backend tests";
83 }
84 const std::string& interface = *interfaceValue;
85 const Bytes frame(kUntaggedFrame.begin(), kUntaggedFrame.begin() + 14);
86
87 auto backend = CreateBackend(interface, kTestEtherType);
88
89 EXPECT_NO_THROW(backend->Send(frame));
90}
91
93TEST_F(EthernetPacketBackendTestFixture, SendRejectsShortEthernetFrame)
94{
95 const auto interfaceValue = GetTestInterface();
96 if (!interfaceValue.has_value())
97 {
98 GTEST_SKIP() << "Set PROFINET_TEST_INTERFACE to run live Ethernet backend tests";
99 }
100 const std::string& interface = *interfaceValue;
101 auto backend = CreateBackend(interface, kTestEtherType);
102
103 EXPECT_THROW(backend->Send(Bytes(13U, 0x00)), std::invalid_argument);
104}
105
107TEST_F(EthernetPacketBackendTestFixture, EtherTypeFilterAcceptsMatchingUntaggedFrame)
108{
109 const auto interfaceValue = GetTestInterface();
110 if (!interfaceValue.has_value())
111 {
112 GTEST_SKIP() << "Set PROFINET_TEST_INTERFACE to run live Ethernet backend tests";
113 }
114 const std::string& interface = *interfaceValue;
115 auto backend = CreateBackend(interface, kTestEtherType);
116
117 EXPECT_TRUE(MatchesEtherType(*backend, kUntaggedFrame));
118}
119
121TEST_F(EthernetPacketBackendTestFixture, EtherTypeFilterRejectsNonMatchingUntaggedFrame)
122{
123 const auto interfaceValue = GetTestInterface();
124 if (!interfaceValue.has_value())
125 {
126 GTEST_SKIP() << "Set PROFINET_TEST_INTERFACE to run live Ethernet backend tests";
127 }
128 const std::string& interface = *interfaceValue;
129 auto backend = CreateBackend(interface, kTestEtherType);
130
131 Bytes frame = kUntaggedFrame;
132 frame[12] = 0x88;
133 frame[13] = 0x92;
134
135 EXPECT_FALSE(MatchesEtherType(*backend, frame));
136}
137
139TEST_F(EthernetPacketBackendTestFixture, EtherTypeFilterAcceptsSingleVlanTaggedFrame)
140{
141 const auto interfaceValue = GetTestInterface();
142 if (!interfaceValue.has_value())
143 {
144 GTEST_SKIP() << "Set PROFINET_TEST_INTERFACE to run live Ethernet backend tests";
145 }
146 const std::string& interface = *interfaceValue;
147 auto backend = CreateBackend(interface, kTestEtherType);
148
149 EXPECT_TRUE(MatchesEtherType(*backend, kSingleVlanFrame));
150}
151
153TEST_F(EthernetPacketBackendTestFixture, EtherTypeFilterAcceptsQinQFrame)
154{
155 const auto interfaceValue = GetTestInterface();
156 if (!interfaceValue.has_value())
157 {
158 GTEST_SKIP() << "Set PROFINET_TEST_INTERFACE to run live Ethernet backend tests";
159 }
160 const std::string& interface = *interfaceValue;
161 auto backend = CreateBackend(interface, kTestEtherType);
162
163 EXPECT_TRUE(MatchesEtherType(*backend, kQinQFrame));
164}
165
167TEST_F(EthernetPacketBackendTestFixture, EtherTypeFilterAcceptsLegacyDoubleTaggedFrame)
168{
169 const auto interfaceValue = GetTestInterface();
170 if (!interfaceValue.has_value())
171 {
172 GTEST_SKIP()
173 << "Set PROFINET_TEST_INTERFACE to run live Ethernet backend tests";
174 }
175 const std::string& interface = *interfaceValue;
176 auto backend = CreateBackend(interface, kTestEtherType);
177
178 Bytes frame{
179 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
180 0x02, 0x00, 0x00, 0x00, 0x00, 0x04,
181 0x91, 0x00,
182 0x00, 0x64,
183 0x88, 0xB5,
184 0x01, 0x02};
185
186 EXPECT_TRUE(MatchesEtherType(*backend, frame));
187}
188
190TEST_F(EthernetPacketBackendTestFixture, EtherTypeFilterRejectsFrameShorterThanHeader)
191{
192 const auto interfaceValue = GetTestInterface();
193 if (!interfaceValue.has_value())
194 {
195 GTEST_SKIP() << "Set PROFINET_TEST_INTERFACE to run live Ethernet backend tests";
196 }
197 const std::string& interface = *interfaceValue;
198 auto backend = CreateBackend(interface, kTestEtherType);
199
200 EXPECT_FALSE(MatchesEtherType(*backend, Bytes(13U, 0x00)));
201}
202
204TEST_F(EthernetPacketBackendTestFixture, EtherTypeFilterRejectsTruncatedVlanFrame)
205{
206 const auto interfaceValue = GetTestInterface();
207 if (!interfaceValue.has_value())
208 {
209 GTEST_SKIP() << "Set PROFINET_TEST_INTERFACE to run live Ethernet backend tests";
210 }
211 const std::string& interface = *interfaceValue;
212 auto backend = CreateBackend(interface, kTestEtherType);
213
214 const Bytes frame{
215 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
216 0x02, 0x00, 0x00, 0x00, 0x00, 0x05,
217 0x81, 0x00};
218
219 EXPECT_FALSE(MatchesEtherType(*backend, frame));
220}
221
223TEST_F(EthernetPacketBackendTestFixture, ZeroEtherTypeAcceptsCompleteFrame)
224{
225 const auto interfaceValue = GetTestInterface();
226 if (!interfaceValue.has_value())
227 {
228 GTEST_SKIP() << "Set PROFINET_TEST_INTERFACE to run live Ethernet backend tests";
229 }
230 const std::string& interface = *interfaceValue;
231 auto backend = CreateBackend(interface, 0U);
232
233 EXPECT_TRUE(MatchesEtherType(*backend, kUntaggedFrame));
234}
235
237TEST_F(EthernetPacketBackendTestFixture, RecvReturnsEmptyFrameOnTimeout)
238{
239 const auto interfaceValue = GetTestInterface();
240 if (!interfaceValue.has_value())
241 {
242 GTEST_SKIP() << "Set PROFINET_TEST_INTERFACE to run live Ethernet backend tests";
243 }
244 const std::string& interface = *interfaceValue;
245 auto backend = CreateBackend(interface, kTestEtherType);
246
247 backend->SetTimeout(25ms);
248
249 const Bytes received = backend->Recv();
250
251 EXPECT_TRUE(received.empty());
252}
253
255TEST_F(EthernetPacketBackendTestFixture, RecvSkipsNonMatchingTraffic)
256{
257 const auto interfaceValue = GetTestInterface();
258 if (!interfaceValue.has_value())
259 {
260 GTEST_SKIP() << "Set PROFINET_TEST_INTERFACE to run live Ethernet backend tests";
261 }
262 const std::string& interface = *interfaceValue;
263 auto sender = CreateBackend(interface, 0U);
264 auto receiver = CreateBackend(interface, kTestEtherType);
265
266 Bytes nonMatching = kUntaggedFrame;
267 nonMatching[12] = 0x88;
268 nonMatching[13] = 0x92;
269
270 receiver->SetTimeout(1000ms);
271
272 sender->Send(nonMatching);
273 sender->Send(kUntaggedFrame);
274
275 const Bytes received = receiver->Recv();
276
277 ASSERT_FALSE(received.empty());
278 EXPECT_EQ(received, kUntaggedFrame);
279}
Shared fixture for EthernetPacketBackend tests.
Socket operation error.
Definition exceptions.h:663
Shared test fixture helpers for EthernetPacketBackend tests.
Declares exceptions and error types used by the PROFINET IO controller stack.
TEST_F(AlarmListenerTests, InitializesWithEndpoint)
std::vector< std::uint8_t > Bytes
Generic byte buffer alias used throughout the library for raw wire data.
Definition protocol.h:55
PROFINET protocol wire-format structures and serialization helpers.
Bytes frame
Declares Linux Ethernet, addressing, timing, and utility helpers used by the PROFINET stack.