Refactor all REST API tests

Rename 'testdefs_json.sh' to 'testdefs_rest.sh'; add setup functions and
rest_request() function, and roll out through existing test scripts.
This commit is contained in:
Andrew Bettison 2018-03-22 22:24:44 +10:30
parent 9ef7d33d69
commit bc7f7aeaaf
6 changed files with 797 additions and 1523 deletions

View File

@ -424,15 +424,17 @@ servald_start() {
# Utility function:
# - test whether the daemon's HTTP server has started
servald_http_server_started() {
local logvar=LOG${1#+}
$GREP 'HTTP SERVER START.*port=[0-9]' "${!logvar}"
local _instance=${1:-+$instance_name}
local _logvar=LOG${_instance#+}
$GREP 'HTTP SERVER START.*port=[0-9]' "${!_logvar}"
}
# Utility function:
# - test whether the daemon's HTTP server has started
servald_restful_http_server_started() {
local logvar=LOG${1#+}
$GREP 'HTTP SERVER START.*port=[0-9].*services=[^ ]*\<RESTful\>' "${!logvar}"
local _instance=${1:-+$instance_name}
local _logvar=LOG${_instance#+}
$GREP 'HTTP SERVER START.*port=[0-9].*services=[^ ]*\<RESTful\>' "${!_logvar}"
}
# Utility function:

View File

@ -1,5 +1,7 @@
# Common definitions for manipulating JSON in test scripts.
# Common definitions for REST API test scripts, including manipulation of JSON.
#
# Copyright 2014 Serval Project Inc.
# Copyright 2018 Flinders University
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@ -15,6 +17,107 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# Setup function:
# - ensure that the curl(1) and jq(1) utilities are available
setup_rest_utilities() {
setup_curl 7
setup_json
}
# Setup function:
# - configure the given (or current) instance with helpful debug options and
# some standard REST API usernames/passwords
setup_rest_config() {
local _instance="$1"
[ -z "$_instance" ] || push_and_set_instance $_instance || return $?
executeOk_servald config \
set debug.http_server on \
set debug.httpd on \
set api.restful.users.harry.password potter \
set api.restful.users.ron.password weasley \
set api.restful.users.hermione.password grainger
[ -z "$_instance" ] || pop_instance
return 0
}
# Setup function:
# - wait for the current instance's server to start processing REST requests
# - initialise the REST_PORT_{I} shell variable with the port number of the REST
# server running in instance {I}
# - zero the request count for the rest_request() function
wait_until_rest_server_ready() {
local _instance
case $1 in
'') _instance=$instance_name;;
+[A-Z]) _instance=${1#+};;
*) error "invalid instance arg: $1";;
esac
wait_until servald_restful_http_server_started +$_instance
local _portvar=REST_PORT_$_instance
get_servald_restful_http_server_port $_portvar +$_instance
REQUEST_COUNT=0
}
# Utility function:
# - perform a REST request to the given instance (default current instance) and
# expect a given response (default 200 OK)
rest_request() {
local _instance=$instance_name
case $1 in
+[A-Z]) _instance=${1#+}; shift;;
esac
local _portvar=REST_PORT_$_instance
local request_verb="${1?}"
local path="${2?}"
shift 2
local response_code=200
case $1 in
[0-9][0-9][0-9]) response_code=$1; shift;;
esac
local timeout=()
local auth=(--basic)
local user=(--user harry:potter)
local buffer=()
local output="response.json"
local dump_header="response.headers"
local trace="response.trace"
local output_preserve="response-$((++REQUEST_COUNT)).json"
local trace_preserve="response-$((++REQUEST_COUNT)).trace"
local form_parts=()
local data=()
local headers=()
while [ $# -ne 0 ]; do
case $1 in
--timeout=*) timeout=(--timeout="${1#*=}"); shift;;
--no-auth) auth=(); user=(); shift;;
--no-buffer) buffer=(--no-buffer); shift;;
--user=*) user=(--user "${1#*=}"); shift;;
--add-header=*) headers+=(--header "${1#*=}"); shift;;
--output=*) output="${1#*=}"; output_preserve="$output"; shift;;
--dump-header=*) dump_header="${1#*=}"; shift;;
--form-part=*) form_parts+=(--form "${1#*=}"); data=(); shift;;
--data=*) data+=(--data "${1#*=}"); form_parts=(); shift;;
*) error "unsupported option: $1";;
esac
done
executeOk "${timeout[@]}" curl \
--silent --show-error \
--write-out '%{http_code}' \
--output "$output" \
--dump-header "$dump_header" \
--trace-ascii "$trace" \
"${auth[@]}" "${user[@]}" "${buffer[@]}" \
--request "$request_verb" \
"${headers[@]}" \
"${data[@]}" "${form_parts[@]}" \
"http://$addr_localhost:${!_portvar}$path"
tfw_cat "$dump_header" "$output"
[ "$output_preserve" != "$output" ] && cp "$output" "$output_preserve"
cp "$trace" "$trace_preserve"
tfw_preserve "$output_preserve" "$trace_preserve"
assertStdoutIs "$response_code"
}
# Utility function:
# - ensure that a given version or later of the jq(1) utility is available
# - for use in setup (fixture) functions

View File

