serval-dna/testdefs_json.sh

169 lines
4.5 KiB
Bash

# Common definitions for manipulating JSON in test scripts.
# Copyright 2014 Serval Project Inc.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# Utility function:
# - ensure that a given version or later of the jq(1) utility is available
# - for use in setup (fixture) functions
setup_jq() {
JQ=$(type -P jq) || error "jq(1) command is not present"
local minversion="${1?}"
local ver="$("$JQ" --version 2>&1)"
case "$ver" in
jq-*)
local oIFS="$IFS"
IFS='-'
set -- $ver
IFS="$oIFS"
jqversion="$2"
;;
jq\ version\ *)
set -- $ver
jqversion="$3"
;;
*)
error "cannot parse output of jq --version: $ver"
;;
esac
tfw_cmp_version "$jqversion" "$minversion"
case $? in
0|2)
export JQ
return 0
;;
esac
error "jq(1) version $jqversion is not adequate (need $minversion or higher)"
}
# Guard function:
JQ=
jq() {
[ -x "$JQ" ] || error "missing call to setup_jq or setup_jsonin the fixture"
"$JQ" "$@"
}
# Setup function:
# - any test wishing to use the JSON utilities in this file must call this in
# its setup()
setup_json() {
setup_jq 1.3
}
assertJq() {
local json="$1"
local jqscript="$2"
assert --message="$jqscript" --dump-on-fail="$json" [ "$(jq "$jqscript" "$json")" = true ]
}
assertJqCmp() {
local opts=()
while [ $# -gt 0 ]; do
case "$1" in
--) shift; break;;
--*) opts+=("$1"); shift;;
*) break;;
esac
done
[ $# -eq 3 ] || error "invalid arguments"
local json="$1"
local jqscript="$2"
local file="$3"
jq --raw-output "$jqscript" "$json" >"$TFWTMP/jqcmp.tmp"
assert --dump-on-fail="$TFWTMP/jqcmp.tmp" --dump-on-fail="$file" "${opts[@]}" cmp "$TFWTMP/jqcmp.tmp" "$file"
}
assertJqIs() {
local opts=()
while [ $# -gt 0 ]; do
case "$1" in
--) shift; break;;
--*) opts+=("$1"); shift;;
*) break;;
esac
done
[ $# -eq 3 ] || error "invalid arguments"
local json="$1"
local jqscript="$2"
local text="$3"
local jqout="$(jq --raw-output "$jqscript" "$json")"
assert "${opts[@]}" [ "$jqout" = "$text" ]
}
assertJqGrep() {
local opts=()
while [ $# -gt 0 ]; do
case "$1" in
--) shift; break;;
--*) opts+=("$1"); shift;;
*) break;;
esac
done
[ $# -eq 3 ] || error "invalid arguments"
local json="$1"
local jqscript="$2"
local pattern="$3"
jq "$jqscript" "$json" >"$TFWTMP/jqgrep.tmp"
assertGrep "${opts[@]}" "$TFWTMP/jqgrep.tmp" "$pattern"
}
transform_list_json() {
# The following jq(1) incantation transforms a JSON array in from the
# following form (which is optimised for transmission size):
# {
# "header":[ "label1", "label2", "label3", ... ],
# "rows":[
# [ row1value1, row1value2, row1value3, ... ],
# [ row2value1, row2value2, row2value3, ... ],
# ...
# [ rowNvalue1, rowNvalue2, rowNvalue3, ... ]
# ]
# }
#
# into an array of JSON objects:
# [
# {
# "label1": row1value1,
# "label2": row1value2,
# "label3": row1value3,
# ...
# },
# {
# "label1": row2value1,
# "label2": row2value2,
# "label3": row2value3,
# ...
# },
# ...
# {
# "label1": rowNvalue1,
# "label2": rowNvalue2,
# "label3": rowNvalue3,
# ...
# }
# ]
# which is much easier to test with jq(1) expressions.
jq '
[
.header as $header |
.rows as $rows |
$rows | keys | .[] as $index |
[ $rows[$index] as $d | $d | keys | .[] as $i | {key:$header[$i], value:$d[$i]} ] |
from_entries |
.["__index"] = $index
]
' "$1" >"$2"
}