7 Commits

Author SHA1 Message Date
Eric Seidel 8072ed9ad7 feat: stage 1 integration test harness (#353)
* docs: integration tests design proposal

Adds docs/integration_tests.md proposing a desktop-only integration suite
that drives the Dart `ShorebirdUpdater` API against the real Rust core via
FFI, with a fake HTTP server and per-test tempdir state. Describes a new
`library_test_hooks` cdylib that reaches into `updater` via a `test-hooks`
Cargo feature, so production C API stays clean. Status: design exploration,
not a committed plan.

* feat: stage 1 integration test harness for shorebird_code_push

Lands the test_hooks crate, the Dart-side loader, and one trivial
end-to-end test, per docs/integration_tests.md stage 1.

Pieces:

- New `library_test_hooks` workspace crate (cdylib). Depends on `updater`
  with a new `test-hooks` Cargo feature that widens the visibility of
  internal items (currently `testing_reset_config`) for sibling-crate
  access only — production builds do not enable it. The crate also
  re-exports `updater::c_api::dart::*` and `updater::c_api::engine::*`,
  which keeps the rlib's `#[no_mangle]` symbols out of DCE so the
  resulting cdylib carries both the production C API and the new
  `shorebird_test_*` hooks.
- Workspace `default-members` excludes `library_test_hooks` so plain
  `cargo build` / `cargo test` invocations don't unify the `test-hooks`
  feature into production builds.
- `shorebird_code_push/test/integration/all_test.dart` (single file,
  with a header comment explaining why) loads the cdylib via
  `DynamicLibrary.open`, reassigns the existing `@visibleForTesting`
  `Updater.bindings` setter, and exercises both surfaces. The build
  helper shells out to `cargo build -p library_test_hooks`; if it
  fails, `markTestSkipped` keeps the suite green on machines without
  a working Rust toolchain.
- ffigen config (`ffigen_test_hooks.yaml`) generates the test-only
  Dart bindings under `test/integration/generated/`, not `lib/`.
- CI: `library_test_hooks` is added to the rust_crate matrix, and the
  shorebird_code_push job triggers on `library/**` and
  `library_test_hooks/**` so cdylib changes can't break the Dart-side
  integration suite without CI noticing.

Verified locally: 232 Rust unit tests + 42 Dart tests (41 existing + 1
integration) green; clippy/fmt/cspell clean; production cdylib does
not contain `shorebird_test_reset` (`nm` confirms feature isolation).

Stages 2 (FakePatchServer + golden path) and 3 (adversarial scenarios)
land separately.

* fix(integration test): early-return on skip and bump per-test timeout

Two issues caught by Shorebird CI on PR #353:

1. `markTestSkipped` does not abort test execution — it only flags the
   test as skipped on its way out. The body kept running and crashed on
   the `late testHooks` field when the cdylib build had failed in
   setUpAll. Move the skip check into the test body itself with an
   early return; drop the (no-op) skip in `setUp`.

2. Default per-test timeout (30s) also covers `setUpAll`. A cold
   `cargo build -p library_test_hooks` compiles `updater` and ~100
   transitive deps, which can run minutes on CI. Bump to 10 minutes
   via `@Timeout` on the library.

Verified locally: passes when cargo is on PATH (1 passed), reports a
clean skip and exit 0 when cargo is removed from PATH (1 skipped).

* refactor(integration test): drop ! by promoting testHooks to late final

`testHooks` was nullable so accessing it after the skipReason check
required `!`, and `markTestSkipped(skipReason!)` had the same smell.
Make `testHooks` `late final` (non-nullable, throws if read before
setUpAll assigns) and pull `skipReason` into a non-null local before
use. Same control flow, no bang operators.
2026-05-05 16:32:57 -07:00
Eric Seidel db99e24726 perf: set panic=abort and drop backtrace features (#342)
Reduces binary size of the updater staticlib when linked into the
Flutter engine. On host macOS arm64 the dylib shrinks from 3.07 MB
to 2.56 MB; the biggest iOS savings come from dropping the DWARF
unwind tables (__eh_frame, __gcc_except_tab, __unwind_info) that
panic=unwind generates.

- panic = "abort" in [profile.release]: kills unwind-table generation
  and eliminates dead panic-unwinding code paths. We don't use
  catch_unwind anywhere in the library. log-panics still runs its
  panic hook before abort, so panic messages continue to surface to
  logcat/oslog during development.
- Drop `backtrace` feature from anyhow and `with-backtrace` from
  log-panics: removes gimli + addr2line + rustc_demangle (~65 KB of
  symbolication machinery) that customers can't read anyway. A
  future in-engine crash reporter will symbolize native stacks,
  making these features redundant.
2026-04-21 19:01:26 +00:00
Eric Seidel 07fa11c9d9 perf: add release profile to reduce binary size (#328)
* perf: add release profile to reduce binary size

Add workspace-level release profile with size optimizations:
- opt-level = "z" (optimize for size)
- lto = true (cross-crate link-time optimization)
- codegen-units = 1 (better whole-program optimization)
- strip = "debuginfo" (remove debug info, preserve C API symbols)

Reduces .text section by ~32% (1.9 MiB → 1.3 MiB). The .a file
grows due to LTO bitcode embedding, but the final linked binary
(libflutter.so) will be smaller when the engine consumes it.

* chore: add codegen and debuginfo to spell check dictionary
2026-04-02 13:29:34 -07:00
Eric Seidel 0a0cd183f5 chore: use resolver=2 to avoid warnings from cargo (#145) 2024-04-19 17:19:49 -04:00
Eric Seidel 4ab78869b8 feat: Add start_updater_thread to update off the main thread (#11)
* feat: Add start_updater_thread to update off the main thread

This makes it so that clients can easily not block when wanting to
queue an update.

I have a separate patch which updates the Engine to use this new
API.

I also needed to split the concept of the "next_boot" patch
from the "current_boot" patch, previously refered to as
"current" or "active" patch.  This required adding a
report_launch_start api to let the updater library know
when to set current_boot patch from next_boot.

I also removed the rust updater/cli in this as well as the
vmpath argument to init.

I also exposed the report_launch_success api, but its not yet
used by the Engine.

I renamed report_failed_launch to report_launch_failure to match
report_launch_start which I introduced.

* Update naming per comments from Felix.

Also added a helper for char* allocation (not sure if it's better).

* Update library/src/updater.rs

---------

Co-authored-by: Felix Angelov <felix@shorebird.dev>
2023-04-25 09:06:40 -07:00
Eric Seidel 0afcb65950 feat: Add patch command for use by cli (#179) 2023-03-27 14:58:52 -05:00
Eric Seidel f757251162 chore: Fix the rust build (#27) 2023-03-06 15:06:31 -08:00