@ -1,6 +1,6 @@
#!/bin/bash
# Tests for Serval DNA HTTP RESTful interface
# Tests for Serval DNA Keyring REST API
#
# Copyright 2013-2015 Serval Project, Inc.
# Copyright 2016-2018 Flinders Univerity
@ -21,29 +21,23 @@
source "${0%/*}/../testframework.sh"
source "${0%/*}/../testdefs.sh"
source "${0%/*}/../testdefs_json.sh"
source "${0%/*}/../testdefs_rest.sh"
shopt -s extglob
setup() {
setup_curl 7
setup_json
setup_rest_utilities
setup_servald
setup_rest_config +A
set_instance +A
set_keyring_config
executeOk_servald config \
set api.restful.users.harry.password potter \
set api.restful.users.ron.password weasley \
set api.restful.users.hermione.password grainger
if [ -z "$IDENTITY_COUNT" ]; then
create_single_identity
else
create_identities $IDENTITY_COUNT
fi
start_servald_instances +A
wait_until servald_restful_http_server_started +A
get_servald_restful_http_server_port PORTA +A
REQUEST_COUNT=0
wait_until_rest_server_ready +A
}
finally() {
@ -58,33 +52,12 @@ teardown() {
set_keyring_config() {
executeOk_servald config \
set debug.httpd on \
set debug.keyring on \
set debug.verbose on \
set log.console.level debug
}
rest_request() {
local oo
local request_verb="${1?}"
local path="${2?}"
local response_code="${3:-200}"
local preserve="request-$((++REQUEST_COUNT)).json"
executeOk curl \
--silent --show-error \
--write-out '%{http_code}' \
--output response.json \
--dump-header response.headers \
--basic --user harry:potter \
--request "$request_verb" \
"http://$addr_localhost:$PORTA$path"
tfw_cat response.headers response.json
cp response.json "$preserve"
tfw_preserve "$preserve"
assertStdoutIs "$response_code"
}
doc_keyringList="HTTP RESTful list keyring identities as JSON"
doc_keyringList="REST API list keyring identities as JSON"
setup_keyringList() {
IDENTITY_COUNT=10
setup
@ -98,7 +71,7 @@ test_keyringList() {
done
}
doc_keyringListPin="HTTP RESTful list keyring identities as JSON, with PIN"
doc_keyringListPin="REST API list keyring identities as JSON, with PIN"
setup_keyringListPin() {
IDENTITY_COUNT=3
PINA1='wif waf'
@ -121,13 +94,13 @@ test_keyringListPin() {
assertJq ids2.json 'contains([{"sid": "'$SIDA3'"}])'
}
doc_keyringGet="HTTP RESTful get single keyring identity as JSON"
doc_keyringGet="REST API get single keyring identity as JSON"
test_keyringGet() {
rest_request GET "/restful/keyring/$SIDA1"
assertJq response.json 'contains({"identity": {"sid": "'$SIDA1'", "identity": "'$IDA1'", "did": "'"$DIDA1"'", "name": "'"$NAMEA1"'"}})'
}
doc_keyringAdd="HTTP RESTful add keyring identity"
doc_keyringAdd="REST API add keyring identity"
setup_keyringAdd() {
IDENTITY_COUNT=2
setup
@ -143,7 +116,7 @@ test_keyringAdd() {
assertStdoutGrep --stderr --matches=1 "^$SID:$ID::\$"
}
doc_keyringAddPin="HTTP RESTful add keyring identity with PIN"
doc_keyringAddPin="REST API add keyring identity with PIN"
setup_keyringAddPin() {
IDENTITY_COUNT=2
setup
@ -165,7 +138,7 @@ test_keyringAddPin() {
assertJq ids.json 'contains([{"sid": "'$SIDA1'"}])'
}
doc_keyringRemove="HTTP RESTful remove keyring identity"
doc_keyringRemove="REST API remove keyring identity"
setup_keyringRemove() {
IDENTITY_COUNT=2
setup
@ -179,7 +152,7 @@ test_keyringRemove() {
assertStdoutGrep --stderr --matches=0 "^$SID:"
}
doc_keyringSetDidName="HTTP RESTful set DID and name"
doc_keyringSetDidName="REST API set keyring identity DID and name"
setup_keyringSetDidName() {
IDENTITY_COUNT=2
setup
@ -192,7 +165,7 @@ test_keyringSetDidName() {
assertStdoutGrep --stderr --matches=1 "^$SIDA1:$IDA1:987654321:Joe Bloggs\$"
}
doc_keyringSetDidNamePin="HTTP RESTful set DID and name with PIN"
doc_keyringSetDidNamePin="REST API set keyring identity DID and name with PIN"
setup_keyringSetDidNamePin() {
IDENTITY_COUNT=2
PINA1=xyzabc
@ -218,7 +191,7 @@ test_keyringSetDidNamePin() {
assertStdoutGrep --stderr --matches=1 "^$SIDA1:$IDA1:321321321:Fred Nurks\$"
}
doc_keyringLockUnlock="HTTP RESTful lock and unlock PIN-protected identities"
doc_keyringLockUnlock="REST API lock and unlock PIN-protected identities"
setup_keyringLockUnlock() {
IDENTITY_COUNT=5
PIN1=abc

View File

@ -1,17 +1,31 @@
#!/bin/bash
# Tests for Serval DNA MeshMB REST API
#
# Copyright 2016-2018 Flinders University
#
# 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_json.sh"
source "${0%/*}/../testdefs_rest.sh"
setup_instance() {
set_instance $1
setup_rest_config
executeOk_servald config \
set api.restful.users.harry.password potter \
set api.restful.users.ron.password weasley \
set api.restful.users.hermione.password grainger \
set debug.http_server on \
set debug.httpd on \
set debug.meshmb on \
set debug.meshms on \
set debug.verbose on \
@ -29,14 +43,12 @@ set_extra_config() {
}
setup() {
setup_curl 7
setup_json
setup_rest_utilities
setup_servald
export SERVALD_RHIZOME_DB_RETRY_LIMIT_MS=60000
setup_instance +A
start_servald_instances +A
wait_until servald_restful_http_server_started +A
get_servald_restful_http_server_port PORTA +A
wait_until_rest_server_ready
}
finally() {
@ -49,36 +61,42 @@ teardown() {
report_all_servald_servers
}
doc_MeshMBRestSend="Restful send of a broadcast message"
doc_AuthBasicMissing="REST API missing MeshMB Basic Authentication credentials"
test_AuthBasicMissing() {
rest_request GET "/restful/meshmb/$IDA1/feedlist.json" 401 --no-auth
assertGrep response.headers "^WWW-Authenticate: Basic realm=\"Serval RESTful API\"$CR\$"
assertJq response.json 'contains({"http_status_code": 401})'
assertJq response.json 'contains({"http_status_message": ""})'
}
doc_AuthBasicWrong="REST API incorrect MeshMB Basic Authentication credentials"
test_AuthBasicWrong() {
rest_request GET "/restful/meshmb/$IDA1/feedlist.json" 401 --user=fred:nurks
assertGrep response.headers "^WWW-Authenticate: Basic realm=\"Serval RESTful API\"$CR\$"
assertJq response.json 'contains({"http_status_code": 401})'
assertJq response.json 'contains({"http_status_message": ""})'
rest_request GET "/restful/meshms/$SIDA/conversationlist.json" 200 --user=ron:weasley
}
doc_MeshMBRestSend="REST API MeshMB send a broadcast message"
test_MeshMBRestSend() {
executeOk curl \
--silent --fail --show-error \
--output sendmessage.json \
--basic --user harry:potter \
--form "message=Hello World;type=text/plain;charset=utf-8" \
"http://$addr_localhost:$PORTA/restful/meshmb/$IDA1/sendmessage"
rest_request POST "/restful/meshmb/$IDA1/sendmessage" 201 \
--form-part="message=Hello World;type=text/plain;charset=utf-8"
executeOk_servald rhizome export bundle $IDA1 broadcast.manifest broadcast
tfw_cat -h broadcast.manifest
tfw_cat -h broadcast
}
doc_MeshMBRestList="Restful list of meshmb messages"
doc_MeshMBRestList="REST API MeshMB list of all messages"
setup_MeshMBRestList() {
setup
executeOk_servald meshmb send $IDA1 "Message 1"
executeOk_servald meshmb send $IDA1 "Message 2"
}
test_MeshMBRestList() {
executeOk curl \
--silent --fail --show-error \
--output listmessages.json \
--dump-header http.headers \
--basic --user harry:potter \
"http://$addr_localhost:$PORTA/restful/meshmb/$IDA1/messagelist.json"
tfw_cat http.headers listmessages.json
tfw_preserve listmessages.json
assert [ "$(jq '.rows | length' listmessages.json)" = 2 ]
transform_list_json listmessages.json list.json
rest_request GET "/restful/meshmb/$IDA1/messagelist.json"
assert [ "$(jq '.rows | length' response.json)" = 2 ]
transform_list_json response.json list.json
tfw_preserve list.json
assertJq list.json \
"contains([
@ -94,7 +112,7 @@ test_MeshMBRestList() {
])"
}
doc_MeshMBRestFollow="Restful follow another feed"
doc_MeshMBRestFollow="REST API MeshMB follow a feed"
setup_MeshMBRestFollow() {
IDENTITY_COUNT=3
setup
@ -103,36 +121,21 @@ setup_MeshMBRestFollow() {
executeOk_servald meshmb send $IDA3 "Message 3"
}
test_MeshMBRestFollow() {
executeOk curl \
--silent --fail --show-error \
--output follow.json \
--basic --user harry:potter \
--request POST \
"http://$addr_localhost:$PORTA/restful/meshmb/$IDA1/follow/$IDA2"
rest_request POST "/restful/meshmb/$IDA1/follow/$IDA2" 201
executeOk_servald meshmb list following $IDA1
assertStdoutGrep --matches=1 ":$IDA2:$SIDA2:false::[0-9]\+:Message 2\$"
assertStdoutGrep --matches=0 ":$IDA3:$SIDA3:false::[0-9]\+:Message 3\$"
executeOk curl \
--silent --fail --show-error \
--output follow.json \
--basic --user harry:potter \
--request POST \
"http://$addr_localhost:$PORTA/restful/meshmb/$IDA1/follow/$IDA3"
rest_request POST "/restful/meshmb/$IDA1/follow/$IDA3" 201
executeOk_servald meshmb list following $IDA1
assertStdoutGrep --matches=1 ":$IDA2:$SIDA2:false::[0-9]\+:Message 2\$"
assertStdoutGrep --matches=1 ":$IDA3:$SIDA3:false::[0-9]\+:Message 3\$"
executeOk curl \
--silent --fail --show-error \
--output follow.json \
--basic --user harry:potter \
--request POST \
"http://$addr_localhost:$PORTA/restful/meshmb/$IDA1/ignore/$IDA2"
rest_request POST "/restful/meshmb/$IDA1/ignore/$IDA2" 201
executeOk_servald meshmb list following $IDA1
assertStdoutGrep --matches=0 ":$IDA2:$SIDA2:false::[0-9]\+:Message 2\$"
assertStdoutGrep --matches=1 ":$IDA3:$SIDA3:false::[0-9]\+:Message 3\$"
}
doc_MeshMBRestFeeds="Restful list subscribed feeds"
doc_MeshMBRestFeeds="REST API MeshMB list subscribed feeds"
setup_MeshMBRestFeeds() {
IDENTITY_COUNT=3
setup
@ -143,16 +146,9 @@ setup_MeshMBRestFeeds() {
executeOk_servald meshmb follow $IDA1 $IDA3
}
test_MeshMBRestFeeds() {
executeOk curl \
--silent --fail --show-error \
--output feedlist.json \
--dump-header http.headers \
--basic --user harry:potter \
"http://$addr_localhost:$PORTA/restful/meshmb/$IDA1/feedlist.json"
tfw_cat http.headers feedlist.json
tfw_preserve feedlist.json
assert [ "$(jq '.rows | length' feedlist.json)" = 2 ]
transform_list_json feedlist.json list.json
rest_request GET "/restful/meshmb/$IDA1/feedlist.json"
assert [ "$(jq '.rows | length' response.json)" = 2 ]
transform_list_json response.json list.json
tfw_preserve list.json
assertJq list.json \
"contains([
@ -168,26 +164,19 @@ test_MeshMBRestFeeds() {
])"
}
doc_MeshMBRestEmptyActivity="Restful activity with no content"
doc_MeshMBRestEmptyActivity="REST API MeshMB activity with no content"
setup_MeshMBRestEmptyActivity() {
IDENTITY_COUNT=1
setup
}
test_MeshMBRestEmptyActivity() {
executeOk --timeout=10 curl \
--silent --fail --show-error \
--output activity.json \
--dump-header http.headers \
--basic --user harry:potter \
"http://$addr_localhost:$PORTA/restful/meshmb/$IDA1/activity.json"
tfw_cat http.headers activity.json
tfw_preserve activity.json
assert [ "$(jq '.rows | length' activity.json)" = 0 ]
transform_list_json activity.json list.json
rest_request GET "/restful/meshmb/$IDA1/activity.json"
assert [ "$(jq '.rows | length' response.json)" = 0 ]
transform_list_json response.json list.json
tfw_preserve list.json
}
doc_MeshMBRestActivity="Restful thread incoming activity"
doc_MeshMBRestActivity="REST API MeshMB thread incoming activity"
setup_MeshMBRestActivity() {
IDENTITY_COUNT=5
setup
@ -218,18 +207,10 @@ setup_MeshMBRestActivity() {
executeOk_servald meshmb activity $IDA1
}
test_MeshMBRestActivity() {
executeOk curl \
--silent --fail --show-error \
--output activity.json \
--dump-header http.headers \
--basic --user harry:potter \
"http://$addr_localhost:$PORTA/restful/meshmb/$IDA1/activity.json"
tfw_cat http.headers activity.json
tfw_preserve activity.json
assert [ "$(jq '.rows | length' activity.json)" = 10 ]
transform_list_json activity.json list.json
rest_request GET "/restful/meshmb/$IDA1/activity.json"
assert [ "$(jq '.rows | length' response.json)" = 10 ]
transform_list_json response.json list.json
tfw_preserve list.json
assertJq list.json "contains([{ __index: 0, id: \"$IDA1\", author: \"$SIDA1\", name: \"Feed A\", message: \"Message 11\"}])"
assertJq list.json "contains([{ __index: 1, id: \"$IDA5\", author: \"$SIDA5\", name: \"Feed E\", message: \"Message 10\"}])"
assertJq list.json "contains([{ __index: 2, id: \"$IDA4\", author: \"$SIDA4\", name: \"Feed D\", message: \"Message 9\"}])"
@ -242,7 +223,7 @@ test_MeshMBRestActivity() {
assertJq list.json "contains([{ __index: 9, id: \"$IDA2\", author: \"$SIDA2\", name: \"Feed B\", message: \"Message 2\"}])"
}
doc_MeshMBRestNewActivity="Restful newsince incoming activity"
doc_MeshMBRestNewActivity="REST API MeshMB newsince incoming activity"
setup_MeshMBRestNewActivity() {
IDENTITY_COUNT=3
setup
@ -253,52 +234,44 @@ setup_MeshMBRestNewActivity() {
executeOk_servald meshmb send $IDA3 "Message 2"
executeOk_servald meshmb follow $IDA1 $IDA2
executeOk_servald meshmb follow $IDA1 $IDA3
executeOk curl \
--silent --fail --show-error \
--output activity.json \
--dump-header http.headers \
--basic --user harry:potter \
"http://$addr_localhost:$PORTA/restful/meshmb/$IDA1/activity.json"
assert [ "$(jq '.rows | length' activity.json)" = 2 ]
transform_list_json activity.json array_of_objects.json
rest_request GET "/restful/meshmb/$IDA1/activity.json"
assert [ "$(jq '.rows | length' response.json)" = 2 ]
transform_list_json response.json array_of_objects.json
tfw_preserve array_of_objects.json
token=$(jq --raw-output '.[0][".token"]' array_of_objects.json)
assert [ -n "$token" ]
}
test_MeshMBRestNewActivity() {
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/meshmb/$IDA1/activity/$token/activity.json"
fork %client$i rest_request GET "/restful/meshmb/$IDA1/activity/$token/activity.json" \
--output=response$i.json \
--no-buffer
done
wait_until [ -e newsince1.json -a -e newsince2.json -a -e newsince3.json ]
wait_until [ -e response1.json -a -e response2.json -a -e response3.json ]
executeOk_servald meshmb send $IDA2 "Message 3"
executeOk_servald meshmb send $IDA3 "Message 4"
executeOk_servald meshmb send $IDA2 "Message 5"
executeOk_servald meshmb send $IDA3 "Message 6"
executeOk_servald meshmb send $IDA1 "Message 7"
for i in 1 2 3; do
wait_until grep "Message 3" newsince$i.json
wait_until grep "Message 4" newsince$i.json
wait_until grep "Message 5" newsince$i.json
wait_until grep "Message 6" newsince$i.json
wait_until grep "Message 7" newsince$i.json
wait_until grep "Message 3" response$i.json
wait_until grep "Message 4" response$i.json
wait_until grep "Message 5" response$i.json
wait_until grep "Message 6" response$i.json
wait_until grep "Message 7" response$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 ]
if [ $(jq . response$i | wc -c) -eq 0 ]; then
echo ']}' >>response$i.json
assert [ $(jq . response$i.json | wc -c) -ne 0 ]
fi
transform_list_json newsince$i.json objects$i.json
tfw_preserve newsince$i.json objects$i.json
transform_list_json response$i.json objects$i.json
tfw_preserve response$i.json objects$i.json
done
for i in 1 2 3; do
assert [ "$(jq '.rows | length' newsince$i.json)" = 5 ]
assert [ "$(jq '.rows | length' response$i.json)" = 5 ]
assertJq objects$i.json "contains([{ id: \"$IDA2\", author: \"$SIDA2\", name: \"Feed B\", message: \"Message 3\"}])"
assertJq objects$i.json "contains([{ id: \"$IDA3\", author: \"$SIDA3\", name: \"Feed C\", message: \"Message 4\"}])"
assertJq objects$i.json "contains([{ id: \"$IDA2\", author: \"$SIDA2\", name: \"Feed B\", message: \"Message 5\"}])"
@ -307,6 +280,4 @@ test_MeshMBRestNewActivity() {
done
}
runTests "$@"

View File

@ -1,8 +1,9 @@
#!/bin/bash
# Tests for Serval DNA MeshMS HTTP RESTful interface
# Tests for Serval DNA MeshMS REST API
#
# Copyright 2013-2014 Serval Project, Inc.
# Copyright 2016-2018 Flinders University
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@ -20,18 +21,15 @@
source "${0%/*}/../testframework.sh"
source "${0%/*}/../testdefs.sh"
source "${0%/*}/../testdefs_json.sh"
source "${0%/*}/../testdefs_rest.sh"
source "${0%/*}/../testdefs_meshms.sh"
shopt -s extglob
setup_instance() {
set_instance $1
setup_rest_config
set_meshms_config
executeOk_servald config \
set api.restful.users.harry.password potter \
set api.restful.users.ron.password weasley \
set api.restful.users.hermione.password grainger
set_extra_config
if [ -z "$IDENTITY_COUNT" ]; then
create_single_identity
@ -41,14 +39,12 @@ setup_instance() {
}
setup() {
setup_curl 7
setup_json
setup_rest_utilities
setup_servald
export SERVALD_RHIZOME_DB_RETRY_LIMIT_MS=60000
setup_instance +A
start_servald_instances +A
wait_until servald_restful_http_server_started +A
get_servald_restful_http_server_port PORTA +A
wait_until_rest_server_ready +A
}
finally() {
@ -67,88 +63,41 @@ set_extra_config() {
set_meshms_config() {
executeOk_servald config \
set debug.http_server on \
set debug.httpd on \
set debug.meshms on \
set debug.verbose on \
set log.console.level debug
}
doc_AuthBasicMissing="HTTP RESTful missing Basic Authentication credentials"
doc_AuthBasicMissing="REST API 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/meshms/$SIDA/conversationlist.json"
assertStdoutIs '401'
assertGrep http.headers "^WWW-Authenticate: Basic realm=\"Serval RESTful API\"$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
rest_request GET "/restful/meshms/$SIDA/conversationlist.json" 401 --no-auth
assertGrep response.headers "^WWW-Authenticate: Basic realm=\"Serval RESTful API\"$CR\$"
assertJq response.json 'contains({"http_status_code": 401})'
assertJq response.json 'contains({"http_status_message": ""})'
}
doc_AuthBasicWrong="HTTP RESTful incorrect Basic Authentication credentials"
doc_AuthBasicWrong="REST API 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/meshms/$SIDA/conversationlist.json"
assertStdoutIs '401'
assertGrep http.headers "^WWW-Authenticate: Basic realm=\"Serval RESTful API\"$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/meshms/$SIDA/conversationlist.json"
assertStdoutIs '200'
}
teardown_AuthBasicWrong() {
tfw_cat http.headers http.output
teardown
rest_request GET "/restful/meshms/$SIDA/conversationlist.json" 401 --user=fred:nurks
assertGrep response.headers "^WWW-Authenticate: Basic realm=\"Serval RESTful API\"$CR\$"
assertJq response.json 'contains({"http_status_code": 401})'
assertJq response.json 'contains({"http_status_message": ""})'
rest_request GET "/restful/meshms/$SIDA/conversationlist.json" 200 --user=ron:weasley
}
doc_MeshmsTalkToYourself="HTTP RESTful talk to yourself"
doc_MeshmsTalkToYourself="REST API talk to yourself"
setup_MeshmsTalkToYourself() {
IDENTITY_COUNT=1
setup
}
test_MeshmsTalkToYourself() {
executeOk curl \
--silent --fail --show-error \
--output sendmessage.json \
--basic --user harry:potter \
--form "message=Hello World;type=text/plain;charset=utf-8" \
"http://$addr_localhost:$PORTA/restful/meshms/$SIDA1/$SIDA1/sendmessage"
tfw_cat sendmessage.json
tfw_preserve sendmessage.json
executeOk curl \
--silent --fail --show-error \
--output conversationlist.json \
--dump-header http.headers \
--basic --user harry:potter \
"http://$addr_localhost:$PORTA/restful/meshms/$SIDA1/conversationlist.json"
tfw_cat conversationlist.json
tfw_preserve conversationlist.json
executeOk curl \
--silent --fail --show-error \
--output messagelist.json \
--dump-header http.headers \
--basic --user harry:potter \
"http://$addr_localhost:$PORTA/restful/meshms/$SIDA1/$SIDA1/messagelist.json"
tfw_cat messagelist.json
tfw_preserve messagelist.json
rest_request POST "/restful/meshms/$SIDA1/$SIDA1/sendmessage" 201 \
--form-part="message=Hello World;type=text/plain;charset=utf-8"
rest_request GET "/restful/meshms/$SIDA1/conversationlist.json"
rest_request GET "/restful/meshms/$SIDA1/$SIDA1/messagelist.json"
}
doc_MeshmsListConversations="HTTP RESTful list MeshMS conversations as JSON"
doc_MeshmsListConversations="REST API list MeshMS conversations as JSON"
setup_MeshmsListConversations() {
IDENTITY_COUNT=5
setup
@ -159,16 +108,9 @@ setup_MeshmsListConversations() {
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
rest_request GET "/restful/meshms/$SIDA1/conversationlist.json"
assert [ "$(jq '.rows | length' response.json)" = 3 ]
transform_list_json response.json conversations1.json
tfw_preserve conversations1.json
assertJq conversations1.json \
"contains([
@ -201,16 +143,9 @@ test_MeshmsListConversations() {
executeOk_servald meshms read messages $SIDA1
executeOk_servald meshms read messages $SIDA1 $SIDA3
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
rest_request GET "/restful/meshms/$SIDA1/conversationlist.json"
assert [ "$(jq '.rows | length' response.json)" = 3 ]
transform_list_json response.json conversations2.json
tfw_preserve conversations2.json
assertJq conversations2.json \
"contains([
@ -241,7 +176,7 @@ test_MeshmsListConversations() {
])"
}
doc_MeshmsListMessages="HTTP RESTful list MeshMS messages in one conversation as JSON"
doc_MeshmsListMessages="REST API list MeshMS messages in one conversation as JSON"
setup_MeshmsListMessages() {
IDENTITY_COUNT=2
setup
@ -256,16 +191,9 @@ setup_MeshmsListMessages() {
tfw_log "delivered: $delivered_offset; read: $read_offset"
}
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
rest_request GET "/restful/meshms/$SIDA1/$SIDA2/messagelist.json"
assert [ "$(jq '.rows | length' response.json)" = $NROWS ]
transform_list_json response.json messages.json
tfw_preserve messages.json
seen_ack=false
let i=0
@ -300,28 +228,20 @@ test_MeshmsListMessages() {
done
}
doc_MeshmsListMessagesNoIdentity="HTTP RESTful list MeshMS messages from unknown identity"
doc_MeshmsListMessagesNoIdentity="REST API 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 419
assertJq http.body 'contains({"http_status_code": 419})'
assertJqGrep --ignore-case http.body '.http_status_message' 'identity locked'
assertJq http.body 'contains({"meshms_status_code": 2})'
assertJqGrep --ignore-case http.body '.meshms_status_message' 'identity.*unknown'
rest_request GET "/restful/meshms/$SIDX/$SIDA/messagelist.json" 419
assertJq response.json 'contains({"http_status_code": 419})'
assertJqGrep --ignore-case response.json '.http_status_message' 'identity locked'
assertJq response.json 'contains({"meshms_status_code": 2})'
assertJqGrep --ignore-case response.json '.meshms_status_message' 'identity.*unknown'
}
doc_MeshmsEmptyNewSince="HTTP RESTful list MeshMS since token with no messages"
doc_MeshmsEmptyNewSince="REST API list MeshMS since token with no messages"
setup_MeshmsEmptyNewSince() {
IDENTITY_COUNT=2
set_extra_config() {
@ -330,16 +250,10 @@ setup_MeshmsEmptyNewSince() {
setup
}
test_MeshmsEmptyNewSince() {
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/newsince/messagelist.json"
tfw_preserve messagelist.json
rest_request GET "/restful/meshms/$SIDA1/$SIDA2/newsince/messagelist.json"
}
doc_MeshmsListMessagesNewSince="HTTP RESTful list MeshMS messages in one conversation since token as JSON"
doc_MeshmsListMessagesNewSince="REST API list MeshMS messages in one conversation since token as JSON"
setup_MeshmsListMessagesNewSince() {
IDENTITY_COUNT=2
set_extra_config() {
@ -348,14 +262,9 @@ setup_MeshmsListMessagesNewSince() {
setup
meshms_add_messages $SIDA1 $SIDA2 '><>>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
rest_request GET "/restful/meshms/$SIDA1/$SIDA2/messagelist.json"
assert [ "$(jq '.rows | length' response.json)" = $NROWS ]
transform_list_json response.json messages.json
tfw_preserve messages.json
for ((i = 0; i < NROWS; i += 3)); do
token[$i]=$(jq --raw-output '.['$i'].token' messages.json)
@ -364,17 +273,14 @@ setup_MeshmsListMessagesNewSince() {
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"
[ $i -ge 15 ] && fork_wait %client$((i-15))
fork %client$i rest_request GET "/restful/meshms/$SIDA1/$SIDA2/newsince/${token[$i]}/messagelist.json" \
--output=response$i.json \
--no-buffer
done
fork_wait_all
for ((i = 0; i < NROWS; i += 3)); do
transform_list_json messagelist$i.json messages$i.json
transform_list_json response$i.json messages$i.json
tfw_preserve messages$i.json
jq '.[:'$i']' messages.json > messages_expected$i.json
tfw_preserve messages_expected$i.json
@ -392,7 +298,7 @@ grepall() {
return 0
}
doc_MeshmsListMessagesNewSinceArrival="HTTP RESTful list newly arriving MeshMS messages in one conversation as JSON"
doc_MeshmsListMessagesNewSinceArrival="REST API list newly arriving MeshMS messages in one conversation as JSON"
setup_MeshmsListMessagesNewSinceArrival() {
IDENTITY_COUNT=2
set_extra_config() {
@ -404,28 +310,21 @@ setup_MeshmsListMessagesNewSinceArrival() {
meshms_use_restful harry potter
meshms_add_messages $SIDA1 $SIDA2 '><>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
rest_request GET "/restful/meshms/$SIDA1/$SIDA2/messagelist.json"
assert [ "$(jq '.rows | length' response.json)" = $NROWS ]
transform_list_json response.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 --timeout=360 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"
fork %client$i rest_request GET "/restful/meshms/$SIDA1/$SIDA2/newsince/$token/messagelist.json" \
--timeout=360 \
--output=response$i.json \
--no-buffer
done
wait_until [ -e newsince1.json -a -e newsince2.json -a -e newsince3.json ]
wait_until [ -e response1.json -a -e response2.json -a -e response3.json ]
for message in '>Rumplestiltskin' 'A' '<Howdydoody' '>Eulenspiegel'; do
meshms_add_messages $SIDA1 $SIDA2 "${message:0:1}" "${message:1}"
case ${message:0:1} in
@ -433,197 +332,127 @@ test_MeshmsListMessagesNewSinceArrival() {
'A') waitfor="ACK";;
*) error "message=${message}";;
esac
wait_until --timeout=10 grepall "$waitfor" newsince{1,2,3}.json
wait_until --timeout=10 grepall "$waitfor" response{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"
doc_MeshmsSend="REST API 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;type=text/plain;charset=utf-8" \
"http://$addr_localhost:$PORTA/restful/meshms/$SIDA1/$SIDA2/sendmessage"
rest_request POST "/restful/meshms/$SIDA1/$SIDA2/sendmessage" 201 \
--form-part="message=Hello World;type=text/plain;charset=utf-8"
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!;type=text/plain;charset=utf-8" \
"http://$addr_localhost:$PORTA/restful/meshms/$SIDA2/$SIDA1/sendmessage"
rest_request POST "/restful/meshms/$SIDA2/$SIDA1/sendmessage" 201 \
--form-part="message=Hello back!;type=text/plain;charset=utf-8"
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"
doc_MeshmsSendMissingMessage="REST API 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 400
assertJq http.body 'contains({"http_status_code": 400})'
assertJqGrep --ignore-case http.body '.http_status_message' 'missing.*message.*form.*part'
rest_request POST "/restful/meshms/$SIDA2/$SIDA1/sendmessage" 400 --data=''
assertJq response.json 'contains({"http_status_code": 400})'
assertJqGrep --ignore-case response.json '.http_status_message' 'missing.*message.*form.*part'
executeOk_servald meshms list messages $SIDA1 $SIDA2
assertStdoutLineCount '==' 2
}
doc_MeshmsSendDuplicateMessage="HTTP RESTful MeshMS send duplicate 'message' form parts"
doc_MeshmsSendDuplicateMessage="REST API MeshMS send duplicate 'message' form parts"
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;type=text/plain;charset=utf-8" \
--form "message=Hello two;type=text/plain;charset=utf-8" \
"http://$addr_localhost:$PORTA/restful/meshms/$SIDA2/$SIDA1/sendmessage"
tfw_cat http.header http.body
assertExitStatus == 0
assertStdoutIs 400
assertJq http.body 'contains({"http_status_code": 400})'
assertJqGrep --ignore-case http.body '.http_status_message' 'duplicate.*message.*form.*part'
rest_request POST "/restful/meshms/$SIDA2/$SIDA1/sendmessage" 400 \
--form-part="message=Hello one;type=text/plain;charset=utf-8" \
--form-part="message=Hello two;type=text/plain;charset=utf-8"
assertJq response.json 'contains({"http_status_code": 400})'
assertJqGrep --ignore-case response.json '.http_status_message' 'duplicate.*message.*form.*part'
executeOk_servald meshms list messages $SIDA1 $SIDA2
assertStdoutLineCount '==' 2
}
doc_MeshmsSendMessageMissingContentType="HTTP RESTful MeshMS send 'message' form part missing Content-Type"
doc_MeshmsSendMessageMissingContentType="REST API MeshMS send 'message' form part missing Content-Type"
setup_MeshmsSendMessageMissingContentType() {
IDENTITY_COUNT=2
setup
}
test_MeshmsSendMessageMissingContentType() {
execute curl \
--silent --show-error --write-out '%{http_code}' \
--output http.body \
--dump-header http.header \
--basic --user harry:potter \
--form "message=Hello there" \
"http://$addr_localhost:$PORTA/restful/meshms/$SIDA2/$SIDA1/sendmessage"
tfw_cat http.header http.body
assertExitStatus == 0
assertStdoutIs 400
assertJq http.body 'contains({"http_status_code": 400})'
assertJqGrep --ignore-case http.body '.http_status_message' 'missing.*content.*type'
rest_request POST "/restful/meshms/$SIDA2/$SIDA1/sendmessage" 400 \
--form-part="message=Hello there"
assertJq response.json 'contains({"http_status_code": 400})'
assertJqGrep --ignore-case response.json '.http_status_message' 'missing.*content.*type'
executeOk_servald meshms list messages $SIDA1 $SIDA2
assertStdoutLineCount '==' 2
}
doc_MeshmsSendMessageUnsupportedContentType="HTTP RESTful MeshMS send 'message' form part unsupported Content-Type"
doc_MeshmsSendMessageUnsupportedContentType="REST API MeshMS send 'message' form part unsupported Content-Type"
setup_MeshmsSendMessageUnsupportedContentType() {
IDENTITY_COUNT=2
setup
}
test_MeshmsSendMessageUnsupportedContentType() {
execute curl \
--silent --show-error --write-out '%{http_code}' \
--output http.body \
--dump-header http.header \
--basic --user harry:potter \
--form "message=Hello there;type=text/rich" \
"http://$addr_localhost:$PORTA/restful/meshms/$SIDA2/$SIDA1/sendmessage"
tfw_cat http.header http.body
assertExitStatus == 0
assertStdoutIs 415
assertJq http.body 'contains({"http_status_code": 415})'
assertJqGrep --ignore-case http.body '.http_status_message' 'unsupported.*content.*type'
rest_request POST "/restful/meshms/$SIDA2/$SIDA1/sendmessage" 415 \
--form-part="message=Hello there;type=text/rich"
assertJq response.json 'contains({"http_status_code": 415})'
assertJqGrep --ignore-case response.json '.http_status_message' 'unsupported.*content.*type'
executeOk_servald meshms list messages $SIDA1 $SIDA2
assertStdoutLineCount '==' 2
}
doc_MeshmsSendMessageMissingCharset="HTTP RESTful MeshMS send 'message' form part missing charset"
doc_MeshmsSendMessageMissingCharset="REST API MeshMS send 'message' form part missing charset"
setup_MeshmsSendMessageMissingCharset() {
IDENTITY_COUNT=2
setup
}
test_MeshmsSendMessageMissingCharset() {
execute curl \
--silent --show-error --write-out '%{http_code}' \
--output http.body \
--dump-header http.header \
--basic --user harry:potter \
--form "message=Hello there;type=text/plain" \
"http://$addr_localhost:$PORTA/restful/meshms/$SIDA2/$SIDA1/sendmessage"
tfw_cat http.header http.body
assertExitStatus == 0
assertStdoutIs 400
assertJq http.body 'contains({"http_status_code": 400})'
assertJqGrep --ignore-case http.body '.http_status_message' 'missing.*charset'
rest_request POST "/restful/meshms/$SIDA2/$SIDA1/sendmessage" 400 \
--form-part="message=Hello there;type=text/plain"
assertJq response.json 'contains({"http_status_code": 400})'
assertJqGrep --ignore-case response.json '.http_status_message' 'missing.*charset'
executeOk_servald meshms list messages $SIDA1 $SIDA2
assertStdoutLineCount '==' 2
}
doc_MeshmsSendMessageUnsupportedCharset="HTTP RESTful MeshMS send 'message' form part unsupported charset"
doc_MeshmsSendMessageUnsupportedCharset="REST API MeshMS send 'message' form part unsupported charset"
setup_MeshmsSendMessageUnsupportedCharset() {
IDENTITY_COUNT=2
setup
}
test_MeshmsSendMessageUnsupportedCharset() {
execute curl \
--silent --show-error --write-out '%{http_code}' \
--output http.body \
--dump-header http.header \
--basic --user harry:potter \
--form "message=Hello there;type=text/plain;charset=latin-1" \
"http://$addr_localhost:$PORTA/restful/meshms/$SIDA2/$SIDA1/sendmessage"
tfw_cat http.header http.body
assertExitStatus == 0
assertStdoutIs 415
assertJq http.body 'contains({"http_status_code": 415})'
assertJqGrep --ignore-case http.body '.http_status_message' 'unsupported.*charset'
rest_request POST "/restful/meshms/$SIDA2/$SIDA1/sendmessage" 415 \
--form-part="message=Hello there;type=text/plain;charset=latin-1"
assertJq response.json 'contains({"http_status_code": 415})'
assertJqGrep --ignore-case response.json '.http_status_message' 'unsupported.*charset'
executeOk_servald meshms list messages $SIDA1 $SIDA2
assertStdoutLineCount '==' 2
}
doc_MeshmsSendNoIdentity="HTTP RESTful MeshMS send from unknown identity"
doc_MeshmsSendNoIdentity="REST API 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;type=text/plain;charset=utf-8" \
"http://$addr_localhost:$PORTA/restful/meshms/$SIDX/$SIDA/sendmessage"
tfw_cat http.header http.body
assertExitStatus == 0
assertStdoutIs 419
assertJq http.body 'contains({"http_status_code": 419})'
assertJqGrep --ignore-case http.body '.http_status_message' 'identity locked'
assertJq http.body 'contains({"meshms_status_code": 2})'
assertJqGrep --ignore-case http.body '.meshms_status_message' 'identity.*unknown'
rest_request POST "/restful/meshms/$SIDX/$SIDA/sendmessage" 419 \
--form-part="message=Hello;type=text/plain;charset=utf-8"
assertJq response.json 'contains({"http_status_code": 419})'
assertJqGrep --ignore-case response.json '.http_status_message' 'identity locked'
assertJq response.json 'contains({"meshms_status_code": 2})'
assertJqGrep --ignore-case response.json '.meshms_status_message' 'identity.*unknown'
}
doc_MeshmsReadAllConversations="HTTP RESTful MeshMS mark all conversations read"
doc_MeshmsReadAllConversations="REST API MeshMS mark all conversations read"
setup_MeshmsReadAllConversations() {
IDENTITY_COUNT=5
setup
@ -638,22 +467,14 @@ setup_MeshmsReadAllConversations() {
assertStdoutGrep --stderr --matches=1 ":$SIDA4:unread:14:0\$"
}
test_MeshmsReadAllConversations() {
executeOk curl \
--silent --show-error --write-out '%{http_code}' \
--output http_body \
--basic --user harry:potter \
--request POST \
"http://$addr_localhost:$PORTA/restful/meshms/$SIDA1/readall"
tfw_cat http_body
assertExitStatus == 0
assertStdoutIs 201
rest_request POST "/restful/meshms/$SIDA1/readall" 201
executeOk_servald meshms list conversations $SIDA1
assertStdoutGrep --stderr --matches=1 ":$SIDA2::0:0\$"
assertStdoutGrep --stderr --matches=1 ":$SIDA3::11:11\$"
assertStdoutGrep --stderr --matches=1 ":$SIDA4::14:14\$"
}
doc_MeshmsPostSpuriousContent="HTTP RESTful MeshMS rejects unwanted content in POST request"
doc_MeshmsPostSpuriousContent="REST API MeshMS rejects unwanted content in POST request"
setup_MeshmsPostSpuriousContent() {
IDENTITY_COUNT=2
setup
@ -666,23 +487,14 @@ setup_MeshmsPostSpuriousContent() {
assertStdoutGrep --stderr --matches=1 ":$SIDA2:unread:35:0\$"
}
test_MeshmsPostSpuriousContent() {
executeOk curl \
--silent --show-error --write-out '%{http_code}' \
--output http_body \
--basic --user harry:potter \
--request POST \
--form "offset=0" \
"http://$addr_localhost:$PORTA/restful/meshms/$SIDA1/readall"
tfw_cat http_body
assertExitStatus == 0
assertStdoutIs 400
assertJq http_body 'contains({"http_status_code": 400})'
assertJqGrep --ignore-case http_body '.http_status_message' 'content length'
rest_request POST "/restful/meshms/$SIDA1/readall" 400 --form-part="offset=0"
assertJq response.json 'contains({"http_status_code": 400})'
assertJqGrep --ignore-case response.json '.http_status_message' 'content length'
executeOk_servald meshms list conversations $SIDA1
assertStdoutGrep --stderr --matches=1 ":$SIDA2:unread:35:0\$"
}
doc_MeshmsReadAllMessages="HTTP RESTful MeshMS mark all conversations read"
doc_MeshmsReadAllMessages="REST API MeshMS mark all conversations read"
setup_MeshmsReadAllMessages() {
IDENTITY_COUNT=5
setup
@ -699,20 +511,12 @@ setup_MeshmsReadAllMessages() {
assertStdoutGrep --stderr --matches=1 ":$SIDA1:unread:45:0\$"
}
test_MeshmsReadAllMessages() {
executeOk curl \
--silent --show-error --write-out '%{http_code}' \
--output http_body \
--basic --user harry:potter \
--request POST \
"http://$addr_localhost:$PORTA/restful/meshms/$SIDA2/$SIDA1/readall"
tfw_cat http_body
assertExitStatus == 0
assertStdoutIs 201
rest_request POST "/restful/meshms/$SIDA2/$SIDA1/readall" 201
executeOk_servald meshms list conversations $SIDA2
assertStdoutGrep --stderr --matches=1 ":$SIDA1::45:45\$"
}
doc_MeshmsReadMessage="HTTP RESTful MeshMS mark a message as read"
doc_MeshmsReadMessage="REST API MeshMS mark a message as read"
setup_MeshmsReadMessage() {
IDENTITY_COUNT=5
setup
@ -727,34 +531,17 @@ setup_MeshmsReadMessage() {
assertStdoutGrep --stderr --matches=1 ":$SIDA1:unread:45:0\$"
}
test_MeshmsReadMessage() {
executeOk curl \
--silent --show-error --write-out '%{http_code}' \
--output http_body \
--basic --user harry:potter \
--request POST \
"http://$addr_localhost:$PORTA/restful/meshms/$SIDA2/$SIDA1/recv/22/read"
tfw_cat http_body
assertExitStatus == 0
assertStdoutIs 201
rest_request POST "/restful/meshms/$SIDA2/$SIDA1/recv/22/read" 201
executeOk_servald meshms list conversations $SIDA2
assertStdoutGrep --stderr --matches=1 ":$SIDA1:unread:45:22\$"
executeOk curl \
--silent --show-error --write-out '%{http_code}' \
--output read.json \
--basic --user harry:potter \
--request POST \
"http://$addr_localhost:$PORTA/restful/meshms/$SIDA2/$SIDA1/recv/11/read"
tfw_cat read.json
assertExitStatus == 0
assertStdoutIs 200
rest_request POST "/restful/meshms/$SIDA2/$SIDA1/recv/11/read" 200
executeOk_servald meshms list conversations $SIDA2
assertStdoutGrep --stderr --matches=1 ":$SIDA1:unread:45:22\$"
}
doc_sendFlood="Send lots of messages over the network"
doc_sendFlood="REST API send lots of MeshMS messages"
setup_sendFlood() {
setup_curl 7
setup_json
setup_rest_utilities
setup_servald
export SERVALD_RHIZOME_DB_RETRY_LIMIT_MS=60000
set_extra_config() {
@ -763,11 +550,8 @@ setup_sendFlood() {
setup_instance +A
setup_instance +B
start_servald_instances +A +B
wait_until servald_restful_http_server_started +A
get_servald_restful_http_server_port PORTA +A
wait_until servald_restful_http_server_started +B
get_servald_restful_http_server_port PORTB +B
tfw_log "PORTA = $PORTA, PORTB = $PORTB"
wait_until_rest_server_ready +A
wait_until_rest_server_ready +B
}
test_sendFlood() {
set_instance +A
@ -776,12 +560,9 @@ test_sendFlood() {
for (( i=0; i<5; i++ ))
do
tfw_log "Sending message $i $j"
curl \
--silent --fail --show-error \
--output /dev/null \
--basic --user harry:potter \
--form "message=0123456789012345678901234567890123456789 $(date +%s%N) $j $i;type=text/plain;charset=utf-8" \
"http://$addr_localhost:$PORTA/restful/meshms/$SIDA/$SIDB/sendmessage"
rest_request +A POST "/restful/meshms/$SIDA/$SIDB/sendmessage" 201 \
--form-part="message=0123456789012345678901234567890123456789 $(date +%s%N) $j $i;type=text/plain;charset=utf-8" \
--output=request$i.json
done
# TODO wait for sync complete
sleep 2
@ -790,25 +571,13 @@ test_sendFlood() {
tfw_cat --stdout
executeOk_servald route print
tfw_cat --stdout
executeOk curl \
--silent --fail --show-error \
--output conversationlist.json \
--dump-header http.headers \
--basic --user harry:potter \
"http://$addr_localhost:$PORTB/restful/meshms/$SIDB/conversationlist.json"
tfw_cat http.headers conversationlist.json
rest_request GET "/restful/meshms/$SIDB/conversationlist.json"
done
set_instance +B
executeOk curl \
--silent --fail --show-error \
--output conversationlist.json \
--dump-header http.headers \
--basic --user harry:potter \
"http://$addr_localhost:$PORTB/restful/meshms/$SIDB/conversationlist.json"
tfw_cat http.headers conversationlist.json
rest_request GET "/restful/meshms/$SIDB/conversationlist.json"
}
doc_unicode="Send and receive unicode emoticons"
doc_unicode="REST API MeshMS UTF-8 emoticons"
setup_unicode() {
IDENTITY_COUNT=2
setup
@ -817,21 +586,11 @@ test_unicode() {
SMILEY1=`echo -e "\xf0\x9f\x98\x80\x0a"`
SMILEY2=`echo -e "\xf0\x9f\x98\x90\x0a"`
executeOk_servald meshms send message $SIDA1 $SIDA2 "$SMILEY1"
executeOk curl \
--silent --fail --show-error \
--output sendmessage.json \
--basic --user harry:potter \
--form "message=$SMILEY2;type=text/plain;charset=utf-8" \
"http://$addr_localhost:$PORTA/restful/meshms/$SIDA2/$SIDA1/sendmessage"
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 messagelist.json
assertGrep --matches=1 messagelist.json '\\uD83D\\uDE10'
assertGrep --matches=1 messagelist.json '\\uD83D\\uDE00'
rest_request POST "/restful/meshms/$SIDA2/$SIDA1/sendmessage" 201 \
--form-part="message=$SMILEY2;type=text/plain;charset=utf-8"
rest_request GET "/restful/meshms/$SIDA1/$SIDA2/messagelist.json"
assertGrep --matches=1 response.json '\\uD83D\\uDE10'
assertGrep --matches=1 response.json '\\uD83D\\uDE00'
executeOk_servald meshms list messages $SIDA1 $SIDA2
tfw_cat --stdout
assertStdoutGrep --matches=1 "$SMILEY1"

File diff suppressed because it is too large Load Diff