/* test_job_dispatch.c -- scheduler-dispatch-commit task 1.1 * * Unit tests for the Controller Dispatch-Failure Classification component * (design.md, "Controller Dispatch-Failure Classification"): a pure, static, * file-local function in job.c that maps each of dispatch_a_job_()'s six * post-lookup failure points (xce_dispatch_fail_site_t) to a retryable-vs- * terminal classification (xce_dispatch_fail_class_t), per Requirements * 4.1/4.2. * * xce_classify_dispatch_fail() and its enum types are deliberately NOT * declared in any header (design.md's own placement-correction note: nothing * outside job.c consumes them). This test file reaches the static function * through a thin, int-typed, XCE_TESTING-only wrapper exported from job.c * (xce_classify_dispatch_fail_test), the same pattern job.c already uses for * job_array_apply_test_set_force_fail_at()/friends -- and, like test_job_ * array_fence.c's ha_arm_promotion_fence_timer_for_test, the extern * declaration lives directly in this test file rather than in a shared * header. * * No cluster_t/persist/worker fixture is needed: the classification is a * pure decision with no side effects, independently testable against every * known failure case without a live dispatch attempt (task 1.1's own * Observable-completion clause). */ #include #include /* Mirrors design.md's Service Interface enum values exactly (job.c's own * xce_dispatch_fail_site_t/xce_dispatch_fail_class_t are file-local and not * shared via a header -- this test drives the wrapper by the same plain-int * values documented there, not by including a private type). */ #define SITE_WORKER_LOOKUP 0 #define SITE_WORKER_NULL 1 #define SITE_WORKER_NOT_READY 2 #define SITE_INVALID_ALLOC 3 #define SITE_QUEUE_EXEC 4 #define SITE_RPC_FAILURE 5 #define CLASS_RETRYABLE 0 #define CLASS_TERMINAL 1 extern int xce_classify_dispatch_fail_test(int site); static void test_worker_lookup_is_retryable(void) { TEST_ASSERT_EQUAL_INT(CLASS_RETRYABLE, xce_classify_dispatch_fail_test(SITE_WORKER_LOOKUP)); printf("test_worker_lookup_is_retryable: PASS\n"); } static void test_worker_null_is_retryable(void) { TEST_ASSERT_EQUAL_INT(CLASS_RETRYABLE, xce_classify_dispatch_fail_test(SITE_WORKER_NULL)); printf("test_worker_null_is_retryable: PASS\n"); } static void test_worker_not_ready_is_retryable(void) { TEST_ASSERT_EQUAL_INT(CLASS_RETRYABLE, xce_classify_dispatch_fail_test( SITE_WORKER_NOT_READY)); printf("test_worker_not_ready_is_retryable: PASS\n"); } static void test_rpc_failure_is_retryable(void) { TEST_ASSERT_EQUAL_INT(CLASS_RETRYABLE, xce_classify_dispatch_fail_test(SITE_RPC_FAILURE)); printf("test_rpc_failure_is_retryable: PASS\n"); } static void test_invalid_alloc_is_terminal(void) { TEST_ASSERT_EQUAL_INT(CLASS_TERMINAL, xce_classify_dispatch_fail_test(SITE_INVALID_ALLOC)); printf("test_invalid_alloc_is_terminal: PASS\n"); } static void test_queue_exec_is_terminal(void) { TEST_ASSERT_EQUAL_INT(CLASS_TERMINAL, xce_classify_dispatch_fail_test(SITE_QUEUE_EXEC)); printf("test_queue_exec_is_terminal: PASS\n"); } /* Invariant (design.md Service Interface Postconditions): the same site * always classifies the same way -- no hidden state, no time-dependence. */ static void test_classification_is_stable_across_repeated_calls(void) { int first = xce_classify_dispatch_fail_test(SITE_WORKER_NOT_READY); int second = xce_classify_dispatch_fail_test(SITE_WORKER_NOT_READY); int third = xce_classify_dispatch_fail_test(SITE_QUEUE_EXEC); int fourth = xce_classify_dispatch_fail_test(SITE_QUEUE_EXEC); TEST_ASSERT_EQUAL_INT(first, second); TEST_ASSERT_EQUAL_INT(third, fourth); printf("test_classification_is_stable_across_repeated_calls: PASS\n"); } void test_job_dispatch(void) { UnitySetTestFile(__FILE__); printf("\n>> dispatch-failure classification tests (Req 4.1, 4.2)\n\n"); RUN_TEST(test_worker_lookup_is_retryable); RUN_TEST(test_worker_null_is_retryable); RUN_TEST(test_worker_not_ready_is_retryable); RUN_TEST(test_rpc_failure_is_retryable); RUN_TEST(test_invalid_alloc_is_terminal); RUN_TEST(test_queue_exec_is_terminal); RUN_TEST(test_classification_is_stable_across_repeated_calls); }