gui/docs/pkg-qa-requests-m1.md R3, filed by the previous session: three GUI M1 DoD items (10k rows at 60 fps, flat RSS over 10 minutes, --slow/--flaky/--drop-connection recovery) had nowhere to run in CI. This is the harness — `gui/tests/dod/run.sh <gate> [--json <path>]`, exactly the path/invocation contract tests/integration/README.md already specified — plus `gui/tests/dod/dod_harness.cpp`, the Qt/RpcClient-driven binary that actually runs each gate against a real mockd run.sh starts and tears down itself. - scroll-60fps: an eased scripted scroll over the whole loaded table, timing each step's synchronous repaint; p99 against a 16.6 ms budget (auto-scaled 4x under a sanitized build — ASan/UBSan overhead, not a loosened bar, see the harness's isSanitizedBuild()). - rss-flat: samples this process's own VmRSS at 1 Hz across the run, discards a warm-up window, checks post-warm-up growth against a stated 20 MiB slack. - unhappy-path: three phases (slow/flaky/drop-connection), each its own mockd instance; passes when the client reaches and holds Connected with no crash or hang. A watchdog (the harness's own QTimer, backstopped by run.sh's external `timeout`) turns a genuine hang into a bounded non-zero exit rather than needing the CI caller to timeout(1) around it. Every gate honours the exit-code and --json contract PKG/QA's pre-drafted CI job expects unchanged (one addition needed: the build step must also build the `gui-dod-harness` target, noted in the R3 update). No leaked mockd processes on any exit path (`trap cleanup EXIT INT TERM`); no writes outside a tempdir except the caller's own --json path. Verified live end-to-end (not just unit-level): all three gates run against a real mockd under the exact `ASAN_OPTIONS=detect_leaks=1:halt_on_error=1` `.github/workflows/ci.yml`'s sanitizers job already sets, all pass, and scroll-60fps was forced red once on purpose (VELOX_DOD_FRAME_BUDGET_MS=1) to prove the fail path and exit code actually work. Building this is also what surfaced the two RpcClient bugs fixed in the previous commit, and one real gap in mockd itself — --drop-connection never worked over the Unix socket transport (only WebSocket) — filed as gui/docs/proto-requests-m1.md since tools/mockd is PROTO's file. gui/docs/pkg-qa-requests-m1.md R3 and R4 (an unrelated, non-blocking Qt6::DBus CMake hygiene note filed while wiring the clipboard global-shortcut path) are updated with the concrete findings above. Co-Authored-By: Claude Sonnet 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01NSCdCWFXBTSBBK3MzWtJiC
158 lines
8.6 KiB
CMake
158 lines
8.6 KiB
CMake
# GUI unit tests. Lane GUI.
|
|
#
|
|
# CLAUDE.md §5: a feature with no test does not exist. Each test below has a concrete
|
|
# failure it catches — that is the bar, not "it runs green".
|
|
|
|
set(CMAKE_AUTOMOC ON)
|
|
|
|
find_package(Qt6 REQUIRED COMPONENTS Test)
|
|
|
|
# tst_downloadtablemodel — the model's logic, headless.
|
|
# Red when: a progress patch widens past the value columns, a reset slips into
|
|
# applyProgress, applyProgress starts synthesizing rows for unknown ids, or add/remove
|
|
# stops emitting rowsInserted/rowsRemoved.
|
|
add_executable(tst_downloadtablemodel
|
|
tst_downloadtablemodel.cpp
|
|
${CMAKE_CURRENT_SOURCE_DIR}/../src/models/DownloadTableModel.cpp
|
|
)
|
|
target_include_directories(tst_downloadtablemodel PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../src)
|
|
target_compile_features(tst_downloadtablemodel PRIVATE cxx_std_23)
|
|
target_compile_options(tst_downloadtablemodel PRIVATE -Wall -Wextra -Wpedantic -Werror)
|
|
target_link_libraries(tst_downloadtablemodel PRIVATE Qt6::Core Qt6::Test)
|
|
add_test(NAME gui_downloadtablemodel COMMAND tst_downloadtablemodel)
|
|
set_tests_properties(gui_downloadtablemodel PROPERTIES LABELS "gui")
|
|
|
|
# tst_downloadfilterproxy — the category-tree filter.
|
|
# Red when: a node stops filtering to its own rows, the Finished/Unfinished split
|
|
# misclassifies a state, or the filter stops being dynamic.
|
|
add_executable(tst_downloadfilterproxy tst_downloadfilterproxy.cpp)
|
|
target_compile_features(tst_downloadfilterproxy PRIVATE cxx_std_23)
|
|
target_compile_options(tst_downloadfilterproxy PRIVATE -Wall -Wextra -Wpedantic -Werror)
|
|
target_link_libraries(tst_downloadfilterproxy PRIVATE velox-gui-lib Qt6::Test)
|
|
add_test(NAME gui_downloadfilterproxy COMMAND tst_downloadfilterproxy)
|
|
set_tests_properties(gui_downloadfilterproxy PROPERTIES LABELS "gui")
|
|
|
|
# tst_rtl — the real RTL check the GUI DoD asks for (the .ts stub alone verifies nothing).
|
|
# Red when: the main window stops propagating Qt::RightToLeft to its children, or the
|
|
# offline-banner layout is pinned so it does not mirror under RTL.
|
|
add_executable(tst_rtl tst_rtl.cpp)
|
|
target_compile_features(tst_rtl PRIVATE cxx_std_23)
|
|
target_compile_options(tst_rtl PRIVATE -Wall -Wextra -Wpedantic -Werror)
|
|
target_link_libraries(tst_rtl PRIVATE velox-gui-lib Qt6::Widgets Qt6::Test)
|
|
add_test(NAME gui_rtl COMMAND tst_rtl)
|
|
set_tests_properties(gui_rtl PROPERTIES
|
|
LABELS "gui"
|
|
ENVIRONMENT "QT_QPA_PLATFORM=offscreen")
|
|
|
|
# tst_segmentbarswidget — the per-connection bar grid.
|
|
# Red when: a determinate segment stops rendering its percentage, an unknown-length
|
|
# segment stops falling back to the indeterminate range, a shrinking segment set
|
|
# destroys rows instead of hiding them, or rows start getting rebuilt per tick.
|
|
add_executable(tst_segmentbarswidget tst_segmentbarswidget.cpp)
|
|
target_compile_features(tst_segmentbarswidget PRIVATE cxx_std_23)
|
|
target_compile_options(tst_segmentbarswidget PRIVATE -Wall -Wextra -Wpedantic -Werror)
|
|
target_link_libraries(tst_segmentbarswidget PRIVATE velox-gui-lib Qt6::Widgets Qt6::Test)
|
|
add_test(NAME gui_segmentbarswidget COMMAND tst_segmentbarswidget)
|
|
set_tests_properties(gui_segmentbarswidget PROPERTIES
|
|
LABELS "gui"
|
|
ENVIRONMENT "QT_QPA_PLATFORM=offscreen")
|
|
|
|
# tst_speedgraphwidget — the 60 s rolling speed graph.
|
|
# Red when: addSample stops throttling bursts to 1 Hz, the bucket count stops
|
|
# incrementing on genuinely separated samples, clear() leaves stale state, or painting
|
|
# crashes before two samples exist.
|
|
add_executable(tst_speedgraphwidget tst_speedgraphwidget.cpp)
|
|
target_compile_features(tst_speedgraphwidget PRIVATE cxx_std_23)
|
|
target_compile_options(tst_speedgraphwidget PRIVATE -Wall -Wextra -Wpedantic -Werror)
|
|
target_link_libraries(tst_speedgraphwidget PRIVATE velox-gui-lib Qt6::Widgets Qt6::Test)
|
|
add_test(NAME gui_speedgraphwidget COMMAND tst_speedgraphwidget)
|
|
set_tests_properties(gui_speedgraphwidget PROPERTIES
|
|
LABELS "gui"
|
|
ENVIRONMENT "QT_QPA_PLATFORM=offscreen")
|
|
|
|
# tst_fileinfodialog — FileInfoDialog::buildSpec, the pure DownloadSpec builder.
|
|
# Red when: an empty optional field starts getting sent instead of omitted, or the
|
|
# queueId stops being dropped for a startMode other than "queue".
|
|
add_executable(tst_fileinfodialog tst_fileinfodialog.cpp)
|
|
target_compile_features(tst_fileinfodialog PRIVATE cxx_std_23)
|
|
target_compile_options(tst_fileinfodialog PRIVATE -Wall -Wextra -Wpedantic -Werror)
|
|
target_link_libraries(tst_fileinfodialog PRIVATE velox-gui-lib Qt6::Widgets Qt6::Test)
|
|
add_test(NAME gui_fileinfodialog COMMAND tst_fileinfodialog)
|
|
set_tests_properties(gui_fileinfodialog PROPERTIES
|
|
LABELS "gui"
|
|
ENVIRONMENT "QT_QPA_PLATFORM=offscreen")
|
|
|
|
# tst_optionsdialog — OptionsDialog::diffChanged, the "only send what changed" logic.
|
|
# Red when an unchanged key gets resent, or a key missing from `original` stops
|
|
# counting as changed.
|
|
add_executable(tst_optionsdialog tst_optionsdialog.cpp)
|
|
target_compile_features(tst_optionsdialog PRIVATE cxx_std_23)
|
|
target_compile_options(tst_optionsdialog PRIVATE -Wall -Wextra -Wpedantic -Werror)
|
|
target_link_libraries(tst_optionsdialog PRIVATE velox-gui-lib Qt6::Widgets Qt6::Test)
|
|
add_test(NAME gui_optionsdialog COMMAND tst_optionsdialog)
|
|
set_tests_properties(gui_optionsdialog PROPERTIES
|
|
LABELS "gui"
|
|
ENVIRONMENT "QT_QPA_PLATFORM=offscreen")
|
|
|
|
# tst_speedlimiterdialog — SpeedLimiterDialog::buildParams.
|
|
# Red when disabling stops zeroing globalBps, or enabling at 0 KiB/s stops being
|
|
# clamped to 1 (Limiter.schema.json: enabled+0 "must not be offered").
|
|
add_executable(tst_speedlimiterdialog tst_speedlimiterdialog.cpp)
|
|
target_compile_features(tst_speedlimiterdialog PRIVATE cxx_std_23)
|
|
target_compile_options(tst_speedlimiterdialog PRIVATE -Wall -Wextra -Wpedantic -Werror)
|
|
target_link_libraries(tst_speedlimiterdialog PRIVATE velox-gui-lib Qt6::Widgets Qt6::Test)
|
|
add_test(NAME gui_speedlimiterdialog COMMAND tst_speedlimiterdialog)
|
|
set_tests_properties(gui_speedlimiterdialog PROPERTIES
|
|
LABELS "gui"
|
|
ENVIRONMENT "QT_QPA_PLATFORM=offscreen")
|
|
|
|
# tst_schedulerdialog — SchedulerDialog::buildSchedule.
|
|
# Red when "use a schedule" unchecked stops sending JSON null, "run until it drains"
|
|
# stops nulling stopTime, or daysOfWeek/onceDate leak into the wrong mode.
|
|
add_executable(tst_schedulerdialog tst_schedulerdialog.cpp)
|
|
target_compile_features(tst_schedulerdialog PRIVATE cxx_std_23)
|
|
target_compile_options(tst_schedulerdialog PRIVATE -Wall -Wextra -Wpedantic -Werror)
|
|
target_link_libraries(tst_schedulerdialog PRIVATE velox-gui-lib Qt6::Widgets Qt6::Test)
|
|
add_test(NAME gui_schedulerdialog COMMAND tst_schedulerdialog)
|
|
set_tests_properties(gui_schedulerdialog PROPERTIES
|
|
LABELS "gui"
|
|
ENVIRONMENT "QT_QPA_PLATFORM=offscreen")
|
|
|
|
# tst_batchdialog — parseUrlBlob, expandWildcard, buildAddBatchParams.
|
|
# Red when the clipboard parser stops deduping or lets a non-URL line through, the
|
|
# wildcard expander mishandles zero-padding or an ambiguous/malformed range, or
|
|
# addBatch params include an empty optional field or a stray queueId.
|
|
add_executable(tst_batchdialog tst_batchdialog.cpp)
|
|
target_compile_features(tst_batchdialog PRIVATE cxx_std_23)
|
|
target_compile_options(tst_batchdialog PRIVATE -Wall -Wextra -Wpedantic -Werror)
|
|
target_link_libraries(tst_batchdialog PRIVATE velox-gui-lib Qt6::Widgets Qt6::Test)
|
|
add_test(NAME gui_batchdialog COMMAND tst_batchdialog)
|
|
set_tests_properties(gui_batchdialog PROPERTIES
|
|
LABELS "gui"
|
|
ENVIRONMENT "QT_QPA_PLATFORM=offscreen")
|
|
|
|
# tst_grabberwizard — buildFileTypes, buildStartParams, buildHarvestParams.
|
|
# Red when every file-type box unchecked stops meaning "every type" (null, not []),
|
|
# a blank filter stops becoming schema null, or a selected fileId goes missing from
|
|
# the harvest params.
|
|
add_executable(tst_grabberwizard tst_grabberwizard.cpp)
|
|
target_compile_features(tst_grabberwizard PRIVATE cxx_std_23)
|
|
target_compile_options(tst_grabberwizard PRIVATE -Wall -Wextra -Wpedantic -Werror)
|
|
target_link_libraries(tst_grabberwizard PRIVATE velox-gui-lib Qt6::Widgets Qt6::Test)
|
|
add_test(NAME gui_grabberwizard COMMAND tst_grabberwizard)
|
|
set_tests_properties(gui_grabberwizard PROPERTIES
|
|
LABELS "gui"
|
|
ENVIRONMENT "QT_QPA_PLATFORM=offscreen")
|
|
|
|
# gui-dod-harness — the M1 DoD gates (scroll-60fps / rss-flat / unhappy-path).
|
|
add_subdirectory(dod)
|
|
|
|
# gui_no_download_logic — CLAUDE.md §3 as an executable check, not a hope.
|
|
# Red when: a download-logic token (curl, raw pwrite, sqlite, QSqlDatabase) appears
|
|
# under gui/src. grep exits 0 only when it finds a match, so a hit fails the test.
|
|
add_test(NAME gui_no_download_logic
|
|
COMMAND ${CMAKE_COMMAND}
|
|
-DGUI_SRC=${CMAKE_CURRENT_SOURCE_DIR}/../src
|
|
-P ${CMAKE_CURRENT_SOURCE_DIR}/no_download_logic.cmake)
|
|
set_tests_properties(gui_no_download_logic PROPERTIES LABELS "gui")
|