test(controller): cover live dispatch's apiserver notification (bug-1679)
New test_dc_success_notifies_job_update_hook_exactly_once (test_dispatch_commit.c): a spy hook counting HOOK_AFTER_EVENT/ HOOK_DETAIL_JOB_UPDATE fires specifically -- the exact hook apiserver_job_update_fun subscribes to in production. Asserts exactly one fire per successful live dispatch. Independently reproduced RED->GREEN: disabled the new notify call with the test kept, rebuilt, confirmed FAIL (Expected 1 Was 0); restored, rebuilt, confirmed PASS. Also independently confirmed no double-WAL-append regression via two existing tests whose fixtures genuinely wire persist.cluster with persist_job_hook_fun registered: test_jobdispatch_receipt_ack_no_wal_append (asserts exactly one WAL entry for a successful dispatch) and test_handle_jobdispatch_matches_dispatch_a_job_notify_count -- both pass unchanged. Full controller_unit_test: 1137/1137 (2 pre-existing test_config_repl.c failures, confirmed identical on stock code via git-stash -- the known overlayfs fdatasync errno=5 flake, bug-1561). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AgYRU3zDTqNGV5Jk8aiKLg
This commit is contained in:
parent
da7813bfdb
commit
8d6f610ef9
1 changed files with 66 additions and 0 deletions
|
|
@ -274,6 +274,71 @@ static void test_dc_success_commits_alloc_state_and_resets_counter(void)
|
|||
printf("test_dc_success_commits_alloc_state_and_resets_counter: PASS\n");
|
||||
}
|
||||
|
||||
/* bug-1679: spy hook counting HOOK_AFTER_EVENT/HOOK_DETAIL_JOB_UPDATE fires
|
||||
* specifically -- the exact hook apiserver_job_update_fun (apiserver.c)
|
||||
* subscribes to in production to push a job's current state to every
|
||||
* connected apiserver. Mirrors test_apply_committed_entry.c's tace_spy_hook
|
||||
* pattern, filtered to this one detail rather than every AFTER_EVENT. */
|
||||
static int g_dc_update_hook_fires;
|
||||
|
||||
static int dc_job_update_spy_hook(int type, int situation, int detail,
|
||||
void* data, va_list ap)
|
||||
{
|
||||
(void)type; (void)data; (void)ap;
|
||||
if (situation == HOOK_AFTER_EVENT && detail == HOOK_DETAIL_JOB_UPDATE)
|
||||
g_dc_update_hook_fires++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define DC_JOBID_NOTIFY 91004ULL
|
||||
|
||||
/* THE core proof for bug-1679 (Req: a live successful dispatch must notify
|
||||
* the apiserver, restart or not): dispatch_a_job_()'s success path fires
|
||||
* HOOK_DETAIL_JOB_UPDATE's AFTER_EVENT exactly once, synchronously, in the
|
||||
* SAME operation that commits state+allocs -- unlike before this fix, where
|
||||
* dispatch_a_job_() fired no hooks at all and relied entirely on
|
||||
* apply_committed_entry()'s later (here, always-suppressed-by-duplicate-
|
||||
* state) notify. RED before the fix: g_dc_update_hook_fires stays 0. */
|
||||
static void test_dc_success_notifies_job_update_hook_exactly_once(void)
|
||||
{
|
||||
job_t* j;
|
||||
xce_job_alloc_t* alloc;
|
||||
int rc;
|
||||
|
||||
dc_setup();
|
||||
g_dc_update_hook_fires = 0;
|
||||
TEST_ASSERT_EQUAL_INT(0,
|
||||
xce_add_hook(&g_dc.hooksys, XCE_CONTROLLER_HOOK_JOB,
|
||||
dc_job_update_spy_hook, NULL));
|
||||
|
||||
j = dc_seed_ready(DC_JOBID_NOTIFY, 0, "dq", "wkr-dc-notify");
|
||||
|
||||
alloc = make_job_alloc(DC_JOBID_NOTIFY, 1,
|
||||
make_host_allocs(1,
|
||||
make_host_alloc((char*)"wkr-dc-notify", 1,
|
||||
make_allocs(1,
|
||||
make_alloc((char*)"slots", NULL, 0, 1.0f, 0)))));
|
||||
TEST_ASSERT_NOT_NULL(alloc);
|
||||
|
||||
rc = dispatch_a_job_test(&g_dc, NULL, alloc);
|
||||
TEST_ASSERT_TRUE(rc >= 0);
|
||||
TEST_ASSERT_EQUAL_UINT32(JOB_STAT_RUN, j->job.state);
|
||||
|
||||
TEST_ASSERT_EQUAL_INT_MESSAGE(1, g_dc_update_hook_fires,
|
||||
"a live successful dispatch must fire HOOK_DETAIL_JOB_UPDATE's "
|
||||
"AFTER_EVENT exactly once (bug-1679) -- apiserver_job_update_fun's "
|
||||
"subscription is the ONLY mechanism that pushes the job's new "
|
||||
"RUN state and allocation to the apiserver; without this fire the "
|
||||
"job is stuck at PEND from the apiserver's perspective forever");
|
||||
|
||||
free_JobAlloc_ptr(&alloc);
|
||||
dc_drain_ep(&g_dc_worker_ep);
|
||||
xce_disable_hook(&g_dc.hooksys, XCE_CONTROLLER_HOOK_JOB,
|
||||
dc_job_update_spy_hook);
|
||||
dc_teardown();
|
||||
printf("test_dc_success_notifies_job_update_hook_exactly_once: PASS\n");
|
||||
}
|
||||
|
||||
#define DC_JOBID_NOTFOUND 91002ULL
|
||||
|
||||
/* Regression safety net (untouched failure branch): a dispatch whose
|
||||
|
|
@ -666,6 +731,7 @@ void test_dispatch_commit(void)
|
|||
"5.1)\n\n");
|
||||
|
||||
RUN_TEST(test_dc_success_commits_alloc_state_and_resets_counter);
|
||||
RUN_TEST(test_dc_success_notifies_job_update_hook_exactly_once);
|
||||
RUN_TEST(test_dc_worker_not_found_leaves_job_pend_and_alloc_uncommitted);
|
||||
RUN_TEST(test_dc_success_appends_wal_job_dispatch_durably);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue