Skip to content

Commit 3fd114e

Browse files
committed
fsm:attempt to have state hooks list traverse
1 parent 596a0bd commit 3fd114e

File tree

5 files changed

+14
-259
lines changed

5 files changed

+14
-259
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# IDE
22
.idea
3+
.vscode
34

45
# Compiled
56
build

src/active-object/active_object_impl.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "./active_object.h"
55
#include "../queue/queue_impl.h"
66

7+
//Generate Unit tests for this macro on Unity framework
78
#define ACTIVE_OBJECT_IMPLEMENTATION(ACTIVE_OBJECT_T, EVENT_T, STATE_T, FIELDS_T, maxQueueCapacity) \
89
QUEUE_IMPLEMENTATION(EVENT_T, maxQueueCapacity); \
910
\
@@ -32,8 +33,8 @@
3233
\
3334
EVENT_T e = QUEUE_##EVENT_T##_Dequeue(&self->queue); \
3435
STATE_T nextState = eventHandlerCb(self, e); \
35-
void* ctx = e->payload ? e->payload : NULL; \
36-
transitionToNextStateCb(self, nextState, ctx); \
36+
/* TODO implement passing ctx from event */\
37+
transitionToNextStateCb(self, nextState, NULL); \
3738
}
3839

3940
#endif //ACTIVE_OBJECT_IMPL_H

test/active-object/active_object.test.c

Lines changed: 6 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -2,100 +2,20 @@
22
#include "../../src/active-object/active_object.h"
33
#include "../../src/active-object/active_object_impl.h"
44

5-
// Define the types for our test
6-
typedef enum {
7-
TEST_EVENT_A,
8-
TEST_EVENT_B
9-
} TestEvent;
10-
11-
typedef enum {
12-
TEST_STATE_IDLE,
13-
TEST_STATE_RUNNING,
14-
TEST_STATE_PAUSED
15-
} TestState;
16-
17-
typedef struct {
18-
int value;
19-
} TestFields;
20-
21-
DECLARE_ACTIVE_OBJECT(TestActiveObject, TestEvent, TestState, TestFields, 5);
22-
ACTIVE_OBJECT_IMPLEMENTATION(TestActiveObject, TestEvent, TestState, TestFields, 5);
23-
24-
TestState handleEvent(TestActiveObject *self, TestEvent e) {
25-
switch(e) {
26-
case TEST_EVENT_A: return TEST_STATE_RUNNING;
27-
case TEST_EVENT_B: return TEST_STATE_PAUSED;
28-
default: return self->state; // No change in state
29-
}
30-
}
31-
32-
bool transitionToState(TestActiveObject *self, TestState nextState) {
33-
return TestActiveObject_basicTransitionToNextState(self, nextState);
34-
}
35-
36-
void handleEmptyQueue(TestActiveObject *self) {
37-
// For this test, do nothing when the queue is empty.
38-
}
39-
405
void setUp(void) {
41-
// Called before each test case
6+
// This is run before EACH test
427
}
438

449
void tearDown(void) {
45-
// Called after each test case
10+
// This is run after EACH test
4611
}
4712

48-
void test_constructor(void) {
49-
TestActiveObject obj;
50-
TestFields fields = { .value = 10 };
51-
TestActiveObject_Ctor(&obj, 1, TEST_STATE_IDLE, fields);
52-
TEST_ASSERT_EQUAL(1, obj.id);
53-
TEST_ASSERT_EQUAL(TEST_STATE_IDLE, obj.state);
54-
TEST_ASSERT_EQUAL(10, obj.fields.value);
55-
TEST_ASSERT_EQUAL(0, QUEUE_TestEvent_GetSize(&obj.queue));
56-
}
5713

