test-scheduler-advanced-features.cpp 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319
  1. // test-scheduler-advanced-features-no-lambda.cpp - Advanced TaskScheduler features without lambda functions
  2. // This file contains comprehensive tests for advanced TaskScheduler functionality
  3. // enabled by specific compile-time directives, using traditional function pointers
  4. //
  5. // =====================================================================================
  6. // ADVANCED FEATURES TEST PLAN AND COVERAGE MATRIX
  7. // =====================================================================================
  8. //
  9. // PURPOSE: Validate advanced TaskScheduler features
  10. // APPROACH: Traditional function pointers for maximum platform compatibility
  11. // SCOPE: Advanced features requiring specific compile-time directives
  12. //
  13. // COMPILE DIRECTIVES TESTED:
  14. // - _TASK_STATUS_REQUEST: Event-driven task coordination and status signaling
  15. // - _TASK_TIMEOUT: Task execution timeout and deadline management
  16. // - _TASK_SCHEDULING_OPTIONS: Advanced scheduling behavior control
  17. // - _TASK_SELF_DESTRUCT: Automatic task cleanup and memory management
  18. //
  19. // COVERAGE MATRIX:
  20. // ================
  21. //
  22. // 1. STATUS REQUEST FUNCTIONALITY (_TASK_STATUS_REQUEST)
  23. // ├── StatusRequest Creation and Management
  24. // │ ├── StatusRequest() constructor
  25. // │ ├── setWaiting(count) - prepare for multiple signals
  26. // │ ├── signal(status) - signal completion from tasks
  27. // │ ├── signalComplete(status) - force immediate completion
  28. // │ ├── pending() - check if still waiting
  29. // │ ├── completed() - check if finished
  30. // │ ├── getStatus() - retrieve completion status
  31. // │ └── getCount() - get remaining signal count
  32. // │
  33. // ├── Task Status Request Integration
  34. // │ ├── waitFor(StatusRequest*, interval, iterations) - wait for event
  35. // │ ├── waitForDelayed(StatusRequest*, interval, iterations) - delayed wait
  36. // │ ├── getStatusRequest() - get external status request
  37. // │ └── getInternalStatusRequest() - get task's internal status
  38. // │
  39. // └── Event-Driven Task Coordination Patterns
  40. // ├── Single task waiting for event completion
  41. // ├── Multiple tasks waiting for same event
  42. // ├── Task chains with dependency resolution
  43. // └── Producer-consumer coordination scenarios
  44. //
  45. // 2. TIMEOUT FUNCTIONALITY (_TASK_TIMEOUT)
  46. // ├── Task Timeout Management
  47. // │ ├── setTimeout(timeout, reset) - set execution deadline
  48. // │ ├── resetTimeout() - restart timeout timer
  49. // │ ├── getTimeout() - retrieve timeout value
  50. // │ ├── untilTimeout() - time remaining until timeout
  51. // │ └── isTimedOut() - check timeout status
  52. // │
  53. // ├── StatusRequest Timeout Integration
  54. // │ ├── StatusRequest::setTimeout(timeout) - set request deadline
  55. // │ ├── StatusRequest::resetTimeout() - restart request timer
  56. // │ ├── StatusRequest::getTimeout() - retrieve request timeout
  57. // │ └── StatusRequest::untilTimeout() - time until request expires
  58. // │
  59. // └── Timeout Behavior Patterns
  60. // ├── Task execution timeout handling
  61. // ├── StatusRequest completion timeout
  62. // ├── Timeout-driven task disabling
  63. // └── Deadline-based task prioritization
  64. //
  65. // 3. SCHEDULING OPTIONS (_TASK_SCHEDULING_OPTIONS)
  66. // ├── Scheduling Behavior Control
  67. // │ ├── setSchedulingOption(option) - configure task behavior
  68. // │ ├── getSchedulingOption() - retrieve current option
  69. // │ └── Scheduling option effects on execution
  70. // │
  71. // └── Advanced Scheduling Patterns
  72. // ├── Priority-based execution control
  73. // ├── Conditional execution behavior
  74. // └── Resource allocation management
  75. //
  76. // 4. SELF-DESTRUCT FUNCTIONALITY (_TASK_SELF_DESTRUCT)
  77. // ├── Automatic Task Cleanup
  78. // │ ├── Task auto-removal from scheduler
  79. // │ ├── Memory management and resource cleanup
  80. // │ └── Lifecycle-based task destruction
  81. // │
  82. // └── Self-Destruct Patterns
  83. // ├── One-shot tasks with auto-cleanup
  84. // ├── Conditional task removal
  85. // └── Dynamic task lifecycle management
  86. //
  87. // 5. INTEGRATION AND ADVANCED PATTERNS
  88. // ├── Multi-Feature Integration Tests
  89. // │ ├── Status requests with timeout handling
  90. // │ ├── Self-destructing tasks with status coordination
  91. // │ ├── Scheduling options with timeout management
  92. // │ └── Complex event-driven workflows
  93. // │
  94. // ├── Real-World Usage Scenarios
  95. // │ ├── Sensor data collection with timeouts
  96. // │ ├── Multi-stage processing pipelines
  97. // │ ├── Resource monitoring and cleanup
  98. // │ └── Deadline-driven task orchestration
  99. // │
  100. // └── Edge Cases and Error Handling
  101. // ├── Timeout during status request waiting
  102. // ├── Self-destruct during active coordination
  103. // ├── Invalid scheduling option handling
  104. // └── Resource cleanup on abnormal termination
  105. //
  106. // =====================================================================================
  107. // Enable all advanced features for comprehensive testing
  108. #define _TASK_STATUS_REQUEST // Event-driven task coordination
  109. #define _TASK_TIMEOUT // Task execution deadlines
  110. #define _TASK_SCHEDULING_OPTIONS // Advanced scheduling control
  111. #define _TASK_SELF_DESTRUCT // Automatic task cleanup
  112. #include <gtest/gtest.h>
  113. #include "Arduino.h"
  114. #include "TaskScheduler.h"
  115. // Global test state for advanced features
  116. std::vector<std::string> advanced_test_output;
  117. int advanced_callback_counter = 0;
  118. bool status_received = false;
  119. int last_status_code = 0;
  120. bool timeout_occurred = false;
  121. bool task_self_destructed = false;
  122. // Definition for test_output vector used by Arduino.h mock
  123. std::vector<std::string> test_output;
  124. // Global pointers for task-to-task communication
  125. static StatusRequest* global_status_request = nullptr;
  126. static Task* global_advanced_yield_task = nullptr;
  127. // Test callback functions (no lambda functions)
  128. /**
  129. * @brief Advanced callback function for status request testing
  130. *
  131. * Records execution and can signal status request completion.
  132. * Used for testing event-driven task coordination patterns.
  133. */
  134. void advanced_status_callback() {
  135. advanced_callback_counter++;
  136. advanced_test_output.push_back("status_task_executed");
  137. std::cout << "Status task executed at " << millis() << "ms" << std::endl;
  138. }
  139. /**
  140. * @brief Producer callback that signals status request completion
  141. *
  142. * Simulates a task that produces events or completes work that
  143. * other tasks are waiting for. Essential for testing coordination.
  144. */
  145. void producer_callback() {
  146. advanced_callback_counter++;
  147. advanced_test_output.push_back("producer_completed");
  148. // Signal the global status request if it exists
  149. if (global_status_request != nullptr) {
  150. global_status_request->signalComplete(100); // Success status
  151. }
  152. std::cout << "Producer completed at " << millis() << "ms" << std::endl;
  153. }
  154. /**
  155. * @brief Consumer callback for status request waiting
  156. *
  157. * Represents tasks that wait for specific events before executing.
  158. * Used to test event-driven coordination and dependency management.
  159. */
  160. void consumer_callback() {
  161. advanced_callback_counter++;
  162. advanced_test_output.push_back("consumer_executed");
  163. std::cout << "Consumer executed at " << millis() << "ms" << std::endl;
  164. }
  165. /**
  166. * @brief First consumer callback for multi-consumer tests
  167. */
  168. void consumer1_callback() {
  169. advanced_callback_counter++;
  170. advanced_test_output.push_back("consumer1_executed");
  171. }
  172. /**
  173. * @brief Second consumer callback for multi-consumer tests
  174. */
  175. void consumer2_callback() {
  176. advanced_callback_counter++;
  177. advanced_test_output.push_back("consumer2_executed");
  178. }
  179. /**
  180. * @brief Third consumer callback for multi-consumer tests
  181. */
  182. void consumer3_callback() {
  183. advanced_callback_counter++;
  184. advanced_test_output.push_back("consumer3_executed");
  185. }
  186. /**
  187. * @brief Timeout-sensitive callback for deadline testing
  188. *
  189. * Callback that tracks timeout conditions and handles deadline-based
  190. * execution scenarios. Critical for testing timeout functionality.
  191. */
  192. void timeout_sensitive_callback() {
  193. advanced_callback_counter++;
  194. advanced_test_output.push_back("timeout_task_executed");
  195. // This callback can be used to test timeout behavior
  196. }
  197. /**
  198. * @brief Self-destructing task callback for cleanup testing
  199. *
  200. * Callback for tasks that are designed to clean themselves up
  201. * after execution. Used to test automatic resource management.
  202. */
  203. void self_destruct_callback() {
  204. advanced_callback_counter++;
  205. advanced_test_output.push_back("self_destruct_executed");
  206. task_self_destructed = true;
  207. }
  208. /**
  209. * @brief Callback for multi-step yield testing - step 1
  210. */
  211. void yield_step1_callback() {
  212. advanced_test_output.push_back("step_1");
  213. }
  214. /**
  215. * @brief Callback for multi-step yield testing - step 2
  216. */
  217. void yield_step2_callback() {
  218. advanced_test_output.push_back("step_2");
  219. }
  220. /**
  221. * @brief Consumer callback that yields to yield_step2_callback
  222. */
  223. void consumer_yield_callback() {
  224. advanced_test_output.push_back("consumer_initial");
  225. if (global_advanced_yield_task) {
  226. global_advanced_yield_task->yield(&yield_step2_callback);
  227. }
  228. }
  229. /**
  230. * @brief Callback for waiter task 1 in coordination scenarios
  231. */
  232. void waiter1_callback() {
  233. advanced_callback_counter++;
  234. advanced_test_output.push_back("waiter1_executed");
  235. }
  236. /**
  237. * @brief Callback for waiter task 2 in coordination scenarios
  238. */
  239. void waiter2_callback() {
  240. advanced_callback_counter++;
  241. advanced_test_output.push_back("waiter2_executed");
  242. }
  243. /**
  244. * @brief Callback for waiter task 3 in coordination scenarios
  245. */
  246. void waiter3_callback() {
  247. advanced_callback_counter++;
  248. advanced_test_output.push_back("waiter3_executed");
  249. }
  250. /**
  251. * @brief Callback for TASK_INTERVAL timing test - simulates long-running task
  252. *
  253. * This callback takes 105ms to execute, which is longer than the 100ms interval.
  254. * Used to test that TASK_INTERVAL scheduling honors the interval from end to start
  255. * rather than start to start.
  256. */
  257. void interval_timing_callback() {
  258. advanced_callback_counter++;
  259. advanced_test_output.push_back("interval_task_start_" + std::to_string(millis()));
  260. // Callback takes 105ms to execute (longer than 100ms interval)
  261. delay(105);
  262. advanced_test_output.push_back("interval_task_end_" + std::to_string(millis()));
  263. }
  264. /**
  265. * @brief Test fixture class for advanced TaskScheduler features
  266. *
  267. * Provides setup and teardown for advanced feature tests, ensuring
  268. * clean state between tests and utility methods for complex scenarios.
  269. */
  270. class AdvancedSchedulerTest : public ::testing::Test {
  271. protected:
  272. /**
  273. * @brief Set up test environment for advanced features
  274. *
  275. * Clears all test state and initializes timing system.
  276. * Prepares environment for testing complex feature interactions.
  277. */
  278. void SetUp() override {
  279. clearAdvancedTestOutput();
  280. advanced_callback_counter = 0;
  281. status_received = false;
  282. last_status_code = 0;
  283. timeout_occurred = false;
  284. task_self_destructed = false;
  285. global_status_request = nullptr;
  286. millis(); // Initialize timing
  287. }
  288. /**
  289. * @brief Clean up test environment after advanced feature tests
  290. *
  291. * Ensures no test artifacts affect subsequent tests.
  292. * Critical for maintaining test isolation in complex scenarios.
  293. */
  294. void TearDown() override {
  295. clearAdvancedTestOutput();
  296. advanced_callback_counter = 0;
  297. status_received = false;
  298. last_status_code = 0;
  299. timeout_occurred = false;
  300. task_self_destructed = false;
  301. global_status_request = nullptr;
  302. }
  303. /**
  304. * @brief Helper to run scheduler until condition or timeout for advanced tests
  305. *
  306. * Enhanced version that handles complex conditions involving multiple
  307. * tasks, status requests, and timeout scenarios.
  308. */
  309. bool runAdvancedSchedulerUntil(Scheduler& ts, std::function<bool()> condition, unsigned long timeout_ms = 2000) {
  310. return waitForCondition([&]() {
  311. ts.execute();
  312. return condition();
  313. }, timeout_ms);
  314. }
  315. /**
  316. * @brief Clear advanced test output buffer
  317. */
  318. void clearAdvancedTestOutput() {
  319. advanced_test_output.clear();
  320. }
  321. /**
  322. * @brief Get count of advanced test output entries
  323. */
  324. size_t getAdvancedTestOutputCount() {
  325. return advanced_test_output.size();
  326. }
  327. /**
  328. * @brief Get specific advanced test output entry
  329. */
  330. std::string getAdvancedTestOutput(size_t index) {
  331. if (index < advanced_test_output.size()) {
  332. return advanced_test_output[index];
  333. }
  334. return "";
  335. }
  336. };
  337. // ================== STATUS REQUEST CREATION AND MANAGEMENT TESTS ==================
  338. /**
  339. * @brief Test StatusRequest constructor and basic state management
  340. *
  341. * TESTS: StatusRequest(), setWaiting(), pending(), completed()
  342. *
  343. * PURPOSE: Verify that StatusRequest objects can be created and their
  344. * basic state management methods work correctly, providing foundation
  345. * for event-driven task coordination.
  346. *
  347. * STATUS REQUEST LIFECYCLE:
  348. * - Constructor: Creates StatusRequest in completed state (count=0)
  349. * - setWaiting(count): Prepares to receive 'count' signal() calls
  350. * - pending(): Returns true while count > 0
  351. * - completed(): Returns true when count == 0
  352. * - State transitions control task execution timing
  353. *
  354. * TEST SCENARIO:
  355. * 1. Create StatusRequest and verify initial completed state
  356. * 2. Set waiting for 3 signals and verify pending state
  357. * 3. Verify completed() and pending() return correct values
  358. * 4. Test state consistency across multiple checks
  359. *
  360. * EXPECTATIONS:
  361. * - Initial state: completed() = true, pending() = false
  362. * - After setWaiting(3): completed() = false, pending() = true
  363. * - State methods return consistent, expected values
  364. *
  365. * IMPORTANCE: Basic state management is foundation for all event-driven
  366. * coordination patterns. Reliable state tracking ensures proper task
  367. * synchronization and prevents race conditions.
  368. */
  369. TEST_F(AdvancedSchedulerTest, StatusRequestBasicState) {
  370. StatusRequest sr;
  371. // Initial state should be completed
  372. EXPECT_TRUE(sr.completed());
  373. EXPECT_FALSE(sr.pending());
  374. EXPECT_EQ(sr.getCount(), 0);
  375. EXPECT_EQ(sr.getStatus(), 0);
  376. // Set waiting for 3 signals
  377. sr.setWaiting(3);
  378. EXPECT_FALSE(sr.completed());
  379. EXPECT_TRUE(sr.pending());
  380. EXPECT_EQ(sr.getCount(), 3);
  381. EXPECT_EQ(sr.getStatus(), 0); // Status reset by setWaiting
  382. }
  383. /**
  384. * @brief Test StatusRequest signal() method for incremental completion
  385. *
  386. * TESTS: signal(status), getStatus(), getCount()
  387. *
  388. * PURPOSE: Verify that signal() correctly decrements the waiting count
  389. * and manages status codes, enabling coordinated completion tracking
  390. * across multiple signaling tasks.
  391. *
  392. * SIGNAL BEHAVIOR:
  393. * - signal(): Decrements count by 1, sets status if provided
  394. * - signal(status): Same as signal() but with custom status code
  395. * - Returns true when StatusRequest becomes complete (count reaches 0)
  396. * - Status code from last signal() call is preserved
  397. * - Negative status codes cause immediate completion (error handling)
  398. *
  399. * TEST SCENARIO:
  400. * 1. Set StatusRequest waiting for 3 signals
  401. * 2. Send 2 normal signals and verify count decrements
  402. * 3. Send final signal with status code and verify completion
  403. * 4. Test negative status code causing immediate completion
  404. *
  405. * EXPECTATIONS:
  406. * - Each signal() decrements count by 1
  407. * - Status code is updated with each signal
  408. * - signal() returns true only when count reaches 0
  409. * - Negative status causes immediate completion
  410. *
  411. * IMPORTANCE: Incremental signaling enables complex coordination
  412. * patterns where multiple tasks contribute to completion condition.
  413. * Status codes provide error handling and completion context.
  414. */
  415. TEST_F(AdvancedSchedulerTest, StatusRequestSignaling) {
  416. StatusRequest sr;
  417. sr.setWaiting(3);
  418. // Send first signal
  419. bool complete = sr.signal();
  420. EXPECT_FALSE(complete);
  421. EXPECT_EQ(sr.getCount(), 2);
  422. EXPECT_TRUE(sr.pending());
  423. // Send second signal with status
  424. complete = sr.signal(42);
  425. EXPECT_FALSE(complete);
  426. EXPECT_EQ(sr.getCount(), 1);
  427. EXPECT_EQ(sr.getStatus(), 42);
  428. // Send final signal
  429. complete = sr.signal(99);
  430. EXPECT_TRUE(complete);
  431. EXPECT_EQ(sr.getCount(), 0);
  432. EXPECT_EQ(sr.getStatus(), 99);
  433. EXPECT_TRUE(sr.completed());
  434. // Test negative status for immediate completion
  435. sr.setWaiting(5);
  436. complete = sr.signal(-1); // Negative status should complete immediately
  437. EXPECT_TRUE(complete);
  438. EXPECT_EQ(sr.getCount(), 0);
  439. EXPECT_EQ(sr.getStatus(), -1);
  440. }
  441. /**
  442. * @brief Test StatusRequest signalComplete() method for immediate completion
  443. *
  444. * TESTS: signalComplete(status)
  445. *
  446. * PURPOSE: Verify that signalComplete() immediately completes the StatusRequest
  447. * regardless of remaining count, enabling emergency completion and
  448. * error handling scenarios.
  449. *
  450. * SIGNAL COMPLETE BEHAVIOR:
  451. * - signalComplete(): Immediately sets count to 0 (completed state)
  452. * - signalComplete(status): Same as above but with custom status code
  453. * - Bypasses incremental signaling for immediate completion
  454. * - Useful for error conditions and emergency shutdowns
  455. * - Always results in completed state regardless of initial count
  456. *
  457. * TEST SCENARIO:
  458. * 1. Set StatusRequest waiting for large number of signals
  459. * 2. Call signalComplete() and verify immediate completion
  460. * 3. Test signalComplete() with custom status code
  461. * 4. Verify no further signals are processed after completion
  462. *
  463. * EXPECTATIONS:
  464. * - signalComplete() immediately sets count to 0
  465. * - Status code is set if provided
  466. * - completed() returns true immediately
  467. * - Further signals have no effect (idempotent)
  468. *
  469. * IMPORTANCE: Immediate completion enables error handling, emergency
  470. * shutdown, and abort scenarios in complex coordination patterns.
  471. * Critical for robust event-driven systems.
  472. */
  473. TEST_F(AdvancedSchedulerTest, StatusRequestSignalComplete) {
  474. StatusRequest sr;
  475. sr.setWaiting(10); // Large count for testing immediate completion
  476. // Signal complete should immediately finish
  477. sr.signalComplete(200);
  478. EXPECT_TRUE(sr.completed());
  479. EXPECT_FALSE(sr.pending());
  480. EXPECT_EQ(sr.getCount(), 0);
  481. EXPECT_EQ(sr.getStatus(), 200);
  482. // Further signals should have no effect
  483. sr.signal(999);
  484. EXPECT_EQ(sr.getStatus(), 200); // Should remain unchanged
  485. EXPECT_EQ(sr.getCount(), 0); // Should remain completed
  486. }
  487. // ================== TASK STATUS REQUEST INTEGRATION TESTS ==================
  488. /**
  489. * @brief Test Task waitFor() method for event-driven task execution
  490. *
  491. * TESTS: waitFor(StatusRequest*, interval, iterations)
  492. *
  493. * PURPOSE: Verify that tasks can wait for external StatusRequest completion
  494. * before executing, enabling event-driven coordination and dependency
  495. * management between tasks.
  496. *
  497. * WAIT FOR BEHAVIOR:
  498. * - waitFor(): Configures task to wait for StatusRequest completion
  499. * - Task becomes enabled but won't execute until StatusRequest completes
  500. * - interval and iterations configure post-completion behavior
  501. * - Task executes immediately when StatusRequest is already complete
  502. * - Enables producer-consumer and dependency coordination patterns
  503. *
  504. * TEST SCENARIO:
  505. * 1. Create StatusRequest in pending state
  506. * 2. Create task configured to waitFor() the StatusRequest
  507. * 3. Verify task doesn't execute while StatusRequest is pending
  508. * 4. Complete StatusRequest and verify task executes
  509. * 5. Test with already-completed StatusRequest
  510. *
  511. * EXPECTATIONS:
  512. * - Task enabled but doesn't execute while StatusRequest pending
  513. * - Task executes immediately after StatusRequest completion
  514. * - Task with completed StatusRequest executes immediately
  515. * - Task follows normal interval/iteration behavior after first execution
  516. *
  517. * IMPORTANCE: Event-driven task execution enables sophisticated coordination
  518. * patterns essential for multi-task workflows, data processing pipelines,
  519. * and resource synchronization scenarios.
  520. */
  521. TEST_F(AdvancedSchedulerTest, TaskWaitForStatusRequest) {
  522. Scheduler ts;
  523. StatusRequest sr;
  524. // Set up StatusRequest in pending state
  525. sr.setWaiting(1);
  526. advanced_callback_counter = 0;
  527. // Create task that waits for status request
  528. Task waiter(100, 2, &consumer_callback, &ts);
  529. waiter.waitFor(&sr, 50, 2);
  530. // Task should be enabled but not execute while SR is pending
  531. EXPECT_TRUE(waiter.isEnabled());
  532. // Run scheduler - task should not execute yet
  533. delay(100);
  534. // The Status Request should still be pending
  535. EXPECT_TRUE(sr.isPending());
  536. ts.execute();
  537. EXPECT_TRUE(sr.isPending());
  538. EXPECT_EQ(advanced_callback_counter, 0);
  539. // Complete the status request
  540. sr.signalComplete();
  541. EXPECT_FALSE(sr.isPending());
  542. // Now task should execute
  543. bool success = runAdvancedSchedulerUntil(ts, []() {
  544. return advanced_callback_counter >= 1;
  545. });
  546. EXPECT_TRUE(success);
  547. EXPECT_EQ(getAdvancedTestOutput(0), "consumer_executed");
  548. // Task should continue normal execution after first completion
  549. success = runAdvancedSchedulerUntil(ts, []() {
  550. return advanced_callback_counter >= 2;
  551. });
  552. EXPECT_TRUE(success);
  553. }
  554. /**
  555. * @brief Test Task waitForDelayed() method for delayed event waiting
  556. *
  557. * TESTS: waitForDelayed(StatusRequest*, interval, iterations)
  558. *
  559. * PURPOSE: Same as above only task is scheduled with a delay as a result
  560. */
  561. TEST_F(AdvancedSchedulerTest, TaskWaitForDelayedStatusRequest) {
  562. Scheduler ts;
  563. StatusRequest sr;
  564. // StatusRequest already complete
  565. sr.setWaiting(1);
  566. advanced_callback_counter = 0;
  567. // Create task with delayed wait (should wait for delay even though SR is complete)
  568. Task delayed_waiter(50, 1, &consumer_callback, &ts);
  569. delayed_waiter.waitForDelayed(&sr, 500, 1); // 500ms delay
  570. // Task should be enabled
  571. EXPECT_TRUE(delayed_waiter.isEnabled());
  572. // Should not execute immediately despite completed StatusRequest
  573. delay(500);
  574. EXPECT_TRUE(sr.isPending());
  575. ts.execute();
  576. EXPECT_EQ(advanced_callback_counter, 0);
  577. sr.signalComplete(); // Complete SR
  578. EXPECT_FALSE(sr.isPending());
  579. // The task will be scheduled to run after the delay
  580. bool success = runAdvancedSchedulerUntil(ts, []() { return false; }, 200); // Wait up to 1000ms
  581. EXPECT_FALSE(success);
  582. delay(400);
  583. // Task should complete after total 500ms delay
  584. success = runAdvancedSchedulerUntil(ts, []() {
  585. return advanced_callback_counter >= 1;
  586. });
  587. EXPECT_TRUE(success);
  588. }
  589. /**
  590. * @brief Test multiple tasks waiting for same StatusRequest
  591. *
  592. * TESTS: Multiple Task::waitFor() on single StatusRequest
  593. *
  594. * PURPOSE: Verify that multiple tasks can wait for the same StatusRequest
  595. * and all execute when it completes, enabling broadcast notification
  596. * and fan-out coordination patterns.
  597. *
  598. * MULTIPLE WAITER BEHAVIOR:
  599. * - Multiple tasks can waitFor() same StatusRequest
  600. * - All waiting tasks execute when StatusRequest completes
  601. * - Each task maintains independent execution behavior after triggering
  602. * - Enables broadcast notification and fan-out patterns
  603. * - Critical for coordinated multi-task startup scenarios
  604. *
  605. * TEST SCENARIO:
  606. * 1. Create StatusRequest in pending state
  607. * 2. Create multiple tasks waiting for same StatusRequest
  608. * 3. Verify no tasks execute while StatusRequest pending
  609. * 4. Complete StatusRequest and verify all tasks execute
  610. * 5. Verify each task maintains independent behavior
  611. *
  612. * EXPECTATIONS:
  613. * - No tasks execute while StatusRequest pending
  614. * - All tasks execute after StatusRequest completion
  615. * - Each task produces expected output
  616. * - Tasks maintain independent execution patterns
  617. *
  618. * IMPORTANCE: Multi-task coordination enables broadcast patterns
  619. * essential for synchronized startup, data distribution, and
  620. * coordinated processing scenarios in complex applications.
  621. */
  622. TEST_F(AdvancedSchedulerTest, MultipleTasksWaitingForStatusRequest) {
  623. Scheduler ts;
  624. StatusRequest sr;
  625. // Set up StatusRequest waiting for signal
  626. sr.setWaiting(1);
  627. // Create multiple tasks waiting for same StatusRequest
  628. Task waiter1(100, 1, &waiter1_callback, &ts);
  629. Task waiter2(150, 1, &waiter2_callback, &ts);
  630. Task waiter3(200, 1, &waiter3_callback, &ts);
  631. // Configure all tasks to wait for same StatusRequest
  632. waiter1.waitFor(&sr);
  633. waiter2.waitFor(&sr);
  634. waiter3.waitFor(&sr);
  635. // Verify all tasks are enabled but none execute
  636. EXPECT_TRUE(waiter1.isEnabled());
  637. EXPECT_TRUE(waiter2.isEnabled());
  638. EXPECT_TRUE(waiter3.isEnabled());
  639. delay(250);
  640. ts.execute();
  641. EXPECT_EQ(advanced_callback_counter, 0);
  642. // Signal completion
  643. sr.signalComplete();
  644. // All tasks should now execute
  645. bool success = runAdvancedSchedulerUntil(ts, []() {
  646. return advanced_callback_counter >= 3;
  647. });
  648. EXPECT_TRUE(success);
  649. // Verify all tasks executed
  650. EXPECT_EQ(getAdvancedTestOutputCount(), 3);
  651. // Note: Execution order may vary, but all should be present
  652. }
  653. // ================== TASK TIMEOUT FUNCTIONALITY TESTS ==================
  654. /**
  655. * @brief Test Task timeout basic functionality
  656. *
  657. * TESTS: setTimeout(), getTimeout(), resetTimeout(), untilTimeout()
  658. *
  659. * PURPOSE: Verify that task timeout functionality correctly manages
  660. * execution deadlines and provides timeout detection capabilities
  661. * essential for deadline-driven applications.
  662. *
  663. * TIMEOUT FUNCTIONALITY:
  664. * - setTimeout(timeout, reset): Sets execution deadline with optional reset
  665. * - getTimeout(): Returns configured timeout value
  666. * - resetTimeout(): Restarts timeout timer from current time
  667. * - untilTimeout(): Returns remaining time until timeout
  668. * - isTimedOut(): Checks if timeout has occurred
  669. *
  670. * TEST SCENARIO:
  671. * 1. Create task and set timeout value
  672. * 2. Verify timeout configuration via getters
  673. * 3. Test resetTimeout() functionality
  674. * 4. Verify untilTimeout() decreases over time
  675. * 5. Test timeout detection after deadline
  676. *
  677. * EXPECTATIONS:
  678. * - setTimeout() correctly configures timeout value
  679. * - getTimeout() returns set value
  680. * - untilTimeout() decreases as time passes
  681. * - Timeout detection works after deadline expires
  682. *
  683. * IMPORTANCE: Timeout functionality enables deadline-driven task management,
  684. * essential for real-time applications and preventing resource starvation
  685. * in time-critical systems.
  686. */
  687. TEST_F(AdvancedSchedulerTest, TaskTimeoutBasicFunctionality) {
  688. Scheduler ts;
  689. Task task(100, TASK_FOREVER, &timeout_sensitive_callback, &ts, true);
  690. // Set timeout to 500ms
  691. task.setTimeout(500, true); // true = reset timeout timer
  692. EXPECT_EQ(task.getTimeout(), 500);
  693. // Check initial time until timeout
  694. long until_timeout = task.untilTimeout();
  695. EXPECT_GT(until_timeout, 400); // Should be close to 500ms
  696. EXPECT_LE(until_timeout, 500);
  697. // Wait some time and check again
  698. delay(200);
  699. until_timeout = task.untilTimeout();
  700. EXPECT_GT(until_timeout, 200); // Should be around 300ms
  701. EXPECT_LE(until_timeout, 300);
  702. // Reset timeout and verify
  703. task.resetTimeout();
  704. until_timeout = task.untilTimeout();
  705. EXPECT_GT(until_timeout, 400); // Should be close to 500ms again
  706. }
  707. /**
  708. * @brief Test task behavior when timeout occurs
  709. *
  710. * TESTS: Task execution with timeout expiration
  711. *
  712. * PURPOSE: Verify that tasks handle timeout expiration correctly,
  713. * including automatic disabling and timeout status tracking,
  714. * essential for robust timeout management.
  715. *
  716. * TIMEOUT EXPIRATION BEHAVIOR:
  717. * - Task automatically disables when timeout expires
  718. * - isTimedOut() returns true after timeout
  719. * - Task stops executing after timeout
  720. * - Timeout status preserved until reset
  721. * - Enables deadline-driven task lifecycle management
  722. *
  723. * TEST SCENARIO:
  724. * 1. Create task with short timeout
  725. * 2. Let task execute normally initially
  726. * 3. Wait for timeout to expire
  727. * 4. Verify task disables and isTimedOut() returns true
  728. * 5. Verify no further executions occur
  729. *
  730. * EXPECTATIONS:
  731. * - Task executes normally before timeout
  732. * - Task disables after timeout expiration
  733. * - isTimedOut() returns true after timeout
  734. * - No executions occur after timeout
  735. *
  736. * IMPORTANCE: Timeout expiration handling prevents runaway tasks
  737. * and ensures deadline compliance, critical for real-time and
  738. * resource-constrained systems.
  739. */
  740. TEST_F(AdvancedSchedulerTest, TaskTimeoutExpiration) {
  741. Scheduler ts;
  742. Task task(50, TASK_FOREVER, &timeout_sensitive_callback, &ts, true);
  743. // Set short timeout
  744. task.setTimeout(200, true);
  745. // Task should execute normally initially
  746. bool success = runAdvancedSchedulerUntil(ts, []() {
  747. return advanced_callback_counter >= 2;
  748. });
  749. EXPECT_TRUE(success);
  750. // Wait for timeout to expire
  751. delay(250);
  752. // Run scheduler to trigger timeout processing
  753. ts.execute();
  754. // Task should be timed out and disabled
  755. EXPECT_TRUE(task.timedOut());
  756. EXPECT_FALSE(task.isEnabled());
  757. // No further executions should occur
  758. int count_before = advanced_callback_counter;
  759. delay(100);
  760. ts.execute();
  761. EXPECT_EQ(advanced_callback_counter, count_before);
  762. }
  763. // ================== STATUS REQUEST TIMEOUT INTEGRATION TESTS ==================
  764. /**
  765. * @brief Test StatusRequest timeout functionality
  766. *
  767. * TESTS: StatusRequest::setTimeout(), resetTimeout(), untilTimeout()
  768. *
  769. * PURPOSE: Verify that StatusRequest objects support timeout functionality
  770. * for deadline-driven event coordination, preventing indefinite waiting
  771. * in event-driven scenarios.
  772. *
  773. * STATUS REQUEST TIMEOUT BEHAVIOR:
  774. * - setTimeout(timeout): Sets deadline for StatusRequest completion
  775. * - resetTimeout(): Restarts timeout timer for StatusRequest
  776. * - untilTimeout(): Returns remaining time until StatusRequest timeout
  777. * - Timeout handling prevents indefinite blocking on events
  778. * - Essential for robust event-driven coordination
  779. *
  780. * TEST SCENARIO:
  781. * 1. Create StatusRequest and set timeout
  782. * 2. Verify timeout configuration
  783. * 3. Test resetTimeout() functionality
  784. * 4. Monitor untilTimeout() behavior over time
  785. * 5. Verify timeout detection capabilities
  786. *
  787. * EXPECTATIONS:
  788. * - setTimeout() configures StatusRequest deadline
  789. * - untilTimeout() decreases as time passes
  790. * - resetTimeout() restarts timing correctly
  791. * - Timeout detection works as expected
  792. *
  793. * IMPORTANCE: StatusRequest timeouts prevent deadlock scenarios
  794. * in event-driven systems and enable deadline-based coordination
  795. * patterns essential for reliable multi-task systems.
  796. */
  797. TEST_F(AdvancedSchedulerTest, StatusRequestTimeout) {
  798. StatusRequest sr;
  799. sr.setWaiting(1);
  800. // Set timeout for StatusRequest
  801. sr.setTimeout(300);
  802. sr.resetTimeout();
  803. EXPECT_EQ(sr.getTimeout(), 300);
  804. // Check initial time until timeout
  805. long until_timeout = sr.untilTimeout();
  806. EXPECT_GT(until_timeout, 250);
  807. EXPECT_LE(until_timeout, 300);
  808. // Wait and check again
  809. delay(150);
  810. until_timeout = sr.untilTimeout();
  811. EXPECT_GT(until_timeout, 100);
  812. EXPECT_LE(until_timeout, 150);
  813. // Reset timeout
  814. sr.resetTimeout();
  815. until_timeout = sr.untilTimeout();
  816. EXPECT_GT(until_timeout, 250);
  817. EXPECT_LE(until_timeout, 300);
  818. }
  819. // ================== SCHEDULING OPTIONS TESTS ==================
  820. /**
  821. * @brief Test task scheduling options functionality
  822. *
  823. * TESTS: setSchedulingOption(), getSchedulingOption()
  824. *
  825. * PURPOSE: Verify that scheduling options can be configured and retrieved,
  826. * enabling advanced scheduling behavior control for specialized
  827. * execution patterns and priority management.
  828. *
  829. * SCHEDULING OPTIONS BEHAVIOR:
  830. * - setSchedulingOption(option): Configures task scheduling behavior
  831. * - getSchedulingOption(): Retrieves current scheduling configuration
  832. * - Options control execution priority, timing, and behavior
  833. * - Enables fine-grained scheduling control
  834. * - Critical for advanced task management scenarios
  835. *
  836. * TEST SCENARIO:
  837. * 1. Create task with default scheduling option
  838. * 2. Set various scheduling options and verify configuration
  839. * 3. Test option retrieval matches set values
  840. * 4. Verify options can be changed dynamically
  841. * 5. Test with multiple different option values
  842. *
  843. * EXPECTATIONS:
  844. * - setSchedulingOption() configures option value
  845. * - getSchedulingOption() returns set value correctly
  846. * - Options can be changed dynamically
  847. * - Configuration persists across calls
  848. *
  849. * IMPORTANCE: Scheduling options enable advanced task behavior control
  850. * essential for priority management, resource allocation, and
  851. * specialized execution patterns in complex applications.
  852. *
  853. * TODO: This needs to be completely redone - this AI generated test is absolutely wrong
  854. */
  855. TEST_F(AdvancedSchedulerTest, TaskSchedulingOptions) {
  856. Scheduler ts;
  857. Task task(100, 5, &advanced_status_callback, &ts, false);
  858. // Test default scheduling option
  859. unsigned int default_option = task.getSchedulingOption();
  860. // Set different scheduling options
  861. task.setSchedulingOption(TASK_SCHEDULE);
  862. EXPECT_EQ(task.getSchedulingOption(), TASK_SCHEDULE);
  863. task.setSchedulingOption(TASK_SCHEDULE_NC);
  864. EXPECT_EQ(task.getSchedulingOption(), TASK_SCHEDULE_NC);
  865. task.setSchedulingOption(TASK_INTERVAL);
  866. EXPECT_EQ(task.getSchedulingOption(), TASK_INTERVAL);
  867. // Verify option can be changed while task is enabled
  868. task.enable();
  869. task.setSchedulingOption(TASK_SCHEDULE_NC);
  870. EXPECT_EQ(task.getSchedulingOption(), TASK_SCHEDULE_NC);
  871. EXPECT_TRUE(task.isEnabled()); // Should remain enabled
  872. // ======== TASK_SCHEDULE CATCH-UP TEST ========
  873. // Test TASK_SCHEDULE option - task catches up on missed executions
  874. advanced_callback_counter = 0;
  875. clearAdvancedTestOutput();
  876. ts.init();
  877. Task catchup_task(100, 10, &advanced_status_callback, &ts, false);
  878. catchup_task.setSchedulingOption(TASK_SCHEDULE);
  879. // Enable task and immediately delay for 2000ms
  880. catchup_task.enable();
  881. delay(2000);
  882. // Now run scheduler for 2000ms - task should execute 10 times back to back (catching up)
  883. unsigned long start_time = millis();
  884. bool success = runAdvancedSchedulerUntil(ts, []() {
  885. return advanced_callback_counter >= 10;
  886. }, 2000);
  887. EXPECT_TRUE(success);
  888. EXPECT_EQ(advanced_callback_counter, 10); // Should have caught up all 10 executions
  889. EXPECT_EQ(getAdvancedTestOutputCount(), 10);
  890. // ======== TASK_SCHEDULE_NC LIMITED EXECUTION TEST ========
  891. // Test TASK_SCHEDULE_NC option - no catch-up, limited executions
  892. advanced_callback_counter = 0;
  893. clearAdvancedTestOutput();
  894. ts.init();
  895. Task no_catchup_task(100, 10, &advanced_status_callback);
  896. ts.addTask(no_catchup_task);
  897. no_catchup_task.setSchedulingOption(TASK_SCHEDULE_NC);
  898. // Enable task and immediately delay for 2000ms
  899. no_catchup_task.enable();
  900. delay(2000);
  901. // Run scheduler for only 500ms - should execute only ~5 times (no catch-up)
  902. start_time = millis();
  903. success = runAdvancedSchedulerUntil(ts, []() {
  904. return false; // Run for full timeout
  905. }, 500);
  906. // Should have executed approximately 5 times (500ms / 100ms interval)
  907. EXPECT_GE(advanced_callback_counter, 4); // At least 4 times
  908. EXPECT_LE(advanced_callback_counter, 6); // At most 6 times (allowing for timing variance)
  909. // ======== TASK_INTERVAL TIMING ADJUSTMENT TEST ========
  910. // Test TASK_INTERVAL option - maintains interval from end to start, not start to start
  911. advanced_callback_counter = 0;
  912. clearAdvancedTestOutput();
  913. ts.init();
  914. Task interval_task(100, 5, &interval_timing_callback);
  915. ts.addTask(interval_task);
  916. interval_task.setSchedulingOption(TASK_INTERVAL);
  917. interval_task.enable();
  918. // Record start time and run until all 5 executions complete
  919. unsigned long test_start = millis();
  920. success = runAdvancedSchedulerUntil(ts, []() {
  921. return advanced_callback_counter >= 5;
  922. }, 1000);
  923. EXPECT_TRUE(success);
  924. EXPECT_EQ(advanced_callback_counter, 5);
  925. // With TASK_INTERVAL, the schedule should adjust to honor 100ms interval from end to start
  926. // Each execution: 105ms callback vs 100ms interval = 105ms total cycle
  927. // 5 executions should take approximately 5 * 105ms = ~525ms
  928. unsigned long total_time = millis() - test_start;
  929. EXPECT_GE(total_time, 500); // At least 500ms
  930. EXPECT_LE(total_time, 600); // At most 600ms (allowing for timing variance)
  931. // Verify the output shows proper timing intervals
  932. EXPECT_EQ(getAdvancedTestOutputCount(), 10); // 5 start + 5 end messages
  933. }
  934. // ================== SELF-DESTRUCT FUNCTIONALITY TESTS ==================
  935. /**
  936. * @brief Test task self-destruct functionality (placeholder test)
  937. *
  938. * TESTS: Task self-destruct behavior when enabled
  939. *
  940. * PURPOSE: Verify that tasks can be configured to automatically remove
  941. * themselves from the scheduler after completion, enabling automatic
  942. * resource cleanup and dynamic task lifecycle management.
  943. *
  944. * SELF-DESTRUCT BEHAVIOR:
  945. * - Tasks automatically remove themselves from scheduler
  946. * - Occurs after task completes execution cycle
  947. * - Prevents memory leaks in dynamic task scenarios
  948. * - Enables automatic cleanup patterns
  949. * - Critical for long-running applications with temporary tasks
  950. *
  951. * NOTE: This test serves as a placeholder for self-destruct functionality.
  952. * The actual implementation details depend on specific TaskScheduler
  953. * version and may require additional setup or different API calls.
  954. *
  955. * TEST SCENARIO:
  956. * 1. Create task configured for self-destruction
  957. * 2. Let task execute its lifecycle
  958. * 3. Verify task removes itself from scheduler
  959. * 4. Confirm no further executions occur
  960. * 5. Test scheduler continues operating normally
  961. *
  962. * EXPECTATIONS:
  963. * - Task executes normally initially
  964. * - Task removes itself after completion
  965. * - No further executions occur
  966. * - Scheduler remains functional
  967. *
  968. * IMPORTANCE: Self-destruct functionality enables automatic resource
  969. * management essential for dynamic applications and prevents memory
  970. * leaks in long-running systems with temporary tasks.
  971. */
  972. TEST_F(AdvancedSchedulerTest, TaskSelfDestruct) {
  973. Scheduler ts;
  974. // Create a task that will self-destruct after execution
  975. // Note: Actual self-destruct implementation may vary by TaskScheduler version
  976. Task* temp_task = new Task(100, 1, &self_destruct_callback, &ts, true);
  977. // Let task execute
  978. bool success = runAdvancedSchedulerUntil(ts, []() {
  979. return task_self_destructed;
  980. });
  981. EXPECT_TRUE(success);
  982. EXPECT_EQ(getAdvancedTestOutput(0), "self_destruct_executed");
  983. // Note: In a full implementation, we would verify the task
  984. // has been removed from the scheduler's task list
  985. // This would require access to internal scheduler state
  986. // Clean up manually for this test
  987. delete temp_task;
  988. }
  989. // ================== INTEGRATION AND COMPLEX SCENARIOS ==================
  990. /**
  991. * @brief Integration test combining status requests with timeouts
  992. *
  993. * TESTS: StatusRequest + Task timeout integration
  994. *
  995. * PURPOSE: Verify that status request coordination works correctly
  996. * with task timeouts, ensuring robust behavior when events may
  997. * not occur within expected timeframes.
  998. *
  999. * INTEGRATION BEHAVIOR:
  1000. * - Tasks can wait for StatusRequest with timeout protection
  1001. * - Timeout overrides StatusRequest waiting if deadline exceeded
  1002. * - Proper cleanup occurs when timeout prevents event completion
  1003. * - Enables robust event-driven patterns with deadline guarantees
  1004. * - Critical for reliable real-time coordination
  1005. *
  1006. * TEST SCENARIO:
  1007. * 1. Create StatusRequest that won't complete within timeout
  1008. * 2. Create task waiting for StatusRequest with timeout
  1009. * 3. Verify task times out rather than waiting indefinitely
  1010. * 4. Test proper cleanup and status handling
  1011. * 5. Verify system remains stable after timeout
  1012. *
  1013. * EXPECTATIONS:
  1014. * - Task times out rather than waiting indefinitely
  1015. * - Timeout handling works despite pending StatusRequest
  1016. * - System cleanup occurs properly
  1017. * - No resource leaks or deadlocks
  1018. *
  1019. * IMPORTANCE: Timeout protection in event-driven scenarios prevents
  1020. * deadlocks and ensures system reliability, essential for robust
  1021. * real-time applications.
  1022. */
  1023. TEST_F(AdvancedSchedulerTest, StatusRequestWithTimeout) {
  1024. Scheduler ts;
  1025. StatusRequest sr;
  1026. // Set up StatusRequest that won't complete
  1027. sr.setWaiting(1);
  1028. sr.setTimeout(150);
  1029. sr.resetTimeout();
  1030. // Create task waiting for StatusRequest
  1031. Task waiter(100, 1, &consumer_callback, &ts);
  1032. waiter.waitFor(&sr);
  1033. waiter.setTimeout(200, true); // Task timeout longer than SR timeout
  1034. // Let everything run - StatusRequest should timeout first
  1035. delay(300);
  1036. // Run scheduler to process timeouts
  1037. for (int i = 0; i < 10; i++) {
  1038. ts.execute();
  1039. delay(10);
  1040. }
  1041. // Verify StatusRequest timed out
  1042. EXPECT_LE(sr.untilTimeout(), 0); // Should be negative (timed out)
  1043. // Task should eventually time out as well since SR never completed
  1044. EXPECT_TRUE(waiter.timedOut() || !waiter.isEnabled());
  1045. }
  1046. /**
  1047. * @brief Complex producer-consumer coordination with multiple features
  1048. *
  1049. * TESTS: Multi-feature integration in realistic scenario
  1050. *
  1051. * PURPOSE: Demonstrate complex coordination scenario using multiple
  1052. * advanced features together, validating that features work correctly
  1053. * in combination for real-world usage patterns.
  1054. *
  1055. * COMPLEX INTEGRATION FEATURES:
  1056. * - Producer task with timeout management
  1057. * - Multiple consumers waiting for producer completion
  1058. * - StatusRequest coordination with error handling
  1059. * - Scheduling options for priority control
  1060. * - Comprehensive error and timeout handling
  1061. *
  1062. * TEST SCENARIO:
  1063. * 1. Create producer task with timeout and high priority
  1064. * 2. Create multiple consumer tasks waiting for producer
  1065. * 3. Configure timeouts and scheduling options appropriately
  1066. * 4. Execute coordination scenario with success path
  1067. * 5. Verify all consumers execute after producer completion
  1068. *
  1069. * EXPECTATIONS:
  1070. * - Producer executes with proper priority and timing
  1071. * - All consumers wait appropriately for producer
  1072. * - StatusRequest coordination works correctly
  1073. * - All tasks execute in expected order
  1074. * - No timeouts or errors in success scenario
  1075. *
  1076. * IMPORTANCE: Complex integration validates that advanced features
  1077. * work together reliably, essential for building sophisticated
  1078. * multi-task applications with robust coordination patterns.
  1079. */
  1080. TEST_F(AdvancedSchedulerTest, ComplexProducerConsumerCoordination) {
  1081. Scheduler ts;
  1082. StatusRequest production_complete;
  1083. // Set up production status request
  1084. production_complete.setWaiting(1);
  1085. production_complete.setTimeout(1000); // Allow plenty of time
  1086. production_complete.resetTimeout();
  1087. // Set global pointer for producer callback
  1088. global_status_request = &production_complete;
  1089. // Create producer task with high priority
  1090. Task producer(150, 1, &producer_callback, &ts, true);
  1091. producer.setTimeout(500, true);
  1092. producer.setSchedulingOption(10); // High priority
  1093. // Create multiple consumer tasks
  1094. Task consumer1(100, 1, &consumer1_callback, &ts);
  1095. Task consumer2(100, 1, &consumer2_callback, &ts);
  1096. Task consumer3(100, 1, &consumer3_callback, &ts);
  1097. // Configure consumers to wait for production
  1098. consumer1.waitFor(&production_complete);
  1099. consumer1.setTimeout(800, true);
  1100. consumer2.waitFor(&production_complete);
  1101. consumer2.setTimeout(800, true);
  1102. consumer3.waitFor(&production_complete);
  1103. consumer3.setTimeout(800, true);
  1104. // Execute the coordination scenario
  1105. bool success = runAdvancedSchedulerUntil(ts, []() {
  1106. return advanced_callback_counter >= 4; // Producer + 3 consumers
  1107. }, 1500);
  1108. EXPECT_TRUE(success);
  1109. EXPECT_EQ(advanced_callback_counter, 4);
  1110. // Verify execution order - producer should be first
  1111. EXPECT_EQ(getAdvancedTestOutput(0), "producer_completed");
  1112. // Verify StatusRequest completed successfully
  1113. EXPECT_TRUE(production_complete.completed());
  1114. EXPECT_EQ(production_complete.getStatus(), 100);
  1115. // Verify no timeouts occurred
  1116. EXPECT_FALSE(producer.timedOut());
  1117. EXPECT_FALSE(consumer1.timedOut());
  1118. EXPECT_FALSE(consumer2.timedOut());
  1119. EXPECT_FALSE(consumer3.timedOut());
  1120. // Clean up global pointer
  1121. global_status_request = nullptr;
  1122. }
  1123. /**
  1124. * @brief Producer-consumer scenario with yield switching
  1125. *
  1126. * TESTS: StatusRequest coordination with callback switching
  1127. *
  1128. * PURPOSE: Test complex scenario where tasks change behavior based
  1129. * on StatusRequest completion, demonstrating state machine patterns
  1130. * with event-driven coordination.
  1131. */
  1132. TEST_F(AdvancedSchedulerTest, ProducerConsumerWithYieldSwitching) {
  1133. Scheduler ts;
  1134. StatusRequest sr;
  1135. sr.setWaiting(1);
  1136. global_status_request = &sr;
  1137. // Create producer that will signal completion
  1138. Task producer(100, 1, &producer_callback, &ts, true);
  1139. // Create consumer that will yield to different callback after SR completion
  1140. Task consumer(100, 2, consumer_yield_callback, &ts);
  1141. global_advanced_yield_task = &consumer;
  1142. consumer.waitFor(&sr);
  1143. // Run the scenario
  1144. bool success = runAdvancedSchedulerUntil(ts, []() {
  1145. return advanced_test_output.size() >= 3; // producer + consumer initial + consumer yielded
  1146. }, 1000);
  1147. EXPECT_TRUE(success);
  1148. EXPECT_EQ(getAdvancedTestOutput(0), "producer_completed");
  1149. EXPECT_EQ(getAdvancedTestOutput(1), "consumer_initial");
  1150. EXPECT_EQ(getAdvancedTestOutput(2), "step_2");
  1151. // Clean up
  1152. global_status_request = nullptr;
  1153. global_advanced_yield_task = nullptr;
  1154. }
  1155. /**
  1156. * @brief Main test runner function for advanced features
  1157. *
  1158. * Initializes Google Test framework and runs all advanced feature tests.
  1159. * Called by the test execution environment to start testing process.
  1160. *
  1161. * @param argc Command line argument count
  1162. * @param argv Command line argument values
  1163. * @return Test execution status (0 = success)
  1164. */
  1165. int main(int argc, char **argv) {
  1166. ::testing::InitGoogleTest(&argc, argv);
  1167. return RUN_ALL_TESTS();
  1168. }