feat(scheduler-sim-discrete-clock): --sim-speed deprecation-warning helper and discrete-clock test binary (task 1.1)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
4b6872d053
commit
4f653d8fbe
6 changed files with 232 additions and 2 deletions
21
src/scheduler/include/cli_compat.h
Normal file
21
src/scheduler/include/cli_compat.h
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#if !defined(_CLI_COMPAT_H_)
|
||||
|
||||
#define _CLI_COMPAT_H_ 1
|
||||
|
||||
/*
|
||||
* cli_compat.h - command-line compatibility shims for retired xce_scheduler
|
||||
* options (scheduler-sim-discrete-clock spec, design.md, Components:
|
||||
* CliCompat).
|
||||
*/
|
||||
|
||||
/*
|
||||
* sched_cli_warn_deprecated_options - logs one WARN per deprecated option
|
||||
* that was given. sim_speed is the raw --sim-speed value as argp stored it
|
||||
* (the last occurrence), or NULL when the option was not given.
|
||||
*
|
||||
* Call once, after mylog_init(), before any mode-specific startup. Never
|
||||
* fails, never exits, never parses the value (Req 2.3, 2.4, 2.5).
|
||||
*/
|
||||
void sched_cli_warn_deprecated_options(const char* sim_speed);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
scheduler_srcs = [
|
||||
'src/main.c',
|
||||
'src/cli_compat.c',
|
||||
'src/handler.c',
|
||||
'src/scheduler.c',
|
||||
'src/sched_election.c',
|
||||
|
|
|
|||
24
src/scheduler/src/cli_compat.c
Normal file
24
src/scheduler/src/cli_compat.c
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* cli_compat.c - command-line compatibility shims for retired xce_scheduler
|
||||
* options (scheduler-sim-discrete-clock spec, design.md, Components:
|
||||
* CliCompat). One place to remove once the deprecated options are dropped.
|
||||
*/
|
||||
|
||||
#include "cli_compat.h"
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
void sched_cli_warn_deprecated_options(const char* sim_speed)
|
||||
{
|
||||
/* Req 2.5: option not given -> no warning. */
|
||||
if (sim_speed == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Req 2.3/2.4: one warning for any value, never parsed; quoted so an
|
||||
* empty value is visible as "". */
|
||||
WARN("xce_scheduler: --sim-speed \"%s\" is deprecated and has no effect "
|
||||
"(the simulator clock moves only at recorded timestamps); it will "
|
||||
"be removed in a future release",
|
||||
sim_speed);
|
||||
}
|
||||
|
|
@ -2333,3 +2333,23 @@ sched_alloc_from_stamp_test = executable(
|
|||
test('scheduler alloc from stamp test',
|
||||
sched_alloc_from_stamp_test, suite: 'scheduler',
|
||||
env: ['ASAN_OPTIONS=detect_leaks=0'])
|
||||
|
||||
# scheduler-sim-discrete-clock spec (task 1.1, Req 2.3-2.5): unit tests for
|
||||
# the --sim-speed deprecation warning (../src/cli_compat.c), and -- in later
|
||||
# tasks -- the discrete-clock and end-to-end command-line tests. Sources are
|
||||
# the test file and cli_compat.c ONLY: the white-box sim #includes live in
|
||||
# the test file itself (listing sim sources here too would define every
|
||||
# symbol twice). XCE_SCHEDULER_BIN points the end-to-end tests at the built
|
||||
# xce_scheduler, which `depends: scheduler` guarantees is built first.
|
||||
sched_sim_discrete_clock_test = executable(
|
||||
'sched_sim_discrete_clock_test',
|
||||
['test_sim_discrete_clock.c', '../src/cli_compat.c'],
|
||||
include_directories:[incdir],
|
||||
dependencies: [scheduler_test_deps, libedit_dep],
|
||||
c_args: ['-DXCE_SCHEDULER_BIN="' + scheduler.full_path() + '"'],
|
||||
install: false)
|
||||
|
||||
test('scheduler sim discrete clock test',
|
||||
sched_sim_discrete_clock_test, suite: 'scheduler',
|
||||
env: ['ASAN_OPTIONS=detect_leaks=0'],
|
||||
depends: scheduler)
|
||||
|
|
|
|||
161
src/scheduler/testsuite/test_sim_discrete_clock.c
Normal file
161
src/scheduler/testsuite/test_sim_discrete_clock.c
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* test_sim_discrete_clock.c - tests for the scheduler-sim-discrete-clock
|
||||
* spec.
|
||||
*
|
||||
* Task 1.1 (Requirements 2.3, 2.4, 2.5; design.md, Components: CliCompat,
|
||||
* Testing Strategy: Unit (CliCompat)): sched_cli_warn_deprecated_options()
|
||||
* logs exactly one warning naming the quoted --sim-speed value, stating it
|
||||
* is deprecated, has no effect and will be removed, for ANY value (numeric,
|
||||
* non-numeric, negative, empty), and logs nothing when the option was not
|
||||
* given (NULL).
|
||||
*
|
||||
* This binary deliberately never calls mylog_init(): without it, tlog's
|
||||
* early-print path writes WARN lines to stdout, which the test-local
|
||||
* capture_stdout_around() below captures.
|
||||
*
|
||||
* XCE_SCHEDULER_BIN (compile-time, from the scheduler executable's
|
||||
* full_path() in testsuite/meson.build) is used by the end-to-end tests
|
||||
* later tasks add to this file.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <unity/unity.h>
|
||||
|
||||
#include "cli_compat.h"
|
||||
|
||||
#if !defined(XCE_SCHEDULER_BIN)
|
||||
#error "XCE_SCHEDULER_BIN must be defined by testsuite/meson.build"
|
||||
#endif
|
||||
|
||||
void setUp(void) { return; }
|
||||
void tearDown(void) { return; }
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Fixture helpers -- test-local copy of the dup()/dup2() stdout capture */
|
||||
/* used by test_repl_help.c (each test file carries its own copy). */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
static const char* g_warn_value;
|
||||
|
||||
static void call_warn_helper(void)
|
||||
{
|
||||
sched_cli_warn_deprecated_options(g_warn_value);
|
||||
}
|
||||
|
||||
static char* capture_stdout_around(void (*fn)(void))
|
||||
{
|
||||
char tmp[] = "/tmp/xce_simclock_stdoutcap_XXXXXX";
|
||||
int fd = mkstemp(tmp);
|
||||
int saved_stdout;
|
||||
off_t len;
|
||||
char* buf;
|
||||
|
||||
TEST_ASSERT_TRUE_MESSAGE(fd >= 0, "mkstemp for stdout capture must "
|
||||
"succeed");
|
||||
|
||||
fflush(stdout);
|
||||
saved_stdout = dup(STDOUT_FILENO);
|
||||
TEST_ASSERT_TRUE_MESSAGE(saved_stdout >= 0, "dup(STDOUT_FILENO) must "
|
||||
"succeed");
|
||||
TEST_ASSERT_TRUE_MESSAGE(dup2(fd, STDOUT_FILENO) >= 0,
|
||||
"dup2 redirect of STDOUT_FILENO must succeed");
|
||||
|
||||
fn();
|
||||
|
||||
fflush(stdout);
|
||||
dup2(saved_stdout, STDOUT_FILENO);
|
||||
close(saved_stdout);
|
||||
|
||||
len = lseek(fd, 0, SEEK_CUR);
|
||||
TEST_ASSERT_TRUE(len >= 0);
|
||||
|
||||
buf = (char*)calloc(1, (size_t)len + 1);
|
||||
TEST_ASSERT_NOT_NULL(buf);
|
||||
if (len > 0) {
|
||||
TEST_ASSERT_EQUAL_INT64((int64_t)len, (int64_t)pread(fd, buf,
|
||||
(size_t)len, 0));
|
||||
}
|
||||
close(fd);
|
||||
unlink(tmp);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static int count_lines(const char* s)
|
||||
{
|
||||
int n = 0;
|
||||
|
||||
for (; *s != '\0'; s++) {
|
||||
if (*s == '\n') {
|
||||
n++;
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/* Asserts the captured output is exactly one line naming the quoted value
|
||||
* and carrying every required phrase. */
|
||||
static void assert_one_warning_for(const char* value)
|
||||
{
|
||||
char* out;
|
||||
char quoted[64];
|
||||
|
||||
g_warn_value = value;
|
||||
out = capture_stdout_around(call_warn_helper);
|
||||
|
||||
snprintf(quoted, sizeof(quoted), "\"%s\"", value);
|
||||
|
||||
TEST_ASSERT_EQUAL_INT_MESSAGE(1, count_lines(out),
|
||||
"exactly one warning line expected");
|
||||
TEST_ASSERT_NOT_NULL_MESSAGE(strstr(out, quoted),
|
||||
"warning must name the quoted value");
|
||||
TEST_ASSERT_NOT_NULL_MESSAGE(strstr(out, "--sim-speed"),
|
||||
"warning must name --sim-speed");
|
||||
TEST_ASSERT_NOT_NULL_MESSAGE(strstr(out, "deprecated"),
|
||||
"warning must say deprecated");
|
||||
TEST_ASSERT_NOT_NULL_MESSAGE(strstr(out, "no effect"),
|
||||
"warning must say no effect");
|
||||
TEST_ASSERT_NOT_NULL_MESSAGE(strstr(out, "will be removed"),
|
||||
"warning must say will be removed");
|
||||
free(out);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* CliCompat (Requirements 2.3, 2.4, 2.5) */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
static void test_warn_numeric_zero_value(void) { assert_one_warning_for("0"); }
|
||||
|
||||
static void test_warn_non_numeric_value(void) { assert_one_warning_for("abc"); }
|
||||
|
||||
static void test_warn_negative_value(void) { assert_one_warning_for("-1"); }
|
||||
|
||||
static void test_warn_empty_value(void) { assert_one_warning_for(""); }
|
||||
|
||||
static void test_no_warning_when_option_absent(void)
|
||||
{
|
||||
char* out;
|
||||
|
||||
g_warn_value = NULL;
|
||||
out = capture_stdout_around(call_warn_helper);
|
||||
TEST_ASSERT_EQUAL_STRING_MESSAGE("", out,
|
||||
"NULL (option not given) must log "
|
||||
"nothing");
|
||||
free(out);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
UNITY_BEGIN();
|
||||
RUN_TEST(test_warn_numeric_zero_value);
|
||||
RUN_TEST(test_warn_non_numeric_value);
|
||||
RUN_TEST(test_warn_negative_value);
|
||||
RUN_TEST(test_warn_empty_value);
|
||||
RUN_TEST(test_no_warning_when_option_absent);
|
||||
return UNITY_END();
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue