circus/nix/tests/service-startup.nix
NotAShelf 7dae114783
nix: split off monolithic VM test
Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: Ifc0a92ed8b6c7622ae345a21880fd0296a6a6964
2026-02-05 22:45:07 +03:00

81 lines
4 KiB
Nix

{
pkgs,
fc-packages,
nixosModule,
}:
pkgs.testers.nixosTest {
name = "fc-service-startup";
nodes.machine = import ./common.nix {inherit pkgs fc-packages nixosModule;};
testScript = ''
machine.start()
machine.wait_for_unit("postgresql.service")
# Ensure PostgreSQL is actually ready to accept connections
# before fc-server starts. Not actually implied by the wait_for_unit
machine.wait_until_succeeds("sudo -u fc psql -U fc -d fc -c 'SELECT 1'", timeout=30)
machine.wait_for_unit("fc-server.service")
# Wait for the server to start listening
machine.wait_until_succeeds("curl -sf http://127.0.0.1:3000/health", timeout=30)
# Verify all three services start
with subtest("fc-evaluator.service starts without crash"):
machine.wait_for_unit("fc-evaluator.service", timeout=30)
result = machine.succeed("journalctl -u fc-evaluator --no-pager -n 20 2>&1")
assert "binary not found" not in result.lower(), f"Evaluator has 'binary not found' error: {result}"
assert "No such file" not in result, f"Evaluator has 'No such file' error: {result}"
with subtest("fc-queue-runner.service starts without crash"):
machine.wait_for_unit("fc-queue-runner.service", timeout=30)
result = machine.succeed("journalctl -u fc-queue-runner --no-pager -n 20 2>&1")
assert "binary not found" not in result.lower(), f"Queue runner has 'binary not found' error: {result}"
assert "No such file" not in result, f"Queue runner has 'No such file' error: {result}"
with subtest("All three FC services are active"):
for svc in ["fc-server", "fc-evaluator", "fc-queue-runner"]:
result = machine.succeed(f"systemctl is-active {svc}")
assert result.strip() == "active", f"Expected {svc} to be active, got '{result.strip()}'"
with subtest("Declarative project was bootstrapped"):
result = machine.succeed(
"curl -sf http://127.0.0.1:3000/api/v1/projects | jq -r '.items[] | select(.name==\"declarative-project\") | .name'"
)
assert result.strip() == "declarative-project", f"Expected declarative-project, got '{result.strip()}'"
with subtest("Declarative project has correct repository URL"):
result = machine.succeed(
"curl -sf http://127.0.0.1:3000/api/v1/projects | jq -r '.items[] | select(.name==\"declarative-project\") | .repository_url'"
)
assert result.strip() == "https://github.com/test/declarative", f"Expected declarative repo URL, got '{result.strip()}'"
with subtest("Declarative project has bootstrapped jobset"):
# Get the declarative project ID
decl_project_id = machine.succeed(
"curl -sf http://127.0.0.1:3000/api/v1/projects | jq -r '.items[] | select(.name==\"declarative-project\") | .id'"
).strip()
result = machine.succeed(
f"curl -sf http://127.0.0.1:3000/api/v1/projects/{decl_project_id}/jobsets | jq '.items[0].name' -r"
)
assert result.strip() == "packages", f"Expected packages jobset, got '{result.strip()}'"
with subtest("Declarative API key works for authentication"):
code = machine.succeed(
"curl -s -o /dev/null -w '%{http_code}' "
"-H 'Authorization: Bearer fc_bootstrap_key' "
"http://127.0.0.1:3000/api/v1/projects"
)
assert code.strip() == "200", f"Expected 200 with bootstrap key, got {code.strip()}"
with subtest("Bootstrap is idempotent (server restarted successfully with same config)"):
# The server already started successfully with declarative config. That
# proves the bootstrap ran. Now we should check that only one declarative
# project exists, and not any duplicates.
result = machine.succeed(
"curl -sf http://127.0.0.1:3000/api/v1/projects | jq '.items | map(select(.name==\"declarative-project\")) | length'"
)
assert result.strip() == "1", f"Expected exactly 1 declarative-project, got {result.strip()}"
'';
}