Commit 39ebe93
Phase 6: drive the shipped ftmsbike parser byte-exact, and find two bugs doing it
ftmsbike::characteristicChanged - nine hundred lines that turn a 0x2AD2 frame into a
speed - had no test at all, in either direction, for one reason: a test cannot build
a QLowEnergyCharacteristic with a UUID in it, so every branch of the handler missed
and the object was unreachable. It has one now.
The seams turned out to be six rather than the two the plan expected. Inbound was as
specified - handleNotification(uuid, value, fromService), which the Qt slot delegates
to. Outbound needed four, because the write path defends itself at four levels and
every one of them ultimately asks for that same unbuildable object: controlPointReady,
enqueueTargetValid, writeTargetReady, performWrite. Plus linkExists and linkState for
update()'s gates. Every default is the code it replaced, WriteRequest moved from
private to protected so a subclass can name what it overrides on, and the suite gives
the same 218/208/10 and exit 0 it gave before the seams.
Two real bugs surfaced on the first run, which is the return on all of that.
An unguarded m_control->error() at the last line of the notification handler - the
same null dereference this fork already fixed in update(), where the comment records
that Qt 5 survives it and Qt 6 crashes, sitting in a second place and reachable by a
notification arriving after a teardown cleared the controller. Being the last
statement, the whole parse succeeds first and the crash looks unrelated to the frame.
And 0x2AD2 read past the end of its buffer. The only length check was that the frame
has a flags word; every field after it was read unguarded, so a frame promising more
than it carries walks off the end - an assert in a debug Qt, silent garbage in a
release one. The 0x2ACE path in the same file already guards every field with
ensureBytesAvailable(); this one did not. Fixed with a single up-front check computed
from the flags rather than thirteen inline ones, because this is the hot path and one
arithmetic statement is easier to review. A frame longer than its flags describe is
still accepted - the real trainer sends one.
The encoder is validated against the trainer rather than against us: an encoder bug
and a parser bug that agree cancel out, so ftmsframes.h has to reproduce the two
recorded frames byte for byte, bit 13 and unflagged trailer included. It caught itself
applying the inverted bit-0 rule twice.
FtmsBikeAsTheBikeEnd is the phase's point: a frame into one side of the whole stack -
real parser, metrics, notifier, DIRCON - and the numbers asserted on the wire at the
other. Both bike ends now feed the same loop.
Not done, and not mine to sign off: a real ride behaving identically. The seams are
mechanical and the suite agrees, but that is an argument rather than evidence. The
device-name branches stay unreachable too, including this trainer's own three-byte
resistance write; that needs a seventh seam and is in TODO.md.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>1 parent 3bd4e7b commit 39ebe93
9 files changed
Lines changed: 980 additions & 34 deletions
File tree
- docs/fork
- src/devices/ftmsbike
- tst
- Devices
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
12 | 31 | | |
13 | 32 | | |
14 | 33 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | | - | |
4 | | - | |
| 3 | + | |
| 4 | + | |
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
| |||
804 | 804 | | |
805 | 805 | | |
806 | 806 | | |
807 | | - | |
808 | | - | |
809 | | - | |
810 | | - | |
811 | | - | |
812 | | - | |
813 | | - | |
| 807 | + | |
| 808 | + | |
| 809 | + | |
| 810 | + | |
| 811 | + | |
| 812 | + | |
| 813 | + | |
| 814 | + | |
| 815 | + | |
| 816 | + | |
| 817 | + | |
| 818 | + | |
| 819 | + | |
| 820 | + | |
| 821 | + | |
| 822 | + | |
| 823 | + | |
| 824 | + | |
| 825 | + | |
| 826 | + | |
| 827 | + | |
| 828 | + | |
| 829 | + | |
| 830 | + | |
| 831 | + | |
| 832 | + | |
| 833 | + | |
| 834 | + | |
| 835 | + | |
| 836 | + | |
| 837 | + | |
| 838 | + | |
| 839 | + | |
| 840 | + | |
| 841 | + | |
| 842 | + | |
| 843 | + | |
| 844 | + | |
| 845 | + | |
| 846 | + | |
| 847 | + | |
| 848 | + | |
| 849 | + | |
| 850 | + | |
| 851 | + | |
| 852 | + | |
| 853 | + | |
| 854 | + | |
| 855 | + | |
| 856 | + | |
| 857 | + | |
| 858 | + | |
| 859 | + | |
| 860 | + | |
| 861 | + | |
| 862 | + | |
| 863 | + | |
| 864 | + | |
| 865 | + | |
814 | 866 | | |
815 | 867 | | |
816 | 868 | | |
| |||
0 commit comments