Skip to content

Commit 2f7bb4e

Browse files
refactor: implement proper test-plans framework pattern in run.sh
- Replaces direct lib-test-execution.sh call with full framework - Adds test matrix generation, image building, compose file generation - Implements parallel test execution with worker support - Includes inputs.yaml generation and caching - Adds comprehensive CLI argument parsing and help - Addresses @dhuseby feedback on framework compliance
1 parent 9db2f86 commit 2f7bb4e

File tree

1 file changed

+332
-13
lines changed

1 file changed

+332
-13
lines changed

echo/run.sh

Lines changed: 332 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,338 @@
11
#!/bin/bash
22

3-
# Echo Protocol Interoperability Tests
4-
# Uses the existing test-plans framework
5-
3+
# run in strict failure mode
64
set -euo pipefail
75

8-
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
9-
ROOT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
6+
# ╔═══╗ ╔═══╗ ╔╗ ╔╗ ╔═══╗
7+
# ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ ║╔══╝ ║╔═╗║ ║║ ║║ ║╔═╗║ ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
8+
# ═══════════════════════════════ ║╚══╗ ║║ ║║ ║╚══╝║ ║║ ║║ ═════════════════════════════════
9+
# ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ ╚═══╝ ╚╝ ╚╝ ╚════╝ ╚╝ ╚╝ ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
10+
11+
# =============================================================================
12+
# STEP 1: BOOTSTRAP: Load inputs.yaml BEFORE setting SCRIPT_LIB_DIR
13+
# -----------------------------------------------------------------------------
14+
# This allows for the re-creation of the environment and command line arguments
15+
# from a previous test run. If the inputs.yaml file doesn't exist, then this
16+
# script will run from a default environment. Any command line arguments passed
17+
# will override any command line arguments loaded from inputs.yaml, however the
18+
# environment variables in inputs.yaml will override the ones initialized in
19+
# the shell executing this script.
20+
# =============================================================================
21+
22+
# Capture original arguments for inputs.yaml generation
23+
ORIGINAL_ARGS=("$@")
24+
25+
# Change to script directory
26+
cd "$(dirname "$0")"
27+
28+
# Loads and exports the environment variables from the inputs yaml file
29+
load_inputs_yaml_inline() {
30+
local inputs_file="${1:-inputs.yaml}"
31+
32+
# Look for the inputs file if it exists
33+
if [ ! -f "${inputs_file}" ]; then
34+
return 1
35+
fi
36+
37+
echo "→ Loading configuration from ${inputs_file}"
38+
39+
# Load and export the environment variables from the inputs file
40+
while IFS='=' read -r key value; do
41+
if [ -n "${key}" ] && [ -n "${value}" ]; then
42+
export "${key}"="${value}"
43+
fi
44+
done < <(yq eval '.environmentVariables | to_entries | .[] | .key + "=" + .value' "${inputs_file}" 2>/dev/null)
45+
46+
return 0
47+
}
48+
49+
# Loads the command line arguments from the inputs yaml file
50+
load_inputs_yaml_args_inline() {
51+
local inputs_file="${1:-inputs.yaml}"
52+
53+
# Look for the inputs file if it exists
54+
if [ ! -f "${inputs_file}" ]; then
55+
return 1
56+
fi
57+
58+
# Load the command line arguments from the inputs file
59+
readarray -t LOADED_ARGS < <(yq eval '.commandLineArguments[]' "${inputs_file}" 2>/dev/null)
60+
61+
return 0
62+
}
63+
64+
# Try to load inputs.yaml if it exists
65+
LOADED_ARGS=()
66+
if load_inputs_yaml_inline "inputs.yaml"; then
67+
load_inputs_yaml_args_inline "inputs.yaml"
68+
fi
69+
70+
# =============================================================================
71+
# STEP 2: ENVIRONMENT SETUP
72+
# =============================================================================
73+
74+
# Set up paths
75+
export TEST_ROOT="$(pwd)"
76+
export SCRIPT_LIB_DIR="${TEST_ROOT}/../lib"
77+
export CACHE_DIR="${CACHE_DIR:-/srv/cache}"
78+
export IMAGES_YAML="${TEST_ROOT}/images.yaml"
79+
80+
# Test configuration
81+
export TEST_TYPE="echo"
82+
export WORKERS="${WORKERS:-$(nproc)}"
83+
export DEBUG="${DEBUG:-false}"
84+
85+
# Filter configuration
86+
export IMPL_SELECT="${IMPL_SELECT:-}"
87+
export IMPL_IGNORE="${IMPL_IGNORE:-}"
88+
export TRANSPORT_SELECT="${TRANSPORT_SELECT:-}"
89+
export TRANSPORT_IGNORE="${TRANSPORT_IGNORE:-}"
90+
export SECURE_SELECT="${SECURE_SELECT:-}"
91+
export SECURE_IGNORE="${SECURE_IGNORE:-}"
92+
export MUXER_SELECT="${MUXER_SELECT:-}"
93+
export MUXER_IGNORE="${MUXER_IGNORE:-}"
94+
export TEST_SELECT="${TEST_SELECT:-}"
95+
export TEST_IGNORE="${TEST_IGNORE:-}"
96+
97+
# =============================================================================
98+
# STEP 3: ARGUMENT PARSING
99+
# =============================================================================
100+
101+
# Merge loaded args with command line args (command line takes precedence)
102+
ALL_ARGS=("${LOADED_ARGS[@]}" "$@")
103+
104+
# Parse arguments
105+
while [[ $# -gt 0 ]]; do
106+
case $1 in
107+
--impl-select)
108+
IMPL_SELECT="$2"
109+
shift 2
110+
;;
111+
--impl-ignore)
112+
IMPL_IGNORE="$2"
113+
shift 2
114+
;;
115+
--transport-select)
116+
TRANSPORT_SELECT="$2"
117+
shift 2
118+
;;
119+
--transport-ignore)
120+
TRANSPORT_IGNORE="$2"
121+
shift 2
122+
;;
123+
--secure-select)
124+
SECURE_SELECT="$2"
125+
shift 2
126+
;;
127+
--secure-ignore)
128+
SECURE_IGNORE="$2"
129+
shift 2
130+
;;
131+
--muxer-select)
132+
MUXER_SELECT="$2"
133+
shift 2
134+
;;
135+
--muxer-ignore)
136+
MUXER_IGNORE="$2"
137+
shift 2
138+
;;
139+
--test-select)
140+
TEST_SELECT="$2"
141+
shift 2
142+
;;
143+
--test-ignore)
144+
TEST_IGNORE="$2"
145+
shift 2
146+
;;
147+
--workers)
148+
WORKERS="$2"
149+
shift 2
150+
;;
151+
--debug)
152+
DEBUG="true"
153+
shift
154+
;;
155+
--check-deps)
156+
exec "${SCRIPT_LIB_DIR}/check-dependencies.sh"
157+
;;
158+
--help|-h)
159+
echo "Echo Protocol Interoperability Tests"
160+
echo ""
161+
echo "Usage: $0 [options]"
162+
echo ""
163+
echo "Filtering Options:"
164+
echo " --impl-select FILTER Select implementations (e.g., 'js-libp2p')"
165+
echo " --impl-ignore FILTER Ignore implementations (e.g., '!py-libp2p')"
166+
echo " --transport-select FILTER Select transports (e.g., 'tcp')"
167+
echo " --transport-ignore FILTER Ignore transports"
168+
echo " --secure-select FILTER Select secure channels (e.g., 'noise')"
169+
echo " --secure-ignore FILTER Ignore secure channels"
170+
echo " --muxer-select FILTER Select muxers (e.g., 'yamux')"
171+
echo " --muxer-ignore FILTER Ignore muxers"
172+
echo " --test-select FILTER Select specific tests"
173+
echo " --test-ignore FILTER Ignore specific tests"
174+
echo ""
175+
echo "Execution Options:"
176+
echo " --workers N Number of parallel workers (default: $(nproc))"
177+
echo " --debug Enable debug output"
178+
echo ""
179+
echo "Utility Options:"
180+
echo " --check-deps Check system dependencies"
181+
echo " --help, -h Show this help"
182+
echo ""
183+
echo "Examples:"
184+
echo " $0 # Run all tests"
185+
echo " $0 --impl-select js-libp2p # Test only js-libp2p"
186+
echo " $0 --transport-ignore '!tcp' # Test only TCP transport"
187+
echo " $0 --debug --workers 1 # Debug mode, single worker"
188+
exit 0
189+
;;
190+
*)
191+
echo "Unknown option: $1" >&2
192+
echo "Use --help for usage information" >&2
193+
exit 1
194+
;;
195+
esac
196+
done
197+
198+
# =============================================================================
199+
# STEP 4: DEPENDENCY CHECKS
200+
# =============================================================================
201+
202+
# Source common libraries
203+
source "${SCRIPT_LIB_DIR}/lib-common-init.sh"
204+
source "${SCRIPT_LIB_DIR}/lib-output-formatting.sh"
205+
206+
# Check dependencies
207+
"${SCRIPT_LIB_DIR}/check-dependencies.sh" || exit 1
208+
209+
# =============================================================================
210+
# STEP 5: GENERATE INPUTS.YAML
211+
# =============================================================================
212+
213+
source "${SCRIPT_LIB_DIR}/lib-inputs-yaml.sh"
214+
generate_inputs_yaml "${TEST_ROOT}/inputs.yaml" "${TEST_TYPE}" "${ORIGINAL_ARGS[@]}"
215+
216+
# =============================================================================
217+
# STEP 6: GENERATE TEST MATRIX
218+
# =============================================================================
219+
220+
print_message "Generating Echo protocol test matrix..."
221+
"${TEST_ROOT}/lib/generate-tests.sh"
222+
223+
# =============================================================================
224+
# STEP 7: BUILD IMAGES
225+
# =============================================================================
226+
227+
print_message "Building Docker images..."
228+
source "${SCRIPT_LIB_DIR}/lib-image-building.sh"
229+
build_all_images
230+
231+
# =============================================================================
232+
# STEP 8: GENERATE DOCKER COMPOSE FILES
233+
# =============================================================================
234+
235+
print_message "Generating Docker Compose files..."
236+
source "${SCRIPT_LIB_DIR}/lib-test-caching.sh"
237+
238+
CACHE_KEY=$(compute_test_cache_key)
239+
TEST_MATRIX_FILE="${CACHE_DIR}/test-matrix/echo-${CACHE_KEY}.yaml"
240+
241+
# Generate compose files for each test
242+
while IFS= read -r test_name; do
243+
COMPOSE_FILE="${CACHE_DIR}/test-docker-compose/echo-${CACHE_KEY}-${test_name}.yaml"
244+
mkdir -p "$(dirname "${COMPOSE_FILE}")"
245+
246+
# Generate basic compose file (simplified for echo tests)
247+
cat > "${COMPOSE_FILE}" << EOF
248+
version: '3.8'
249+
services:
250+
redis:
251+
image: redis:alpine
252+
networks:
253+
- echo-test
254+
255+
server:
256+
image: \${SERVER_IMAGE}
257+
depends_on:
258+
- redis
259+
environment:
260+
- REDIS_ADDR=redis://redis:6379
261+
networks:
262+
- echo-test
263+
264+
client:
265+
image: \${CLIENT_IMAGE}
266+
depends_on:
267+
- server
268+
environment:
269+
- REDIS_ADDR=redis://redis:6379
270+
networks:
271+
- echo-test
272+
273+
networks:
274+
echo-test:
275+
driver: bridge
276+
EOF
277+
done < <(yq eval '.tests[].name' "${TEST_MATRIX_FILE}")
278+
279+
# =============================================================================
280+
# STEP 9: RUN TESTS
281+
# =============================================================================
282+
283+
print_message "Running Echo protocol tests..."
284+
285+
# Create results directory
286+
RESULTS_DIR="${TEST_ROOT}/results"
287+
mkdir -p "${RESULTS_DIR}"
288+
289+
# Run tests in parallel
290+
export -f run_single_test
291+
readarray -t test_names < <(yq eval '.tests[].name' "${TEST_MATRIX_FILE}")
292+
293+
if [[ "${WORKERS}" -eq 1 ]] || [[ "${DEBUG}" == "true" ]]; then
294+
# Sequential execution for debugging
295+
for test_name in "${test_names[@]}"; do
296+
run_single_test "${test_name}"
297+
done
298+
else
299+
# Parallel execution
300+
printf '%s\n' "${test_names[@]}" | xargs -P "${WORKERS}" -I {} bash -c 'run_single_test "$@"' _ {}
301+
fi
302+
303+
# =============================================================================
304+
# STEP 10: GENERATE DASHBOARD
305+
# =============================================================================
306+
307+
print_message "Generating test dashboard..."
308+
"${TEST_ROOT}/lib/generate-dashboard.sh" "${RESULTS_DIR}"
309+
310+
# =============================================================================
311+
# STEP 11: SUMMARY
312+
# =============================================================================
313+
314+
TOTAL_TESTS=$(find "${RESULTS_DIR}" -name "*.json" | wc -l)
315+
PASSED_TESTS=$(find "${RESULTS_DIR}" -name "*.json" -exec grep -l '"result": "PASS"' {} \; | wc -l)
316+
FAILED_TESTS=$((TOTAL_TESTS - PASSED_TESTS))
317+
318+
print_message "Echo Protocol Test Results:"
319+
print_message " Total: ${TOTAL_TESTS}"
320+
print_message " Passed: ${PASSED_TESTS}"
321+
print_message " Failed: ${FAILED_TESTS}"
322+
323+
if [[ "${FAILED_TESTS}" -gt 0 ]]; then
324+
print_message "❌ Some tests failed - check ${RESULTS_DIR}/echo-dashboard.html"
325+
exit 1
326+
else
327+
print_message "✅ All tests passed!"
328+
exit 0
329+
fi
10330

11-
# Source the test-plans library functions
12-
source "${ROOT_DIR}/lib/lib-common-init.sh"
13-
source "${ROOT_DIR}/lib/lib-test-execution.sh"
331+
# =============================================================================
332+
# HELPER FUNCTIONS
333+
# =============================================================================
14334

15-
# Run echo protocol tests using existing framework
16-
exec "${ROOT_DIR}/lib/lib-test-execution.sh" \
17-
--test-dir "${SCRIPT_DIR}" \
18-
--images-file "${SCRIPT_DIR}/images.yaml" \
19-
"$@"
335+
run_single_test() {
336+
local test_name="$1"
337+
"${TEST_ROOT}/lib/run-single-test.sh" "${test_name}" > "${RESULTS_DIR}/${test_name}.json"
338+
}

0 commit comments

Comments
 (0)