cannam@150
|
1 #!/bin/bash
|
cannam@150
|
2
|
cannam@150
|
3 set -eu
|
cannam@150
|
4
|
cannam@158
|
5 mydir=$(dirname "$0")
|
cannam@158
|
6
|
cannam@158
|
7 piperdir="$mydir"/../../piper
|
cannam@158
|
8 vampsdkdir="$mydir"/../../vamp-plugin-sdk
|
cannam@158
|
9 bindir="$mydir"/../bin
|
cannam@150
|
10 schemadir="$piperdir"/json/schema
|
cannam@150
|
11
|
cannam@150
|
12 if [ ! -d "$schemadir" ]; then
|
cannam@150
|
13 echo "WARNING: schema directory $schemadir not found, won't be validating JSON schema" 1>&2
|
cannam@150
|
14 fi
|
cannam@150
|
15
|
cannam@150
|
16 tmpdir=$(mktemp -d)
|
cannam@150
|
17
|
cannam@150
|
18 if [ ! -d "$tmpdir" ]; then
|
cannam@150
|
19 echo "Temp directory creation failed" 1>&2
|
cannam@150
|
20 exit 1
|
cannam@150
|
21 fi
|
cannam@150
|
22
|
cannam@150
|
23 trap "rm -rf $tmpdir" 0
|
cannam@150
|
24
|
cannam@150
|
25 reqfile="$tmpdir/req.json"
|
cannam@150
|
26 respfile="$tmpdir/resp.json"
|
cannam@150
|
27 allrespfile="$tmpdir/resp.all"
|
cannam@150
|
28 input="$tmpdir/input"
|
cannam@150
|
29 expected="$tmpdir/expected"
|
dev@181
|
30 expected_less_strict="$tmpdir/expected-less-strict"
|
cannam@150
|
31 obtained="$tmpdir/obtained"
|
cannam@150
|
32
|
cannam@220
|
33 fail() {
|
cannam@220
|
34 local msg="$1"
|
cannam@220
|
35 echo " !! $msg!" 1>&2
|
cannam@220
|
36 exit 1
|
cannam@220
|
37 }
|
cannam@220
|
38
|
cannam@150
|
39 validate() {
|
cannam@150
|
40 local file="$1"
|
cannam@150
|
41 local schemaname="$2"
|
cannam@150
|
42 if [ -d "$schemadir" ]; then
|
cannam@150
|
43 echo " * validating against schema $schemaname... " 1>&2
|
cannam@150
|
44 jsonschema -i "$file" "$schemadir/$schemaname.json" 1>&2 && \
|
cannam@150
|
45 echo " -> validated against schema $schemaname" 1>&2 || \
|
cannam@220
|
46 fail "failed to validate $schemaname"
|
cannam@150
|
47 else
|
cannam@150
|
48 echo "(schema directory $schemadir not found, skipping validation)" 1>&2
|
cannam@150
|
49 fi
|
cannam@150
|
50 }
|
cannam@150
|
51
|
cannam@150
|
52 validate_request() {
|
cannam@150
|
53 local json="$1"
|
cannam@150
|
54 echo "$json" > "$reqfile"
|
cannam@150
|
55 validate "$reqfile" "rpcrequest"
|
cannam@150
|
56 }
|
cannam@150
|
57
|
cannam@150
|
58 validate_response() {
|
cannam@150
|
59 local json="$1"
|
cannam@150
|
60 echo "$json" > "$respfile"
|
cannam@150
|
61 validate "$respfile" "rpcresponse"
|
cannam@150
|
62 }
|
cannam@150
|
63
|
cannam@158
|
64 # NB this list of commands includes a couple that are expected to fail
|
cannam@158
|
65 # (process before configure, configure with nonexistent handle, finish
|
cannam@158
|
66 # same handle twice)
|
cannam@150
|
67 cat > "$input" <<EOF
|
cannam@150
|
68 {"method":"list"}
|
cannam@150
|
69 {"method":"list","params": {"from":["vamp-example-plugins","something-nonexistent"]}}
|
cannam@150
|
70 {"method":"list","params": {"from":["something-nonexistent"]}}
|
cannam@150
|
71 {"method":"load","id":6,"params": {"key":"vamp-example-plugins:percussiononsets","inputSampleRate":44100,"adapterFlags":["AdaptInputDomain","AdaptBufferSize"]}}
|
cannam@158
|
72 {"method":"process","params": {"handle": 1, "processInput": { "timestamp": {"s": 0, "n": 0}, "inputBuffers": [ [1,2,3,4,5,6,7,8] ]}}}
|
cannam@185
|
73 {"method":"configure","id":"weevil","params":{"handle":1,"configuration":{"framing":{"blockSize": 8,"stepSize":8}, "channelCount": 1, "parameterValues": {"sensitivity": 40, "threshold": 3}}}}
|
cannam@278
|
74 {"method":"configure","id":9,"params":{"handle":9999,"configuration":{"framing":{"blockSize": 8,"stepSize":8}, "channelCount": 1, "parameterValues": {"sensitivity": 40, "threshold": 3}}}}
|
cannam@150
|
75 {"method":"process","params": {"handle": 1, "processInput": { "timestamp": {"s": 0, "n": 0}, "inputBuffers": [ [1,2,3,4,5,6,7,8] ]}}}
|
cannam@150
|
76 {"method":"finish","params": {"handle": 1}}
|
cannam@158
|
77 {"method":"finish","id":"blah","params": {"handle": 1}}
|
cannam@150
|
78 EOF
|
cannam@150
|
79
|
cannam@150
|
80 # Expected output, apart from the plugin list which seems a bit
|
cannam@150
|
81 # fragile to check here
|
cannam@150
|
82 cat > "$expected" <<EOF
|
cannam@290
|
83 {"id": 6, "jsonrpc": "2.0", "method": "load", "result": {"defaultConfiguration": {"channelCount": 1, "framing": {"blockSize": 1024, "stepSize": 1024}, "parameterValues": {"sensitivity": 40, "threshold": 3}}, "handle": 1, "programParameters": {}, "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
|
84 {"error": {"code": 0, "message": "error in process request: plugin has not been configured"}, "jsonrpc": "2.0", "method": "process"}
|
cannam@220
|
85 {"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
|
86 {"error": {"code": 0, "message": "error in configure request: unknown plugin handle supplied to configure"}, "id": 9, "jsonrpc": "2.0", "method": "configure"}
|
cannam@150
|
87 {"jsonrpc": "2.0", "method": "process", "result": {"features": {}, "handle": 1}}
|
cannam@150
|
88 {"jsonrpc": "2.0", "method": "finish", "result": {"features": {"detectionfunction": [{"featureValues": [0], "timestamp": {"n": 11609977, "s": 0}}]}, "handle": 1}}
|
cannam@158
|
89 {"error": {"code": 0, "message": "error in finish request: unknown plugin handle supplied to finish"}, "id": "blah", "jsonrpc": "2.0", "method": "finish"}
|
cannam@150
|
90 EOF
|
cannam@150
|
91
|
dev@179
|
92 # We run the whole test three times,
|
dev@178
|
93 # to cover (de)serialisation of json and capnp requests and responses
|
dev@178
|
94 # as well as exercising both server modes (json and capnp)
|
dev@178
|
95 # converting / reading from capnp requests is currently not tested
|
cannam@150
|
96
|
cannam@150
|
97 #debugflag=-d
|
cannam@150
|
98 debugflag=
|
cannam@150
|
99
|
dev@182
|
100 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
|
101
|
cannam@150
|
102 ( export VAMP_PATH="$vampsdkdir"/examples ;
|
cannam@150
|
103 while read request ; do
|
cannam@150
|
104 validate_request "$request"
|
cannam@150
|
105 echo "$request"
|
cannam@150
|
106 done |
|
dev@168
|
107 if [ "$request_response_conversion" = "none" ]; then
|
cannam@158
|
108 "$bindir"/piper-vamp-simple-server $debugflag json
|
dev@168
|
109 elif [ "$request_response_conversion" = "json_to_json" ]; then
|
dev@168
|
110 "$bindir"/piper-convert request -i json -o json |
|
dev@168
|
111 "$bindir"/piper-vamp-simple-server $debugflag json |
|
dev@168
|
112 "$bindir"/piper-convert response -i json -o json
|
cannam@150
|
113 else
|
dev@168
|
114 # The capnp output doesn't preserve the method name in error
|
dev@168
|
115 # responses, so replace those now that we've done the json tests
|
dev@168
|
116 perl -i -p -e 's/(error.*"method": )"[^"]*"/$1"invalid"/' "$expected"
|
cannam@158
|
117 "$bindir"/piper-convert request -i json -o capnp |
|
cannam@158
|
118 "$bindir"/piper-vamp-simple-server $debugflag capnp |
|
cannam@158
|
119 "$bindir"/piper-convert response -i capnp -o json
|
cannam@150
|
120 fi |
|
cannam@150
|
121 while read response ; do
|
cannam@150
|
122 echo "$response" >> "$allrespfile"
|
cannam@150
|
123 validate_response "$response"
|
cannam@150
|
124 done
|
cannam@150
|
125 ) < "$input"
|
cannam@150
|
126
|
cannam@150
|
127 # Skip plugin lists
|
cannam@150
|
128 tail -n +4 "$allrespfile" > "$obtained"
|
cannam@150
|
129
|
dev@179
|
130 echo "Checking response contents against expected contents..."
|
dev@179
|
131 # the expected configuration response is fragile, capnp fills in optional fields,
|
dev@179
|
132 # json doesn't - which is fine behaviour, but causes the test to fail - remove empty binCount and binNames
|
dev@178
|
133 expected_without_optional_fields=$( cat "$expected" | sed -E 's/\"(binCount|binNames)\": ?((\[\])|0),? ?//g')
|
dev@178
|
134 echo "$expected_without_optional_fields" > "$expected_less_strict"
|
dev@178
|
135
|
dev@178
|
136 if cmp "$obtained" "$expected" -s || cmp "$obtained" "$expected_less_strict" -s; then
|
dev@178
|
137 echo "OK"
|
cannam@150
|
138 else
|
dev@178
|
139 diff -U 1 "$obtained" "$expected"
|
cannam@150
|
140 fi
|
cannam@150
|
141
|
cannam@150
|
142 echo "Checking plugin counts from list responses..."
|
cannam@150
|
143
|
cannam@150
|
144 # Now check the plugin lists, but as the descriptions etc are
|
cannam@150
|
145 # probably a bit fragile, let's just count the number of plugins
|
cannam@150
|
146
|
cannam@150
|
147 # First, with no "from" arg to the list call
|
cannam@159
|
148 list_no_from=$(head -n +1 "$allrespfile" | fmt -1 | grep '"key"' | wc -l | sed 's/[^0-9]//g')
|
cannam@150
|
149
|
cannam@150
|
150 # Now with a "from" arg that includes the library that exists
|
cannam@150
|
151 list_with_good_from=$(tail -n +2 "$allrespfile" | head -n +1 | fmt -1 |
|
cannam@159
|
152 grep '"key"' | wc -l | sed 's/[^0-9]//g')
|
cannam@150
|
153
|
cannam@150
|
154 # Now with a "from" arg that doesn't include any real library
|
cannam@150
|
155 list_with_bad_from=$(tail -n +3 "$allrespfile" | head -n +1 | fmt -1 |
|
cannam@159
|
156 grep '"key"' | wc -l | sed 's/[^0-9]//g')
|
cannam@150
|
157
|
cannam@150
|
158 if [ "$list_no_from" != "6" ]; then
|
cannam@150
|
159 echo "Wrong number of plugins from list response without \"from\" arg"
|
cannam@150
|
160 echo "Expected 6, obtained $list_no_from"
|
cannam@150
|
161 false
|
cannam@150
|
162 fi
|
cannam@150
|
163 if [ "$list_with_good_from" != "6" ]; then
|
cannam@150
|
164 echo "Wrong number of plugins from list response with good \"from\" arg"
|
cannam@150
|
165 echo "Expected 6, obtained $list_with_good_from"
|
cannam@150
|
166 false
|
cannam@150
|
167 fi
|
cannam@150
|
168 if [ "$list_with_bad_from" != "0" ]; then
|
cannam@150
|
169 echo "Wrong number of plugins from list response with bad \"from\" arg"
|
cannam@150
|
170 echo "Expected 0, obtained $list_with_bad_from"
|
cannam@150
|
171 false
|
cannam@150
|
172 fi
|
cannam@150
|
173 echo OK
|
cannam@150
|
174
|
cannam@150
|
175 rm "$allrespfile"
|
cannam@150
|
176 done
|
cannam@150
|
177
|
cannam@150
|
178 echo "Tests succeeded" # set -e at top should ensure we don't get here otherwise
|