public inbox for linux-bluetooth@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH BlueZ v3 00/20] Functional/integration testing
@ 2026-03-22 21:29 Pauli Virtanen
  2026-03-22 21:29 ` [PATCH BlueZ v3 01/20] emulator: btvirt: check pkt lengths, don't get stuck on malformed Pauli Virtanen
                   ` (19 more replies)
  0 siblings, 20 replies; 26+ messages in thread
From: Pauli Virtanen @ 2026-03-22 21:29 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Pauli Virtanen

Add framework for writing tests simulating "real" environments where
BlueZ and other parts of the stack run on different virtual machine
hosts that communicate with each other.

*** v3 ***

https://github.com/pv/bluez/compare/func-test-v2-r..func-test-v3

* fix configure.ac openpty() detection to match TOOLS conditional,
  to fix make distcheck

* properly retry virtio RPC connection if it fails initially

* properly restart VM if previous test hangs

* allow custom parent host side proxy objects, use them for pexpect

* improve --list with out-of-tree test files

* fix missing bus.set_exit_on_disconnect(False) for obex tests

* have --vm-timeout etc. change values also on VM host side

* use larger-memory VM instances for Pipewire, in case ASAN enabled

* set reasonable inside-VM ASAN_OPTION default values

* don't run btvirt under stdbuf, since not compatible with ASAN

*** v2 ***

https://github.com/pv/bluez/compare/func-test-v1-r..func-test-v2

* move unit/func_test -> test/functional & test/pytest_bluez

  The pytest_bluez plugin is in principle reusable for other projects,
  so we can eg. have more complete Pipewire integration tests that can
  live in Pipewire repository.

* openpty() is in -lutil on some platforms, detect this in autoconf

* more emulator adjustments:

  - fix SCO data packet support in btvirt
  - more complete Reset command

* improve logging: get timestamps from kernel, and reorder logs
  to timestamp order, so that lines from different hosts, btmon,
  and parent tester appear in right order regardless of whether
  VM console / btmon is lagging

  - this requires accurate clock sync in the VM, so enable KVM PTP in
    config and run chronyd inside the VMs
  - use virtio port instead of qemu console to export logs, since the
    console has fixed baud rate and is too slow

* add --btmon & export btsnoop dumps from VM hosts

* fix compatibility with older Python versions

* add parametrized_host_config()

* split Pipewire test to A2DP/BAP/HFP and really stream audio.
  These catch the 5.86 regression fixed in 066a164a524e498 and
  the 5.84 one in 6b0a08776a

* add support for tests that reuse tester environment, so they can run
  faster without needing Bluetoothd teardown/setup in between

* add HostPlugin.presetup (mainly for test skipping)

* deal with RPC virtio port buffer possibly containing unflushed
  commands from previous failed test

* add some Agent1 interface tests

* add basic Obex file transfer tests

* add support for logging in to a running test instance (for gdb etc)

* export any core dumps out from test environ

Some bells & whistles:

* add --kernel-build for kernel image build

* test suite Python code formatting checks

***

Implements:

- RPC communication with tester instances running each of the VM hosts.
  Tests run on parent host, which instructs VM hosts what to do.

- Extensible way to add stateful test-specific code inside the VM
  instances

- Logging control: output from different processes running inside the VM
  are separated and can be filtered.

- Test runner framework with Pytest (more convenient than Python/unittest)

- Automatic grouping of tests to minimize VM reboots

- Redirecting USB controllers to use for testing in addition to btvirt

- Fairly straightforward, ~1600 sloc for the framework

There is no requirement that the tests spawn VM instances, the test
runner can be used for any tests written in Python.

See doc/test-functional.rst for various examples.

Also test/functional/test_bluetoothctl_vm.py has some simple cases, and
test/functional/test_pipewire.py for a more complicated setup

    host0(qemu): Pipewire <-> BlueZ <-> kernel
    <-> btvirt
    host1(qemu): kernel <-> BlueZ <-> Pipewire

The framework allows easily passing any data and code between the parent
and VM hosts, so writing tests is straightforward.

***

Some examples:

$ test/test-functional --list -q

test/functional/lib/tests/test_rpc.py::test_basic
test/functional/test_bluetoothctl_vm.py::test_bluetoothctl_pair[hosts0-vm2]
test/functional/test_bluetoothctl_vm.py::test_bluetoothctl_script_show[hosts1-vm1]
test/functional/test_btmgmt_vm.py::test_btmgmt_info[hosts2-vm1]
test/functional/test_pipewire.py::test_pipewire[hosts3-vm2]

$ test/test-functional -v --no-header
======================================= test session starts ========================================
collected 5 items

test/functional/lib/tests/test_rpc.py::test_basic PASSED                                      [ 20%]
test/functional/test_bluetoothctl_vm.py::test_bluetoothctl_script_show[hosts1-vm1] SKIPPED    [ 40%]
test/functional/test_btmgmt_vm.py::test_btmgmt_info[hosts2-vm1] SKIPPED (No kernel image)     [ 60%]
test/functional/test_bluetoothctl_vm.py::test_bluetoothctl_pair[hosts0-vm2] SKIPPED (No k...) [ 80%]
test/functional/test_pipewire.py::test_pipewire[hosts3-vm2] SKIPPED (No kernel image)         [100%]

=================================== 1 passed, 4 skipped in 0.19s ===================================

$ test/test-functional --kernel=../linux
============================= test session starts ==============================
platform linux -- Python 3.14.3, pytest-8.3.5, pluggy-1.6.0
rootdir: /home/pauli/prj/external/bluez/unit
configfile: pytest.ini
plugins: cov-5.0.0, forked-1.6.0, rerunfailures-15.0, timeout-2.4.0, xdist-3.7.0, hypothesis-6.123.0, flaky-3.8.1, anyio-4.12.1
collected 5 items

test/functional/lib/tests/test_rpc.py .                                   [ 20%]
test/functional/test_bluetoothctl_vm.py .                                 [ 40%]
test/functional/test_btmgmt_vm.py .                                       [ 60%]
test/functional/test_bluetoothctl_vm.py .                                 [ 80%]
test/functional/test_pipewire.py .                                        [100%]

============================== 5 passed in 41.92s ==============================

$ test/test-functional --kernel=../linux -k test_btmgmt
============================= test session starts ==============================
platform linux -- Python 3.14.3, pytest-8.3.5, pluggy-1.6.0
rootdir: /home/pauli/prj/external/bluez/unit
configfile: pytest.ini
plugins: cov-5.0.0, forked-1.6.0, rerunfailures-15.0, timeout-2.4.0, xdist-3.7.0, hypothesis-6.123.0, flaky-3.8.1, anyio-4.12.1
collected 5 items / 4 deselected / 1 selected

test/functional/test_btmgmt_vm.py .                                       [100%]

======================= 1 passed, 4 deselected in 9.15s ========================

$ grep btmgmt test-functional.log
13:15:42 INFO   rpc.host.0.0        :  client: call_plugin ('call', '__call__', <function run at 0x7f27b81ce140>, ['/home/pauli/prj/external/bluez/build/tools/btmgmt', '--index', '0', 'info']) {'stdout': -1, 'stdin': -3, 'encoding': 'utf-8'}
13:15:42 INFO   host.0.0.rpc        :  server: call_plugin ('call', '__call__', <function run at 0x7fd5e35a1010>, ['/home/pauli/prj/external/bluez/build/tools/btmgmt', '--index', '0', 'info']) {'stdout': -1, 'stdin': -3, 'encoding': 'utf-8'}
13:15:42 INFO   host.0.0.run        :      $ /home/pauli/prj/external/bluez/build/tools/btmgmt --index 0 info

$ test/test-functional --kernel=../linux -k test_btmgmt --log-cli-level=0
============================= test session starts ==============================
platform linux -- Python 3.14.3, pytest-8.3.5, pluggy-1.6.0
rootdir: /home/pauli/prj/external/bluez/unit
configfile: pytest.ini
plugins: cov-5.0.0, forked-1.6.0, rerunfailures-15.0, timeout-2.4.0, xdist-3.7.0, hypothesis-6.123.0, flaky-3.8.1, anyio-4.12.1
collected 5 items / 4 deselected / 1 selected

