Skip to content

test(eventhubs): cover consumer receive options - #5091

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

test(eventhubs): cover consumer receive options#5091
Johnathan W (j7nw4r) wants to merge 2 commits into
Azure:mainfrom
j7nw4r:j7nw4r/eventhubs-receive-options-live-tests

Conversation

@j7nw4r

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

Copy link
Copy Markdown
Member

Summary

This change adds tests/eventhubs_receive_options.rs with six live tests for the consumer receive options. The tests cover a custom prefetch value, the smallest usable prefetch value, the receive_timeout semantics on an idle partition and on a slow partition, the consumer with_instance_id option, and the producer with_application_id option.

Motivation

Prefetch sets the credit that the receiver grants to the AMQP link, so a wrong value can stall a stream or waste memory, and no test sets OpenReceiverOptions::prefetch today. The receive timeout controls what happens when a partition is idle; five tests set receive_timeout and none assert it. ConsumerClientBuilder::with_instance_id has no caller in the repository. Part of #4886.

Changes

  • Add tests/eventhubs_receive_options.rs with six #[recorded::test(live)] tests.
  • Cover a custom prefetch of 3 and the smallest usable prefetch of 1, and assert that every event of the run arrives in order.
  • Assert that an idle partition yields a receive-timeout error whose chain reaches std::io::ErrorKind::TimedOut, that it arrives inside a timing window, and that the stream then ends.
  • Assert that a stream fed slower than the receive timeout is not truncated, which pins the documented per-delivery meaning of the option.
  • Cover ConsumerClientBuilder::with_instance_id and ProducerClientBuilder::with_application_id.
  • Tag every event with a per-run marker, so each test asserts on its own events and tolerates the foreign traffic that shares a partition.

Test plan

  • CARGO_BUILD_JOBS=1 RUSTFLAGS=-Dwarnings cargo test --no-run --package azure_messaging_eventhubs exits 0. CI sets RUSTFLAGS: "-Dwarnings", so this gate catches an unused import, an unused constant, or an uncalled helper.
  • cargo test --package azure_messaging_eventhubs --test eventhubs_receive_options -- --test-threads=1 reports 0 passed; 0 failed; 6 ignored, because the tests are live-gated.
  • cargo test --package azure_messaging_eventhubs -- --test-threads=1 reports 196 passed and 0 failed across all targets.
  • cargo fmt --package azure_messaging_eventhubs -- --check, cargo clippy --package azure_messaging_eventhubs --all-features --all-targets with -Dwarnings, and cargo doc --package azure_messaging_eventhubs --all-features --no-deps with -Dwarnings all exit 0.
  • npx cspell lint --config ./.vscode/cspell.json --no-must-find-files --no-gitignore --root . <the new file> reports Files checked: 1, Issues found: 0.
  • No red proof accompanies these tests, and none is possible. They pin behavior that the shipped source already has, this change touches no source file, and a live-gated test cannot run without a namespace. A throwaway unit test invented to produce a failing run would prove nothing.

Assumptions and divergences from the .NET tests

  • The small prefetch value is 1, not 0. prefetch maps to ReceiverCreditMode::Auto(n), and a value of 0 gives the link no credit and stalls the reader, so no test pins that path. .NET maps PrefetchCount = 0 to AutoSendFlow = false and issues credit per read instead, which this crate cannot express through OpenReceiverOptions. A follow-up issue should decide whether prefetch: Some(0) ought to select ReceiverCreditMode::Manual.
  • The idle test asserts the current Rust behavior, which is that the stream yields an error and then ends. .NET ReadEventOptions.MaximumWaitTime yields a repeatable empty event and never ends the enumeration, so a direct port of ConsumerRespectsTheWaitTimeWhenReading could not pass. A follow-up issue should decide whether the Rust stream ought to surface an idle interval in band instead.
  • The producer test uses with_application_id, because ProducerClientBuilder has no with_instance_id. Adding one is a public API change and is out of scope for a test change. A follow-up issue should decide whether the producer needs identifier parity with the consumer.
  • The producer test overlaps existing coverage in tests/eventhubs_producer.rs on purpose, so the third item in [Event Hubs] Add live tests for consumer receive options #4891 maps to a named test.
  • The two prefetch tests cannot detect a regression that silently drops prefetch and substitutes the default of 300, because the negotiated link credit is not observable through the public API. They do catch a broken credit replenishment and a rejected small credit.

Closes #4891.

Live validation

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

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

One assertion was widened after that run. The receive timeout cause could not be downcast to std::io::Error, because the receiver wraps it in Box::new at common/recoverable/receiver.rs:129 and azure_core::Error::new boxes again, so the stored type is Box<std::io::Error>. The test accepts either shape, so it keeps passing once the extra box goes away. The extra box is tracked in #5098.

@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.

Issue Azure#4891 asks for live coverage of the consumer receive options and
of the client identifiers. Add six live tests in one new file.

Two tests read a ten event backlog with a prefetch of three and of one,
which proves the receiver replenishes its link credit. One test leaves
an idle receiver and asserts the receive timeout gives a TimedOut I/O
error and then ends the stream. One test sends six events three seconds
apart under a ten second receive timeout, which pins the documented rule
that the timeout applies to each delivery and not to the whole read. One
test opens a consumer with an instance identifier and reads its events
back. One test opens a producer with an application identifier and sends.

Each test reads the tail of its partition before it sends, and it tags
every event with a run marker. The assertions look only at events that
carry the marker, so traffic from another run never enters a result.

These tests pin behavior the shipped source already has, so they pass
against unchanged source. No source file changes.
The receive timeout error could not be downcast to `std::io::Error`. The
receiver wraps the cause in `Box::new` at
common/recoverable/receiver.rs:129, and `azure_core::Error::new` boxes
its argument again, so the stored concrete type is
`Box<std::io::Error>`.

Try both shapes, so the test states the real contract, that the timeout
reports an I/O `TimedOut` cause, and keeps passing once the redundant box
goes away. A live run of the six tests now passes.
@j7nw4r
Johnathan W (j7nw4r) force-pushed the j7nw4r/eventhubs-receive-options-live-tests branch from bc53400 to d91a5a9 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 consumer receive options

1 participant