Files
Martin Vogel f6e3af4325 feat(diagnostics): make superlinear passes visible from an ordinary run
Finding the 0.10.x indexing regression took an 11-corpus A/B across two
release binaries, a subset-scaling series, and a per-pass exponent fit.
None of that should have been necessary: the pass that carried it,
cross-file LSP, was already timed and already logged its def count. The
numbers were there, just never normalised into something a reader could
judge.

Three additions, all shipped without a flag except the detailed curve:

- parallel.resolve.cross_lsp_cost — cross-LSP cost NORMALISED per file,
  next to defs_total. Wall time cannot separate "big repo" from
  "superlinear pass"; us_per_file can. Measured on one Java tree:

      files=3710   defs=102845  us_per_file=35129   us_per_file_per_kdef=341
      files=14833  defs=339866  us_per_file=106722  us_per_file_per_kdef=314

  Per-file cost tripled while per-kdef stayed flat — the fingerprint of
  work proportional to the whole corpus (files x defs). One grep on two
  differently sized repos now answers what previously took a two-binary
  bench.

- parallel.resolve.scan_cost — candidates visited per tail-match lookup,
  plus fallback_rows, which the code has counted since #1085 but exposed
  only to a test. On the same tree the tail scan reached 242M candidate
  visits (n^2.04), worth seeing even though it proved cheap in wall time.

- cbm_scale_probe (foundation/profile.h) — samples cumulative elapsed at
  1/8, 1/4, 1/2 and 1 of a pass's items and fits k in T ~ n^k, warning
  once k reaches 1.35 in shipped builds. Wired into parallel_extract and
  parallel_resolve.

The probe's limits are documented rather than oversold: it catches growth
WITHIN a run, and would NOT have caught this bug, whose per-item cost is
constant-but-large within any single run (it reported 1.26 while the
cross-corpus exponent was 1.86). That is exactly why us_per_item and
us_per_file are emitted alongside it.

Tests are deterministic by construction: the exponent fit is a pure
function fed synthetic points, and the checkpoint bookkeeping is asserted
directly. A test that proved the detector by generating a real quadratic
workload would be asserting on the scheduler.

No product behaviour changes; diagnostics only.

Refs #1669.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-08-16 13:12:25 +02:00

669 lines
25 KiB
C

