Skip to content

test(eventhubs): cover producer routing and payload edges - #5089

Draft
Johnathan W (j7nw4r) wants to merge 2 commits into
Azure:mainfrom
j7nw4r:j7nw4r/eventhubs-producer-routing-live-tests
Draft

test(eventhubs): cover producer routing and payload edges#5089
Johnathan W (j7nw4r) wants to merge 2 commits into
Azure:mainfrom
j7nw4r:j7nw4r/eventhubs-producer-routing-live-tests

Conversation

@j7nw4r

@j7nw4r Johnathan W (j7nw4r) commented Aug 20, 2026

Copy link
Copy Markdown
Member

Summary

This change adds ten tests for producer partition key routing and for the payload edges of an event in azure_messaging_eventhubs. Eight are live tests, and two are plain unit tests that pin the new helpers. The change adds one new test file and edits no source file.

Closes #4890. Part of #4886.

Motivation

Partition key routing is a service side hash, so only a live test proves that one key maps to one partition. The payload edges, which are a zero length body, a large event, and an oversized event, exercise the encoder and the service limit check. Receive side validation of the AMQP body types proves the round trip and not only the encode step. The issue says that no test reads a value body or a sequence body back. test_round_trip_batch does read both back, but it asserts only the sequence number and the message id, so the body content was never pinned. The real gap is the missing assertion.

Changes

  • Add sdk/eventhubs/azure_messaging_eventhubs/tests/eventhubs_producer_routing.rs with eight #[recorded::test(live)] tests and two plain #[test] unit tests.
  • partition_key_routes_batch_to_one_partition sends one keyed batch, sweeps every partition, and proves that all marked events land on one partition and that each event carries the key back.
  • same_partition_key_routes_to_same_partition sends two batches with the same key and proves that both land on the same partition.
  • zero_length_body_round_trips_as_empty_slice proves that a zero length body arrives as an empty slice and not as an absent body.
  • large_event_body_round_trips_intact sends a 100000 byte body and compares the received bytes against the sent bytes.
  • oversized_send_event_does_not_succeed proves that send_event does not accept a 2 MB payload.
  • amqp_value_body_round_trips_without_event_data_body, amqp_sequence_body_round_trips_in_order, and binary_application_property_round_trips assert the received AMQP body shapes and a binary application property.
  • tagged_label_matches_only_the_run_marker and large_body_fills_a_non_constant_pattern pin the two pure helpers, and they run in every test mode.
  • The manifest does not change, so this branch cannot conflict with PR test(eventhubs): cover consumer start positions #5077, which adds the tokio sync feature to the same file.

Assumptions

The issue left several points open. This change takes the most conservative reading of each one.

  1. Requirement 4 covers the send_event path only. The test asserts that the send does not succeed, inside a bounded timeout. It asserts no ErrorKind, because src/error.rs holds no size limit variant and nothing pins how the AMQP LinkPayloadSizeExceeded condition reaches the caller. A live run can tighten this later.
  2. The batch refusal half of requirement 4 gets no new test. create_batch_honors_max_size_in_bytes and create_batch_rejects_size_above_link_maximum already pin it in tests/eventhubs_producer.rs.
  3. The large body is 100000 bytes, which matches the .NET test ProducerCanSendSingleLargeEventInASet. Event Hubs caps a single event for each tier, at 256 KB on Basic and 1 MB on Standard, so a fixed 1 MB body would fail on a Basic namespace.
  4. The routing tests observe the landing partition with a sequential receiver sweep that filters on a per run marker. A sequence number delta was rejected, because a concurrent sender on a shared namespace advances a second partition and breaks the assertion.
  5. No test asserts a specific partition id, and no test asserts that a different key lands on a different partition. The hash is stable only for a fixed partition count, and two keys can collide over four partitions.
  6. All tests live in one new file. The shipped tests/eventhubs_round_trip.rs is not edited.
  7. No public API is added. An accessor for the maximum batch size was rejected as out of scope for a test only issue, because it would need an API review and a changelog entry.

Test plan

Run the live tests with this exact command:

AZURE_TEST_MODE=live EVENTHUBS_HOST=<namespace>.servicebus.windows.net EVENTHUB_NAME=<hub> cargo test --package azure_messaging_eventhubs --test eventhubs_producer_routing -- --test-threads=1