test/functional/test_btmgmt_vm.py::test_btmgmt_info[hosts2-vm1]
-------------------------------- live log setup --------------------------------
13:00:31 INFO   func_test.lib.env   :  Starting btvirt: /usr/bin/stdbuf -o L -e L /home/pauli/prj/external/bluez/build/emulator/btvirt --server=/tmp/bluez-func-test-8t6ychy8
13:00:31 OUT    btvirt              :  Bluetooth emulator ver 5.86
13:00:31 INFO   func_test.lib.env   :  Starting host: /home/pauli/prj/external/bluez/build/tools/test-runner --kernel=../linux/arch/x86/boot/bzImage -u/tmp/bluez-func-test-8t6ychy8/bt-server-bredrle -o -chardev -o socket,id=ser0,path=/tmp/bluez-func-test-8t6ychy8/bluez-func-test-rpc-0,server=on,wait=off -o -device -o virtio-serial -o -device -o virtserialport,chardev=ser0,name=bluez-func-test-rpc -H -- /usr/bin/python3 -P /home/pauli/prj/external/bluez/test/functional/lib/runner.py /dev/ttyS2
13:00:31 OUT    btvirt              :  Request for /tmp/bluez-func-test-8t6ychy8/bt-server-bredrle
13:00:32 OUT    host.0.0            :  early console in extract_kernel
13:00:32 OUT    host.0.0            :  input_data: 0x000000000425c2c4
...
13:00:39 INFO   rpc.host.0.0        :  client: call_plugin ('call', '__call__', <function run at 0x7f7547472140>, ['/home/pauli/prj/external/bluez/build/tools/btmgmt', '--index', '0', 'info']) {'stdout': -1, 'stdin': -3, 'encoding': 'utf-8'}
13:00:39 DEBUG  host.0.0.rpc        :  server: done
13:00:39 INFO   host.0.0.rpc        :  server: call_plugin ('call', '__call__', <function run at 0x7f77dcc81010>, ['/home/pauli/prj/external/bluez/build/tools/btmgmt', '--index', '0', 'info']) {'stdout': -1, 'stdin': -3, 'encoding': 'utf-8'}
13:00:39 INFO   host.0.0.run        :      $ /home/pauli/prj/external/bluez/build/tools/btmgmt --index 0 info
13:00:40 OUT    host.0.0.run.out    :  hci0:	Primary controller
13:00:40 OUT    host.0.0.run.out    :  	addr 00:AA:01:00:00:42 version 11 manufacturer 1521 class 0x000000
13:00:40 OUT    host.0.0.run.out    :  	supported settings: powered connectable fast-connectable discoverable bondable link-security ssp br/edr le advertising secure-conn debug-keys privacy static-addr phy-configuration cis-central cis-peripheral iso-broadcaster sync-receiver ll-privacy past-sender past-receiver
13:00:40 OUT    host.0.0.run.out    :  	current settings: br/edr
13:00:40 OUT    host.0.0.run.out    :  	name
13:00:40 OUT    host.0.0.run.out    :  	short name
13:00:40 INFO   host.0.0.run        :  (return code 0)
13:00:40 DEBUG  rpc.host.0.0        :  client-reply
PASSED                                                                   [100%]
13:00:40 OUT    host.0.0            :  qemu-system-x86_64: terminating on signal 15 from pid 149047 (python3)
======================= 1 passed, 4 deselected in 8.84s ========================

$ test/test-functional --kernel=../linux -k test_bluetoothctl_pair --log-cli-level=0 --log-filter=*.bluetoothctl,rpc.* --force-usb
============================= test session starts ==============================
platform linux -- Python 3.14.3, pytest-8.3.5, pluggy-1.6.0
rootdir: /home/pauli/prj/external/bluez/unit
configfile: pytest.ini
plugins: cov-5.0.0, forked-1.6.0, rerunfailures-15.0, timeout-2.4.0, xdist-3.7.0, hypothesis-6.123.0, flaky-3.8.1, anyio-4.12.1
collected 5 items / 4 deselected / 1 selected

