Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,13 @@ target_link_libraries(test-hydra-rpc-stale-sock PRIVATE ggml)
# #470: test uses ggml_backend_buffer_copy_tensor (declared in ggml-backend-impl.h).
target_include_directories(test-hydra-rpc-stale-sock PRIVATE ${PROJECT_SOURCE_DIR}/ggml/src)

# epic #610 WS1: hermetic A/B seam checks (HYDRA_EXT_MODE parsing + the WS1
# no-op factory). Needs the server-context TU so hydra_create_extension() and
# the inline mode parser are visible.
llama_build_and_test(test-hydra-ext-ab.cpp)
target_link_libraries(test-hydra-ext-ab PRIVATE server-context)
target_include_directories(test-hydra-ext-ab PRIVATE ${CMAKE_SOURCE_DIR}/tools/server)

if (NOT WIN32 OR NOT BUILD_SHARED_LIBS)
# these tests are disabled on Windows because they use internal functions not exported with LLAMA_API (when building with shared libraries)
llama_build_and_test(test-sampling.cpp)
Expand Down
83 changes: 83 additions & 0 deletions tests/test-hydra-ext-ab.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// epic #610 WS1: hermetic A/B seam checks.
//
// What this can test without a model/GPU:
// - HYDRA_EXT_MODE env parsing (legacy default, "seam" activates seam)
// - the factory returns the expected no-op WS1 implementation
// - the no-op contract: hooks don't claim tasks / don't alter the loop
//
// What CANNOT be tested hermetically: a server_context_impl requires a loaded
// model+context, so the behavioral A/B (run the SAME scenario through
// HYDRA_EXT_MODE=legacy vs =seam and diff the outputs) is a loopback / live-rig
// step, documented as WS4 in the epic.

#include "server-hydra-extension.h"

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <memory>

static int g_failures = 0;

static void expect(const char * what, bool ok) {
if (!ok) {
fprintf(stderr, "FAIL: %s\n", what);
g_failures++;
}
}

// setenv/unsetenv are POSIX; on Windows use _putenv_s (empty = unset).
#if defined(_WIN32)
static void set_ext_mode(const char * value) {
_putenv_s("HYDRA_EXT_MODE", value ? value : "");
}
#else
static void set_ext_mode(const char * value) {
if (value == nullptr) {
unsetenv("HYDRA_EXT_MODE");
} else {
setenv("HYDRA_EXT_MODE", value, 1);
}
}
#endif

int main() {
// --- mode parsing (WS5: default = seam unless explicitly legacy) ----
set_ext_mode(nullptr);
expect("unset HYDRA_EXT_MODE -> seam (default)", hydra_ext_mode_seam());

set_ext_mode("legacy");
expect("HYDRA_EXT_MODE=legacy -> legacy", !hydra_ext_mode_seam());

set_ext_mode("seam");
expect("HYDRA_EXT_MODE=seam -> seam", hydra_ext_mode_seam());

set_ext_mode("garbage");
expect("HYDRA_EXT_MODE=garbage -> seam (default)", hydra_ext_mode_seam());

set_ext_mode("LEGACY"); // case-sensitive: not "legacy"
expect("HYDRA_EXT_MODE=LEGACY -> seam (default)", hydra_ext_mode_seam());

// --- factory + WS1 no-op contract ---------------------------------
std::unique_ptr<server_hydra_extension> ext = hydra_create_extension();
expect("factory returns non-null", ext != nullptr);
if (ext) {
// WS2/WS3 impl name (handle_task routes to hydra_process_task, and
// pre_loop/on_empty_batch replicate the update_slots clusters).
expect("impl name is hydra-task-ws2", std::strcmp(ext->name(), "hydra-task-ws2") == 0);
}

// The no-op hooks take a server_context_impl&, which cannot be constructed
// here (needs a loaded model). Their return values are pinned by the WS1
// contract: handle_task=false (never claims), pre_loop=false (never skips
// the decode loop), on_empty_batch=false (never handles the empty batch).
// Behavioral parity is verified by the live-rig A/B in WS4.

if (g_failures != 0) {
fprintf(stderr, "test-hydra-ext-ab FAILED (%d)\n", g_failures);
return 1;
}

fprintf(stderr, "%s", "test-hydra-ext-ab OK\n");
return 0;
}
Loading