Commit 731b74db authored by Connor Baker's avatar Connor Baker
Browse files

testers.testEqualArrayOrMap: use buildCommandPath and change checkSetupScript argument to script

parent 261693fe
Loading
Loading
Loading
Loading
+22 −22
Original line number Diff line number Diff line
@@ -351,7 +351,7 @@ testers.testEqualContents {

Check that bash arrays (including associative arrays, referred to as "maps") are populated correctly.

This can be used to ensure setup hooks are registered in a certain order, or write unit tests for shell functions which transform arrays.
This can be used to ensure setup hooks are registered in a certain order, or to write unit tests for shell functions which transform arrays.

:::{.example #ex-testEqualArrayOrMap-test-function-add-cowbell}

@@ -369,7 +369,7 @@ testers.testEqualArrayOrMap {
    "cowbell"
    "cowbell"
  ];
  checkSetupScript = ''
  script = ''
    addCowbell() {
      local -rn arrayNameRef="$1"
      arrayNameRef+=( "cowbell" )
@@ -390,8 +390,8 @@ testers.testEqualArrayOrMap {

### Inputs {#tester-testEqualArrayOrMap-inputs}

NOTE: Internally, this tester uses `__structuredAttrs` to handle marhsalling between Nix expressions and shell variables.
This imposes the restriction that arrays and "maps" have values which are string-coercible.
NOTE: Internally, this tester uses `__structuredAttrs` to handle marshalling between Nix expressions and shell variables.
This imposes the restriction that arrays and "maps" have values which are string-like.

NOTE: At least one of `expectedArray` and `expectedMap` must be provided.

@@ -399,39 +399,39 @@ NOTE: At least one of `expectedArray` and `expectedMap` must be provided.

: The name of the test.

`checkSetupScript` (string)
`script` (string)

: The singular task of `checkSetupScript` is to populate `actualArray` or `actualMap` (it may populate both).
  To do this, checkSetupScript may access the following shell variables:
: The singular task of `script` is to populate `actualArray` or `actualMap` (it may populate both).
  To do this, `script` may access the following shell variables:

  - `valuesArray`
  - `valuesMap`
  - `actualArray`
  - `actualMap`
  - `valuesArray` (available when `valuesArray` is provided to the tester)
  - `valuesMap` (available when `valuesMap` is provided to the tester)
  - `actualArray` (available when `expectedArray` is provided to the tester)
  - `actualMap` (available when `expectedMap` is provided to the tester)

  While both `expectedArray` and `expectedMap` are in scope during the execution of `checkSetupScript`, they *must not* be accessed or modified from within `checkSetupScript`.
  While both `expectedArray` and `expectedMap` are in scope during the execution of `script`, they *must not* be accessed or modified from within `script`.

`valuesArray` (array of string-like values, optional)

: An array of string-coercible values.
  This array may be used within `checkSetupScript`.
: An array of string-like values.
  This array may be used within `script`.

`valuesMap` (attribute set of string-like values, optional)

: An attribute set of string-coercible values.
  This attribute set may be used within `checkSetupScript`.
: An attribute set of string-like values.
  This attribute set may be used within `script`.

`expectedArray` (array of string-like values, optional)

: An array of string-coercible values.
  This array *must not* be accessed or modified from within `checkSetupScript`.
  When provided, `checkSetupScript` is expected to populate `actualArray`.
: An array of string-like values.
  This array *must not* be accessed or modified from within `script`.
  When provided, `script` is expected to populate `actualArray`.

`expectedMap` (attribute set of string-like values, optional)

: An attribute set of string-coercible values.
  This attribute set *must not* be accessed or modified from within `checkSetupScript`.
  When provided, `checkSetupScript` is expected to populate `actualMap`.
: An attribute set of string-like values.
  This attribute set *must not* be accessed or modified from within `script`.
  When provided, `script` is expected to populate `actualMap`.

### Return value {#tester-testEqualArrayOrMap-return}

+1 −1
Original line number Diff line number Diff line
@@ -72,7 +72,7 @@
  # See https://nixos.org/manual/nixpkgs/unstable/#tester-testEqualArrayOrMap
  # or doc/build-helpers/testers.chapter.md
  # NOTE: Must be `import`-ed rather than `callPackage`-d to preserve the `override` attribute.
  testEqualArrayOrMap = import ./testEqualArrayOrMap/tester.nix { inherit lib runCommand; };
  testEqualArrayOrMap = import ./testEqualArrayOrMap/tester.nix { inherit lib stdenvNoCC; };

  # See https://nixos.org/manual/nixpkgs/unstable/#tester-testVersion
  # or doc/build-helpers/testers.chapter.md
+10 −4
Original line number Diff line number Diff line
# 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() {
@@ -12,13 +18,13 @@ assertEqualArray() {
  local -nr expectedArrayRef="$1"
  local -nr actualArrayRef="$2"

  if [[ ! ${expectedArrayRef@a} =~ a ]]; then
    nixErrorLog "first arugment expectedArrayRef must be an array reference"
  if ! isDeclaredArray expectedArrayRef; then
    nixErrorLog "first arugment expectedArrayRef must be an array reference to a declared array"
    exit 1
  fi

  if [[ ! ${actualArrayRef@a} =~ a ]]; then
    nixErrorLog "second arugment actualArrayRef must be an array reference"
  if ! isDeclaredArray actualArrayRef; then
    nixErrorLog "second arugment actualArrayRef must be an array reference to a declared array"
    exit 1
  fi

+10 −4
Original line number Diff line number Diff line
# 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() {
@@ -12,13 +18,13 @@ assertEqualMap() {
  local -nr expectedMapRef="$1"
  local -nr actualMapRef="$2"

  if [[ ! ${expectedMapRef@a} =~ A ]]; then
    nixErrorLog "first arugment expectedMapRef must be an associative array reference"
  if ! isDeclaredMap expectedMapRef; then
    nixErrorLog "first arugment expectedMapRef must be an associative array reference to a declared associative array"
    exit 1
  fi

  if [[ ! ${actualMapRef@a} =~ A ]]; then
    nixErrorLog "second arugment actualMapRef must be an associative array reference"
  if ! isDeclaredMap actualMapRef; then
    nixErrorLog "second arugment actualMapRef must be an associative array reference to a declared associative array"
    exit 1
  fi

+64 −0
Original line number Diff line number Diff line
# shellcheck shell=bash

set -eu

preScript() {
  # If neither expectedArray nor expectedMap are declared, the test is meaningless.
  if ! isDeclaredArray expectedArray && ! isDeclaredMap expectedMap; then
    nixErrorLog "neither expectedArray nor expectedMap were set, so test is meaningless!"
    exit 1
  fi

  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:?}"
Loading