/*
* test_diagnostics.c — Security and lifecycle guards for the optional
* periodic diagnostics writer.
*/
#include "test_framework.h"
#include "../src/foundation/compat.h"
#include "../src/foundation/compat_fs.h"
#include "../src/foundation/diagnostics.h"
#include "../src/foundation/log.h"
#include "../src/foundation/platform.h"
#include "../src/foundation/profile.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef _WIN32
#include <windows.h>
#include <aclapi.h>
#include <process.h>
#define getpid _getpid
#else
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#endif
typedef struct {
char directory[1024];
char snapshot[1024];
char trajectory[1024];
} diagnostics_paths_t;
static void diagnostics_wait_ms(unsigned int milliseconds) {
struct timespec delay = {
.tv_sec = (time_t)(milliseconds / 1000U),
.tv_nsec = (long)((milliseconds % 1000U) * 1000000U),
};
(void)cbm_nanosleep(&delay, NULL);
}
#ifndef _WIN32
static bool diagnostics_file_equals(const char *path, const char *expected) {
char contents[128] = "";
FILE *file = cbm_fopen(path, "rb");
if (!file) {
return false;
}
size_t length = fread(contents, 1, sizeof(contents) - 1, file);
bool closed = fclose(file) == 0;
contents[length] = '\0';
return closed && strcmp(contents, expected) == 0;
}
#endif
static bool diagnostics_capture_paths(diagnostics_paths_t *paths) {
return cbm_diag_test_copy_paths(paths->directory, sizeof(paths->directory), paths->snapshot,
sizeof(paths->snapshot), paths->trajectory,
sizeof(paths->trajectory));
}
static bool diagnostics_wait_for_file(const char *path, unsigned int timeout_ms) {
uint64_t deadline = cbm_now_ms() + timeout_ms;
while (cbm_now_ms() < deadline) {
if (cbm_file_exists(path)) {
return true;
}
diagnostics_wait_ms(10);
}
return cbm_file_exists(path);
}
static char *diagnostics_read_file(const char *path) {
FILE *file = cbm_fopen(path, "rb");
if (!file || fseek(file, 0, SEEK_END) != 0) {
if (file) {
(void)fclose(file);
}
return NULL;
}
long length = ftell(file);
if (length < 0 || fseek(file, 0, SEEK_SET) != 0) {
(void)fclose(file);
return NULL;
}
char *contents = malloc((size_t)length + 1);
if (!contents) {
(void)fclose(file);
return NULL;
}
size_t read_length = fread(contents, 1, (size_t)length, file);
bool closed = fclose(file) == 0;
bool complete = read_length == (size_t)length && closed;
contents[read_length] = '\0';
if (!complete) {
free(contents);
return NULL;
}
return contents;
}
static void diagnostics_cleanup_outputs(const diagnostics_paths_t *paths) {
char temporary[1100];
char rotated[1100];
if (snprintf(temporary, sizeof(temporary), "%s.tmp", paths->snapshot) > 0) {
(void)cbm_unlink(temporary);
}
if (snprintf(rotated, sizeof(rotated), "%s.1", paths->trajectory) > 0) {
(void)cbm_unlink(rotated);
}
(void)cbm_unlink(paths->snapshot);
(void)cbm_unlink(paths->trajectory);
(void)cbm_rmdir(paths->directory);
}
#ifndef _WIN32
TEST(diagnostics_rejects_predictable_tmp_symlinks) {
char snapshot_link[256];
char trajectory_link[256];
char snapshot_target[256];
char trajectory_target[256];
const char *snapshot_seed = "snapshot sentinel\n";
const char *trajectory_seed = "trajectory sentinel\n";
int pid = (int)getpid();
ASSERT_LT(
snprintf(snapshot_link, sizeof(snapshot_link), "/tmp/cbm-diagnostics-%d.json.tmp", pid),
(int)sizeof(snapshot_link));
ASSERT_LT(
snprintf(trajectory_link, sizeof(trajectory_link), "/tmp/cbm-diagnostics-%d.ndjson", pid),
(int)sizeof(trajectory_link));
ASSERT_LT(snprintf(snapshot_target, sizeof(snapshot_target),
"/tmp/cbm-diagnostics-snapshot-sentinel-%d", pid),
(int)sizeof(snapshot_target));
ASSERT_LT(snprintf(trajectory_target, sizeof(trajectory_target),
"/tmp/cbm-diagnostics-trajectory-sentinel-%d", pid),
(int)sizeof(trajectory_target));
(void)cbm_unlink(snapshot_link);
(void)cbm_unlink(trajectory_link);
(void)cbm_unlink(snapshot_target);
(void)cbm_unlink(trajectory_target);
FILE *snapshot = cbm_fopen(snapshot_target, "wb");
ASSERT_NOT_NULL(snapshot);
ASSERT_GTE(fputs(snapshot_seed, snapshot), 0);
ASSERT_EQ(fclose(snapshot), 0);
FILE *trajectory = cbm_fopen(trajectory_target, "wb");
ASSERT_NOT_NULL(trajectory);
ASSERT_GTE(fputs(trajectory_seed, trajectory), 0);
ASSERT_EQ(fclose(trajectory), 0);
ASSERT_EQ(symlink(snapshot_target, snapshot_link), 0);
ASSERT_EQ(symlink(trajectory_target, trajectory_link), 0);
ASSERT_EQ(cbm_setenv("CBM_DIAGNOSTICS", "1", 1), 0);
ASSERT_TRUE(cbm_diag_start());
diagnostics_paths_t outputs;
bool captured = diagnostics_capture_paths(&outputs);
bool emitted = captured && diagnostics_wait_for_file(outputs.snapshot, 1000);
cbm_diag_stop();
ASSERT_EQ(cbm_unsetenv("CBM_DIAGNOSTICS"), 0);
bool snapshot_untouched = diagnostics_file_equals(snapshot_target, snapshot_seed);
bool trajectory_untouched = diagnostics_file_equals(trajectory_target, trajectory_seed);
(void)cbm_unlink(snapshot_link);
(void)cbm_unlink(trajectory_link);
(void)cbm_unlink(snapshot_target);
(void)cbm_unlink(trajectory_target);
if (captured) {
diagnostics_cleanup_outputs(&outputs);
}
ASSERT_TRUE(captured);
ASSERT_TRUE(emitted);
ASSERT_TRUE(snapshot_untouched);
ASSERT_TRUE(trajectory_untouched);
PASS();
}
#endif
TEST(diagnostics_stop_interrupts_periodic_wait) {
char legacy_snapshot[256];
char legacy_trajectory[256];
int pid = (int)getpid();
ASSERT_LT(snprintf(legacy_snapshot, sizeof(legacy_snapshot), "%s/cbm-diagnostics-%d.json",
cbm_tmpdir(), pid),
(int)sizeof(legacy_snapshot));
ASSERT_LT(snprintf(legacy_trajectory, sizeof(legacy_trajectory), "%s/cbm-diagnostics-%d.ndjson",
cbm_tmpdir(), pid),
(int)sizeof(legacy_trajectory));
(void)cbm_unlink(legacy_snapshot);
(void)cbm_unlink(legacy_trajectory);
ASSERT_EQ(cbm_setenv("CBM_DIAGNOSTICS", "1", 1), 0);
ASSERT_TRUE(cbm_diag_start());
diagnostics_paths_t outputs;
bool captured = diagnostics_capture_paths(&outputs);
/* A visible snapshot proves the writer has reached its periodic wait. */
bool emitted = captured && diagnostics_wait_for_file(outputs.snapshot, 1000);
uint64_t started_ms = cbm_now_ms();
cbm_diag_stop();
uint64_t elapsed_ms = cbm_now_ms() - started_ms;
ASSERT_EQ(cbm_unsetenv("CBM_DIAGNOSTICS"), 0);
(void)cbm_unlink(legacy_snapshot);
(void)cbm_unlink(legacy_trajectory);
if (captured) {
diagnostics_cleanup_outputs(&outputs);
}
ASSERT_TRUE(captured);
ASSERT_TRUE(emitted);
ASSERT_LT(elapsed_ms, UINT64_C(1000));
PASS();
}
#ifndef _WIN32
TEST(diagnostics_outputs_are_owner_private_regular_files) {
ASSERT_EQ(cbm_setenv("CBM_DIAGNOSTICS", "1", 1), 0);
ASSERT_TRUE(cbm_diag_start());
diagnostics_paths_t outputs;
bool captured = diagnostics_capture_paths(&outputs);
bool snapshot_emitted = captured && diagnostics_wait_for_file(outputs.snapshot, 1000);
bool trajectory_emitted = captured && diagnostics_wait_for_file(outputs.trajectory, 1000);
struct stat directory_state;
struct stat snapshot_state;
struct stat trajectory_state;
bool secure = captured && snapshot_emitted && trajectory_emitted &&
lstat(outputs.directory, &directory_state) == 0 &&
S_ISDIR(directory_state.st_mode) && directory_state.st_uid == geteuid() &&
(directory_state.st_mode & 07777) == 0700 &&
lstat(outputs.snapshot, &snapshot_state) == 0 &&
S_ISREG(snapshot_state.st_mode) && snapshot_state.st_uid == geteuid() &&
snapshot_state.st_nlink == 1 && (snapshot_state.st_mode & 07777) == 0600 &&
lstat(outputs.trajectory, &trajectory_state) == 0 &&
S_ISREG(trajectory_state.st_mode) && trajectory_state.st_uid == geteuid() &&
trajectory_state.st_nlink == 1 && (trajectory_state.st_mode & 07777) == 0600;
cbm_diag_stop();
ASSERT_EQ(cbm_unsetenv("CBM_DIAGNOSTICS"), 0);
if (captured) {
diagnostics_cleanup_outputs(&outputs);
}
ASSERT_TRUE(secure);
PASS();
}
#endif
TEST(diagnostics_stalled_writer_cannot_retain_shutdown) {
cbm_diag_test_hold_writer(true);
ASSERT_EQ(cbm_setenv("CBM_DIAGNOSTICS", "1", 1), 0);
if (!cbm_diag_start()) {
cbm_diag_test_hold_writer(false);
(void)cbm_unsetenv("CBM_DIAGNOSTICS");
FAIL("failed to start held diagnostics writer");
}
diagnostics_paths_t outputs;
bool captured = diagnostics_capture_paths(&outputs);
uint64_t reach_deadline = cbm_now_ms() + 1000;
while (!cbm_diag_test_writer_reached() && cbm_now_ms() < reach_deadline) {
diagnostics_wait_ms(10);
}
bool reached = cbm_diag_test_writer_reached();
if (!captured || !reached) {
cbm_diag_test_hold_writer(false);
cbm_diag_stop();
(void)cbm_unsetenv("CBM_DIAGNOSTICS");
if (captured) {
diagnostics_cleanup_outputs(&outputs);
}
FAIL("diagnostics writer did not reach the held I/O boundary");
}
uint64_t started_ms = cbm_now_ms();
cbm_diag_stop();
uint64_t elapsed_ms = cbm_now_ms() - started_ms;
bool abandoned = cbm_diag_test_abandoned();
cbm_diag_test_hold_writer(false);
bool reset = false;
uint64_t reset_deadline = cbm_now_ms() + 1000;
while (!reset && cbm_now_ms() < reset_deadline) {
reset = cbm_diag_test_reset_abandoned();
if (!reset) {
diagnostics_wait_ms(10);
}
}
(void)cbm_unsetenv("CBM_DIAGNOSTICS");
diagnostics_cleanup_outputs(&outputs);
ASSERT_LT(elapsed_ms, UINT64_C(1500));
ASSERT_TRUE(abandoned);
ASSERT_TRUE(reset);
PASS();
}
TEST(diagnostics_soak_discovers_daemon_emitted_paths) {
char *script = diagnostics_read_file("scripts/soak-test.sh");
ASSERT_NOT_NULL(script);
bool parses_start_event = strstr(script, "\"event\":\"diagnostics.start\"") != NULL;
bool isolates_daemon = strstr(script, "CBM_CACHE_DIR=\"$SOAK_CACHE_DIR_VALUE\"") != NULL;
bool legacy_predictable_path = strstr(script, "/tmp/cbm-diagnostics-${SERVER_PID}") != NULL;
free(script);
ASSERT_TRUE(parses_start_event);
ASSERT_TRUE(isolates_daemon);
ASSERT_FALSE(legacy_predictable_path);
PASS();
}
/* ── Discovery record contract ───────────────────────────────────────── */
static char diagnostics_discovery_line[2048];
static int diagnostics_discovery_records;
static void diagnostics_discovery_sink(const char *line) {
if (!line || !strstr(line, "\"event\":\"diagnostics.start\"")) {
return;
}
diagnostics_discovery_records++;
(void)snprintf(diagnostics_discovery_line, sizeof(diagnostics_discovery_line), "%s", line);
}
static bool diagnostics_discovery_value(const char *key, char *out, size_t out_size) {
char marker[64];
if (snprintf(marker, sizeof(marker), "\"%s\":\"", key) >= (int)sizeof(marker)) {
return false;
}
const char *cursor = strstr(diagnostics_discovery_line, marker);
if (!cursor) {
return false;
}
cursor += strlen(marker);
size_t used = 0;
while (*cursor && *cursor != '"' && used + 1 < out_size) {
if (*cursor == '\\' && cursor[1] != '\0') {
cursor++;
char decoded = *cursor;
if (decoded == 'n') {
decoded = '\n';
} else if (decoded == 't') {
decoded = '\t';
} else if (decoded == 'r') {
decoded = '\r';
}
out[used++] = decoded;
cursor++;
continue;
}
out[used++] = *cursor++;
}
out[used] = '\0';
return *cursor == '"';
}
TEST(diagnostics_discovery_record_survives_suppressed_log_level) {
diagnostics_discovery_records = 0;
diagnostics_discovery_line[0] = '\0';
cbm_log_set_level(CBM_LOG_NONE);
cbm_log_set_sink_ex(diagnostics_discovery_sink, CBM_LOG_SINK_REPLACE);
ASSERT_EQ(cbm_setenv("CBM_DIAGNOSTICS", "1", 1), 0);
bool started = cbm_diag_start();
diagnostics_paths_t outputs;
bool captured = started && diagnostics_capture_paths(&outputs);
cbm_diag_stop();
(void)cbm_unsetenv("CBM_DIAGNOSTICS");
cbm_log_set_sink(NULL);
cbm_log_set_level(CBM_LOG_INFO);
char recorded_snapshot[1024] = "";
char recorded_trajectory[1024] = "";
bool decoded =
diagnostics_discovery_value("snapshot", recorded_snapshot, sizeof(recorded_snapshot)) &&
diagnostics_discovery_value("trajectory", recorded_trajectory,
sizeof(recorded_trajectory));
if (captured) {
diagnostics_cleanup_outputs(&outputs);
}
ASSERT_TRUE(started);
ASSERT_TRUE(captured);
/* Exactly one discovery record, delivered despite CBM_LOG_LEVEL=none, and
* its decoded paths are byte-exact against the writer's own paths. */
ASSERT_EQ(diagnostics_discovery_records, 1);
ASSERT_TRUE(decoded);
ASSERT_EQ(strcmp(recorded_snapshot, outputs.snapshot), 0);
ASSERT_EQ(strcmp(recorded_trajectory, outputs.trajectory), 0);
PASS();
}
#ifndef _WIN32
TEST(diagnostics_placement_honors_tmpdir_with_spaces) {
char saved_tmpdir[1024] = "";
const char *current_tmpdir = getenv("TMPDIR");
bool had_tmpdir = current_tmpdir != NULL;
if (had_tmpdir) {
ASSERT_LT(snprintf(saved_tmpdir, sizeof(saved_tmpdir), "%s", current_tmpdir),
(int)sizeof(saved_tmpdir));
}
char base[256];
ASSERT_LT(snprintf(base, sizeof(base), "/tmp/cbm diag spaces %d", (int)getpid()),
(int)sizeof(base));
(void)cbm_rmdir(base);
ASSERT_EQ(mkdir(base, 0700), 0);
ASSERT_EQ(cbm_setenv("TMPDIR", base, 1), 0);
diagnostics_discovery_records = 0;
diagnostics_discovery_line[0] = '\0';
cbm_log_set_sink_ex(diagnostics_discovery_sink, CBM_LOG_SINK_REPLACE);
ASSERT_EQ(cbm_setenv("CBM_DIAGNOSTICS", "1", 1), 0);
bool started = cbm_diag_start();
diagnostics_paths_t outputs;
bool captured = started && diagnostics_capture_paths(&outputs);
bool emitted = captured && diagnostics_wait_for_file(outputs.snapshot, 1000);
cbm_diag_stop();
(void)cbm_unsetenv("CBM_DIAGNOSTICS");
cbm_log_set_sink(NULL);
if (had_tmpdir) {
(void)cbm_setenv("TMPDIR", saved_tmpdir, 1);
} else {
(void)cbm_unsetenv("TMPDIR");
}
char recorded[1024] = "";
bool decoded = diagnostics_discovery_value("snapshot", recorded, sizeof(recorded));
bool under_base = captured && strncmp(outputs.directory, base, strlen(base)) == 0;
if (captured) {
diagnostics_cleanup_outputs(&outputs);
}
(void)cbm_rmdir(base);
ASSERT_TRUE(started);
ASSERT_TRUE(captured);
ASSERT_TRUE(emitted);
/* The documented contract: honor $TMPDIR (with /tmp fallback), and the
* discovery record must round-trip a path containing spaces exactly. */
ASSERT_TRUE(under_base);
ASSERT_TRUE(decoded);
ASSERT_EQ(strcmp(recorded, outputs.snapshot), 0);
PASS();
}
#endif
#ifdef _WIN32
static wchar_t *diagnostics_windows_utf8_to_wide(const char *value) {
int needed = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, value, -1, NULL, 0);
wchar_t *wide = needed > 0 ? calloc((size_t)needed, sizeof(*wide)) : NULL;
if (!wide || MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, value, -1, wide, needed) <= 0) {
free(wide);
return NULL;
}
return wide;
}
static bool diagnostics_windows_current_user_sid(void **information_out, PSID *sid_out) {
*information_out = NULL;
*sid_out = NULL;
HANDLE token = NULL;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) {
return false;
}
DWORD needed = 0;
(void)GetTokenInformation(token, TokenUser, NULL, 0, &needed);
void *information = needed > 0 ? calloc(1, needed) : NULL;
bool ok =
information && GetTokenInformation(token, TokenUser, information, needed, &needed) != 0;
(void)CloseHandle(token);
if (!ok) {
free(information);
return false;
}
PSID sid = ((TOKEN_USER *)information)->User.Sid;
if (!sid || !IsValidSid(sid)) {
free(information);
return false;
}
*information_out = information;
*sid_out = sid;
return true;
}
/* Owner is the current user AND the protected DACL grants access to that
* owner alone — the Windows equivalent of the POSIX 0700/0600 assertions. */
static bool diagnostics_windows_path_owner_private(const char *path, bool directory) {
void *user_information = NULL;
PSID user_sid = NULL;
wchar_t *wide_path = diagnostics_windows_utf8_to_wide(path);
DWORD flags = FILE_FLAG_OPEN_REPARSE_POINT | (directory ? FILE_FLAG_BACKUP_SEMANTICS : 0);
HANDLE handle = wide_path
? CreateFileW(wide_path, READ_CONTROL,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
OPEN_EXISTING, flags, NULL)
: INVALID_HANDLE_VALUE;
PSID owner = NULL;
PACL dacl = NULL;
PSECURITY_DESCRIPTOR descriptor = NULL;
SECURITY_DESCRIPTOR_CONTROL control = 0;
DWORD revision = 0;
bool ok = handle != INVALID_HANDLE_VALUE &&
diagnostics_windows_current_user_sid(&user_information, &user_sid) &&
GetSecurityInfo(handle, SE_FILE_OBJECT,
OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, &owner, NULL,
&dacl, NULL, &descriptor) == ERROR_SUCCESS &&
owner && IsValidSid(owner) && EqualSid(owner, user_sid) &&
GetSecurityDescriptorControl(descriptor, &control, &revision) != 0 &&
(control & SE_DACL_PROTECTED) != 0 && dacl && dacl->AceCount == 1;
if (ok) {
void *ace = NULL;
ok = GetAce(dacl, 0, &ace) != 0 &&
((ACE_HEADER *)ace)->AceType == ACCESS_ALLOWED_ACE_TYPE &&
EqualSid((PSID)&((ACCESS_ALLOWED_ACE *)ace)->SidStart, user_sid);
}
if (descriptor) {
(void)LocalFree(descriptor);
}
if (handle != INVALID_HANDLE_VALUE) {
(void)CloseHandle(handle);
}
free(wide_path);
free(user_information);
return ok;
}
static bool diagnostics_windows_output_contract(const char *path) {
/* Mirrors production's diag_win_handle_valid: files are secured by their
* owner-private parent directory; the file itself must be a plain local
* regular file — no reparse, no extra links. Owner/DACL are asserted on
* the directory, where the security boundary actually lives (file owners
* follow the machine's default-owner policy, e.g. Administrators on
* GitHub-runner-class images). */
wchar_t *wide_path = diagnostics_windows_utf8_to_wide(path);
HANDLE handle = wide_path
? CreateFileW(wide_path, GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT, NULL)
: INVALID_HANDLE_VALUE;
BY_HANDLE_FILE_INFORMATION information;
bool ok = handle != INVALID_HANDLE_VALUE && GetFileType(handle) == FILE_TYPE_DISK &&
GetFileInformationByHandle(handle, &information) != 0 &&
(information.dwFileAttributes &
(FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT)) == 0 &&
information.nNumberOfLinks == 1;
if (handle != INVALID_HANDLE_VALUE) {
(void)CloseHandle(handle);
}
free(wide_path);
return ok;
}
TEST(diagnostics_outputs_are_owner_private_windows) {
ASSERT_EQ(cbm_setenv("CBM_DIAGNOSTICS", "1", 1), 0);
ASSERT_TRUE(cbm_diag_start());
diagnostics_paths_t outputs;
bool captured = diagnostics_capture_paths(&outputs);
bool snapshot_emitted = captured && diagnostics_wait_for_file(outputs.snapshot, 1000);
bool trajectory_emitted = captured && diagnostics_wait_for_file(outputs.trajectory, 1000);
bool secure = captured && snapshot_emitted && trajectory_emitted &&
diagnostics_windows_path_owner_private(outputs.directory, true) &&
diagnostics_windows_output_contract(outputs.snapshot) &&
diagnostics_windows_output_contract(outputs.trajectory);
cbm_diag_stop();
ASSERT_EQ(cbm_unsetenv("CBM_DIAGNOSTICS"), 0);
if (captured) {
diagnostics_cleanup_outputs(&outputs);
}
ASSERT_TRUE(secure);
PASS();
}
#endif
/* ── scaling probe (profile.h) ──────────────────────────────────────
*
* These pin the arithmetic and the checkpoint bookkeeping, deliberately WITHOUT
* timing anything. A test that tried to prove the detector works by generating
* a genuinely quadratic workload would be asserting on the scheduler, and would
* go flaky on a loaded CI box — so the fit is a pure function and gets fed
* synthetic points instead. */
TEST(scale_fit_k_recognises_linear_and_quadratic_growth) {
/* 8x the items, 8x the time => k = 1 */
ASSERT_TRUE(cbm_scale_fit_k(1000, 1000, 8000, 8000) > 0.99);
ASSERT_TRUE(cbm_scale_fit_k(1000, 1000, 8000, 8000) < 1.01);
/* 8x the items, 64x the time => k = 2 */
ASSERT_TRUE(cbm_scale_fit_k(1000, 1000, 8000, 64000) > 1.99);
ASSERT_TRUE(cbm_scale_fit_k(1000, 1000, 8000, 64000) < 2.01);
/* n log n sits between, and must NOT be mistaken for quadratic */
double k_nlogn = cbm_scale_fit_k(1000, 1000, 8000, 8000 * 13 / 10);
ASSERT_TRUE(k_nlogn > 1.0);
ASSERT_TRUE(k_nlogn < CBM_SCALE_WARN_K);
PASS();
}
TEST(scale_fit_k_rejects_degenerate_input) {
ASSERT_TRUE(cbm_scale_fit_k(0, 1000, 8000, 8000) < 0.0); /* no first point */
ASSERT_TRUE(cbm_scale_fit_k(1000, 0, 8000, 8000) < 0.0); /* zero elapsed */
ASSERT_TRUE(cbm_scale_fit_k(1000, 1000, 1000, 8000) < 0.0); /* n did not grow */
ASSERT_TRUE(cbm_scale_fit_k(1000, 1000, 500, 8000) < 0.0); /* n went backwards */
ASSERT_TRUE(cbm_scale_fit_k(1000, 1000, 8000, 0) < 0.0); /* zero total */
PASS();
}
TEST(scale_probe_records_checkpoints_at_eighths) {
cbm_scale_probe_t p;
cbm_scale_begin(&p, "unit", 1024);
/* Below the first threshold (1024/8 = 128), nothing is claimed. */
for (long i = 0; i < 128; i++) {
cbm_scale_tick(&p, i);
}
ASSERT_EQ(atomic_load(&p.next_cp), 0);
cbm_scale_tick(&p, 128); /* 1/8 */
ASSERT_EQ(atomic_load(&p.next_cp), 1);
cbm_scale_tick(&p, 200); /* still short of 1/4 */
ASSERT_EQ(atomic_load(&p.next_cp), 1);
cbm_scale_tick(&p, 256); /* 1/4 */
ASSERT_EQ(atomic_load(&p.next_cp), 2);
cbm_scale_tick(&p, 512); /* 1/2 */
ASSERT_EQ(atomic_load(&p.next_cp), 3);
cbm_scale_tick(&p, 1024); /* all */
ASSERT_EQ(atomic_load(&p.next_cp), 4);
/* Saturates rather than overrunning the array. */
cbm_scale_tick(&p, 2048);
ASSERT_EQ(atomic_load(&p.next_cp), 4);
ASSERT_EQ(p.cp_items[0], 128);
ASSERT_EQ(p.cp_items[3], 1024);
cbm_scale_end(&p);
PASS();
}
TEST(scale_probe_ignores_runs_too_small_to_judge) {
/* Under SCALE_MIN_ITEMS a pass is not where an O(n^2) hurts anyone, and the
* fit would be measuring noise — so the probe must stay silent. */
cbm_scale_probe_t p;
cbm_scale_begin(&p, "tiny", 64);
for (long i = 0; i <= 64; i++) {
cbm_scale_tick(&p, i);
}
ASSERT_EQ(atomic_load(&p.next_cp), 0);
cbm_scale_end(&p); /* must not emit, must not crash */
PASS();
}
SUITE(diagnostics) {
RUN_TEST(scale_fit_k_recognises_linear_and_quadratic_growth);
RUN_TEST(scale_fit_k_rejects_degenerate_input);
RUN_TEST(scale_probe_records_checkpoints_at_eighths);
RUN_TEST(scale_probe_ignores_runs_too_small_to_judge);
#ifndef _WIN32
RUN_TEST(diagnostics_rejects_predictable_tmp_symlinks);
#endif
RUN_TEST(diagnostics_stop_interrupts_periodic_wait);
#ifndef _WIN32
RUN_TEST(diagnostics_outputs_are_owner_private_regular_files);
RUN_TEST(diagnostics_placement_honors_tmpdir_with_spaces);
#endif
#ifdef _WIN32
RUN_TEST(diagnostics_outputs_are_owner_private_windows);
#endif
RUN_TEST(diagnostics_discovery_record_survives_suppressed_log_level);
RUN_TEST(diagnostics_stalled_writer_cannot_retain_shutdown);
RUN_TEST(diagnostics_soak_discovers_daemon_emitted_paths);
}