Accept successful completion of StorageRace and kill and reap finite examples that exceed their deadline. Run the native Linux regression with disposable storage as an unprivileged user, since container root cannot necessarily create realtime threads. Use tmpfs so per-round fsync calls do not turn the regression into a disk-latency test.
Exercise the QuadPlane-specific parts of ArduPlane/GCS_MAVLink_Plane.cpp
which no existing test reached:
- AVAILABLE_MODES including the VTOL modes
- ATTITUDE_TARGET from the VTOL attitude controller
- PID_TUNING from the VTOL rate and vertical acceleration controllers
- HIGH_LATENCY2 target heading and altitude in VTOL modes
- NAV_TAKEOFF and DO_VTOL_TRANSITION rejection paths, and NAV_TAKEOFF
as COMMAND_INT
- precision landing using LANDING_TARGET
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Coverage analysis of the Plane and QuadPlane autotest suites showed
large parts of ArduPlane/GCS_MAVLink_Plane.cpp were never executed.
These tests exercise that code:
- AVAILABLE_MODES, including FLTMODE_GCSBLOCK and single-index requests
- rejection paths of DO_REPOSITION, DO_CHANGE_ALTITUDE, DO_CHANGE_SPEED,
GUIDED_CHANGE_SPEED/ALTITUDE/HEADING, MISSION_START, DO_LAND_START
and the VTOL commands on a non-VTOL Plane
- flying headings and course-over-ground with GUIDED_CHANGE_HEADING
- SET_POSITION_TARGET_LOCAL_NED altitude offsets
- SET_ATTITUDE_TARGET and SET_POSITION_TARGET_GLOBAL_INT being ignored
outside GUIDED, and an invalid frame being reported
- DO_RETURN_PATH_START as a command
- SET_HAGL triggering the landing flare
- DO_PARACHUTE enable, disable, unknown action and repeated release
- DO_SET_MISSION_CURRENT as a command
- DO_REPOSITION loiter radius and direction
- DO_SET_HOME while in RTL
- HEARTBEAT system_status through standby, active, failsafe and crash
- EXTENDED_SYS_STATE landed_state through a fixed-wing flight
- PID_TUNING axes selected by GCS_PID_MASK, including the landing PID
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
MAVProxy can do some funky things with SIGTERM, accomodate it
also cut out a 0.1s pause during pexpect shutdown by nuking some of its attributes when we know the process is dead
Vagrant: compile wxpython in home for resolute and future releases
switch to excluding older versions to avoid needing to change this when making new releases
Neither of SITL's 300 character ROMFS names fits in a listing packet, so
listing their directory gives nothing, but finding them must not read or
write outside the names around them. Run under --asan, this caught
AP_ROMFS::dir_list() reading past the previous name.
SITL's ROMFS gains files which sort just before a directory of the same
name, at the top level and below it, so MAVFTPListROMFS checks such a
directory is still listed.
Nothing listed @ROMFS. Walk it as a GCS browsing it would, and check every
file named in the build's embedded header is found, at its decompressed
size, with nothing extra and no directory listed twice. Then read
vehicleinfo.json out of it, which is stored compressed and takes many
reads, and check it matches the file it was built from.
SITL's ROMFS gains a file and a directory, each with a 300 character name,
so the tests can check listing them is safe: a directory entry's d_name
is 255 bytes on ChibiOS and 256 with glibc, so neither name fits. They go
under autotest_fixtures, where autotest's fixtures are kept apart from
anything a user embeds.
fetch_file_via_ftp() polled 'ftp status' for 'No transfer in progress'
and took that as completion, within a timeout measured in simulated
time. Both are wrong:
- the loop is paced by MAVProxy and pexpect, not the simulation. At
full speedup a single one-second expect consumes the whole
twenty-second sim-time budget, so a status poll which lands
mid-transfer fails the fetch about a second after it began, even
though the file arrived:
Wrote 7403 bytes to /tmp/tmptcsw8tm2 in 0.02s 391.1kByte/s
Timed out looking for No transfer in progress
Exception caught: expected complete transfer
- 'No transfer in progress' is also true before the transfer starts,
and after one is aborted, so it can yield an empty or truncated
file. PerfInfo has failed both ways:
Expected TasksV2 as first line first not ()
Expected EFI last not (AP_Generator::update ...)
Expect MAVProxy's 'Wrote N bytes to' message instead, which is printed
only once the whole file has been written, with a wall-clock timeout,
and retry the fetch a couple of times if it does not arrive.
install_script() honours install_name when choosing the destination, but
install_applet_script_context() recorded the source name for removal, so
a script installed under a different name was never cleaned up when the
context went away.
AerobaticsScripting installs Aerobatics/FixedWing/Schedules/AirShow.txt
as trick72.txt: context pop then tried to unlink scripts/AirShow.txt,
which had never existed, and left scripts/trick72.txt behind after every
run. The scripting engine itself never loads that leftover - it takes
only names ending in .lua - but plane_aerobatics.lua searches scripts/
for trick<n>.txt, so a later run reads the stale copy and would still
pass even if the install had broken.
install_script_module_context() and install_driver_script_context()
already resolve install_name this way; do the same here, and spell the
parameter out as they do rather than taking it through **kwargs.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Fails without the fix (EKF height 2.5 m high above 5 m), with only the
baro offset held (3.0 m drop at liftoff) and with only the reset skipped
(2.5 m high). Takeoff only; the touchdown half of the fix is not covered.
The check is about aiding in flight. With the flow focus floor from #34292
the flow on the ground after touchdown is not fused, so relative aiding
stops before the disarm and would count against this test. Count only
between NOT_LANDED and LAND_COMPLETE.
Fail every compass in flight, remove optical flow until aiding stops,
then restore it. Aiding has to restart, which needs the gyro bias check
to ignore the Z axis while no yaw is being fused.
Covers no yaw source, a compass that stops delivering data and GPS yaw
lost. The simulated gyro has no bias, so any Z bias the EKF learns is
phantom. The yaw reference is removed at arming and the flow scale error
doubled, so the bias grows within 40 s of flight rather than 240 s: yaw
fused during the climb otherwise holds it down.
Flow has to have been fused for a zero bias to mean anything. XKF5 flow
innovations do not show that, as they are written before the innovation
gate and never cleared, so the test requires that flow fusion started
and that aiding never stopped while armed, which with flow as the only
aiding source means an update passed the gate at least every 5 s.
Debug build, max Z gyro bias in deg/s against a 0.1 limit. Merge-base:
no yaw source 0.26 to 0.27 (4 runs), compass lost 0.95 to 1.10 (4
runs), GPS yaw lost 1.09 to 1.26 (3 runs). With the fix: 0.00, 0.01 and
0.01 to 0.02 (3 runs). The test takes about 23 s.
Renames and rescales the Copter and QuadPlane parameters that changed
name or units in 4.7 (attitude, position and waypoint controllers,
loiter, circle, RTL, land, pilot, rangefinder, MAV_ and stream rate
parameters), converts ARMING_CHECK to ARMING_SKIPCHK and moves the
MAVLink bits of SERIALn_OPTIONS into MAVn_OPTIONS. Files are converted
in place or into an output directory, --patch selects the 4.7.0 or 4.7.1
names and the vehicle is detected from the file content.
Move the parameter file parsing, rescaling and rewriting into importable
helpers so that other conversion scripts can reuse them. The standalone
interface is unchanged apart from a new --sig-digits option (default 3).
QGroundControl files are now handled, names are matched exactly instead
of by prefix, and separators, comments and untouched lines are preserved.
Add MountAVTCM62DualImageStartCapture covering a single image on all
cameras and on each camera, a fixed count via COMMAND_LONG, capture
until stopped via IMAGE_STOP_CAPTURE, and rejection of a zero interval
with multiple images, a negative camera ID and an absent camera slot.
Extend MountAVTCM62DualMission with an all-cameras mission item and
check MountAVTCM62 rejects an unconfigured slot.
Unconfigured and absent camera slots are DENIED by the camera selector
resolution rather than FAILED as in the original tests.
Based on Peter Barker's work in ArduPilot/ardupilot#33900.
Co-authored-by: Peter Barker <pbarker@barker.dropbear.id.au>
The analyser no longer reports the GCS.h num_intervals finding, so
retaining its suppression fails CI. Keep the separate suppression for
the remaining read in GCS_Common.cpp.
FBWB and CRUISE circuit legs require a minimum distance, not arrival
inside a narrow band. Accept distances beyond the threshold so
high-speedup position samples cannot skip the success window.
Exercise MT11 and AVT camera and gimbal behaviour, telemetry-driven
targeting, RTSP bounds, target refresh, capture-status expiry and
backpressure-safe stream replies.
Verify unicast routing and opt-in telemetry, extended parameter replies
from isolated links, forced home and origin events, and MT11 directory
listing and XML downloads through a unicast connection.
Check native camera identity across isolated and broadcast links,
default, configured and colliding component IDs, mixed native and servo
cameras, and native versus configured mount associations.
Cover camera and gimbal selectors for live commands and missions,
including legacy NaN values under floating-point traps, video stream
selection, native gimbal IDs, cached attitude frames and FC-owned
camera ACK identity. Fix the MAVFTP import ordering required by Ruff.
lcov 2.x, as shipped in the Ubuntu 24.04 CI containers, promotes two
conditions the weekly coverage run always hits from warnings to fatal
errors:
- "mismatched end line": two functions starting on the same source
line with different end lines. Every gtest TEST() body trips this,
as the macro also defines the fixture constructor and destructor on
the TEST() line, so both lcov --capture invocations abort.
- "unused": a --remove pattern which matched nothing; ".waf*" never
matches, so the pattern-removal step aborts.
Pass --ignore-errors for those classes on the affected invocations.
lcov 1.x rejects unknown error classes, so the arguments are only
emitted when lcov reports version 2 or later.
The coverage flags were added in configure_env, so every probe program
built by cfg.check() was compiled with -fprofile-arcs and linked with
-lgcov. On boards which also link with -Wl,--wrap,malloc (SITL, Linux,
QURT) libgcov's malloc call is rewritten to __wrap_malloc, which the
probe does not define, so the probe fails to link and the feature under
test is silently recorded as absent. Under --coverage every header
check ("endian.h", "byteswap.h", the cmath checks, memrchr) reported
"not found"; HAVE_BYTESWAP_H was never defined and the fallback in
AP_Common/missing/byteswap.h was compiled instead. That fallback
collides with glibc's own __bswap_16/32/64 as soon as a translation
unit also includes netinet/in.h, which broke build.unit_tests in the
weekly coverage workflow.
Move the flags into Board.configure_coverage() and call it from the
top-level configure once the checks are done, so the probes are never
instrumented and the coverage configuration produces the same
ap_config.h as a normal one.
Co-authored-by: Pierre Kancir <pierre.kancir.emn@gmail.com>
The size table marks a board "*" when the two builds are byte-identical
and "0" when they are the same size but differ, and two whole classes of
board could never reach "*".
The name reaches binaries_are_identical() lower-cased, because that is
the key the column lookup needs, but the files are AP_Periph.bin and
AP_Bootloader.bin, so on a case-sensitive filesystem neither candidate
was found and the answer was "differs" whatever the bytes said. CI
proves those two are identical: base and pull request builds log the same
APP_DESCRIPTOR crc32 pair, which covers the whole image.
A Linux board writes neither .bin nor .elf -- disco's bin/ holds bare
ELFs -- so nothing was compared there either. Match a file without
regard to case, and fall back to the extensionless ELF.
While here: enumerate the directory being measured rather than always the
master one, and import tabulate where it is used, so the module can be
imported by a test without it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
restart_SITL_frame() called build_SITL_frame() with none of the options
the suite was built with, so the frame binaries were configured without
--debug, --num-aux-imus and the rest. The binary under test then no
longer matched the suite's configuration, and CI - whose ccache holds
--debug objects - rebuilt both firmwares from scratch inside the test:
DroneCANCompass sitl 8m19s + sitl_periph_universal 3m51s of 743s
CircuitStatusScript sitl 5m51s + sitl_periph_universal 2m43s of 520s
It also left build/sitl configured without --debug for later tests.
Pass the suite's build options through, as the Replay tool build
already does. PPPPeriph no longer needs to ask for --debug itself.
The underlying problem is not really new, it was just never noticed by
the analyzer. Previously, `find_grid_cache` would dereference a null
pointer by working with `cache[0]` if it was called when `cache` is
`nullptr`. Now it will just dereference a null pointer directly.
Unfortunately, this is impossible to fix as the function must return a
cache block. Fortunately, nobody calls it in this circumstance.
Unseeded, MAVProxy draws the lost packets from fresh entropy on every run,
so a failure could not be reproduced. A fixed seed loses the same packets
each time; it still leaves gaps to fill.
The listing tests only ever listed a directory they had just made, so the
paths they used were all of one shape. The bug where listing the root
dropped every file lived through all of them because no test named the
root, which is the first thing a file browser asks for.
Cover the shapes a client actually sends: a directory with nothing in it,
and "." for the directory the vehicle was started in.
The long-name test also only listed without times, where the boundary of
what fits a packet sits eleven bytes further out. Run it both ways, with
names either side of the boundary a listing with times has, so that
dropping an entry which no longer fits still cannot end the listing.
These three were skipped pending MAVProxy fixes: continuing a directory
listing from the listing's own state rather than by mutating the last
operation sent, and taking a listing entry's size from the end of the
entry. MAVProxy master now does both, so rather than skipping them
outright they ask MAVProxy whether it can do this and return early if it
cannot.
The test set 50% receive loss and then waited only for "Total size",
which a listing that gave up part-way through would still print. Wait for
the total the files actually add up to instead.
Give every file a different size while doing so: with all of them the same
the total is just a count, so a listing which lost one page and repeated
another still reached it.
MAVFTPListDirectoryWithTimeMAVProxy checks times are asked for by
default and rendered in local time, and that "ftp set list_time 0"
turns them off again. MAVFTPListDirectoryUnknownTimeMAVProxy checks a
file whose time the autopilot does not know shows as "-" rather than as
a date; its directory holds one file, because a listing is printed in
readdir order and an expect for one entry cannot sit behind another.
MAVFTPListDirectoryFallbackMAVProxy makes the timestamped replies
disappear with the module's own pkt_loss_rx and requires the plain
listing to complete once the loss is lifted - the fallback is the whole
point of the new opcode and nothing else exercises it.
MAVFTPListDirectoryLossyRetry drops half the replies and requires the
listing to finish, as it has no retransmit of its own.
MAVFTPListDirectoryWithTimeMAVProxyTabInName is the timestamped
counterpart of the existing tab test, which takes the size and the time
from the end of the entry rather than the size from the front.
That existing test now asks for a plain listing explicitly: against a
MAVProxy which knows the opcode it would otherwise get a time it is not
expecting.
All are skipped, as they need a MAVProxy which is not released yet.
The spec says a virtual directory is named with an @ prefix, that the
recipient maps it to the underlying filesystem, and that a path which is
not there is NAKed FileNotFound. Check each of those: the alias lists what
the log directory holds, a path below it resolves both with and without
the trailing slash the spec's own example carries, an unknown path below
it is NAKed FileNotFound, and a file read through the alias gives back
what was written.
@MAV_LOG has no class of its own to find in the symbol table, so it is
detected by its prefix string, which only the backend table row puts in the
binary. That row is also only built where logs go to a filesystem, so the
option depends on Logging.
A name containing a tab must come back from ListDirectoryWithTime as a bare
skip entry, with the names around it still listed, while a plain listing
still sends it as it is.
A listing with times gives a directory the same three fields as a file,
so the listing helper now picks directory entries apart the same way and
the test checks the subdirectory's size and time. The subdirectory gets a
modification time of its own so that an entry carrying some other entry's
time would be caught.
Lists a directory of files with known sizes and modification times both
with and without times, paging through the listing by entry count as a
GCS does, and checks the entry format, that directories are still bare
D entries, and that a time the autopilot does not know comes back as
the zero the format defines rather than as the FAT epoch.
The listing helpers learn to ask for times; the directory they build
gets modification times to ask about.
The previous thresholds only checked the sign and a 2-degree minimum.
On the ground the pilot's total lean is limited to 10 degrees, split
across both axes by the test's diagonal stick, so the saved trim is
fully determined; check it against that value.