96fd32796e
Lands the fake HTTP server, the patch fixture pipeline, and the first two scenarios that exercise the real FFI path end-to-end. Plus a test that would have caught the patch-to-release rollback bug (shorebirdtech/shorebird#3728). Architecture follows the principles surfaced in review: - Dart tests call the public `ShorebirdUpdater` API only — never the raw `Updater` FFI wrapper, never the engine API. - Engine API stays inside the `library_test_hooks` Rust crate. `shorebird_test_init` constructs `AppParameters` + stub `FileCallbacks` internally so Dart never sees those types. `shorebird_test_simulate_successful_launch` wraps the start/success protocol so the Dart layer never knows there's a protocol — it just knows "the engine reported a successful boot." - ffigen scans only the test_hooks header. The engine header (updater_engine.h) does not appear in the Dart bindings. - A `TestEngine` Dart helper concentrates engine-side simulation in one place; the test bodies stay focused on `ShorebirdUpdater`. Implementation choices worth flagging: - FFI calls run via `Isolate.run`. Synchronous run blocks the main isolate, deadlocking against the in-isolate shelf server. The test's IsolateRun callback re-opens the cdylib (cheap: dlopen is ref-counted) and resets `Updater.bindings` in the sub-isolate because Dart isolates do not share static fields. - `libapp_path` must be a real file on the desktop integration build: the non-Android non-iOS non-test `patch_base` reads it directly from disk. Tests that install a patch write the fixture's `base` bytes to `libapp.so` before init. - Fake server kept minimal: shelf, no Range support, no auth, no concurrency knobs. Stage 3+ scenarios (download cutoff, hash mismatch loop, etc.) extend it as needed. Three scenarios cover three reasons we wanted this suite: 1. `checkForUpdate returns upToDate when server has no patch` — baseline: confirms the harness boots cleanly and returns the expected enum. 2. `install a patch and boot from it` — golden path: check → update → simulateSuccessfulLaunch, then assert `readCurrentPatch` / `readNextPatch` / `checkForUpdate` transitions match the public API contract. 3. `checkForUpdate returns restartRequired after patch-to-release rollback` — regression for shorebirdtech/shorebird#3728. Pre-fix this returned `upToDate` and left no signal to prompt a restart. Verified locally: 232 Rust unit tests + 44 Dart tests (41 existing unit + 3 new integration) green; clippy/fmt/cspell clean.
36 lines
1.1 KiB
YAML
36 lines
1.1 KiB
YAML
name: shorebird_code_push
|
|
description: Check for and download Shorebird code push updates from your app.
|
|
version: 2.0.7
|
|
homepage: https://shorebird.dev
|
|
repository: https://github.com/shorebirdtech/updater/tree/main/shorebird_code_push
|
|
|
|
environment:
|
|
sdk: ">=3.5.4 <4.0.0"
|
|
flutter: ">=3.24.5"
|
|
|
|
dependencies:
|
|
ffi: ^2.0.2
|
|
meta: ^1.9.1
|
|
|
|
dev_dependencies:
|
|
ffigen: ">=8.0.2 <21.0.0"
|
|
mocktail: ^1.0.0
|
|
# Used by integration tests under test/integration/ for FakePatchServer.
|
|
# Not part of the package's public API or runtime dependencies.
|
|
shelf: ^1.4.0
|
|
test: ^1.19.2
|
|
very_good_analysis: ">=7.0.0 <11.0.0"
|
|
|
|
ffigen:
|
|
output: "lib/src/generated/updater_bindings.g.dart"
|
|
name: "UpdaterBindings"
|
|
headers:
|
|
# Only the Dart-stable surface drives ffigen. Engine-only symbols live in
|
|
# ../library/include/updater_engine.h and must NOT be reachable from the
|
|
# generated bindings — the package's public ABI is exactly what this file
|
|
# exposes.
|
|
entry-points:
|
|
- "../library/include/updater_dart.h"
|
|
preamble: |
|
|
// ignore_for_file: unused_element, unused_field
|