adding freeRtos API from different project
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
idf_component_register(
|
||||
SRC_DIRS "."
|
||||
INCLUDE_DIRS "."
|
||||
REQUIRES cmock freeRtosApi esp_timer
|
||||
)
|
||||
@@ -0,0 +1,30 @@
|
||||
#include "esp_log.h"
|
||||
#include "esp_timer.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "sdkconfig.h"
|
||||
#include <stdio.h>
|
||||
constexpr int StackSize = 1024;
|
||||
|
||||
#include <unity.h>
|
||||
|
||||
class TimeTest {
|
||||
private:
|
||||
bool running{};
|
||||
TickType_t _begin;
|
||||
|
||||
public:
|
||||
TimeTest() {
|
||||
start();
|
||||
}
|
||||
|
||||
void start() {
|
||||
_begin = xTaskGetTickCount();
|
||||
running = true;
|
||||
}
|
||||
|
||||
|
||||
TickType_t getRunTime() {
|
||||
return xTaskGetTickCount() - _begin;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,85 @@
|
||||
#include "test.hpp"
|
||||
|
||||
#include <Mutex.hpp>
|
||||
#include <Semaphore.hpp>
|
||||
#include <Task.hpp>
|
||||
|
||||
using namespace fos;
|
||||
|
||||
constexpr int SHORT_DELAY = 10;
|
||||
|
||||
TEST_CASE("Test mutexes", "[freeRtos][mutex]") {
|
||||
Mutex eut;
|
||||
// first take fails
|
||||
TEST_ASSERT_TRUE(eut.claim(0));
|
||||
eut.release();
|
||||
|
||||
TEST_ASSERT_TRUE(eut.claim(0));
|
||||
TEST_ASSERT_FALSE(eut.claim(0));
|
||||
|
||||
eut.release();
|
||||
// eut.release(); // not a good idea
|
||||
TEST_ASSERT_TRUE(eut.claim(0));
|
||||
// second take after give fails
|
||||
TEST_ASSERT_FALSE(eut.claim(0));
|
||||
}
|
||||
|
||||
static Semaphore starter1;
|
||||
static void testClaimer(Mutex &m) {
|
||||
m.claim();
|
||||
starter1.give();
|
||||
vTaskDelay(SHORT_DELAY);
|
||||
m.release();
|
||||
vTaskDelay(SHORT_DELAY);
|
||||
m.claim();
|
||||
starter1.give();
|
||||
while (true) {
|
||||
vTaskDelay(SHORT_DELAY);
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("Test mutex timing", "[freeRtos][mutex]") {
|
||||
static Mutex eut;
|
||||
|
||||
TaskT<Mutex &> claimer(testClaimer, eut, "signal1");
|
||||
starter1.take(100);
|
||||
{ // All ok
|
||||
TimeTest timer;
|
||||
TEST_ASSERT_TRUE(eut.claim(100));
|
||||
TEST_ASSERT_INT_WITHIN(1, SHORT_DELAY, timer.getRunTime());
|
||||
eut.release();
|
||||
}
|
||||
starter1.take(100);
|
||||
{ // Timeout
|
||||
TimeTest timer;
|
||||
TEST_ASSERT_FALSE(eut.claim(20));
|
||||
TEST_ASSERT_INT_WITHIN(1, 20, timer.getRunTime());
|
||||
}
|
||||
|
||||
{ // NoWeit timeout
|
||||
Mutex passiveSem;
|
||||
passiveSem.claim(0);
|
||||
TimeTest timer;
|
||||
TEST_ASSERT_FALSE(passiveSem.claim(0));
|
||||
TEST_ASSERT_INT_WITHIN(1, 0, timer.getRunTime());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Test mutex guard", "[freeRtos][mutex]") {
|
||||
Mutex mtx;
|
||||
{
|
||||
MutexGuard eut(mtx, 100);
|
||||
TEST_ASSERT_TRUE(eut.isActive());
|
||||
// already taken
|
||||
TEST_ASSERT_FALSE(mtx.claim(0));
|
||||
}
|
||||
// now free to go
|
||||
TEST_ASSERT_TRUE(mtx.claim(0));
|
||||
{ // Timeout
|
||||
TimeTest timer;
|
||||
MutexGuard eut(mtx, SHORT_DELAY);
|
||||
TEST_ASSERT_FALSE(eut.isActive());
|
||||
TEST_ASSERT_INT_WITHIN(1, SHORT_DELAY, timer.getRunTime());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
#include "test.hpp"
|
||||
|
||||
#include <Queue.hpp>
|
||||
#include <Task.hpp>
|
||||
#include <string>
|
||||
|
||||
using namespace fos;
|
||||
|
||||
constexpr int SHORT_DELAY = 10;
|
||||
|
||||
struct MessageFrame {
|
||||
MessageFrame(int v, std::string msg) : value(v), message(msg) {}
|
||||
int value;
|
||||
std::string message;
|
||||
};
|
||||
|
||||
TEST_CASE("Test enqueueing then dequeueing", "[freeRtos][queue]") {
|
||||
Queue<MessageFrame> eut(10);
|
||||
|
||||
auto e = std::make_unique<MessageFrame>(1, "one");
|
||||
eut.enqueue(std::move(e));
|
||||
|
||||
auto r = eut.dequeue(100);
|
||||
TEST_ASSERT_NOT_NULL(r.get());
|
||||
TEST_ASSERT_EQUAL(1, r->value);
|
||||
TEST_ASSERT_TRUE(r->message == "one");
|
||||
}
|
||||
|
||||
TEST_CASE("Test enqueueing then dequeue multiple", "[freeRtos][queue]") {
|
||||
Queue<MessageFrame> eut(10);
|
||||
|
||||
auto e = std::make_unique<MessageFrame>(1, "one");
|
||||
eut.enqueue(std::move(e));
|
||||
e = std::make_unique<MessageFrame>(2, "two");
|
||||
eut.enqueue(std::move(e));
|
||||
e = std::make_unique<MessageFrame>(3, "three");
|
||||
eut.enqueue(std::move(e));
|
||||
|
||||
auto r = eut.dequeue(100);
|
||||
TEST_ASSERT_NOT_NULL(r.get());
|
||||
TEST_ASSERT_EQUAL(1, r->value);
|
||||
TEST_ASSERT_TRUE(r->message == "one");
|
||||
r = eut.dequeue(100);
|
||||
TEST_ASSERT_NOT_NULL(r.get());
|
||||
TEST_ASSERT_EQUAL(2, r->value);
|
||||
TEST_ASSERT_TRUE(r->message == "two");
|
||||
r = eut.dequeue(100);
|
||||
TEST_ASSERT_NOT_NULL(r.get());
|
||||
TEST_ASSERT_EQUAL(3, r->value);
|
||||
TEST_ASSERT_TRUE(r->message == "three");
|
||||
}
|
||||
|
||||
TEST_CASE("Test enqueue cyclically", "[freeRtos][queue]") {
|
||||
constexpr int Size = 10;
|
||||
Queue<MessageFrame> eut(Size);
|
||||
for (size_t i = 0; i < Size * 2; i++) {
|
||||
auto e = std::make_unique<MessageFrame>(i, "Some message");
|
||||
eut.enqueue(std::move(e));
|
||||
|
||||
auto r = eut.dequeue(100);
|
||||
TEST_ASSERT_NOT_NULL(r.get());
|
||||
TEST_ASSERT_EQUAL(i, r->value);
|
||||
}
|
||||
TEST_ASSERT_TRUE(true);
|
||||
}
|
||||
|
||||
TEST_CASE("Test enqueueing till overflow", "[freeRtos][queue]") {
|
||||
Queue<MessageFrame> eut(3);
|
||||
|
||||
auto e = std::make_unique<MessageFrame>(1, "one");
|
||||
auto r = eut.enqueue(std::move(e));
|
||||
TEST_ASSERT_EQUAL(nullptr, r.get());
|
||||
|
||||
e = std::make_unique<MessageFrame>(2, "two");
|
||||
r = eut.enqueue(std::move(e));
|
||||
TEST_ASSERT_EQUAL(nullptr, r.get());
|
||||
|
||||
e = std::make_unique<MessageFrame>(3, "three");
|
||||
r = eut.enqueue(std::move(e));
|
||||
TEST_ASSERT_EQUAL(nullptr, r.get());
|
||||
|
||||
e = std::make_unique<MessageFrame>(4, "four");
|
||||
auto pE = e.get();
|
||||
r = eut.enqueue(std::move(e));
|
||||
TEST_ASSERT_NOT_EQUAL(nullptr, r.get());
|
||||
// also return old element ...
|
||||
TEST_ASSERT_EQUAL(pE, r.get());
|
||||
}
|
||||
|
||||
TEST_CASE("Test enqueueing then dequeue multiple", "[freeRtos][queue]") {
|
||||
Queue<MessageFrame> eut(10);
|
||||
|
||||
auto e = std::make_unique<MessageFrame>(1, "one");
|
||||
eut.enqueue(std::move(e));
|
||||
e = std::make_unique<MessageFrame>(2, "two");
|
||||
eut.enqueue(std::move(e));
|
||||
|
||||
auto r = eut.dequeue(100);
|
||||
TEST_ASSERT_NOT_NULL(r.get());
|
||||
TEST_ASSERT_EQUAL(1, r->value);
|
||||
r = eut.dequeue(100);
|
||||
TEST_ASSERT_NOT_NULL(r.get());
|
||||
TEST_ASSERT_EQUAL(2, r->value);
|
||||
r = eut.dequeue(0); // no waiting
|
||||
TEST_ASSERT_EQUAL(nullptr, r.get());
|
||||
}
|
||||
|
||||
static void queue1Gen(Queue<MessageFrame> &q) {
|
||||
vTaskDelay(SHORT_DELAY);
|
||||
auto e = std::make_unique<MessageFrame>(0, "msg");
|
||||
q.enqueue(std::move(e));
|
||||
while (true) {
|
||||
vTaskDelay(SHORT_DELAY);
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("Test timing of queue", "[freeRtos][queue]") {
|
||||
static Queue<MessageFrame> eut(8);
|
||||
TaskT<Queue<MessageFrame> &> signaler(queue1Gen, eut, "queue1Gen");
|
||||
{ // All ok
|
||||
TimeTest timer;
|
||||
auto r = eut.dequeue(100);
|
||||
TEST_ASSERT_NOT_NULL(r.get());
|
||||
TEST_ASSERT_INT_WITHIN(1, SHORT_DELAY, timer.getRunTime());
|
||||
}
|
||||
|
||||
{ // Timeout
|
||||
TimeTest timer;
|
||||
auto r = eut.dequeue(20);
|
||||
TEST_ASSERT_NULL(r.get());
|
||||
TEST_ASSERT_INT_WITHIN(1, 20, timer.getRunTime());
|
||||
}
|
||||
}
|
||||
|
||||
static void senderTask(Queue<MessageFrame> &q) {
|
||||
size_t i = 0;
|
||||
while (q.isActive()) {
|
||||
auto e = std::make_unique<MessageFrame>(i++, "Some message");
|
||||
q.enqueue(std::move(e));
|
||||
vTaskDelay(1);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Test enqueueing series of message", "[freeRtos][queue]") {
|
||||
constexpr int Size = 10;
|
||||
Queue<MessageFrame> eut(Size);
|
||||
TaskT<Queue<MessageFrame> &> sender(senderTask, eut, "sender");
|
||||
for (size_t i = 0; i < Size * 2; i++) {
|
||||
auto r = eut.dequeue(100);
|
||||
TEST_ASSERT_NOT_NULL(r.get());
|
||||
TEST_ASSERT_EQUAL(i, r->value);
|
||||
}
|
||||
eut.signalClose();
|
||||
TEST_ASSERT_TRUE(true);
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
#include "test.hpp"
|
||||
|
||||
#include <Semaphore.hpp>
|
||||
#include <Task.hpp>
|
||||
|
||||
using namespace fos;
|
||||
|
||||
constexpr int SHORT_DELAY = 10;
|
||||
|
||||
TEST_CASE("Test binary semaphore", "[freeRtos][sem]") {
|
||||
Semaphore eut;
|
||||
// first take fails
|
||||
TEST_ASSERT_FALSE(eut.take(0));
|
||||
eut.give();
|
||||
// first take after give fails
|
||||
TEST_ASSERT_TRUE(eut.take(0));
|
||||
TEST_ASSERT_FALSE(eut.take(0));
|
||||
|
||||
eut.give();
|
||||
eut.give();
|
||||
TEST_ASSERT_TRUE(eut.take(0));
|
||||
// second take after give fails
|
||||
TEST_ASSERT_FALSE(eut.take(0));
|
||||
}
|
||||
|
||||
TEST_CASE("Test counting semaphore", "[freeRtos][sem]") {
|
||||
Semaphore eut(2, 0);
|
||||
// first take fails
|
||||
TEST_ASSERT_FALSE(eut.take(0));
|
||||
eut.give();
|
||||
// first take after give fails
|
||||
TEST_ASSERT_TRUE(eut.take(0));
|
||||
TEST_ASSERT_FALSE(eut.take(0));
|
||||
|
||||
eut.give();
|
||||
eut.give();
|
||||
TEST_ASSERT_TRUE(eut.take(0));
|
||||
TEST_ASSERT_TRUE(eut.take(0));
|
||||
// third take after give fails
|
||||
TEST_ASSERT_FALSE(eut.take(0));
|
||||
|
||||
eut.give();
|
||||
eut.give();
|
||||
eut.give();
|
||||
TEST_ASSERT_TRUE(eut.take(0));
|
||||
TEST_ASSERT_TRUE(eut.take(0));
|
||||
// still third take after give fails
|
||||
TEST_ASSERT_FALSE(eut.take(0));
|
||||
}
|
||||
|
||||
TEST_CASE("Test preset counting semaphore", "[freeRtos][sem]") {
|
||||
Semaphore eut(2, 2);
|
||||
TEST_ASSERT_TRUE(eut.take(0));
|
||||
TEST_ASSERT_TRUE(eut.take(0));
|
||||
// third take fails
|
||||
TEST_ASSERT_FALSE(eut.take(0));
|
||||
|
||||
eut.give();
|
||||
// first take after give fails
|
||||
TEST_ASSERT_TRUE(eut.take(0));
|
||||
TEST_ASSERT_FALSE(eut.take(0));
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
static void test1Signal(Semaphore &s) {
|
||||
vTaskDelay(SHORT_DELAY);
|
||||
s.give();
|
||||
while (true) {
|
||||
vTaskDelay(SHORT_DELAY);
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("Test timing binary semaphore", "[freeRtos][sem]") {
|
||||
static Semaphore eut;
|
||||
|
||||
TaskT<Semaphore &> signaler(test1Signal, eut, "signal1");
|
||||
{ // All ok
|
||||
TimeTest timer;
|
||||
TEST_ASSERT_TRUE(eut.take(100));
|
||||
TEST_ASSERT_INT_WITHIN(1, SHORT_DELAY, timer.getRunTime());
|
||||
}
|
||||
|
||||
{ // Timeout
|
||||
TimeTest timer;
|
||||
TEST_ASSERT_FALSE(eut.take(20));
|
||||
TEST_ASSERT_INT_WITHIN(1, 20, timer.getRunTime());
|
||||
}
|
||||
|
||||
{ // NoWait timeout
|
||||
Semaphore passiveSem;
|
||||
TimeTest timer;
|
||||
TEST_ASSERT_FALSE(passiveSem.take(0));
|
||||
TEST_ASSERT_INT_WITHIN(1, 0, timer.getRunTime());
|
||||
}
|
||||
}
|
||||
|
||||
static int syncCount = 0;
|
||||
static void producerTask(Semaphore &s) {
|
||||
while (true) {
|
||||
s.give();
|
||||
vTaskDelay(SHORT_DELAY);
|
||||
};
|
||||
}
|
||||
static void consumerTask(Semaphore &s) {
|
||||
while (true) {
|
||||
s.take();
|
||||
syncCount++;
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("Test if tasks signaling with semaphore", "[freeRtos][sem]") {
|
||||
static Semaphore eut;
|
||||
|
||||
TaskT<Semaphore &> producer(producerTask, eut, "producer");
|
||||
TaskT<Semaphore &> consumer(consumerTask, eut, "consumer");
|
||||
vTaskDelay(5 * SHORT_DELAY);
|
||||
TEST_ASSERT_INT_WITHIN(1, 5, syncCount);
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
#include "test.hpp"
|
||||
|
||||
#include <Task.hpp>
|
||||
#include <array>
|
||||
|
||||
using namespace fos;
|
||||
|
||||
TEST_CASE("Test Delay", "[freeRtos][task]") {
|
||||
TickType_t start = xTaskGetTickCount();
|
||||
Task::delayMs(5 * portTICK_PERIOD_MS);
|
||||
TickType_t end = xTaskGetTickCount();
|
||||
TEST_ASSERT_GREATER_OR_EQUAL(5, (end - start));
|
||||
TEST_ASSERT_LESS_OR_EQUAL(6, (end - start));
|
||||
}
|
||||
|
||||
static bool taskWasCalled = false;
|
||||
static void callableTask() {
|
||||
taskWasCalled = true;
|
||||
while (true) {
|
||||
vTaskDelay(100);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Test creation and deletion", "[freeRtos][task]") {
|
||||
static Task task(callableTask, "task1");
|
||||
Task::delayMs(50);
|
||||
TEST_ASSERT_TRUE(taskWasCalled);
|
||||
task.kill();
|
||||
}
|
||||
|
||||
static void callableTask2() {
|
||||
taskWasCalled = true;
|
||||
while (true) {
|
||||
vTaskDelay(100);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Test if task can be killed", "[freeRtos][task]") {
|
||||
static Task task(callableTask2, "task2");
|
||||
auto handle = task.getHandle();
|
||||
configASSERT(handle);
|
||||
TEST_ASSERT_TRUE(eTaskState::eReady == task.getState() ||
|
||||
eTaskState::eBlocked == task.getState());
|
||||
Task::delayMs(50);
|
||||
TEST_ASSERT_TRUE(taskWasCalled);
|
||||
task.kill();
|
||||
TEST_ASSERT_EQUAL(eTaskState::eDeleted, eTaskGetState(handle));
|
||||
}
|
||||
|
||||
static std::array<int, 2> values;
|
||||
|
||||
static void oneOfMultiple(int idx) {
|
||||
static std::array<int, 2> c{1, -1};
|
||||
|
||||
for (size_t i = 0; i < 10; i++) {
|
||||
values.at(idx) += c.at(idx);
|
||||
}
|
||||
|
||||
while (true) {
|
||||
vTaskDelay(100);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Test if tasks do not interfere", "[freeRtos][task]") {
|
||||
// Both tasks are run by starting the same static function body
|
||||
int param1 = 0;
|
||||
TaskT<int> task1(oneOfMultiple, param1, "pTask1");
|
||||
int param2 = 1;
|
||||
TaskT<int> task2(oneOfMultiple, param2, "pTask2");
|
||||
|
||||
Task::delayMs(50);
|
||||
|
||||
TEST_ASSERT_EQUAL(10, values[0]);
|
||||
TEST_ASSERT_EQUAL(-10, values[1]);
|
||||
}
|
||||
|
||||
TEST_CASE("Test if tasks can be joined correctly", "[freeRtos][task]") {
|
||||
// Both tasks are run by starting the same static function body
|
||||
int param1 = 0;
|
||||
Task task1(oneOfMultiple, param1, "pTask1");
|
||||
int param2 = 1;
|
||||
TaskT<int> task2(oneOfMultiple, param2, "pTask2");
|
||||
|
||||
Task::delayMs(50);
|
||||
|
||||
TEST_ASSERT_EQUAL(10, values[0]);
|
||||
TEST_ASSERT_EQUAL(-10, values[1]);
|
||||
}
|
||||
Reference in New Issue
Block a user