Skip to content

Phase19e loopback integration test#101

Draft
JustinKovacich wants to merge 2 commits into
feature/phase19c_embassy_net_socket_iofrom
feature/phase19e_loopback_integration_test
Draft

Phase19e loopback integration test#101
JustinKovacich wants to merge 2 commits into
feature/phase19c_embassy_net_socket_iofrom
feature/phase19e_loopback_integration_test

Conversation

@JustinKovacich
Copy link
Copy Markdown
Contributor

Validates 19a-c against a real embassy_net::Stack:

  • LoopbackDriver pair: two in-memory Pipes (queue + waker)
    bridge two embassy_net::Stack instances. No kernel TUN, no
    privileges; runs in any CI without setup. HardwareAddress::Ip
    medium skips ARP/Ethernet — pure IP traffic over the loopback.
  • adapter_udp_roundtrip: two stacks on 169.254.1.1 / .1.2,
    two EmbassyNetFactory + SocketPool pairs, bind a socket on
    each, send a UDP datagram A→B, assert byte-equality + source
    address. Tightest end-to-end exercise of bind / send_to /
    recv_from / local_addr / SocketPool slot lifecycle.
  • Runtime: #[tokio::test(flavor = "current_thread")] + a
    LocalSet driving per-stack spawn_local runners.
    Stack<LoopbackDriver> is !Sync (RefCell internals), so
    Stack::run() is !Send — multi-thread tokio::spawn does
    not type-check. The current_thread flavor matches the
    single-task model bare-metal targets actually run under.
  • Cargo: adds tokio (rt-multi-thread, macros, time, sync) and
    futures to dev-deps.

What this leaves for follow-on phases:

  • 19f — Server::new_with_deps_local + parallel impl Server
    block with relaxed Send + Sync bounds. Required because
    embassy_net::udp::UdpSocket<'static> is !Sync (borrows
    from Stack's RefCell<Inner<D>>), and Server's existing
    three impl blocks (mod.rs:275/430/1065) all require
    F::Socket: Send + Sync. Mirrors Client's existing
    new_with_deps_local pattern.
  • 19g — SOME/IP Client+Server integration test. Lifts the
    tests/bare_metal_e2e.rs harness onto the loopback stack
    pair using the 19f _local API. Mirrors the parent crate's
    client_receives_server_sd_announcement and
    client_send_request_server_runloop_stable, with
    EmbassyNetFactory swapped in for MockFactory.

Scope split rationale: per phase_13_5_lessons.md lesson #2,
"abstract over X" and "drop X" are separate commitments —
bundling the Server bound-relaxation under "loopback test"
would repeat the v2 phases-11/13a aspirational-gate mistake.

Plan v3 updated 2026-04-29 (memory) with the 19e/f/g/h/i/j
re-numbering.

Gates green:

  • cargo fmt --check
  • cargo clippy -p simple-someip-embassy-net --all-targets -D warnings
  • cargo test -p simple-someip-embassy-net --test loopback
  • cargo build -p simple-someip-embassy-net --target thumbv7em-none-eabihf
  • cargo check --workspace --all-targets

JustinKovacich and others added 2 commits April 29, 2026 05:58
…ndtrip)

Validates 19a-c against a real embassy_net::Stack:

- `LoopbackDriver` pair: two in-memory `Pipe`s (queue + waker)
  bridge two `embassy_net::Stack` instances. No kernel TUN, no
  privileges; runs in any CI without setup. `HardwareAddress::Ip`
  medium skips ARP/Ethernet — pure IP traffic over the loopback.
- `adapter_udp_roundtrip`: two stacks on 169.254.1.1 / .1.2,
  two `EmbassyNetFactory` + `SocketPool` pairs, bind a socket on
  each, send a UDP datagram A→B, assert byte-equality + source
  address. Tightest end-to-end exercise of `bind` / `send_to` /
  `recv_from` / `local_addr` / `SocketPool` slot lifecycle.
- Runtime: `#[tokio::test(flavor = "current_thread")]` + a
  `LocalSet` driving per-stack `spawn_local` runners.
  `Stack<LoopbackDriver>` is `!Sync` (RefCell internals), so
  `Stack::run()` is `!Send` — multi-thread `tokio::spawn` does
  not type-check. The `current_thread` flavor matches the
  single-task model bare-metal targets actually run under.
- Cargo: adds `tokio` (rt-multi-thread, macros, time, sync) and
  `futures` to dev-deps.

What this leaves for follow-on phases:

- 19f — `Server::new_with_deps_local` + parallel `impl Server`
  block with relaxed `Send + Sync` bounds. Required because
  `embassy_net::udp::UdpSocket<'static>` is `!Sync` (borrows
  from `Stack`'s `RefCell<Inner<D>>`), and Server's existing
  three impl blocks (`mod.rs:275/430/1065`) all require
  `F::Socket: Send + Sync`. Mirrors Client's existing
  `new_with_deps_local` pattern.
- 19g — SOME/IP Client+Server integration test. Lifts the
  `tests/bare_metal_e2e.rs` harness onto the loopback stack
  pair using the 19f `_local` API. Mirrors the parent crate's
  `client_receives_server_sd_announcement` and
  `client_send_request_server_runloop_stable`, with
  `EmbassyNetFactory` swapped in for `MockFactory`.

Scope split rationale: per phase_13_5_lessons.md lesson #2,
"abstract over X" and "drop X" are separate commitments —
bundling the Server bound-relaxation under "loopback test"
would repeat the v2 phases-11/13a aspirational-gate mistake.

Plan v3 updated 2026-04-29 (memory) with the 19e/f/g/h/i/j
re-numbering.

Gates green:
- cargo fmt --check
- cargo clippy -p simple-someip-embassy-net --all-targets -D warnings
- cargo test -p simple-someip-embassy-net --test loopback
- cargo build -p simple-someip-embassy-net --target thumbv7em-none-eabihf
- cargo check --workspace --all-targets

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Missed in 10fdfdc; adds tokio + futures-util + transitive deps
that the loopback test pulls in.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a host-runnable loopback integration test to validate the simple-someip-embassy-net transport adapter against a real embassy_net::Stack, without requiring a kernel TUN/TAP device or special privileges.

Changes:

  • Introduces tests/loopback.rs with an in-memory LoopbackDriver bridging two embassy_net::Stack instances and a UDP roundtrip assertion.
  • Updates simple-someip-embassy-net dev-dependencies to support the Tokio-based test harness.
  • Refreshes Cargo.lock for newly added dev-deps.

Reviewed changes

Copilot reviewed 2 out of 3 changed files in this pull request and generated 4 comments.

File Description
simple-someip-embassy-net/tests/loopback.rs Implements a software loopback Driver and a Tokio LocalSet-driven UDP roundtrip test across two stacks.
simple-someip-embassy-net/Cargo.toml Updates host-test dev-deps and adds Tokio (+ futures) for the new test harness.
Cargo.lock Locks new transitive dependencies introduced by the dev-dependency updates.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +62 to +64
# `tokio::spawn` for the per-stack `Stack::run()` futures, and
# `tokio::time::timeout` for bounded assertions. Same shape as the
# parent crate's `tests/bare_metal_e2e.rs` harness.
Copy link

Copilot AI Apr 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These comments say the harness uses tokio::spawn for the per-stack Stack::run() tasks, but the test uses tokio::task::spawn_local (required by LocalSet / current_thread). Updating the comment will avoid confusion about why rt-multi-thread isn’t actually needed for the test.

Suggested change
# `tokio::spawn` for the per-stack `Stack::run()` futures, and
# `tokio::time::timeout` for bounded assertions. Same shape as the
# parent crate's `tests/bare_metal_e2e.rs` harness.
# `tokio::task::spawn_local` for the per-stack `Stack::run()` futures
# within a `LocalSet` / current-thread runtime, and
# `tokio::time::timeout` for bounded assertions. Same overall shape as
# the parent crate's `tests/bare_metal_e2e.rs` harness.

Copilot uses AI. Check for mistakes.
Comment on lines +66 to +68
# `futures` brings `select_biased!` / `FusedFuture` / `pin_mut!` into
# scope for the test driver.
futures = "0.3"
Copy link

Copilot AI Apr 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The crate adds futures = "0.3" as a dev-dependency, but there’s no code in simple-someip-embassy-net (including tests/loopback.rs) that actually uses the futures crate right now. Consider dropping this dev-dep until it’s needed (or add the missing usage) to keep the dependency surface minimal.

Suggested change
# `futures` brings `select_biased!` / `FusedFuture` / `pin_mut!` into
# scope for the test driver.
futures = "0.3"

Copilot uses AI. Check for mistakes.
//! * **`adapter_udp_roundtrip`** — bind two `EmbassyNetSocket`s,
//! one per stack, send a UDP datagram from A to B, assert
//! byte-equality + source-address. Tightest test of `bind` /
//! `send_to` / `recv_from` / `local_addr` end-to-end.
Copy link

Copilot AI Apr 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The module docs claim this test exercises local_addr end-to-end, but the test body never calls local_addr(). Either add an assertion that checks sock_a.local_addr() / sock_b.local_addr() matches the bound address, or adjust the docs to reflect what’s actually covered.

Suggested change
//! `send_to` / `recv_from` / `local_addr` end-to-end.
//! `send_to` / `recv_from` end-to-end.

Copilot uses AI. Check for mistakes.
Comment on lines +211 to +214
/// Build a stack on `ip/24` with our `LoopbackDriver`. Returns a
/// `&'static Stack<LoopbackDriver>` ready for `EmbassyNetFactory`
/// and a separately-leaked future to `tokio::spawn` for the
/// stack's run loop.
Copy link

Copilot AI Apr 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doc comment says build_stack returns a separately-leaked future to tokio::spawn, but the function only returns &'static Stack<LoopbackDriver>. Update the comment (or function signature) so the documentation matches the actual API.

Suggested change
/// Build a stack on `ip/24` with our `LoopbackDriver`. Returns a
/// `&'static Stack<LoopbackDriver>` ready for `EmbassyNetFactory`
/// and a separately-leaked future to `tokio::spawn` for the
/// stack's run loop.
/// Build a stack on `ip/24` with our `LoopbackDriver` and return a
/// leaked `&'static Stack<LoopbackDriver>` ready for
/// `EmbassyNetFactory`.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants