Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,30 @@ name = "bdd_pool"
path = "tests/bdd_pool/mod.rs"
required-features = ["advanced-tests", "pool"]

[[test]]
name = "connection"
path = "tests/connection/mod.rs"

[[test]]
name = "formal_tooling"
path = "tests/formal_tooling/mod.rs"

[[test]]
name = "fragment_transport"
path = "tests/fragment_transport/mod.rs"

[[test]]
name = "preamble"
path = "tests/preamble/mod.rs"

[[test]]
name = "prepared_app"
path = "tests/prepared_app/mod.rs"

[[test]]
name = "response"
path = "tests/response/mod.rs"

[[bench]]
name = "codec_performance"
harness = false
Expand Down
12 changes: 6 additions & 6 deletions docs/adr-002-streaming-requests-and-shared-message-assembly.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,9 @@ sequenceDiagram

#### Implementation decisions (2026-02-12)

- The inbound integration seam for this ADR is `src/app/inbound_handler.rs` and
`src/app/frame_handling/`, not `src/connection/`, because inbound decode and
dispatch already occur in the app-layer connection loop.
- The inbound integration seam for this ADR is `src/app/inbound_handler/mod.rs`
and `src/app/frame_handling/`, not `src/connection/`, because inbound decode
and dispatch already occur in the app-layer connection loop.
- Message-assembly parsing, length, and continuity violations are treated as
inbound deserialization failures and therefore use the same threshold-based
invalid-data policy as other malformed inbound input.
Expand Down Expand Up @@ -319,8 +319,8 @@ Precedence is:
#### Implementation decisions (2026-02-23)

- Roadmap item `8.3.3` now implements soft-limit back-pressure in the inbound
read loop (`src/app/inbound_handler.rs`) by pausing briefly before polling
the next frame when buffered assembly bytes are under pressure.
read loop (`src/app/inbound_handler/mod.rs`) by pausing briefly before
polling the next frame when buffered assembly bytes are under pressure.
- Soft pressure is computed from assembly-state buffered bytes versus the
smaller aggregate cap (`min(bytes_per_connection, bytes_in_flight)`), with a
threshold of 80% to engage pacing before hard-cap rejection.
Expand All @@ -342,7 +342,7 @@ Precedence is:
`evaluate_memory_pressure()` function in
`src/app/frame_handling/backpressure.rs`, returning a `MemoryPressureAction`
enum (`Continue`, `Pause`, or `Abort`). This keeps the inbound loop
(`src/app/inbound_handler.rs`) within the 400-line file limit.
(`src/app/inbound_handler/mod.rs`) within the 400-line file limit.
- The hard cap uses `>` (strictly exceeds) for the comparison, matching the
`check_aggregate_budgets` convention in `budget.rs`. The limit value itself
is permitted.
Expand Down
6 changes: 3 additions & 3 deletions docs/adr-004-pluggable-protocol-codecs.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ length-delimited implementation.

Wireframe currently hardcodes `tokio_util::codec::LengthDelimitedCodec` with a
4-byte big-endian length prefix in the connection pipeline (notably in
`src/app/inbound_handler.rs` and `src/app/frame_handling.rs`). This makes
`src/app/inbound_handler/mod.rs` and `src/app/frame_handling/`). This makes
framing inflexible and prevents protocols with alternative framing rules (such
as Hotline, MySQL, and Redis Serialization Protocol (RESP)) from reusing
Wireframe's routing, middleware, and serialization infrastructure.
Expand Down Expand Up @@ -156,7 +156,7 @@ pub trait FrameCodec: Send + Sync + Clone + 'static {

### Phase 1: Trait definition (non-breaking)

- Create `src/codec.rs` with the `FrameCodec` trait and
- Create `src/codec/mod.rs` with the `FrameCodec` trait and
`LengthDelimitedFrameCodec` default.
- Add unit tests covering the default codec behaviour.