test/functional/test_bluetoothctl_vm.py::test_bluetoothctl_pair[hosts0-vm2]
-------------------------------- live log setup --------------------------------
13:03:20 INFO   rpc.host.0.0        :  client: start_load (<func_test.lib.host_plugins.Bdaddr object at 0x7f268712d160>,) {}
13:03:20 INFO   rpc.host.0.0        :  client: start_load (<func_test.lib.host_plugins.Call object at 0x7f268712d2b0>,) {}
13:03:20 INFO   rpc.host.0.0        :  client: start_load (<func_test.lib.host_plugins.DbusSystem object at 0x7f2687aa30e0>,) {}
13:03:20 INFO   rpc.host.0.0        :  client: start_load (<func_test.lib.host_plugins.Bluetoothd object at 0x7f2687aa3230>,) {}
13:03:20 INFO   rpc.host.0.0        :  client: start_load (<func_test.lib.host_plugins.Bluetoothctl object at 0x7f268712d010>,) {}
13:03:20 INFO   rpc.host.0.1        :  client: start_load (<func_test.lib.host_plugins.Bdaddr object at 0x7f26871542d0>,) {}
13:03:20 INFO   rpc.host.0.1        :  client: start_load (<func_test.lib.host_plugins.Call object at 0x7f2687154410>,) {}
13:03:20 INFO   rpc.host.0.1        :  client: start_load (<func_test.lib.host_plugins.DbusSystem object at 0x7f2687aa30e0>,) {}
13:03:20 INFO   rpc.host.0.1        :  client: start_load (<func_test.lib.host_plugins.Bluetoothd object at 0x7f2687aa3230>,) {}
13:03:20 INFO   rpc.host.0.1        :  client: start_load (<func_test.lib.host_plugins.Bluetoothctl object at 0x7f2687154190>,) {}
13:03:20 INFO   rpc.host.0.0        :  client: wait_load () {}
13:03:21 DEBUG  rpc.host.0.0        :  client-reply
13:03:21 INFO   rpc.host.0.1        :  client: wait_load () {}
13:03:21 DEBUG  rpc.host.0.1        :  client-reply
-------------------------------- live log call ---------------------------------
13:03:21 INFO   rpc.host.0.0        :  client: call_plugin ('bluetoothctl', 'send', 'show\n') {}
13:03:21 DEBUG  rpc.host.0.0        :  client-reply
13:03:21 INFO   rpc.host.0.0        :  client: call_plugin ('bluetoothctl', 'expect', 'Powered: yes') {}
...
13:03:23 INFO   rpc.host.0.0        :  client: call_plugin ('bluetoothctl', 'send', 'pair 70:1a:b8:73:99:bb\n') {}
13:03:23 OUT    host.0.0.bluetoothctl:  pair 70:1a:b8:73:99:bb
13:03:23 DEBUG  rpc.host.0.0        :  client-reply
13:03:23 INFO   rpc.host.0.0        :  client: call_plugin ('bluetoothctl', 'expect', 'Confirm passkey (\\d+).*:') {}
13:03:23 OUT    host.0.0.bluetoothctl:  [bluetoothctl]> pair 70:1a:b8:73:99:bb
13:03:23 OUT    host.0.0.bluetoothctl:  Attempting to pair with 70:1A:B8:73:99:BB
13:03:23 OUT    host.0.0.bluetoothctl:  [bluetoothctl]> hci0 device_flags_changed: 70:1A:B8:73:99:BB (BR/EDR)
13:03:23 OUT    host.0.0.bluetoothctl:  [bluetoothctl]>      supp: 0x00000007  curr: 0x00000000
13:03:23 OUT    host.0.0.bluetoothctl:  [bluetoothctl]> hci0 type 7 discovering off
13:03:25 OUT    host.0.0.bluetoothctl:  [bluetoothctl]> hci0 70:1A:B8:73:99:BB type BR/EDR connected eir_len 12
13:03:25 OUT    host.0.0.bluetoothctl:  [bluetoothctl]> [BlueZ 5.86]> [CHG] Device 70:1A:B8:73:99:BB Connected: yes
13:03:25 OUT    host.0.0.bluetoothctl:  [BlueZ 5.86]> Request confirmation
13:03:25 DEBUG  rpc.host.0.0        :  client-reply
13:03:25 INFO   rpc.host.0.1        :  client: call_plugin ('bluetoothctl', 'expect', 'Confirm passkey 237345') {}
13:03:25 OUT    host.0.1.bluetoothctl:  [bluetoothctl]> hci0 84:5C:F3:77:31:19 type BR/EDR connected eir_len 12
13:03:25 OUT    host.0.1.bluetoothctl:  [bluetoothctl]> [NEW] Device 84:5C:F3:77:31:19 BlueZ 5.86
13:03:25 DEBUG  rpc.host.0.1        :  client-reply
13:03:25 INFO   rpc.host.0.0        :  client: call_plugin ('bluetoothctl', 'send', 'yes\n') {}
13:03:25 OUT    host.0.1.bluetoothctl:  [bluetoothctl]> [BlueZ 5.86]> Request confirmation
13:03:25 OUT    host.0.0.bluetoothctl:  [BlueZ 5.86]> [agent] Confirm passkey 237345 (yes/no): yes
13:03:25 DEBUG  rpc.host.0.0        :  client-reply
13:03:25 INFO   rpc.host.0.1        :  client: call_plugin ('bluetoothctl', 'send', 'yes\n') {}
13:03:25 OUT    host.0.1.bluetoothctl:  [BlueZ 5.86]> [agent] Confirm passkey 237345 (yes/no): yes
13:03:25 DEBUG  rpc.host.0.1        :  client-reply
13:03:25 INFO   rpc.host.0.0        :  client: call_plugin ('bluetoothctl', 'expect', 'Pairing successful') {}
13:03:25 OUT    host.0.0.bluetoothctl:  yes
13:03:25 OUT    host.0.0.bluetoothctl:  [BlueZ 5.86]> hci0 new_link_key 70:1A:B8:73:99:BB type 0x08 pin_len 0 store_hint 1
13:03:25 OUT    host.0.0.bluetoothctl:  [BlueZ 5.86]> [CHG] Device 70:1A:B8:73:99:BB Bonded: yes
13:03:26 OUT    host.0.0.bluetoothctl:  [BlueZ 5.86]> [CHG] Device 70:1A:B8:73:99:BB AddressType: public
13:03:26 OUT    host.0.0.bluetoothctl:  [BlueZ 5.86]> [CHG] Device 70:1A:B8:73:99:BB UUIDs: 0000110c-0000-1000-8000-00805f9b34fb
13:03:26 OUT    host.0.0.bluetoothctl:  [BlueZ 5.86]> [CHG] Device 70:1A:B8:73:99:BB UUIDs: 0000110e-0000-1000-8000-00805f9b34fb
13:03:26 DEBUG  rpc.host.0.0        :  client-reply
PASSED                                                                   [100%]
------------------------------ live log teardown -------------------------------
13:03:26 OUT    host.0.0.bluetoothctl:  [BlueZ 5.86]> [CHG] Device 70:1A:B8:98:FF:qemu-system-x86_64: terminating on signal 15 from pid 149357 (python3)

