1 1.1 christos /* $NetBSD: job_test.c,v 1.2 2025/01/26 16:25:49 christos Exp $ */ 2 1.1 christos 3 1.1 christos /* 4 1.1 christos * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 1.1 christos * 6 1.1 christos * SPDX-License-Identifier: MPL-2.0 7 1.1 christos * 8 1.1 christos * This Source Code Form is subject to the terms of the Mozilla Public 9 1.1 christos * License, v. 2.0. If a copy of the MPL was not distributed with this 10 1.1 christos * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 1.1 christos * 12 1.1 christos * See the COPYRIGHT file distributed with this work for additional 13 1.1 christos * information regarding copyright ownership. 14 1.1 christos */ 15 1.1 christos 16 1.1 christos #include <inttypes.h> 17 1.1 christos #include <sched.h> /* IWYU pragma: keep */ 18 1.1 christos #include <setjmp.h> 19 1.1 christos #include <stdarg.h> 20 1.1 christos #include <stddef.h> 21 1.1 christos #include <stdlib.h> 22 1.1 christos #include <string.h> 23 1.1 christos #include <sys/types.h> 24 1.1 christos #include <unistd.h> 25 1.1 christos 26 1.1 christos #define UNIT_TESTING 27 1.1 christos #include <cmocka.h> 28 1.1 christos 29 1.1 christos #include <isc/atomic.h> 30 1.1 christos #include <isc/job.h> 31 1.1 christos #include <isc/loop.h> 32 1.1 christos #include <isc/os.h> 33 1.1 christos #include <isc/result.h> 34 1.1 christos #include <isc/util.h> 35 1.1 christos 36 1.1 christos #include <tests/isc.h> 37 1.1 christos 38 1.1 christos static atomic_uint scheduled; 39 1.1 christos static atomic_uint executed; 40 1.1 christos 41 1.1 christos #define MAX_EXECUTED 1000000 42 1.1 christos 43 1.1 christos struct test_arg { 44 1.1 christos isc_job_t job; 45 1.1 christos union { 46 1.1 christos int n; 47 1.1 christos void *ptr; 48 1.1 christos } arg; 49 1.1 christos }; 50 1.1 christos 51 1.1 christos static void 52 1.1 christos shutdown_cb(void *arg) { 53 1.1 christos struct test_arg *ta = arg; 54 1.1 christos 55 1.1 christos isc_mem_put(mctx, ta, sizeof(*ta)); 56 1.1 christos 57 1.1 christos isc_loopmgr_shutdown(loopmgr); 58 1.1 christos } 59 1.1 christos 60 1.1 christos static void 61 1.1 christos job_cb(void *arg) { 62 1.1 christos struct test_arg *ta = arg; 63 1.1 christos unsigned int n = atomic_fetch_add(&executed, 1); 64 1.1 christos 65 1.1 christos if (n <= MAX_EXECUTED) { 66 1.1 christos atomic_fetch_add(&scheduled, 1); 67 1.1 christos isc_job_run(isc_loop(), &ta->job, job_cb, ta); 68 1.1 christos } else { 69 1.1 christos isc_job_run(isc_loop(), &ta->job, shutdown_cb, ta); 70 1.1 christos } 71 1.1 christos } 72 1.1 christos 73 1.1 christos static void 74 1.1 christos job_run_cb(void *arg) { 75 1.1 christos struct test_arg *ta = arg; 76 1.1 christos atomic_fetch_add(&scheduled, 1); 77 1.1 christos 78 1.1 christos if (arg == NULL) { 79 1.1 christos ta = isc_mem_get(mctx, sizeof(*ta)); 80 1.1 christos *ta = (struct test_arg){ .job = ISC_JOB_INITIALIZER }; 81 1.1 christos } 82 1.1 christos 83 1.1 christos isc_job_run(isc_loop(), &ta->job, job_cb, ta); 84 1.1 christos } 85 1.1 christos 86 1.1 christos ISC_RUN_TEST_IMPL(isc_job_run) { 87 1.1 christos atomic_init(&scheduled, 0); 88 1.1 christos atomic_init(&executed, 0); 89 1.1 christos 90 1.1 christos isc_loopmgr_setup(loopmgr, job_run_cb, NULL); 91 1.1 christos 92 1.1 christos isc_loopmgr_run(loopmgr); 93 1.1 christos 94 1.1 christos assert_int_equal(atomic_load(&scheduled), atomic_load(&executed)); 95 1.1 christos } 96 1.1 christos 97 1.1 christos static char string[32] = ""; 98 1.1 christos struct test_arg n1 = { .job = ISC_JOB_INITIALIZER, .arg.n = 1 }; 99 1.1 christos struct test_arg n2 = { .job = ISC_JOB_INITIALIZER, .arg.n = 2 }; 100 1.1 christos struct test_arg n3 = { .job = ISC_JOB_INITIALIZER, .arg.n = 3 }; 101 1.1 christos struct test_arg n4 = { .job = ISC_JOB_INITIALIZER, .arg.n = 4 }; 102 1.1 christos struct test_arg n5 = { .job = ISC_JOB_INITIALIZER, .arg.n = 5 }; 103 1.1 christos 104 1.1 christos static void 105 1.1 christos append(void *arg) { 106 1.1 christos struct test_arg *ta = arg; 107 1.1 christos 108 1.1 christos char value[32]; 109 1.1 christos sprintf(value, "%d", ta->arg.n); 110 1.1 christos strlcat(string, value, 10); 111 1.1 christos } 112 1.1 christos 113 1.1 christos static void 114 1.1 christos job_multiple(void *arg) { 115 1.1 christos UNUSED(arg); 116 1.1 christos 117 1.1 christos /* These will be processed in normal order */ 118 1.1 christos isc_job_run(mainloop, &n1.job, append, &n1); 119 1.1 christos isc_job_run(mainloop, &n2.job, append, &n2); 120 1.1 christos isc_job_run(mainloop, &n3.job, append, &n3); 121 1.1 christos isc_job_run(mainloop, &n4.job, append, &n4); 122 1.1 christos isc_job_run(mainloop, &n5.job, append, &n5); 123 1.1 christos isc_loopmgr_shutdown(loopmgr); 124 1.1 christos } 125 1.1 christos 126 1.1 christos ISC_RUN_TEST_IMPL(isc_job_multiple) { 127 1.1 christos string[0] = '\0'; 128 1.1 christos isc_loop_setup(isc_loop_main(loopmgr), job_multiple, loopmgr); 129 1.1 christos isc_loopmgr_run(loopmgr); 130 1.1 christos assert_string_equal(string, "12345"); 131 1.1 christos } 132 1.1 christos 133 1.1 christos ISC_TEST_LIST_START 134 1.1 christos ISC_TEST_ENTRY_CUSTOM(isc_job_run, setup_loopmgr, teardown_loopmgr) 135 1.1 christos ISC_TEST_ENTRY_CUSTOM(isc_job_multiple, setup_loopmgr, teardown_loopmgr) 136 1.1 christos ISC_TEST_LIST_END 137 1.1 christos 138 1.1 christos ISC_TEST_MAIN 139