mirror of
https://github.com/servalproject/serval-dna.git
synced 2024-12-20 21:53:12 +00:00
1311 lines
46 KiB
Bash
Executable File
1311 lines
46 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# Tests for Serval DNA HTTP RESTful interface
|
|
#
|
|
# Copyright 2013 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.
|
|
|
|
source "${0%/*}/../testframework.sh"
|
|
source "${0%/*}/../testdefs.sh"
|
|
source "${0%/*}/../testdefs_rhizome.sh"
|
|
|
|
shopt -s extglob
|
|
|
|
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"
|
|
}
|
|
|
|
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"
|
|
}
|
|
|
|
setup() {
|
|
CR='
|
|
'
|
|
VT=' '
|
|
setup_curl 7
|
|
setup_jq 1.3
|
|
setup_servald
|
|
set_instance +A
|
|
set_rhizome_config
|
|
executeOk_servald config \
|
|
set rhizome.api.restful.users.harry.password potter \
|
|
set rhizome.api.restful.users.ron.password weasley \
|
|
set rhizome.api.restful.users.hermione.password grainger
|
|
set_extra_config
|
|
if [ -z "$IDENTITY_COUNT" ]; then
|
|
create_single_identity
|
|
else
|
|
create_identities $IDENTITY_COUNT
|
|
fi
|
|
start_servald_instances +A
|
|
wait_until rhizome_http_server_started +A
|
|
get_rhizome_server_port PORTA +A
|
|
}
|
|
|
|
finally() {
|
|
stop_all_servald_servers
|
|
}
|
|
|
|
teardown() {
|
|
kill_all_servald_processes
|
|
assert_no_servald_processes
|
|
report_all_servald_servers
|
|
}
|
|
|
|
set_extra_config() {
|
|
:
|
|
}
|
|
|
|
set_rhizome_config() {
|
|
executeOk_servald config \
|
|
set debug.http_server on \
|
|
set debug.httpd on \
|
|
set debug.rhizome_manifest on \
|
|
set debug.externalblobs on \
|
|
set debug.rhizome on \
|
|
set debug.verbose on \
|
|
set log.console.level debug
|
|
}
|
|
|
|
doc_AuthBasicMissing="HTTP RESTful missing Basic Authentication credentials"
|
|
test_AuthBasicMissing() {
|
|
executeOk curl \
|
|
--silent --show-error --write-out '%{http_code}' \
|
|
--output http.output \
|
|
--dump-header http.headers \
|
|
"http://$addr_localhost:$PORTA/restful/rhizome/bundlelist.json"
|
|
assertStdoutIs '401'
|
|
assertGrep http.headers "^WWW-Authenticate: Basic realm=\"Serval Rhizome\"$CR\$"
|
|
assertJq http.output 'contains({"http_status_code": 401})'
|
|
assertJq http.output 'contains({"http_status_message": ""})'
|
|
}
|
|
teardown_AuthBasicMissing() {
|
|
tfw_cat http.headers http.output
|
|
teardown
|
|
}
|
|
|
|
doc_AuthBasicWrong="HTTP RESTful incorrect Basic Authentication credentials"
|
|
test_AuthBasicWrong() {
|
|
executeOk curl \
|
|
--silent --show-error --write-out '%{http_code}' \
|
|
--output http.output \
|
|
--dump-header http.headers \
|
|
--basic --user fred:nurks \
|
|
"http://$addr_localhost:$PORTA/restful/rhizome/bundlelist.json"
|
|
assertStdoutIs '401'
|
|
assertGrep http.headers "^WWW-Authenticate: Basic realm=\"Serval Rhizome\"$CR\$"
|
|
assertJq http.output 'contains({"http_status_code": 401})'
|
|
assertJq http.output 'contains({"http_status_message": ""})'
|
|
executeOk curl \
|
|
--silent --fail --show-error --write-out '%{http_code}' \
|
|
--output http.output \
|
|
--dump-header http.headers \
|
|
--basic --user ron:weasley \
|
|
"http://$addr_localhost:$PORTA/restful/rhizome/bundlelist.json"
|
|
assertStdoutIs '200'
|
|
}
|
|
teardown_AuthBasicWrong() {
|
|
tfw_cat http.headers http.output
|
|
teardown
|
|
}
|
|
|
|
add_bundles() {
|
|
local encrypted=false
|
|
case "$1" in
|
|
--encrypted) encrypted=true; shift;;
|
|
esac
|
|
local n
|
|
for ((n = $1; n <= $2; ++n)); do
|
|
create_file file$n $((1000 + $n))
|
|
if $encrypted; then
|
|
echo "crypt=1" >file$n.manifest
|
|
fi
|
|
executeOk_servald rhizome add file $SIDA file$n file$n.manifest
|
|
extract_stdout_manifestid BID[$n]
|
|
extract_stdout_version VERSION[$n]
|
|
extract_stdout_filesize SIZE[$n]
|
|
extract_stdout_filehash HASH[$n]
|
|
extract_stdout_date DATE[$n]
|
|
extract_stdout_BK BK[$n]
|
|
extract_stdout_rowid ROWID[$n]
|
|
extract_stdout_author AUTHOR[$n]
|
|
extract_stdout_secret SECRET[$n]
|
|
extract_stdout_inserttime INSERTTIME[$n]
|
|
NAME[$n]=file$n
|
|
if $encrypted; then
|
|
extract_stdout_crypt CRYPT[$n]
|
|
assert [ "${CRYPT[$n]}" = 1 ]
|
|
else
|
|
CRYPT[$n]=
|
|
fi
|
|
executeOk_servald rhizome export file ${HASH[$n]} raw$n
|
|
if $encrypted; then
|
|
assert ! cmp file$n raw$n
|
|
else
|
|
assert cmp file$n raw$n
|
|
fi
|
|
[ "${ROWID[$n]}" -gt "${ROWID_MAX:-0}" ] && ROWID_MAX=${ROWID[$n]}
|
|
done
|
|
}
|
|
|
|
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"
|
|
}
|
|
|
|
doc_RhizomeList="HTTP RESTful list Rhizome bundles as JSON"
|
|
setup_RhizomeList() {
|
|
setup
|
|
NBUNDLES=100
|
|
add_bundles 0 $((NBUNDLES-1))
|
|
assert [ "$ROWID_MAX" -ge "$NBUNDLES" ]
|
|
}
|
|
test_RhizomeList() {
|
|
executeOk curl \
|
|
--silent --fail --show-error \
|
|
--output bundlelist.json \
|
|
--dump-header http.headers \
|
|
--basic --user harry:potter \
|
|
"http://$addr_localhost:$PORTA/restful/rhizome/bundlelist.json"
|
|
tfw_cat http.headers bundlelist.json
|
|
tfw_preserve bundlelist.json
|
|
assert [ "$(jq '.rows | length' bundlelist.json)" = $NBUNDLES ]
|
|
transform_list_json bundlelist.json array_of_objects.json
|
|
tfw_preserve array_of_objects.json
|
|
for ((n = 0; n != NBUNDLES; ++n)); do
|
|
if [ "${ROWID[$n]}" -eq "$ROWID_MAX" ]; then
|
|
# The first row must contain a non-null token string.
|
|
token=',".token":"","__index":0,'
|
|
else
|
|
token=',".token":null,'
|
|
fi
|
|
assertJq array_of_objects.json \
|
|
"contains([
|
|
{ name:\"file$n\",
|
|
service:\"file\",
|
|
id:\"${BID[$n]}\",
|
|
version:${VERSION[$n]},
|
|
filesize:${SIZE[$n]},
|
|
filehash:\"${HASH[$n]}\",
|
|
date:${DATE[$n]},
|
|
_id:${ROWID[$n]},
|
|
\".fromhere\":1,
|
|
\".author\":\"$SIDA\"
|
|
$token
|
|
}
|
|
])"
|
|
done
|
|
}
|
|
|
|
doc_RhizomeNewSince="HTTP RESTful list Rhizome bundles since token as JSON"
|
|
setup_RhizomeNewSince() {
|
|
set_extra_config() {
|
|
executeOk_servald config set rhizome.api.restful.newsince_timeout 60s \
|
|
set rhizome.api.restful.newsince_poll_ms 500
|
|
}
|
|
setup
|
|
add_bundles 0 5
|
|
executeOk curl \
|
|
--silent --fail --show-error \
|
|
--output bundlelist.json \
|
|
--dump-header http.headers \
|
|
--basic --user harry:potter \
|
|
"http://$addr_localhost:$PORTA/restful/rhizome/bundlelist.json"
|
|
assert [ "$(jq '.rows | length' bundlelist.json)" = 6 ]
|
|
transform_list_json bundlelist.json array_of_objects.json
|
|
token=$(jq --raw-output '.[0][".token"]' array_of_objects.json)
|
|
assert [ -n "$token" ]
|
|
}
|
|
test_RhizomeNewSince() {
|
|
for i in 1 2 3; do
|
|
fork %curl$i curl \
|
|
--silent --fail --show-error \
|
|
--no-buffer \
|
|
--output newsince$i.json \
|
|
--basic --user harry:potter \
|
|
"http://$addr_localhost:$PORTA/restful/rhizome/newsince/$token/bundlelist.json"
|
|
done
|
|
wait_until [ -e newsince1.json -a -e newsince2.json -a -e newsince3.json ]
|
|
add_bundles 6 10
|
|
for i in 1 2 3; do
|
|
wait_until --timeout=10 grep "${BID[10]}" newsince$i.json
|
|
done
|
|
fork_terminate_all
|
|
fork_wait_all
|
|
for i in 1 2 3; do
|
|
if [ $(jq . newsince$i | wc -c) -eq 0 ]; then
|
|
echo ']}' >>newsince$i.json
|
|
assert [ $(jq . newsince$i.json | wc -c) -ne 0 ]
|
|
fi
|
|
transform_list_json newsince$i.json objects$i.json
|
|
tfw_preserve newsince$i.json objects$i.json
|
|
for ((n = 0; n <= 5; ++n)); do
|
|
assertJq objects$i.json "contains([{id:\"${BID[$n]}\"}]) | not"
|
|
done
|
|
for ((n = 6; n <= 10; ++n)); do
|
|
assertJq objects$i.json \
|
|
"contains([
|
|
{ name:\"file$n\",
|
|
service:\"file\",
|
|
id:\"${BID[$n]}\",
|
|
version:${VERSION[$n]},
|
|
filesize:${SIZE[$n]},
|
|
filehash:\"${HASH[$n]}\",
|
|
date:${DATE[$n]},
|
|
_id:${ROWID[$n]},
|
|
\".fromhere\":1,
|
|
\".author\":\"$SIDA\",
|
|
\".token\":\"\"
|
|
}
|
|
])"
|
|
done
|
|
done
|
|
}
|
|
|
|
assert_http_response_headers() {
|
|
local n=$1
|
|
assertGrep --matches=1 http.headers$n "^Serval-Rhizome-Bundle-Id: ${BID[$n]}$CR\$"
|
|
assertGrep --matches=1 http.headers$n "^Serval-Rhizome-Bundle-Version: ${VERSION[$n]}$CR\$"
|
|
assertGrep --matches=1 http.headers$n "^Serval-Rhizome-Bundle-Filesize: ${SIZE[$n]}$CR\$"
|
|
assertGrep --matches=1 http.headers$n "^Serval-Rhizome-Bundle-Filehash: ${HASH[$n]}$CR\$"
|
|
assertGrep --matches=1 http.headers$n "^Serval-Rhizome-Bundle-BK: ${BK[$n]}$CR\$"
|
|
assertGrep --matches=1 http.headers$n "^Serval-Rhizome-Bundle-Date: ${DATE[$n]}$CR\$"
|
|
assertGrep --matches=1 http.headers$n "^Serval-Rhizome-Bundle-Name: \"${NAME[$n]}\"$CR\$"
|
|
assertGrep --matches=1 http.headers$n "^Serval-Rhizome-Bundle-Service: file$CR\$"
|
|
assertGrep --matches=1 http.headers$n "^Serval-Rhizome-Bundle-Author: ${AUTHOR[$n]}$CR\$"
|
|
assertGrep --matches=1 http.headers$n "^Serval-Rhizome-Bundle-Secret: ${SECRET[$n]}$CR\$"
|
|
assertGrep --matches=1 http.headers$n "^Serval-Rhizome-Bundle-Inserttime: ${INSERTTIME[$n]}$CR\$"
|
|
assertGrep --matches=1 http.headers$n "^Serval-Rhizome-Bundle-Rowid: ${ROWID[$n]}$CR\$"
|
|
}
|
|
|
|
doc_RhizomeManifest="HTTP RESTful fetch Rhizome manifest"
|
|
setup_RhizomeManifest() {
|
|
setup
|
|
add_bundles 0 2
|
|
}
|
|
test_RhizomeManifest() {
|
|
for n in 0 1 2; do
|
|
executeOk curl \
|
|
--silent --fail --show-error \
|
|
--output bundle$n.rhm \
|
|
--dump-header http.headers$n \
|
|
--basic --user harry:potter \
|
|
"http://$addr_localhost:$PORTA/restful/rhizome/${BID[$n]}.rhm"
|
|
tfw_cat http.headers$n bundle$n.rhm
|
|
tfw_preserve bundle$n.rhm
|
|
done
|
|
for n in 0 1 2; do
|
|
assert diff file$n.manifest bundle$n.rhm
|
|
assert_http_response_headers $n
|
|
done
|
|
}
|
|
|
|
doc_RhizomePayloadRaw="HTTP RESTful fetch Rhizome raw payload"
|
|
setup_RhizomePayloadRaw() {
|
|
setup
|
|
add_bundles 0 1
|
|
add_bundles --encrypted 2 3
|
|
}
|
|
test_RhizomePayloadRaw() {
|
|
for n in 0 1 2 3; do
|
|
executeOk curl \
|
|
--silent --fail --show-error \
|
|
--output raw.bin$n \
|
|
--dump-header http.headers$n \
|
|
--basic --user harry:potter \
|
|
"http://$addr_localhost:$PORTA/restful/rhizome/${BID[$n]}/raw.bin"
|
|
tfw_cat http.headers$n raw.bin$n
|
|
done
|
|
for n in 0 1 2 3; do
|
|
assert cmp raw$n raw.bin$n
|
|
assert_http_response_headers $n
|
|
done
|
|
}
|
|
|
|
doc_RhizomePayloadDecrypted="HTTP RESTful fetch Rhizome decrypted payload"
|
|
setup_RhizomePayloadDecrypted() {
|
|
setup
|
|
add_bundles 0 1
|
|
add_bundles --encrypted 2 3
|
|
}
|
|
test_RhizomePayloadDecrypted() {
|
|
for n in 0 1 2 3; do
|
|
executeOk curl \
|
|
--silent --fail --show-error \
|
|
--output decrypted.bin$n \
|
|
--dump-header http.headers$n \
|
|
--basic --user harry:potter \
|
|
"http://$addr_localhost:$PORTA/restful/rhizome/${BID[$n]}/decrypted.bin"
|
|
tfw_cat http.headers$n decrypted.bin$n
|
|
done
|
|
for n in 0 1 2 3; do
|
|
assert cmp file$n decrypted.bin$n
|
|
assert_http_response_headers $n
|
|
done
|
|
}
|
|
|
|
extract_http_header() {
|
|
local __var="$1"
|
|
local __headerfile="$2"
|
|
local __header="$3"
|
|
local __rexp="$4"
|
|
local __value=$($SED -n -e "/^$__header:[ $VT]*$__rexp$CR\$/s/^$__header:[ $VT]*\(.*\)$CR\$/\1/p" "$__headerfile")
|
|
assert --message="$__headerfile contains valid '$__header' header" \
|
|
--dump-on-fail="$__headerfile" \
|
|
[ -n "$__value" ]
|
|
[ -n "$__var" ] && eval $__var=\"\$__value\"
|
|
}
|
|
|
|
http_unquote_string() {
|
|
local __var="$1"
|
|
local __unq="$(eval echo '"${'$__var'}"' | sed -e 's/^"//' -e 's/"$//' -e 's/\\\(.\)/\1/g')"
|
|
eval $__var=\"\$__unq\"
|
|
}
|
|
|
|
doc_RhizomeInsert="HTTP RESTful insert new Rhizome bundles"
|
|
setup_RhizomeInsert() {
|
|
IDENTITY_COUNT=3
|
|
SIDA4=
|
|
setup
|
|
for n in 1 2 3 4; do
|
|
create_file file$n $((1000 + $n))
|
|
create_file nfile$n $((1100 + $n))
|
|
payload_filename[$n]=
|
|
eval author[$n]=\$SIDA$n
|
|
service[$n]=file
|
|
done
|
|
name[1]=blarg
|
|
echo "name=blarg" >manifest1
|
|
name[2]=file2
|
|
echo "crypt=1" >manifest2
|
|
name[3]=kibble
|
|
payload_filename[3]=kibble
|
|
>manifest3
|
|
name[4]=
|
|
service[4]=wah
|
|
echo -e "service=wah\ncrypt=0" >manifest4
|
|
}
|
|
test_RhizomeInsert() {
|
|
for n in 1 2 3 4; do
|
|
authorargs=()
|
|
[ -n "${author[$n]}" ] && authorargs=(--form "bundle-author=${author[$n]}")
|
|
execute curl \
|
|
--silent --show-error --write-out '%{http_code}' \
|
|
--output file$n.manifest \
|
|
--dump-header http.header$n \
|
|
--basic --user harry:potter \
|
|
"${authorargs[@]}" \
|
|
--form "manifest=@manifest$n;type=rhizome-manifest/text" \
|
|
--form "payload=@file$n${payload_filename[$n]:+;filename=\"${payload_filename[$n]}\"}" \
|
|
"http://$addr_localhost:$PORTA/restful/rhizome/insert"
|
|
tfw_cat http.header$n file$n.manifest
|
|
assertExitStatus == 0
|
|
assertStdoutIs 201
|
|
extract_http_header BID[$n] http.header$n Serval-Rhizome-Bundle-Id "$rexp_manifestid"
|
|
extract_http_header VERSION[$n] http.header$n Serval-Rhizome-Bundle-Version "$rexp_version"
|
|
extract_http_header SIZE[$n] http.header$n Serval-Rhizome-Bundle-Filesize "$rexp_filesize"
|
|
extract_http_header HASH[$n] http.header$n Serval-Rhizome-Bundle-Filehash "$rexp_filehash"
|
|
extract_http_header DATE[$n] http.header$n Serval-Rhizome-Bundle-Date "$rexp_date"
|
|
extract_http_header ROWID[$n] http.header$n Serval-Rhizome-Bundle-Rowid "$rexp_rowid"
|
|
extract_http_header INSERTTIME[$n] http.header$n Serval-Rhizome-Bundle-Inserttime "$rexp_date"
|
|
extract_http_header SECRET[$n] http.header$n Serval-Rhizome-Bundle-Secret "$rexp_bundlesecret"
|
|
extract_http_header SERVICE[$n] http.header$n Serval-Rhizome-Bundle-Service ".*"
|
|
assert [ ${SIZE[$n]} -eq $((1000 + $n)) ]
|
|
assert [ "${SERVICE[$n]}" = "${service[$n]}" ]
|
|
extract_manifest_id BID file$n.manifest
|
|
extract_manifest_version VERSION file$n.manifest
|
|
extract_manifest_filesize SIZE file$n.manifest
|
|
extract_manifest_filehash HASH file$n.manifest
|
|
extract_manifest_date DATE file$n.manifest
|
|
extract_manifest_service SERVICE file$n.manifest
|
|
assert [ "$BID" = "${BID[$n]}" ]
|
|
assert [ "$VERSION" = "${VERSION[$n]}" ]
|
|
assert [ "$SIZE" = "${SIZE[$n]}" ]
|
|
assert [ "$HASH" = "${HASH[$n]}" ]
|
|
assert [ "$DATE" = "${DATE[$n]}" ]
|
|
assert [ "$SERVICE" = "${SERVICE[$n]}" ]
|
|
if [ -n "${name[$n]}" ]; then
|
|
extract_http_header NAME[$n] http.header$n Serval-Rhizome-Bundle-Name ".*"
|
|
http_unquote_string NAME[$n]
|
|
assert [ "${NAME[$n]}" = "${name[$n]}" ]
|
|
extract_manifest_name NAME file$n.manifest
|
|
assert [ "$NAME" = "${NAME[$n]}" ]
|
|
fi
|
|
if [ -n "${author[$n]}" ]; then
|
|
extract_http_header AUTHOR[$n] http.header$n Serval-Rhizome-Bundle-Author "$rexp_sid"
|
|
assert [ "${AUTHOR[$n]}" = "${author[$n]}" ]
|
|
extract_http_header BK[$n] http.header$n Serval-Rhizome-Bundle-BK "$rexp_bundlekey"
|
|
extract_manifest_BK BK file$n.manifest
|
|
assert [ "$BK" = "${BK[$n]}" ]
|
|
fi
|
|
done
|
|
executeOk_servald rhizome list
|
|
assert_rhizome_list \
|
|
--fromhere=1 \
|
|
--author=${author[1]} file1 \
|
|
--author=${author[2]} file2 \
|
|
--author=${author[3]} file3 \
|
|
--fromhere=0 \
|
|
--author=${author[4]} file4
|
|
for n in 1 2 3 4; do
|
|
executeOk_servald rhizome extract bundle ${BID[$n]} xfile$n.manifest xfile$n
|
|
assert diff xfile$n.manifest file$n.manifest
|
|
assert diff file$n xfile$n
|
|
done
|
|
for n in 1 2 3 4; do
|
|
$SED -e '/^version=/d;/^date=/d;/^filehash=/d;/^filesize=/d' xfile$n.manifest >nmanifest$n
|
|
execute curl \
|
|
--silent --show-error --write-out '%{http_code}' \
|
|
--output nfile$n.manifest \
|
|
--dump-header http.header$n \
|
|
--basic --user harry:potter \
|
|
--form "manifest=@nmanifest$n;type=rhizome-manifest/text" \
|
|
--form "payload=@nfile$n;filename=\"nfile$n\"" \
|
|
"http://$addr_localhost:$PORTA/restful/rhizome/insert"
|
|
tfw_cat http.header$n nfile$n.manifest
|
|
assertExitStatus == 0
|
|
if [ -n "${author[$n]}" ]; then
|
|
assertStdoutIs 201
|
|
else
|
|
assertStdoutIs 403
|
|
assertJq nfile$n.manifest 'contains({"http_status_code": 403})'
|
|
assertJqGrep --ignore-case nfile$n.manifest '.http_status_message' "missing bundle secret"
|
|
fi
|
|
done
|
|
}
|
|
|
|
doc_RhizomeInsertAnon="HTTP RESTful update anonymous Rhizome bundle"
|
|
setup_RhizomeInsertAnon() {
|
|
setup
|
|
create_file file1 1001
|
|
executeOk_servald rhizome add file '' file1 file1.manifest
|
|
extract_stdout_secret SECRET
|
|
assertGrep --matches=0 file1.manifest '^BK='
|
|
$SED -e '/^version=/d;/^date=/d;/^filehash=/d;/^filesize=/d' file1.manifest >file2.manifest
|
|
create_file file2 1002
|
|
}
|
|
test_RhizomeInsertAnon() {
|
|
execute curl \
|
|
--silent --show-error --write-out '%{http_code}' \
|
|
--output ifile2.manifest \
|
|
--dump-header http.header \
|
|
--basic --user harry:potter \
|
|
--form "bundle-secret=$SECRET" \
|
|
--form "manifest=@file2.manifest;type=rhizome-manifest/text" \
|
|
--form "payload=@file2" \
|
|
"http://$addr_localhost:$PORTA/restful/rhizome/insert"
|
|
tfw_cat http.header ifile2.manifest
|
|
assertExitStatus == 0
|
|
assertStdoutIs 201
|
|
executeOk_servald rhizome list
|
|
assert_rhizome_list --fromhere=0 --manifest=ifile2.manifest file2
|
|
}
|
|
|
|
doc_RhizomeInsertEmpty="HTTP RESTful insert empty Rhizome bundle"
|
|
setup_RhizomeInsertEmpty() {
|
|
setup
|
|
>empty
|
|
assert [ ! -s empty ]
|
|
}
|
|
test_RhizomeInsertEmpty() {
|
|
execute curl \
|
|
--silent --show-error --write-out '%{http_code}' \
|
|
--output empty.manifest \
|
|
--dump-header http.header \
|
|
--basic --user harry:potter \
|
|
--form "manifest=;type=rhizome-manifest/text" \
|
|
--form "payload=@empty;filename=\"lucky\"" \
|
|
"http://$addr_localhost:$PORTA/restful/rhizome/insert"
|
|
tfw_cat http.header empty.manifest
|
|
assertExitStatus == 0
|
|
assertStdoutIs 201
|
|
extract_manifest_id BID empty.manifest
|
|
executeOk_servald rhizome list
|
|
assert_rhizome_list empty
|
|
executeOk_servald rhizome extract bundle $BID xempty.manifest xempty
|
|
assert [ ! -e xempty ]
|
|
assert diff xempty.manifest empty.manifest
|
|
}
|
|
|
|
doc_RhizomeInsertLarge="HTTP RESTful insert 50 MiB Rhizome bundle"
|
|
setup_RhizomeInsertLarge() {
|
|
setup
|
|
create_file file1 50m
|
|
}
|
|
test_RhizomeInsertLarge() {
|
|
execute --timeout=120 curl \
|
|
--silent --show-error --write-out '%{http_code}' \
|
|
--output file1.manifest \
|
|
--dump-header http.header \
|
|
--basic --user harry:potter \
|
|
--form "manifest=;type=rhizome-manifest/text" \
|
|
--form "payload=@file1" \
|
|
"http://$addr_localhost:$PORTA/restful/rhizome/insert"
|
|
tfw_cat http.header file1.manifest
|
|
assertExitStatus == 0
|
|
assertStdoutIs 201
|
|
extract_manifest_id BID file1.manifest
|
|
executeOk_servald rhizome list
|
|
assert_rhizome_list file1
|
|
executeOk_servald rhizome extract bundle $BID xfile1.manifest xfile1
|
|
assert diff xfile1.manifest file1.manifest
|
|
assert cmp file1 xfile1
|
|
}
|
|
|
|
doc_RhizomeInsertMissingManifest="HTTP RESTful insert missing 'manifest' form part"
|
|
setup_RhizomeInsertMissingManifest() {
|
|
setup
|
|
echo 'File one' >file1
|
|
}
|
|
test_RhizomeInsertMissingManifest() {
|
|
execute curl \
|
|
--silent --show-error --write-out '%{http_code}' \
|
|
--output http.body \
|
|
--dump-header http.header \
|
|
--basic --user harry:potter \
|
|
--form "payload=@file1" \
|
|
"http://$addr_localhost:$PORTA/restful/rhizome/insert"
|
|
tfw_cat http.header http.body
|
|
assertExitStatus == 0
|
|
assertStdoutIs 403
|
|
assertJq http.body 'contains({"http_status_code": 403})'
|
|
assertJqGrep --ignore-case http.body '.http_status_message' 'missing.*manifest.*form.*part'
|
|
executeOk_servald rhizome list
|
|
assert_rhizome_list
|
|
}
|
|
|
|
doc_RhizomeInsertIncorrectManifestType="HTTP RESTful insert incorrect 'manifest' content type"
|
|
setup_RhizomeInsertIncorrectManifestType() {
|
|
setup
|
|
echo 'File one' >file1
|
|
}
|
|
test_RhizomeInsertIncorrectManifestType() {
|
|
execute curl \
|
|
--silent --show-error --write-out '%{http_code}' \
|
|
--output http.body \
|
|
--dump-header http.header \
|
|
--basic --user harry:potter \
|
|
--form "manifest=;type=rhizome-manifest/something" \
|
|
--form "payload=@file1" \
|
|
"http://$addr_localhost:$PORTA/restful/rhizome/insert"
|
|
tfw_cat http.header http.body
|
|
assertExitStatus == 0
|
|
assertStdoutIs 403
|
|
assertJq http.body 'contains({"http_status_code": 403})'
|
|
assertJqGrep --ignore-case http.body '.http_status_message' 'unsupported content-type.*manifest.*form.*part'
|
|
executeOk_servald rhizome list
|
|
assert_rhizome_list
|
|
}
|
|
|
|
doc_RhizomeInsertDuplicateManifest="HTTP RESTful insert duplicate 'manifest' form part"
|
|
setup_RhizomeInsertDuplicateManifest() {
|
|
setup
|
|
echo 'File one' >file1
|
|
echo 'name=wah' >file1.manifest
|
|
echo 'name=bee' >file2.manifest
|
|
}
|
|
test_RhizomeInsertDuplicateManifest() {
|
|
execute curl \
|
|
--silent --show-error --write-out '%{http_code}' \
|
|
--output http.body \
|
|
--dump-header http.header \
|
|
--basic --user harry:potter \
|
|
--form "manifest=@file1.manifest;type=rhizome-manifest/text" \
|
|
--form "manifest=@file2.manifest;type=rhizome-manifest/text" \
|
|
--form "payload=@file1" \
|
|
"http://$addr_localhost:$PORTA/restful/rhizome/insert"
|
|
tfw_cat http.header http.body
|
|
assertExitStatus == 0
|
|
assertStdoutIs 403
|
|
assertJq http.body 'contains({"http_status_code": 403})'
|
|
assertJqGrep --ignore-case http.body '.http_status_message' 'duplicate.*manifest.*form.*part'
|
|
executeOk_servald rhizome list
|
|
assert_rhizome_list
|
|
}
|
|
|
|
doc_RhizomeInsertJournal="HTTP RESTful insert does not support journals"
|
|
setup_RhizomeInsertJournal() {
|
|
setup
|
|
echo 'File one' >file1
|
|
echo 'tail=0' >file1.manifest
|
|
}
|
|
test_RhizomeInsertJournal() {
|
|
execute curl \
|
|
--silent --show-error --write-out '%{http_code}' \
|
|
--output http.body \
|
|
--dump-header http.header \
|
|
--basic --user harry:potter \
|
|
--form "manifest=@file1.manifest;type=rhizome-manifest/text" \
|
|
--form "payload=@file1" \
|
|
"http://$addr_localhost:$PORTA/restful/rhizome/insert"
|
|
tfw_cat http.header http.body
|
|
assertExitStatus == 0
|
|
assertStdoutIs 403
|
|
assertJq http.body 'contains({"http_status_code": 403})'
|
|
assertJqGrep --ignore-case http.body '.http_status_message' 'not supported.*journal'
|
|
executeOk_servald rhizome list
|
|
assert_rhizome_list
|
|
}
|
|
|
|
doc_RhizomeInsertMissingPayload="HTTP RESTful insert missing 'payload' form part"
|
|
setup_RhizomeInsertMissingPayload() {
|
|
setup
|
|
echo 'File one' >file1
|
|
echo 'name=wah' >file1.manifest
|
|
}
|
|
test_RhizomeInsertMissingPayload() {
|
|
execute curl \
|
|
--silent --show-error --write-out '%{http_code}' \
|
|
--output http.body \
|
|
--dump-header http.header \
|
|
--basic --user harry:potter \
|
|
--form "manifest=@file1.manifest;type=rhizome-manifest/text" \
|
|
"http://$addr_localhost:$PORTA/restful/rhizome/insert"
|
|
tfw_cat http.header http.body
|
|
assertExitStatus == 0
|
|
assertStdoutIs 403
|
|
assertJq http.body 'contains({"http_status_code": 403})'
|
|
assertJqGrep --ignore-case http.body '.http_status_message' 'missing.*payload.*form.*part'
|
|
executeOk_servald rhizome list
|
|
assert_rhizome_list
|
|
}
|
|
|
|
doc_RhizomeInsertDuplicatePayload="HTTP RESTful insert duplicate 'payload' form part"
|
|
setup_RhizomeInsertDuplicatePayload() {
|
|
setup
|
|
echo 'File one' >file1
|
|
echo 'File two' >file2
|
|
echo 'name=wah' >file1.manifest
|
|
}
|
|
test_RhizomeInsertDuplicatePayload() {
|
|
execute curl \
|
|
--silent --show-error --write-out '%{http_code}' \
|
|
--output http.body \
|
|
--dump-header http.header \
|
|
--basic --user harry:potter \
|
|
--form "manifest=@file1.manifest;type=rhizome-manifest/text" \
|
|
--form "payload=@file1" \
|
|
--form "payload=@file2" \
|
|
"http://$addr_localhost:$PORTA/restful/rhizome/insert"
|
|
tfw_cat http.header http.body
|
|
assertExitStatus == 0
|
|
assertStdoutIs 403
|
|
assertJq http.body 'contains({"http_status_code": 403})'
|
|
assertJqGrep --ignore-case http.body '.http_status_message' 'duplicate.*payload.*form.*part'
|
|
executeOk_servald rhizome list
|
|
assert_rhizome_list
|
|
}
|
|
|
|
doc_RhizomeInsertPartOrder="HTTP RESTful insert 'payload' form part before 'manifest'"
|
|
setup_RhizomeInsertPartOrder() {
|
|
setup
|
|
echo 'File one' >file1
|
|
echo 'name=wah' >file1.manifest
|
|
}
|
|
test_RhizomeInsertPartOrder() {
|
|
execute curl \
|
|
--silent --show-error --write-out '%{http_code}' \
|
|
--output http.body \
|
|
--dump-header http.header \
|
|
--basic --user harry:potter \
|
|
--form "payload=@file1" \
|
|
--form "manifest=@file1.manifest;type=rhizome-manifest/text" \
|
|
"http://$addr_localhost:$PORTA/restful/rhizome/insert"
|
|
tfw_cat http.header http.body
|
|
assertExitStatus == 0
|
|
assertStdoutIs 403
|
|
assertJq http.body 'contains({"http_status_code": 403})'
|
|
assertJqGrep --ignore-case http.body '.http_status_message' 'missing.*manifest.*form.*part'
|
|
executeOk_servald rhizome list
|
|
assert_rhizome_list
|
|
}
|
|
|
|
doc_RhizomeInsertPartUnsupported="HTTP RESTful insert unsupported form part"
|
|
setup_RhizomeInsertPartUnsupported() {
|
|
setup
|
|
echo 'File one' >file1
|
|
echo 'name=wah' >file1.manifest
|
|
}
|
|
test_RhizomeInsertPartUnsupported() {
|
|
execute curl \
|
|
--silent --show-error --write-out '%{http_code}' \
|
|
--output http.body \
|
|
--dump-header http.header \
|
|
--basic --user harry:potter \
|
|
--form "manifest=@file1.manifest;type=rhizome-manifest/text" \
|
|
--form "payload=@file1" \
|
|
--form "happyhappy=joyjoy" \
|
|
"http://$addr_localhost:$PORTA/restful/rhizome/insert"
|
|
tfw_cat http.header http.body
|
|
assertExitStatus == 0
|
|
assertStdoutIs 403
|
|
assertJq http.body 'contains({"http_status_code": 403})'
|
|
assertJqGrep --ignore-case http.body '.http_status_message' 'unsupported.*form.*part'
|
|
assertJqGrep http.body '.http_status_message' 'happyhappy'
|
|
executeOk_servald rhizome list
|
|
assert_rhizome_list
|
|
}
|
|
|
|
doc_RhizomeInsertIncorrectFilesize="HTTP RESTful insert with incorrect filesize"
|
|
setup_RhizomeInsertIncorrectFilesize() {
|
|
setup
|
|
echo 'File one' >file1
|
|
echo 'filesize=6' >file1.manifest
|
|
echo 'File two' >file2
|
|
echo 'filesize=100' >file2.manifest
|
|
}
|
|
test_RhizomeInsertIncorrectFilesize() {
|
|
execute curl \
|
|
--silent --show-error --write-out '%{http_code}' \
|
|
--output http.body \
|
|
--dump-header http.header \
|
|
--basic --user harry:potter \
|
|
--form "manifest=@file1.manifest;type=rhizome-manifest/text" \
|
|
--form "payload=@file1" \
|
|
"http://$addr_localhost:$PORTA/restful/rhizome/insert"
|
|
tfw_cat http.header http.body
|
|
assertExitStatus == 0
|
|
assertStdoutIs 403
|
|
assertJq http.body 'contains({"http_status_code": 403})'
|
|
assertJqGrep --ignore-case http.body '.http_status_message' 'payload size.*contradicts manifest'
|
|
execute curl \
|
|
--silent --show-error --write-out '%{http_code}' \
|
|
--output http.body \
|
|
--dump-header http.header \
|
|
--basic --user harry:potter \
|
|
--form "manifest=@file2.manifest;type=rhizome-manifest/text" \
|
|
--form "payload=@file2" \
|
|
"http://$addr_localhost:$PORTA/restful/rhizome/insert"
|
|
tfw_cat http.header http.body
|
|
assertExitStatus == 0
|
|
assertStdoutIs 403
|
|
assertGrep --ignore-case http.body 'payload size.*contradicts manifest'
|
|
executeOk_servald rhizome list
|
|
assert_rhizome_list
|
|
}
|
|
|
|
doc_RhizomeInsertIncorrectFilehash="HTTP RESTful insert with incorrect filehash"
|
|
setup_RhizomeInsertIncorrectFilehash() {
|
|
setup
|
|
echo 'File one' >file1
|
|
echo 'filehash=FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' >file1.manifest
|
|
}
|
|
test_RhizomeInsertIncorrectFilehash() {
|
|
execute curl \
|
|
--silent --show-error --write-out '%{http_code}' \
|
|
--output http.body \
|
|
--dump-header http.header \
|
|
--basic --user harry:potter \
|
|
--form "manifest=@file1.manifest;type=rhizome-manifest/text" \
|
|
--form "payload=@file1" \
|
|
"http://$addr_localhost:$PORTA/restful/rhizome/insert"
|
|
tfw_cat http.header http.body
|
|
assertExitStatus == 0
|
|
assertStdoutIs 403
|
|
assertJq http.body 'contains({"http_status_code": 403})'
|
|
assertJqGrep --ignore-case http.body '.http_status_message' 'payload hash.*contradicts manifest'
|
|
executeOk_servald rhizome list
|
|
assert_rhizome_list
|
|
}
|
|
|
|
doc_MeshmsListConversations="HTTP RESTful list MeshMS conversations as JSON"
|
|
setup_MeshmsListConversations() {
|
|
IDENTITY_COUNT=5
|
|
setup
|
|
# create 3 threads, with all permutations of incoming and outgoing messages
|
|
executeOk_servald meshms send message $SIDA1 $SIDA2 "Message1"
|
|
executeOk_servald meshms send message $SIDA3 $SIDA1 "Message2"
|
|
executeOk_servald meshms send message $SIDA1 $SIDA4 "Message3"
|
|
executeOk_servald meshms send message $SIDA4 $SIDA1 "Message4"
|
|
}
|
|
test_MeshmsListConversations() {
|
|
executeOk curl \
|
|
--silent --fail --show-error \
|
|
--output conversationlist1.json \
|
|
--dump-header http.headers \
|
|
--basic --user harry:potter \
|
|
"http://$addr_localhost:$PORTA/restful/meshms/$SIDA1/conversationlist.json"
|
|
tfw_cat http.headers conversationlist1.json
|
|
tfw_preserve conversationlist1.json
|
|
assert [ "$(jq '.rows | length' conversationlist1.json)" = 3 ]
|
|
transform_list_json conversationlist1.json conversations1.json
|
|
tfw_preserve conversations1.json
|
|
assertJq conversations1.json \
|
|
"contains([
|
|
{ my_sid: \"$SIDA1\",
|
|
their_sid: \"$SIDA2\",
|
|
read: true,
|
|
last_message: 0,
|
|
read_offset: 0
|
|
}
|
|
])"
|
|
assertJq conversations1.json \
|
|
"contains([
|
|
{ my_sid: \"$SIDA1\",
|
|
their_sid: \"$SIDA3\",
|
|
read: false,
|
|
last_message: 11,
|
|
read_offset: 0
|
|
}
|
|
])"
|
|
assertJq conversations1.json \
|
|
"contains([
|
|
{ my_sid: \"$SIDA1\",
|
|
their_sid: \"$SIDA4\",
|
|
read: false,
|
|
last_message: 14,
|
|
read_offset: 0
|
|
}
|
|
])"
|
|
# mark all incoming messages as read
|
|
executeOk_servald meshms read messages $SIDA1
|
|
tfw_cat --stderr
|
|
executeOk curl \
|
|
--silent --fail --show-error \
|
|
--output conversationlist2.json \
|
|
--dump-header http.headers \
|
|
--basic --user harry:potter \
|
|
"http://$addr_localhost:$PORTA/restful/meshms/$SIDA1/conversationlist.json"
|
|
tfw_cat http.headers conversationlist2.json
|
|
tfw_preserve conversationlist2.json
|
|
assert [ "$(jq '.rows | length' conversationlist2.json)" = 3 ]
|
|
transform_list_json conversationlist2.json conversations2.json
|
|
tfw_preserve conversations2.json
|
|
assertJq conversations2.json \
|
|
"contains([
|
|
{ my_sid: \"$SIDA1\",
|
|
their_sid: \"$SIDA2\",
|
|
read: true,
|
|
last_message: 0,
|
|
read_offset: 0
|
|
}
|
|
])"
|
|
assertJq conversations2.json \
|
|
"contains([
|
|
{ my_sid: \"$SIDA1\",
|
|
their_sid: \"$SIDA3\",
|
|
read: true,
|
|
last_message: 11,
|
|
read_offset: 11
|
|
}
|
|
])"
|
|
assertJq conversations2.json \
|
|
"contains([
|
|
{ my_sid: \"$SIDA1\",
|
|
their_sid: \"$SIDA4\",
|
|
read: true,
|
|
last_message: 14,
|
|
read_offset: 14
|
|
}
|
|
])"
|
|
}
|
|
|
|
# Create a file that contains no blank lines.
|
|
create_message_file() {
|
|
create_file "$1" $2
|
|
sed -i -e '/^$/d' "$1"
|
|
}
|
|
|
|
# Add a sequence of messages of varying sizes up to 1 KiB.
|
|
add_messages() {
|
|
local symbols="$1"
|
|
shift
|
|
local texts=("$@")
|
|
local sent_since_ack=0
|
|
local i n size msize
|
|
local size=0
|
|
for ((i = 0; i < ${#symbols}; ++i)); do
|
|
local sym="${symbols:$i:1}"
|
|
let size+=379
|
|
let msize=size%1021
|
|
let n=NMESSAGE++
|
|
local text="${texts[$i]}"
|
|
case $sym in
|
|
'>'|'<')
|
|
if [ -n "$text" ]; then
|
|
echo "$text" >text$n
|
|
else
|
|
create_message_file text$n $msize
|
|
text="$(<text$n)"
|
|
fi
|
|
;;
|
|
esac
|
|
case $sym in
|
|
'>')
|
|
MESSAGE[$n]=">"
|
|
executeOk_servald meshms send message $SIDA1 $SIDA2 "$text"
|
|
let ++sent_since_ack
|
|
let ++NSENT
|
|
;;
|
|
'<')
|
|
MESSAGE[$n]="<"
|
|
executeOk_servald meshms send message $SIDA2 $SIDA1 "$text"
|
|
let ++NRECV
|
|
;;
|
|
'A')
|
|
MESSAGE[$n]=ACK
|
|
[ $i -ne 0 -a $sent_since_ack -eq 0 ] && error "two ACKs in a row (at position $i)"
|
|
executeOk_servald meshms list messages $SIDA2 $SIDA1
|
|
let ++NACK
|
|
;;
|
|
*)
|
|
error "invalid message symbol '$sym' (at position $i)"
|
|
;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
doc_MeshmsListMessages="HTTP RESTful list MeshMS messages in one conversation as JSON"
|
|
setup_MeshmsListMessages() {
|
|
IDENTITY_COUNT=2
|
|
setup
|
|
add_messages '><>>A>A<>><><><>>>A>A><<<<A<>><>>A<<>'
|
|
let NROWS=NSENT+NRECV+(NACK?1:0)
|
|
executeOk_servald meshms list messages $SIDA1 $SIDA2
|
|
delivered_offset=$(sed -n -e '/^[0-9]\+:[0-9]\+:ACK:delivered$/{n;s/^[0-9]\+:\([0-9]\+\):>:.*/\1/p;q}' "$TFWSTDOUT")
|
|
[ -z "$delivered_offset" ] && delivered_offset=0
|
|
read_offset=$(sed -n -e 's/^[0-9]\+:\([0-9]\+\):MARK:read$/\1/p' "$TFWSTDOUT")
|
|
[ -z "$read_offset" ] && read_offset=0
|
|
}
|
|
test_MeshmsListMessages() {
|
|
executeOk curl \
|
|
--silent --fail --show-error \
|
|
--output messagelist.json \
|
|
--dump-header http.headers \
|
|
--basic --user harry:potter \
|
|
"http://$addr_localhost:$PORTA/restful/meshms/$SIDA1/$SIDA2/messagelist.json"
|
|
tfw_cat http.headers messagelist.json
|
|
tfw_preserve messagelist.json
|
|
assert [ "$(jq '.rows | length' messagelist.json)" = $NROWS ]
|
|
transform_list_json messagelist.json messages.json
|
|
tfw_preserve messages.json
|
|
seen_ack=false
|
|
let i=0
|
|
for ((j = NMESSAGE-1; j >= 0; --j)); do
|
|
case ${MESSAGE[$j]} in
|
|
'ACK') $seen_ack && continue
|
|
esac
|
|
assertJq messages.json '(.['$i'].token | length) > 0'
|
|
assertJq messages.json '.['$i'].my_sid == "'$SIDA1'"'
|
|
assertJq messages.json '.['$i'].their_sid == "'$SIDA2'"'
|
|
case ${MESSAGE[$j]} in
|
|
'>')
|
|
assertJq messages.json '.['$i'].type == ">"'
|
|
assertJqCmp messages.json '.['$i'].text' text$j
|
|
assertJq messages.json '.['$i'].delivered == (.['$i'].offset <= '$delivered_offset')'
|
|
let ++i
|
|
;;
|
|
'<')
|
|
assertJq messages.json '.['$i'].type == "<"'
|
|
assertJqCmp messages.json '.['$i'].text' text$j
|
|
assertJq messages.json '.['$i'].read == (.['$i'].offset <= '$read_offset')'
|
|
let ++i
|
|
;;
|
|
'ACK')
|
|
assertJq messages.json '.['$i'].type == "ACK"'
|
|
assertJq messages.json '.['$i'].text == null'
|
|
assertJq messages.json '.['$i'].ack_offset == '$delivered_offset
|
|
let ++i
|
|
seen_ack=true
|
|
;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
doc_MeshmsListMessagesNoIdentity="HTTP RESTful list MeshMS messages from unknown identity"
|
|
setup_MeshmsListMessagesNoIdentity() {
|
|
setup
|
|
SIDX=0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF
|
|
}
|
|
test_MeshmsListMessagesNoIdentity() {
|
|
execute curl \
|
|
--silent --show-error --write-out '%{http_code}' \
|
|
--output http.body \
|
|
--dump-header http.header \
|
|
--basic --user harry:potter \
|
|
"http://$addr_localhost:$PORTA/restful/meshms/$SIDX/$SIDA/messagelist.json"
|
|
tfw_cat http.header http.body
|
|
assertExitStatus == 0
|
|
assertStdoutIs 403
|
|
assertJq http.body 'contains({"http_status_code": 403})'
|
|
assertJq http.body 'contains({"meshms_status_code": 2})'
|
|
assertJqGrep --ignore-case http.body '.http_status_message' 'identity.*unknown'
|
|
}
|
|
|
|
doc_MeshmsListMessagesNewSince="HTTP RESTful list MeshMS messages in one conversation since token as JSON"
|
|
setup_MeshmsListMessagesNewSince() {
|
|
IDENTITY_COUNT=2
|
|
set_extra_config() {
|
|
executeOk_servald config set rhizome.api.restful.newsince_timeout 1s \
|
|
set rhizome.api.restful.newsince_poll_ms 500
|
|
}
|
|
setup
|
|
add_messages '><>>A>A<>><><><>>>A>A><<<<A<>><>>A<<>'
|
|
let NROWS=NSENT+NRECV+(NACK?1:0)
|
|
executeOk curl \
|
|
--silent --fail --show-error \
|
|
--output messagelist.json \
|
|
--dump-header http.headers \
|
|
--basic --user harry:potter \
|
|
"http://$addr_localhost:$PORTA/restful/meshms/$SIDA1/$SIDA2/messagelist.json"
|
|
assert [ "$(jq '.rows | length' messagelist.json)" = $NROWS ]
|
|
transform_list_json messagelist.json messages.json
|
|
tfw_preserve messages.json
|
|
for ((i = 0; i < NROWS; i += 3)); do
|
|
token[$i]=$(jq --raw-output '.['$i'].token' messages.json)
|
|
done
|
|
}
|
|
test_MeshmsListMessagesNewSince() {
|
|
for ((i = 0; i < NROWS; i += 3)); do
|
|
# At most five requests going at once
|
|
[ $i -ge 15 ] && fork_wait %curl$((i-15))
|
|
fork %curl$i executeOk curl \
|
|
--silent --fail --show-error \
|
|
--output messagelist$i.json \
|
|
--dump-header http.headers$i \
|
|
--basic --user harry:potter \
|
|
"http://$addr_localhost:$PORTA/restful/meshms/$SIDA1/$SIDA2/newsince/${token[$i]}/messagelist.json"
|
|
done
|
|
fork_wait_all
|
|
for ((i = 0; i < NROWS; i += 3)); do
|
|
transform_list_json messagelist$i.json messages$i.json
|
|
tfw_preserve messages$i.json
|
|
{ echo '{"a":'; cat messages.json; echo ',"b":'; cat messages$i.json; echo '}'; } >tmp.json
|
|
assertJq tmp.json '.a[:'$i'] == .b'
|
|
done
|
|
}
|
|
|
|
grepall() {
|
|
local pattern="$1"
|
|
shift
|
|
for file; do
|
|
grep "$pattern" "$file" || return $?
|
|
done
|
|
return 0
|
|
}
|
|
|
|
doc_MeshmsListMessagesNewSinceArrival="HTTP RESTful list newly arriving MeshMS messages in one conversation as JSON"
|
|
setup_MeshmsListMessagesNewSinceArrival() {
|
|
IDENTITY_COUNT=2
|
|
set_extra_config() {
|
|
executeOk_servald config set rhizome.api.restful.newsince_timeout 60s \
|
|
set rhizome.api.restful.newsince_poll_ms 500
|
|
}
|
|
setup
|
|
add_messages '><>A>'
|
|
let NROWS=NSENT+NRECV+(NACK?1:0)
|
|
executeOk curl \
|
|
--silent --fail --show-error \
|
|
--output messagelist.json \
|
|
--dump-header http.headers \
|
|
--basic --user harry:potter \
|
|
"http://$addr_localhost:$PORTA/restful/meshms/$SIDA1/$SIDA2/messagelist.json"
|
|
assert [ "$(jq '.rows | length' messagelist.json)" = $NROWS ]
|
|
transform_list_json messagelist.json messages.json
|
|
tfw_preserve messages.json
|
|
token=$(jq --raw-output '.[0].token' messages.json)
|
|
assert [ -n "$token" ]
|
|
}
|
|
test_MeshmsListMessagesNewSinceArrival() {
|
|
for i in 1 2 3; do
|
|
fork %curl$i executeOk curl \
|
|
--silent --fail --show-error \
|
|
--no-buffer \
|
|
--output newsince$i.json \
|
|
--basic --user harry:potter \
|
|
"http://$addr_localhost:$PORTA/restful/meshms/$SIDA1/$SIDA2/newsince/$token/messagelist.json"
|
|
done
|
|
wait_until [ -e newsince1.json -a -e newsince2.json -a -e newsince3.json ]
|
|
for message in '>Rumplestiltskin' 'A' '<Howdydoody' '>Eulenspiegel'; do
|
|
add_messages "${message:0:1}" "${message:1}"
|
|
wait_until --timeout=60 grepall "${message:1}" newsince{1,2,3}.json
|
|
done
|
|
fork_terminate_all
|
|
fork_wait_all
|
|
}
|
|
teardown_MeshmsListMessagesNewSinceArrival() {
|
|
tfw_preserve newsince{1,2,3}.json
|
|
teardown
|
|
}
|
|
|
|
doc_MeshmsSend="HTTP RESTful send MeshMS message"
|
|
setup_MeshmsSend() {
|
|
IDENTITY_COUNT=2
|
|
setup
|
|
}
|
|
test_MeshmsSend() {
|
|
executeOk curl \
|
|
--silent --fail --show-error \
|
|
--output sendmessage.json \
|
|
--basic --user harry:potter \
|
|
--form "message=Hello World" \
|
|
"http://$addr_localhost:$PORTA/restful/meshms/$SIDA1/$SIDA2/sendmessage"
|
|
executeOk_servald meshms list messages $SIDA1 $SIDA2
|
|
assertStdoutGrep --matches=1 ':>:Hello World'
|
|
executeOk curl \
|
|
--silent --fail --show-error \
|
|
--output sendmessage.json \
|
|
--basic --user ron:weasley \
|
|
--form "message=Hello back!" \
|
|
"http://$addr_localhost:$PORTA/restful/meshms/$SIDA2/$SIDA1/sendmessage"
|
|
executeOk_servald meshms list messages $SIDA1 $SIDA2
|
|
assertStdoutGrep --matches=1 ':>:Hello World$'
|
|
assertStdoutGrep --matches=1 ':<:Hello back!$'
|
|
}
|
|
|
|
doc_MeshmsSendMissingMessage="HTTP RESTful MeshMS send missing 'message' form part "
|
|
setup_MeshmsSendMissingMessage() {
|
|
IDENTITY_COUNT=2
|
|
setup
|
|
}
|
|
test_MeshmsSendMissingMessage() {
|
|
execute curl \
|
|
--silent --show-error --write-out '%{http_code}' \
|
|
--output http.body \
|
|
--dump-header http.header \
|
|
--basic --user harry:potter \
|
|
--data '' \
|
|
"http://$addr_localhost:$PORTA/restful/meshms/$SIDA2/$SIDA1/sendmessage"
|
|
tfw_cat http.header http.body
|
|
assertExitStatus == 0
|
|
assertStdoutIs 403
|
|
assertJq http.body 'contains({"http_status_code": 403})'
|
|
assertJqGrep --ignore-case http.body '.http_status_message' 'missing.*message.*form.*part'
|
|
executeOk_servald meshms list messages $SIDA1 $SIDA2
|
|
assertStdoutLineCount '==' 2
|
|
}
|
|
|
|
doc_MeshmsSendDuplicateMessage="HTTP RESTful MeshMS send missing 'message' form part "
|
|
setup_MeshmsSendDuplicateMessage() {
|
|
IDENTITY_COUNT=2
|
|
setup
|
|
}
|
|
test_MeshmsSendDuplicateMessage() {
|
|
execute curl \
|
|
--silent --show-error --write-out '%{http_code}' \
|
|
--output http.body \
|
|
--dump-header http.header \
|
|
--basic --user harry:potter \
|
|
--form "message=Hello one" \
|
|
--form "message=Hello two" \
|
|
"http://$addr_localhost:$PORTA/restful/meshms/$SIDA2/$SIDA1/sendmessage"
|
|
tfw_cat http.header http.body
|
|
assertExitStatus == 0
|
|
assertStdoutIs 403
|
|
assertJq http.body 'contains({"http_status_code": 403})'
|
|
assertJqGrep --ignore-case http.body '.http_status_message' 'duplicate.*message.*form.*part'
|
|
executeOk_servald meshms list messages $SIDA1 $SIDA2
|
|
assertStdoutLineCount '==' 2
|
|
}
|
|
|
|
doc_MeshmsSendNoIdentity="HTTP RESTful MeshMS send from unknown identity"
|
|
setup_MeshmsSendNoIdentity() {
|
|
setup
|
|
SIDX=0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF
|
|
}
|
|
test_MeshmsSendNoIdentity() {
|
|
execute curl \
|
|
--silent --show-error --write-out '%{http_code}' \
|
|
--output http.body \
|
|
--dump-header http.header \
|
|
--basic --user harry:potter \
|
|
--form "message=Hello" \
|
|
"http://$addr_localhost:$PORTA/restful/meshms/$SIDX/$SIDA/sendmessage"
|
|
tfw_cat http.header http.body
|
|
assertExitStatus == 0
|
|
assertStdoutIs 403
|
|
assertJq http.body 'contains({"http_status_code": 403})'
|
|
assertJq http.body 'contains({"meshms_status_code": 2})'
|
|
assertJqGrep --ignore-case http.body '.http_status_message' 'identity.*unknown'
|
|
}
|
|
|
|
runTests "$@"
|