Skip to content

Commit 6541c6b

Browse files
dummy active object: add an event recorder option.
1 parent d770883 commit 6541c6b

File tree

3 files changed

+139
-3
lines changed

3 files changed

+139
-3
lines changed

cpputest-for-qpc-lib/include/cmsDummyActiveObject.hpp

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
#include <array>
3131
#include <functional>
3232
#include <cstdlib>
33+
#include "cmsVectorBackedQEQueue.hpp"
34+
#include "qevtUniquePtr.hpp"
3335

3436
namespace cms {
3537

@@ -40,17 +42,42 @@ namespace cms {
4042
template <size_t InternalEventCount>
4143
class DummyActiveObject {
4244
public:
45+
46+
enum class EventBehavior {
47+
CALLBACK, //original behavior, will call the provided callback
48+
RECORDER //will record the event
49+
};
50+
4351
using PostedEventHandler = std::function<void(QEvt const*)>;
4452

45-
explicit DummyActiveObject() :
53+
DummyActiveObject() :
4654
m_super(),
4755
m_eventHandler(nullptr),
48-
m_incomingEvents()
56+
m_incomingEvents(),
57+
m_behavior(EventBehavior::CALLBACK),
58+
m_recordedEvents(0)
4959
{
5060
m_incomingEvents.fill(nullptr);
5161
QActive_ctor(&m_super, Q_STATE_CAST(initial));
5262
}
5363

64+
explicit DummyActiveObject(EventBehavior behavior) :
65+
m_super(),
66+
m_eventHandler(nullptr),
67+
m_incomingEvents(),
68+
m_behavior(behavior),
69+
m_recordedEvents(100)
70+
{
71+
m_incomingEvents.fill(nullptr);
72+
QActive_ctor(&m_super, Q_STATE_CAST(initial));
73+
74+
if (m_behavior == EventBehavior::RECORDER) {
75+
m_eventHandler = [=](QEvt const* e) {
76+
this->RecorderEventHandler(e);
77+
};
78+
}
79+
}
80+
5481
~DummyActiveObject()
5582
{
5683
QActive_stop(&m_super);
@@ -63,7 +90,9 @@ class DummyActiveObject {
6390

6491
void SetPostedEventHandler(const PostedEventHandler& handler)
6592
{
66-
m_eventHandler = handler;
93+
if (m_behavior == EventBehavior::CALLBACK) {
94+
m_eventHandler = handler;
95+
}
6796
}
6897

6998
void dummyStart(uint_fast8_t priority = 1)
@@ -78,6 +107,30 @@ class DummyActiveObject {
78107
return &m_super;
79108
}
80109

110+
bool isRecorderEmpty() { return m_recordedEvents.isEmpty(); }
111+
112+
bool isAnyEventRecorded() { return !m_recordedEvents.isEmpty(); }
113+
114+
bool isSignalRecorded(enum_t sig)
115+
{
116+
if (!isAnyEventRecorded()) {
117+
return false;
118+
}
119+
120+
const auto e = getRecordedEvent();
121+
enum_t recordedSig = e->sig;
122+
return recordedSig == sig;
123+
}
124+
125+
cms::QEvtUniquePtr getRecordedEvent()
126+
{
127+
if (!isAnyEventRecorded()) {
128+
return {};
129+
}
130+
131+
return cms::QEvtUniquePtr(m_recordedEvents.get());
132+
}
133+
81134
protected:
82135
static QState initial(DummyActiveObject* const me,
83136
QEvt const* const)
@@ -108,10 +161,21 @@ class DummyActiveObject {
108161
return rtn;
109162
}
110163

164+
protected:
165+
void RecorderEventHandler(QEvt const * e)
166+
{
167+
if (e->sig >= Q_USER_SIG) {
168+
// record the event
169+
m_recordedEvents.post(e, QF_NO_MARGIN);
170+
}
171+
}
172+
111173
private:
112174
QActive m_super;
113175
PostedEventHandler m_eventHandler;
114176
std::array<QEvt const*, InternalEventCount> m_incomingEvents;
177+
EventBehavior m_behavior;
178+
cms::VectorBackedQEQueue m_recordedEvents;
115179
};
116180

117181
using DefaultDummyActiveObject = DummyActiveObject<50>;

cpputest-for-qpc-lib/tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ set(TEST_SOURCES
55
cms_cpputest_qf_ctrlTests.cpp
66
cms_cpputest_qf_ctrlPublishTests.cpp
77
cms_cpputest_qf_ctrl_post_tests.cpp
8+
cms_dummy_active_object_tests.cpp
89
publishedEventRecorderTests.cpp
910
backedQueueTests.cpp
1011
)
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#include "cmsDummyActiveObject.hpp"
2+
#include "cms_cpputest_qf_ctrl.hpp"
3+
#include "qpc.h"
4+
#include <memory>
5+
6+
//cpputest header include must always be last
7+
#include "CppUTest/TestHarness.h"
8+
9+
using namespace cms;
10+
using namespace cms::test;
11+
12+
TEST_GROUP(dummy_ao_tests)
13+
{
14+
void setup() final
15+
{
16+
qf_ctrl::Setup(Q_USER_SIG, 100);
17+
}
18+
19+
void teardown() final
20+
{
21+
qf_ctrl::Teardown();
22+
}
23+
};
24+
25+
TEST(dummy_ao_tests, dummy_ao_provides_callback_by_default)
26+
{
27+
auto dummy = std::make_unique<DefaultDummyActiveObject>();
28+
dummy->dummyStart();
29+
CHECK_TRUE(dummy->isRecorderEmpty());
30+
CHECK_FALSE(dummy->isAnyEventRecorded());
31+
32+
static constexpr enum_t TEST1_SIG = Q_USER_SIG + 1;
33+
enum_t capturedSig = -1;
34+
dummy->SetPostedEventHandler([&](const QEvt* e){
35+
capturedSig = e->sig;
36+
});
37+
qf_ctrl::PostAndProcess<TEST1_SIG>(dummy->getQActive());
38+
CHECK_EQUAL(TEST1_SIG, capturedSig);
39+
CHECK_FALSE(dummy->isAnyEventRecorded()); //still false, internal recorder not in use here.
40+
CHECK_TRUE(dummy->isRecorderEmpty());
41+
}
42+
43+
TEST(dummy_ao_tests, dummy_ao_provides_recorder_option)
44+
{
45+
auto dummy = std::make_unique<DefaultDummyActiveObject>(DefaultDummyActiveObject::EventBehavior::RECORDER);
46+
dummy->dummyStart();
47+
48+
static constexpr enum_t TEST1_SIG = Q_USER_SIG + 1;
49+
static constexpr enum_t TEST2_SIG = TEST1_SIG + 1;
50+
51+
CHECK_TRUE(dummy->isRecorderEmpty());
52+
53+
enum_t capturedSig = -1;
54+
55+
//this should actually do nothing, since this AO is using its internal
56+
//recorder
57+
dummy->SetPostedEventHandler([&](const QEvt* e){
58+
capturedSig = e->sig;
59+
});
60+
qf_ctrl::PostAndProcess<TEST1_SIG>(dummy->getQActive());
61+
qf_ctrl::PostAndProcess<TEST2_SIG>(dummy->getQActive());
62+
CHECK_EQUAL(-1, capturedSig); //confirm above callback did NOT happen
63+
64+
CHECK_TRUE(dummy->isAnyEventRecorded());
65+
auto recordedEvent1 = dummy->getRecordedEvent();
66+
CHECK_TRUE(recordedEvent1 != nullptr);
67+
CHECK_EQUAL(TEST1_SIG, recordedEvent1->sig);
68+
69+
CHECK_TRUE(dummy->isAnyEventRecorded());
70+
CHECK_TRUE(dummy->isSignalRecorded(TEST2_SIG));
71+
}

0 commit comments

Comments
 (0)