Skip to content

Commit 5d71300

Browse files
committed
tests: add audio-record prompting integration tests
Signed-off-by: Oliver Calder <oliver.calder@canonical.com>
1 parent dee46fb commit 5d71300

10 files changed

Lines changed: 438 additions & 0 deletions

File tree

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
{
2+
"version": 1,
3+
"prompt-filter": {
4+
"snap": "prompt-requester",
5+
"interface": "audio-record",
6+
"constraints": {
7+
"path": "$BASE_PATH/.*"
8+
}
9+
},
10+
"prompts": [
11+
{
12+
"prompt-filter": {
13+
"interface": "audio-record",
14+
"constraints": {
15+
"requested-permissions": [ "access" ]
16+
}
17+
},
18+
"reply": {
19+
"action": "allow",
20+
"lifespan": "single",
21+
"constraints": {
22+
"permissions": [ "access" ]
23+
}
24+
}
25+
},
26+
{
27+
"prompt-filter": {
28+
"interface": "audio-record",
29+
"constraints": {
30+
"requested-permissions": [ "access" ]
31+
}
32+
},
33+
"reply": {
34+
"action": "deny",
35+
"lifespan": "single",
36+
"constraints": {
37+
"permissions": [ "access" ]
38+
}
39+
}
40+
},
41+
{
42+
"prompt-filter": {
43+
"interface": "audio-record",
44+
"constraints": {
45+
"requested-permissions": [ "access" ]
46+
}
47+
},
48+
"reply": {
49+
"action": "deny",
50+
"lifespan": "single",
51+
"constraints": {
52+
"permissions": [ "access" ]
53+
}
54+
}
55+
},
56+
{
57+
"prompt-filter": {
58+
"interface": "audio-record",
59+
"constraints": {
60+
"requested-permissions": [ "access" ]
61+
}
62+
},
63+
"reply": {
64+
"action": "allow",
65+
"lifespan": "single",
66+
"constraints": {
67+
"permissions": [ "access" ]
68+
}
69+
}
70+
},
71+
{
72+
"prompt-filter": {
73+
"interface": "audio-record",
74+
"constraints": {
75+
"requested-permissions": [ "access" ]
76+
}
77+
},
78+
"reply": {
79+
"action": "allow",
80+
"lifespan": "single",
81+
"constraints": {
82+
"permissions": [ "access" ]
83+
}
84+
}
85+
}
86+
]
87+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#!/usr/bin/sh
2+
3+
# A test of allow once for the audio-record interface.
4+
5+
TEST_DIR="$1"
6+
TIMEOUT="$2"
7+
if [ -z "$TIMEOUT" ] ; then
8+
TIMEOUT=10
9+
fi
10+
11+
# The audio-record interface doesn't use a target file to trigger a prompt.
12+
# Instead, we use a file to tell the snap to finish running. We need a snap
13+
# running under a cgroup in order for the "ask" request to be handled correctly.
14+
TARGET_FILE="${TEST_DIR}/finish"
15+
16+
# Start the snap running in the background so "ask" can use its PID to look up
17+
# its cgroup, and from that derive the snap name.
18+
prompt-requester.wait-for "$TARGET_FILE" &
19+
WAITER_SHELL_PID="$!"
20+
21+
# Background PID will be of the /snap/bin command, not the internal script, so
22+
# need to get the real PID. The snap will write its own PID to
23+
# $HOME/snap/prompt-requester/current/running.pid
24+
retry --wait 1 -n 10 test -f "$HOME/snap/prompt-requester/current/running.pid"
25+
WAITER_SNAP_PID="$(cat "$HOME/snap/prompt-requester/current/running.pid")"
26+
27+
test "$WAITER_SHELL_PID" = "$WAITER_SNAP_PID"
28+
29+
# Actually trigger the request by querying the API
30+
ASK_BODY="{\"action\": \"ask\", \"interface\": \"audio-record\", \"pid\": $WAITER_SNAP_PID}"
31+
RESULT="$(echo "$ASK_BODY" | snap debug api -X POST -H 'Content-Type: application/json' "/v2/interfaces/requests")"
32+
MATCH '"status-code": 200' < "$RESULT"
33+
MATCH '"outcome": "allow"' < "$RESULT"
34+
35+
# Trigger a second request
36+
ASK_BODY="{\"action\": \"ask\", \"interface\": \"audio-record\", \"pid\": $WAITER_SNAP_PID}"
37+
RESULT="$(echo "$ASK_BODY" | snap debug api -X POST -H 'Content-Type: application/json' "/v2/interfaces/requests")"
38+
MATCH '"status-code": 200' < "$RESULT"
39+
MATCH '"outcome": "deny"' < "$RESULT"
40+
41+
# Trigger a third request
42+
ASK_BODY="{\"action\": \"ask\", \"interface\": \"audio-record\", \"pid\": $WAITER_SNAP_PID}"
43+
RESULT="$(echo "$ASK_BODY" | snap debug api -X POST -H 'Content-Type: application/json' "/v2/interfaces/requests")"
44+
MATCH '"status-code": 200' < "$RESULT"
45+
MATCH '"outcome": "deny"' < "$RESULT"
46+
47+
# Trigger a fourth request
48+
ASK_BODY="{\"action\": \"ask\", \"interface\": \"audio-record\", \"pid\": $WAITER_SNAP_PID}"
49+
RESULT="$(echo "$ASK_BODY" | snap debug api -X POST -H 'Content-Type: application/json' "/v2/interfaces/requests")"
50+
MATCH '"status-code": 200' < "$RESULT"
51+
MATCH '"outcome": "allow"' < "$RESULT"
52+
53+
# Trigger a fifth request
54+
ASK_BODY="{\"action\": \"ask\", \"interface\": \"audio-record\", \"pid\": $WAITER_SNAP_PID}"
55+
RESULT="$(echo "$ASK_BODY" | snap debug api -X POST -H 'Content-Type: application/json' "/v2/interfaces/requests")"
56+
MATCH '"status-code": 200' < "$RESULT"
57+
MATCH '"outcome": "allow"' < "$RESULT"
58+
59+
# Tell the waiter to stop waiting
60+
touch "$TARGET_FILE"
61+
wait "$WAITER_SHELL_PID"
62+
63+
# Wait for the client to write its result and exit
64+
timeout "$TIMEOUT" sh -c "while pgrep -f 'prompting-client.scripted.*${TEST_DIR}' > /dev/null; do sleep 0.1; done"
65+
66+
CLIENT_OUTPUT="$(cat "${TEST_DIR}/result")"
67+
68+
if [ "$CLIENT_OUTPUT" != "success" ] ; then
69+
echo "test failed"
70+
echo "output='$CLIENT_OUTPUT'"
71+
exit 1
72+
fi
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
{
2+
"version": 1,
3+
"prompt-filter": {
4+
"snap": "prompt-requester",
5+
"interface": "audio-record",
6+
"constraints": {
7+
"path": "$BASE_PATH/.*"
8+
}
9+
},
10+
"prompts": [
11+
{
12+
"prompt-filter": {
13+
"interface": "audio-record",
14+
"constraints": {
15+
"requested-permissions": [ "access" ]
16+
}
17+
},
18+
"reply": {
19+
"action": "allow",
20+
"lifespan": "timespan",
21+
"duration": "10s",
22+
"constraints": {
23+
"permissions": [ "access" ]
24+
}
25+
}
26+
},
27+
{
28+
"prompt-filter": {
29+
"interface": "audio-record",
30+
"constraints": {
31+
"requested-permissions": [ "access" ]
32+
}
33+
},
34+
"reply": {
35+
"action": "deny",
36+
"lifespan": "single",
37+
"constraints": {
38+
"permissions": [ "access" ]
39+
}
40+
}
41+
}
42+
]
43+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#!/usr/bin/sh
2+
3+
# A test of allow with timespan for the audio-record interface.
4+
5+
TEST_DIR="$1"
6+
TIMEOUT="$2"
7+
if [ -z "$TIMEOUT" ] ; then
8+
TIMEOUT=10
9+
fi
10+
11+
# The audio-record interface doesn't use a target file to trigger a prompt.
12+
# Instead, we use a file to tell the snap to finish running. We need a snap
13+
# running under a cgroup in order for the "ask" request to be handled correctly.
14+
TARGET_FILE="${TEST_DIR}/finish"
15+
16+
# Start the snap running in the background so "ask" can use its PID to look up
17+
# its cgroup, and from that derive the snap name.
18+
prompt-requester.wait-for "$TARGET_FILE" &
19+
WAITER_SHELL_PID="$!"
20+
21+
# Background PID will be of the /snap/bin command, not the internal script, so
22+
# need to get the real PID. The snap will write its own PID to
23+
# $HOME/snap/prompt-requester/current/running.pid
24+
retry --wait 1 -n 10 test -f "$HOME/snap/prompt-requester/current/running.pid"
25+
WAITER_SNAP_PID="$(cat "$HOME/snap/prompt-requester/current/running.pid")"
26+
27+
test "$WAITER_SHELL_PID" = "$WAITER_SNAP_PID"
28+
29+
# Actually trigger the request by querying the API
30+
ASK_BODY="{\"action\": \"ask\", \"interface\": \"audio-record\", \"pid\": $WAITER_SNAP_PID}"
31+
RESULT="$(echo "$ASK_BODY" | snap debug api -X POST -H 'Content-Type: application/json' "/v2/interfaces/requests")"
32+
MATCH '"status-code": 200' < "$RESULT"
33+
MATCH '"outcome": "allow"' < "$RESULT"
34+
35+
# Trigger a second request
36+
ASK_BODY="{\"action\": \"ask\", \"interface\": \"audio-record\", \"pid\": $WAITER_SNAP_PID}"
37+
RESULT="$(echo "$ASK_BODY" | snap debug api -X POST -H 'Content-Type: application/json' "/v2/interfaces/requests")"
38+
MATCH '"status-code": 200' < "$RESULT"
39+
MATCH '"outcome": "allow"' < "$RESULT"
40+
41+
# Trigger a third request
42+
ASK_BODY="{\"action\": \"ask\", \"interface\": \"audio-record\", \"pid\": $WAITER_SNAP_PID}"
43+
RESULT="$(echo "$ASK_BODY" | snap debug api -X POST -H 'Content-Type: application/json' "/v2/interfaces/requests")"
44+
MATCH '"status-code": 200' < "$RESULT"
45+
MATCH '"outcome": "allow"' < "$RESULT"
46+
47+
# Trigger a fourth request
48+
ASK_BODY="{\"action\": \"ask\", \"interface\": \"audio-record\", \"pid\": $WAITER_SNAP_PID}"
49+
RESULT="$(echo "$ASK_BODY" | snap debug api -X POST -H 'Content-Type: application/json' "/v2/interfaces/requests")"
50+
MATCH '"status-code": 200' < "$RESULT"
51+
MATCH '"outcome": "allow"' < "$RESULT"
52+
53+
echo "Wait for the rule to expire"
54+
sleep 10
55+
56+
# Trigger a fifth request
57+
ASK_BODY="{\"action\": \"ask\", \"interface\": \"audio-record\", \"pid\": $WAITER_SNAP_PID}"
58+
RESULT="$(echo "$ASK_BODY" | snap debug api -X POST -H 'Content-Type: application/json' "/v2/interfaces/requests")"
59+
MATCH '"status-code": 200' < "$RESULT"
60+
MATCH '"outcome": "deny"' < "$RESULT"
61+
62+
# Tell the waiter to stop waiting
63+
touch "$TARGET_FILE"
64+
wait "$WAITER_SHELL_PID"
65+
66+
# Wait for the client to write its result and exit
67+
timeout "$TIMEOUT" sh -c "while pgrep -f 'prompting-client.scripted.*${TEST_DIR}' > /dev/null; do sleep 0.1; done"
68+
69+
CLIENT_OUTPUT="$(cat "${TEST_DIR}/result")"
70+
71+
if [ "$CLIENT_OUTPUT" != "success" ] ; then
72+
echo "test failed"
73+
echo "output='$CLIENT_OUTPUT'"
74+
exit 1
75+
fi
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
{
2+
"version": 1,
3+
"prompt-filter": {
4+
"snap": "prompt-requester",
5+
"interface": "audio-record",
6+
"constraints": {
7+
"path": "$BASE_PATH/.*"
8+
}
9+
},
10+
"prompts": [
11+
{
12+
"prompt-filter": {
13+
"interface": "audio-record",
14+
"constraints": {
15+
"requested-permissions": [ "access" ]
16+
}
17+
},
18+
"reply": {
19+
"action": "deny",
20+
"lifespan": "timespan",
21+
"duration": "10s",
22+
"constraints": {
23+
"permissions": [ "access" ]
24+
}
25+
}
26+
},
27+
{
28+
"prompt-filter": {
29+
"interface": "audio-record",
30+
"constraints": {
31+
"requested-permissions": [ "access" ]
32+
}
33+
},
34+
"reply": {
35+
"action": "allow",
36+
"lifespan": "single",
37+
"constraints": {
38+
"permissions": [ "access" ]
39+
}
40+
}
41+
}
42+
]
43+
}

0 commit comments

Comments
 (0)