The eight live tests report as ignored without AZURE_TEST_MODE=live, so they must be run live before they are trusted.

These checks pass on this branch, and each one exits 0:

  • RUSTFLAGS=-Dwarnings cargo test --no-run --package azure_messaging_eventhubs, which is the CI gate that denies warnings.
  • cargo test --package azure_messaging_eventhubs --test eventhubs_producer_routing -- --test-threads=1 reports 2 passed, 0 failed, and 8 ignored.
  • cargo test --package azure_messaging_eventhubs -- --test-threads=1 for the whole crate suite.
  • RUSTFLAGS=-Dwarnings cargo clippy --package azure_messaging_eventhubs --all-targets --no-deps.
  • cargo fmt --package azure_messaging_eventhubs -- --check.
  • RUSTDOCFLAGS=-Dwarnings cargo doc --package azure_messaging_eventhubs --all-features --no-deps.
  • cspell with the repository config on the new file, which reports 1 file checked and 0 issues.

The two plain unit tests carry a mutation proof. A contains_key version of the marker helper fails the case for the marker of another run, and a constant fill fails the pattern assertion in the body helper.

Known nits

These two points came out of review. Neither one blocks the change, and each is a small follow up.

  • In oversized_send_event_does_not_succeed, the arm that panics on an unexpected success runs before the producer closes, so that one failure path leaves the connection open until the process ends. The other seven live tests close both clients before their assertions.
  • The panic text for an unexpected AMQP body prints through SafeDebug, so it names the wrong variant but hides the inner payload. The crate does not enable the debug feature. A live run can tighten this if the variant name is not enough.

Live validation

Every test here ran against a live Event Hubs namespace on 2026-08-20: 10 passed, 0 failed.

Command: AZURE_TEST_MODE=live cargo test --package azure_messaging_eventhubs --test eventhubs_producer_routing -- --test-threads=1.

One assertion was rewritten after that run. The single event oversized test could not pass: the sender link reported max_allowed: 1048576, and send_event still accepted a 2 MiB event, returned Ok(()), and moved the partition tail. The batch path refuses the same event, and that is also what the .NET ProducerCannotSendSetLargerThanMaximumSize asserts, so the test now reads the maximum from the InvalidBatchSize error and asserts the batch refusal. The single event divergence is tracked in #5101.

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).
3 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

Add tests/eventhubs_producer_routing.rs. The file covers the partition
key routing of a batch, the zero length body, the large body, the
oversized single event, the AMQP value body, the AMQP sequence body,
and the binary application property.

Each test captures the tail sequence number of every partition that it
reads, then reads strictly after that boundary. Every event carries a
per run marker, and every receive side assertion filters on it. No
assertion depends on a partition tail staying still, so the tests need
no lock against each other, and only one receiver is open at a time.

The eight live tests are unproven until a live run. The test macro
marks them as ignored when the compile time mode is below Live, so they
neither pass nor fail here. The two plain unit tests carry a mutation
proof: a contains_key marker check makes tagged_label accept another
run, and a constant fill or a 256 byte fill makes large_body fail its
pattern assertions.

The file needs no Cargo.toml change, so it cannot conflict with PR
5077, which adds the tokio sync feature to the same manifest.
A live run showed that the single event path does not enforce the
negotiated AMQP link maximum. The sender link reported
`max_allowed: 1048576` on a Standard namespace, and `send_event` still
accepted a 2 MiB event, returned `Ok(())`, and moved the partition tail.
The batch path refuses the same event, so the old assertion could never
pass against a real broker.

Assert the batch refusal instead, which is also what the .NET
`ProducerCannotSendSetLargerThanMaximumSize` asserts. Read the maximum
from the `InvalidBatchSize` error rather than hardcoding it, so the test
holds on every tier. The single event divergence needs its own issue.
@j7nw4r
Johnathan W (j7nw4r) force-pushed the j7nw4r/eventhubs-producer-routing-live-tests branch from f64462e to 6bd09de Compare August 25, 2026 18:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Event Hubs] Add live tests for producer routing and payload edge cases

1 participant