Skip to content

Commit 6a06774

Browse files
committed
Document backend test modes and separate mode definitions
1 parent 0be8da2 commit 6a06774

3 files changed

Lines changed: 286 additions & 0 deletions

File tree

test/dockerfiles/Dockerfile.base

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
FROM ubuntu:24.04

test/dockerfiles/Dockerfile.delta

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
FROM ddiff-test/base
2+
RUN apt-get update && apt-get install -y --no-install-recommends tmux && rm -rf /var/lib/apt/lists/*

test/test_ddiff_backends.sh

Lines changed: 283 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,283 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
# Integration tests for ddiff backend modes.
5+
#
6+
# Common lifecycle validated by every mode:
7+
# 1) build base/delta test images
8+
# 2) run `ddiff diff` against a first registry
9+
# 3) remove that registry and delete its data
10+
# 4) run `ddiff load` against a fresh registry
11+
# 5) verify the loaded image contains tmux
12+
# 6) clean all containers/images/archive/tmp files
13+
14+
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
15+
TEST_DIR="$ROOT_DIR/test"
16+
DOCKERFILES_DIR="$TEST_DIR/dockerfiles"
17+
DDIFF_PY="$ROOT_DIR/ddiff.py"
18+
19+
BASE_TAG="ddiff-test/base:latest"
20+
DELTA_TAG="ddiff-test/delta:latest"
21+
ARCHIVE_NAME="ddiff-test--delta-latest.tar.gz"
22+
ARCHIVE_PATH="$ROOT_DIR/$ARCHIVE_NAME"
23+
REGISTRY_IMAGE="registry:2.8.3"
24+
TMP_ROOT="$TEST_DIR/.tmp/ddiff-backends"
25+
26+
TOTAL=0
27+
PASSED=0
28+
FAILED=0
29+
SKIPPED=0
30+
31+
log() {
32+
echo "[test] $*"
33+
}
34+
35+
# Run one command, stream its captured output, and return exact exit code.
36+
run_step() {
37+
local logfile="$1"
38+
shift
39+
40+
mkdir -p "$(dirname "$logfile")"
41+
{
42+
echo "+ $*"
43+
"$@"
44+
} >"$logfile" 2>&1
45+
local status=$?
46+
47+
cat "$logfile"
48+
return "$status"
49+
}
50+
51+
# Wait for Docker Registry HTTP API to become ready.
52+
wait_for_registry() {
53+
local port="$1"
54+
for _ in $(seq 1 30); do
55+
if curl -fsS "http://127.0.0.1:${port}/v2/" >/dev/null 2>&1; then
56+
return 0
57+
fi
58+
sleep 1
59+
done
60+
return 1
61+
}
62+
63+
# Print missing tools and return non-zero if any required command is absent.
64+
have_all_commands() {
65+
local missing=0
66+
local cmd
67+
for cmd in "$@"; do
68+
if ! command -v "$cmd" >/dev/null 2>&1; then
69+
echo "[SKIP] missing command: $cmd"
70+
missing=1
71+
fi
72+
done
73+
[[ "$missing" -eq 0 ]]
74+
}
75+
76+
# Best-effort cleanup for a single test case.
77+
cleanup_case() {
78+
local runtime="$1"
79+
local diff_container="$2"
80+
local load_container="$3"
81+
local work_dir="$4"
82+
83+
set +e
84+
"$runtime" rm -f "$diff_container" >/dev/null 2>&1
85+
"$runtime" rm -f "$load_container" >/dev/null 2>&1
86+
"$runtime" rmi "$DELTA_TAG" >/dev/null 2>&1
87+
"$runtime" rmi "$BASE_TAG" >/dev/null 2>&1
88+
rm -f "$ARCHIVE_PATH"
89+
rm -rf "$work_dir"
90+
set -e
91+
}
92+
93+
# Generic mode runner.
94+
#
95+
# Injected behavior per mode:
96+
# - runtime: docker or podman
97+
# - force_key/force_value: optional env injection (DDIFF_FORCE_*)
98+
# - expect_marker: optional log marker that confirms mode selection
99+
# - required tools: mode-specific prerequisites
100+
run_case() {
101+
local name="$1"
102+
local runtime="$2"
103+
local force_key="$3"
104+
local force_value="$4"
105+
local expect_marker="$5"
106+
local diff_port="$6"
107+
local load_port="$7"
108+
shift 7
109+
local -a required=("$@")
110+
111+
TOTAL=$((TOTAL + 1))
112+
113+
local work_dir="$TMP_ROOT/$name"
114+
local logs_dir="$work_dir/logs"
115+
local diff_registry_dir="$work_dir/registry_diff"
116+
local load_registry_dir="$work_dir/registry_load"
117+
local diff_container="ddiff-${name}-diff"
118+
local load_container="ddiff-${name}-load"
119+
120+
rm -rf "$work_dir"
121+
mkdir -p "$logs_dir" "$diff_registry_dir" "$load_registry_dir"
122+
123+
log "[$name] prerequisites"
124+
if ! have_all_commands "${required[@]}"; then
125+
SKIPPED=$((SKIPPED + 1))
126+
echo "SKIP: $name"
127+
cleanup_case "$runtime" "$diff_container" "$load_container" "$work_dir"
128+
return 0
129+
fi
130+
131+
local status=0
132+
133+
log "[$name] build base image"
134+
run_step "$logs_dir/build-base.log" \
135+
"$runtime" build -t "$BASE_TAG" -f "$DOCKERFILES_DIR/Dockerfile.base" "$TEST_DIR" || status=$?
136+
137+
if [[ "$status" -eq 0 ]]; then
138+
log "[$name] build delta image"
139+
run_step "$logs_dir/build-delta.log" \
140+
"$runtime" build -t "$DELTA_TAG" -f "$DOCKERFILES_DIR/Dockerfile.delta" "$TEST_DIR" || status=$?
141+
fi
142+
143+
if [[ "$status" -eq 0 ]]; then
144+
log "[$name] start diff registry"
145+
run_step "$logs_dir/registry-diff-start.log" \
146+
"$runtime" run -d --name "$diff_container" -p "${diff_port}:5000" -v "$diff_registry_dir:/var/lib/registry" "$REGISTRY_IMAGE" || status=$?
147+
fi
148+
149+
if [[ "$status" -eq 0 ]]; then
150+
wait_for_registry "$diff_port" || { echo "registry not ready on ${diff_port}" | tee "$logs_dir/registry-diff-ready.log"; status=1; }
151+
fi
152+
153+
if [[ "$status" -eq 0 ]]; then
154+
log "[$name] ddiff diff"
155+
if [[ -n "$force_key" ]]; then
156+
run_step "$logs_dir/ddiff-diff.log" \
157+
env DDIFF_URL="http://127.0.0.1:${diff_port}" "$force_key=$force_value" \
158+
python3 "$DDIFF_PY" diff "$BASE_TAG" "$DELTA_TAG" || status=$?
159+
else
160+
run_step "$logs_dir/ddiff-diff.log" \
161+
env DDIFF_URL="http://127.0.0.1:${diff_port}" \
162+
python3 "$DDIFF_PY" diff "$BASE_TAG" "$DELTA_TAG" || status=$?
163+
fi
164+
fi
165+
166+
if [[ "$status" -eq 0 && ! -f "$ARCHIVE_PATH" ]]; then
167+
echo "missing archive: $ARCHIVE_PATH" | tee "$logs_dir/archive-check.log"
168+
status=1
169+
fi
170+
171+
if [[ "$status" -eq 0 ]]; then
172+
log "[$name] delete diff registry and data"
173+
"$runtime" rm -f "$diff_container" >/dev/null 2>&1 || true
174+
rm -rf "$diff_registry_dir"
175+
mkdir -p "$diff_registry_dir"
176+
177+
log "[$name] start fresh load registry"
178+
run_step "$logs_dir/registry-load-start.log" \
179+
"$runtime" run -d --name "$load_container" -p "${load_port}:5000" -v "$load_registry_dir:/var/lib/registry" "$REGISTRY_IMAGE" || status=$?
180+
fi
181+
182+
if [[ "$status" -eq 0 ]]; then
183+
wait_for_registry "$load_port" || { echo "registry not ready on ${load_port}" | tee "$logs_dir/registry-load-ready.log"; status=1; }
184+
fi
185+
186+
if [[ "$status" -eq 0 ]]; then
187+
log "[$name] ddiff load"
188+
if [[ -n "$force_key" ]]; then
189+
run_step "$logs_dir/ddiff-load.log" \
190+
env DDIFF_URL="http://127.0.0.1:${load_port}" "$force_key=$force_value" \
191+
python3 "$DDIFF_PY" load "$ARCHIVE_PATH" || status=$?
192+
else
193+
run_step "$logs_dir/ddiff-load.log" \
194+
env DDIFF_URL="http://127.0.0.1:${load_port}" \
195+
python3 "$DDIFF_PY" load "$ARCHIVE_PATH" || status=$?
196+
fi
197+
fi
198+
199+
if [[ "$status" -eq 0 && -n "$expect_marker" ]]; then
200+
if ! grep -q "$expect_marker" "$logs_dir/ddiff-diff.log"; then
201+
echo "missing mode marker: $expect_marker" | tee "$logs_dir/mode-check.log"
202+
status=1
203+
fi
204+
fi
205+
206+
if [[ "$status" -eq 0 ]]; then
207+
log "[$name] verify loaded image"
208+
run_step "$logs_dir/verify.log" "$runtime" run --rm "$DELTA_TAG" tmux -V || status=$?
209+
fi
210+
211+
cleanup_case "$runtime" "$diff_container" "$load_container" "$work_dir"
212+
213+
if [[ "$status" -eq 0 ]]; then
214+
PASSED=$((PASSED + 1))
215+
echo "PASS: $name"
216+
else
217+
FAILED=$((FAILED + 1))
218+
echo "FAIL: $name"
219+
fi
220+
}
221+
222+
# Test 1: docker mode
223+
# Inject: no force flags
224+
# Expect: default docker path succeeds end-to-end
225+
run_docker_mode() {
226+
run_case \
227+
"docker" \
228+
"docker" \
229+
"" "" "" \
230+
5601 5602 \
231+
python3 curl docker
232+
}
233+
234+
# Test 2: docker-skopeo mode
235+
# Inject: DDIFF_FORCE_SKOPEO=1
236+
# Expect: ddiff log contains "DDIFF_FORCE_SKOPEO is enabled"
237+
run_docker_skopeo_mode() {
238+
run_case \
239+
"docker-skopeo" \
240+
"docker" \
241+
"DDIFF_FORCE_SKOPEO" "1" "DDIFF_FORCE_SKOPEO is enabled" \
242+
5611 5612 \
243+
python3 curl docker skopeo
244+
}
245+
246+
# Test 3: podman mode
247+
# Inject: DDIFF_FORCE_PODMAN=1
248+
# Expect: ddiff log contains "DDIFF_FORCE_PODMAN is enabled"
249+
run_podman_mode() {
250+
run_case \
251+
"podman" \
252+
"podman" \
253+
"DDIFF_FORCE_PODMAN" "1" "DDIFF_FORCE_PODMAN is enabled" \
254+
5621 5622 \
255+
python3 curl podman skopeo
256+
}
257+
258+
run_selected_cases() {
259+
local target="$1"
260+
case "$target" in
261+
all|docker|docker-skopeo|podman) ;;
262+
*)
263+
echo "Usage: $0 [all|docker|docker-skopeo|podman]"
264+
exit 2
265+
;;
266+
esac
267+
268+
[[ "$target" == "all" || "$target" == "docker" ]] && run_docker_mode
269+
[[ "$target" == "all" || "$target" == "docker-skopeo" ]] && run_docker_skopeo_mode
270+
[[ "$target" == "all" || "$target" == "podman" ]] && run_podman_mode
271+
}
272+
273+
main() {
274+
mkdir -p "$TMP_ROOT"
275+
run_selected_cases "${1:-all}"
276+
277+
echo ""
278+
echo "Total: $TOTAL, Passed: $PASSED, Failed: $FAILED, Skipped: $SKIPPED"
279+
280+
[[ "$FAILED" -eq 0 ]]
281+
}
282+
283+
main "$@"

0 commit comments

Comments
 (0)