#!/bin/bash # Test utilities for DataBuild end-to-end tests set -euo pipefail # Logging functions (no colors for simplicity) log_info() { printf "[INFO] %s\n" "$1" } log_warn() { printf "[WARN] %s\n" "$1" } log_error() { printf "[ERROR] %s\n" "$1" } # Test result functions test_pass() { log_info "TEST PASSED: $1" } test_fail() { log_error "TEST FAILED: $1" exit 1 } # Create test directory with cleanup create_test_dir() { local test_dir="$1" mkdir -p "$test_dir" trap "cleanup_test_dir '$test_dir'" EXIT echo "$test_dir" } cleanup_test_dir() { local test_dir="$1" if [[ -d "$test_dir" ]]; then rm -rf "$test_dir" fi } # Wait for a service to be ready wait_for_service() { local url="$1" local timeout="${2:-30}" local count=0 while ! curl -sf "$url" > /dev/null 2>&1; do if [[ $count -ge $timeout ]]; then log_error "Service at $url did not become ready within $timeout seconds" return 1 fi sleep 1 ((count++)) done log_info "Service at $url is ready" >&2 } # Kill process and wait for it to exit kill_and_wait() { local pid="$1" local timeout="${2:-10}" if kill -0 "$pid" 2>/dev/null; then kill "$pid" 2>/dev/null || true local count=0 while kill -0 "$pid" 2>/dev/null; do if [[ $count -ge $timeout ]]; then log_warn "Process $pid did not exit gracefully, sending SIGKILL" kill -9 "$pid" 2>/dev/null || true break fi sleep 1 ((count++)) done fi } # Find available port find_available_port() { local port port=$(python3 -c " import socket sock = socket.socket() sock.bind(('', 0)) port = sock.getsockname()[1] sock.close() print(port) ") echo "$port" } # Compare two files ignoring timestamps and random values compare_files_flexible() { local file1="$1" local file2="$2" # Create temporary files with normalized content local temp1=$(mktemp) local temp2=$(mktemp) # Remove timestamps and normalize random values sed -E 's/[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}[.0-9]*Z?/TIMESTAMP/g' "$file1" > "$temp1" sed -E 's/[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}[.0-9]*Z?/TIMESTAMP/g' "$file2" > "$temp2" # Compare normalized files local result=0 if ! diff -q "$temp1" "$temp2" > /dev/null 2>&1; then result=1 fi # Cleanup rm -f "$temp1" "$temp2" return $result } # HTTP request helper http_request() { local method="$1" local url="$2" local data="${3:-}" if [[ -n "$data" ]]; then curl -s -X "$method" \ -H "Content-Type: application/json" \ -d "$data" \ "$url" else curl -s -X "$method" "$url" fi } # Run command with timeout run_with_timeout() { local timeout_secs="$1" shift # Check if timeout command is available if command -v timeout > /dev/null 2>&1; then timeout "$timeout_secs" "$@" else # Fallback: just run the command without timeout on macOS "$@" fi } # Check if file exists and is not empty check_file_exists() { local file="$1" if [[ ! -f "$file" ]]; then log_error "File does not exist: $file" return 1 fi if [[ ! -s "$file" ]]; then log_error "File is empty: $file" return 1 fi return 0 } # Setup test environment setup_test_env() { local test_name="$1" local test_dir="/tmp/databuild_test_${test_name}_$$" # Create test directory mkdir -p "$test_dir" # Set environment variables export DATABUILD_TEST_DIR="$test_dir" export DATABUILD_TEST_NAME="$test_name" log_info "Test environment setup: $test_dir" >&2 echo "$test_dir" } # Assert that two values are equal assert_equal() { local expected="$1" local actual="$2" local message="${3:-Values are not equal}" if [[ "$expected" != "$actual" ]]; then log_error "$message: expected '$expected', got '$actual'" return 1 fi } # Assert that value is not empty assert_not_empty() { local value="$1" local message="${2:-Value is empty}" if [[ -z "$value" ]]; then log_error "$message" return 1 fi } # Extract JSON value using jq extract_json_value() { local json="$1" local path="$2" echo "$json" | jq -r "$path" } # Count lines in file count_lines() { local file="$1" wc -l < "$file" | tr -d ' ' } # Check if all processes in list are running check_processes_running() { local pids="$@" for pid in $pids; do if ! kill -0 "$pid" 2>/dev/null; then log_error "Process $pid is not running" return 1 fi done return 0 }