58-
void test_dispatchAndProcessQueue(void) {
59-
TestActiveObject obj;
60-
TestFields fields = { .value = 10 };
61-
TestActiveObject_Ctor(&obj, 1, TEST_STATE_IDLE, fields);
62-
63-
// Dispatch TEST_EVENT_A and process it
64-
TestActiveObject_Dispatch(&obj, TEST_EVENT_A);
65-
TestActiveObject_ProcessQueue(&obj, handleEvent, transitionToState);
66-
67-
TEST_ASSERT_EQUAL(TEST_STATE_RUNNING, obj.state);
68-
69-
// Dispatch TEST_EVENT_B and process it
70-
TestActiveObject_Dispatch(&obj, TEST_EVENT_B);
71-
TestActiveObject_ProcessQueue(&obj, handleEvent, transitionToState);
72-
73-
TEST_ASSERT_EQUAL(TEST_STATE_PAUSED, obj.state);
74-
}
75-
76-
void test_hasEmptyQueue(void) {
77-
TestActiveObject obj;
78-
TestFields fields = { .value = 10 };
79-
TestActiveObject_Ctor(&obj, 1, TEST_STATE_IDLE, fields);
80-
81-
// Initially the queue should be empty
82-
TEST_ASSERT_TRUE(TestActiveObject_HasEmptyQueue(&obj));
83-
84-
// Add an item to the queue and check again
85-
TestActiveObject_Dispatch(&obj, TEST_EVENT_A);
86-
TEST_ASSERT_FALSE(TestActiveObject_HasEmptyQueue(&obj));
87-
88-
// Process the queue, it should become empty again
89-
TestActiveObject_ProcessQueue(&obj, handleEvent, transitionToState);
90-
TEST_ASSERT_TRUE(TestActiveObject_HasEmptyQueue(&obj));
91-
}
14+
int main(void)
15+
{
16+
// UNITY_BEGIN();
9217

93-
int main(void) {
94-
UNITY_BEGIN();
95-
RUN_TEST(test_constructor);
96-
RUN_TEST(test_dispatchAndProcessQueue);
97-
RUN_TEST(test_hasEmptyQueue);
98-
UNITY_END();
18+
// return UNITY_END();
9919

10020
return 0;
10121
}

test/fsm/fsm.test.c

Lines changed: 2 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -2,83 +2,14 @@
22
#include "../../src/fsm/fsm.h"
33
#include "../../src/fsm/fsm_impl.h"
44

5-
typedef struct {
6-
int sig;
7-
} MockEvent;
8-
9-
enum {
10-
MOCK_EVENT_A_SIG,
11-
MOCK_EVENT_B_SIG,
12-
MOCK_EVENT_C_SIG
13-
};
14-
15-
typedef enum {
16-
MOCK_STATE_IDLE,
17-
MOCK_STATE_RUNNING,
18-
MOCK_STATE_PAUSED
19-
} MockState;
20-
21-
typedef struct {
22-
int value;
23-
MockState state;
24-
} MockActiveObject;
25-
26-
DECLARE_FSM(MockActiveObject, MockEvent, MockState, 3, 3);
27-
FSM_IMPLEMENTATION(MockActiveObject, MockEvent, MockState, 3, 3);
28-
29-
// Mock state handlers
30-
MockState mock_idle_handler(MockActiveObject *const ao, MockEvent event) {
31-
return MOCK_STATE_RUNNING;
32-
}
33-
34-
MockState mock_running_handler(MockActiveObject *const ao, MockEvent event) {
35-
return MOCK_STATE_PAUSED;
36-
}
37-
38-
MockState mock_paused_handler(MockActiveObject *const ao, MockEvent event) {
39-
return MOCK_STATE_IDLE;
40-
}
41-
425
void setUp(void) {
43-
// Called before each test case
6+
// This is run before EACH test
447
}
458

469
void tearDown(void) {
47-
// Called after each test case
48-
}
49-
50-
void test_fsm_process_event_to_next_state(void) {
51-
MockActiveObject ao = { .value = 10 };
52-
53-
// Declare and initialize transition table
54-
MockEvent_HANDLE_F transitionTable[3][3];
55-
transitionTable[MOCK_STATE_IDLE][MOCK_EVENT_A_SIG] = mock_idle_handler;
56-
transitionTable[MOCK_STATE_RUNNING][MOCK_EVENT_B_SIG] = mock_running_handler;
57-
transitionTable[MOCK_STATE_PAUSED][MOCK_EVENT_C_SIG] = mock_paused_handler;
58-
59-
// Process MOCK_EVENT_A_SIG while in MOCK_STATE_IDLE -> should transition to MOCK_STATE_RUNNING
60-
ao.state = MOCK_STATE_IDLE;
61-
MockEvent e = { .sig = MOCK_EVENT_A_SIG };
62-
MockState nextState = MockActiveObject_FSM_ProcessEventToNextState(&ao, e, transitionTable, NULL);
63-
TEST_ASSERT_EQUAL(MOCK_STATE_RUNNING, nextState);
64-
65-
// Process MOCK_EVENT_B_SIG while in MOCK_STATE_RUNNING -> should transition to MOCK_STATE_PAUSED
66-
ao.state = MOCK_STATE_RUNNING;
67-
e.sig = MOCK_EVENT_B_SIG;
68-
nextState = MockActiveObject_FSM_ProcessEventToNextState(&ao, e, transitionTable, NULL);
69-
TEST_ASSERT_EQUAL(MOCK_STATE_PAUSED, nextState);
70-
71-
// Process MOCK_EVENT_C_SIG while in MOCK_STATE_PAUSED -> should transition to MOCK_STATE_IDLE
72-
ao.state = MOCK_STATE_PAUSED;
73-
e.sig = MOCK_EVENT_C_SIG;
74-
nextState = MockActiveObject_FSM_ProcessEventToNextState(&ao, e, transitionTable, NULL);
75-
TEST_ASSERT_EQUAL(MOCK_STATE_IDLE, nextState);
10+
// This is run after EACH test
7611
}
7712

7813
int main(void) {
79-
UNITY_BEGIN();
80-
RUN_TEST(test_fsm_process_event_to_next_state);
81-
UNITY_END();
82-
8314
return 0;
8415
}

test/integration/fsm_active_object.test.c

Lines changed: 2 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -4,114 +4,16 @@
44
#include "../../src/fsm/fsm.h"
55
#include "../../src/fsm/fsm_impl.h"
66

7-
#define QUEUE_CAPACITY 5
8-
#define EVENTS_MAX 3
9-
#define STATES_MAX 3
10-
11-
typedef enum {
12-
MOCK_EVENT_A_SIG,
13-
MOCK_EVENT_B_SIG,
14-
MOCK_EVENT_C_SIG
15-
} MockEventSignal;
16-
17-
typedef struct {
18-
MockEventSignal sig;
19-
} MockEvent;
20-
21-
typedef enum {
22-
MOCK_STATE_IDLE,
23-
MOCK_STATE_RUNNING,
24-
MOCK_STATE_PAUSED
25-
} MockState;
26-
27-
typedef struct {
28-
int value;
29-
} MockFields;
30-
31-
DECLARE_ACTIVE_OBJECT(MockActiveObject, MockEvent, MockState, MockFields, QUEUE_CAPACITY);
32-
ACTIVE_OBJECT_IMPLEMENTATION(MockActiveObject, MockEvent, MockState, MockFields, QUEUE_CAPACITY);
33-
DECLARE_FSM(MockActiveObject, MockEvent, MockState, EVENTS_MAX, STATES_MAX);
34-
FSM_IMPLEMENTATION(MockActiveObject, MockEvent, MockState, EVENTS_MAX, STATES_MAX);
35-
36-
// Mock state handlers (FSM)
37-
MockState mock_idle_handler(MockActiveObject *const ao, MockEvent event) {
38-
return MOCK_STATE_RUNNING;
39-
}
40-
41-
MockState mock_running_handler(MockActiveObject *const ao, MockEvent event) {
42-
return MOCK_STATE_PAUSED;
43-
}
44-
45-
MockState mock_paused_handler(MockActiveObject *const ao, MockEvent event) {
46-
return MOCK_STATE_IDLE;
47-
}
48-
49-
MockEvent_HANDLE_F stateTransitionTable[STATES_MAX][EVENTS_MAX] = {
50-
[MOCK_STATE_IDLE] = {
51-
[MOCK_EVENT_A_SIG] = mock_idle_handler,
52-
[MOCK_EVENT_B_SIG] = NULL,
53-
[MOCK_EVENT_C_SIG] = NULL
54-
},
55-
[MOCK_STATE_RUNNING] = {
56-
[MOCK_EVENT_A_SIG] = NULL,
57-
[MOCK_EVENT_B_SIG] = mock_running_handler,
58-
[MOCK_EVENT_C_SIG] = NULL
59-
},
60-
[MOCK_STATE_PAUSED] = {
61-
[MOCK_EVENT_A_SIG] = NULL,
62-
[MOCK_EVENT_B_SIG] = NULL,
63-
[MOCK_EVENT_C_SIG] = mock_paused_handler
64-
}
65-
};
66-
677
void setUp(void) {
68-
// Called before each test case
8+
// This is run before EACH test
699
}
7010

7111
void tearDown(void) {
72-
// Called after each test case
12+
// This is run after EACH test
7313
}
7414

75-
void integration_test_active_object_with_fsm_and_queue(void) {
76-
MockActiveObject ao;
77-
MockFields fields = { .value = 10 };
78-
79-
// Initialization
80-
MockActiveObject_Ctor(&ao, 1, MOCK_STATE_IDLE, fields);
81-
TEST_ASSERT_EQUAL(1, ao.id);
82-
TEST_ASSERT_EQUAL(MOCK_STATE_IDLE, ao.state);
83-
TEST_ASSERT_EQUAL(10, ao.fields.value);
84-
TEST_ASSERT_EQUAL(0, QUEUE_MockEvent_GetSize(&ao.queue));
85-
86-
// Dispatching and processing an event
87-
MockEvent e1 = { .sig = MOCK_EVENT_A_SIG };
88-
MockActiveObject_Dispatch(&ao, e1);
89-
TEST_ASSERT_EQUAL(1, QUEUE_MockEvent_GetSize(&ao.queue));
90-
91-
// Process Event with FSM
92-
MockState nextState = MockActiveObject_FSM_ProcessEventToNextState(&ao, e1, stateTransitionTable, NULL);
93-
TEST_ASSERT_EQUAL(MOCK_STATE_RUNNING, nextState);
94-
ao.state = nextState; // Update the actual state of the active object
95-
96-
// Dispatching and processing a second event
97-
MockEvent e2 = { .sig = MOCK_EVENT_B_SIG };
98-
MockActiveObject_Dispatch(&ao, e2);
99-
nextState = MockActiveObject_FSM_ProcessEventToNextState(&ao, e2, stateTransitionTable, NULL);
100-
TEST_ASSERT_EQUAL(MOCK_STATE_PAUSED, nextState);
101-
ao.state = nextState; // Update the actual state of the active object
102-
103-
// Dispatching and processing a third event
104-
MockEvent e3 = { .sig = MOCK_EVENT_C_SIG };
105-
MockActiveObject_Dispatch(&ao, e3);
106-
nextState = MockActiveObject_FSM_ProcessEventToNextState(&ao, e3, stateTransitionTable, NULL);
107-
TEST_ASSERT_EQUAL(MOCK_STATE_IDLE, nextState);
108-
ao.state = nextState; // Update the actual state of the active object
109-
}
11015

11116
int main(void) {
112-
UNITY_BEGIN();
113-
RUN_TEST(integration_test_active_object_with_fsm_and_queue);
114-
UNITY_END();
11517

11618
return 0;
11719
}

0 commit comments

Comments
 (0)