cannam@150: #!/bin/bash cannam@150: cannam@150: set -eu cannam@150: cannam@158: mydir=$(dirname "$0") cannam@158: cannam@158: piperdir="$mydir"/../../piper cannam@158: vampsdkdir="$mydir"/../../vamp-plugin-sdk cannam@158: bindir="$mydir"/../bin cannam@150: schemadir="$piperdir"/json/schema cannam@150: cannam@150: if [ ! -d "$schemadir" ]; then cannam@150: echo "WARNING: schema directory $schemadir not found, won't be validating JSON schema" 1>&2 cannam@150: fi cannam@150: cannam@150: tmpdir=$(mktemp -d) cannam@150: cannam@150: if [ ! -d "$tmpdir" ]; then cannam@150: echo "Temp directory creation failed" 1>&2 cannam@150: exit 1 cannam@150: fi cannam@150: cannam@150: trap "rm -rf $tmpdir" 0 cannam@150: cannam@150: reqfile="$tmpdir/req.json" cannam@150: respfile="$tmpdir/resp.json" cannam@150: allrespfile="$tmpdir/resp.all" cannam@150: input="$tmpdir/input" cannam@150: expected="$tmpdir/expected" dev@181: expected_less_strict="$tmpdir/expected-less-strict" cannam@150: obtained="$tmpdir/obtained" cannam@150: cannam@220: fail() { cannam@220: local msg="$1" cannam@220: echo " !! $msg!" 1>&2 cannam@220: exit 1 cannam@220: } cannam@220: cannam@150: validate() { cannam@150: local file="$1" cannam@150: local schemaname="$2" cannam@150: if [ -d "$schemadir" ]; then cannam@150: echo " * validating against schema $schemaname... " 1>&2 cannam@150: jsonschema -i "$file" "$schemadir/$schemaname.json" 1>&2 && \ cannam@150: echo " -> validated against schema $schemaname" 1>&2 || \ cannam@220: fail "failed to validate $schemaname" cannam@150: else cannam@150: echo "(schema directory $schemadir not found, skipping validation)" 1>&2 cannam@150: fi cannam@150: } cannam@150: cannam@150: validate_request() { cannam@150: local json="$1" cannam@150: echo "$json" > "$reqfile" cannam@150: validate "$reqfile" "rpcrequest" cannam@150: } cannam@150: cannam@150: validate_response() { cannam@150: local json="$1" cannam@150: echo "$json" > "$respfile" cannam@150: validate "$respfile" "rpcresponse" cannam@150: } cannam@150: cannam@158: # NB this list of commands includes a couple that are expected to fail cannam@158: # (process before configure, configure with nonexistent handle, finish cannam@158: # same handle twice) cannam@150: cat > "$input" <<EOF cannam@150: {"method":"list"} cannam@150: {"method":"list","params": {"from":["vamp-example-plugins","something-nonexistent"]}} cannam@150: {"method":"list","params": {"from":["something-nonexistent"]}} cannam@150: {"method":"load","id":6,"params": {"key":"vamp-example-plugins:percussiononsets","inputSampleRate":44100,"adapterFlags":["AdaptInputDomain","AdaptBufferSize"]}} cannam@158: {"method":"process","params": {"handle": 1, "processInput": { "timestamp": {"s": 0, "n": 0}, "inputBuffers": [ [1,2,3,4,5,6,7,8] ]}}} cannam@185: {"method":"configure","id":"weevil","params":{"handle":1,"configuration":{"framing":{"blockSize": 8,"stepSize":8}, "channelCount": 1, "parameterValues": {"sensitivity": 40, "threshold": 3}}}} cannam@278: {"method":"configure","id":9,"params":{"handle":9999,"configuration":{"framing":{"blockSize": 8,"stepSize":8}, "channelCount": 1, "parameterValues": {"sensitivity": 40, "threshold": 3}}}} cannam@150: {"method":"process","params": {"handle": 1, "processInput": { "timestamp": {"s": 0, "n": 0}, "inputBuffers": [ [1,2,3,4,5,6,7,8] ]}}} cannam@150: {"method":"finish","params": {"handle": 1}} cannam@158: {"method":"finish","id":"blah","params": {"handle": 1}} cannam@150: EOF cannam@150: cannam@150: # Expected output, apart from the plugin list which seems a bit cannam@150: # fragile to check here cannam@150: cat > "$expected" <<EOF cannam@229: {"id": 6, "jsonrpc": "2.0", "method": "load", "result": {"defaultConfiguration": {"channelCount": 1, "framing": {"blockSize": 1024, "stepSize": 1024}, "parameterValues": {"sensitivity": 40, "threshold": 3}}, "handle": 1, "staticData": {"basic": {"description": "Detect percussive note onsets by identifying broadband energy rises", "identifier": "percussiononsets", "name": "Simple Percussion Onset Detector"}, "basicOutputInfo": [{"description": "Percussive note onset locations", "identifier": "onsets", "name": "Onsets"}, {"description": "Broadband energy rise detection function", "identifier": "detectionfunction", "name": "Detection Function"}], "category": ["Time", "Onsets"], "inputDomain": "TimeDomain", "key": "vamp-example-plugins:percussiononsets", "maker": "Vamp SDK Example Plugins", "maxChannelCount": 1, "minChannelCount": 1, "parameters": [{"basic": {"description": "Energy rise within a frequency bin necessary to count toward broadband total", "identifier": "threshold", "name": "Energy rise threshold"}, "defaultValue": 3, "extents": {"max": 20, "min": 0}, "unit": "dB", "valueNames": []}, {"basic": {"description": "Sensitivity of peak detector applied to broadband detection function", "identifier": "sensitivity", "name": "Sensitivity"}, "defaultValue": 40, "extents": {"max": 100, "min": 0}, "unit": "%", "valueNames": []}], "programs": [], "rights": "Code copyright 2006 Queen Mary, University of London, after Dan Barry et al 2005. Freely redistributable (BSD license)", "staticOutputInfo": {"detectionfunction": {"typeURI": "http://purl.org/ontology/af/OnsetDetectionFunction"}, "onsets": {"typeURI": "http://purl.org/ontology/af/Onset"}}, "version": 2}}} cannam@158: {"error": {"code": 0, "message": "error in process request: plugin has not been configured"}, "jsonrpc": "2.0", "method": "process"} cannam@220: {"id": "weevil", "jsonrpc": "2.0", "method": "configure", "result": {"framing": {"blockSize": 8, "stepSize": 8}, "handle": 1, "outputList": [{"basic": {"description": "Percussive note onset locations", "identifier": "onsets", "name": "Onsets"}, "configured": {"binCount": 0, "binNames": [], "hasDuration": false, "sampleRate": 44100, "sampleType": "VariableSampleRate", "unit": ""}, "static": {}}, {"basic": {"description": "Broadband energy rise detection function", "identifier": "detectionfunction", "name": "Detection Function"}, "configured": {"binCount": 1, "binNames": [""], "hasDuration": false, "quantizeStep": 1, "sampleRate": 86.1328125, "sampleType": "FixedSampleRate", "unit": ""}, "static": {}}]}} cannam@158: {"error": {"code": 0, "message": "error in configure request: unknown plugin handle supplied to configure"}, "id": 9, "jsonrpc": "2.0", "method": "configure"} cannam@150: {"jsonrpc": "2.0", "method": "process", "result": {"features": {}, "handle": 1}} cannam@150: {"jsonrpc": "2.0", "method": "finish", "result": {"features": {"detectionfunction": [{"featureValues": [0], "timestamp": {"n": 11609977, "s": 0}}]}, "handle": 1}} cannam@158: {"error": {"code": 0, "message": "error in finish request: unknown plugin handle supplied to finish"}, "id": "blah", "jsonrpc": "2.0", "method": "finish"} cannam@150: EOF cannam@150: dev@179: # We run the whole test three times, dev@178: # to cover (de)serialisation of json and capnp requests and responses dev@178: # as well as exercising both server modes (json and capnp) dev@178: # converting / reading from capnp requests is currently not tested cannam@150: cannam@150: #debugflag=-d cannam@150: debugflag= cannam@150: dev@182: for request_response_conversion in none json_to_json json_to_capnp ; do # nb json_to_capnp must be last: see comment in else case cannam@150: cannam@150: ( export VAMP_PATH="$vampsdkdir"/examples ; cannam@150: while read request ; do cannam@150: validate_request "$request" cannam@150: echo "$request" cannam@150: done | dev@168: if [ "$request_response_conversion" = "none" ]; then cannam@158: "$bindir"/piper-vamp-simple-server $debugflag json dev@168: elif [ "$request_response_conversion" = "json_to_json" ]; then dev@168: "$bindir"/piper-convert request -i json -o json | dev@168: "$bindir"/piper-vamp-simple-server $debugflag json | dev@168: "$bindir"/piper-convert response -i json -o json cannam@150: else dev@168: # The capnp output doesn't preserve the method name in error dev@168: # responses, so replace those now that we've done the json tests dev@168: perl -i -p -e 's/(error.*"method": )"[^"]*"/$1"invalid"/' "$expected" cannam@158: "$bindir"/piper-convert request -i json -o capnp | cannam@158: "$bindir"/piper-vamp-simple-server $debugflag capnp | cannam@158: "$bindir"/piper-convert response -i capnp -o json cannam@150: fi | cannam@150: while read response ; do cannam@150: echo "$response" >> "$allrespfile" cannam@150: validate_response "$response" cannam@150: done cannam@150: ) < "$input" cannam@150: cannam@150: # Skip plugin lists cannam@150: tail -n +4 "$allrespfile" > "$obtained" cannam@150: dev@179: echo "Checking response contents against expected contents..." dev@179: # the expected configuration response is fragile, capnp fills in optional fields, dev@179: # json doesn't - which is fine behaviour, but causes the test to fail - remove empty binCount and binNames dev@178: expected_without_optional_fields=$( cat "$expected" | sed -E 's/\"(binCount|binNames)\": ?((\[\])|0),? ?//g') dev@178: echo "$expected_without_optional_fields" > "$expected_less_strict" dev@178: dev@178: if cmp "$obtained" "$expected" -s || cmp "$obtained" "$expected_less_strict" -s; then dev@178: echo "OK" cannam@150: else dev@178: diff -U 1 "$obtained" "$expected" cannam@150: fi cannam@150: cannam@150: echo "Checking plugin counts from list responses..." cannam@150: cannam@150: # Now check the plugin lists, but as the descriptions etc are cannam@150: # probably a bit fragile, let's just count the number of plugins cannam@150: cannam@150: # First, with no "from" arg to the list call cannam@159: list_no_from=$(head -n +1 "$allrespfile" | fmt -1 | grep '"key"' | wc -l | sed 's/[^0-9]//g') cannam@150: cannam@150: # Now with a "from" arg that includes the library that exists cannam@150: list_with_good_from=$(tail -n +2 "$allrespfile" | head -n +1 | fmt -1 | cannam@159: grep '"key"' | wc -l | sed 's/[^0-9]//g') cannam@150: cannam@150: # Now with a "from" arg that doesn't include any real library cannam@150: list_with_bad_from=$(tail -n +3 "$allrespfile" | head -n +1 | fmt -1 | cannam@159: grep '"key"' | wc -l | sed 's/[^0-9]//g') cannam@150: cannam@150: if [ "$list_no_from" != "6" ]; then cannam@150: echo "Wrong number of plugins from list response without \"from\" arg" cannam@150: echo "Expected 6, obtained $list_no_from" cannam@150: false cannam@150: fi cannam@150: if [ "$list_with_good_from" != "6" ]; then cannam@150: echo "Wrong number of plugins from list response with good \"from\" arg" cannam@150: echo "Expected 6, obtained $list_with_good_from" cannam@150: false cannam@150: fi cannam@150: if [ "$list_with_bad_from" != "0" ]; then cannam@150: echo "Wrong number of plugins from list response with bad \"from\" arg" cannam@150: echo "Expected 0, obtained $list_with_bad_from" cannam@150: false cannam@150: fi cannam@150: echo OK cannam@150: cannam@150: rm "$allrespfile" cannam@150: done cannam@150: cannam@150: echo "Tests succeeded" # set -e at top should ensure we don't get here otherwise