test-scheduler-advanced-features-no-lambda.cpp 43 KB

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