[
https://issues.apache.org/jira/browse/CAMEL-25738?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18128714#comment-18128714
]
Claus Ibsen commented on CAMEL-25738:
-------------------------------------
Merged to main for 4.24.0 in https://github.com/apache/camel/pull/28067 (commit
6f36673e85cf).
_Claude Code on behalf of Claus Ibsen_
> camel-test-dst - deterministic simulation testing for Camel consumers (stage
> 1)
> -------------------------------------------------------------------------------
>
> Key: CAMEL-25738
> URL: https://issues.apache.org/jira/browse/CAMEL-25738
> Project: Camel
> Issue Type: New Feature
> Components: camel-test
> Reporter: Claus Ibsen
> Assignee: shashank
> Priority: Major
> Fix For: 4.24.0
>
> Attachments: camel-test-dst-sqs-world.patch
>
>
> A new {{camel-test-dst}} module for deterministic simulation testing of Camel
> consumers: one seeded scheduler runs every Camel thread pool on the test
> thread, time is virtual, a fake of the external system injects faults chosen
> by the seed, invariants are checked after each run, and a failing seed
> replays with the same trace.
> The prototype is on the branch {{camel-test-dst-prototype}} of
> github.com/allthingssecurity/camel
> ({{components/camel-test/camel-test-dst}}). This issue is the scope of stage
> 1: making the harness trustworthy enough that a fake world can be written for
> a component without running into the harness. The chaos proposal waits until
> this is done.
> h3. Evidence so far
> A third world was written for camel-aws2-sqs (the visibility timeout
> extender, a fake SQS queue written from the AWS API reference, 458 lines):
> * main: 0 of 5000 seeds fail; {{Sqs2Consumer}} before CAMEL-25700: 1383 of
> 5000 fail, only with {{maxMessagesPerPoll >= 2}} and {{concurrentConsumers >=
> 2}}, as that fix describes; a failing seed replays with the same SHA-256.
> * it found CAMEL-25737 ({{visibilityTimeout=1}}), because the seed also picks
> the endpoint configuration.
> * it needed a harness fix first (item 1): without it, 271 of 500 seeds on
> main were false failures.
> h3. Stage 1 scope
> # *Time read outside the instrumented package.* Byte code is rewritten only
> in the package of {{@DstInstrument}}, and {{java.time}} was not rewritten at
> all ({{Instant.now()}} in the SQS extender). Core clocks still read real
> time: {{MonotonicClock}} (camel-support), {{StopWatch}} (camel-util),
> {{ScheduledPollConsumer}}. Decide between rewriting the core packages too and
> a small time-source hook in core that DST replaces (the README suggests the
> hook; it touches core, so it needs a dev@ discussion).
> # *Real sleeps on the loop thread.* {{RedeliveryPolicy.sleep()}}
> ({{Thread.sleep}}, used by the default synchronous redelivery,
> {{asyncDelayedRedelivery=false}}), {{ForegroundTask}} (used by 10 component
> source files), {{DefaultShutdownStrategy}} (waits for in-flight exchanges
> with {{Thread.sleep}}; the Slack world copies the suspend sequence by hand
> because of it). A virtual sleep that becomes {{dst.block()}} on the loop
> thread.
> # *Timed waits never time out.* {{DstTask.get(timeout)}} ignores the timeout
> and {{awaitTermination}} returns true, so timeout paths (circuit breaker,
> shutdown, {{Future.get(timeout)}}) cannot be explored. Timeouts must fire in
> virtual time.
> # *Waits on something that is not a DST task deadlock.*
> {{CompletableFuture.get()}}/{{join()}} or {{CountDownLatch.await()}} on the
> loop thread hang (the SQS consumer with more than 10 messages per poll). At
> least fail fast with a clear message; better, rewrite them to run the loop
> until the future completes.
> # *Escapes fail the seed, not only the report.* The {{Instant.now()}} gap
> showed up only as a line in {{escapes.txt}}; a mode where reaching an
> uncontrolled escape at runtime fails the seed makes the cause obvious.
> # *Module layout.* camel-test-dst holds the harness only; the demos
> (azure-eventhubs, slack, and the sqs world) move to the tests of their
> component modules as passing regression tests. Refresh the README numbers:
> the fixes of #27922 and #27923 are on main.
> # *A guide for AI agents (and humans) on writing a fake world*, in the module
> doc page with a pointer in {{AGENTS.md}}, using the SQS world as the worked
> example:
> #* find where the client is swapped (an endpoint option such as
> {{amazonSQSClient}}, else a static mock of the factory);
> #* run the escape scan before writing anything, and fix, avoid or document
> every escape;
> #* write the fake from the service's documentation, quoting the rule for each
> behaviour and marking assumptions;
> #* the one-stack timing rule: a blocked task resumes only after the tasks
> that blocked after it, so reads take effect at the end of their latency,
> writes at the start, and background tasks (extenders, timers) do not block;
> #* let the seed pick the endpoint configuration as well as the timing;
> #* seeded faults, switched off for a drain phase, with a record of which
> injected fault excuses which violation;
> #* the invariant from the component's contract, starting from the reusable
> {{Invariants}};
> #* the self-check: fail on the code before a past fix ({{git log}}), pass on
> main, and the same SHA-256 when a seed is replayed;
> #* triage before reporting: group failing seeds by configuration, read one
> trace, tell harness artifact, fake mistake and real bug apart.
> Each harness fix comes with a self-test, like {{DstSchedulerTest}}.
> h3. Later stages (not in this issue)
> * The one-stack model itself (a real fix may need virtual threads with a
> custom scheduler); stage 1 documents it.
> * Async clients on Reactor's own schedulers (the Azure SDKs).
> * Several runs in parallel in one JVM (the active run is a static field).
> * Sharing the fault rules with the chaos proposal.
> _Claude Code on behalf of Claus Ibsen_
--
This message was sent by Atlassian Jira
(v8.20.10#820010)