Pantheon/tests/test_serve_spec_lookup.c

78 lines
3.7 KiB
C

/* SPDX-License-Identifier: AGPL-3.0-or-later */
/* Copyright (C) 2026 David (Corey) Herrera */
/**
* @file test_serve_spec_lookup.c
* @brief The serve's prompt-lookup drafts: matches, the minimum suffix, the cap, the history
* growth and the throttle. `--selftest` breaks the expected continuation and must fail.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../src/serve/serve_spec_lookup.h"
static int g_failed;
#define CHECK(cond, ...) \
do { \
if (!(cond)) { \
g_failed++; \
fprintf(stderr, " FAIL: " __VA_ARGS__); \
fprintf(stderr, "\n"); \
} \
} while (0)
int main(int argc, char **argv)
{
const int selftest = argc > 1 && strcmp(argv[1], "--selftest") == 0;
/* "a b c d e f g ... a b c" : the suffix a b c recurs, d e f g follow it. */
const uint32_t prompt[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2 };
uint32_t drafts[16];
sg_spec_lookup lookup;
int n, i;
setenv("PN_TT_SPEC_LOOKUP", "1", 1);
setenv("PN_TT_SPEC_LOOKUP_K", "4", 1);
setenv("PN_TT_SPEC_LOOKUP_MIN", "3", 1);
CHECK(sg_spec_lookup_init(&lookup, prompt, 14, 1) == 0 && lookup.on, "init");
/* Suffix "1 2" is two tokens: below the minimum of three. */
CHECK(sg_spec_lookup_draft(&lookup, 15, drafts) == 0, "a 2-token match drafted");
sg_spec_lookup_push(&lookup, 3); /* grows past the initial capacity of 14 + 1 + 16 */
n = sg_spec_lookup_draft(&lookup, 15, drafts);
CHECK(n == 4, "drafts %d, want 4", n);
for (i = 0; i < n; i++)
CHECK(drafts[i] == (uint32_t)(4 + i + (selftest ? 1 : 0)), "draft %d = %u", i,
drafts[i]);
CHECK(sg_spec_lookup_draft(&lookup, 2, drafts) == 2, "the cap");
for (i = 0; i < 40; i++)
sg_spec_lookup_push(&lookup, 100u + (uint32_t)i);
CHECK(lookup.count == 55 && lookup.on, "history grew to %d", lookup.count);
/* The throttle: two lookup cycles accepting < 3 rest it for 16 cycles. */
for (i = 0; i < 40; i++)
sg_spec_lookup_push(&lookup, 1u + (uint32_t)(i % 3));
CHECK(sg_spec_lookup_draft(&lookup, 15, drafts) > 0, "a repeating tail drafts");
sg_spec_lookup_report(&lookup, 4, 0);
sg_spec_lookup_report(&lookup, 4, 1);
CHECK(sg_spec_lookup_draft(&lookup, 15, drafts) == 0, "throttled");
CHECK(sg_spec_lookup_agrees(&lookup, 5u, 6u), "mode 1 takes lookup whatever MTP says");
sg_spec_lookup_free(&lookup);
setenv("PN_TT_SPEC_LOOKUP", "2", 1);
CHECK(sg_spec_lookup_init(&lookup, prompt, 14, 1) == 0 && lookup.on, "mode 2 init");
CHECK(sg_spec_lookup_agrees(&lookup, 5u, 5u) && !sg_spec_lookup_agrees(&lookup, 5u, 6u),
"mode 2 takes lookup only when the first drafts agree");
sg_spec_lookup_free(&lookup);
unsetenv("PN_TT_SPEC_LOOKUP");
CHECK(sg_spec_lookup_init(&lookup, prompt, 14, 1) == 0 && !lookup.on, "off by default");
sg_spec_lookup_free(&lookup);
setenv("PN_TT_SPEC_LOOKUP", "0", 1);
CHECK(sg_spec_lookup_init(&lookup, prompt, 14, 1) == 0 && !lookup.on, "off by env");
CHECK(sg_spec_lookup_draft(&lookup, 15, drafts) == 0, "off drafts nothing");
sg_spec_lookup_free(&lookup);
if (g_failed) {
printf("=== %d FAILED ===\n", g_failed);
return 1;
}
printf("=== all tests passed ===\n");
return 0;
}