1# shellcheck shell=bash
2
3# Asserts that two arrays are equal, printing out differences if they are not.
4# Does not short circuit on the first difference.
5assertEqualArray() {
6 if (($# != 2)); then
7 nixErrorLog "expected two arguments!"
8 nixErrorLog "usage: assertEqualArray expectedArrayRef actualArrayRef"
9 exit 1
10 fi
11
12 local -nr expectedArrayRef="$1"
13 local -nr actualArrayRef="$2"
14
15 if ! isDeclaredArray "${!expectedArrayRef}"; then
16 nixErrorLog "first argument expectedArrayRef must be a reference to an indexed array"
17 exit 1
18 fi
19
20 if ! isDeclaredArray "${!actualArrayRef}"; then
21 nixErrorLog "second argument actualArrayRef must be a reference to an indexed array"
22 exit 1
23 fi
24
25 local -ir expectedLength=${#expectedArrayRef[@]}
26 local -ir actualLength=${#actualArrayRef[@]}
27
28 local -i hasDiff=0
29
30 if ((expectedLength != actualLength)); then
31 nixErrorLog "arrays differ in length: expectedArray has length $expectedLength but actualArray has length $actualLength"
32 hasDiff=1
33 fi
34
35 local -i idx=0
36 local expectedValue
37 local actualValue
38
39 # We iterate so long as at least one array has indices we've not considered.
40 # This means that `idx` is a valid index to *at least one* of the arrays.
41 for ((idx = 0; idx < expectedLength || idx < actualLength; idx++)); do
42 # Update values for variables which are still in range/valid.
43 if ((idx < expectedLength)); then
44 expectedValue="${expectedArrayRef[idx]}"
45 fi
46
47 if ((idx < actualLength)); then
48 actualValue="${actualArrayRef[idx]}"
49 fi
50
51 # Handle comparisons.
52 if ((idx >= expectedLength)); then
53 nixErrorLog "arrays differ at index $idx: expectedArray has no such index but actualArray has value ${actualValue@Q}"
54 hasDiff=1
55 elif ((idx >= actualLength)); then
56 nixErrorLog "arrays differ at index $idx: expectedArray has value ${expectedValue@Q} but actualArray has no such index"
57 hasDiff=1
58 elif [[ $expectedValue != "$actualValue" ]]; then
59 nixErrorLog "arrays differ at index $idx: expectedArray has value ${expectedValue@Q} but actualArray has value ${actualValue@Q}"
60 hasDiff=1
61 fi
62 done
63
64 ((hasDiff)) && exit 1 || return 0
65}