test_task.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. #include <atomic>
  2. #include <esp_log.h>
  3. #include "kbf.h"
  4. #include "kbf/task.h"
  5. #include <unity.h>
  6. /** delay between cycles */
  7. #define KBF_TASK_TEST_DELAY 200
  8. /** counter increase factor for the "runner" task */
  9. #define KBF_TASK_TEST_RUNNER_INC 10
  10. /** counter increase factor for the "quitter" task */
  11. #define KBF_TASK_TEST_QUITTER_INC 1
  12. /** number of cycles to run for each testing stage */
  13. #define KBF_TASK_TEST_CYCLES 5
  14. using namespace std;
  15. using namespace kbf;
  16. static atomic<int> counter{0};
  17. /** runs until stopped */
  18. class Runner : public Task {
  19. public:
  20. Runner(const string &name, void *arg, const uint32_t stackSize, const uint32_t priority) :
  21. Task(name, arg, stackSize, priority) {}
  22. static constexpr const char *const TAG = "Runner";
  23. protected:
  24. [[noreturn]] void run(void *arg) override {
  25. auto delay = static_cast<int *>(arg);
  26. TEST_ASSERT_EQUAL(KBF_TASK_TEST_DELAY, *delay);
  27. int i = 0;
  28. while (true) {
  29. ESP_LOGI(TAG, "cycle %d", i++);
  30. counter += KBF_TASK_TEST_RUNNER_INC;
  31. kbf::sleep(*delay);
  32. }
  33. }
  34. };
  35. struct QuitterArg {
  36. int delay;
  37. int cycles;
  38. };
  39. /** stops after KBF_TASK_TEST_CYCLES cycles */
  40. class Quitter : public Task {
  41. public:
  42. Quitter(const string &name, void *arg, const uint32_t stackSize, const uint32_t priority) :
  43. Task(name, arg, stackSize, priority) {}
  44. static constexpr const char *const TAG = "Quitter";
  45. protected:
  46. void run(void *arg) override {
  47. auto argData = static_cast<QuitterArg *>(arg);
  48. TEST_ASSERT_EQUAL(KBF_TASK_TEST_DELAY, argData->delay);
  49. TEST_ASSERT_EQUAL(KBF_TASK_TEST_CYCLES, argData->cycles);
  50. int i;
  51. for (i = 0; i < argData->cycles; i++) {
  52. ESP_LOGI(TAG, "cycle %d/%d", i, argData->cycles);
  53. counter += KBF_TASK_TEST_QUITTER_INC;
  54. kbf::sleep(argData->delay);
  55. }
  56. ESP_LOGI(TAG, "done: %d/%d", i, argData->cycles);
  57. }
  58. };
  59. TEST_CASE("Task", "[kbf_task]") {
  60. counter = 0;
  61. uint32_t delay = KBF_TASK_TEST_DELAY;
  62. QuitterArg quitterArg = {KBF_TASK_TEST_DELAY, KBF_TASK_TEST_CYCLES};
  63. auto runnerTask = task::start<Runner>("test_runner", &delay);
  64. auto quitterTask = task::start<Quitter>("test_quitter", &quitterArg);
  65. kbf::sleep(40); // make sure the tasks have started
  66. int expected = 0;
  67. // both tasks are running
  68. for (int i = 0; i < KBF_TASK_TEST_CYCLES; i++) {
  69. expected += KBF_TASK_TEST_RUNNER_INC + KBF_TASK_TEST_QUITTER_INC;
  70. TEST_ASSERT_EQUAL(expected, counter);
  71. TEST_ASSERT_TRUE(runnerTask->running())
  72. TEST_ASSERT_TRUE(quitterTask->running())
  73. kbf::sleep(KBF_TASK_TEST_DELAY);
  74. }
  75. // quitter has quit, only runner is left
  76. for (int i = 0; i < KBF_TASK_TEST_CYCLES; i++) {
  77. expected += KBF_TASK_TEST_RUNNER_INC;
  78. TEST_ASSERT_EQUAL(expected, counter);
  79. TEST_ASSERT_TRUE(runnerTask->running())
  80. TEST_ASSERT_FALSE(quitterTask->running())
  81. kbf::sleep(KBF_TASK_TEST_DELAY);
  82. }
  83. // stop runner; no more updates
  84. runnerTask->stop();
  85. TEST_ASSERT_FALSE(runnerTask->running());
  86. expected += KBF_TASK_TEST_RUNNER_INC; // runner went another cycle while we were sleeping
  87. for (int i = 0; i < KBF_TASK_TEST_CYCLES; i++) {
  88. TEST_ASSERT_EQUAL(expected, counter);
  89. kbf::sleep(KBF_TASK_TEST_DELAY);
  90. }
  91. }
  92. static QuitterArg scopeTestArg = {KBF_TASK_TEST_DELAY, KBF_TASK_TEST_CYCLES};
  93. void createTask() {
  94. task::start<Quitter>("test_task_scope", &scopeTestArg);
  95. }
  96. TEST_CASE("Task out of scope", "[kbf_task]") {
  97. counter = 0;
  98. createTask();
  99. kbf::sleep(KBF_TASK_TEST_DELAY * KBF_TASK_TEST_CYCLES);
  100. TEST_ASSERT_EQUAL(KBF_TASK_TEST_CYCLES * KBF_TASK_TEST_QUITTER_INC, counter);
  101. }
  102. TEST_CASE("Task out of memory", "[kbf_task]") {
  103. QuitterArg quitterArg = {KBF_TASK_TEST_DELAY, KBF_TASK_TEST_CYCLES};
  104. counter = 0;
  105. bool caught = false;
  106. try {
  107. task::start<Quitter>("test_task_oom", &quitterArg, 2 << 24);
  108. } catch (kbf::exception::OutOfMemoryError &e) {
  109. caught = true;
  110. }
  111. TEST_ASSERT_TRUE(caught)
  112. }