-
-
Notifications
You must be signed in to change notification settings - Fork 15k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'feat/testEqualArrayOrMap' into feat/testEqualArrayOrMap…
…-uses-testBuildFailurePrime
- Loading branch information
Showing
9 changed files
with
668 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
71 changes: 71 additions & 0 deletions
71
pkgs/build-support/testers/testEqualArrayOrMap/assert-equal-array.sh
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
# shellcheck shell=bash | ||
|
||
# Tests if an array is declared. | ||
isDeclaredArray() { | ||
# shellcheck disable=SC2034 | ||
local -nr arrayRef="$1" && [[ ${!arrayRef@a} =~ a ]] | ||
} | ||
|
||
# Asserts that two arrays are equal, printing out differences if they are not. | ||
# Does not short circuit on the first difference. | ||
assertEqualArray() { | ||
if (($# != 2)); then | ||
nixErrorLog "expected two arguments!" | ||
nixErrorLog "usage: assertEqualArray expectedArrayRef actualArrayRef" | ||
exit 1 | ||
fi | ||
|
||
local -nr expectedArrayRef="$1" | ||
local -nr actualArrayRef="$2" | ||
|
||
if ! isDeclaredArray expectedArrayRef; then | ||
nixErrorLog "first arugment expectedArrayRef must be an array reference to a declared array" | ||
exit 1 | ||
fi | ||
|
||
if ! isDeclaredArray actualArrayRef; then | ||
nixErrorLog "second arugment actualArrayRef must be an array reference to a declared array" | ||
exit 1 | ||
fi | ||
|
||
local -ir expectedLength=${#expectedArrayRef[@]} | ||
local -ir actualLength=${#actualArrayRef[@]} | ||
|
||
local -i hasDiff=0 | ||
|
||
if ((expectedLength != actualLength)); then | ||
nixErrorLog "arrays differ in length: expectedArray has length $expectedLength but actualArray has length $actualLength" | ||
hasDiff=1 | ||
fi | ||
|
||
local -i idx=0 | ||
local expectedValue | ||
local actualValue | ||
|
||
# We iterate so long as at least one array has indices we've not considered. | ||
# This means that `idx` is a valid index to *at least one* of the arrays. | ||
for ((idx = 0; idx < expectedLength || idx < actualLength; idx++)); do | ||
# Update values for variables which are still in range/valid. | ||
if ((idx < expectedLength)); then | ||
expectedValue="${expectedArrayRef[idx]}" | ||
fi | ||
|
||
if ((idx < actualLength)); then | ||
actualValue="${actualArrayRef[idx]}" | ||
fi | ||
|
||
# Handle comparisons. | ||
if ((idx >= expectedLength)); then | ||
nixErrorLog "arrays differ at index $idx: expectedArray has no such index but actualArray has value ${actualValue@Q}" | ||
hasDiff=1 | ||
elif ((idx >= actualLength)); then | ||
nixErrorLog "arrays differ at index $idx: expectedArray has value ${expectedValue@Q} but actualArray has no such index" | ||
hasDiff=1 | ||
elif [[ $expectedValue != "$actualValue" ]]; then | ||
nixErrorLog "arrays differ at index $idx: expectedArray has value ${expectedValue@Q} but actualArray has value ${actualValue@Q}" | ||
hasDiff=1 | ||
fi | ||
done | ||
|
||
((hasDiff)) && exit 1 || return 0 | ||
} |
102 changes: 102 additions & 0 deletions
102
pkgs/build-support/testers/testEqualArrayOrMap/assert-equal-map.sh
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
# shellcheck shell=bash | ||
|
||
# Tests if a map is declared. | ||
isDeclaredMap() { | ||
# shellcheck disable=SC2034 | ||
local -nr mapRef="$1" && [[ ${!mapRef@a} =~ A ]] | ||
} | ||
|
||
# Asserts that two maps are equal, printing out differences if they are not. | ||
# Does not short circuit on the first difference. | ||
assertEqualMap() { | ||
if (($# != 2)); then | ||
nixErrorLog "expected two arguments!" | ||
nixErrorLog "usage: assertEqualMap expectedMapRef actualMapRef" | ||
exit 1 | ||
fi | ||
|
||
local -nr expectedMapRef="$1" | ||
local -nr actualMapRef="$2" | ||
|
||
if ! isDeclaredMap expectedMapRef; then | ||
nixErrorLog "first arugment expectedMapRef must be an associative array reference to a declared associative array" | ||
exit 1 | ||
fi | ||
|
||
if ! isDeclaredMap actualMapRef; then | ||
nixErrorLog "second arugment actualMapRef must be an associative array reference to a declared associative array" | ||
exit 1 | ||
fi | ||
|
||
# NOTE: | ||
# From the `sort` manpage: "The locale specified by the environment affects sort order. Set LC_ALL=C to get the | ||
# traditional sort order that uses native byte values." | ||
# We specify the environment variable in a subshell to avoid polluting the caller's environment. | ||
|
||
local -a sortedExpectedKeys | ||
mapfile -d '' -t sortedExpectedKeys < <(printf '%s\0' "${!expectedMapRef[@]}" | LC_ALL=C sort --stable --zero-terminated) | ||
|
||
local -a sortedActualKeys | ||
mapfile -d '' -t sortedActualKeys < <(printf '%s\0' "${!actualMapRef[@]}" | LC_ALL=C sort --stable --zero-terminated) | ||
|
||
local -ir expectedLength=${#expectedMapRef[@]} | ||
local -ir actualLength=${#actualMapRef[@]} | ||
|
||
local -i hasDiff=0 | ||
|
||
if ((expectedLength != actualLength)); then | ||
nixErrorLog "maps differ in length: expectedMap has length $expectedLength but actualMap has length $actualLength" | ||
hasDiff=1 | ||
fi | ||
|
||
local -i expectedKeyIdx=0 | ||
local expectedKey | ||
local expectedValue | ||
local -i actualKeyIdx=0 | ||
local actualKey | ||
local actualValue | ||
|
||
# We iterate so long as at least one map has keys we've not considered. | ||
while ((expectedKeyIdx < expectedLength || actualKeyIdx < actualLength)); do | ||
# Update values for variables which are still in range/valid. | ||
if ((expectedKeyIdx < expectedLength)); then | ||
expectedKey="${sortedExpectedKeys["$expectedKeyIdx"]}" | ||
expectedValue="${expectedMapRef["$expectedKey"]}" | ||
fi | ||
|
||
if ((actualKeyIdx < actualLength)); then | ||
actualKey="${sortedActualKeys["$actualKeyIdx"]}" | ||
actualValue="${actualMapRef["$actualKey"]}" | ||
fi | ||
|
||
# In the case actualKeyIdx is valid and expectedKey comes after actualKey or expectedKeyIdx is invalid, actualMap | ||
# has an extra key relative to expectedMap. | ||
# NOTE: In Bash, && and || have the same precedence, so use the fact they're left-associative to enforce groups. | ||
if ((actualKeyIdx < actualLength)) && [[ $expectedKey > $actualKey ]] || ((expectedKeyIdx >= expectedLength)); then | ||
nixErrorLog "maps differ at key ${actualKey@Q}: expectedMap has no such key but actualMap has value ${actualValue@Q}" | ||
hasDiff=1 | ||
actualKeyIdx+=1 | ||
|
||
# In the case actualKeyIdx is invalid or expectedKey comes before actualKey, expectedMap has an extra key relative | ||
# to actualMap. | ||
# NOTE: By virtue of the previous condition being false, we know the negation is true. Namely, expectedKeyIdx is | ||
# valid AND (actualKeyIdx is invalid OR expectedKey <= actualKey). | ||
elif ((actualKeyIdx >= actualLength)) || [[ $expectedKey < $actualKey ]]; then | ||
nixErrorLog "maps differ at key ${expectedKey@Q}: expectedMap has value ${expectedValue@Q} but actualMap has no such key" | ||
hasDiff=1 | ||
expectedKeyIdx+=1 | ||
|
||
# In the case where both key indices are valid and the keys are equal. | ||
else | ||
if [[ $expectedValue != "$actualValue" ]]; then | ||
nixErrorLog "maps differ at key ${expectedKey@Q}: expectedMap has value ${expectedValue@Q} but actualMap has value ${actualValue@Q}" | ||
hasDiff=1 | ||
fi | ||
|
||
expectedKeyIdx+=1 | ||
actualKeyIdx+=1 | ||
fi | ||
done | ||
|
||
((hasDiff)) && exit 1 || return 0 | ||
} |
61 changes: 61 additions & 0 deletions
61
pkgs/build-support/testers/testEqualArrayOrMap/build-command.sh
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
# shellcheck shell=bash | ||
|
||
set -eu | ||
|
||
# NOTE: If neither expectedArray nor expectedMap are declared, the test is meaningless. | ||
# This precondition is checked in the Nix expression through an assert. | ||
|
||
preScript() { | ||
if isDeclaredArray valuesArray; then | ||
# shellcheck disable=SC2154 | ||
nixLog "using valuesArray: $(declare -p valuesArray)" | ||
fi | ||
|
||
if isDeclaredMap valuesMap; then | ||
# shellcheck disable=SC2154 | ||
nixLog "using valuesMap: $(declare -p valuesMap)" | ||
fi | ||
|
||
if isDeclaredArray expectedArray; then | ||
# shellcheck disable=SC2154 | ||
nixLog "using expectedArray: $(declare -p expectedArray)" | ||
declare -ag actualArray=() | ||
fi | ||
|
||
if isDeclaredMap expectedMap; then | ||
# shellcheck disable=SC2154 | ||
nixLog "using expectedMap: $(declare -p expectedMap)" | ||
declare -Ag actualMap=() | ||
fi | ||
|
||
return 0 | ||
} | ||
|
||
scriptPhase() { | ||
runHook preScript | ||
|
||
runHook script | ||
|
||
runHook postScript | ||
} | ||
|
||
postScript() { | ||
if isDeclaredArray expectedArray; then | ||
nixLog "using actualArray: $(declare -p actualArray)" | ||
nixLog "comparing actualArray against expectedArray" | ||
assertEqualArray expectedArray actualArray | ||
nixLog "actualArray matches expectedArray" | ||
fi | ||
|
||
if isDeclaredMap expectedMap; then | ||
nixLog "using actualMap: $(declare -p actualMap)" | ||
nixLog "comparing actualMap against expectedMap" | ||
assertEqualMap expectedMap actualMap | ||
nixLog "actualMap matches expectedMap" | ||
fi | ||
|
||
return 0 | ||
} | ||
|
||
runHook scriptPhase | ||
touch "${out:?}" |
Oops, something went wrong.