======================= 1 passed, 4 deselected in 13.22s =======================

$ test/test-functional -k test_btmgmt --kernel=../linux --trace
============================= test session starts ==============================
platform linux -- Python 3.14.3, pytest-8.3.5, pluggy-1.6.0
rootdir: /home/pauli/prj/external/bluez/unit
configfile: pytest.ini
plugins: cov-5.0.0, forked-1.6.0, rerunfailures-15.0, timeout-2.4.0, xdist-3.7.0, hypothesis-6.123.0, flaky-3.8.1, anyio-4.12.1
collected 5 items / 4 deselected / 1 selected

test/functional/test_btmgmt_vm.py
>>>>>>>>>>>>>>>>>>>> PDB runcall (IO-capturing turned off) >>>>>>>>>>>>>>>>>>>>>
> /home/pauli/prj/external/bluez/test/functional/test_btmgmt_vm.py(19)test_btmgmt_info()
-> (host,) = hosts
(Pdb) n
> /home/pauli/prj/external/bluez/test/functional/test_btmgmt_vm.py(21)test_btmgmt_info()
-> result = host.call(
(Pdb) p host.bdaddr
'00:aa:01:00:00:42'
(Pdb) n
> /home/pauli/prj/external/bluez/test/functional/test_btmgmt_vm.py(22)test_btmgmt_info()
-> run,
(Pdb) n
> /home/pauli/prj/external/bluez/test/functional/test_btmgmt_vm.py(23)test_btmgmt_info()
-> [btmgmt, "--index", "0", "info"],
(Pdb) n
> /home/pauli/prj/external/bluez/test/functional/test_btmgmt_vm.py(24)test_btmgmt_info()
-> stdout=subprocess.PIPE,
(Pdb) n
> /home/pauli/prj/external/bluez/test/functional/test_btmgmt_vm.py(25)test_btmgmt_info()
-> stdin=subprocess.DEVNULL,
(Pdb) n
> /home/pauli/prj/external/bluez/test/functional/test_btmgmt_vm.py(26)test_btmgmt_info()
-> encoding="utf-8",
(Pdb) n
> /home/pauli/prj/external/bluez/test/functional/test_btmgmt_vm.py(21)test_btmgmt_info()
-> result = host.call(
(Pdb) n
> /home/pauli/prj/external/bluez/test/functional/test_btmgmt_vm.py(28)test_btmgmt_info()
-> assert result.returncode == 0
(Pdb) p result
CompletedProcess(args=['/home/pauli/prj/external/bluez/build/tools/btmgmt', '--index', '0', 'info'], returncode=0, stdout='hci0:\tPrimary controller\n\taddr 00:AA:01:00:00:42 version 11 manufacturer 1521 class 0x000000\n\tsupported settings: powered connectable fast-connectable discoverable bondable link-security ssp br/edr le advertising secure-conn debug-keys privacy static-addr phy-configuration cis-central cis-peripheral iso-broadcaster sync-receiver ll-privacy past-sender past-receiver \n\tcurrent settings: br/edr \n\tname \n\tshort name \n')
(Pdb) print(result.stdout)
hci0:	Primary controller
	addr 00:AA:01:00:00:42 version 11 manufacturer 1521 class 0x000000
	supported settings: powered connectable fast-connectable discoverable bondable link-security ssp br/edr le advertising secure-conn debug-keys privacy static-addr phy-configuration cis-central cis-peripheral iso-broadcaster sync-receiver ll-privacy past-sender past-receiver
	current settings: br/edr
	name
	short name
(Pdb) q

!!!!!!!!!!!!!!!!!!! _pytest.outcomes.Exit: Quitting debugger !!!!!!!!!!!!!!!!!!!
======================= 4 deselected in 75.91s (0:01:15) =======================

***

Pauli Virtanen (20):
  emulator: btvirt: check pkt lengths, don't get stuck on malformed
  emulator: btvirt: allow specifying where server unix sockets are made
  emulator: btvirt: support SCO data packets
  emulator: btdev: clear more state on Reset
  test-runner: enable path argument for --unix
  test-runner: Add -o/--option option
  test-runner: allow source tree root for -k
  doc: enable CONFIG_VIRTIO_CONSOLE in tester config
  test-runner: use virtio-serial for implementing -u device forwarding
  doc: enable KVM paravirtualization & clock support in tester kernel
    config
  doc: add functional/integration testing documentation
  test: add functional/integration testing framework
  test: functional: add Pipewire-using audio streaming tests
  test: functional: add --btmon option to start btmon
  build: add functional testing target
  test: functional: impose Python code formatting
  test: functional: add option for building kernel image first
  test: functional: add custom Agent1 implementation for testing
  test: functional: warn on kernel warning/bug messages
  test: functional: add basic obex file transfer tests

 Makefile.am                             |   9 +
 Makefile.tools                          |   2 +
 configure.ac                            |  31 +
 doc/ci.config                           |   9 +
 doc/test-functional.rst                 | 949 ++++++++++++++++++++++++
 doc/test-runner.rst                     |  17 +
 doc/tester.config                       |   9 +
 emulator/btdev.c                        | 117 +--
 emulator/main.c                         |  37 +-
 emulator/server.c                       |  21 +
 test/functional/__init__.py             |   2 +
 test/functional/requirements.txt        |   4 +
 test/functional/test_agent.py           |  46 ++
 test/functional/test_bluetoothctl_vm.py | 152 ++++
 test/functional/test_btmgmt_vm.py       |  30 +
 test/functional/test_obex.py            | 285 +++++++
 test/functional/test_pipewire.py        | 539 ++++++++++++++
 test/functional/test_tests.py           |  23 +
 test/pytest.ini                         |  18 +
 test/pytest_bluez/__init__.py           |  12 +
 test/pytest_bluez/agent.py              | 371 +++++++++
 test/pytest_bluez/btmon.py              | 116 +++
 test/pytest_bluez/build_kernel.py       |  43 ++
 test/pytest_bluez/env.py                | 803 ++++++++++++++++++++
 test/pytest_bluez/host_plugins.py       | 627 ++++++++++++++++
 test/pytest_bluez/plugin.py             | 637 ++++++++++++++++
 test/pytest_bluez/rpc.py                | 385 ++++++++++
 test/pytest_bluez/runner.py             |  20 +
 test/pytest_bluez/tests/__init__.py     |   2 +
 test/pytest_bluez/tests/test_rpc.py     |  62 ++
 test/pytest_bluez/tests/test_utils.py   |  16 +
 test/pytest_bluez/utils.py              | 706 ++++++++++++++++++
 test/test-functional                    |   7 +
 test/test-functional-attach             |  52 ++
 tools/test-runner.c                     | 376 +++++++---
 35 files changed, 6383 insertions(+), 152 deletions(-)
 create mode 100644 doc/test-functional.rst
 create mode 100644 test/functional/__init__.py
 create mode 100644 test/functional/requirements.txt
 create mode 100644 test/functional/test_agent.py
 create mode 100644 test/functional/test_bluetoothctl_vm.py
 create mode 100644 test/functional/test_btmgmt_vm.py
 create mode 100644 test/functional/test_obex.py
 create mode 100644 test/functional/test_pipewire.py
 create mode 100644 test/functional/test_tests.py
 create mode 100644 test/pytest.ini
 create mode 100644 test/pytest_bluez/__init__.py
 create mode 100644 test/pytest_bluez/agent.py
 create mode 100644 test/pytest_bluez/btmon.py
 create mode 100644 test/pytest_bluez/build_kernel.py
 create mode 100644 test/pytest_bluez/env.py
 create mode 100644 test/pytest_bluez/host_plugins.py
 create mode 100644 test/pytest_bluez/plugin.py
 create mode 100644 test/pytest_bluez/rpc.py
 create mode 100644 test/pytest_bluez/runner.py
 create mode 100644 test/pytest_bluez/tests/__init__.py
 create mode 100644 test/pytest_bluez/tests/test_rpc.py
 create mode 100644 test/pytest_bluez/tests/test_utils.py
 create mode 100644 test/pytest_bluez/utils.py
 create mode 100755 test/test-functional
 create mode 100755 test/test-functional-attach

-- 
2.53.0


^ permalink raw reply	[flat|nested] 26+ messages in thread
* [PATCH BlueZ v2 01/20] emulator: btvirt: check pkt lengths, don't get stuck on malformed
@ 2026-03-20 21:10 Pauli Virtanen
  2026-03-20 22:14 ` Functional/integration testing bluez.test.bot
  0 siblings, 1 reply; 26+ messages in thread
From: Pauli Virtanen @ 2026-03-20 21:10 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Pauli Virtanen

Don't try to parse packet before whole header is received.

If received data has unknown packet type, reset buffer so that we don't
get stuck.
---
 emulator/server.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/emulator/server.c b/emulator/server.c
index fa2bc07be..f14e14cd2 100644
--- a/emulator/server.c
+++ b/emulator/server.c
@@ -136,12 +136,20 @@ again:
 				client->pkt_len = 0;
 				break;
 			case HCI_ACLDATA_PKT:
+				if (count < HCI_ACL_HDR_SIZE + 1) {
+					client->pkt_offset += len;
+					return;
+				}
 				acl_hdr = (hci_acl_hdr*)(ptr + 1);
 				client->pkt_expect = HCI_ACL_HDR_SIZE + acl_hdr->dlen + 1;
 				client->pkt_data = malloc(client->pkt_expect);
 				client->pkt_len = 0;
 				break;
 			case HCI_ISODATA_PKT:
+				if (count < HCI_ISO_HDR_SIZE + 1) {
+					client->pkt_offset += len;
+					return;
+				}
 				iso_hdr = (hci_iso_hdr *)(ptr + 1);
 				client->pkt_expect = HCI_ISO_HDR_SIZE +
 							iso_hdr->dlen + 1;
@@ -151,6 +159,7 @@ again:
 			default:
 				printf("packet error, unknown type: %d\n",
 					client->pkt_type);
+				client->pkt_offset = 0;
 				return;
 			}
 
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 26+ messages in thread
* [PATCH BlueZ 01/11] emulator: btvirt: check pkt lengths, don't get stuck on malformed
@ 2026-02-28 12:51 Pauli Virtanen
  2026-02-28 13:45 ` Functional/integration testing bluez.test.bot
  0 siblings, 1 reply; 26+ messages in thread
From: Pauli Virtanen @ 2026-02-28 12:51 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Pauli Virtanen

Don't try to parse packet before whole header is received.

If received data has unknown packet type, reset buffer so that we don't
get stuck.
---
 emulator/server.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/emulator/server.c b/emulator/server.c
index fa2bc07be..f14e14cd2 100644
--- a/emulator/server.c
+++ b/emulator/server.c
@@ -136,12 +136,20 @@ again:
 				client->pkt_len = 0;
 				break;
 			case HCI_ACLDATA_PKT:
+				if (count < HCI_ACL_HDR_SIZE + 1) {
+					client->pkt_offset += len;
+					return;
+				}
 				acl_hdr = (hci_acl_hdr*)(ptr + 1);
 				client->pkt_expect = HCI_ACL_HDR_SIZE + acl_hdr->dlen + 1;
 				client->pkt_data = malloc(client->pkt_expect);
 				client->pkt_len = 0;
 				break;
 			case HCI_ISODATA_PKT:
+				if (count < HCI_ISO_HDR_SIZE + 1) {
+					client->pkt_offset += len;
+					return;
+				}
 				iso_hdr = (hci_iso_hdr *)(ptr + 1);
 				client->pkt_expect = HCI_ISO_HDR_SIZE +
 							iso_hdr->dlen + 1;
@@ -151,6 +159,7 @@ again:
 			default:
 				printf("packet error, unknown type: %d\n",
 					client->pkt_type);
+				client->pkt_offset = 0;
 				return;
 			}
 
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2026-03-24 21:00 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-22 21:29 [PATCH BlueZ v3 00/20] Functional/integration testing Pauli Virtanen
2026-03-22 21:29 ` [PATCH BlueZ v3 01/20] emulator: btvirt: check pkt lengths, don't get stuck on malformed Pauli Virtanen
2026-03-22 22:38   ` Functional/integration testing bluez.test.bot
2026-03-22 21:29 ` [PATCH BlueZ v3 02/20] emulator: btvirt: allow specifying where server unix sockets are made Pauli Virtanen
2026-03-22 21:29 ` [PATCH BlueZ v3 03/20] emulator: btvirt: support SCO data packets Pauli Virtanen
2026-03-22 21:29 ` [PATCH BlueZ v3 04/20] emulator: btdev: clear more state on Reset Pauli Virtanen
2026-03-22 21:29 ` [PATCH BlueZ v3 05/20] test-runner: enable path argument for --unix Pauli Virtanen
2026-03-22 21:29 ` [PATCH BlueZ v3 06/20] test-runner: Add -o/--option option Pauli Virtanen
2026-03-22 21:29 ` [PATCH BlueZ v3 07/20] test-runner: allow source tree root for -k Pauli Virtanen
2026-03-22 21:29 ` [PATCH BlueZ v3 08/20] doc: enable CONFIG_VIRTIO_CONSOLE in tester config Pauli Virtanen
2026-03-22 21:29 ` [PATCH BlueZ v3 09/20] test-runner: use virtio-serial for implementing -u device forwarding Pauli Virtanen
2026-03-24 20:24   ` Luiz Augusto von Dentz
2026-03-24 21:00     ` Pauli Virtanen
2026-03-22 21:29 ` [PATCH BlueZ v3 10/20] doc: enable KVM paravirtualization & clock support in tester kernel config Pauli Virtanen
2026-03-22 21:30 ` [PATCH BlueZ v3 11/20] doc: add functional/integration testing documentation Pauli Virtanen
2026-03-22 21:30 ` [PATCH BlueZ v3 12/20] test: add functional/integration testing framework Pauli Virtanen
2026-03-22 21:30 ` [PATCH BlueZ v3 13/20] test: functional: add Pipewire-using audio streaming tests Pauli Virtanen
2026-03-22 21:30 ` [PATCH BlueZ v3 14/20] test: functional: add --btmon option to start btmon Pauli Virtanen
2026-03-22 21:31 ` [PATCH BlueZ v3 15/20] build: add functional testing target Pauli Virtanen
2026-03-22 21:31 ` [PATCH BlueZ v3 16/20] test: functional: impose Python code formatting Pauli Virtanen
2026-03-22 21:31 ` [PATCH BlueZ v3 17/20] test: functional: add option for building kernel image first Pauli Virtanen
2026-03-22 21:31 ` [PATCH BlueZ v3 18/20] test: functional: add custom Agent1 implementation for testing Pauli Virtanen
2026-03-22 21:31 ` [PATCH BlueZ v3 19/20] test: functional: warn on kernel warning/bug messages Pauli Virtanen
2026-03-22 21:31 ` [PATCH BlueZ v3 20/20] test: functional: add basic obex file transfer tests Pauli Virtanen
  -- strict thread matches above, loose matches on Subject: below --
2026-03-20 21:10 [PATCH BlueZ v2 01/20] emulator: btvirt: check pkt lengths, don't get stuck on malformed Pauli Virtanen
2026-03-20 22:14 ` Functional/integration testing bluez.test.bot
2026-02-28 12:51 [PATCH BlueZ 01/11] emulator: btvirt: check pkt lengths, don't get stuck on malformed Pauli Virtanen
2026-02-28 13:45 ` Functional/integration testing bluez.test.bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox