commit 29d95a2fadb3dbeb4955ebed3d0a2c8165beb770
parent e08f498d65f64eb6e7701fe318c8a55580ab22c6
Author: cowmonk <cowmonk@based.pt>
Date: Mon, 24 Aug 2026 19:32:48 -0700
serva/svc tests
added test suite to ensure serva/svc basic functionality
Diffstat:
11 files changed, 192 insertions(+), 0 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -7,3 +7,7 @@ svc.o
slog
slog.o
util.o
+
+tests/serva-test
+tests/serva.log
+tests/svc-test
diff --git a/README b/README
@@ -212,6 +212,10 @@ Source Layout
config.mk build configuration
Makefile posix (should work with any *competent* make impl)
+ tests/
+ run.sh run this to test init suite (currently only serva/svc)
+ Makefile build serva/svc test binaries
+ ssv/* dummy ssv
files/
rc.* optional example configurations
bin/* optional scripts to use along with RATS
diff --git a/tests/Makefile b/tests/Makefile
@@ -0,0 +1,26 @@
+# tests/Makefile: build serva/svc against a sandboxed ssv dir + socket
+.POSIX:
+
+include ../config.mk
+
+TOP = ..
+CC ?= cc
+
+all: serva-test svc-test
+
+serva-test: $(TOP)/serva.c $(TOP)/util.o
+ $(CC) $(CFLAGS) -DSVC_DIR='"$(CURDIR)/ssv"' \
+ -DSOCK_PATH='"$(CURDIR)/serva.sock"' \
+ $(LDFLAGS) -o $@ $(TOP)/serva.c $(TOP)/util.o
+
+svc-test: $(TOP)/svc.c $(TOP)/util.o
+ $(CC) $(CFLAGS) -DSOCK_PATH='"$(CURDIR)/serva.sock"' \
+ $(LDFLAGS) -o $@ $(TOP)/svc.c $(TOP)/util.o
+
+$(TOP)/util.o: $(TOP)/util.c $(TOP)/util.h
+ cd $(TOP) && $(MAKE) util.o
+
+clean:
+ rm -f serva-test svc-test serva.log
+
+.PHONY: all clean run-tests
diff --git a/tests/run.sh b/tests/run.sh
@@ -0,0 +1,144 @@
+#!/bin/sh
+# tests/run.sh: integration test for serva + svc
+#
+# Boots a sandboxed serva against ./ssv and drives it with svc-test.
+# No root needed: everything lives under tests/.
+
+set -u
+cd "$(dirname "$0")"
+
+SOCK="$PWD/serva.sock"
+SERVA=./serva-test
+SVC=./svc-test
+LOG=serva.log
+PASS=0
+FAIL=0
+
+say() { printf '%s\n' "$*"; }
+ok() { PASS=$((PASS + 1)); say "ok - $1"; }
+bad() { FAIL=$((FAIL + 1)); say "FAIL - $1"; }
+
+cleanup() {
+ [ -n "${SERVA_PID:-}" ] && kill "$SERVA_PID" 2>/dev/null
+ wait 2>/dev/null
+ rm -f "$SOCK"
+}
+trap cleanup EXIT
+
+# --- setup sandbox -----------------------------------------------------------
+rm -rf ssv
+mkdir -p ssv/boot/crashme ssv/default/sleeper ssv/default/oneshot ssv/default/depender/need
+
+cat > ssv/boot/crashme/run <<'EOF'
+#!/bin/sh
+echo "crashme starting"
+exit 42
+EOF
+
+cat > ssv/default/sleeper/run <<'EOF'
+#!/bin/sh
+echo "sleeper starting"
+trap 'exit 0' TERM
+while :; do sleep 1; done
+EOF
+
+cat > ssv/default/oneshot/run <<'EOF'
+#!/bin/sh
+echo "oneshot ran"
+touch "$PWD.marker" 2>/dev/null || true
+exit 0
+EOF
+touch ssv/default/oneshot/once
+
+cat > ssv/default/depender/run <<'EOF'
+#!/bin/sh
+trap 'exit 0' TERM
+while :; do sleep 1; done
+EOF
+touch ssv/default/depender/need/sleeper
+
+chmod +x ssv/*/*/run
+
+# --- build + launch ----------------------------------------------------------
+make -s all || { say "build failed"; exit 1; }
+
+"$SERVA" >"$LOG" 2>&1 &
+SERVA_PID=$!
+
+for i in 1 2 3 4 5 6 7 8 9 10; do
+ [ -S "$SOCK" ] && break
+ sleep 0.2
+done
+[ -S "$SOCK" ] || { bad "serva socket never appeared"; exit 1; }
+sleep 1 # let services start (and crashme crash once)
+
+# --- tests -------------------------------------------------------------------
+out=$("$SVC" -s)
+case $out in
+*default/sleeper*RUN*) ok "svc -s lists sleeper as RUN" ;;
+*) bad "svc -s should show sleeper RUN, got: $out" ;;
+esac
+
+out=$("$SVC" -s sleeper)
+case $out in
+*sleeper*RUN*runs=1*) ok "svc -s <name> shows single service with runs=1" ;;
+*) bad "svc -s sleeper unexpected: $out" ;;
+esac
+
+out=$("$SVC" -s crashme)
+case $out in
+*exit=42*) ok "svc -s crashme records exit code 42" ;;
+*) bad "svc -s crashme missing exit=42: $out" ;;
+esac
+
+out=$("$SVC" -s crashme)
+runs=$(printf '%s' "$out" | sed -n 's/.*runs=\([0-9]*\).*/\1/p')
+[ "${runs:-0}" -ge 2 ] && ok "crashme restarted with backoff (runs=$runs)" \
+ || bad "crashme should have restarted, runs=${runs:-?}"
+
+out=$("$SVC" -s depender)
+case $out in
+*RUN*) ok "depender started once sleeper was running" ;;
+*) bad "depender should be RUN after dep met: $out" ;;
+esac
+
+out=$("$SVC" -s oneshot)
+case $out in
+*DONE*) ok "oneshot reports DONE after exit" ;;
+*) bad "oneshot should be DONE: $out" ;;
+esac
+
+out=$("$SVC" -d sleeper 2>&1) && sleep 0.5 && out=$("$SVC" -s sleeper)
+case $out in
+*DOWN*) ok "svc -d brings sleeper down" ;;
+*) bad "sleeper should be DOWN after svc -d: $out" ;;
+esac
+
+out=$("$SVC" -s depender)
+case $out in
+*WAIT*) ok "depender cascades to WAIT when sleeper stops" ;;
+*) bad "depender should be WAIT after sleeper down: $out" ;;
+esac
+
+"$SVC" -u sleeper >/dev/null && sleep 0.5
+out=$("$SVC" -s depender)
+case $out in
+*RUN*) ok "depender restarts when dep comes back" ;;
+*) bad "depender should be RUN again: $out" ;;
+esac
+
+out=$("$SVC" -s nosuchsvc 2>&1)
+case $out in
+*ERR*) ok "svc -s on unknown service returns ERR" ;;
+*) bad "expected ERR for unknown service: $out" ;;
+esac
+
+out=$("$SVC" -r sleeper 2>&1) && sleep 0.5
+runs=$("$SVC" -s sleeper | sed -n 's/.*runs=\([0-9]*\).*/\1/p')
+[ "${runs:-0}" -ge 2 ] && ok "svc -r restarts sleeper (runs=$runs)" \
+ || bad "svc -r did not restart sleeper: runs=${runs:-?}"
+
+# --- summary -----------------------------------------------------------------
+say ""
+say "passed: $PASS failed: $FAIL"
+[ "$FAIL" -eq 0 ]
diff --git a/tests/ssv/boot/crashme/run b/tests/ssv/boot/crashme/run
@@ -0,0 +1,3 @@
+#!/bin/sh
+echo "crashme starting"
+exit 42
diff --git a/tests/ssv/default/depender/need/sleeper b/tests/ssv/default/depender/need/sleeper
diff --git a/tests/ssv/default/depender/run b/tests/ssv/default/depender/run
@@ -0,0 +1,3 @@
+#!/bin/sh
+trap 'exit 0' TERM
+while :; do sleep 1; done
diff --git a/tests/ssv/default/oneshot.marker b/tests/ssv/default/oneshot.marker
diff --git a/tests/ssv/default/oneshot/once b/tests/ssv/default/oneshot/once
diff --git a/tests/ssv/default/oneshot/run b/tests/ssv/default/oneshot/run
@@ -0,0 +1,4 @@
+#!/bin/sh
+echo "oneshot ran"
+touch "$PWD.marker" 2>/dev/null || true
+exit 0
diff --git a/tests/ssv/default/sleeper/run b/tests/ssv/default/sleeper/run
@@ -0,0 +1,4 @@
+#!/bin/sh
+echo "sleeper starting"
+trap 'exit 0' TERM
+while :; do sleep 1; done