Implemented new C++ logic

This commit is contained in:
Martino Ferrari
2026-06-12 15:25:13 +02:00
parent 617b5bd712
commit f25bd7f08e
220 changed files with 39185 additions and 850 deletions
@@ -0,0 +1,222 @@
/**
* @file TriggerEngineGTest.cpp
* @brief Unit tests for the StreamHub hub-side trigger FSM.
*
* @copyright Copyright 2015 F4E | European Joint Undertaking for ITER and
* the Development of Fusion Energy ('Fusion for Energy').
* Licensed under the EUPL, Version 1.1 or - as soon they will be approved
* by the European Commission - subsequent versions of the EUPL (the "Licence")
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
*
* @warning Unless required by applicable law or agreed to in writing,
* software distributed under the Licence is distributed on an "AS IS"
* basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the Licence permissions and limitations under the Licence.
*/
#include "TriggerEngine.h"
#include <gtest/gtest.h>
using namespace StreamHub;
using MARTe::float64;
static TriggerConfig MakeConfig(TrigEdge edge, float64 threshold,
float64 windowSec, float64 prePercent,
TrigAcqMode mode = kTrigNormal) {
TriggerConfig cfg;
cfg.signalKey = "src:sig";
cfg.edge = edge;
cfg.threshold = threshold;
cfg.windowSec = windowSec;
cfg.prePercent = prePercent;
cfg.mode = mode;
return cfg;
}
TEST(TriggerEngineGTest, TestInitialState) {
TriggerEngine eng;
EXPECT_EQ(kTrigIdle, eng.GetState());
EXPECT_FALSE(eng.GetStopped());
float64 tt, pre, post;
EXPECT_FALSE(eng.GetFiredWindow(tt, pre, post));
}
TEST(TriggerEngineGTest, TestIdleIgnoresSamples) {
TriggerEngine eng;
eng.SetConfig(MakeConfig(kEdgeRising, 0.5, 1.0, 20.0));
eng.CheckSample(1.0, 0.0);
eng.CheckSample(2.0, 1.0); /* would fire if armed */
EXPECT_EQ(kTrigIdle, eng.GetState());
}
TEST(TriggerEngineGTest, TestRisingEdgeFires) {
TriggerEngine eng;
eng.SetConfig(MakeConfig(kEdgeRising, 0.5, 1.0, 20.0));
eng.Arm();
EXPECT_EQ(kTrigArmed, eng.GetState());
eng.CheckSample(1.0, 0.0); /* primes prevValue */
eng.CheckSample(2.0, 1.0); /* 0.0 < 0.5 <= 1.0 → fire */
EXPECT_EQ(kTrigCollecting, eng.GetState());
float64 tt, pre, post;
ASSERT_TRUE(eng.GetFiredWindow(tt, pre, post));
EXPECT_DOUBLE_EQ(2.0, tt);
EXPECT_DOUBLE_EQ(0.2, pre); /* 1.0 s × 20 % */
EXPECT_DOUBLE_EQ(0.8, post);
}
TEST(TriggerEngineGTest, TestFirstSampleNeverFires) {
TriggerEngine eng;
eng.SetConfig(MakeConfig(kEdgeRising, 0.5, 1.0, 20.0));
eng.Arm();
/* First sample above threshold must only prime the detector */
eng.CheckSample(1.0, 2.0);
EXPECT_EQ(kTrigArmed, eng.GetState());
}
TEST(TriggerEngineGTest, TestFallingEdgeFires) {
TriggerEngine eng;
eng.SetConfig(MakeConfig(kEdgeFalling, 0.5, 1.0, 50.0));
eng.Arm();
eng.CheckSample(1.0, 1.0);
eng.CheckSample(2.0, 1.5); /* rising: must not fire */
EXPECT_EQ(kTrigArmed, eng.GetState());
eng.CheckSample(3.0, 0.2); /* 1.5 > 0.5 >= 0.2 → fire */
EXPECT_EQ(kTrigCollecting, eng.GetState());
float64 tt, pre, post;
ASSERT_TRUE(eng.GetFiredWindow(tt, pre, post));
EXPECT_DOUBLE_EQ(3.0, tt);
EXPECT_DOUBLE_EQ(0.5, pre);
EXPECT_DOUBLE_EQ(0.5, post);
}
TEST(TriggerEngineGTest, TestBothEdgesFire) {
TriggerEngine eng;
eng.SetConfig(MakeConfig(kEdgeBoth, 0.0, 1.0, 0.0));
eng.Arm();
eng.CheckSample(1.0, -1.0);
eng.CheckSample(2.0, 1.0); /* rising through 0 */
EXPECT_EQ(kTrigCollecting, eng.GetState());
eng.Arm();
eng.CheckSample(3.0, 1.0);
eng.CheckSample(4.0, -1.0); /* falling through 0 */
EXPECT_EQ(kTrigCollecting, eng.GetState());
}
TEST(TriggerEngineGTest, TestNoFireBelowThreshold) {
TriggerEngine eng;
eng.SetConfig(MakeConfig(kEdgeRising, 5.0, 1.0, 20.0));
eng.Arm();
eng.CheckSample(1.0, 0.0);
eng.CheckSample(2.0, 1.0);
eng.CheckSample(3.0, 4.9);
EXPECT_EQ(kTrigArmed, eng.GetState());
}
TEST(TriggerEngineGTest, TestConfigClamping) {
TriggerEngine eng;
eng.SetConfig(MakeConfig(kEdgeRising, 0.0, 100.0, 150.0));
TriggerConfig cfg = eng.GetConfig();
EXPECT_DOUBLE_EQ(10.0, cfg.windowSec);
EXPECT_DOUBLE_EQ(100.0, cfg.prePercent);
eng.SetConfig(MakeConfig(kEdgeRising, 0.0, 1.0e-6, -5.0));
cfg = eng.GetConfig();
EXPECT_DOUBLE_EQ(1.0e-4, cfg.windowSec);
EXPECT_DOUBLE_EQ(0.0, cfg.prePercent);
}
TEST(TriggerEngineGTest, TestConfigEpochIncrements) {
TriggerEngine eng;
MARTe::uint32 e0 = eng.GetConfigEpoch();
eng.SetConfig(MakeConfig(kEdgeRising, 0.0, 1.0, 20.0));
EXPECT_EQ(e0 + 1u, eng.GetConfigEpoch());
eng.SetConfig(MakeConfig(kEdgeFalling, 1.0, 2.0, 30.0));
EXPECT_EQ(e0 + 2u, eng.GetConfigEpoch());
}
TEST(TriggerEngineGTest, TestMarkTriggeredOnlyFromCollecting) {
TriggerEngine eng;
eng.SetConfig(MakeConfig(kEdgeRising, 0.5, 1.0, 20.0));
/* Not collecting: no-op */
eng.MarkTriggered();
EXPECT_EQ(kTrigIdle, eng.GetState());
eng.Arm();
eng.MarkTriggered();
EXPECT_EQ(kTrigArmed, eng.GetState());
/* Collecting → triggered */
eng.CheckSample(1.0, 0.0);
eng.CheckSample(2.0, 1.0);
ASSERT_EQ(kTrigCollecting, eng.GetState());
eng.MarkTriggered();
EXPECT_EQ(kTrigTriggered, eng.GetState());
}
TEST(TriggerEngineGTest, TestDisarmResetsEverything) {
TriggerEngine eng;
eng.SetConfig(MakeConfig(kEdgeRising, 0.5, 1.0, 20.0));
eng.Arm();
eng.SetStopped(true);
eng.CheckSample(1.0, 0.0);
eng.CheckSample(2.0, 1.0);
ASSERT_EQ(kTrigCollecting, eng.GetState());
eng.Disarm();
EXPECT_EQ(kTrigIdle, eng.GetState());
EXPECT_FALSE(eng.GetStopped());
float64 tt, pre, post;
EXPECT_FALSE(eng.GetFiredWindow(tt, pre, post));
}
TEST(TriggerEngineGTest, TestRearmResetsEdgeDetection) {
TriggerEngine eng;
eng.SetConfig(MakeConfig(kEdgeRising, 0.5, 1.0, 20.0));
eng.Arm();
eng.CheckSample(1.0, 0.0);
eng.CheckSample(2.0, 1.0);
eng.MarkTriggered();
ASSERT_EQ(kTrigTriggered, eng.GetState());
/* Re-arm: first sample only primes even if it crosses the threshold
* relative to the value seen before the re-arm. */
eng.Arm();
EXPECT_EQ(kTrigArmed, eng.GetState());
eng.CheckSample(3.0, 0.0);
EXPECT_EQ(kTrigArmed, eng.GetState());
eng.CheckSample(4.0, 1.0);
EXPECT_EQ(kTrigCollecting, eng.GetState());
float64 tt, pre, post;
ASSERT_TRUE(eng.GetFiredWindow(tt, pre, post));
EXPECT_DOUBLE_EQ(4.0, tt);
}
TEST(TriggerEngineGTest, TestStoppedFlag) {
TriggerEngine eng;
EXPECT_FALSE(eng.GetStopped());
eng.SetStopped(true);
EXPECT_TRUE(eng.GetStopped());
eng.SetStopped(false);
EXPECT_FALSE(eng.GetStopped());
}
TEST(TriggerEngineGTest, TestWindowLatchedAtFireTime) {
TriggerEngine eng;
eng.SetConfig(MakeConfig(kEdgeRising, 0.5, 1.0, 20.0));
eng.Arm();
eng.CheckSample(1.0, 0.0);
eng.CheckSample(2.0, 1.0);
ASSERT_EQ(kTrigCollecting, eng.GetState());
/* Config edits after the fire must not change the latched window */
eng.SetConfig(MakeConfig(kEdgeRising, 0.5, 10.0, 50.0));
float64 tt, pre, post;
ASSERT_TRUE(eng.GetFiredWindow(tt, pre, post));
EXPECT_DOUBLE_EQ(0.2, pre);
EXPECT_DOUBLE_EQ(0.8, post);
}