Skip to content

Commit 3ad4526

Browse files
jori-nordicstephanosio
authored andcommitted
tests: Bluetooth: reproduce gatt settings bug
Reproduce #54470. - client connects - client writes to CF & CCC - client bonds - server reboots After this, we would expect to have the CCC and CF values be correctly restored from settings but they are not. Additionally add the same test with BT_PRIVACY=y, which shows that the feature is broken with that config (fixed in a subsequent commit). Signed-off-by: Jonathan Rico <[email protected]>
1 parent 5d46a0c commit 3ad4526

File tree

11 files changed

+122
-7
lines changed

11 files changed

+122
-7
lines changed

tests/bluetooth/bsim_bt/bsim_test_gatt_settings/prj.conf

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,5 @@ CONFIG_BT_SETTINGS=y
2222

2323
CONFIG_BT_GATT_AUTO_DISCOVER_CCC=y
2424
CONFIG_BT_GATT_AUTO_RESUBSCRIBE=n
25+
26+
CONFIG_BT_PRIVACY=n
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
CONFIG_BT=y
2+
CONFIG_BT_PERIPHERAL=y
3+
CONFIG_BT_CENTRAL=y
4+
CONFIG_BT_DEVICE_NAME="GATT settings"
5+
6+
CONFIG_LOG=y
7+
CONFIG_ASSERT=y
8+
CONFIG_BT_TESTING=y
9+
10+
CONFIG_BT_AUTO_PHY_UPDATE=n
11+
CONFIG_BT_AUTO_DATA_LEN_UPDATE=n
12+
CONFIG_BT_GAP_AUTO_UPDATE_CONN_PARAMS=n
13+
14+
CONFIG_BT_SMP=y
15+
CONFIG_BT_GATT_CLIENT=y
16+
CONFIG_BT_GATT_DYNAMIC_DB=y
17+
CONFIG_BT_GATT_CACHING=y
18+
19+
CONFIG_SETTINGS=y
20+
CONFIG_SETTINGS_CUSTOM=y
21+
CONFIG_BT_SETTINGS=y
22+
23+
CONFIG_BT_GATT_AUTO_DISCOVER_CCC=y
24+
CONFIG_BT_GATT_AUTO_RESUBSCRIBE=n
25+
26+
CONFIG_BT_PRIVACY=y

tests/bluetooth/bsim_bt/bsim_test_gatt_settings/src/client.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,22 @@ void client_round_0(void)
2424

2525
conn = connect_as_peripheral();
2626
printk("connected: conn %p\n", conn);
27-
wait_bonded();
2827

2928
gatt_discover();
3029
activate_robust_caching();
3130
/* subscribe to the SC indication, so we don't have to ATT read to
3231
* become change-aware.
3332
*/
3433
gatt_subscribe_to_service_changed(true);
35-
3634
read_test_char(true);
3735

36+
/* We should normally wait until we are bonded to write the CCC / CF
37+
* characteristics, but here we bond after the fact on purpose, to
38+
* simulate a client that has this exact behavior.
39+
* The CCC and CF should still persist on reboot.
40+
*/
41+
wait_bonded();
42+
3843
disconnect(conn);
3944
}
4045

tests/bluetooth/bsim_bt/bsim_test_gatt_settings/src/gatt_utils.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ static struct bt_gatt_attr test_attrs[] = {
7070

7171
BT_GATT_CHARACTERISTIC(&test_chrc_uuid.uuid,
7272
BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE,
73-
BT_GATT_PERM_READ_ENCRYPT |
74-
BT_GATT_PERM_WRITE_ENCRYPT,
73+
BT_GATT_PERM_READ |
74+
BT_GATT_PERM_WRITE,
7575
read_test, write_test, test_value),
7676
};
7777

@@ -361,3 +361,13 @@ void read_test_char(bool expect_success)
361361
{
362362
read_char(gatt_handles[TEST_CHAR], expect_success);
363363
}
364+
365+
void gatt_clear_flags(void)
366+
{
367+
UNSET_FLAG(flag_client_read);
368+
UNSET_FLAG(flag_discovered);
369+
UNSET_FLAG(flag_sc_indicated);
370+
UNSET_FLAG(flag_sc_subscribed);
371+
UNSET_FLAG(flag_written);
372+
UNSET_FLAG(flag_read);
373+
}

tests/bluetooth/bsim_bt/bsim_test_gatt_settings/src/gatt_utils.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ void read_test_char(bool expect_success);
1414
void wait_for_client_read(void);
1515
void gatt_subscribe_to_service_changed(bool subscribe);
1616
void wait_for_sc_indication(void);
17+
void gatt_clear_flags(void);

tests/bluetooth/bsim_bt/bsim_test_gatt_settings/src/server.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,10 @@ void server_round_0(void)
4040
settings_load();
4141

4242
conn = connect_as_central();
43+
wait_for_client_read();
44+
4345
printk("bonding\n");
4446
bond(conn);
45-
46-
wait_for_client_read();
47-
wait_disconnected();
4847
}
4948

