Skip to content

Commit 320162c

Browse files
committed
Testing: thread safe unit test updates
1 parent 5b95a26 commit 320162c

4 files changed

Lines changed: 114 additions & 86 deletions

File tree

.github/workflows/test.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,7 @@ jobs:
479479
# Create the thread-safe test executable
480480
add_executable(test_thread_safe
481481
tests/test-scheduler-thread-safe.cpp
482+
tests/test-queue-impl.cpp
482483
${TASKSCHEDULER_SOURCES}
483484
)
484485
@@ -492,6 +493,7 @@ jobs:
492493
# Compiler definitions for Arduino compatibility and thread safety
493494
target_compile_definitions(test_thread_safe PRIVATE
494495
ARDUINO=300
496+
_TASK_NON_ARDUINO
495497
_TASK_THREAD_SAFE
496498
_TASK_STATUS_REQUEST
497499
_TASK_TIMEOUT

tests/test-queue-impl.cpp

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
// test-queue-impl.cpp - Linux queue implementation for thread-safe testing
2+
// This file provides the actual implementation of the queue functions
3+
// to override the weak symbols defined in TaskScheduler.h
4+
5+
#include "Arduino.h"
6+
7+
// Define thread-safe features before including TaskScheduler
8+
#define _TASK_NON_ARDUINO
9+
#define _TASK_THREAD_SAFE
10+
#define _TASK_STATUS_REQUEST
11+
#define _TASK_TIMEOUT
12+
#include "TaskSchedulerDeclarations.h"
13+
14+
#include <thread>
15+
#include <mutex>
16+
#include <queue>
17+
#include <condition_variable>
18+
19+
// ============================================
20+
// Thread-Safe Queue Implementation for Linux
21+
// ============================================
22+
23+
// Queue for task requests
24+
std::queue<_task_request_t> taskRequestQueue;
25+
std::mutex queueMutex;
26+
std::condition_variable queueCV;
27+
const size_t MAX_QUEUE_SIZE = 100;
28+
29+
/**
30+
* @brief Enqueue a task request (Linux implementation)
31+
*
32+
* Thread-safe enqueue operation using std::mutex.
33+
* Simulates FreeRTOS queue behavior for Linux testing.
34+
*
35+
* @param req Pointer to the request structure
36+
* @return true if enqueued successfully, false if queue is full
37+
*/
38+
bool _task_enqueue_request(_task_request_t* req) {
39+
std::unique_lock<std::mutex> lock(queueMutex);
40+
41+
// Check queue size limit
42+
if (taskRequestQueue.size() >= MAX_QUEUE_SIZE) {
43+
return false; // Queue full
44+
}
45+
46+
// Add request to queue
47+
taskRequestQueue.push(*req);
48+
49+
// Notify waiting threads
50+
queueCV.notify_one();
51+
52+
return true;
53+
}
54+
55+
/**
56+
* @brief Dequeue a task request (Linux implementation)
57+
*
58+
* Thread-safe dequeue operation. Non-blocking for scheduler.
59+
*
60+
* @param req Pointer to store the dequeued request
61+
* @return true if request dequeued, false if queue empty
62+
*/
63+
bool _task_dequeue_request(_task_request_t* req) {
64+
std::unique_lock<std::mutex> lock(queueMutex);
65+
66+
if (taskRequestQueue.empty()) {
67+
return false; // No requests
68+
}
69+
70+
// Get request from queue
71+
*req = taskRequestQueue.front();
72+
taskRequestQueue.pop();
73+
74+
return true;
75+
}
76+
77+
/**
78+
* @brief Helper to clear the queue between tests
79+
*/
80+
void clearTaskRequestQueue() {
81+
std::unique_lock<std::mutex> lock(queueMutex);
82+
while (!taskRequestQueue.empty()) {
83+
taskRequestQueue.pop();
84+
}
85+
}
86+
87+
/**
88+
* @brief Helper to get current queue size
89+
*/
90+
size_t getQueueSize() {
91+
std::unique_lock<std::mutex> lock(queueMutex);
92+
return taskRequestQueue.size();
93+
}

tests/test-queue-impl.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// test-queue-impl.h - Header for Linux queue implementation
2+
// Declares helper functions for queue management in tests
3+
4+
#ifndef TEST_QUEUE_IMPL_H
5+
#define TEST_QUEUE_IMPL_H
6+
7+
#include <cstddef>
8+
9+
// Helper functions for testing
10+
void clearTaskRequestQueue();
11+
size_t getQueueSize();
12+
13+
// Maximum queue size constant
14+
extern const size_t MAX_QUEUE_SIZE;
15+
16+
#endif // TEST_QUEUE_IMPL_H

tests/test-scheduler-thread-safe.cpp

Lines changed: 3 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -17,98 +17,15 @@
1717

1818
#include <gtest/gtest.h>
1919
#include "Arduino.h"
20-
21-
// Define thread-safe features before including TaskScheduler
22-
#define _TASK_THREAD_SAFE
23-
#define _TASK_STATUS_REQUEST
24-
#define _TASK_TIMEOUT
25-
#include "TaskScheduler.h"
20+
// #include "TaskScheduler.h"
21+
#include "test-queue-impl.h"
2622

2723
#include <thread>
28-
#include <mutex>
29-
#include <queue>
3024
#include <atomic>
31-
#include <condition_variable>
32-
33-
// ============================================
34-
// Thread-Safe Queue Implementation for Linux
35-
// ============================================
36-
37-
// Queue for task requests
38-
std::queue<_task_request_t> taskRequestQueue;
39-
std::mutex queueMutex;
40-
std::condition_variable queueCV;
41-
const size_t MAX_QUEUE_SIZE = 100;
4225

4326
// Thread-local storage to simulate ISR context
4427
thread_local bool isInISRContext = false;
4528

46-
/**
47-
* @brief Enqueue a task request (Linux implementation)
48-
*
49-
* Thread-safe enqueue operation using std::mutex.
50-
* Simulates FreeRTOS queue behavior for Linux testing.
51-
*
52-
* @param req Pointer to the request structure
53-
* @return true if enqueued successfully, false if queue is full
54-
*/
55-
bool _task_enqueue_request(_task_request_t* req) {
56-
std::unique_lock<std::mutex> lock(queueMutex);
57-
58-
// Check queue size limit
59-
if (taskRequestQueue.size() >= MAX_QUEUE_SIZE) {
60-
return false; // Queue full
61-
}
62-
63-
// Add request to queue
64-
taskRequestQueue.push(*req);
65-
66-
// Notify waiting threads
67-
queueCV.notify_one();
68-
69-
return true;
70-
}
71-
72-
/**
73-
* @brief Dequeue a task request (Linux implementation)
74-
*
75-
* Thread-safe dequeue operation. Non-blocking for scheduler.
76-
*
77-
* @param req Pointer to store the dequeued request
78-
* @return true if request dequeued, false if queue empty
79-
*/
80-
bool _task_dequeue_request(_task_request_t* req) {
81-
std::unique_lock<std::mutex> lock(queueMutex);
82-
83-
if (taskRequestQueue.empty()) {
84-
return false; // No requests
85-
}
86-
87-
// Get request from queue
88-
*req = taskRequestQueue.front();
89-
taskRequestQueue.pop();
90-
91-
return true;
92-
}
93-
94-
/**
95-
* @brief Helper to clear the queue between tests
96-
*/
97-
void clearTaskRequestQueue() {
98-
std::unique_lock<std::mutex> lock(queueMutex);
99-
while (!taskRequestQueue.empty()) {
100-
taskRequestQueue.pop();
101-
}
102-
}
103-
104-
/**
105-
* @brief Helper to get current queue size
106-
*/
107-
size_t getQueueSize() {
108-
std::unique_lock<std::mutex> lock(queueMutex);
109-
return taskRequestQueue.size();
110-
}
111-
11229
// ============================================
11330
// Global Test State
11431
// ============================================
@@ -475,7 +392,7 @@ TEST_F(ThreadSafeTest, QueueOverflowHandling) {
475392
int successful = 0;
476393
int failed = 0;
477394

478-
for (int i = 0; i < MAX_QUEUE_SIZE + 50; i++) {
395+
for (size_t i = 0; i < MAX_QUEUE_SIZE + 50; i++) {
479396
if (ts.requestAction(&testTask, TASK_REQUEST_SETINTERVAL_1, i, 0, 0, 0, 0)) {
480397
successful++;
481398
} else {

0 commit comments

Comments
 (0)