Expand Down Expand Up @@ -301,7 +301,7 @@ let extracted = MyCodec::frame_payload_bytes(&frame);
assert_eq!(frame.payload.as_ptr(), extracted.as_ptr());
```

See `src/codec/tests.rs` for zero-copy regression tests covering
See `src/codec/tests/mod.rs` for zero-copy regression tests covering
`LengthDelimitedFrameCodec`, `HotlineFrameCodec`, and `MysqlFrameCodec`.

### Property-based codec round-trip hardening (resolved 2026-02-19)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ and especially the following runtime surfaces:
- `src/push/queues/handle.rs`;
- `src/middleware.rs`;
- `src/hooks.rs`;
- `src/server/runtime.rs` and `src/server/connection_spawner.rs`;
- `src/server/runtime/mod.rs` and `src/server/connection_spawner.rs`;
- `src/client/pool/*`.

It complements rather than supersedes:
Expand Down Expand Up @@ -237,7 +237,7 @@ Examples governed by this rule include:

`WireframeServer::run_with_shutdown` is a supervisor for independently
scheduled accept-loop tasks. It owns their `CancellationToken` and
`TaskTracker`, and `src/server/runtime.rs` holds a named `drop_guard_ref()`
`TaskTracker`, and `src/server/runtime/mod.rs` holds a named `drop_guard_ref()`
borrow in the supervisor frame. If the supervisor future is dropped, including
through `JoinHandle::abort()`, the guard cancels the accept loops so they
eventually release their listener references. The guarantee is eventual: the
Expand Down
4 changes: 2 additions & 2 deletions docs/adr-012-prepared-application-and-connection-runtime.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@ Primary code surfaces:
- `src/app/builder/routing.rs`;
- `src/app/builder/lifecycle.rs`;
- `src/app/builder/protocol.rs`;
- `src/app/inbound_handler.rs`;
- `src/app/inbound_handler/mod.rs`;
- `src/server/mod.rs`;
- `src/server/runtime.rs`;
- `src/server/runtime/mod.rs`;
- `src/server/runtime/accept.rs`;
- `src/server/connection_spawner.rs`;
- `examples/ping_pong.rs` and `examples/packet_enum.rs`.
Expand Down
33 changes: 22 additions & 11 deletions docs/developers-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -392,9 +392,9 @@ the rustdoc for `wireframe::NoProtocolError` for the public API contract.

## Message sequence validation architecture

Message continuation ordering lives in `src/message_assembler/series.rs`. The
public-facing control point is `validate_and_advance_sequence()`, which keeps
the series state machine readable by delegating to two private helpers:
Message continuation ordering lives in `src/message_assembler/series/mod.rs`.
The public-facing control point is `validate_and_advance_sequence()`, which
keeps the series state machine readable by delegating to two private helpers:

- `start_sequence_tracking()` handles the first numbered continuation after an
untracked start. It switches the series into tracked mode and then delegates
Expand Down Expand Up @@ -1033,13 +1033,14 @@ evaluations and four middleware transforms for the former path, versus one of
each for the prepared root. The counters are collected for each Criterion
sample so the counts remain visible alongside the timing results.

Fragment transport integration tests import `tests/common/fragment_helpers.rs`
as a facade. Keep the public re-export surface stable there, and place helper
implementation details in responsibility-focused modules under
`tests/common/fragment_helpers/`: app construction and spawning, assertions,
fragmentation configuration, envelope building, error types, and framed
transport. New fragment helpers should be added to the smallest matching module
and re-exported only when more than one test binary needs the helper.
Fragment transport integration tests import
`tests/common/fragment_helpers/mod.rs` as a facade. Keep the public re-export
surface stable there, and place helper implementation details in
responsibility-focused modules under `tests/common/fragment_helpers/`: app
construction and spawning, assertions, fragmentation configuration, envelope
building, error types, and framed transport. New fragment helpers should be
added to the smallest matching module and re-exported only when more than one
test binary needs the helper.

## Formal verification tooling

Expand Down Expand Up @@ -1192,6 +1193,16 @@ because a model that cannot finish hangs rather than failing.

## Test infrastructure and framework

### Integration-test target layout

Integration-test roots may be relocated from `tests/<name>.rs` to
`tests/<name>/mod.rs` so that supporting modules sit beside the root. Cargo
auto-discovers `tests/*.rs` and `tests/<name>/main.rs`, but not
`tests/<name>/mod.rs`, so a relocated root must be declared as an explicit
`[[test]]` target in `Cargo.toml` whose `path` names that `mod.rs`. Without the
declaration the root is not built, so its tests stop running with no compile
error to flag the loss.

### rstest and rstest-bdd

The test suite uses [`rstest`](https://crates.io/crates/rstest) for
Expand Down Expand Up @@ -1295,7 +1306,7 @@ propagates both the `JoinError` and the inner error with `handle.await??`.
interrupted before calling `finish_server`, so a server-side failure is never
silently discarded on the happy path. See `ClientLifecycleWorld::finish_server`
in `tests/fixtures/client_lifecycle.rs` and the precedent in
`tests/fixtures/client_preamble.rs`.
`tests/fixtures/client_preamble/mod.rs`.

**The server-task cleanup contract**, as implemented by
`run_hook_test_with_server` in `src/client/tests/request_hooks_support.rs`: on
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ Testkit/public API touch points:

- [`wireframe_testing/src/lib.rs`](../../wireframe_testing/src/lib.rs) is the
public re-export surface.
- [`wireframe_testing/src/helpers.rs`](../../wireframe_testing/src/helpers.rs)
- [`wireframe_testing/src/helpers/mod.rs`](../../wireframe_testing/src/helpers/mod.rs)
currently re-exports the in-memory driver helpers added in `8.5.1` and
`8.5.2`.
- [`docs/wireframe-testing-crate.md`](../wireframe-testing-crate.md) is the
Expand Down
2 changes: 1 addition & 1 deletion docs/formal-verification-methods-in-wireframe.md
Original file line number Diff line number Diff line change
Expand Up @@ -1188,7 +1188,7 @@ organizational friction.
[^22]: Wireframe
[`src/message_assembler/header.rs`](../src/message_assembler/header.rs)
[^23]: Wireframe
[`src/message_assembler/series.rs`](../src/message_assembler/series.rs)
[`src/message_assembler/series/mod.rs`](../src/message_assembler/series/mod.rs)
[^24]: Wireframe
[`src/message_assembler/state.rs`](../src/message_assembler/state.rs)
[^25]: Wireframe [`src/fairness.rs`](../src/fairness.rs)
Expand Down
17 changes: 9 additions & 8 deletions docs/frame-vec-u8-inventory.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,11 @@ PR #283 moved more of the codec path toward `Bytes`.[^issue-286]
The middleware layer currently sits entirely inside an owned-`Vec<u8>` segment
of the request/response pipeline:

1. `src/app/inbound_handler.rs` builds or reuses the middleware chain through
`WireframeApp::build_chains()`, wrapping each route handler inside
1. `src/app/inbound_handler/mod.rs` builds or reuses the middleware chain
through `WireframeApp::build_chains()`, wrapping each route handler inside
`HandlerService<E>`.
2. `src/app/frame_handling/decode.rs` and `src/app/inbound_handler.rs` decode
an inbound codec frame into an `Envelope`.
2. `src/app/frame_handling/decode.rs` and `src/app/inbound_handler/mod.rs`
decode an inbound codec frame into an `Envelope`.
3. `src/app/frame_handling/response.rs` crosses the middleware boundary by
calling `ServiceRequest::new(env.payload, env.correlation_id)`.
4. `src/middleware.rs` exposes that payload to middleware as
Expand Down Expand Up @@ -152,8 +152,9 @@ The practical consequence is that middleware currently forms a hard
- `src/app/frame_handling/response.rs` is the request/response bridge into and
out of middleware. Any type change has to preserve correlation handling and
packet reconstruction here.
- `src/app/inbound_handler.rs` owns middleware-chain construction and therefore
any staging or compatibility story for mixed old/new middleware types.
- `src/app/inbound_handler/mod.rs` owns middleware-chain construction and
therefore any staging or compatibility story for mixed old/new middleware
types.
- `tests/middleware.rs` and `tests/middleware_order.rs` demonstrate the current
mutation semantics directly through `push`, `clear`, and `extend_from_slice`
on `frame_mut()`.
Expand Down Expand Up @@ -257,7 +258,7 @@ themselves `Frame = Vec<u8>` bindings:
`F: FrameLike + CorrelatableFrame + Packet` for the `ConnectionActor`.
- `src/app/builder/protocol.rs` stores protocols as
`WireframeProtocol<Frame = F::Frame, ProtocolError = ()>`.
- `src/codec.rs` defines the default `LengthDelimitedFrameCodec` with
- `src/codec/mod.rs` defines the default `LengthDelimitedFrameCodec` with
`Bytes` frames, not `Vec<u8>`.

Taken together, these show that the main frame-level tension is between generic
Expand Down Expand Up @@ -405,7 +406,7 @@ ADRs:
[comment](https://github.com/leynos/wireframe/pull/283#issuecomment-3167997856).
[^codec]: See
[Pluggable protocol codecs](execplans/pluggable-protocol-codecs.md)
and `src/codec.rs`.
and `src/codec/mod.rs`.
[^hooks]: See `src/hooks.rs` and the hook overview in
[users-guide.md](users-guide.md).
[^unified-path]: See
Expand Down
12 changes: 6 additions & 6 deletions docs/multi-packet-and-streaming-responses-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -515,15 +515,15 @@ staying true to the architecture already in production use.
mirrors the message attribution strategy outlined in the capability roadmap.
- **Correlation provenance today.** The current implementation expects
correlation to live inside the serialized `Envelope` payload. See the decode
path in `src/app/inbound_handler.rs` and the payload-carried correlation
path in `src/app/inbound_handler/mod.rs` and the payload-carried correlation
fields in `src/app/envelope.rs`.
- **Header correlation (if that is not the intent).** The boundary for
injecting header correlation is the frame-to-`Envelope` step in
`WireframeApp::decode_envelope` (`src/app/inbound_handler.rs`). That is where
the decoded frame and the deserialized `Envelope` are both available, so the
runtime can merge header correlation into `Envelope::correlation_id` (for
example, “if payload correlation is `None`, inherit from the header; if both
exist and differ, log and pick a precedence rule”). On the outbound path,
`WireframeApp::decode_envelope` (`src/app/inbound_handler/mod.rs`). That is
where the decoded frame and the deserialized `Envelope` are both available,
so the runtime can merge header correlation into `Envelope::correlation_id`
(for example, “if payload correlation is `None`, inherit from the header; if
both exist and differ, log and pick a precedence rule”). On the outbound path,
`FrameCodec::wrap_payload` receives the codec instance and raw `Bytes`, but
it still cannot see correlation unless it is embedded in the payload.
Supporting header correlation therefore requires a codec API that can wrap
Expand Down
6 changes: 5 additions & 1 deletion docs/repository-layout.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ and shared test support. Its main areas are:
- `src/` contains the published `wireframe` library.
- `crates/wireframe-verification/` contains verification support.
- `wireframe_testing/` contains shared test fixtures and helpers.
- `tests/` contains integration and behaviour-driven tests.
- `tests/` contains integration and behaviour-driven tests. An
integration-test root laid out as `tests/<name>/mod.rs` needs an explicit
`[[test]]` entry in `Cargo.toml`, because Cargo auto-discovers `tests/*.rs`
and `tests/<name>/main.rs` but not `tests/<name>/mod.rs`. Without the entry
the root is silently not built or run.
- `tools/dev-fast/config.toml` is the explicitly selected development Cargo
configuration. The
[development builds](developers-guide.md#development-builds) section
Expand Down
3 changes: 2 additions & 1 deletion docs/roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,8 @@ integration boundaries.
[outbound messaging design](asynchronous-outbound-messaging-design.md)).
- [x] Route app-level request and response handling through the
`FramePipeline` so fragmentation and metrics apply consistently.
- [x] Remove duplicate codec construction in `src/app/inbound_handler.rs`; the
- [x] Remove duplicate codec construction in
`src/app/inbound_handler/mod.rs`; the
`FramePipeline` owns outbound fragmentation.
- [x] Add integration tests covering the unified pipeline (round-trip,
fragmentation, sequential requests, disabled fragmentation).
Expand Down
10 changes: 5 additions & 5 deletions docs/users-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -2655,8 +2655,8 @@ directories (one per shard on full dispatch runs) for offline triage.
[^3]: Implemented in `src/app/builder.rs` (lines 100-121, 347-360).
[^4]: Implemented in `src/app/builder.rs` (lines 326-344).
[^5]: Implemented in `src/error.rs` (lines 1-68).
[^6]: Implemented in `src/app/inbound_handler.rs` (lines 41-205).
[^7]: Implemented in `src/app/inbound_handler.rs` (lines 207-289).
[^6]: Implemented in `src/app/inbound_handler/mod.rs` (lines 41-205).
[^7]: Implemented in `src/app/inbound_handler/mod.rs` (lines 207-289).
[^8]: Implemented in `src/app/envelope.rs` (lines 11-172).
[^9]: Implemented in `src/frame/metadata.rs` (lines 1-40).
[^10]: Implemented in `src/message.rs` (lines 4-41).
Expand All @@ -2665,10 +2665,10 @@ directories (one per shard on full dispatch runs) for offline triage.
[^13]: Implemented in `src/extractor.rs` (lines 1-236).
[^14]: Implemented in `src/hooks.rs` (lines 18-175).
[^15]: Implemented in `src/server/config/mod.rs` (lines 47-152).
[^16]: Implemented in `src/server/runtime.rs` (lines 46-83).
[^16]: Implemented in `src/server/runtime/mod.rs` (lines 46-83).
[^17]: Implemented in `src/server/config/binding.rs` (lines 68-214).
[^18]: Implemented in `src/server/runtime.rs` (lines 90-233).
[^19]: Implemented in `src/server/runtime.rs` (lines 240-333).
[^18]: Implemented in `src/server/runtime/mod.rs` (lines 90-233).
[^19]: Implemented in `src/server/runtime/mod.rs` (lines 240-333).
[^20]: Implemented in `src/server/config/preamble.rs` (lines 14-135) and
`src/server/connection_spawner.rs` (lines 1-222).
[^21]: Implemented in `src/server/error.rs` (lines 7-18).
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,31 @@
//! fragment envelope construction, framed transport, test app construction,
//! and assertions.

#[path = "fragment_helpers/app.rs"]
#[path = "app.rs"]
mod app;
#[path = "fragment_helpers/assertions.rs"]
#[path = "assertions.rs"]
mod assertions;
#[path = "fragment_helpers/config.rs"]
#[path = "config.rs"]
mod config;
#[path = "fragment_helpers/envelopes.rs"]
#[path = "envelopes.rs"]
mod envelopes;
#[path = "fragment_helpers/errors.rs"]
#[path = "errors.rs"]
mod errors;
#[path = "fragment_helpers/transport.rs"]
#[path = "transport.rs"]
mod transport;

pub use app::{make_app, make_handler, spawn_app};
pub use assertions::assert_handler_observed;
pub use config::{fragmentation_config, fragmentation_config_with_timeout};
pub use envelopes::{build_envelopes, fragment_envelope};
pub use errors::{TestError, TestResult};
pub use transport::{read_reassembled_response, read_response_payload, send_envelopes};
pub use transport::{
FramedResponse,
read_framed_response,
read_reassembled_response,
read_response_payload,
send_envelopes,
};

/// Default route ID used in fragmentation tests.
pub const ROUTE_ID: u32 = 42;
Expand Down
Loading
Loading