9#include <gtest/gtest.h>
29constexpr MacAddress kDeviceMac{0x02, 0x00, 0x00, 0x00, 0x00, 0x01};
58std::unique_ptr<CyclicController> MakeController()
62 return std::make_unique<CyclicController>(
63 ioContext,
"eth0", kControllerMac, kDeviceMac,
75TEST(SanitizerConcurrencyTest, ConcurrentStatisticsSnapshotIsRaceFree)
77 auto tx = std::make_unique<testing::NiceMock<MockRawEthernetSocket>>();
78 auto rx = std::make_unique<testing::NiceMock<MockRawEthernetSocket>>();
84 std::atomic<bool> stop{
false};
85 std::atomic<std::uint64_t> snapshots{0U};
87 std::thread reader([&]()
89 while (!stop.load(std::memory_order_acquire))
91 const auto snapshot = controller->StatsSnapshot();
92 static_cast<void>(snapshot.framesSent);
93 static_cast<void>(snapshot.framesReceived);
94 static_cast<void>(snapshot.framesMissed);
95 static_cast<void>(snapshot.cycleCount);
96 static_cast<void>(snapshot.cycleTimeSumUs);
97 static_cast<void>(snapshot.AvgCycleTimeUs());
98 snapshots.fetch_add(1U, std::memory_order_relaxed);
102 std::this_thread::sleep_for(std::chrono::milliseconds(20));
104 stop.store(
true, std::memory_order_release);
108 EXPECT_GT(snapshots.load(std::memory_order_relaxed), 0U);
114TEST(SanitizerConcurrencyTest, ConcurrentOutputDataWritersAreRaceFree)
118 constexpr std::size_t kWriterCount = 4U;
119 constexpr std::size_t kIterations = 5000U;
120 std::atomic<bool> failed{
false};
122 std::vector<std::thread> writers;
123 writers.reserve(kWriterCount);
125 for (std::size_t writerIndex = 0U; writerIndex < kWriterCount; ++writerIndex)
127 writers.emplace_back([&, writerIndex]()
129 for (std::size_t iteration = 0U; iteration < kIterations; ++iteration)
133 const std::size_t
length = (iteration % 16U) + 1U;
134 const auto value =
static_cast<std::uint8_t
>(writerIndex + iteration);
139 failed.store(
true, std::memory_order_release);
146 for (
auto& writer : writers)
151 EXPECT_FALSE(failed.load(std::memory_order_acquire));
156TEST(SanitizerConcurrencyTest, RepeatedStartStopJoinsWorkers)
160 for (std::size_t iteration = 0U; iteration < 50U; ++iteration)
162 auto tx = std::make_unique<testing::NiceMock<MockRawEthernetSocket>>();
163 auto rx = std::make_unique<testing::NiceMock<MockRawEthernetSocket>>();
168 std::this_thread::sleep_for(std::chrono::milliseconds(2));
172 EXPECT_EQ(
controller->State(), CyclicState::Stopped);
179TEST(SanitizerConcurrencyTest, DestructionAfterWorkerActivityIsClean)
181 for (std::size_t iteration = 0U; iteration < 25U; ++iteration)
183 auto tx = std::make_unique<testing::NiceMock<MockRawEthernetSocket>>();
184 auto rx = std::make_unique<testing::NiceMock<MockRawEthernetSocket>>();
188 std::this_thread::sleep_for(std::chrono::milliseconds(2));
Declares the PROFINET RTC1 cyclic IO controller and process-data exchange API.
GoogleMock implementation of IRawEthernetSocket.
constexpr int DEFAULT_MAX_CONSECUTIVE_TIMEOUTS
Default number of consecutive watchdog timeouts before transitioning to Fault.
constexpr std::uint16_t IOCR_TYPE_INPUT
IOCR direction: Device -> Controller.
constexpr std::uint16_t ETHERTYPE_PROFINET
EtherType used by PROFINET RT frames (0x8892).
constexpr std::uint16_t IOCR_TYPE_OUTPUT
IOCR direction: Controller -> Device.
constexpr MacAddress kControllerMac
TEST(AlarmEndpointTests, DefaultTransportIsLayer2)
std::array< std::uint8_t, macAddressLength > MacAddress
A 6-byte Ethernet MAC address.
constexpr std::uint16_t kInputFrameId
std::vector< std::uint8_t > Bytes
Generic byte buffer alias used throughout the library for raw wire data.
constexpr std::uint16_t kOutputFrameId
Declares PROFINET RT_CLASS_1 cyclic frame and IOCR data structures.
IOCR configuration derived from AR setup: timing parameters and IO object mappings needed for cyclic ...
std::vector< IODataObject > objects
IO data objects carried in this IOCR's cyclic frame.
std::uint16_t dataLength
Total cyclic data length in bytes.
std::uint16_t typeIOCR
IOCR direction: 1=Input, 2=Output.
std::uint16_t sendClockFactor
Send clock base factor (31.25us units).
std::uint16_t frameId
Frame ID assigned to this IOCR.
std::uint16_t reductionRatio
Reduction ratio relative to the send clock.
std::uint16_t watchdogFactor
Watchdog factor (missed-frame tolerance before a timeout fault).
Single IO data object within the C_SDU: one piece of process data mapped to a slot/subslot,...
std::uint16_t slot
Slot number.
std::uint16_t frameId
Ethernet FrameID.
std::unique_ptr< MockRawEthernetSocket > tx
std::unique_ptr< MockRawEthernetSocket > rx
std::unique_ptr< cyclic::CyclicController > controller
std::unique_ptr< asio::io_context > ioContext
Shared ASIO context.