master
sh 289 lines 10.2 KB
Raw
1 #!/usr/bin/env bash
2
3 # Improved log2journal test framework with .cmd and .fail support
4
5 set -e
6
7 # Parse command line arguments
8 VERBOSE=false
9 SPECIFIC_TEST=""
10
11 while [[ $# -gt 0 ]]; do
12 case $1 in
13 --verbose)
14 VERBOSE=true
15 shift
16 ;;
17 --test)
18 SPECIFIC_TEST="$2"
19 shift 2
20 ;;
21 -h|--help)
22 echo "Usage: $0 [OPTIONS]"
23 echo "Options:"
24 echo " --verbose Show exact commands and full diff output"
25 echo " --test NAME Run only the specified test"
26 echo " --help Show this help message"
27 echo ""
28 echo "Environment variables:"
29 echo " TESTED_LOG2JOURNAL_BIN Path to log2journal binary (default: log2journal)"
30 exit 0
31 ;;
32 *)
33 echo "Unknown option: $1"
34 echo "Use --help for usage information"
35 exit 1
36 ;;
37 esac
38 done
39
40 TEST_DIR="tests.d"
41 RESULTS_DIR="/tmp/log2journal_test_results"
42
43 # Use installed log2journal by default, allow override via environment variable
44 if [ -z "${TESTED_LOG2JOURNAL_BIN}" -a ! -z "${LOG2JOURNAL}" ]; then
45 export TESTED_LOG2JOURNAL_BIN="${LOG2JOURNAL}"
46 fi
47 if [ -z "$TESTED_LOG2JOURNAL_BIN" ]; then
48 export TESTED_LOG2JOURNAL_BIN="log2journal"
49 fi
50
51 echo "log2journal cmd: ${TESTED_LOG2JOURNAL_BIN}"
52
53 # Colors for output
54 GREEN='\033[0;32m'
55 RED='\033[0;31m'
56 YELLOW='\033[0;33m'
57 NC='\033[0m' # No Color
58
59 # Counters
60 TESTS_RUN=0
61 TESTS_PASSED=0
62 TESTS_FAILED=0
63 TESTS_IGNORED=0
64
65 # Create results directory
66 mkdir -p "$RESULTS_DIR"
67
68 # Execute a test command with proper input redirection.
69 # For .cmd files, eval is required since they may contain pipes/operators.
70 # For standard commands, the command array is invoked directly (no eval).
71 # Args: input_file use_cmd_file cmd_str_or_empty cmd_args...
72 _exec_with_input() {
73 local input="$1"
74 local use_eval="$2"
75 local cmd_str="$3"
76 shift 3
77
78 if [ "$use_eval" = true ]; then
79 if [ -f "$input" ]; then
80 eval "$cmd_str" < "$input"
81 else
82 eval "$cmd_str" < /dev/null
83 fi
84 else
85 if [ -f "$input" ]; then
86 "$@" < "$input"
87 else
88 "$@" < /dev/null
89 fi
90 fi
91 }
92
93 # Function to run a single test
94 run_test() {
95 local test_name="$1"
96 local yaml_file="$2"
97 local input_file="$3"
98 local expected_output="$4"
99 local expected_config="$5"
100 local cmd_file="$6"
101 local fail_file="$7"
102
103 TESTS_RUN=$((TESTS_RUN + 1))
104 local test_passed=true
105 local error_msg=""
106
107 # Determine command to run.
108 # For .cmd files: use eval (they may contain pipes/operators).
109 # For standard cases: use an array to avoid eval entirely.
110 local use_cmd_file=false
111 local cmd_str=""
112 local cmd_args=()
113 if [ -f "$cmd_file" ]; then
114 use_cmd_file=true
115 cmd_str=$(envsubst < "$cmd_file")
116 elif [ -f "$yaml_file" ]; then
117 cmd_args=("$TESTED_LOG2JOURNAL_BIN" -f "$yaml_file")
118 else
119 # Internal config test (extract config name from test_name)
120 if [[ "$test_name" =~ ^(default|nginx-combined|nginx-json|logfmt)$ ]]; then
121 cmd_args=("$TESTED_LOG2JOURNAL_BIN" -c "$test_name")
122 else
123 echo -e "${YELLOW}IGNORED${NC} (no config or cmd file)"
124 TESTS_IGNORED=$((TESTS_IGNORED + 1))
125 return
126 fi
127 fi
128
129 if [ "$VERBOSE" = true ]; then
130 echo "Running test: $test_name"
131 if [ "$use_cmd_file" = true ]; then
132 echo " Command: $cmd_str < ${input_file}"
133 else
134 echo " Command: ${cmd_args[*]} < ${input_file}"
135 fi
136 else
137 echo -n "Running test: $test_name ... "
138 fi
139
140 # Check if this is a failure test
141 if [ -f "$fail_file" ]; then
142 # Test should fail
143 local actual_error="$RESULTS_DIR/${test_name}.err"
144 if _exec_with_input "$input_file" "$use_cmd_file" "$cmd_str" "${cmd_args[@]}" > /dev/null 2> "$actual_error"; then
145 test_passed=false
146 error_msg="Test was expected to fail but succeeded"
147 else
148 # Command failed as expected, check error message if fail file has content
149 if [ -s "$fail_file" ]; then
150 if ! grep -qF "$(cat "$fail_file")" "$actual_error"; then
151 test_passed=false
152 error_msg="Error message mismatch - see $actual_error vs $fail_file"
153 fi
154 fi
155 fi
156 else
157 # Normal test - check output
158 if [ -f "$expected_output" ]; then
159 local actual_output="$RESULTS_DIR/${test_name}.out"
160
161 if ! _exec_with_input "$input_file" "$use_cmd_file" "$cmd_str" "${cmd_args[@]}" > "$actual_output" 2> "$RESULTS_DIR/${test_name}.err"; then
162 test_passed=false
163 error_msg="Command failed with non-zero exit code - see $RESULTS_DIR/${test_name}.err"
164 else
165 # Only check output if command succeeded
166 # For help/error output tests, ignore version lines to avoid build-dependent failures
167 if [[ "$test_name" =~ ^error- ]] && grep -q "^Netdata log2journal v" "$expected_output"; then
168 # Version-agnostic comparison for error tests
169 grep -v "^Netdata log2journal v" "$expected_output" > "$RESULTS_DIR/${test_name}.expected_no_version"
170 grep -v "^Netdata log2journal v" "$actual_output" > "$RESULTS_DIR/${test_name}.actual_no_version"
171 if ! diff -u "$RESULTS_DIR/${test_name}.expected_no_version" "$RESULTS_DIR/${test_name}.actual_no_version" > "$RESULTS_DIR/${test_name}.diff" 2>&1; then
172 test_passed=false
173 if [ "$VERBOSE" = true ]; then
174 error_msg="Output mismatch (version-agnostic):\n$(cat "$RESULTS_DIR/${test_name}.diff")"
175 else
176 error_msg="Output mismatch (version-agnostic) - see $RESULTS_DIR/${test_name}.diff"
177 fi
178 fi
179
180 # Also verify version format is correct
181 if ! grep -q "^Netdata log2journal v[0-9]\+\.[0-9]\+\.[0-9]\+-[0-9]\+-g[a-f0-9]\+$" "$actual_output"; then
182 test_passed=false
183 error_msg="$error_msg\nVersion format is incorrect"
184 fi
185 else
186 # Normal comparison for non-version-dependent tests
187 if ! diff -u "$expected_output" "$actual_output" > "$RESULTS_DIR/${test_name}.diff" 2>&1; then
188 test_passed=false
189 if [ "$VERBOSE" = true ]; then
190 error_msg="Output mismatch:\n$(cat "$RESULTS_DIR/${test_name}.diff")"
191 else
192 error_msg="Output mismatch - see $RESULTS_DIR/${test_name}.diff"
193 fi
194 fi
195 fi
196 fi
197 fi
198
199 # Check config output if expected
200 if [ -f "$expected_config" ]; then
201 local actual_config="$RESULTS_DIR/${test_name}-config.yaml"
202
203 if [ "$use_cmd_file" = true ]; then
204 if [ -f "$input_file" ]; then
205 eval "$cmd_str --show-config" < "$input_file" 2>/dev/null | sed '1,/^$/d' > "$actual_config" || true
206 else
207 eval "$cmd_str --show-config" < /dev/null 2>/dev/null | sed '1,/^$/d' > "$actual_config" || true
208 fi
209 else
210 if [ -f "$input_file" ]; then
211 "${cmd_args[@]}" --show-config < "$input_file" 2>/dev/null | sed '1,/^$/d' > "$actual_config" || true
212 else
213 "${cmd_args[@]}" --show-config < /dev/null 2>/dev/null | sed '1,/^$/d' > "$actual_config" || true
214 fi
215 fi
216
217 if ! diff -u "$expected_config" "$actual_config" > "$RESULTS_DIR/${test_name}-config.diff" 2>&1; then
218 test_passed=false
219 if [ "$VERBOSE" = true ]; then
220 error_msg="$error_msg\nConfig mismatch:\n$(cat "$RESULTS_DIR/${test_name}-config.diff")"
221 else
222 error_msg="$error_msg\nConfig mismatch - see $RESULTS_DIR/${test_name}-config.diff"
223 fi
224 fi
225 fi
226 fi
227
228 # Report result
229 if [ "$test_passed" = true ]; then
230 echo -e "${GREEN}PASSED${NC}"
231 TESTS_PASSED=$((TESTS_PASSED + 1))
232 else
233 echo -e "${RED}FAILED${NC}"
234 echo -e "$error_msg"
235 TESTS_FAILED=$((TESTS_FAILED + 1))
236 fi
237 }
238
239 # Main test loop
240 echo "Starting log2journal unit tests (v2 framework)..."
241 echo "================================"
242
243 # Find all unique test names by looking for any test files
244 if [ -n "$SPECIFIC_TEST" ]; then
245 test_names="$SPECIFIC_TEST"
246 echo "Running specific test: $SPECIFIC_TEST"
247 else
248 test_names=$(find "$TEST_DIR" -name "*.yaml" -o -name "*.input" -o -name "*.output" -o -name "*.cmd" -o -name "*.fail" -o -name "*-final-config.yaml" | \
249 sed -E 's/.*\/([^\/]+)\.(yaml|input|output|cmd|fail|-final-config\.yaml)$/\1/' | \
250 sed 's/-final-config$//' | \
251 sort -u)
252 fi
253
254 for test_name in $test_names; do
255 # Check what files exist for this test
256 yaml_file="$TEST_DIR/${test_name}.yaml"
257 input_file="$TEST_DIR/${test_name}.input"
258 output_file="$TEST_DIR/${test_name}.output"
259 config_file="$TEST_DIR/${test_name}-final-config.yaml"
260 cmd_file="$TEST_DIR/${test_name}.cmd"
261 fail_file="$TEST_DIR/${test_name}.fail"
262
263 # Check if test has any actual test files
264 if [ ! -f "$output_file" ] && [ ! -f "$config_file" ] && [ ! -f "$fail_file" ]; then
265 echo "Warning: Test $test_name has no expected output, config, or fail files, skipping"
266 TESTS_IGNORED=$((TESTS_IGNORED + 1))
267 continue
268 fi
269
270 run_test "$test_name" "$yaml_file" "$input_file" "$output_file" "$config_file" "$cmd_file" "$fail_file"
271 done
272
273 # Summary
274 echo "================================"
275 echo "Test Summary:"
276 echo " Total tests run: $TESTS_RUN"
277 echo -e " Passed: ${GREEN}$TESTS_PASSED${NC}"
278 echo -e " Failed: ${RED}$TESTS_FAILED${NC}"
279 if [ $TESTS_IGNORED -gt 0 ]; then
280 echo -e " Ignored: ${YELLOW}$TESTS_IGNORED${NC}"
281 fi
282
283 if [ $TESTS_FAILED -gt 0 ]; then
284 echo -e "\n${RED}TESTS FAILED${NC}"
285 exit 1
286 else
287 echo -e "\n${GREEN}ALL TESTS PASSED${NC}"
288 exit 0
289 fi