5049
void server_round_1(void)
@@ -161,6 +160,9 @@ void server_round_6(void)
161160
/* What is being tested: since this deals with settings it's not the rounds
162161
* themselves, but rather the transitions that test expected behavior.
163162
*
163+
* Round 0 -> 1: test CCC / CF values written before bonding are stored to NVS
164+
* if the server reboots before disconnecting.
165+
*
164166
* Round 1 -> 2: test change-awareness is updated if GATT DB changes _after_ the
165167
* peer has disconnected. In round 2 we also make sure we receive the Service
166168
* Changed indication.

tests/bluetooth/bsim_bt/bsim_test_gatt_settings/src/utils.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66

77
#include "utils.h"
8+
#include "gatt_utils.h"
89
#include <zephyr/sys/__assert.h>
910
#include <zephyr/bluetooth/hci.h>
1011

@@ -30,6 +31,7 @@ static void disconnected(struct bt_conn *conn, uint8_t reason)
3031
{
3132
bt_conn_unref(conn);
3233
UNSET_FLAG(flag_is_connected);
34+
gatt_clear_flags();
3335
}
3436

3537
static void connected(struct bt_conn *conn, uint8_t err)

tests/bluetooth/bsim_bt/bsim_test_gatt_settings/test_scripts/_compile.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,6 @@ source "${bash_source_dir}/_env.sh"
1111
# Place yourself in the test's root (i.e. ./../)
1212
west build -b nrf52_bsim -d build_test && \
1313
cp build_test/zephyr/zephyr.exe "${test_exe}"
14+
15+
west build -b nrf52_bsim -d build_test_2 -- -DCONF_FILE=prj_2.conf && \
16+
cp build_test_2/zephyr/zephyr.exe "${test_2_exe}"

tests/bluetooth/bsim_bt/bsim_test_gatt_settings/test_scripts/_env.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ test_name="$(basename "$(realpath "$bash_source_dir/..")")"
1010
bsim_bin="${BSIM_OUT_PATH}/bin"
1111
BOARD="${BOARD:-nrf52_bsim}"
1212
test_exe="${bsim_bin}/bs_${BOARD}_tests_bluetooth_bsim_bt_${test_name}_prj_conf"
13+
test_2_exe="${bsim_bin}/bs_${BOARD}_tests_bluetooth_bsim_bt_${test_name}_prj_2_conf"
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#!/usr/bin/env bash
2+
# Copyright 2022 Nordic Semiconductor ASA
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
set -eu
6+
bash_source_dir="$(realpath "$(dirname "${BASH_SOURCE[0]}")")"
7+
8+
source "${bash_source_dir}/_env.sh"
9+
simulation_id="${test_name}_2"
10+
verbosity_level=2
11+
process_ids=""
12+
exit_code=0
13+
14+
function Execute() {
15+
if [ ! -f $1 ]; then
16+
echo -e " \e[91m$(pwd)/$(basename $1) cannot be found (did you forget to\
17+
compile it?)\e[39m"
18+
exit 1
19+
fi
20+
$@ &
21+
process_ids="$process_ids $!"
22+
}
23+
24+
: "${BSIM_OUT_PATH:?BSIM_OUT_PATH must be defined}"
25+
26+
cd ${BSIM_OUT_PATH}/bin
27+
28+
# Remove the files used by the custom SETTINGS backend
29+
echo "remove settings files ${simulation_id}_*.log"
30+
rm ${simulation_id}_*.log || true
31+
32+
Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s="${simulation_id}" -D=8 -sim_length=30e6
33+
34+
# Only one `server` device is really running at a time. This is a necessary hack
35+
# because bsim doesn't support plugging devices in and out of a running
36+
# simulation, but this test needs a way to power-cycle the `server` device a few
37+
# times.
38+
#
39+
# Each device will wait until the previous instance (called 'test round') has
40+
# finished executing before starting up.
41+
Execute "$test_2_exe" -v=${verbosity_level} \
42+
-s="${simulation_id}" -d=0 -testid=server -RealEncryption=1 -argstest 0 6 "server_2"
43+
Execute "$test_2_exe" -v=${verbosity_level} \
44+
-s="${simulation_id}" -d=1 -testid=server -RealEncryption=1 -argstest 1 6 "server_2"
45+
Execute "$test_2_exe" -v=${verbosity_level} \
46+
-s="${simulation_id}" -d=2 -testid=server -RealEncryption=1 -argstest 2 6 "server_2"
47+
Execute "$test_2_exe" -v=${verbosity_level} \
48+
-s="${simulation_id}" -d=3 -testid=server -RealEncryption=1 -argstest 3 6 "server_2"
49+
Execute "$test_2_exe" -v=${verbosity_level} \
50+
-s="${simulation_id}" -d=4 -testid=server -RealEncryption=1 -argstest 4 6 "server_2"
51+
Execute "$test_2_exe" -v=${verbosity_level} \
52+
-s="${simulation_id}" -d=5 -testid=server -RealEncryption=1 -argstest 5 6 "server_2"
53+
Execute "$test_2_exe" -v=${verbosity_level} \
54+
-s="${simulation_id}" -d=6 -testid=server -RealEncryption=1 -argstest 6 6 "server_2"
55+
56+
Execute "$test_2_exe" -v=${verbosity_level} \
57+
-s="${simulation_id}" -d=7 -testid=client -RealEncryption=1 -argstest 0 0 "client_2"
58+
59+
for process_id in $process_ids; do
60+
wait $process_id || let "exit_code=$?"
61+
done
62+
exit $exit_code #the last exit code != 0

0 commit comments

Comments
 (0)