110 lines
3.5 KiB
C++
110 lines
3.5 KiB
C++
#include "foundation/task_queue.h"
|
|
#include "test_harness.h"
|
|
|
|
using pp::foundation::StatusCode;
|
|
using pp::foundation::TaskItem;
|
|
using pp::foundation::TaskQueue;
|
|
using pp::foundation::max_task_queue_entries;
|
|
|
|
namespace {
|
|
|
|
struct Counter {
|
|
int value = 0;
|
|
};
|
|
|
|
void increment(void* user_data) noexcept
|
|
{
|
|
auto* counter = static_cast<Counter*>(user_data);
|
|
++counter->value;
|
|
}
|
|
|
|
void add_two(void* user_data) noexcept
|
|
{
|
|
auto* counter = static_cast<Counter*>(user_data);
|
|
counter->value += 2;
|
|
}
|
|
|
|
void runs_tasks_in_fifo_order(pp::tests::Harness& h)
|
|
{
|
|
Counter counter;
|
|
TaskQueue queue(4);
|
|
|
|
PP_EXPECT(h, queue.push(TaskItem { .callback = increment, .user_data = &counter, .id = 1 }).ok());
|
|
PP_EXPECT(h, queue.push(TaskItem { .callback = add_two, .user_data = &counter, .id = 2 }).ok());
|
|
PP_EXPECT(h, queue.size() == 2U);
|
|
PP_EXPECT(h, queue.run_next().ok());
|
|
PP_EXPECT(h, counter.value == 1);
|
|
PP_EXPECT(h, queue.run_next().ok());
|
|
PP_EXPECT(h, counter.value == 3);
|
|
PP_EXPECT(h, queue.empty());
|
|
}
|
|
|
|
void pops_without_running(pp::tests::Harness& h)
|
|
{
|
|
Counter counter;
|
|
TaskQueue queue(2);
|
|
|
|
PP_EXPECT(h, queue.push(TaskItem { .callback = increment, .user_data = &counter, .id = 42 }).ok());
|
|
const auto task = queue.pop();
|
|
|
|
PP_EXPECT(h, task.ok());
|
|
PP_EXPECT(h, task.value().id == 42U);
|
|
PP_EXPECT(h, counter.value == 0);
|
|
PP_EXPECT(h, queue.empty());
|
|
}
|
|
|
|
void rejects_invalid_or_excessive_work(pp::tests::Harness& h)
|
|
{
|
|
Counter counter;
|
|
TaskQueue queue(1);
|
|
TaskQueue invalid_queue(0);
|
|
TaskQueue too_large(max_task_queue_entries + 1U);
|
|
|
|
const auto null_task = queue.push(TaskItem {});
|
|
PP_EXPECT(h, !null_task.ok());
|
|
PP_EXPECT(h, null_task.code == StatusCode::invalid_argument);
|
|
|
|
PP_EXPECT(h, queue.push(TaskItem { .callback = increment, .user_data = &counter }).ok());
|
|
const auto full = queue.push(TaskItem { .callback = increment, .user_data = &counter });
|
|
PP_EXPECT(h, !full.ok());
|
|
PP_EXPECT(h, full.code == StatusCode::out_of_range);
|
|
|
|
const auto invalid_capacity = invalid_queue.push(TaskItem { .callback = increment, .user_data = &counter });
|
|
const auto excessive_capacity = too_large.push(TaskItem { .callback = increment, .user_data = &counter });
|
|
PP_EXPECT(h, !invalid_capacity.ok());
|
|
PP_EXPECT(h, invalid_capacity.code == StatusCode::out_of_range);
|
|
PP_EXPECT(h, !excessive_capacity.ok());
|
|
PP_EXPECT(h, excessive_capacity.code == StatusCode::out_of_range);
|
|
}
|
|
|
|
void run_all_and_clear_are_bounded(pp::tests::Harness& h)
|
|
{
|
|
Counter counter;
|
|
TaskQueue queue(4);
|
|
|
|
PP_EXPECT(h, queue.max_entries() == 4U);
|
|
PP_EXPECT(h, queue.push(TaskItem { .callback = increment, .user_data = &counter }).ok());
|
|
PP_EXPECT(h, queue.push(TaskItem { .callback = increment, .user_data = &counter }).ok());
|
|
PP_EXPECT(h, queue.run_all() == 2U);
|
|
PP_EXPECT(h, counter.value == 2);
|
|
|
|
PP_EXPECT(h, queue.push(TaskItem { .callback = add_two, .user_data = &counter }).ok());
|
|
queue.clear();
|
|
PP_EXPECT(h, queue.empty());
|
|
const auto empty_pop = queue.pop();
|
|
PP_EXPECT(h, !empty_pop.ok());
|
|
PP_EXPECT(h, empty_pop.status().code == StatusCode::out_of_range);
|
|
}
|
|
|
|
}
|
|
|
|
int main()
|
|
{
|
|
pp::tests::Harness harness;
|
|
harness.run("runs_tasks_in_fifo_order", runs_tasks_in_fifo_order);
|
|
harness.run("pops_without_running", pops_without_running);
|
|
harness.run("rejects_invalid_or_excessive_work", rejects_invalid_or_excessive_work);
|
|
harness.run("run_all_and_clear_are_bounded", run_all_and_clear_are_bounded);
|
|
return harness.finish();
|
|
}
|