rdkafka-hs (empty) → 1.1.0.0
raw patch · 163 files changed
+73014/−0 lines, 163 filesdep +basedep +bifunctorsdep +bytestring
Dependencies added: base, bifunctors, bytestring, containers, directory, network, process, random, rdkafka-hs, tasty, tasty-hunit, tasty-quickcheck, text, transformers, unix
Files
- CHANGELOG.md +162/−0
- LICENSE +21/−0
- README.md +532/−0
- docs/testing/authentication-evidence.json +428/−0
- docs/testing/authentication-qualification-context.json +101/−0
- docs/testing/broker-failure-evidence.json +377/−0
- docs/testing/broker-qualification-context.json +93/−0
- docs/testing/callback-buffer-evidence.json +95/−0
- docs/testing/callback-native-diagnostics.json +54/−0
- docs/testing/callback-ownership-inventory.json +241/−0
- docs/testing/compatibility-matrix.json +2565/−0
- docs/testing/compiler-forwarding-coverage-audit.json +57/−0
- docs/testing/config-string-evidence.json +59/−0
- docs/testing/consumer-commit-evidence.json +51/−0
- docs/testing/consumer-edges-evidence.json +57/−0
- docs/testing/consumer-state-evidence.json +60/−0
- docs/testing/coverage-classification-remap.json +337/−0
- docs/testing/coverage-evidence.json +28991/−0
- docs/testing/coverage-matrix.json +14213/−0
- docs/testing/coverage.md +141/−0
- docs/testing/deferred-public-contract-evidence.json +150/−0
- docs/testing/deferred-source-audit.json +241/−0
- docs/testing/deferred-validation-snapshot.json +686/−0
- docs/testing/deferred-validation.md +89/−0
- docs/testing/deprecated-runner-evidence.json +39/−0
- docs/testing/diagnostic-evidence.json +42/−0
- docs/testing/example-evidence.json +48/−0
- docs/testing/final-boundaries-evidence.json +54/−0
- docs/testing/generated-mapping-evidence.json +37/−0
- docs/testing/input-identity-evidence.json +58/−0
- docs/testing/legacy-seek-evidence.json +215/−0
- docs/testing/linux-tuple-evidence.json +1413/−0
- docs/testing/message-ownership-evidence.json +54/−0
- docs/testing/metadata-evidence.json +58/−0
- docs/testing/metadata-field-evidence.json +47/−0
- docs/testing/metadata-partition-evidence.json +53/−0
- docs/testing/metadata-unicode-evidence.json +73/−0
- docs/testing/mutation-runner-parity.json +351/−0
- docs/testing/native-storable-coverage-audit.json +59/−0
- docs/testing/partition-list-evidence.json +63/−0
- docs/testing/post-wrapper-evidence.json +48/−0
- docs/testing/primary-validation-evidence.json +149/−0
- docs/testing/private-binding-coverage-audit.json +62/−0
- docs/testing/private-haskell-coverage-audit.json +142/−0
- docs/testing/producer-evidence.json +380/−0
- docs/testing/producer-properties-evidence.json +232/−0
- docs/testing/public-data-evidence.json +56/−0
- docs/testing/public-properties-evidence.json +87/−0
- docs/testing/queue-notification-evidence.json +71/−0
- docs/testing/rebalance-error-evidence.json +43/−0
- docs/testing/runtime-evidence.json +41/−0
- docs/testing/seek-evidence.json +165/−0
- docs/testing/topic-admin-evidence.json +295/−0
- docs/testing/transaction-evidence.json +93/−0
- docs/testing/transaction-native-diagnostics.json +27/−0
- example/ConsumerExample.hs +79/−0
- example/Main.hs +28/−0
- example/ProducerExample.hs +119/−0
- rdkafka-hs.cabal +268/−0
- scripts/binding-inventory.sh +226/−0
- scripts/check-coverage.py +149/−0
- scripts/collect-coverage.py +274/−0
- scripts/coverage-preprocess.py +78/−0
- scripts/coverage-zero.hs +22/−0
- scripts/coverage_common.py +124/−0
- scripts/test-coverage-tools.py +282/−0
- scripts/test-coverage.sh +7/−0
- scripts/test-mutations.hs +621/−0
- src/Kafka/Callbacks.hs +57/−0
- src/Kafka/Consumer.hs +929/−0
- src/Kafka/Consumer/Callbacks.hs +134/−0
- src/Kafka/Consumer/ConsumerProperties.hs +200/−0
- src/Kafka/Consumer/Convert.hs +241/−0
- src/Kafka/Consumer/Subscription.hs +69/−0
- src/Kafka/Consumer/Types.hs +269/−0
- src/Kafka/Dump.hs +82/−0
- src/Kafka/Internal/CallbackOwner.hs +90/−0
- src/Kafka/Internal/RdKafka.chs +1550/−0
- src/Kafka/Internal/Setup.hs +228/−0
- src/Kafka/Internal/Shared.hs +174/−0
- src/Kafka/Metadata.hs +362/−0
- src/Kafka/Producer.hs +312/−0
- src/Kafka/Producer/Callbacks.hs +93/−0
- src/Kafka/Producer/Convert.hs +46/−0
- src/Kafka/Producer/ProducerProperties.hs +136/−0
- src/Kafka/Producer/Types.hs +91/−0
- src/Kafka/Topic.hs +196/−0
- src/Kafka/Topic/Types.hs +24/−0
- src/Kafka/Transaction.hs +142/−0
- src/Kafka/Types.hs +211/−0
- src/Kafka/Version.hs +51/−0
- test-integration/Kafka/AdminTestSupport.hs +140/−0
- test-integration/Kafka/CallbackLifetimeSupport.hs +28/−0
- test-integration/Kafka/CallbackTestSupport.hs +56/−0
- test-integration/Kafka/Compatibility/KafkaFixture.hs +252/−0
- test-integration/Kafka/Compatibility/SecurityFixture.hs +164/−0
- test-integration/Kafka/ConsumerStateSupport.hs +63/−0
- test-integration/Kafka/DiagnosticTestSupport.hs +30/−0
- test-integration/Kafka/FaultTestSupport.hs +50/−0
- test-integration/Kafka/FixtureSupport.hs +84/−0
- test-integration/Kafka/FixtureSupportTest.hs +99/−0
- test-integration/Kafka/Integration/AssignOnlyTest.hs +77/−0
- test-integration/Kafka/Integration/AttributedErrorTest.hs +90/−0
- test-integration/Kafka/Integration/AuthenticationTest.hs +265/−0
- test-integration/Kafka/Integration/BatchTest.hs +34/−0
- test-integration/Kafka/Integration/BrokerFailureTest.hs +339/−0
- test-integration/Kafka/Integration/CallbackLifetimeTest.hs +660/−0
- test-integration/Kafka/Integration/ConfigStringContractTest.hs +62/−0
- test-integration/Kafka/Integration/ConfigurationTest.hs +40/−0
- test-integration/Kafka/Integration/ConsumerCommitContractTest.hs +167/−0
- test-integration/Kafka/Integration/ConsumerPropertyTest.hs +110/−0
- test-integration/Kafka/Integration/ConsumerStateContractTest.hs +330/−0
- test-integration/Kafka/Integration/ConsumerTest.hs +171/−0
- test-integration/Kafka/Integration/DeprecatedRunnerContractTest.hs +120/−0
- test-integration/Kafka/Integration/DestroyTest.hs +182/−0
- test-integration/Kafka/Integration/DiagnosticContractTest.hs +133/−0
- test-integration/Kafka/Integration/FatalErrorTest.hs +108/−0
- test-integration/Kafka/Integration/HeadersTest.hs +119/−0
- test-integration/Kafka/Integration/InputBoundaryContractTest.hs +89/−0
- test-integration/Kafka/Integration/LifecycleTest.hs +133/−0
- test-integration/Kafka/Integration/MetadataContractTest.hs +237/−0
- test-integration/Kafka/Integration/ObserverTest.hs +104/−0
- test-integration/Kafka/Integration/PartitionListContractTest.hs +137/−0
- test-integration/Kafka/Integration/PerMessageCommitTest.hs +41/−0
- test-integration/Kafka/Integration/ProducerPropertyTest.hs +65/−0
- test-integration/Kafka/Integration/ProducerRegressionTest.hs +541/−0
- test-integration/Kafka/Integration/PublicConsumerContractTest.hs +407/−0
- test-integration/Kafka/Integration/QueueEventTest.hs +200/−0
- test-integration/Kafka/Integration/ReadCommittedTest.hs +72/−0
- test-integration/Kafka/Integration/RuntimeContractTest.hs +56/−0
- test-integration/Kafka/Integration/SeekPartitionsTest.hs +268/−0
- test-integration/Kafka/Integration/StoreOffsetsTest.hs +72/−0
- test-integration/Kafka/Integration/TopicConfigurationTest.hs +527/−0
- test-integration/Kafka/Integration/TopicTest.hs +56/−0
- test-integration/Kafka/Integration/TransactionErrorTest.hs +305/−0
- test-integration/Kafka/MessageTestSupport.hs +26/−0
- test-integration/Kafka/MetadataTestSupport.hs +36/−0
- test-integration/Kafka/ProducerTestSupport.hs +70/−0
- test-integration/Kafka/SeekTestSupport.hs +26/−0
- test-integration/Kafka/TestEnv.hs +321/−0
- test-integration/Kafka/TransactionTestSupport.hs +34/−0
- test-integration/Main.hs +120/−0
- test-integration/cbits/admin_ownership.c +297/−0
- test-integration/cbits/callback_lifetime.c +173/−0
- test-integration/cbits/consumer_state.c +191/−0
- test-integration/cbits/diagnostics.c +113/−0
- test-integration/cbits/message_ownership.c +215/−0
- test-integration/cbits/metadata.c +151/−0
- test-integration/cbits/partition_lists.c +112/−0
- test-integration/cbits/producer_ownership.c +207/−0
- test-integration/cbits/seek_faults.c +108/−0
- test-integration/cbits/transaction_ownership.c +186/−0
- test-support/Kafka/PropertySupport.hs +22/−0
- test/Kafka/Consumer/ConsumerPropertiesSpec.hs +27/−0
- test/Kafka/Consumer/ConsumerRecordMapSpec.hs +42/−0
- test/Kafka/Consumer/ConsumerRecordTraverseSpec.hs +58/−0
- test/Kafka/Internal/CallbackOwnerSpec.hs +145/−0
- test/Kafka/Producer/ProducerPropertiesSpec.hs +93/−0
- test/Kafka/PublicDataContractSpec.hs +274/−0
- test/Kafka/PublicPropertiesSpec.hs +283/−0
- test/Kafka/VersionTest.hs +24/−0
- test/Main.hs +35/−0
- test/cbits/error_constants.c +22/−0
+ CHANGELOG.md view
@@ -0,0 +1,162 @@+# Changelog++All notable changes to rdkafka-hs are recorded here.++The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and+this project adheres to the [Haskell Package Versioning Policy](https://pvp.haskell.org/).++## [Unreleased]++## [1.1.0.0] - 2026-10-24++### Changed++- Later subscription property values now override earlier values. Topic names+ still accumulate by set union. This changes the inherited precedence rule.+- Producer topic settings now take effect; explicit topic values override+ matching global values. Empty keys and values remain distinct from absent ones.+- Consumer, seek, metadata and administration calls preserve native failures,+ including per-partition errors. Embedded NUL names and out-of-range numeric+ inputs are rejected before changing state.+- Callback exceptions are contained in Haskell and reported through the runtime+ exception handler. Async consumers require a threaded runtime; sync consumers+ also work in nonthreaded executables.++### Fixed++- Topic creation applies its configuration without the inherited crash. Admin+ requests retain their actual deadline and cannot report malformed responses+ as success.+- Manual synchronous callback polling preserves ordered records. Successful+ seek/rebalance operations discard the appropriate stale buffered state;+ failed native state changes preserve it and report their errors.+- Native clients, callbacks, message batches, metadata/group results,+ transaction errors and partition lists release their owners across failure,+ cancellation and teardown. Temporary seek topics are destroyed before their+ native parent, preventing late finalizers from corrupting another consumer.+- Diagnostic output flushes correctly, preserves the caller's handle and closes+ temporary native streams and duplicate descriptors on errors.+- SASL credential replacement preserves Unicode identity, rejects embedded NUL+ and releases native errors. Native producer error codes remain intact, and+ rejected per-message callback roots are released before error decoding.++Validation includes full primary normal/coverage runs and named Linux, Apache+failover, native lifetime and authenticated TLS/ACL/reconnect scenarios. The+remaining comprehensive qualification work stays tracked in+[MasterPlan 3](docs/masterplans/3-complete-deferred-coverage-and-compatibility-validation.md).++## [1.0.0.1] - 2026-10-23++### Fixed++- Consumed record headers were decoded in reverse wire order, so+ `headersToList` returned the last header first and selecting the last+ occurrence of a repeated name picked the first value the producer sent.+ `pollMessage`, `pollMessageAttributed` and every other consumer path now+ return the headers in the order the producer sent them, repeated names and+ identical pairs included. The `Headers` API is unchanged.+- The `setConsumerQueueIOEvent` documentation described a wait protocol that+ discarded pending wake-ups after draining the queue, which can lose the+ wake-up for a record that arrives in between. It now discards them first.++## [1.0.0.0] - 2026-10-22++rdkafka-hs is the maintained successor of+[hw-kafka-client](https://github.com/haskell-works/hw-kafka-client). Its history+starts from hw-kafka-client 5.3.0 (Hackage, 2023), includes the twelve commits on+upstream `main` that were never released (up to `56be4a6`, 2025-10-03), and adds+the consumer fatal-error fix `6caed63`. Everything below is relative to Hackage's+hw-kafka-client 5.3.0. See the README's "Migrating from hw-kafka-client".++### Changed++- The package is renamed from `hw-kafka-client` to `rdkafka-hs` and its version+ restarts at `1.0.0.0`. The `Kafka.*` module namespace, public type names and+ record field names are unchanged, so dependents migrate by changing the+ dependency name and version bounds in `build-depends`, not their imports.+- GHC 9.12 or newer is required. Every component uses the `GHC2024` language+ edition with `DeriveAnyClass`, `DuplicateRecordFields`, `OverloadedLabels` and+ `OverloadedStrings` enabled, and every `deriving` clause names its strategy.+- librdkafka 2.15 or newer is required; building against an older header stops+ with `rdkafka-hs requires librdkafka 2.15 or newer`.+- `cpCallbackPollMode` is now `Maybe CallbackPollMode` (`Nothing` until+ `callbackPollMode` sets it); `effectiveCallbackPollMode` returns the mode a+ consumer uses. See the poll-mode fix below.+- `flushProducer` is implemented with `rd_kafka_flush` and still blocks until+ the outbound queue is empty.+- `closeConsumer` is idempotent: closing again, or after `destroyConsumer`,+ does nothing and returns `Nothing`.+- The unit test suite (`rdkafka-hs-test`) uses tasty instead of hspec. The+ integration test suite is now `rdkafka-hs-integration`, behind the manual+ `integration` flag (formerly `it`).++### Added++- From unreleased upstream `main`: admin API topic creation and deletion,+ `Kafka.Topic` and `Kafka.Topic.Types`.+- `Kafka.Consumer.consumerFatalError` returns the fatal error raised on a+ consumer, if any, with librdkafka's description.+- `Kafka.Consumer.setConsumerQueueIOEvent` asks librdkafka to write to a+ non-blocking file descriptor when records or events reach the queue+ `pollMessage` reads, in both callback poll modes, so applications can wait+ with `threadWaitRead` instead of polling on a timer (improvement request+ IR-1). `Kafka.Internal.RdKafka` binds `rd_kafka_queue_io_event_enable`,+ `rd_kafka_queue_cb_event_enable` and `rd_kafka_queue_get_consumer`.+- For bounded, read-only observers (improvement request IR-2):+ - `Kafka.Consumer.newAssignedConsumer` creates a consumer that never+ subscribes and so never joins its group; it reads only the partitions+ given to `assign`.+ - `Kafka.Consumer.pollMessageAttributed` and+ `Kafka.Consumer.Types.ConsumerMessageError` report the topic, partition and+ offset of an errored message, such as a partition EOF.+ - `Kafka.Consumer.destroyConsumer` destroys the librdkafka client+ synchronously and exactly once, closing its broker connections before it+ returns.+- `Kafka.Producer.flushProducerTimeout` (`rd_kafka_flush`) waits a bounded time+ for the outbound queue to drain, and `Kafka.Producer.purgeProducer`+ (`rd_kafka_purge`, with `PurgeFlag`) purges queued or in-flight messages,+ reporting each to the delivery callback with `RdKafkaRespErrPurgeQueue` or+ `RdKafkaRespErrPurgeInflight`.+- `Kafka.Consumer.assignmentLost` (`rd_kafka_assignment_lost`) and+ `Kafka.Consumer.consumerClosed` (`rd_kafka_consumer_closed`).+- `setSaslCredentials` in `Kafka.Consumer` and `Kafka.Producer`+ (`rd_kafka_sasl_set_credentials`) replaces a client's SASL credentials.+- `Kafka.Version` reports the linked librdkafka version (`librdkafkaVersion`,+ `librdkafkaVersionNumber`, `librdkafkaVersionParts`).+- `docs/bindings.md` inventories which of librdkafka's exported functions are+ bound, checked by `just bindings-check`.+- The integration suite runs against a project-local Redpanda broker on Apple+ Container (`just test-it`), selected by `RDKAFKA_TEST_BROKER` (default+ `127.0.0.1:39092`), and refuses the machine-global broker on port 9092. It+ includes a regression test that fences a static group member in both callback+ poll modes and checks the in-band fatal error and its cause.++### Fixed++- A raised consumer fatal error is reported in-band: `pollMessage`,+ `pollMessageBatch` and `pollMessageAttributed` return+ `KafkaResponseError RdKafkaRespErrFatal` in both callback poll modes, on every+ call, instead of the error being unobservable in `CallbackPollModeAsync`.+- The background callback-poll loop destroys the messages it consumes instead+ of leaking them.+- In `CallbackPollModeAsync`, records from partitions assigned with `assign`+ are delivered to `pollMessage`, including after reassignment; previously the+ background callback-poll loop drained and discarded them.+- Composing `ConsumerProperties` no longer resets the callback poll mode:+ every builder used to carry the default `CallbackPollModeAsync` and the+ semigroup took the right operand's mode, so+ `callbackPollMode CallbackPollModeSync <> groupId g` silently produced an+ async consumer. A mode now changes only when `callbackPollMode` sets it.+- `closeConsumer` no longer leaves a released message queue reachable, and+ polling destroys each message exactly once even if conversion fails.+- From unreleased upstream `main`: `storeOffsets` and `storeOffsetMessage` free+ the native partition list they allocate, and subscribing to an empty topic+ set no longer calls `rd_kafka_subscribe`.++### Removed++- The niv-based Nix files (`default.nix`, `shell.nix`, `nix/sources.*`),+ `docker-compose.yml`, the GitHub Actions workflow, `Setup.hs` and the+ `build/` and `scripts/` helpers of hw-kafka-client; the seihou-managed flake+ replaces them.+- The `it` Cabal flag (renamed `integration`) and the hspec test suites.
+ LICENSE view
@@ -0,0 +1,21 @@+Copyright (c) 2016 Alexey Raga+Copyright (c) 2026 Nadeem Bitar++Permission is hereby granted, free of charge, to any person obtaining+a copy of this software and associated documentation files (the+"Software"), to deal in the Software without restriction, including+without limitation the rights to use, copy, modify, merge, publish,+distribute, sublicense, and/or sell copies of the Software, and to+permit persons to whom the Software is furnished to do so, subject to+the following conditions:++The above copyright notice and this permission notice shall be included+in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ README.md view
@@ -0,0 +1,532 @@+# rdkafka-hs++Kafka bindings for Haskell backed by+[librdkafka](https://github.com/confluentinc/librdkafka), the C client for+Apache Kafka.++rdkafka-hs is the maintained successor of+[hw-kafka-client](https://github.com/haskell-works/hw-kafka-client), whose last+Hackage release, 5.3.0, dates from 2023. It contains the full upstream history,+the upstream commits that were never released, and fixes dependents needed,+most importantly that a consumer fatal error is reported from every poll+instead of being silently swallowed in the default callback poll mode. See+[CHANGELOG.md](CHANGELOG.md) for everything that differs from hw-kafka-client+5.3.0.++## Installation++rdkafka-hs is not on Hackage; depend on a release tag. In `cabal.project`:++```cabal+source-repository-package+ type: git+ location: https://github.com/shinzui/rdkafka-hs.git+ tag: v1.1.0.0+```++and in each component's `build-depends`:++```cabal+build-depends: rdkafka-hs >=1.1 && <1.2+```++The modules are `Kafka.Consumer`, `Kafka.Producer`, `Kafka.Metadata`,+`Kafka.Topic`, `Kafka.Transaction` and `Kafka.Version`.++## Migrating from hw-kafka-client++Replace any `hw-kafka-client` pin in `cabal.project` with the stanza above.+Then, in every component that depends on it (libraries, executables, test+suites and benchmarks), replace the dependency and its bounds; keeping+`>=5.3 && <6` would exclude rdkafka-hs's restarted version line:++```diff+- hw-kafka-client >=5.3 && <6,++ rdkafka-hs >=1.1 && <1.2,+```++Imports do not change: the `Kafka.*` module namespace, type names and record+field names are the same. GHC 9.12 and librdkafka 2.15 are required (see+Requirements). Behaviour worth knowing when you switch:++- A consumer fatal error (for example a static group member fenced by another+ consumer with the same `group.instance.id`) is now reported by every poll as+ `Left (KafkaResponseError RdKafkaRespErrFatal)`, in both callback poll modes;+ `consumerFatalError` returns the cause. In `CallbackPollModeAsync` it used to+ be unobservable. A fatal consumer must be recreated.+- `callbackPollMode` is no longer reset by properties composed after it, so a+ consumer configured as `callbackPollMode CallbackPollModeSync <> groupId g`+ is now actually synchronous; under hw-kafka-client it ran in async mode. Code+ that reads `cpCallbackPollMode` gets a `Maybe`; use+ `effectiveCallbackPollMode`.+- `flushProducer` uses `rd_kafka_flush`; it still blocks until the queue is+ empty. `flushProducerTimeout` bounds the wait.+- In `CallbackPollModeAsync`, partitions given to `assign` now deliver their+ records to `pollMessage`.+- `closeConsumer` leaves the group gracefully but never frees the client,+ which waits for its garbage-collector finalizer; it can block against an+ unresponsive broker. `destroyConsumer` frees the client immediately, within a+ bound. Close first if you need a graceful departure.++## Requirements++- GHC 9.12 or newer.+- librdkafka 2.15 or newer, with its headers. The build stops with+ `rdkafka-hs requires librdkafka 2.15 or newer` on an older header.+ `Kafka.Version.librdkafkaVersion` reports the library a program is actually+ linked against.+- [c2hs](https://hackage.haskell.org/package/c2hs), used to generate the FFI+ bindings at build time. Cabal builds it automatically through+ `build-tool-depends`.++## Consumer++A high-level consumer joins a consumer group and has partitions assigned to it+by the group; when consumers join or leave, the group rebalances the+partitions among them. A working example is in+[ConsumerExample.hs](example/ConsumerExample.hs). The examples connect to a+broker at `localhost:9092`; build and run them with:++```bash+cabal run kafka-client-example -f examples+```++To select a broker, topic and consumer group, pass all three arguments. The+program reads three input lines, produces four records and then consumes them:++```bash+cabal run kafka-client-example -f examples -- 127.0.0.1:39092 my-example-topic my-example-group+```++```haskell+import Control.Exception (bracket)+import Control.Monad (replicateM_)+import Kafka.Consumer++-- Global consumer properties+consumerProps :: ConsumerProperties+consumerProps = brokersList ["localhost:9092"]+ <> groupId "consumer_example_group"+ <> noAutoCommit+ <> logLevel KafkaLogInfo++-- Subscription to topics+consumerSub :: Subscription+consumerSub = topics ["kafka-client-example-topic"]+ <> offsetReset Earliest++-- Running an example+runConsumerExample :: IO ()+runConsumerExample = do+ res <- bracket mkConsumer clConsumer runHandler+ print res+ where+ mkConsumer = newConsumer consumerProps consumerSub+ clConsumer (Left err) = return (Left err)+ clConsumer (Right kc) = maybe (Right ()) Left <$> closeConsumer kc+ runHandler (Left err) = return (Left err)+ runHandler (Right kc) = processMessages kc++-------------------------------------------------------------------+processMessages :: KafkaConsumer -> IO (Either KafkaError ())+processMessages kafka = do+ replicateM_ 10 $ do+ msg <- pollMessage kafka (Timeout 1000)+ putStrLn $ "Message: " <> show msg+ err <- commitAllOffsets OffsetCommit kafka+ putStrLn $ "Offsets: " <> maybe "Committed." show err+ return $ Right ()+```++Consumer topic names and metadata group queries reject embedded NUL. Partition+IDs outside the native C integer range return `KafkaBadSpecification` through+the operation’s existing error result before changing state. Other invalid+inputs retain librdkafka’s validation and error conventions.++The examples in the sections below assume `import Kafka.Consumer` (or+`import Kafka.Producer`) and the `LambdaCase` and `OverloadedStrings`+extensions.++### Callback poll modes++The default async mode requires an executable linked with `-threaded`.+Without it, consumer construction returns `KafkaBadSpecification`; select+`callbackPollMode CallbackPollModeSync` to use a nonthreaded executable.++librdkafka reports rebalances, offset commits, errors, logs and statistics+through callbacks, which run only while something polls the client. A consumer+has one of two callback poll modes, set with `callbackPollMode`:++- `CallbackPollModeAsync` (the default): a background thread polls every+ 100 ms to serve callbacks, and records are redirected to a separate queue+ that `pollMessage` reads. Callbacks keep running while the application is+ busy, so librdkafka's `max.poll.interval.ms` cannot detect an application+ that has stopped polling.+- `CallbackPollModeSync`: callbacks run inside the application's own+ `pollMessage` calls, and nothing runs between them. `pollMessageBatch` is not+ available in this mode.++```haskell+syncProps :: ConsumerProperties+syncProps = brokersList ["localhost:9092"]+ <> groupId "my-group"+ <> callbackPollMode CallbackPollModeSync+```++### Fatal errors++Some errors are permanent: once librdkafka raises a fatal error on a consumer,+it stops all group activity, and the only remedy is a new consumer. Every poll+then returns `Left (KafkaResponseError RdKafkaRespErrFatal)`, in both poll modes,+and `consumerFatalError` returns the underlying cause:++```haskell+consumeLoop :: KafkaConsumer -> IO ()+consumeLoop consumer =+ pollMessage consumer (Timeout 1000) >>= \case+ Right record -> print (crValue record) >> consumeLoop consumer+ Left (KafkaResponseError RdKafkaRespErrTimedOut) -> consumeLoop consumer+ Left (KafkaResponseError RdKafkaRespErrFatal) -> do+ cause <- consumerFatalError consumer+ putStrLn ("consumer is permanently broken: " <> show cause)+ -- close or destroy it, then create a new consumer+ Left err -> print err >> consumeLoop consumer+```++### Waiting for records without polling++`setConsumerQueueIOEvent` makes librdkafka write a payload to a non-blocking+file descriptor when records or events reach the queue `pollMessage` reads, so+an application can wait with `threadWaitRead` instead of polling on a timer.+The notification is edge-triggered: one wake-up can stand for several records,+or for an event that is not a record. Discard pending wake-ups, poll the queue+empty, then wait, and bound the wait so a fatal error is still noticed:++```haskell+import Control.Concurrent (threadWaitRead)+import Control.Exception (bracket, try)+import Control.Monad (when)+import Data.ByteString (ByteString)+import Foreign.Marshal.Alloc (allocaBytes)+import System.Posix.IO (FdOption (..), closeFd, createPipe, fdReadBuf, setFdOption)+import System.Posix.Types (ByteCount, Fd)+import System.Timeout (timeout)++-- | Handle records as librdkafka announces them, waking at least once a second.+-- Returns when the consumer turns fatal.+waitAndConsume :: KafkaConsumer -> (ConsumerRecord (Maybe ByteString) (Maybe ByteString) -> IO ()) -> IO ()+waitAndConsume consumer handle =+ bracket createPipe release $ \(readEnd, writeEnd) -> do+ -- NonBlockingRead sets O_NONBLOCK, which librdkafka's writes need too.+ setFdOption readEnd NonBlockingRead True+ setFdOption writeEnd NonBlockingRead True+ setConsumerQueueIOEvent consumer (Just (writeEnd, "1"))+ let drain =+ pollMessage consumer (Timeout 0) >>= \case+ Right record -> handle record >> drain+ Left (KafkaResponseError RdKafkaRespErrTimedOut) -> pure True -- queue empty+ Left (KafkaResponseError RdKafkaRespErrFatal) -> pure False+ Left _ -> drain -- a non-record event+ loop = do+ discardWakeups readEnd -- before draining, so no wake-up is lost+ alive <- drain+ when alive $ do+ _ <- timeout 1000000 (threadWaitRead readEnd)+ loop+ loop+ where+ release (readEnd, writeEnd) = do+ setConsumerQueueIOEvent consumer Nothing -- before closing the descriptor+ closeFd readEnd+ closeFd writeEnd++discardWakeups :: Fd -> IO ()+discardWakeups fd =+ allocaBytes 64 $ \buf ->+ (try (fdReadBuf fd buf 64) :: IO (Either IOError ByteCount)) >>= \case+ Right n | n > 0 -> discardWakeups fd+ _ -> pure ()+```++### Reading partitions without joining a group++`newAssignedConsumer` creates a consumer that never subscribes, so it never+joins its consumer group: it reads only the partitions given to `assign`, from+the offsets given there. With `enable.partition.eof` set, librdkafka reports when+a partition's end is reached, and `pollMessageAttributed` says which partition+and offset each such error belongs to. Together they make a read-only scanner:++```haskell+-- | Print partition 0 of "events" from its first offset to its current end.+scanPartition :: IO ()+scanPartition =+ bracket (newAssignedConsumer props) (either (const (pure ())) destroyConsumer) $ \case+ Left err -> print err+ Right consumer -> do+ _ <- assign consumer [TopicPartition "events" (PartitionId 0) PartitionOffsetBeginning]+ let loop =+ pollMessageAttributed consumer (Timeout 1000) >>= \case+ Right record -> print (crOffset record, crValue record) >> loop+ Left ConsumerMessageError {cmeError = KafkaResponseError RdKafkaRespErrPartitionEof, cmeOffset} ->+ putStrLn ("reached the end at " <> show cmeOffset)+ Left ConsumerMessageError {cmeError = KafkaResponseError RdKafkaRespErrTimedOut} -> loop+ Left err -> print err+ loop+ where+ props = brokersList ["localhost:9092"]+ <> groupId "events-observer" -- required by librdkafka; never joined+ <> noAutoCommit+ <> extraProp "enable.partition.eof" "true"+```++### Shutting down a consumer++`closeConsumer` is the graceful close: it leaves the consumer group (letting the+group rebalance at once) and commits offsets if auto-commit is enabled. It does+not free the librdkafka client, which otherwise waits for a garbage collection,+and it can block against an unresponsive broker. `destroyConsumer` stops the+consumer's threads and closes its broker connections before it returns; every+other operation on the consumer is invalid afterwards. Closing and destroying+are each safe to repeat.++```haskell+shutdownConsumer :: KafkaConsumer -> IO ()+shutdownConsumer consumer = do+ _ <- closeConsumer consumer -- leave the group; commits if auto-commit is on+ destroyConsumer consumer -- free the client and close its connections now+```++To bound shutdown when the broker may not answer, call only `destroyConsumer`;+the group then notices the departure when the consumer's session times out.++## Producer++The producer sends messages to any number of topics; the target topic is part+of each `ProducerRecord` given to `produceMessage`. A working example is in+[ProducerExample.hs](example/ProducerExample.hs).++```haskell+{-# LANGUAGE OverloadedStrings #-}+import Control.Exception (bracket)+import Control.Monad (forM_)+import Data.ByteString (ByteString)+import Kafka.Producer++-- Global producer properties+producerProps :: ProducerProperties+producerProps = brokersList ["localhost:9092"]+ <> logLevel KafkaLogDebug++-- Topic to send messages to+targetTopic :: TopicName+targetTopic = "kafka-client-example-topic"++-- Run an example+runProducerExample :: IO ()+runProducerExample =+ bracket mkProducer clProducer runHandler >>= print+ where+ mkProducer = newProducer producerProps+ clProducer (Left _) = return ()+ clProducer (Right prod) = closeProducer prod+ runHandler (Left err) = return $ Left err+ runHandler (Right prod) = sendMessages prod++sendMessages :: KafkaProducer -> IO (Either KafkaError ())+sendMessages prod = do+ err1 <- produceMessage prod (mkMessage Nothing (Just "test from producer") )+ forM_ err1 print++ err2 <- produceMessage prod (mkMessage (Just "key") (Just "test from producer (with key)"))+ forM_ err2 print++ return $ Right ()++mkMessage :: Maybe ByteString -> Maybe ByteString -> ProducerRecord+mkMessage k v = ProducerRecord+ { prTopic = targetTopic+ , prPartition = UnassignedPartition+ , prKey = k+ , prValue = v+ , prHeaders = mempty+ }+```++### Delivery reports++The producer keeps its own queue of outgoing messages. `produceMessage`+returning means the message is queued, not that it has reached Kafka. A message+that cannot be sent within `message.timeout.ms` (see librdkafka's+[configuration](https://github.com/confluentinc/librdkafka/blob/master/CONFIGURATION.md))+is dropped from the queue and reported as failed. `sendTimeout (Timeout 0)`+makes the timeout infinite, so messages are never dropped:++```haskell+producerProps :: ProducerProperties+producerProps = brokersList ["localhost:9092"]+ <> sendTimeout (Timeout 0) -- for librdkafka "0" means "infinite"+```++`deliveryCallback` receives a `DeliveryReport` for every message: delivered at an+offset, failed with an error, or an error librdkafka could not attach to a+message. Callbacks run while the producer is polled, for example by+`flushProducer`:++```haskell+producerProps :: ProducerProperties+producerProps = brokersList ["localhost:9092"]+ <> setCallback (deliveryCallback report)+ where+ report = \case+ DeliverySuccess record offset -> putStrLn ("delivered to " <> show (prTopic record) <> " at " <> show offset)+ DeliveryFailure _ err -> putStrLn ("not delivered: " <> show err)+ NoMessageError err -> putStrLn ("delivery error: " <> show err)+```++### Synchronous sending of messages++librdkafka has no synchronous produce call, but `produceMessage'` takes a+callback for the message's own delivery report, which an `MVar` turns into a+synchronous send:++```haskell+{-# LANGUAGE LambdaCase #-}+import Control.Concurrent.MVar (newEmptyMVar, putMVar, takeMVar)+import Control.Monad.IO.Class (MonadIO (liftIO))+import Kafka.Consumer (Offset)+import Kafka.Producer++sendMessageSync :: MonadIO m => KafkaProducer -> ProducerRecord -> m (Either KafkaError Offset)+sendMessageSync producer record = liftIO $ do+ var <- newEmptyMVar+ res <- produceMessage' producer record (putMVar var)+ case res of+ Left (ImmediateError err) -> pure (Left err)+ Right () -> do+ -- Flush so the delivery report is served rather than waited for forever.+ flushProducer producer+ takeMVar var >>= \case+ DeliverySuccess _ offset -> pure (Right offset)+ DeliveryFailure _ err -> pure (Left err)+ NoMessageError err -> pure (Left err)+```++`flushProducer` waits until the queue is empty, which against an unreachable+broker can take as long as `message.timeout.ms`.++### Bounded shutdown++`closeProducer` flushes the queue without a time limit. To bound shutdown, flush+with `flushProducerTimeout` and purge whatever is left; purged messages are+reported to the delivery callback as failed+(`RdKafkaRespErrPurgeQueue` or `RdKafkaRespErrPurgeInflight`):++```haskell+shutdownProducer :: KafkaProducer -> IO ()+shutdownProducer producer =+ flushProducerTimeout producer (Timeout 5000) >>= \case+ Nothing -> pure ()+ Just _ -> do+ _ <- purgeProducer producer [PurgeQueue, PurgeInFlight]+ _ <- flushProducerTimeout producer (Timeout 1000) -- serves the purged reports+ pure ()+```++## Development++The Nix flake provides GHC, HLS, cabal, c2hs and librdkafka. Enter the shell+with `nix develop` (or let direnv load it), then:++```bash+just build # cabal build all+just test # cabal test rdkafka-hs-test (unit tests, no broker)+just test-it # integration tests against the private broker (below)+just build-examples # build the example executable+just fmt # nix fmt: fourmolu, cabal-gild and nixpkgs-fmt+just check # sandboxed build and unit tests, formatting, docs and bindings checks+just docs-check # validate docs/adr and docs/improvement-requests+just bindings-check # verify docs/bindings.md against the binding module+```++`nix build` builds the package and runs its unit tests in the Nix sandbox.++[docs/bindings.md](docs/bindings.md) lists every function librdkafka's public+header exports and which of them this package binds. It is generated from the+header of the librdkafka release that pkg-config finds (cloned once into+`~/.cache/rdkafka-hs/`, or named by `RDKAFKA_SOURCE_HEADER`) and from+`src/Kafka/Internal/RdKafka.chs`; regenerate it with `just bindings-inventory`+after changing the bindings.++Design decisions are recorded in [docs/adr/](docs/adr/index.md).++## Integration tests++The current functional candidate passes 78 unit and 753 integration cases in both+normal and Haskell coverage runs on macOS 26.7/arm64, GHC 9.12.4,+librdkafka 2.15.0 and private Redpanda 26.2.1. Four additional runtime checks+run in an actual nonthreaded executable.++A clean source archive also builds the library, examples and suites on Ubuntu+24.04.5/aarch64 with GHC 9.14.1, librdkafka 2.16.0 and Apache Kafka 4.4.0.+That tuple passes 78 unit, four nonthreaded and 279 native-lifetime cases,+nine distributed leader/group/outage/transaction cases, and seventeen+SASL PLAIN/TLS/ACL/credential-reconnect cases. Linux diagnostics detect deliberate+invalid-access and native-header retention controls; complementary Darwin ASan+covers invalid access with leak detection disabled. These are named scenario+results, with diagnostic limits recorded in the+[compatibility matrix](docs/testing/compatibility-matrix.json).++Comprehensive qualification remains open: two producer exception-path coverage ticks and the final all-evidence/package gate+are tracked by the [follow-up plan](docs/masterplans/3-complete-deferred-coverage-and-compatibility-validation.md).+The [historical primary release record](docs/testing/primary-validation-evidence.json)+retains its own exact source and package results.++The integration suite `rdkafka-hs-integration` needs a running Kafka broker and+is disabled unless the manual `integration` flag is set, so `cabal build all`,+`cabal test` and `nix build` never need one.++The suite runs against a private Redpanda broker owned by this project. It never+uses the machine-wide broker at `127.0.0.1:9092`, and refuses to start if+`RDKAFKA_TEST_BROKER` names it, because the tests create and delete topics.++Requirements: an Apple Silicon Mac on macOS 26 or newer with+[Apple Container](https://github.com/apple/container) installed and its service+running (`container system start`).++```bash+just test-it # start the broker if needed, then run the suite+just redpanda-up # start the broker (idempotent)+just redpanda-status # exits non-zero unless the broker is serving+just redpanda-logs # tail the broker logs+just redpanda-down # stop the broker, keeping its data+just redpanda-purge # delete its containers, network and volume+```++Arguments after `just test-it` go to cabal; to run one group, for example:++```bash+just test-it --test-option=-p '--test-option=/queue event/'+```++`process-compose up` also starts the broker. The dev shell exports+`RDKAFKA_TEST_BROKER=127.0.0.1:39092` unless it is already set. Every topic and+consumer group a run creates carries a random per-run prefix, so runs do not+interfere with each other.++| Service | Host port | Container |+|------------------|-----------|----------------------|+| Kafka | 39092 | `rdkafka-hs-rp-0` |+| Admin API | 39644 | `rdkafka-hs-rp-0` |+| Schema Registry | 38081 | `rdkafka-hs-rp-0` |+| HTTP Proxy | 38082 | `rdkafka-hs-rp-0` |++The ports are the `redpanda.*-port` variables in `.seihou/manifest.json`,+rendered into `nix/redpanda.nix` by `seihou run nix-haskell-flake`; changing one+means changing it there, in `flake.module.nix` and in+`test-integration/Kafka/TestEnv.hs`.++## Credits++rdkafka-hs is a fork of [hw-kafka-client](https://github.com/haskell-works/hw-kafka-client)+by Alexey Raga and its contributors, which was itself inspired by+[Haskakafka](https://github.com/cosbynator/haskakafka).
+ docs/testing/authentication-evidence.json view
@@ -0,0 +1,428 @@+{+ "status": "Accepted 17 permanent security cases replayed on the exact current clean source archive; ephemeral secrets/processes/ACL data removed",+ "environment": {+ "os": "PRETTY_NAME=\"Ubuntu 24.04.5 LTS\"\nNAME=\"Ubuntu\"\nVERSION_ID=\"24.04\"\nVERSION=\"24.04.5 LTS (Noble Numbat)\"\nVERSION_CODENAME=noble\nID=ubuntu\nID_LIKE=debian\nHOME_URL=\"https://www.ubuntu.com/\"\nSUPPORT_URL=\"https://help.ubuntu.com/\"\nBUG_REPORT_URL=\"https://bugs.launchpad.net/ubuntu/\"\nPRIVACY_POLICY_URL=\"https://www.ubuntu.com/legal/terms-and-policies/privacy-policy\"\nUBUNTU_CODENAME=noble\nLOGO=ubuntu-logo",+ "kernel": "Linux 6.18.15",+ "architecture": "aarch64",+ "ghc": "9.14.1",+ "cabal": "3.16.1.0",+ "java": "openjdk 21.0.12.1 2026-08-18\nOpenJDK Runtime Environment (build 21.0.12.1+1-1-24.04.4-Ubuntu)\nOpenJDK 64-Bit Server VM (build 21.0.12.1+1-1-24.04.4-Ubuntu, mixed mode, sharing)",+ "native_version": "2.16.0",+ "broker_version": "Apache Kafka 4.4.0",+ "loaded_native_identity": {+ "observed": "(\"2.16.0\",34603263)",+ "path": "/opt/librdkafka-2.16.0/lib/librdkafka.so.1",+ "sha256": "e4ebf0b82581b51a86a0d861a90c07004b0b1fec67ab71e409b572594846154f"+ },+ "broker_topology": "run-owned one-node combined broker/controller; ephemeral SASL_SSL listener; verified localhost CA; ephemeral PLAIN users and ACLs"+ },+ "source": {+ "project": "mori://shinzui/rdkafka-hs",+ "candidate_fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "execution_fingerprint": "74c7156e6fee8653bcec844001fd8f95d703bcf4d8e978a857a9f8f3560b6b0a",+ "revision": "bfa4f2e plus captured source",+ "archive": {+ "path": "dist-compatibility/expanded-source9/candidate.tar.gz",+ "sha256": "a70e4839d24c5e5179ff9a8be48643951e185d604cd8ba3401587730279f3b22"+ },+ "root_file_inventory": {+ "path": "dist-compatibility/expanded-source9/root-functional-files.json",+ "sha256": "69506c90cfc124f3a175a664873f5d8b49aff62a7426265c56c3dd64fcc84c21"+ },+ "archive_file_inventory": {+ "path": "dist-compatibility/expanded-source9/phase9-functional-files.json",+ "sha256": "d0e5d59aa49833ecd1305410c839cbebdbbb418679cecc6de0c2548b142dca4b"+ },+ "archive_comparison": {+ "changed_files": [],+ "added_files": [],+ "omitted_development_files": [+ ".envrc",+ "cabal.project",+ "flake.lock",+ "flake.module.nix",+ "flake.nix",+ "justfile",+ "nix/haskell.nix",+ "nix/pre-commit.nix",+ "nix/redpanda.nix",+ "nix/treefmt.nix"+ ],+ "omitted_project_configuration": {+ "path": "cabal.project",+ "content": "packages: .\n",+ "replacement": "Cabal implicit single package in clean extraction; same package set, no solver/compiler constraints in omitted file"+ },+ "execution_fingerprint": "74c7156e6fee8653bcec844001fd8f95d703bcf4d8e978a857a9f8f3560b6b0a",+ "root_fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ "configuration_sha256": "c6c0771e7da58c35d40170db3ec18cdd2439997e223ef4c088ac3f4e793707f9"+ },+ "results": {+ "authentication_cases": 17,+ "primary_setter_cases": 7,+ "compiled_credential_mutations": 4,+ "mutation_control_cases": 7,+ "mutation_manifest": {+ "path": "dist-mutations/20261025T010428Z-credentials-39063-0/results.json",+ "sha256": "5aa5d6b7833f9f5c2405218e4cc90ba7f43a4cf5d656636932495ccf5b4fa795",+ "fingerprint": "3849c13e1816569ebea01785af4a0d074f2e5d891df13313d8016a340dd63f44"+ },+ "outcomes": [+ "Exact authenticated delivery, complete records and committed next offset in async/sync modes",+ "Exact AUTHENTICATION for wrong passwords and SSL for missing CA or hostname mismatch; producer delivery ultimately MSG_TIMED_OUT",+ "Topic ACL permits Describe but denies Read/Write, yielding exact TOPIC_AUTHORIZATION_FAILED",+ "Denied group FindCoordinator is audited by the broker and native synchronous commit returns WAIT_COORD; 6-second session limit",+ "Exact topic creation authorization error and allowed administration by ephemeral admin",+ "Invalid replacement is observed after owned broker restart, then corrected second identity performs its exclusive topic action; producer and both consumer modes",+ "NUL username/password rejected before native setter; real native errors destroyed once during ordinary return and pending acquisition/decoder cancellation"+ ],+ "tests": [+ "authentication-contract.verified TLS authenticated delivery and exact consume/commit in both modes",+ "authentication-contract.authenticated identity without topic ACL receives exact produce denial",+ "authentication-contract.invalid-password producer reports the exact connection failure and no delivery",+ "authentication-contract.untrusted-CA producer reports the exact connection failure and no delivery",+ "authentication-contract.hostname-mismatch producer reports the exact connection failure and no delivery",+ "authentication-contract.invalid-password async consumer reports the exact connection failure",+ "authentication-contract.invalid-password sync consumer reports the exact connection failure",+ "authentication-contract.untrusted-CA async consumer reports the exact connection failure",+ "authentication-contract.untrusted-CA sync consumer reports the exact connection failure",+ "authentication-contract.hostname-mismatch async consumer reports the exact connection failure",+ "authentication-contract.hostname-mismatch sync consumer reports the exact connection failure",+ "authentication-contract.async exact topic/group/admin authorization denials",+ "authentication-contract.sync exact topic/group/admin authorization denials",+ "authentication-contract.producer credential replacement authenticates a new identity after observed reconnect and recovers from invalid replacement",+ "authentication-contract.async consumer credential replacement authenticates after observed reconnect and recovers from invalid replacement",+ "authentication-contract.sync consumer credential replacement authenticates after observed reconnect and recovers from invalid replacement",+ "authentication-contract.interruption destroys owned secure processes, credentials, ACL state and private keys"+ ],+ "clean_archive_command": [+ "rdkafka-hs-integration",+ "--authentication-qualification"+ ],+ "seconds": 84.72,+ "command": [+ "/evidence/native-phase9-binary",+ "--authentication-qualification"+ ]+ },+ "cleanup": {+ "owned_java_processes_remaining": [],+ "fixtures": [+ {+ "root": "dist-compatibility/kafka-fixtures/owned-138157-0",+ "cleanup": "All owned process handles exited; owned broker data removed.",+ "security_cleanup": null,+ "broker_data_remaining": [],+ "secret_directory_remaining": false+ },+ {+ "root": "dist-compatibility/kafka-fixtures/owned-154935-0",+ "cleanup": "All owned process handles exited; owned broker data removed.",+ "security_cleanup": "Owned credential files and JAAS configurations removed; owned log files checked for ephemeral passwords.",+ "broker_data_remaining": [],+ "secret_directory_remaining": false+ },+ {+ "root": "dist-compatibility/kafka-fixtures/owned-154935-51",+ "cleanup": "All owned process handles exited; owned broker data removed.",+ "security_cleanup": "Owned credential files and JAAS configurations removed; owned log files checked for ephemeral passwords.",+ "broker_data_remaining": [],+ "secret_directory_remaining": false+ }+ ]+ },+ "mechanisms": {+ "PLAIN": "tested with TLS, ACLs and reconnect",+ "SCRAM-SHA-256/SCRAM-SHA-512": "No mechanism-specific support promise in README/public Haddock; property maps pass native configuration through. Not claimed tested by this checkpoint.",+ "GSSAPI/OAUTHBEARER": "No project implementation or support promise; outside the username/password setter qualification."+ },+ "artifacts": {+ "candidate-phase4.tar.gz": {+ "path": "dist-compatibility/owned-fixture-checkpoint/candidate-phase4.tar.gz",+ "sha256": "dc5c41a11cac52b49499d7a07e63c7a19c19e24526a34f620820c95bdf0806b8"+ },+ "security-current.tar": {+ "path": "dist-compatibility/owned-fixture-checkpoint/security-current.tar",+ "sha256": "486f90a0cb0933de71ed7d7747dc6017e69f96c46c66650c0b91c84060cfe26e"+ },+ "security-policy.tar": {+ "path": "dist-compatibility/owned-fixture-checkpoint/security-policy.tar",+ "sha256": "7765655f2b4783d5943c6aef86f62890bec26acfa88c7c8cba9857b7f21c1ed2"+ },+ "security-policy-build.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/security-policy-build.log",+ "sha256": "7d5b7edb43e7c5fec848613cafeedc33d85ba379a08a9631265393aca4aa72b0"+ },+ "security-policy.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/security-policy.log",+ "sha256": "86fcfd19ffe9f5cfa9b8f366e26d94fbe5c186d85828d7fc47ac395a6fa5e84a"+ },+ "security-policy-fingerprint.txt": {+ "path": "dist-compatibility/owned-fixture-checkpoint/security-policy-fingerprint.txt",+ "sha256": "d4f30d1f8ee1db854e25ee0dc24c26956db705fea5ccfce4e0e99dd576386f63"+ },+ "security-policy-source-hashes.txt": {+ "path": "dist-compatibility/owned-fixture-checkpoint/security-policy-source-hashes.txt",+ "sha256": "af512a813cda384c18aa94a6d04aa82d3642ae7c4435f1bc2df04b3f57fd67ba"+ },+ "security-policy-cleanup.txt": {+ "path": "dist-compatibility/owned-fixture-checkpoint/security-policy-cleanup.txt",+ "sha256": "c61ecc0ace7c1ea9b3c58333a7fe9d871fea828c3f79de0b4ef8c901e585976d"+ },+ "security-policy-process-cleanup.txt": {+ "path": "dist-compatibility/owned-fixture-checkpoint/security-policy-process-cleanup.txt",+ "sha256": "72dfa2a664784e9e0959c0c8b820ea8ccfb2bda33afb6e606f5d2bbabe666157"+ },+ "security-policy-ldd.txt": {+ "path": "dist-compatibility/owned-fixture-checkpoint/security-policy-ldd.txt",+ "sha256": "b9f2442e48a14f37fb7c0038f1bcdff5db7de01aaa27e6d92145c24dac7e1f36"+ },+ "broker-policy.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/broker-policy.log",+ "sha256": "bf13d5b8e73c44c17788214b953afcc4e21d17dc06724011ce2885077f92d7b1"+ },+ "permanent-broker.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/permanent-broker.log",+ "sha256": "e1c106d4035053ed8469d832a752cc5a1f492870598064e56f4b8dcb495ba3c4"+ },+ "permanent-auth.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/permanent-auth.log",+ "sha256": "36d380e36186348986ff3f93d235fea5882d2dc993e50686ee44e45eadaf1e1d"+ },+ "RtsBaseline.hs": {+ "path": "dist-compatibility/owned-fixture-checkpoint/RtsBaseline.hs",+ "sha256": "667b93357c3b851e3b4944dc2d8400540580440be59d5b75e9e6a12eb546e585"+ },+ "rts-baseline.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/rts-baseline.log",+ "sha256": "b853dc070bcd72d34eba8d220959b39b619086318aed79a6f890fdbb870326b9"+ },+ "rts-baseline-suppressed.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/rts-baseline-suppressed.log",+ "sha256": "7a20a2b619bce7ac929f70b7db4225cc3013298d3a0651511ba6397552cbf4a5"+ },+ "ghc914-IOManager.c": {+ "path": "dist-compatibility/owned-fixture-checkpoint/ghc914-IOManager.c",+ "sha256": "75b19a43809b3155ba6265c6c4bc73fab86ddfed4d17312ce5422fe4227714dc"+ },+ "ghc914-rts.supp": {+ "path": "dist-compatibility/owned-fixture-checkpoint/ghc914-rts.supp",+ "sha256": "c9b04b1b79da557d62a4183c4108a636646feadb4f025ff4439ae026121e48f4"+ },+ "native-diagnostic-exports.diff": {+ "path": "dist-compatibility/owned-fixture-checkpoint/native-diagnostic-exports.diff",+ "sha256": "ff6312086bba73e0e6891060f48f02540b38174dbcbc26c080b12b8655bceafb"+ },+ "diagnostic-export-symbols.txt": {+ "path": "dist-compatibility/owned-fixture-checkpoint/diagnostic-export-symbols.txt",+ "sha256": "b959a9d7f9aab8245708a13d9d605c7e32b01930ecc91372f5d848094830f873"+ },+ "native-full.stdout": {+ "path": "dist-compatibility/owned-fixture-checkpoint/native-full.stdout",+ "sha256": "d9a93a21c5b34100767a43ea4eb4074330d3f80f9c9215a9731631d57cb2828d"+ },+ "native-phase4.stdout": {+ "path": "dist-compatibility/owned-fixture-checkpoint/native-phase4.stdout",+ "sha256": "03686ed592108efc49b895798d98c38183bda1ad68f4662396ff9a04cbb465d9"+ },+ "auth-variants-restart.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/auth-variants-restart.log",+ "sha256": "a80f767b754629d8d1bdfc85a53fa2069f46db5b823eca27239aac36e9225e87"+ },+ "security-current.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/security-current.log",+ "sha256": "bced9033bd01f585405853d666130fc890185995f77a9e9475ea874203ab1b91"+ },+ "security-describe.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/security-describe.log",+ "sha256": "3f0b2f8730d3adc5beaa336d5bc3b5361181dc9ccb22b2624bb58ab6a4d42893"+ },+ "sasl-before": {+ "path": "dist-compatibility/owned-fixture-checkpoint/sasl-before.log",+ "sha256": "53377a7555c0993829a5df8bf6fdcf8078477dab95c86d39bf80d1f30f305a42"+ },+ "sasl-acquire-before": {+ "path": "dist-compatibility/owned-fixture-checkpoint/sasl-acquire-before.log",+ "sha256": "4554a90b12ecd6373a23720e93fa513fffa17dd8418bc778c4864002cabefd32"+ },+ "sasl-after": {+ "path": "dist-compatibility/owned-fixture-checkpoint/sasl-after.log",+ "sha256": "79cbdc9f157beff14f68d77fa376d59d0b3d0579840670a1dea6eabcc0ed0055"+ },+ "candidate-phase5.tar.gz": {+ "path": "dist-compatibility/owned-fixture-checkpoint/candidate-phase5.tar.gz",+ "sha256": "07b996694a93bd7fd1a19d649a64c7456adc0522adc66b5d31919b232a5d7167"+ },+ "phase5-build.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/phase5-build.log",+ "sha256": "e2cb907393ef68a061bbd2bbb2406a369de8edf14678681b69f75042d4da1b4a"+ },+ "phase5-fingerprint.txt": {+ "path": "dist-compatibility/owned-fixture-checkpoint/phase5-fingerprint.txt",+ "sha256": "11f543eac0f314bd059eed35c4e325d0ab07d4aa131424287bc3ebadaefcf66e"+ },+ "phase5-fingerprint-files.json": {+ "path": "dist-compatibility/owned-fixture-checkpoint/phase5-fingerprint-files.json",+ "sha256": "479ad262d71dd40d6edfd9c1db3069744b8e26898f8d1f588d2db08cde38bda2"+ },+ "root-fingerprint-files.json": {+ "path": "dist-compatibility/owned-fixture-checkpoint/root-fingerprint-files.json",+ "sha256": "4e82164f2a0fa9c56a85c2372aaa78eb79185770a0fe22f7e94cdb8a8bda9821"+ },+ "phase5-normal-ldd.txt": {+ "path": "dist-compatibility/owned-fixture-checkpoint/phase5-normal-ldd.txt",+ "sha256": "ab1041dc9d2c9d876d269ca135985451af58aa02ac61b754d8f706a2363900c3"+ },+ "security-phase5.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/security-phase5.log",+ "sha256": "79d2d93b7ec51860ef21c0947fe4993f94a513c63e6cb84f6881b5bbea4c8810"+ },+ "security-phase5-tests.txt": {+ "path": "dist-compatibility/owned-fixture-checkpoint/security-phase5-tests.txt",+ "sha256": "e011f6a1ed4544904bc4117ebdd30e85339b33c096b3d0619bbff506f5e2e893"+ },+ "security-phase5-cleanup.txt": {+ "path": "dist-compatibility/owned-fixture-checkpoint/security-phase5-cleanup.txt",+ "sha256": "e5881de7257c9d5594697bdc4ad6628ca1c54b2ee1ddda0fa84b5b76a8f2b4b0"+ },+ "broker-phase5.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/broker-phase5.log",+ "sha256": "172c7b476e1e4868a75c17a54226fa1f4c2b57a3e05ce2bd7c58b15f746a4570"+ },+ "broker-phase5-tests.txt": {+ "path": "dist-compatibility/owned-fixture-checkpoint/broker-phase5-tests.txt",+ "sha256": "506f5bff1a6a34e7b328321480bb5cb7fc97cfee2ca1c7864dd270e0a37e50a4"+ }+ },+ "historical_incremental_source": {+ "execution": "sdist extraction plus explicit incremental overlays; final clean archive replay still required",+ "fingerprint": "35f44f61ae9c18f7e7e0e085f3258081e1d391fc2c934c9bf112a64ab0d8cf00",+ "root_current_fingerprint": "d8c7d0519912a75a841fe905d68d35f7a0f021d29b666c77cb169ff4ce2835af",+ "qualification_overlays": [+ "candidate-phase4.tar.gz",+ "security-current.tar",+ "security-policy.tar"+ ],+ "source_hashes": {+ "path": "dist-compatibility/owned-fixture-checkpoint/security-policy-source-hashes.txt",+ "sha256": "af512a813cda384c18aa94a6d04aa82d3642ae7c4435f1bc2df04b3f57fd67ba"+ }+ },+ "test_configuration": {+ "mode": "--authentication-qualification",+ "callback_modes": [+ "async",+ "sync"+ ],+ "SASL": "PLAIN",+ "security_protocol": "SASL_SSL",+ "TLS_hostname_verification": "https",+ "server_SAN": "DNS:localhost",+ "credentials": "ephemeral, local private files only",+ "authorization": "Separate original/replacement writer/reader ACLs; Describe-only denied identity; group denial audited at FindCoordinator; admin allow/deny",+ "cleanup": "Owned ProcessHandles stopped, broker state/JAAS/passwords/private keys removed, retained textual logs scanned for generated passwords"+ },+ "previous_accepted_checkpoint": {+ "source": {+ "candidate_fingerprint": "abbf4e69f7806356c083acb0bb163c3e24f1fc7b4b1b5d78d1f469b0653a8993",+ "execution_fingerprint": "2571e68979f3fd59c2b2e85c07c8e986787de49042d4b7645b59b17ea240cf49",+ "revision": "e29e2f7 plus captured uncommitted source",+ "archive": {+ "path": "dist-compatibility/owned-fixture-checkpoint/candidate-phase5.tar.gz",+ "sha256": "07b996694a93bd7fd1a19d649a64c7456adc0522adc66b5d31919b232a5d7167"+ },+ "root_file_inventory": {+ "path": "dist-compatibility/owned-fixture-checkpoint/root-fingerprint-files.json",+ "sha256": "4e82164f2a0fa9c56a85c2372aaa78eb79185770a0fe22f7e94cdb8a8bda9821"+ },+ "archive_file_inventory": {+ "path": "dist-compatibility/owned-fixture-checkpoint/phase5-fingerprint-files.json",+ "sha256": "479ad262d71dd40d6edfd9c1db3069744b8e26898f8d1f588d2db08cde38bda2"+ },+ "archive_comparison": {+ "changed_files": [],+ "added_files": [],+ "omitted_development_files": [+ ".envrc",+ "flake.lock",+ "flake.module.nix",+ "flake.nix",+ "justfile",+ "nix/haskell.nix",+ "nix/pre-commit.nix",+ "nix/redpanda.nix",+ "nix/treefmt.nix"+ ]+ },+ "configuration_sha256": "029db047ce9030f57c90485d05305cee35c9031f2651304434c226d586fcb653"+ },+ "results": {+ "authentication_cases": 17,+ "primary_setter_cases": 7,+ "compiled_credential_mutations": 4,+ "mutation_control_cases": 7,+ "mutation_manifest": {+ "path": "dist-mutations/20261025T010428Z-credentials-39063-0/results.json",+ "sha256": "5aa5d6b7833f9f5c2405218e4cc90ba7f43a4cf5d656636932495ccf5b4fa795",+ "fingerprint": "3849c13e1816569ebea01785af4a0d074f2e5d891df13313d8016a340dd63f44"+ },+ "outcomes": [+ "Exact authenticated delivery, complete records and committed next offset in async/sync modes",+ "Exact AUTHENTICATION for wrong passwords and SSL for missing CA or hostname mismatch; producer delivery ultimately MSG_TIMED_OUT",+ "Topic ACL permits Describe but denies Read/Write, yielding exact TOPIC_AUTHORIZATION_FAILED",+ "Denied group FindCoordinator is audited by the broker and native synchronous commit returns WAIT_COORD; 6-second session limit",+ "Exact topic creation authorization error and allowed administration by ephemeral admin",+ "Invalid replacement is observed after owned broker restart, then corrected second identity performs its exclusive topic action; producer and both consumer modes",+ "NUL username/password rejected before native setter; real native errors destroyed once during ordinary return and pending acquisition/decoder cancellation"+ ],+ "tests": [+ "authentication-contract.verified TLS authenticated delivery and exact consume/commit in both modes",+ "authentication-contract.authenticated identity without topic ACL receives exact produce denial",+ "authentication-contract.invalid-password producer reports the exact connection failure and no delivery",+ "authentication-contract.untrusted-CA producer reports the exact connection failure and no delivery",+ "authentication-contract.hostname-mismatch producer reports the exact connection failure and no delivery",+ "authentication-contract.invalid-password async consumer reports the exact connection failure",+ "authentication-contract.invalid-password sync consumer reports the exact connection failure",+ "authentication-contract.untrusted-CA async consumer reports the exact connection failure",+ "authentication-contract.untrusted-CA sync consumer reports the exact connection failure",+ "authentication-contract.hostname-mismatch async consumer reports the exact connection failure",+ "authentication-contract.hostname-mismatch sync consumer reports the exact connection failure",+ "authentication-contract.async exact topic/group/admin authorization denials",+ "authentication-contract.sync exact topic/group/admin authorization denials",+ "authentication-contract.producer credential replacement authenticates a new identity after observed reconnect and recovers from invalid replacement",+ "authentication-contract.async consumer credential replacement authenticates after observed reconnect and recovers from invalid replacement",+ "authentication-contract.sync consumer credential replacement authenticates after observed reconnect and recovers from invalid replacement",+ "authentication-contract.interruption destroys owned secure processes, credentials, ACL state and private keys"+ ],+ "clean_archive_command": [+ "rdkafka-hs-integration",+ "--authentication-qualification"+ ]+ },+ "cleanup": {+ "normal": "Owned Java exited, broker state and credential/JAAS files removed; retained textual logs checked against generated passwords",+ "interrupted_prototype": "Run-owned VM became unresponsive with concurrent diagnostic/distributed workloads. Only that VM was restarted; prototype secrets/data removed and retained logs sanitized. Interrupted scenarios are not accepted.",+ "remaining": [],+ "interruption": "The final case creates an independently owned authenticated secure fixture, cancels its active bracket, observes ThreadKilled, and asserts all owned process handles exited and secret/config/data directories were removed."+ }+ },+ "current_artifacts": {+ "authentication-final9.log": {+ "path": "dist-compatibility/expanded-source9/authentication-final9.log",+ "sha256": "a9cc23df591ca6608c613090bf42ae57ece89c1dc3e3ede7bbc0dee1cbcd2457"+ },+ "authentication-final9-tests.txt": {+ "path": "dist-compatibility/expanded-source9/authentication-final9-tests.txt",+ "sha256": "e011f6a1ed4544904bc4117ebdd30e85339b33c096b3d0619bbff506f5e2e893"+ },+ "configuration.json": {+ "path": "dist-compatibility/expanded-source9/configuration.json",+ "sha256": "c6c0771e7da58c35d40170db3ec18cdd2439997e223ef4c088ac3f4e793707f9"+ },+ "fixture-cleanup.json": {+ "path": "dist-compatibility/expanded-source9/fixture-cleanup.json",+ "sha256": "22a1434a32c0b23c77e8cb0f788c46ca45dc4129ff55add57033437db77be5aa"+ }+ }+}
+ docs/testing/authentication-qualification-context.json view
@@ -0,0 +1,101 @@+{+ "kind": "qualification-context",+ "mode": "--authentication-qualification",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "tests": [+ "authentication-contract.verified TLS authenticated delivery and exact consume/commit in both modes",+ "authentication-contract.authenticated identity without topic ACL receives exact produce denial",+ "authentication-contract.invalid-password producer reports the exact connection failure and no delivery",+ "authentication-contract.untrusted-CA producer reports the exact connection failure and no delivery",+ "authentication-contract.hostname-mismatch producer reports the exact connection failure and no delivery",+ "authentication-contract.invalid-password async consumer reports the exact connection failure",+ "authentication-contract.invalid-password sync consumer reports the exact connection failure",+ "authentication-contract.untrusted-CA async consumer reports the exact connection failure",+ "authentication-contract.untrusted-CA sync consumer reports the exact connection failure",+ "authentication-contract.hostname-mismatch async consumer reports the exact connection failure",+ "authentication-contract.hostname-mismatch sync consumer reports the exact connection failure",+ "authentication-contract.async exact topic/group/admin authorization denials",+ "authentication-contract.sync exact topic/group/admin authorization denials",+ "authentication-contract.producer credential replacement authenticates a new identity after observed reconnect and recovers from invalid replacement",+ "authentication-contract.async consumer credential replacement authenticates after observed reconnect and recovers from invalid replacement",+ "authentication-contract.sync consumer credential replacement authenticates after observed reconnect and recovers from invalid replacement",+ "authentication-contract.interruption destroys owned secure processes, credentials, ACL state and private keys"+ ],+ "passed": 17,+ "command": [+ "/evidence/native-phase9-binary",+ "--authentication-qualification"+ ],+ "environment": {+ "os": "PRETTY_NAME=\"Ubuntu 24.04.5 LTS\"\nNAME=\"Ubuntu\"\nVERSION_ID=\"24.04\"\nVERSION=\"24.04.5 LTS (Noble Numbat)\"\nVERSION_CODENAME=noble\nID=ubuntu\nID_LIKE=debian\nHOME_URL=\"https://www.ubuntu.com/\"\nSUPPORT_URL=\"https://help.ubuntu.com/\"\nBUG_REPORT_URL=\"https://bugs.launchpad.net/ubuntu/\"\nPRIVACY_POLICY_URL=\"https://www.ubuntu.com/legal/terms-and-policies/privacy-policy\"\nUBUNTU_CODENAME=noble\nLOGO=ubuntu-logo",+ "kernel": "Linux 6.18.15",+ "architecture": "aarch64",+ "ghc": "9.14.1",+ "cabal": "3.16.1.0",+ "java": "openjdk 21.0.12.1 2026-08-18\nOpenJDK Runtime Environment (build 21.0.12.1+1-1-24.04.4-Ubuntu)\nOpenJDK 64-Bit Server VM (build 21.0.12.1+1-1-24.04.4-Ubuntu, mixed mode, sharing)",+ "native_version": "2.16.0",+ "broker_version": "Apache Kafka 4.4.0",+ "loaded_native_identity": {+ "observed": "(\"2.16.0\",34603263)",+ "path": "/opt/librdkafka-2.16.0/lib/librdkafka.so.1",+ "sha256": "e4ebf0b82581b51a86a0d861a90c07004b0b1fec67ab71e409b572594846154f"+ },+ "broker_topology": "run-owned one-node combined broker/controller; ephemeral SASL_SSL listener; verified localhost CA; ephemeral PLAIN users and ACLs"+ },+ "source": {+ "project": "mori://shinzui/rdkafka-hs",+ "candidate_fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "execution_fingerprint": "74c7156e6fee8653bcec844001fd8f95d703bcf4d8e978a857a9f8f3560b6b0a",+ "revision": "bfa4f2e plus captured source",+ "archive": {+ "path": "dist-compatibility/expanded-source9/candidate.tar.gz",+ "sha256": "a70e4839d24c5e5179ff9a8be48643951e185d604cd8ba3401587730279f3b22"+ },+ "root_file_inventory": {+ "path": "dist-compatibility/expanded-source9/root-functional-files.json",+ "sha256": "69506c90cfc124f3a175a664873f5d8b49aff62a7426265c56c3dd64fcc84c21"+ },+ "archive_file_inventory": {+ "path": "dist-compatibility/expanded-source9/phase9-functional-files.json",+ "sha256": "d0e5d59aa49833ecd1305410c839cbebdbbb418679cecc6de0c2548b142dca4b"+ },+ "archive_comparison": {+ "changed_files": [],+ "added_files": [],+ "omitted_development_files": [+ ".envrc",+ "cabal.project",+ "flake.lock",+ "flake.module.nix",+ "flake.nix",+ "justfile",+ "nix/haskell.nix",+ "nix/pre-commit.nix",+ "nix/redpanda.nix",+ "nix/treefmt.nix"+ ],+ "omitted_project_configuration": {+ "path": "cabal.project",+ "content": "packages: .\n",+ "replacement": "Cabal implicit single package in clean extraction; same package set, no solver/compiler constraints in omitted file"+ },+ "execution_fingerprint": "74c7156e6fee8653bcec844001fd8f95d703bcf4d8e978a857a9f8f3560b6b0a",+ "root_fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ "configuration_sha256": "c6c0771e7da58c35d40170db3ec18cdd2439997e223ef4c088ac3f4e793707f9"+ },+ "listing": "dist-compatibility/expanded-source9/authentication-final9-tests.txt",+ "log": "dist-compatibility/expanded-source9/authentication-final9.log",+ "artifacts": {+ "dist-compatibility/expanded-source9/authentication-final9-tests.txt": "e011f6a1ed4544904bc4117ebdd30e85339b33c096b3d0619bbff506f5e2e893",+ "dist-compatibility/expanded-source9/authentication-final9.log": "a9cc23df591ca6608c613090bf42ae57ece89c1dc3e3ede7bbc0dee1cbcd2457",+ "dist-compatibility/expanded-source9/candidate.tar.gz": "a70e4839d24c5e5179ff9a8be48643951e185d604cd8ba3401587730279f3b22",+ "dist-compatibility/expanded-source9/root-functional-files.json": "69506c90cfc124f3a175a664873f5d8b49aff62a7426265c56c3dd64fcc84c21",+ "dist-compatibility/expanded-source9/phase9-functional-files.json": "d0e5d59aa49833ecd1305410c839cbebdbbb418679cecc6de0c2548b142dca4b",+ "dist-compatibility/expanded-source9/source-comparison.json": "635403f708e286d4461d40a3d86842d4c670ac70862a9688e2b5fbd72801ace5",+ "dist-compatibility/expanded-source9/configuration.json": "c6c0771e7da58c35d40170db3ec18cdd2439997e223ef4c088ac3f4e793707f9",+ "dist-compatibility/expanded-source9/fixture-cleanup.json": "22a1434a32c0b23c77e8cb0f788c46ca45dc4129ff55add57033437db77be5aa",+ "dist-compatibility/expanded-source9/phase9-loaded.log": "0ea352a045eddd425369467d19eef2c60d2ca235538e1335b9557897a003d120",+ "dist-compatibility/expanded-source9/phase9-version.log": "6ec9b644a82e1dd0a2ec1c57250b4e2d3043deb9a608d8384f7ec30026876a93"+ }+}
+ docs/testing/broker-failure-evidence.json view
@@ -0,0 +1,377 @@+{+ "status": "Accepted all nine permanent leader/group/outage/transaction/cancellation cases on the exact clean archive; Apache policy and inherited fencing/init evidence integrated",+ "source": {+ "candidate_archive": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/candidate.tar.gz",+ "sha256": "b02206dc4621d86226f15f6b8b88768e8e9e494b51cb13ec6746805ae1d367ba"+ },+ "library_fingerprint": "eb6352fe62c75ec289a0a5f543ed0692106d24f3370ddb46ef31f0188410b14a",+ "probe": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/LeaderProbe.hs",+ "sha256": "932cf2bec75d2ed20ed8193a8dd7a0ddc76a0240a79c6b002edd865b298388e9"+ }+ },+ "environment": {+ "os": "PRETTY_NAME=\"Ubuntu 24.04.5 LTS\"\nNAME=\"Ubuntu\"\nVERSION_ID=\"24.04\"\nVERSION=\"24.04.5 LTS (Noble Numbat)\"\nVERSION_CODENAME=noble\nID=ubuntu\nID_LIKE=debian\nHOME_URL=\"https://www.ubuntu.com/\"\nSUPPORT_URL=\"https://help.ubuntu.com/\"\nBUG_REPORT_URL=\"https://bugs.launchpad.net/ubuntu/\"\nPRIVACY_POLICY_URL=\"https://www.ubuntu.com/legal/terms-and-policies/privacy-policy\"\nUBUNTU_CODENAME=noble\nLOGO=ubuntu-logo\n",+ "kernel": "Linux 6.18.15 aarch64",+ "architecture": "aarch64",+ "ghc": "9.14.1",+ "cabal": "3.16.1.0",+ "loaded_libraries": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/loaded-libraries.log",+ "sha256": "1eadb3fce16b3a55fd4cc4a9a27eccefc277fd3e664fd3b76c75acccfa846e3a"+ },+ "native_binary": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/native-candidate.so.1",+ "sha256": "e4ebf0b82581b51a86a0d861a90c07004b0b1fec67ab71e409b572594846154f"+ },+ "native_version": "2.16.0",+ "loaded_native_identity": {+ "version": "2.16.0",+ "number": 34603263,+ "path": "/opt/librdkafka-2.16.0/lib/librdkafka.so.1",+ "sha256": "e4ebf0b82581b51a86a0d861a90c07004b0b1fec67ab71e409b572594846154f",+ "observed": "(\"2.16.0\",34603263)"+ },+ "broker_version": "Apache Kafka 4.4.0",+ "broker_topology": "Three owned combined broker/controllers, IDs 1/2/3 on loopback 41092/42092/43092; broker default min ISR 1 for single-replica inherited fixtures; failover topic replication 3 and min ISR 2"+ },+ "observations": {+ "callback_modes": [+ "async",+ "sync"+ ],+ "old_leader": 2,+ "new_leader": 3,+ "replication_factor": 3,+ "min_insync_replicas": 2,+ "observed_isr_after_failure": [+ 3,+ 1+ ],+ "exact_record_offsets": [+ 0,+ 1+ ],+ "exact_committed_next_offset": 2,+ "stopped_node": 2,+ "restoration": "Node 2 restarted and ISR returned to three before cleanup in each mode"+ },+ "artifacts": {+ "LeaderProbe.hs": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/LeaderProbe.hs",+ "sha256": "932cf2bec75d2ed20ed8193a8dd7a0ddc76a0240a79c6b002edd865b298388e9"+ },+ "leader-build.log": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/leader-build.log",+ "sha256": "e76e214025478ec384c464ceb3edb651bedd5f56d97836ecc6de6bd833117ed2"+ },+ "leader-probe.log": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/leader-probe.log",+ "sha256": "8f82f2c0f05e3d73b2c5040b3de68b060d25c8d18abdfc29d8b52677183c4cf7"+ },+ "restart-one.py": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/restart-one.py",+ "sha256": "88b578b3e71233c580474dfd890ebafc48a4ed412d76707faea03009a112db55"+ },+ "start-kafka.py": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/start-kafka.py",+ "sha256": "4e3bb507b55624513a7fdd72d10912e754c88620fc9a15e2011a58cb93fb69e8"+ },+ "kafka-start.log": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/kafka-start.log",+ "sha256": "e04defe1b1b98ad409439177368842c1c2c2767a44aebe68c77066fa6e4ad02d"+ }+ },+ "remaining": [],+ "permanent_m1": {+ "test_cases": 2,+ "source_fingerprint": "35f44f61ae9c18f7e7e0e085f3258081e1d391fc2c934c9bf112a64ab0d8cf00",+ "configuration": "Owned three-node Apache Kafka 4.4.0, RF3 topic and min ISR2; actual loaded librdkafka 2.16.0",+ "command": "rdkafka-hs-integration --broker-qualification",+ "observations": {+ "async_leader": [+ 1,+ 2+ ],+ "sync_leader": [+ 3,+ 1+ ],+ "records": [+ 0,+ 1+ ],+ "committed_next": 2,+ "ISR": "Exact [1,2,3] before stop, exact remaining two after election, exact [1,2,3] after owned node restart"+ },+ "log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/broker-policy.log",+ "sha256": "bf13d5b8e73c44c17788214b953afcc4e21d17dc06724011ce2885077f92d7b1"+ },+ "remaining": "Fresh full candidate replay and interruption acceptance are distinct from the passing M1 behaviors."+ },+ "distributed_checkpoint": {+ "tests": 8,+ "seconds": 337.27,+ "source_receipt": "dist-compatibility/expanded-recovery-checkpoint/distributed-phase6-receipt.json",+ "observations": {+ "leader": {+ "modes": [+ "async",+ "sync"+ ],+ "offsets": [+ 0,+ 1+ ],+ "committed_next": 2,+ "ISR": "three -> two -> three"+ },+ "group": {+ "protocols": [+ "eager",+ "cooperative"+ ],+ "modes": [+ "async",+ "sync"+ ],+ "transitions": [+ "split",+ "pause/seek",+ "handoff",+ "full outage",+ "loss-phase eviction",+ "reconnect"+ ],+ "assignmentLost_in_before_revoke": true,+ "outage_commit_all": "WaitCoord before eviction; NoOffset after unassignment",+ "producer": "queue-full overflow and accepted timeout, with neither record appearing after restore",+ "pre_outage_stored_next": 3,+ "pre_outage_committed_next": 2,+ "replay_offsets": [+ 2,+ 2+ ],+ "final_committed_next": [+ 4,+ 4+ ]+ },+ "transaction": {+ "modes": [+ "async",+ "sync"+ ],+ "offline_commit": "TimedOut; retriable=True, fatal=False, abort=False",+ "native_error_counts": [+ 1,+ 1+ ],+ "restored": "same transaction commit succeeds; read-committed publishes offset 0 exactly once"+ }+ },+ "artifacts": {+ "distributed-all6.log": {+ "path": "dist-compatibility/expanded-recovery-checkpoint/distributed-all6.log",+ "sha256": "65efc755a6a98f8bb143623f4e7668fe9f27986d49da5a42b49d79a182c9e627"+ },+ "distributed-phase6-receipt.json": {+ "path": "dist-compatibility/expanded-recovery-checkpoint/distributed-phase6-receipt.json",+ "sha256": "09f0fc485c48fbbeca7cc236eee6c7c0b490430ed1d5240b77097318d6e3823d"+ },+ "apache-policy6.log": {+ "path": "dist-compatibility/expanded-recovery-checkpoint/apache-policy6.log",+ "sha256": "15e7af9d13c2dacee1f8b8cecf7376899067f61975e3e60c0cae1fba96ab1753"+ }+ }+ },+ "accepted_current": {+ "source": {+ "project": "mori://shinzui/rdkafka-hs",+ "candidate_fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "execution_fingerprint": "74c7156e6fee8653bcec844001fd8f95d703bcf4d8e978a857a9f8f3560b6b0a",+ "revision": "bfa4f2e plus captured source",+ "archive": {+ "path": "dist-compatibility/expanded-source9/candidate.tar.gz",+ "sha256": "a70e4839d24c5e5179ff9a8be48643951e185d604cd8ba3401587730279f3b22"+ },+ "root_file_inventory": {+ "path": "dist-compatibility/expanded-source9/root-functional-files.json",+ "sha256": "69506c90cfc124f3a175a664873f5d8b49aff62a7426265c56c3dd64fcc84c21"+ },+ "archive_file_inventory": {+ "path": "dist-compatibility/expanded-source9/phase9-functional-files.json",+ "sha256": "d0e5d59aa49833ecd1305410c839cbebdbbb418679cecc6de0c2548b142dca4b"+ },+ "archive_comparison": {+ "changed_files": [],+ "added_files": [],+ "omitted_development_files": [+ ".envrc",+ "cabal.project",+ "flake.lock",+ "flake.module.nix",+ "flake.nix",+ "justfile",+ "nix/haskell.nix",+ "nix/pre-commit.nix",+ "nix/redpanda.nix",+ "nix/treefmt.nix"+ ],+ "omitted_project_configuration": {+ "path": "cabal.project",+ "content": "packages: .\n",+ "replacement": "Cabal implicit single package in clean extraction; same package set, no solver/compiler constraints in omitted file"+ },+ "execution_fingerprint": "74c7156e6fee8653bcec844001fd8f95d703bcf4d8e978a857a9f8f3560b6b0a",+ "root_fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ "configuration_sha256": "c6c0771e7da58c35d40170db3ec18cdd2439997e223ef4c088ac3f4e793707f9"+ },+ "environment": {+ "os": "PRETTY_NAME=\"Ubuntu 24.04.5 LTS\"\nNAME=\"Ubuntu\"\nVERSION_ID=\"24.04\"\nVERSION=\"24.04.5 LTS (Noble Numbat)\"\nVERSION_CODENAME=noble\nID=ubuntu\nID_LIKE=debian\nHOME_URL=\"https://www.ubuntu.com/\"\nSUPPORT_URL=\"https://help.ubuntu.com/\"\nBUG_REPORT_URL=\"https://bugs.launchpad.net/ubuntu/\"\nPRIVACY_POLICY_URL=\"https://www.ubuntu.com/legal/terms-and-policies/privacy-policy\"\nUBUNTU_CODENAME=noble\nLOGO=ubuntu-logo",+ "kernel": "Linux 6.18.15",+ "architecture": "aarch64",+ "ghc": "9.14.1",+ "cabal": "3.16.1.0",+ "java": "openjdk 21.0.12.1 2026-08-18\nOpenJDK Runtime Environment (build 21.0.12.1+1-1-24.04.4-Ubuntu)\nOpenJDK 64-Bit Server VM (build 21.0.12.1+1-1-24.04.4-Ubuntu, mixed mode, sharing)",+ "native_version": "2.16.0",+ "broker_version": "Apache Kafka 4.4.0",+ "loaded_native_identity": {+ "observed": "(\"2.16.0\",34603263)",+ "path": "/opt/librdkafka-2.16.0/lib/librdkafka.so.1",+ "sha256": "e4ebf0b82581b51a86a0d861a90c07004b0b1fec67ab71e409b572594846154f"+ },+ "broker_topology": "run-owned three-node combined broker/controllers; ephemeral loopback ports; RF3/min ISR2 fault topics"+ },+ "tests": [+ "broker-failure.async observed leader election preserves exact records and commits",+ "broker-failure.sync observed leader election preserves exact records and commits",+ "broker-failure.eager async handoff pause seek eviction and complete outage recover exact offsets",+ "broker-failure.eager sync handoff pause seek eviction and complete outage recover exact offsets",+ "broker-failure.cooperative async handoff pause seek eviction and complete outage recover exact offsets",+ "broker-failure.cooperative sync handoff pause seek eviction and complete outage recover exact offsets",+ "broker-failure.async transaction commit timeout across full outage retries and preserves read-committed visibility",+ "broker-failure.sync transaction commit timeout across full outage retries and preserves read-committed visibility",+ "broker-failure.cancellation during complete outage restores all owned brokers"+ ],+ "passed": 9,+ "seconds": 347.08,+ "command": [+ "/evidence/native-phase9-binary",+ "--broker-qualification"+ ],+ "native_transaction_integration": [+ "rdkafka-hs-integration.transaction-errors.transaction-error-leak-probe releases 300 immediate native errors",+ "rdkafka-hs-integration.transaction-errors.native allocation control detects the inherited three-error leak",+ "rdkafka-hs-integration.transaction-errors.initialization timeout destroys its native error on each retry",+ "rdkafka-hs-integration.transaction-errors.zero-timeout initialization resumes successfully against the broker",+ "rdkafka-hs-integration.transaction-errors.transaction state errors preserve empty commit and abort recovery",+ "rdkafka-hs-integration.transaction-errors.duplicate transactional IDs report a real fatal fencing error",+ "rdkafka-hs-integration.transaction-errors.broker-rejected delivery requires abort and permits a successful new transaction",+ "rdkafka-hs-integration.transaction-errors.init without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.begin without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.abort without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.commit without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.offset without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.init NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.begin NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.abort NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.commit NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.offset NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.init invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.begin invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.abort invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.commit invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.offset invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 0 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 1 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 2 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 3 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 4 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 5 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 6 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 7 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 0 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 1 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 2 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 3 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 4 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 5 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 6 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 7 before destruction",+ "rdkafka-hs-integration.transaction-errors.init cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.begin cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.abort cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 21 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 22 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 23 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 21 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 22 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 23 releases once",+ "rdkafka-hs-integration.transaction-errors.async commit publishes output and source next offset atomically; abort publishes neither",+ "rdkafka-hs-integration.transaction-errors.sync commit publishes output and source next offset atomically; abort publishes neither"+ ],+ "apache_configuration_policy": {+ "declared": "reject",+ "passed": 1,+ "command": [+ "/evidence/native-phase9-binary",+ "-p",+ "/unsupported configuration follows/"+ ],+ "artifact": {+ "path": "dist-compatibility/expanded-source9/apache-policy9.log",+ "sha256": "619f1dacc2a5c8f5e4fa510ce8d50ef9490183a6e2a9078da8c6a023eaecec7c"+ }+ },+ "cleanup": {+ "owned_java_processes_remaining": [],+ "fixtures": [+ {+ "root": "dist-compatibility/kafka-fixtures/owned-138157-0",+ "cleanup": "All owned process handles exited; owned broker data removed.",+ "security_cleanup": null,+ "broker_data_remaining": [],+ "secret_directory_remaining": false+ },+ {+ "root": "dist-compatibility/kafka-fixtures/owned-154935-0",+ "cleanup": "All owned process handles exited; owned broker data removed.",+ "security_cleanup": "Owned credential files and JAAS configurations removed; owned log files checked for ephemeral passwords.",+ "broker_data_remaining": [],+ "secret_directory_remaining": false+ },+ {+ "root": "dist-compatibility/kafka-fixtures/owned-154935-51",+ "cleanup": "All owned process handles exited; owned broker data removed.",+ "security_cleanup": "Owned credential files and JAAS configurations removed; owned log files checked for ephemeral passwords.",+ "broker_data_remaining": [],+ "secret_directory_remaining": false+ }+ ]+ },+ "artifacts": {+ "broker-final9.log": {+ "path": "dist-compatibility/expanded-source9/broker-final9.log",+ "sha256": "f9236628ae671ffa549c4c9ce17ba8ba1acaf5f69e066acfe4ebfe94bd303681"+ },+ "broker-final9-tests.txt": {+ "path": "dist-compatibility/expanded-source9/broker-final9-tests.txt",+ "sha256": "1b2270f302280d667a9a755787ee368fce03adc8f849ef070c54f02d99919b84"+ },+ "configuration.json": {+ "path": "dist-compatibility/expanded-source9/configuration.json",+ "sha256": "c6c0771e7da58c35d40170db3ec18cdd2439997e223ef4c088ac3f4e793707f9"+ },+ "fixture-cleanup.json": {+ "path": "dist-compatibility/expanded-source9/fixture-cleanup.json",+ "sha256": "22a1434a32c0b23c77e8cb0f788c46ca45dc4129ff55add57033437db77be5aa"+ }+ }+ }+}
+ docs/testing/broker-qualification-context.json view
@@ -0,0 +1,93 @@+{+ "kind": "qualification-context",+ "mode": "--broker-qualification",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "tests": [+ "broker-failure.async observed leader election preserves exact records and commits",+ "broker-failure.sync observed leader election preserves exact records and commits",+ "broker-failure.eager async handoff pause seek eviction and complete outage recover exact offsets",+ "broker-failure.eager sync handoff pause seek eviction and complete outage recover exact offsets",+ "broker-failure.cooperative async handoff pause seek eviction and complete outage recover exact offsets",+ "broker-failure.cooperative sync handoff pause seek eviction and complete outage recover exact offsets",+ "broker-failure.async transaction commit timeout across full outage retries and preserves read-committed visibility",+ "broker-failure.sync transaction commit timeout across full outage retries and preserves read-committed visibility",+ "broker-failure.cancellation during complete outage restores all owned brokers"+ ],+ "passed": 9,+ "command": [+ "/evidence/native-phase9-binary",+ "--broker-qualification"+ ],+ "environment": {+ "os": "PRETTY_NAME=\"Ubuntu 24.04.5 LTS\"\nNAME=\"Ubuntu\"\nVERSION_ID=\"24.04\"\nVERSION=\"24.04.5 LTS (Noble Numbat)\"\nVERSION_CODENAME=noble\nID=ubuntu\nID_LIKE=debian\nHOME_URL=\"https://www.ubuntu.com/\"\nSUPPORT_URL=\"https://help.ubuntu.com/\"\nBUG_REPORT_URL=\"https://bugs.launchpad.net/ubuntu/\"\nPRIVACY_POLICY_URL=\"https://www.ubuntu.com/legal/terms-and-policies/privacy-policy\"\nUBUNTU_CODENAME=noble\nLOGO=ubuntu-logo",+ "kernel": "Linux 6.18.15",+ "architecture": "aarch64",+ "ghc": "9.14.1",+ "cabal": "3.16.1.0",+ "java": "openjdk 21.0.12.1 2026-08-18\nOpenJDK Runtime Environment (build 21.0.12.1+1-1-24.04.4-Ubuntu)\nOpenJDK 64-Bit Server VM (build 21.0.12.1+1-1-24.04.4-Ubuntu, mixed mode, sharing)",+ "native_version": "2.16.0",+ "broker_version": "Apache Kafka 4.4.0",+ "loaded_native_identity": {+ "observed": "(\"2.16.0\",34603263)",+ "path": "/opt/librdkafka-2.16.0/lib/librdkafka.so.1",+ "sha256": "e4ebf0b82581b51a86a0d861a90c07004b0b1fec67ab71e409b572594846154f"+ },+ "broker_topology": "run-owned three-node combined broker/controllers; ephemeral loopback ports; RF3/min ISR2 fault topics"+ },+ "source": {+ "project": "mori://shinzui/rdkafka-hs",+ "candidate_fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "execution_fingerprint": "74c7156e6fee8653bcec844001fd8f95d703bcf4d8e978a857a9f8f3560b6b0a",+ "revision": "bfa4f2e plus captured source",+ "archive": {+ "path": "dist-compatibility/expanded-source9/candidate.tar.gz",+ "sha256": "a70e4839d24c5e5179ff9a8be48643951e185d604cd8ba3401587730279f3b22"+ },+ "root_file_inventory": {+ "path": "dist-compatibility/expanded-source9/root-functional-files.json",+ "sha256": "69506c90cfc124f3a175a664873f5d8b49aff62a7426265c56c3dd64fcc84c21"+ },+ "archive_file_inventory": {+ "path": "dist-compatibility/expanded-source9/phase9-functional-files.json",+ "sha256": "d0e5d59aa49833ecd1305410c839cbebdbbb418679cecc6de0c2548b142dca4b"+ },+ "archive_comparison": {+ "changed_files": [],+ "added_files": [],+ "omitted_development_files": [+ ".envrc",+ "cabal.project",+ "flake.lock",+ "flake.module.nix",+ "flake.nix",+ "justfile",+ "nix/haskell.nix",+ "nix/pre-commit.nix",+ "nix/redpanda.nix",+ "nix/treefmt.nix"+ ],+ "omitted_project_configuration": {+ "path": "cabal.project",+ "content": "packages: .\n",+ "replacement": "Cabal implicit single package in clean extraction; same package set, no solver/compiler constraints in omitted file"+ },+ "execution_fingerprint": "74c7156e6fee8653bcec844001fd8f95d703bcf4d8e978a857a9f8f3560b6b0a",+ "root_fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ "configuration_sha256": "c6c0771e7da58c35d40170db3ec18cdd2439997e223ef4c088ac3f4e793707f9"+ },+ "listing": "dist-compatibility/expanded-source9/broker-final9-tests.txt",+ "log": "dist-compatibility/expanded-source9/broker-final9.log",+ "artifacts": {+ "dist-compatibility/expanded-source9/broker-final9-tests.txt": "1b2270f302280d667a9a755787ee368fce03adc8f849ef070c54f02d99919b84",+ "dist-compatibility/expanded-source9/broker-final9.log": "f9236628ae671ffa549c4c9ce17ba8ba1acaf5f69e066acfe4ebfe94bd303681",+ "dist-compatibility/expanded-source9/candidate.tar.gz": "a70e4839d24c5e5179ff9a8be48643951e185d604cd8ba3401587730279f3b22",+ "dist-compatibility/expanded-source9/root-functional-files.json": "69506c90cfc124f3a175a664873f5d8b49aff62a7426265c56c3dd64fcc84c21",+ "dist-compatibility/expanded-source9/phase9-functional-files.json": "d0e5d59aa49833ecd1305410c839cbebdbbb418679cecc6de0c2548b142dca4b",+ "dist-compatibility/expanded-source9/source-comparison.json": "635403f708e286d4461d40a3d86842d4c670ac70862a9688e2b5fbd72801ace5",+ "dist-compatibility/expanded-source9/configuration.json": "c6c0771e7da58c35d40170db3ec18cdd2439997e223ef4c088ac3f4e793707f9",+ "dist-compatibility/expanded-source9/fixture-cleanup.json": "22a1434a32c0b23c77e8cb0f788c46ca45dc4129ff55add57033437db77be5aa",+ "dist-compatibility/expanded-source9/phase9-loaded.log": "0ea352a045eddd425369467d19eef2c60d2ca235538e1335b9557897a003d120",+ "dist-compatibility/expanded-source9/phase9-version.log": "6ec9b644a82e1dd0a2ec1c57250b4e2d3043deb9a608d8384f7ec30026876a93"+ }+}
+ docs/testing/callback-buffer-evidence.json view
@@ -0,0 +1,95 @@+{+ "status": "accepted manual sync callback polling checkpoint; EP-14 incomplete",+ "fingerprint": "acc3974e02bc5dfc6d23b9291a865133b52f8019dcae4783219e8763029a82de",+ "user_decision": "Preserve manual sync callback polling",+ "runs": {+ "normal-unit": {+ "log": "/tmp/rdkafka-ep14-buffer-unit-final.log",+ "sha256": "bc425907d26104c2a4995d0a1dd5c76391025e3be693af846f90780bfe29e10b",+ "passed": 78+ },+ "normal-integration": {+ "log": "/tmp/rdkafka-ep14-buffer-integration-final.log",+ "sha256": "17e770c6c241f30c4d566147d72a71e5556e3e90e408fdc78baa2f5ce9f28694",+ "passed": 560+ },+ "instrumented-haskell": {+ "manifest": "docs/testing/coverage-evidence.json",+ "unit": 78,+ "integration": 560,+ "nonthreaded_runtime": 4+ },+ "instrumented-native": {+ "log": "/tmp/rdkafka-ep14-buffer-asan-final.log",+ "sha256": "f40c7ecddff5e41c2e91a71a11b588a4768671de4230da19e0a0a28e9c382e54",+ "passed": 130+ }+ },+ "mutations": "dist-mutations/20261024T200227Z-buffer-65215-0/results.json",+ "compiled_mutations_caught": 8,+ "controls": 1,+ "retained_state_sensitivity": {+ "mutations": "dist-mutations/20261024T200733Z-state-78197-0/results.json",+ "compiled_mutations_caught": 4,+ "controls": 1,+ "reason": "Update the omitted-pause mutation anchor after sharing native pause/resume bookkeeping; preserve the four original state regressions."+ },+ "baseline": {+ "record_loss": {+ "log": "/tmp/rdkafka-ep14-consumer-extra-probe-accepted.log",+ "sha256": "fea8a66fe0aa0bffdc069aca92531a2e521b311a4db5b2711f3dd38e6614e0e1"+ },+ "record_loss_failures": 1,+ "record_loss_cases": 30,+ "prototype_state_failures": {+ "log": "/tmp/rdkafka-ep14-buffer-state-baseline.log",+ "sha256": "2b1cef3319f3851de6d82cc1ba92f67a95b27fcd09e681755220d40a017880a5"+ },+ "prototype_failed": 3,+ "prototype_cases": 6+ },+ "discarded_probes": [+ {+ "log": "/tmp/rdkafka-ep14-consumer-extra-probe.log",+ "reason": "An unsupported compound Tasty pattern selected zero tests; no behavioral acceptance. The accepted baseline selects the whole consumer-state group."+ },+ {+ "log": "/tmp/rdkafka-ep14-consumer-buffer-normal.log",+ "reason": "The private attributed-copy helper initially needed an explicit export; a compile failure is excluded."+ },+ {+ "log": "/tmp/rdkafka-ep14-buffer-fields-normal.log",+ "reason": "The test initially expected Either from produceMessage, whose result is Maybe; corrected before acceptance."+ },+ {+ "log": "/tmp/rdkafka-ep14-buffer-check.log",+ "reason": "Formatting failed; nix fmt corrected imports/layout before the accepted package checks."+ }+ ],+ "ownership": "Copy records/errors within the existing native-message bracket, release native messages before callback polling returns, and retain only Haskell-owned values. Clear copies on teardown, replace successful seek/assignment scopes, and defer paused partitions without blocking other partitions. Both modes install checked rebalance transitions; sync application polls continue serving ready callbacks while copies exist.",+ "scope": [+ "Exact FIFO, binary/empty/null fields, duplicate headers and three timestamp forms",+ "Attributed EOF and decoder errors, without queued idle timeouts",+ "Partial legacy seeks, replacement seeks, reassignment and unassignment",+ "Pause/resume with other partitions progressing and mixed native failures",+ "Native acquisition cancellation and immediate native-message destruction counters",+ "Real manual sync rebalance callbacks and exact record preservation in actual threaded/nonthreaded runtimes"+ ],+ "native_library": "mori://confluentinc/librdkafka",+ "native_version": "2.15.0",+ "native_diagnostic_control": "docs/testing/callback-native-diagnostics.json",+ "leak_instrumentation": false,+ "required_checks": {+ "log": "/tmp/rdkafka-ep14-buffer-check-final.log",+ "sha256": "07254125e7b02d850e95d0c77d096cefd2bec6f38e689348bd6c1421d6cd0fe3"+ },+ "tooling_controls": 22,+ "inventory": {+ "newly_reconciled": 7,+ "statuses": {+ "tested": 132,+ "unimplemented": 49+ }+ },+ "remaining": "Consumer commit/deprecated/example/input-boundary obligations, remaining metadata field checks, saved historical deprecated-seek diagnosis, remaining handwritten misses and EP-15 environments remain open."+}
+ docs/testing/callback-native-diagnostics.json view
@@ -0,0 +1,54 @@+{+ "status": "accepted native invalid-access diagnostic",+ "fingerprint": "b77c65366fab1dd8d2316d972086e89ca4dfc41ef52bc5987c5b0534ec80f9e9",+ "source_project": "mori://confluentinc/librdkafka",+ "native_tag": "v2.15.0",+ "native_revision": "9a94e11452cdeb0a844db44ee5dd01ccbe17d3ab",+ "compiler": "Apple clang version 21.0.0 (clang-2100.1.1.101)\nTarget: arm64-apple-darwin25.6.0\nThread model: posix\nInstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin",+ "flags": "-O1 -g -fsanitize=address -fno-omit-frame-pointer",+ "build_log": "/tmp/rdkafka-ep11-asan-apple-build-sdk.log",+ "runtime": "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/21/lib/darwin/libclang_rt.asan_osx_dynamic.dylib",+ "runtime_sha256": "fe1e17021123184ac0380808606a7cce00ad657158d2d4f62916970df1e8eaef",+ "native_library": "/tmp/rdkafka-hs-ep11-asan-install/lib/librdkafka.1.dylib",+ "native_library_sha256": "2fa8b4e5d5e623550305022c6dc881674ccf0c0fb43183e532c27d9faaa6e51f",+ "binary_sha256": "c235beb64b611128bce213b103b7527a12fc0d9c808924c6c0a6debcc9e5b26a",+ "environment": {+ "DYLD_LIBRARY_PATH": "/tmp/rdkafka-hs-ep11-asan-install/lib",+ "DYLD_INSERT_LIBRARIES": "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/21/lib/darwin/libclang_rt.asan_osx_dynamic.dylib",+ "ASAN_OPTIONS": "detect_leaks=0:abort_on_error=1:symbolize=1",+ "DYLD_PRINT_LIBRARIES": "1"+ },+ "cases": [+ {+ "kind": "negative",+ "command": [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-newstyle/build/aarch64-osx/ghc-9.12.4/rdkafka-hs-1.0.0.1/t/rdkafka-hs-integration/build/rdkafka-hs-integration/rdkafka-hs-integration",+ "--callback-lifetime-native-control"+ ],+ "exit": -6,+ "log": "/tmp/rdkafka-ep11-final-asan-negative.log",+ "log_sha256": "e46a5b479df34eae4333afaa6ed91f1479e5390e86fb27ea5fbdab30c396606e"+ },+ {+ "kind": "positive",+ "command": [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-newstyle/build/aarch64-osx/ghc-9.12.4/rdkafka-hs-1.0.0.1/t/rdkafka-hs-integration/build/rdkafka-hs-integration/rdkafka-hs-integration",+ "-p",+ "/callback-lifetime/",+ "+RTS",+ "-N2",+ "-RTS"+ ],+ "exit": 0,+ "log": "/tmp/rdkafka-ep11-final-asan-positive.log",+ "log_sha256": "084fb6e990ed6e670e8db2e97b078ba971235c5de72904ae4ed6f97863a313e6"+ }+ ],+ "scope": "55 callback lifetime cases, including all publicly installable persistent kinds, real shutdown callbacks, failed construction, GC, replacement, concurrent destruction, observed cancellation and throwing callbacks in both consumer modes. The explicit negative control frees a native configuration then calls its getter; the diagnostic reports the read in native code. Leak diagnosis and other compatibility tuples remain EP-15 obligations.",+ "discarded_attempts": [+ "/tmp/rdkafka-ep11-asan-control-attempt.log",+ "/tmp/rdkafka-ep11-asan-startup.sample",+ "/tmp/rdkafka-ep11-asan-apple-runtime.log"+ ],+ "runtime_note": "The Nix LLVM runtime stalled during pre-main initialization on macOS 26.7. Rebuilding with matching Apple clang/runtime and the actual Xcode SDK passed the same native control and positive group. No package pins changed."+}
+ docs/testing/callback-ownership-inventory.json view
@@ -0,0 +1,241 @@+{+ "schema_version": 1,+ "owner": 11,+ "status": "accepted",+ "allocations": [+ {+ "allocator": "mkRebalanceCallback",+ "setter": "rdKafkaConfSetRebalanceCb",+ "route": "rebalanceCallback",+ "publicly_installable": true,+ "owner": "Kafka.Internal.CallbackOwner.installCallback",+ "release": "releaseCallbackOwner after native client destruction"+ },+ {+ "allocator": "mkDeliveryCallback",+ "setter": "rdKafkaConfSetDrMsgCb",+ "route": "deliveryCallback and producer default",+ "publicly_installable": true,+ "owner": "Kafka.Internal.CallbackOwner.installCallback",+ "release": "releaseCallbackOwner after native client destruction"+ },+ {+ "allocator": "mkConsumeCallback",+ "setter": "rdKafkaConfSetConsumeCb",+ "route": "internal binding only",+ "publicly_installable": false,+ "owner": "Kafka.Internal.CallbackOwner.installCallback",+ "release": "releaseCallbackOwner after native client destruction",+ "rationale": "No call site reachable from an exposed module; the internal setter still requires an owner."+ },+ {+ "allocator": "mkOffsetCommitCallback",+ "setter": "rdKafkaConfSetOffsetCommitCb",+ "route": "offsetCommitCallback",+ "publicly_installable": true,+ "owner": "Kafka.Internal.CallbackOwner.installCallback",+ "release": "releaseCallbackOwner after native client destruction"+ },+ {+ "allocator": "mkErrorCallback",+ "setter": "rdKafkaConfSetErrorCb",+ "route": "errorCallback",+ "publicly_installable": true,+ "owner": "Kafka.Internal.CallbackOwner.installCallback",+ "release": "releaseCallbackOwner after native client destruction"+ },+ {+ "allocator": "mkThrottleCallback",+ "setter": "rdKafkaConfSetThrottleCb",+ "route": "internal binding only",+ "publicly_installable": false,+ "owner": "Kafka.Internal.CallbackOwner.installCallback",+ "release": "releaseCallbackOwner after native client destruction",+ "rationale": "No call site reachable from an exposed module; the internal setter still requires an owner."+ },+ {+ "allocator": "mkLogCallback",+ "setter": "rdKafkaConfSetLogCb",+ "route": "logCallback",+ "publicly_installable": true,+ "owner": "Kafka.Internal.CallbackOwner.installCallback",+ "release": "releaseCallbackOwner after native client destruction"+ },+ {+ "allocator": "mkStatsCallback",+ "setter": "rdKafkaConfSetStatsCb",+ "route": "statsCallback",+ "publicly_installable": true,+ "owner": "Kafka.Internal.CallbackOwner.installCallback",+ "release": "releaseCallbackOwner after native client destruction"+ },+ {+ "allocator": "mkSocketCallback",+ "setter": "rdKafkaConfSetSocketCb",+ "route": "internal binding only",+ "publicly_installable": false,+ "owner": "Kafka.Internal.CallbackOwner.installCallback",+ "release": "releaseCallbackOwner after native client destruction",+ "rationale": "No call site reachable from an exposed module; the internal setter still requires an owner."+ },+ {+ "allocator": "mkPartitionerCallback",+ "setter": "rdKafkaTopicConfSetPartitionerCb",+ "route": "internal binding only",+ "publicly_installable": false,+ "owner": "Kafka.Internal.CallbackOwner.installCallback",+ "release": "releaseCallbackOwner after native client destruction",+ "rationale": "No call site reachable from an exposed module; the internal setter still requires an owner."+ }+ ],+ "configurations": {+ "original": "ForeignPtr owns the native configuration; inspection view remains passive after client creation.",+ "duplicate": "Native client consumes it on success; wrapper destroys it on native creation failure.",+ "replacements": "All allocated bridges remain owned until final native teardown.",+ "borrowed_consumers": "Callback wrappers borrow native pointers and never acquire the native client deallocator."+ },+ "callback_capable_destruction": [+ {+ "kind": "client",+ "policy": "Haskell finalizer or safe scoped native call; public operations retain the client through child cleanup."+ },+ {+ "kind": "topic",+ "policy": "Haskell finalizer or safe scoped native call; public operations retain the client through child cleanup."+ },+ {+ "kind": "partition list with private partition references",+ "policy": "Haskell finalizer or safe scoped native call; public operations retain the client through child cleanup."+ },+ {+ "kind": "queue",+ "policy": "Haskell finalizer or safe scoped native call; public operations retain the client through child cleanup."+ },+ {+ "kind": "event",+ "policy": "Haskell finalizer or safe scoped native call; public operations retain the client through child cleanup."+ },+ {+ "kind": "message",+ "policy": "Haskell finalizer or safe scoped native call; public operations retain the client through child cleanup."+ }+ ],+ "remaining_c_finalizers": [+ {+ "kind": "global configuration",+ "policy": "Detached allocation/property cleanup; no library-installed Haskell callback invocation."+ },+ {+ "kind": "topic configuration",+ "policy": "Detached allocation/property cleanup; no library-installed Haskell callback invocation."+ },+ {+ "kind": "metadata snapshot",+ "policy": "Detached allocation/property cleanup; no library-installed Haskell callback invocation."+ },+ {+ "kind": "group list",+ "policy": "Detached allocation/property cleanup; no library-installed Haskell callback invocation."+ },+ {+ "kind": "admin options",+ "policy": "Detached allocation/property cleanup; no library-installed Haskell callback invocation."+ },+ {+ "kind": "new-topic request",+ "policy": "Detached allocation/property cleanup; no library-installed Haskell callback invocation."+ }+ ],+ "evidence": {+ "before": "/tmp/rdkafka-ep11-before-isolated.log",+ "native_cases": "/tmp/rdkafka-ep11-throwing-thread.log",+ "registry_cases": "/tmp/rdkafka-ep11-owner-unit4.log",+ "tooling_controls": "/tmp/rdkafka-ep11-final-tools.log",+ "native_case_count": 55,+ "registry_case_count": 8,+ "tooling_controls_count": 19,+ "fingerprint": "b77c65366fab1dd8d2316d972086e89ca4dfc41ef52bc5987c5b0534ec80f9e9",+ "normal": "/tmp/rdkafka-ep11-final-normal.log",+ "normal_counts": {+ "unit": 29,+ "integration": 375+ },+ "coverage": "docs/testing/coverage-evidence.json",+ "coverage_counts": {+ "unit": 29,+ "integration": 375+ },+ "normal_integration_seconds": 151.84,+ "instrumented_integration_seconds": 158.52,+ "mutations": "dist-mutations/20261024T135134Z-callback-6370-0/results.json",+ "native_diagnostics": "docs/testing/callback-native-diagnostics.json",+ "required_checks": "/tmp/rdkafka-ep11-final-check.log",+ "tests": [+ "rdkafka-hs.Callback owner.bridge allocation executes masked before ownership is recorded",+ "rdkafka-hs.Callback owner.installed and replaced bridges release exactly once",+ "rdkafka-hs.Callback owner.failed native install still owns its allocated bridge",+ "rdkafka-hs.Callback owner.failed allocation has no release",+ "rdkafka-hs.Callback owner.transfer preserves a callable bridge until client release",+ "rdkafka-hs.Callback owner.transferred and released owners reject reuse before allocating",+ "rdkafka-hs.Callback owner.release retry does not repeat completed releases",+ "rdkafka-hs.Callback owner.concurrent releases join before returning",+ "rdkafka-hs-integration.callback-lifetime.async throwing error callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing log callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing stats callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing rebalance callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing commit callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing error callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing log callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing stats callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing rebalance callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing commit callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async error callback releases after destroy with retained wrapper",+ "rdkafka-hs-integration.callback-lifetime.sync error callback releases after destroy with retained wrapper",+ "rdkafka-hs-integration.callback-lifetime.producer delivery callback releases after native finalization",+ "rdkafka-hs-integration.callback-lifetime.noncaptured control is collectible",+ "rdkafka-hs-integration.callback-lifetime.async log callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.async stats callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.sync log callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.sync stats callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.async construction failure releases callbacks: topic",+ "rdkafka-hs-integration.callback-lifetime.async construction failure releases callbacks: native",+ "rdkafka-hs-integration.callback-lifetime.sync construction failure releases callbacks: topic",+ "rdkafka-hs-integration.callback-lifetime.sync construction failure releases callbacks: native",+ "rdkafka-hs-integration.callback-lifetime.producer native construction failure releases callbacks",+ "rdkafka-hs-integration.callback-lifetime.async rebalance callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.async commit callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.sync rebalance callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.sync commit callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.replaced producer delivery callbacks both release",+ "rdkafka-hs-integration.callback-lifetime.async concurrent destruction joins at native entry",+ "rdkafka-hs-integration.callback-lifetime.async concurrent destruction joins at native completion",+ "rdkafka-hs-integration.callback-lifetime.async concurrent destruction joins at native shutdown callback",+ "rdkafka-hs-integration.callback-lifetime.sync concurrent destruction joins at native entry",+ "rdkafka-hs-integration.callback-lifetime.sync concurrent destruction joins at native completion",+ "rdkafka-hs-integration.callback-lifetime.sync concurrent destruction joins at native shutdown callback",+ "rdkafka-hs-integration.callback-lifetime.async cancellation at native entry preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.async cancellation at native completion preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.async cancellation at native shutdown callback preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation at native entry preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation at native completion preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation at native shutdown callback preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.async cancellation after poll stop and queue detachment preserves teardown",+ "rdkafka-hs-integration.callback-lifetime.producer constructor cancellation at partial registration releases its owner",+ "rdkafka-hs-integration.callback-lifetime.producer constructor cancellation at native acceptance releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-async constructor cancellation at partial registration releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-async constructor cancellation at native acceptance releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-sync constructor cancellation at partial registration releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-sync constructor cancellation at native acceptance releases its owner",+ "rdkafka-hs-integration.callback-lifetime.async cancellation while waiting for active callback permits retry",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation while waiting for active callback permits retry",+ "rdkafka-hs-integration.callback-lifetime.async closed consumer GC releases its registrations once",+ "rdkafka-hs-integration.callback-lifetime.sync closed consumer GC releases its registrations once",+ "rdkafka-hs-integration.callback-lifetime.producer error callback remains live through close and releases on GC",+ "rdkafka-hs-integration.callback-lifetime.producer log callback remains live through close and releases on GC",+ "rdkafka-hs-integration.callback-lifetime.producer stats callback remains live through close and releases on GC",+ "rdkafka-hs-integration.callback-lifetime.failed native construction releases the caller-owned duplicate config"+ ]+ },+ "remaining": [],+ "separate_obligations": "EP-15 still owns native leak diagnostics and remaining supported environment tuples. EP-14 owns the recorded batch-conversion interruption and cooperative-rebalance error-object defects; neither changes the persistent callback release boundary."+}
+ docs/testing/compatibility-matrix.json view
@@ -0,0 +1,2565 @@+{+ "schema_version": 1,+ "scope": "Historical primary release retained; exact current primary, Linux/newer, distributed and security scenarios accepted. Comprehensive qualification remains open.",+ "fingerprint": "060dade4e8a9c764dabee54df3030fa6d857be3ea1404a2bc680a45ddadd5e4e",+ "primary": [+ {+ "os": "macOS 26.7",+ "kernel": "Darwin 25.6.0",+ "architecture": "arm64",+ "ghc": "9.12.4",+ "cabal": "3.16.1.0",+ "native": "2.15.0",+ "loaded_native": "(\"2.15.0\",34537727)",+ "broker_versions": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "broker": "127.0.0.1:39092",+ "id": "darwin-arm64-ghc9124-native215-redpanda2621",+ "status": "passed",+ "evidence": "docs/testing/primary-validation-evidence.json"+ }+ ],+ "deferred": [+ {+ "id": "linux-native-diagnostics",+ "owner": 17,+ "status": "passed named expanded scenarios; final EP-20 integration remains open"+ },+ {+ "id": "newer-released-toolchain-native",+ "owner": 17,+ "status": "passed named expanded scenarios; final EP-20 integration remains open"+ },+ {+ "id": "apache-distributed-failure-group-transaction",+ "owner": 18,+ "status": "passed named expanded scenarios; final EP-20 integration remains open"+ },+ {+ "id": "sasl-tls-acl-credential-reconnect",+ "owner": 19,+ "status": "passed named expanded scenarios; final EP-20 integration remains open"+ },+ {+ "id": "strict-complete-inventory-matrix-package-gate",+ "owner": 20,+ "status": "deferred; not qualified"+ }+ ],+ "limits": [+ "No new environment claim follows from broad dependency bounds.",+ "No comprehensive native leak claim follows from Darwin ASan runs with leak detection disabled.",+ "Plaintext setter checks do not prove real authentication or credential replacement at a broker."+ ],+ "qualification": {+ "schema_version": 1,+ "status": "in-progress; EP-16 required source/cause work and EP-20 integration remain open",+ "candidate_fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "tuple_fields": [+ "id",+ "owner",+ "required",+ "status",+ "source",+ "environment",+ "test_configuration",+ "scenarios",+ "artifacts"+ ],+ "source_fields": [+ "candidate_fingerprint",+ "revision",+ "archive_sha256",+ "configuration_sha256"+ ],+ "environment_fields": [+ "os",+ "kernel",+ "architecture",+ "ghc",+ "cabal",+ "native_version",+ "loaded_native_identity",+ "broker_version",+ "broker_topology"+ ],+ "scenario_fields": [+ "id",+ "required",+ "status",+ "command",+ "tests",+ "passed",+ "artifacts",+ "limitations"+ ],+ "artifact_format": "Repository-relative path to immutable output and its SHA-256; credentials and private keys are never fields",+ "status_values": [+ "not-run",+ "in-progress",+ "passed",+ "failed",+ "unavailable"+ ],+ "acceptance": "Only passed required scenarios with nonzero expected test identities, actual loaded versions, matching source/configuration and verified artifact hashes qualify. Historical primary evidence retains its original source identity.",+ "tuples": [+ {+ "id": "darwin-arm64-ghc9124-native215-redpanda2621-current",+ "owner": 17,+ "required": true,+ "status": "passed",+ "source": {+ "candidate_fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "revision": "bfa4f2e plus captured source",+ "configuration": "Normal and HPC root builds; separate actual nonthreaded build"+ },+ "environment": {+ "os": "macOS 26.7",+ "kernel": "Darwin 25.6.0",+ "architecture": "arm64",+ "ghc": "9.12.4",+ "cabal": "3.16.1.0",+ "native_version": "2.15.0",+ "loaded_native_identity": "(\"2.15.0\",34537727)",+ "broker_version": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "broker_topology": "Project-owned single Redpanda at 127.0.0.1:39092, admin 39644"+ },+ "test_configuration": {+ "quickcheck_tests": 1000,+ "quickcheck_replay": 20261024,+ "native_asan": "Matched Apple clang runtime; detect_leaks=0"+ },+ "scenarios": [+ {+ "id": "complete-normal-and-mapped",+ "required": true,+ "status": "passed",+ "command": [+ "scripts/test-coverage.sh"+ ],+ "tests": [+ "rdkafka-hs.Callback owner.bridge allocation executes masked before ownership is recorded",+ "rdkafka-hs.Callback owner.installed and replaced bridges release exactly once",+ "rdkafka-hs.Callback owner.failed native install still owns its allocated bridge",+ "rdkafka-hs.Callback owner.failed allocation has no release",+ "rdkafka-hs.Callback owner.transfer preserves a callable bridge until client release",+ "rdkafka-hs.Callback owner.transferred and released owners reject reuse before allocating",+ "rdkafka-hs.Callback owner.release retry does not repeat completed releases",+ "rdkafka-hs.Callback owner.concurrent releases join before returning",+ "rdkafka-hs.Kafka.Consumer.ConsumerProperties.the poll mode defaults to async",+ "rdkafka-hs.Kafka.Consumer.ConsumerProperties.properties composed after the poll mode keep it",+ "rdkafka-hs.Kafka.Consumer.ConsumerProperties.properties composed before the poll mode keep it",+ "rdkafka-hs.Kafka.Consumer.ConsumerProperties.a later poll mode overrides an earlier one",+ "rdkafka-hs.Kafka.Consumer.ConsumerRecordMapSpec.should extract key",+ "rdkafka-hs.Kafka.Consumer.ConsumerRecordMapSpec.should extract value",+ "rdkafka-hs.Kafka.Consumer.ConsumerRecordMapSpec.should extract both key and value",+ "rdkafka-hs.Kafka.Consumer.ConsumerRecordTraverseSpec.should sequence",+ "rdkafka-hs.Kafka.Consumer.ConsumerRecordTraverseSpec.should traverse",+ "rdkafka-hs.Kafka.Consumer.ConsumerRecordTraverseSpec.should bisequence",+ "rdkafka-hs.Kafka.Consumer.ConsumerRecordTraverseSpec.should bitraverse",+ "rdkafka-hs.Kafka.Version.linked librdkafka is at least 2.15.0",+ "rdkafka-hs.Kafka.Version.version string agrees with the version number",+ "rdkafka-hs.Kafka.Version.decodes the hex version encoding",+ "rdkafka-hs.Producer properties generated.program follows last-write semantics",+ "rdkafka-hs.Producer properties generated.configuration has left and right identity",+ "rdkafka-hs.Producer properties generated.configuration composition is associative",+ "rdkafka-hs.Producer properties generated.composition appends writes in order",+ "rdkafka-hs.Producer properties generated.unrelated keys survive a conflicting write",+ "rdkafka-hs.Producer properties generated.last explicit log level wins",+ "rdkafka-hs.Producer properties generated.fixed empty duplicate and binary text values",+ "rdkafka-hs.Public properties.consumer composition.consumer program follows independent last-write model",+ "rdkafka-hs.Public properties.consumer composition.consumer identity preserves every observable field",+ "rdkafka-hs.Public properties.consumer composition.consumer association preserves writes and poll mode",+ "rdkafka-hs.Public properties.consumer composition.consumer composition appends programs",+ "rdkafka-hs.Public properties.consumer composition.unset poll mode preserves a prior explicit mode",+ "rdkafka-hs.Public properties.consumer composition.consumer helpers write exact native property names",+ "rdkafka-hs.Public properties.subscription.subscription follows last-write properties and topic union",+ "rdkafka-hs.Public properties.subscription.subscription identity and association retain topics and properties",+ "rdkafka-hs.Public properties.subscription.subscription composition appends property writes",+ "rdkafka-hs.Public properties.subscription.later subscription reset and explicit properties win",+ "rdkafka-hs.Public properties.headers.header list round-trip preserves duplicates and binary bytes",+ "rdkafka-hs.Public properties.headers.header concatenation follows list order",+ "rdkafka-hs.Public properties.headers.headers have two identities and associative concatenation",+ "rdkafka-hs.Public properties.headers.fixed duplicate empty and binary header values",+ "rdkafka-hs.Public properties.records.record functor identity",+ "rdkafka-hs.Public properties.records.record functor composition",+ "rdkafka-hs.Public properties.records.record bifunctor identity and composition",+ "rdkafka-hs.Public properties.records.record mapping preserves origin timestamp and headers",+ "rdkafka-hs.Public properties.records.record traversal identity and failure preserve the applicative contract",+ "rdkafka-hs.Public properties.records.record traversal composition preserves nested effects",+ "rdkafka-hs.Public properties.records.record bitraversal visits key before value",+ "rdkafka-hs.Public properties.records.record bitraversal composition preserves nested effects",+ "rdkafka-hs.Public properties.records.record folds retain key and value order",+ "rdkafka-hs.Public properties.records.deprecated record mapping remains equivalent",+ "rdkafka-hs.Public properties.records.deprecated traversal helpers preserve successful effects",+ "rdkafka-hs.Public properties.records.deprecated traversal helpers preserve failed effects",+ "rdkafka-hs.Public properties.representations.text newtypes preserve arbitrary represented text",+ "rdkafka-hs.Public properties.representations.integer newtypes preserve signed machine boundaries",+ "rdkafka-hs.Public properties.representations.offset and milliseconds preserve signed 64-bit boundaries",+ "rdkafka-hs.Public properties.representations.timestamp constructors retain their represented boundary",+ "rdkafka-hs.Public properties.representations.system topic classification requires two initial underscores",+ "rdkafka-hs.Public properties.representations.fixed empty underscore and signed numeric boundaries",+ "rdkafka-hs.Public properties.version.version bytes decode independently of prerelease byte",+ "rdkafka-hs.Public properties.version.version extraction agrees with arithmetic for every Int",+ "rdkafka-hs.Public properties.version.fixed zero and full version byte boundaries",+ "rdkafka-hs.Public properties.every compression debug and log enumeration has its native spelling",+ "rdkafka-hs.Public data contracts.builders.semigroup defaults retain writes callbacks and subscription union",+ "rdkafka-hs.Public data contracts.builders.consumer builders preserve exact settings and leave other fields unset",+ "rdkafka-hs.Public data contracts.builders.producer builders preserve global versus explicit topic placement",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs.Public data contracts.representations.numeric ordering and reads agree with represented signed values",+ "rdkafka-hs.Public data contracts.representations.numeric instances preserve primitive arithmetic including boundaries",+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.consumer variants retain fields and distinguish constructors",+ "rdkafka-hs.Public data contracts.representations.producer records delivery variants and topic requests retain exact fields",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs.Public data contracts.representations.every Kafka error preserves its Exception identity and generic form",+ "rdkafka-hs.Public data contracts.all linked native errors retain sparse numeric codes names and descriptions",+ "rdkafka-hs-integration.Fixture error controls.immediate enqueue rejection propagates",+ "rdkafka-hs-integration.Fixture error controls.delivery failure propagates",+ "rdkafka-hs-integration.Fixture error controls.flush failure propagates",+ "rdkafka-hs-integration.Fixture error controls.missing delivery callback fails",+ "rdkafka-hs-integration.Fixture error controls.wrong delivery identity fails",+ "rdkafka-hs-integration.Fixture error controls.matching delivery succeeds",+ "rdkafka-hs-integration.Fixture error controls.unexpected poll error propagates",+ "rdkafka-hs-integration.Fixture error controls.missing record fails",+ "rdkafka-hs-integration.Fixture error controls.extra record fails",+ "rdkafka-hs-integration.Fixture error controls.idle before exact records is retried",+ "rdkafka-hs-integration.Fixture error controls.partial setup releases first resource",+ "rdkafka-hs-integration.Fixture error controls.interrupted partial setup releases first resource",+ "rdkafka-hs-integration.Fixture error controls.weak control retains while rooted and collects after release",+ "rdkafka-hs-integration.configuration.defaults to the private broker",+ "rdkafka-hs-integration.configuration.accepts another private endpoint",+ "rdkafka-hs-integration.configuration.accepts a list of private endpoints",+ "rdkafka-hs-integration.configuration.rejects an empty value",+ "rdkafka-hs-integration.configuration.rejects localhost:9092",+ "rdkafka-hs-integration.configuration.rejects 127.0.0.1:9092",+ "rdkafka-hs-integration.configuration.rejects [::1]:9092",+ "rdkafka-hs-integration.configuration.rejects a loopback host without a port",+ "rdkafka-hs-integration.configuration.rejects the shared broker anywhere in a list",+ "rdkafka-hs-integration.callback-lifetime.async throwing error callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing log callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing stats callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing rebalance callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing commit callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing error callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing log callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing stats callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing rebalance callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing commit callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async error callback releases after destroy with retained wrapper",+ "rdkafka-hs-integration.callback-lifetime.sync error callback releases after destroy with retained wrapper",+ "rdkafka-hs-integration.callback-lifetime.producer delivery callback releases after native finalization",+ "rdkafka-hs-integration.callback-lifetime.noncaptured control is collectible",+ "rdkafka-hs-integration.callback-lifetime.async log callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.async stats callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.sync log callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.sync stats callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.async construction failure releases callbacks: topic",+ "rdkafka-hs-integration.callback-lifetime.async construction failure releases callbacks: native",+ "rdkafka-hs-integration.callback-lifetime.async construction failure releases callbacks: redirect",+ "rdkafka-hs-integration.callback-lifetime.async construction failure releases callbacks: subscribe",+ "rdkafka-hs-integration.callback-lifetime.sync construction failure releases callbacks: topic",+ "rdkafka-hs-integration.callback-lifetime.sync construction failure releases callbacks: native",+ "rdkafka-hs-integration.callback-lifetime.sync construction failure releases callbacks: redirect",+ "rdkafka-hs-integration.callback-lifetime.sync construction failure releases callbacks: subscribe",+ "rdkafka-hs-integration.callback-lifetime.producer native construction failure releases callbacks",+ "rdkafka-hs-integration.callback-lifetime.async constructor exception at callback-install releases partial native ownership",+ "rdkafka-hs-integration.callback-lifetime.async constructor exception at post-native-loglevel releases partial native ownership",+ "rdkafka-hs-integration.callback-lifetime.sync constructor exception at callback-install releases partial native ownership",+ "rdkafka-hs-integration.callback-lifetime.sync constructor exception at post-native-loglevel releases partial native ownership",+ "rdkafka-hs-integration.callback-lifetime.async rebalance callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.async commit callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.sync rebalance callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.sync commit callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.replaced producer delivery callbacks both release",+ "rdkafka-hs-integration.callback-lifetime.async concurrent destruction joins at native entry",+ "rdkafka-hs-integration.callback-lifetime.async concurrent destruction joins at native completion",+ "rdkafka-hs-integration.callback-lifetime.async concurrent destruction joins at native shutdown callback",+ "rdkafka-hs-integration.callback-lifetime.sync concurrent destruction joins at native entry",+ "rdkafka-hs-integration.callback-lifetime.sync concurrent destruction joins at native completion",+ "rdkafka-hs-integration.callback-lifetime.sync concurrent destruction joins at native shutdown callback",+ "rdkafka-hs-integration.callback-lifetime.async cancellation at native entry preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.async cancellation at native completion preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.async cancellation at native shutdown callback preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation at native entry preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation at native completion preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation at native shutdown callback preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.async cancellation after poll stop and queue detachment preserves teardown",+ "rdkafka-hs-integration.callback-lifetime.producer constructor cancellation at partial registration releases its owner",+ "rdkafka-hs-integration.callback-lifetime.producer constructor cancellation at native acceptance releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-async constructor cancellation at partial registration releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-async constructor cancellation at native acceptance releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-sync constructor cancellation at partial registration releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-sync constructor cancellation at native acceptance releases its owner",+ "rdkafka-hs-integration.callback-lifetime.async cancellation while waiting for active callback permits retry",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation while waiting for active callback permits retry",+ "rdkafka-hs-integration.callback-lifetime.async closed consumer GC releases its registrations once",+ "rdkafka-hs-integration.callback-lifetime.sync closed consumer GC releases its registrations once",+ "rdkafka-hs-integration.callback-lifetime.producer error callback remains live through close and releases on GC",+ "rdkafka-hs-integration.callback-lifetime.producer log callback remains live through close and releases on GC",+ "rdkafka-hs-integration.callback-lifetime.producer stats callback remains live through close and releases on GC",+ "rdkafka-hs-integration.callback-lifetime.failed native construction releases the caller-owned duplicate config",+ "rdkafka-hs-integration.transaction-errors.transaction-error-leak-probe releases 300 immediate native errors",+ "rdkafka-hs-integration.transaction-errors.native allocation control detects the inherited three-error leak",+ "rdkafka-hs-integration.transaction-errors.initialization timeout destroys its native error on each retry",+ "rdkafka-hs-integration.transaction-errors.zero-timeout initialization resumes successfully against the broker",+ "rdkafka-hs-integration.transaction-errors.transaction state errors preserve empty commit and abort recovery",+ "rdkafka-hs-integration.transaction-errors.duplicate transactional IDs report a real fatal fencing error",+ "rdkafka-hs-integration.transaction-errors.broker-rejected delivery requires abort and permits a successful new transaction",+ "rdkafka-hs-integration.transaction-errors.init without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.begin without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.abort without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.commit without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.offset without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.init NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.begin NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.abort NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.commit NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.offset NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.init invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.begin invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.abort invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.commit invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.offset invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 0 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 1 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 2 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 3 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 4 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 5 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 6 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 7 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 0 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 1 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 2 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 3 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 4 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 5 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 6 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 7 before destruction",+ "rdkafka-hs-integration.transaction-errors.init cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.begin cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.abort cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 21 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 22 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 23 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 21 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 22 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 23 releases once",+ "rdkafka-hs-integration.transaction-errors.async commit publishes output and source next offset atomically; abort publishes neither",+ "rdkafka-hs-integration.transaction-errors.sync commit publishes output and source next offset atomically; abort publishes neither",+ "rdkafka-hs-integration.lifecycle.flushProducerTimeout times out, purgeProducer empties the queue",+ "rdkafka-hs-integration.lifecycle.consumerClosed is False until closeConsumer",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials replaces credentials on a consumer",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials replaces credentials on a producer",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials rejects NUL in username without changing producer or consumer identity",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials rejects NUL in password without changing producer or consumer identity",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials releases each actual native error after decoding its exact code",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials cancellation at error decoding releases the owned error",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials cancellation at error acquisition releases the owned error",+ "rdkafka-hs-integration.topic-configuration.singleton configuration reaches the broker",+ "rdkafka-hs-integration.topic-configuration.native allocation control detects a retained request",+ "rdkafka-hs-integration.topic-configuration.setter rejection releases allocated request before submission",+ "rdkafka-hs-integration.topic-configuration.interruption after allocation releases request before submission",+ "rdkafka-hs-integration.topic-configuration.multiple configuration entries reach the broker",+ "rdkafka-hs-integration.topic-configuration.broker-rejected values release requests and response events repeatedly",+ "rdkafka-hs-integration.topic-configuration.mismatched topic in an error response cannot report another topic's error",+ "rdkafka-hs-integration.topic-configuration.unrepresentable partition count never wraps to broker defaults",+ "rdkafka-hs-integration.topic-configuration.NUL in a topic name never creates a truncated topic",+ "rdkafka-hs-integration.topic-configuration.unresponsive broker preserves the native timeout error",+ "rdkafka-hs-integration.topic-configuration.empty configuration creates a usable topic",+ "rdkafka-hs-integration.topic-configuration.later setter rejection releases partially configured request",+ "rdkafka-hs-integration.topic-configuration.duplicate creation preserves the existing topic",+ "rdkafka-hs-integration.topic-configuration.deletion removes exactly the existing topic",+ "rdkafka-hs-integration.topic-configuration.missing topic deletion preserves its error and releases the request",+ "rdkafka-hs-integration.topic-configuration.NUL deletion cannot remove a truncated victim name",+ "rdkafka-hs-integration.topic-configuration.broker default partition and replication counts remain supported",+ "rdkafka-hs-integration.topic-configuration.replication above the available broker count is rejected",+ "rdkafka-hs-integration.topic-configuration.unsupported configuration follows the declared broker policy",+ "rdkafka-hs-integration.topic-configuration.minimum unrepresentable partition count is rejected",+ "rdkafka-hs-integration.topic-configuration.maximum unrepresentable replication count is rejected",+ "rdkafka-hs-integration.topic-configuration.minimum unrepresentable replication count is rejected",+ "rdkafka-hs-integration.topic-configuration.NUL configuration key is rejected before native allocation",+ "rdkafka-hs-integration.topic-configuration.NUL configuration value is rejected before native allocation",+ "rdkafka-hs-integration.topic-configuration.negative invalid partition count retains native validation",+ "rdkafka-hs-integration.topic-configuration.maximum C partition count retains native validation",+ "rdkafka-hs-integration.topic-configuration.negative invalid replication count retains native validation",+ "rdkafka-hs-integration.topic-configuration.maximum C replication count retains native validation",+ "rdkafka-hs-integration.topic-configuration.empty topic name is rejected by the broker",+ "rdkafka-hs-integration.topic-configuration.space in a topic name is rejected by the broker",+ "rdkafka-hs-integration.topic-configuration.overlong topic name is rejected by the broker",+ "rdkafka-hs-integration.topic-configuration.zero partition count is rejected by the broker",+ "rdkafka-hs-integration.topic-configuration.zero replication count is rejected by the broker",+ "rdkafka-hs-integration.topic-configuration.wrong event type fails and releases its event",+ "rdkafka-hs-integration.topic-configuration.empty response fails and releases its event",+ "rdkafka-hs-integration.topic-configuration.wrong topic response cannot report success",+ "rdkafka-hs-integration.topic-configuration.missing polled event reports a timeout",+ "rdkafka-hs-integration.topic-configuration.delayed response succeeds with balanced ownership",+ "rdkafka-hs-integration.topic-configuration.consumer administration applies settings in async mode",+ "rdkafka-hs-integration.topic-configuration.consumer administration applies settings in sync mode",+ "rdkafka-hs-integration.topic-configuration.consumer administration applies settings in async-closed mode",+ "rdkafka-hs-integration.topic-configuration.consumer administration applies settings in sync-closed mode",+ "rdkafka-hs-integration.topic-configuration.concurrent requests keep their own queues and responses",+ "rdkafka-hs-integration.topic-configuration.unresponsive deletion preserves the native timeout error",+ "rdkafka-hs-integration.topic-configuration.deletion rejects a wrong event type and releases it",+ "rdkafka-hs-integration.topic-configuration.deletion rejects an empty result and releases its event",+ "rdkafka-hs-integration.topic-configuration.deletion rejects a mismatched topic result",+ "rdkafka-hs-integration.topic-configuration.deletion reports a missing response as a timeout",+ "rdkafka-hs-integration.topic-configuration.missing native timeout configuration returns an error",+ "rdkafka-hs-integration.topic-configuration.malformed native timeout configuration returns an error",+ "rdkafka-hs-integration.topic-configuration.zero native timeout configuration returns an error",+ "rdkafka-hs-integration.topic-configuration.negative native timeout configuration returns an error",+ "rdkafka-hs-integration.topic-configuration.overflowing native timeout configuration returns an error",+ "rdkafka-hs-integration.topic-configuration.oversized native timeout configuration never reads a truncated buffer",+ "rdkafka-hs-integration.producer-regressions.explicit topic timeout expires an accepted message",+ "rdkafka-hs-integration.producer-regressions.global timeout still expires an accepted message",+ "rdkafka-hs-integration.producer-regressions.queue-full rejection releases callback capture without invoking it",+ "rdkafka-hs-integration.producer-regressions.accepted callback retains its capture until a purged report completes",+ "rdkafka-hs-integration.producer-regressions.throwing global callback preserves per-message delivery and releases capture",+ "rdkafka-hs-integration.producer-regressions.throwing per-message callback reports exception and releases capture",+ "rdkafka-hs-integration.producer-regressions.repeated queue-full rejections release every callback capture",+ "rdkafka-hs-integration.producer-regressions.cancellation at a rejected enqueue releases capture before unmasking",+ "rdkafka-hs-integration.producer-regressions.cancellation after native acceptance retains callback until its report",+ "rdkafka-hs-integration.producer-regressions.another poller can deliver before successful enqueue returns",+ "rdkafka-hs-integration.producer-regressions.running callback keeps its capture after the native root is released",+ "rdkafka-hs-integration.producer-regressions.native error decoding failure releases rejected callback capture",+ "rdkafka-hs-integration.producer-regressions.non-null native success-code error rejects and releases capture",+ "rdkafka-hs-integration.producer-regressions.unknown native error code is preserved instead of reading errno",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: defaults",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: global only",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: topic only",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: disjoint maps",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: explicit topic wins duplicate",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: last topic property wins",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: empty topic map preserves global",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: zero topic timeout is infinite",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: maximum native topic timeout",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: explicit topic wins native timeout alias",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: topic codec overrides global codec",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: global codec survives unrelated topic keys",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with NoCompression",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Gzip",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Snappy",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Lz4",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Zstd",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: none",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: inflight",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue+inflight",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue+nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: inflight+nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: all",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: none",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: inflight",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue+inflight",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue+nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: inflight+nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: all",+ "rdkafka-hs-integration.producer-regressions.bounded flush timeout recovers when the delayed response arrives",+ "rdkafka-hs-integration.producer-regressions.close retries a timed-out flush until the delayed delivery completes",+ "rdkafka-hs-integration.producer-regressions.oversized rejection releases capture without a delivery report",+ "rdkafka-hs-integration.producer-regressions.known invalid partition rejection releases capture",+ "rdkafka-hs-integration.producer-regressions.empty queue supports repeated flush and close",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: NUL topic name",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: NUL header name",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: maximum unrepresentable partition",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: minimum unrepresentable partition",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: unknown global key",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: unknown topic key",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: invalid topic timeout",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: excessive topic timeout",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: global-only key in topic map",+ "rdkafka-hs-integration.producer-regressions.later delivery callback replaces the earlier callback",+ "rdkafka-hs-integration.producer-regressions.null native delivery frame reports the generic errno fallback without dereferencing a message",+ "rdkafka-hs-integration.producer-regressions.native delivery without an opaque Haskell callback preserves the complete record",+ "rdkafka-hs-integration.producer-regressions.delivery header acquisition failure preserves the outcome with empty headers",+ "rdkafka-hs-integration.producer-properties.callback composition preserves order and identity",+ "rdkafka-hs-integration.consumer-properties.consumer callback composition preserves registration order and identity",+ "rdkafka-hs-integration.consumer-properties.generated source offsets reach native code as the representable next position",+ "rdkafka-hs-integration.consumer-properties.async later subscription reset reaches the native consumer",+ "rdkafka-hs-integration.consumer-properties.sync later subscription reset reaches the native consumer",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.counter detects a retained native list before explicit release",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.pair conversion failure releases the partial list before GC",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.offset conversion failure releases the partial list before GC",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.ordinary input lists release after exact native results",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.native logical offsets decode independently without losing partition identity",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.missing native partition queue preserves assignment and later forwarding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.assignment outputs release after exact decoding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.subscription outputs release after exact decoding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.subscription acquisition failure preserves the native error without a list",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.assignment decoder failure releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.subscription decoder failure releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.cancellation at input allocation releases the owned list",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.cancellation at assignment return releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.pair conversion failure releases the partial list before GC",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.offset conversion failure releases the partial list before GC",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.ordinary input lists release after exact native results",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.native logical offsets decode independently without losing partition identity",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.missing native partition queue preserves assignment and later forwarding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.assignment outputs release after exact decoding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.subscription outputs release after exact decoding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.subscription acquisition failure preserves the native error without a list",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.assignment decoder failure releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.subscription decoder failure releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.cancellation at input allocation releases the owned list",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.cancellation at assignment return releases the owned output",+ "rdkafka-hs-integration.public-contract.messages.batch conversion releases every returned native message",+ "rdkafka-hs-integration.public-contract.messages.native message counter detects a retained final object",+ "rdkafka-hs-integration.public-contract.messages.batch decoder exception releases unprocessed messages",+ "rdkafka-hs-integration.public-contract.messages.batch native header errors remain errors while later records are released",+ "rdkafka-hs-integration.public-contract.messages.batch cancellation at native return releases every acquired message",+ "rdkafka-hs-integration.public-contract.messages.batch cancellation at middle conversion releases every acquired message",+ "rdkafka-hs-integration.public-contract.messages.async single cancellation at native return releases its native message",+ "rdkafka-hs-integration.public-contract.messages.async single cancellation at inside conversion releases its native message",+ "rdkafka-hs-integration.public-contract.messages.sync single cancellation at native return releases its native message",+ "rdkafka-hs-integration.public-contract.messages.sync single cancellation at inside conversion releases its native message",+ "rdkafka-hs-integration.public-contract.messages.async header failure preserves the polled record origin",+ "rdkafka-hs-integration.public-contract.messages.sync header failure preserves the polled record origin",+ "rdkafka-hs-integration.public-contract.messages.async plain polling surfaces native header failure",+ "rdkafka-hs-integration.public-contract.messages.sync plain polling surfaces native header failure",+ "rdkafka-hs-integration.public-contract.messages.async attributed error preserves independently absent partition-and-offset",+ "rdkafka-hs-integration.public-contract.messages.async attributed error preserves independently absent offset",+ "rdkafka-hs-integration.public-contract.messages.async attributed error preserves independently absent partition",+ "rdkafka-hs-integration.public-contract.messages.sync attributed error preserves independently absent partition-and-offset",+ "rdkafka-hs-integration.public-contract.messages.sync attributed error preserves independently absent offset",+ "rdkafka-hs-integration.public-contract.messages.sync attributed error preserves independently absent partition",+ "rdkafka-hs-integration.public-contract.messages.callback-event polling cancellation releases a returned message",+ "rdkafka-hs-integration.public-contract.messages.callback buffer preserves attributed header failure",+ "rdkafka-hs-integration.public-contract.messages.callback buffer preserves plain header failure",+ "rdkafka-hs-integration.public-contract.messages.originless callback error survives seek filtering and a paused partition",+ "rdkafka-hs-integration.public-contract.messages.callback-event polling releases and discards a returned fatal frame",+ "rdkafka-hs-integration.public-contract.messages.zero batch size leaves the queued records available",+ "rdkafka-hs-integration.public-contract.messages.unsupported sync batch does not discard a record",+ "rdkafka-hs-integration.public-contract.messages.signed native batch failure preserves its error and queued data",+ "rdkafka-hs-integration.public-contract.messages.infinite batch timeout returns available records",+ "rdkafka-hs-integration.public-contract.messages.batch capacity 1 preserves complete ordered records across partial batches",+ "rdkafka-hs-integration.public-contract.messages.batch capacity 2 preserves complete ordered records across partial batches",+ "rdkafka-hs-integration.public-contract.messages.batch capacity 5 preserves complete ordered records across partial batches",+ "rdkafka-hs-integration.public-contract.messages.invalid batch array size is rejected before native acquisition: -1",+ "rdkafka-hs-integration.public-contract.messages.invalid batch array size is rejected before native acquisition: -9223372036854775808",+ "rdkafka-hs-integration.public-contract.messages.invalid batch array size is rejected before native acquisition: 9223372036854775807",+ "rdkafka-hs-integration.public-contract.messages.batch preserves complete records followed by exact partition EOF and idle timeout",+ "rdkafka-hs-integration.public-contract.messages.empty batch respects timeout 0",+ "rdkafka-hs-integration.public-contract.messages.empty batch respects timeout 100",+ "rdkafka-hs-integration.public-contract.rebalance-errors.native rebalance counter detects an undisposed error",+ "rdkafka-hs-integration.public-contract.rebalance-errors.async real cooperative assignment and revocation preserve records",+ "rdkafka-hs-integration.public-contract.rebalance-errors.sync real cooperative assignment and revocation preserve records",+ "rdkafka-hs-integration.public-contract.rebalance-errors.cooperative assign async native reports failure without a success event",+ "rdkafka-hs-integration.public-contract.rebalance-errors.cooperative assign async decode reports failure without a success event",+ "rdkafka-hs-integration.public-contract.rebalance-errors.cooperative assign sync native reports failure without a success event",+ "rdkafka-hs-integration.public-contract.rebalance-errors.cooperative assign sync decode reports failure without a success event",+ "rdkafka-hs-integration.public-contract.rebalance-errors.cooperative revoke async native reports failure without a success event",+ "rdkafka-hs-integration.public-contract.rebalance-errors.cooperative revoke async decode reports failure without a success event",+ "rdkafka-hs-integration.public-contract.rebalance-errors.cooperative revoke sync native reports failure without a success event",+ "rdkafka-hs-integration.public-contract.rebalance-errors.cooperative revoke sync decode reports failure without a success event",+ "rdkafka-hs-integration.public-contract.rebalance-errors.eager assign async native reports failure without a success event",+ "rdkafka-hs-integration.public-contract.rebalance-errors.eager assign sync native reports failure without a success event",+ "rdkafka-hs-integration.public-contract.rebalance-errors.eager revoke async native reports failure without a success event",+ "rdkafka-hs-integration.public-contract.rebalance-errors.eager revoke sync native reports failure without a success event",+ "rdkafka-hs-integration.public-contract.rebalance-errors.async unexpected rebalance error clears assignment and pending records",+ "rdkafka-hs-integration.public-contract.rebalance-errors.async unexpected rebalance error preserves state when native reset fails",+ "rdkafka-hs-integration.public-contract.rebalance-errors.sync unexpected rebalance error clears assignment and pending records",+ "rdkafka-hs-integration.public-contract.rebalance-errors.sync unexpected rebalance error preserves state when native reset fails",+ "rdkafka-hs-integration.public-contract.consumer-state.async.assignment-replacement",+ "rdkafka-hs-integration.public-contract.consumer-state.async.unknown-assignment-reports-through-error-callback-and-recovers",+ "rdkafka-hs-integration.public-contract.consumer-state.async.representable-partition-boundaries-keep-native-query-semantics",+ "rdkafka-hs-integration.public-contract.consumer-state.async.deprecated-seek-reports-unassigned-state-and-recovers-after-assignment",+ "rdkafka-hs-integration.public-contract.consumer-state.async.subscription-preserves-the-exact-multiple-topic-set",+ "rdkafka-hs-integration.public-contract.consumer-state.async.empty-requests-preserve-empty-assignment",+ "rdkafka-hs-integration.public-contract.consumer-state.async.unknown-position-is-invalid-without-native-error",+ "rdkafka-hs-integration.public-contract.consumer-state.async.multiple-assigned-partitions-retain-the-exact-topic-map",+ "rdkafka-hs-integration.public-contract.consumer-state.async.legacy-seek-constructor-failure-does-not-execute-an-earlier-valid-seek",+ "rdkafka-hs-integration.public-contract.consumer-state.async.pause-resume-preserves-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-event-poll-preserves-application-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-seek-replaces-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-reassignment-replaces-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-pause-defers-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-legacy-seek-replaces-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-legacy-partial-seek-keeps-success",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-paused-partition-does-not-block-another",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-unassignment-discards-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.pausing-one-partition-leaves-the-other-running",+ "rdkafka-hs-integration.public-contract.consumer-state.async.pause-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.async.resume-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.async.store-commit-next-offset",+ "rdkafka-hs-integration.public-contract.consumer-state.async.store-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.async.position-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.async.deprecated-seek-exact-repeated-replay",+ "rdkafka-hs-integration.public-contract.consumer-state.async.explicit-subscription-overrides-global-reset",+ "rdkafka-hs-integration.public-contract.consumer-state.async.regex-subscription-selects-run-owned-topic",+ "rdkafka-hs-integration.public-contract.consumer-state.async.global-topic-setting-survives-empty-subscription-properties",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.assignment-replacement",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.unknown-assignment-reports-through-error-callback-and-recovers",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.representable-partition-boundaries-keep-native-query-semantics",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.deprecated-seek-reports-unassigned-state-and-recovers-after-assignment",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.subscription-preserves-the-exact-multiple-topic-set",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.empty-requests-preserve-empty-assignment",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.unknown-position-is-invalid-without-native-error",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.multiple-assigned-partitions-retain-the-exact-topic-map",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.legacy-seek-constructor-failure-does-not-execute-an-earlier-valid-seek",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.pause-resume-preserves-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-event-poll-preserves-application-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-seek-replaces-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-reassignment-replaces-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-pause-defers-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-legacy-seek-replaces-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-legacy-partial-seek-keeps-success",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-paused-partition-does-not-block-another",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-unassignment-discards-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.pausing-one-partition-leaves-the-other-running",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.pause-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.resume-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.store-commit-next-offset",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.store-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.position-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.deprecated-seek-exact-repeated-replay",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.explicit-subscription-overrides-global-reset",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.regex-subscription-selects-run-owned-topic",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.global-topic-setting-survives-empty-subscription-properties",+ "rdkafka-hs-integration.public-contract.consumer-state.sync-buffer-fields-native-time",+ "rdkafka-hs-integration.public-contract.consumer-state.sync-buffer-fields-no-time",+ "rdkafka-hs-integration.public-contract.consumer-state.sync-buffer-fields-append-time",+ "rdkafka-hs-integration.public-contract.consumer-state.sync-buffer-fields-create-time",+ "rdkafka-hs-integration.public-contract.consumer-state.cooperative subset callbacks preserve unrelated buffers pauses and originless errors",+ "rdkafka-hs-integration.public-contract.consumer-state.sync callback mixed seek retains only the failed partition's copied records",+ "rdkafka-hs-integration.public-contract.consumer-commit.async commit modes preserve native flags callback offsets and broker state",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync commit modes preserve native flags callback offsets and broker state",+ "rdkafka-hs-integration.public-contract.consumer-commit.async message and stored commits preserve unrelated partition offsets",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync message and stored commits preserve unrelated partition offsets",+ "rdkafka-hs-integration.public-contract.consumer-commit.async empty commit requests preserve no-offset callbacks",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync empty commit requests preserve no-offset callbacks",+ "rdkafka-hs-integration.public-contract.consumer-commit.async mixed broker commit failures preserve successful offsets",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync mixed broker commit failures preserve successful offsets",+ "rdkafka-hs-integration.public-contract.consumer-commit.async committed query preserves an unavailable coordinator timeout",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync committed query preserves an unavailable coordinator timeout",+ "rdkafka-hs-integration.public-contract.diagnostics.supported-property print flushes and preserves the caller handle",+ "rdkafka-hs-integration.public-contract.diagnostics.client print flushes and preserves the caller handle",+ "rdkafka-hs-integration.public-contract.diagnostics.failed fdopen releases the duplicate and preserves the original",+ "rdkafka-hs-integration.public-contract.diagnostics.failed native flush is reported after closing the duplicate",+ "rdkafka-hs-integration.public-contract.diagnostics.producer configuration dumps retain exact explicit and global settings",+ "rdkafka-hs-integration.public-contract.diagnostics.producer constructor log level overrides the global property on the native client",+ "rdkafka-hs-integration.public-contract.diagnostics.consumer configuration dump preserves global settings after subscription merge",+ "rdkafka-hs-integration.public-contract.diagnostics.native dump counter detects an unreleased array",+ "rdkafka-hs-integration.public-contract.diagnostics.global cancellation at native acquisition releases its array",+ "rdkafka-hs-integration.public-contract.diagnostics.topic cancellation at native acquisition releases its array",+ "rdkafka-hs-integration.public-contract.input-boundaries.async assign rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async pause rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async resume rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async store rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async store-message rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async commit rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async commit-message rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async committed rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async position rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async legacy-seek rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async seek rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async timestamp rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async watermark rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async assign rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async pause rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async resume rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async store rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async store-message rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async commit rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async commit-message rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async committed rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async position rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async legacy-seek rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async seek rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async timestamp rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async watermark rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async assign rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async pause rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async resume rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async store rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async store-message rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async commit rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async commit-message rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async committed rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async position rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async legacy-seek rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async seek rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async timestamp rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async watermark rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync assign rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync pause rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync resume rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync store rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync store-message rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync commit rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync commit-message rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync committed rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync position rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync legacy-seek rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync seek rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync timestamp rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync watermark rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync assign rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync pause rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync resume rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync store rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync store-message rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync commit rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync commit-message rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync committed rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync position rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync legacy-seek rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync seek rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync timestamp rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync watermark rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync assign rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync pause rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync resume rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync store rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync store-message rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync commit rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync commit-message rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync committed rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync position rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync legacy-seek rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync seek rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync timestamp rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync watermark rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async string queries and subscription reject NUL before native effects",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync string queries and subscription reject NUL before native effects",+ "rdkafka-hs-integration.public-contract.deprecated-runners.producer flushes after Returned",+ "rdkafka-hs-integration.public-contract.deprecated-runners.producer flushes after Refused",+ "rdkafka-hs-integration.public-contract.deprecated-runners.producer flushes after Thrown",+ "rdkafka-hs-integration.public-contract.deprecated-runners.async consumer closes after Returned",+ "rdkafka-hs-integration.public-contract.deprecated-runners.async consumer closes after Refused",+ "rdkafka-hs-integration.public-contract.deprecated-runners.async consumer closes after Thrown",+ "rdkafka-hs-integration.public-contract.deprecated-runners.sync consumer closes after Returned",+ "rdkafka-hs-integration.public-contract.deprecated-runners.sync consumer closes after Refused",+ "rdkafka-hs-integration.public-contract.deprecated-runners.sync consumer closes after Thrown",+ "rdkafka-hs-integration.public-contract.deprecated-runners.producer preserves native construction failure without invoking handler",+ "rdkafka-hs-integration.public-contract.deprecated-runners.producer preserves configuration exceptions without invoking handler",+ "rdkafka-hs-integration.public-contract.deprecated-runners.async consumer preserves native construction failure",+ "rdkafka-hs-integration.public-contract.deprecated-runners.async consumer preserves configuration construction failure",+ "rdkafka-hs-integration.public-contract.deprecated-runners.sync consumer preserves native construction failure",+ "rdkafka-hs-integration.public-contract.deprecated-runners.sync consumer preserves configuration construction failure",+ "rdkafka-hs-integration.public-contract.fatal.async",+ "rdkafka-hs-integration.public-contract.fatal.sync",+ "rdkafka-hs-integration.public-contract.queue event.empty pipes are idle but invalid descriptor errors are preserved",+ "rdkafka-hs-integration.public-contract.queue event.async.wakes an idle consumer and stays quiet once disabled",+ "rdkafka-hs-integration.public-contract.queue event.async.finds records queued before it was enabled, then rearms",+ "rdkafka-hs-integration.public-contract.queue event.async.one wake-up covers several records, then rearms",+ "rdkafka-hs-integration.public-contract.queue event.async.binary payloads retain every byte and empty payloads preserve records",+ "rdkafka-hs-integration.public-contract.queue event.async.native record errors are never treated as idle",+ "rdkafka-hs-integration.public-contract.queue event.async.close stops notifications and keeps caller descriptors open",+ "rdkafka-hs-integration.public-contract.queue event.async.destroy stops notifications and keeps caller descriptors open",+ "rdkafka-hs-integration.public-contract.queue event.sync.wakes an idle consumer and stays quiet once disabled",+ "rdkafka-hs-integration.public-contract.queue event.sync.finds records queued before it was enabled, then rearms",+ "rdkafka-hs-integration.public-contract.queue event.sync.one wake-up covers several records, then rearms",+ "rdkafka-hs-integration.public-contract.queue event.sync.binary payloads retain every byte and empty payloads preserve records",+ "rdkafka-hs-integration.public-contract.queue event.sync.native record errors are never treated as idle",+ "rdkafka-hs-integration.public-contract.queue event.sync.close stops notifications and keeps caller descriptors open",+ "rdkafka-hs-integration.public-contract.queue event.sync.destroy stops notifications and keeps caller descriptors open",+ "rdkafka-hs-integration.public-contract.runtime-contract.RTS capability is observed by async construction",+ "rdkafka-hs-integration.public-contract.runtime-contract.explicit async construction checks the runtime",+ "rdkafka-hs-integration.public-contract.runtime-contract.sync subscription delivers an exact record",+ "rdkafka-hs-integration.public-contract.runtime-contract.deprecated sync runner closes after an exact record",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata counter detects an unreleased result",+ "rdkafka-hs-integration.public-contract.metadata-contract.native topic-constructor failure survives metadata convenience queries",+ "rdkafka-hs-integration.public-contract.metadata-contract.empty native metadata remains empty and releases every result",+ "rdkafka-hs-integration.public-contract.metadata-contract.timestamp lookup preserves native overall errors",+ "rdkafka-hs-integration.public-contract.metadata-contract.watermark queries preserve unknown partition errors and empty provided metadata",+ "rdkafka-hs-integration.public-contract.metadata-contract.topic identity replica sets and exact watermarks",+ "rdkafka-hs-integration.public-contract.metadata-contract.distinct native metadata fields retain exact identities and errors",+ "rdkafka-hs-integration.public-contract.metadata-contract.provided metadata preserves partition failures in convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata partition failures survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.group query timeout preserves initial metadata wait failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.missing topic errors survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.timestamp lookup distinguishes before at and after actual record times",+ "rdkafka-hs-integration.public-contract.metadata-contract.mixed timestamp request preserves native partition failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata timeouts preserve the native error",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.groups native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.async group identity lifecycle and supported native states",+ "rdkafka-hs-integration.public-contract.metadata-contract.sync group identity lifecycle and supported native states",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.empty producer client id retains the native default",+ "rdkafka-hs-integration.public-contract.config-strings.consumer ordinary UTF8 values remain exact",+ "rdkafka-hs-integration.public-contract.config-strings.empty global key retains native unknown-key rejection",+ "rdkafka-hs-integration.seek-partitions.async.unassigned member reports native error",+ "rdkafka-hs-integration.seek-partitions.async.empty list preserves top-level invalid argument",+ "rdkafka-hs-integration.seek-partitions.async.zero-timeout unassigned failure is immediate",+ "rdkafka-hs-integration.seek-partitions.async.empty zero-timeout preserves top-level error",+ "rdkafka-hs-integration.seek-partitions.async.rewind without assignment does not seek",+ "rdkafka-hs-integration.seek-partitions.async.top-level error precedes member error and is destroyed",+ "rdkafka-hs-integration.seek-partitions.async.first substantive error follows input order",+ "rdkafka-hs-integration.seek-partitions.async.reversed input selects the other substantive error",+ "rdkafka-hs-integration.seek-partitions.async.zero-timeout skips pending but reports later failure",+ "rdkafka-hs-integration.seek-partitions.async.nonzero-timeout preserves residual pending",+ "rdkafka-hs-integration.seek-partitions.async.zero-timeout all pending promises initiation only",+ "rdkafka-hs-integration.seek-partitions.async.nonzero-timeout all pending is not success",+ "rdkafka-hs-integration.seek-partitions.async.top-level decoder exception still destroys error object",+ "rdkafka-hs-integration.seek-partitions.async.rewind assignment failure prevents seek",+ "rdkafka-hs-integration.seek-partitions.async.single seek replays exact record",+ "rdkafka-hs-integration.seek-partitions.async.multiple successful seeks replay both partitions",+ "rdkafka-hs-integration.seek-partitions.async.mixed seek reports failure without rolling back success",+ "rdkafka-hs-integration.seek-partitions.async.mixed errors follow actual request order",+ "rdkafka-hs-integration.seek-partitions.async.zero-timeout valid seek is followed by synchronous replay",+ "rdkafka-hs-integration.seek-partitions.async.zero-timeout mixed request keeps immediate unknown error",+ "rdkafka-hs-integration.seek-partitions.async.zero-timeout logical offsets promise initiation only",+ "rdkafka-hs-integration.seek-partitions.async.infinite native timeout completes a valid seek",+ "rdkafka-hs-integration.seek-partitions.async.duplicate entries preserve residual native pending error",+ "rdkafka-hs-integration.seek-partitions.async.unassigned existing partition returns state error",+ "rdkafka-hs-integration.seek-partitions.async.unknown topic reports member error",+ "rdkafka-hs-integration.seek-partitions.async.stored sentinel is rejected without altering position",+ "rdkafka-hs-integration.seek-partitions.async.end and exact high watermark produce no record",+ "rdkafka-hs-integration.seek-partitions.async.seek before retained log range resets to actual low watermark",+ "rdkafka-hs-integration.seek-partitions.async.rewind without committed offset starts at beginning",+ "rdkafka-hs-integration.seek-partitions.async.rewind uses committed next offset exactly",+ "rdkafka-hs-integration.seek-partitions.async.rewind message commit resumes after committed message",+ "rdkafka-hs-integration.seek-partitions.async.rewind lookup failure prevents seek",+ "rdkafka-hs-integration.seek-partitions.async.rewind propagates assignment change after committed lookup",+ "rdkafka-hs-integration.seek-partitions.async.beginning sentinel replays offset zero",+ "rdkafka-hs-integration.seek-partitions.async.absolute low watermark replays offset zero",+ "rdkafka-hs-integration.seek-partitions.async.invalid sentinel uses configured earliest reset",+ "rdkafka-hs-integration.seek-partitions.async.above high watermark uses configured earliest reset",+ "rdkafka-hs-integration.seek-partitions.async.native tail sentinel replays final two records",+ "rdkafka-hs-integration.seek-partitions.sync.unassigned member reports native error",+ "rdkafka-hs-integration.seek-partitions.sync.empty list preserves top-level invalid argument",+ "rdkafka-hs-integration.seek-partitions.sync.zero-timeout unassigned failure is immediate",+ "rdkafka-hs-integration.seek-partitions.sync.empty zero-timeout preserves top-level error",+ "rdkafka-hs-integration.seek-partitions.sync.rewind without assignment does not seek",+ "rdkafka-hs-integration.seek-partitions.sync.top-level error precedes member error and is destroyed",+ "rdkafka-hs-integration.seek-partitions.sync.first substantive error follows input order",+ "rdkafka-hs-integration.seek-partitions.sync.reversed input selects the other substantive error",+ "rdkafka-hs-integration.seek-partitions.sync.zero-timeout skips pending but reports later failure",+ "rdkafka-hs-integration.seek-partitions.sync.nonzero-timeout preserves residual pending",+ "rdkafka-hs-integration.seek-partitions.sync.zero-timeout all pending promises initiation only",+ "rdkafka-hs-integration.seek-partitions.sync.nonzero-timeout all pending is not success",+ "rdkafka-hs-integration.seek-partitions.sync.top-level decoder exception still destroys error object",+ "rdkafka-hs-integration.seek-partitions.sync.rewind assignment failure prevents seek",+ "rdkafka-hs-integration.seek-partitions.sync.single seek replays exact record",+ "rdkafka-hs-integration.seek-partitions.sync.multiple successful seeks replay both partitions",+ "rdkafka-hs-integration.seek-partitions.sync.mixed seek reports failure without rolling back success",+ "rdkafka-hs-integration.seek-partitions.sync.mixed errors follow actual request order",+ "rdkafka-hs-integration.seek-partitions.sync.zero-timeout valid seek is followed by synchronous replay",+ "rdkafka-hs-integration.seek-partitions.sync.zero-timeout mixed request keeps immediate unknown error",+ "rdkafka-hs-integration.seek-partitions.sync.zero-timeout logical offsets promise initiation only",+ "rdkafka-hs-integration.seek-partitions.sync.infinite native timeout completes a valid seek",+ "rdkafka-hs-integration.seek-partitions.sync.duplicate entries preserve residual native pending error",+ "rdkafka-hs-integration.seek-partitions.sync.unassigned existing partition returns state error",+ "rdkafka-hs-integration.seek-partitions.sync.unknown topic reports member error",+ "rdkafka-hs-integration.seek-partitions.sync.stored sentinel is rejected without altering position",+ "rdkafka-hs-integration.seek-partitions.sync.end and exact high watermark produce no record",+ "rdkafka-hs-integration.seek-partitions.sync.seek before retained log range resets to actual low watermark",+ "rdkafka-hs-integration.seek-partitions.sync.rewind without committed offset starts at beginning",+ "rdkafka-hs-integration.seek-partitions.sync.rewind uses committed next offset exactly",+ "rdkafka-hs-integration.seek-partitions.sync.rewind message commit resumes after committed message",+ "rdkafka-hs-integration.seek-partitions.sync.rewind lookup failure prevents seek",+ "rdkafka-hs-integration.seek-partitions.sync.rewind propagates assignment change after committed lookup",+ "rdkafka-hs-integration.seek-partitions.sync.beginning sentinel replays offset zero",+ "rdkafka-hs-integration.seek-partitions.sync.absolute low watermark replays offset zero",+ "rdkafka-hs-integration.seek-partitions.sync.invalid sentinel uses configured earliest reset",+ "rdkafka-hs-integration.seek-partitions.sync.above high watermark uses configured earliest reset",+ "rdkafka-hs-integration.seek-partitions.sync.native tail sentinel replays final two records",+ "rdkafka-hs-integration.broker.Per-message commit.1. sends 2 messages to test topic",+ "rdkafka-hs-integration.broker.Per-message commit.2. should receive 2 messages",+ "rdkafka-hs-integration.broker.Per-message commit.3. sends 2 messages to test topic",+ "rdkafka-hs-integration.broker.Per-message commit.4. should receive 2 messages again",+ "rdkafka-hs-integration.broker.Store offsets.1. sends 2 messages to test topic",+ "rdkafka-hs-integration.broker.Store offsets.2. should receive 2 messages without storing",+ "rdkafka-hs-integration.broker.Store offsets.3. sends 2 messages to test topic",+ "rdkafka-hs-integration.broker.Store offsets.4. should receive 4 messages and store them",+ "rdkafka-hs-integration.broker.Store offsets.5. sends 2 messages to test topic",+ "rdkafka-hs-integration.broker.Store offsets.6. should receive 2 messages",+ "rdkafka-hs-integration.broker.Store offsets.Part 3 - Consume after committing stored offsets.5. sends 2 messages to test topic",+ "rdkafka-hs-integration.broker.Store offsets.Part 3 - Consume after committing stored offsets.6. should receive 2 messages",+ "rdkafka-hs-integration.broker.Consumer.Run producer.sends messages to test topic",+ "rdkafka-hs-integration.broker.Consumer.Run producer.sends messages with callback to test topic",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should receive messages",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should get committed",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should get position",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should get watermark offsets",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should return subscription",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should return assignment",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.assignment is not lost",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should return all topics metadata",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should return topic metadata",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should describe all consumer groups",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should describe a given consumer group",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should describe non-existent consumer group",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should read topic offsets for time",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should seek and return no error",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should seek to the beginning",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should seek to the end",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should respect out-of-bound offsets (invalid offset)",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should respect out-of-bound offsets (huge offset)",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should receive messages",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should get committed",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should get position",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should get watermark offsets",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should return subscription",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should return assignment",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.assignment is not lost",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should return all topics metadata",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should return topic metadata",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should describe all consumer groups",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should describe a given consumer group",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should describe non-existent consumer group",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should read topic offsets for time",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should seek and return no error",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should seek to the beginning",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should seek to the end",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should respect out-of-bound offsets (invalid offset)",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should respect out-of-bound offsets (huge offset)",+ "rdkafka-hs-integration.broker.Batch consumer.should consume first batch",+ "rdkafka-hs-integration.broker.Batch consumer.should consume second batch with not enough messages",+ "rdkafka-hs-integration.broker.Batch consumer.should consume empty batch when there are no messages",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessage sync.interleaved duplicate names keep wire order and last values",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessage sync.distinct names keep wire order",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessage sync.identical repeated pairs are not deduplicated",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessage sync.a single header round-trips",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessage sync.no headers decode as an empty list",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessage async.interleaved duplicate names keep wire order and last values",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessage async.distinct names keep wire order",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessage async.identical repeated pairs are not deduplicated",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessage async.a single header round-trips",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessage async.no headers decode as an empty list",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessageAttributed sync.interleaved duplicate names keep wire order and last values",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessageAttributed sync.distinct names keep wire order",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessageAttributed sync.identical repeated pairs are not deduplicated",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessageAttributed sync.a single header round-trips",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessageAttributed sync.no headers decode as an empty list",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessageAttributed async.interleaved duplicate names keep wire order and last values",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessageAttributed async.distinct names keep wire order",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessageAttributed async.identical repeated pairs are not deduplicated",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessageAttributed async.a single header round-trips",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessageAttributed async.no headers decode as an empty list",+ "rdkafka-hs-integration.broker.assign-only.async.newAssignedConsumer",+ "rdkafka-hs-integration.broker.assign-only.async.newConsumer with an empty subscription",+ "rdkafka-hs-integration.broker.assign-only.sync.newAssignedConsumer",+ "rdkafka-hs-integration.broker.assign-only.sync.newConsumer with an empty subscription",+ "rdkafka-hs-integration.broker.attributed.async",+ "rdkafka-hs-integration.broker.attributed.sync",+ "rdkafka-hs-integration.broker.destroy.async.closes broker connections within one second",+ "rdkafka-hs-integration.broker.destroy.async.is safe to repeat",+ "rdkafka-hs-integration.broker.destroy.async.concurrent destroys both return after cleanup",+ "rdkafka-hs-integration.broker.destroy.async.completes after an interrupted destroy",+ "rdkafka-hs-integration.broker.destroy.async.close then destroy, destroy then close",+ "rdkafka-hs-integration.broker.destroy.sync.closes broker connections within one second",+ "rdkafka-hs-integration.broker.destroy.sync.is safe to repeat",+ "rdkafka-hs-integration.broker.destroy.sync.concurrent destroys both return after cleanup",+ "rdkafka-hs-integration.broker.destroy.sync.completes after an interrupted destroy",+ "rdkafka-hs-integration.broker.destroy.sync.close then destroy, destroy then close",+ "rdkafka-hs-integration.broker.read_committed watermark stops before an open transaction",+ "rdkafka-hs-integration.broker.observer.async",+ "rdkafka-hs-integration.broker.observer.sync",+ "rdkafka-hs-integration.broker.Read all topics.should create a topic",+ "rdkafka-hs-integration.broker.Read all topics.should return all the topics",+ "rdkafka-hs-integration.broker.Read all topics.should delete this run's topics"+ ],+ "passed": 831,+ "artifacts": {+ "normal": {+ "path": "dist-compatibility/expanded-source9/primary-normal9.log",+ "sha256": "0cc78933babadbb7d223879eb76ddd60513010cfab5cd282a0e4ee974a52faeb"+ },+ "mapped": {+ "path": "dist-compatibility/expanded-source9/primary-mapped9.log",+ "sha256": "563e4fcf86cd2047cea629df6837a502e4795dca676f96671655b9758eacf6c8"+ },+ "allow_open": {+ "path": "dist-compatibility/expanded-source9/coverage-allow-open.log",+ "sha256": "6aaeb4a62ef5152f0f1adf20bb654b54b8fe12f057b757150972ebe61992fb7a"+ },+ "strict": {+ "path": "dist-compatibility/expanded-source9/coverage-strict.log",+ "sha256": "542cc685cf514e26aec1535c91dba78ce90b78baacf3eebe98e98afc47a43222"+ },+ "tooling": {+ "path": "dist-compatibility/expanded-source9/coverage-tools.log",+ "sha256": "d9301ebe380dc7a7bd690c77c4421a8314098575c7200305f60c5fb093bc118a"+ },+ "measured": {+ "path": "dist-compatibility/expanded-source9/primary-measured9-with-contexts.json",+ "sha256": "9a98d410cbeb3ef8ce0e3d99f39d989dbf145ee434db9aedf7aa771c52922ffe"+ }+ },+ "limitations": [+ "857 aggregate registrations include 26 separately executed external cases; primary normal/mapped each executes 831."+ ]+ },+ {+ "id": "native-invalid-access-complement",+ "required": true,+ "status": "passed",+ "command": [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-compatibility/expanded-source9/darwin-native-candidate",+ "-p",+ "/producer-regressions/ || /callback-lifetime/ || (/public-contract/ && (/messages/ || /partition-list-ownership/ || /metadata-contract/ || /diagnostics/)) || /transaction-errors/ || /lifecycle/",+ "+RTS",+ "-N2",+ "-RTS"+ ],+ "tests": [+ "rdkafka-hs-integration.callback-lifetime.async throwing error callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing log callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing stats callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing rebalance callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing commit callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing error callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing log callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing stats callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing rebalance callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing commit callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async error callback releases after destroy with retained wrapper",+ "rdkafka-hs-integration.callback-lifetime.sync error callback releases after destroy with retained wrapper",+ "rdkafka-hs-integration.callback-lifetime.producer delivery callback releases after native finalization",+ "rdkafka-hs-integration.callback-lifetime.noncaptured control is collectible",+ "rdkafka-hs-integration.callback-lifetime.async log callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.async stats callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.sync log callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.sync stats callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.async construction failure releases callbacks: topic",+ "rdkafka-hs-integration.callback-lifetime.async construction failure releases callbacks: native",+ "rdkafka-hs-integration.callback-lifetime.async construction failure releases callbacks: redirect",+ "rdkafka-hs-integration.callback-lifetime.async construction failure releases callbacks: subscribe",+ "rdkafka-hs-integration.callback-lifetime.sync construction failure releases callbacks: topic",+ "rdkafka-hs-integration.callback-lifetime.sync construction failure releases callbacks: native",+ "rdkafka-hs-integration.callback-lifetime.sync construction failure releases callbacks: redirect",+ "rdkafka-hs-integration.callback-lifetime.sync construction failure releases callbacks: subscribe",+ "rdkafka-hs-integration.callback-lifetime.producer native construction failure releases callbacks",+ "rdkafka-hs-integration.callback-lifetime.async constructor exception at callback-install releases partial native ownership",+ "rdkafka-hs-integration.callback-lifetime.async constructor exception at post-native-loglevel releases partial native ownership",+ "rdkafka-hs-integration.callback-lifetime.sync constructor exception at callback-install releases partial native ownership",+ "rdkafka-hs-integration.callback-lifetime.sync constructor exception at post-native-loglevel releases partial native ownership",+ "rdkafka-hs-integration.callback-lifetime.async rebalance callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.async commit callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.sync rebalance callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.sync commit callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.replaced producer delivery callbacks both release",+ "rdkafka-hs-integration.callback-lifetime.async concurrent destruction joins at native entry",+ "rdkafka-hs-integration.callback-lifetime.async concurrent destruction joins at native completion",+ "rdkafka-hs-integration.callback-lifetime.async concurrent destruction joins at native shutdown callback",+ "rdkafka-hs-integration.callback-lifetime.sync concurrent destruction joins at native entry",+ "rdkafka-hs-integration.callback-lifetime.sync concurrent destruction joins at native completion",+ "rdkafka-hs-integration.callback-lifetime.sync concurrent destruction joins at native shutdown callback",+ "rdkafka-hs-integration.callback-lifetime.async cancellation at native entry preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.async cancellation at native completion preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.async cancellation at native shutdown callback preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation at native entry preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation at native completion preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation at native shutdown callback preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.async cancellation after poll stop and queue detachment preserves teardown",+ "rdkafka-hs-integration.callback-lifetime.producer constructor cancellation at partial registration releases its owner",+ "rdkafka-hs-integration.callback-lifetime.producer constructor cancellation at native acceptance releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-async constructor cancellation at partial registration releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-async constructor cancellation at native acceptance releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-sync constructor cancellation at partial registration releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-sync constructor cancellation at native acceptance releases its owner",+ "rdkafka-hs-integration.callback-lifetime.async cancellation while waiting for active callback permits retry",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation while waiting for active callback permits retry",+ "rdkafka-hs-integration.callback-lifetime.async closed consumer GC releases its registrations once",+ "rdkafka-hs-integration.callback-lifetime.sync closed consumer GC releases its registrations once",+ "rdkafka-hs-integration.callback-lifetime.producer error callback remains live through close and releases on GC",+ "rdkafka-hs-integration.callback-lifetime.producer log callback remains live through close and releases on GC",+ "rdkafka-hs-integration.callback-lifetime.producer stats callback remains live through close and releases on GC",+ "rdkafka-hs-integration.callback-lifetime.failed native construction releases the caller-owned duplicate config",+ "rdkafka-hs-integration.transaction-errors.transaction-error-leak-probe releases 300 immediate native errors",+ "rdkafka-hs-integration.transaction-errors.native allocation control detects the inherited three-error leak",+ "rdkafka-hs-integration.transaction-errors.initialization timeout destroys its native error on each retry",+ "rdkafka-hs-integration.transaction-errors.zero-timeout initialization resumes successfully against the broker",+ "rdkafka-hs-integration.transaction-errors.transaction state errors preserve empty commit and abort recovery",+ "rdkafka-hs-integration.transaction-errors.duplicate transactional IDs report a real fatal fencing error",+ "rdkafka-hs-integration.transaction-errors.broker-rejected delivery requires abort and permits a successful new transaction",+ "rdkafka-hs-integration.transaction-errors.init without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.begin without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.abort without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.commit without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.offset without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.init NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.begin NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.abort NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.commit NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.offset NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.init invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.begin invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.abort invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.commit invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.offset invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 0 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 1 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 2 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 3 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 4 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 5 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 6 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 7 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 0 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 1 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 2 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 3 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 4 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 5 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 6 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 7 before destruction",+ "rdkafka-hs-integration.transaction-errors.init cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.begin cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.abort cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 21 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 22 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 23 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 21 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 22 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 23 releases once",+ "rdkafka-hs-integration.transaction-errors.async commit publishes output and source next offset atomically; abort publishes neither",+ "rdkafka-hs-integration.transaction-errors.sync commit publishes output and source next offset atomically; abort publishes neither",+ "rdkafka-hs-integration.lifecycle.flushProducerTimeout times out, purgeProducer empties the queue",+ "rdkafka-hs-integration.lifecycle.consumerClosed is False until closeConsumer",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials replaces credentials on a consumer",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials replaces credentials on a producer",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials rejects NUL in username without changing producer or consumer identity",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials rejects NUL in password without changing producer or consumer identity",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials releases each actual native error after decoding its exact code",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials cancellation at error decoding releases the owned error",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials cancellation at error acquisition releases the owned error",+ "rdkafka-hs-integration.producer-regressions.explicit topic timeout expires an accepted message",+ "rdkafka-hs-integration.producer-regressions.global timeout still expires an accepted message",+ "rdkafka-hs-integration.producer-regressions.queue-full rejection releases callback capture without invoking it",+ "rdkafka-hs-integration.producer-regressions.accepted callback retains its capture until a purged report completes",+ "rdkafka-hs-integration.producer-regressions.throwing global callback preserves per-message delivery and releases capture",+ "rdkafka-hs-integration.producer-regressions.throwing per-message callback reports exception and releases capture",+ "rdkafka-hs-integration.producer-regressions.repeated queue-full rejections release every callback capture",+ "rdkafka-hs-integration.producer-regressions.cancellation at a rejected enqueue releases capture before unmasking",+ "rdkafka-hs-integration.producer-regressions.cancellation after native acceptance retains callback until its report",+ "rdkafka-hs-integration.producer-regressions.another poller can deliver before successful enqueue returns",+ "rdkafka-hs-integration.producer-regressions.running callback keeps its capture after the native root is released",+ "rdkafka-hs-integration.producer-regressions.native error decoding failure releases rejected callback capture",+ "rdkafka-hs-integration.producer-regressions.non-null native success-code error rejects and releases capture",+ "rdkafka-hs-integration.producer-regressions.unknown native error code is preserved instead of reading errno",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: defaults",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: global only",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: topic only",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: disjoint maps",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: explicit topic wins duplicate",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: last topic property wins",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: empty topic map preserves global",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: zero topic timeout is infinite",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: maximum native topic timeout",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: explicit topic wins native timeout alias",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: topic codec overrides global codec",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: global codec survives unrelated topic keys",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with NoCompression",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Gzip",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Snappy",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Lz4",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Zstd",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: none",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: inflight",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue+inflight",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue+nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: inflight+nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: all",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: none",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: inflight",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue+inflight",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue+nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: inflight+nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: all",+ "rdkafka-hs-integration.producer-regressions.bounded flush timeout recovers when the delayed response arrives",+ "rdkafka-hs-integration.producer-regressions.close retries a timed-out flush until the delayed delivery completes",+ "rdkafka-hs-integration.producer-regressions.oversized rejection releases capture without a delivery report",+ "rdkafka-hs-integration.producer-regressions.known invalid partition rejection releases capture",+ "rdkafka-hs-integration.producer-regressions.empty queue supports repeated flush and close",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: NUL topic name",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: NUL header name",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: maximum unrepresentable partition",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: minimum unrepresentable partition",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: unknown global key",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: unknown topic key",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: invalid topic timeout",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: excessive topic timeout",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: global-only key in topic map",+ "rdkafka-hs-integration.producer-regressions.later delivery callback replaces the earlier callback",+ "rdkafka-hs-integration.producer-regressions.null native delivery frame reports the generic errno fallback without dereferencing a message",+ "rdkafka-hs-integration.producer-regressions.native delivery without an opaque Haskell callback preserves the complete record",+ "rdkafka-hs-integration.producer-regressions.delivery header acquisition failure preserves the outcome with empty headers",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.counter detects a retained native list before explicit release",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.pair conversion failure releases the partial list before GC",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.offset conversion failure releases the partial list before GC",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.ordinary input lists release after exact native results",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.native logical offsets decode independently without losing partition identity",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.missing native partition queue preserves assignment and later forwarding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.assignment outputs release after exact decoding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.subscription outputs release after exact decoding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.subscription acquisition failure preserves the native error without a list",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.assignment decoder failure releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.subscription decoder failure releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.cancellation at input allocation releases the owned list",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.cancellation at assignment return releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.pair conversion failure releases the partial list before GC",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.offset conversion failure releases the partial list before GC",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.ordinary input lists release after exact native results",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.native logical offsets decode independently without losing partition identity",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.missing native partition queue preserves assignment and later forwarding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.assignment outputs release after exact decoding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.subscription outputs release after exact decoding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.subscription acquisition failure preserves the native error without a list",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.assignment decoder failure releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.subscription decoder failure releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.cancellation at input allocation releases the owned list",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.cancellation at assignment return releases the owned output",+ "rdkafka-hs-integration.public-contract.messages.batch conversion releases every returned native message",+ "rdkafka-hs-integration.public-contract.messages.native message counter detects a retained final object",+ "rdkafka-hs-integration.public-contract.messages.batch decoder exception releases unprocessed messages",+ "rdkafka-hs-integration.public-contract.messages.batch native header errors remain errors while later records are released",+ "rdkafka-hs-integration.public-contract.messages.batch cancellation at native return releases every acquired message",+ "rdkafka-hs-integration.public-contract.messages.batch cancellation at middle conversion releases every acquired message",+ "rdkafka-hs-integration.public-contract.messages.async single cancellation at native return releases its native message",+ "rdkafka-hs-integration.public-contract.messages.async single cancellation at inside conversion releases its native message",+ "rdkafka-hs-integration.public-contract.messages.sync single cancellation at native return releases its native message",+ "rdkafka-hs-integration.public-contract.messages.sync single cancellation at inside conversion releases its native message",+ "rdkafka-hs-integration.public-contract.messages.async header failure preserves the polled record origin",+ "rdkafka-hs-integration.public-contract.messages.sync header failure preserves the polled record origin",+ "rdkafka-hs-integration.public-contract.messages.async plain polling surfaces native header failure",+ "rdkafka-hs-integration.public-contract.messages.sync plain polling surfaces native header failure",+ "rdkafka-hs-integration.public-contract.messages.async attributed error preserves independently absent partition-and-offset",+ "rdkafka-hs-integration.public-contract.messages.async attributed error preserves independently absent offset",+ "rdkafka-hs-integration.public-contract.messages.async attributed error preserves independently absent partition",+ "rdkafka-hs-integration.public-contract.messages.sync attributed error preserves independently absent partition-and-offset",+ "rdkafka-hs-integration.public-contract.messages.sync attributed error preserves independently absent offset",+ "rdkafka-hs-integration.public-contract.messages.sync attributed error preserves independently absent partition",+ "rdkafka-hs-integration.public-contract.messages.callback-event polling cancellation releases a returned message",+ "rdkafka-hs-integration.public-contract.messages.callback buffer preserves attributed header failure",+ "rdkafka-hs-integration.public-contract.messages.callback buffer preserves plain header failure",+ "rdkafka-hs-integration.public-contract.messages.originless callback error survives seek filtering and a paused partition",+ "rdkafka-hs-integration.public-contract.messages.callback-event polling releases and discards a returned fatal frame",+ "rdkafka-hs-integration.public-contract.messages.zero batch size leaves the queued records available",+ "rdkafka-hs-integration.public-contract.messages.unsupported sync batch does not discard a record",+ "rdkafka-hs-integration.public-contract.messages.signed native batch failure preserves its error and queued data",+ "rdkafka-hs-integration.public-contract.messages.infinite batch timeout returns available records",+ "rdkafka-hs-integration.public-contract.messages.batch capacity 1 preserves complete ordered records across partial batches",+ "rdkafka-hs-integration.public-contract.messages.batch capacity 2 preserves complete ordered records across partial batches",+ "rdkafka-hs-integration.public-contract.messages.batch capacity 5 preserves complete ordered records across partial batches",+ "rdkafka-hs-integration.public-contract.messages.invalid batch array size is rejected before native acquisition: -1",+ "rdkafka-hs-integration.public-contract.messages.invalid batch array size is rejected before native acquisition: -9223372036854775808",+ "rdkafka-hs-integration.public-contract.messages.invalid batch array size is rejected before native acquisition: 9223372036854775807",+ "rdkafka-hs-integration.public-contract.messages.batch preserves complete records followed by exact partition EOF and idle timeout",+ "rdkafka-hs-integration.public-contract.messages.empty batch respects timeout 0",+ "rdkafka-hs-integration.public-contract.messages.empty batch respects timeout 100",+ "rdkafka-hs-integration.public-contract.diagnostics.supported-property print flushes and preserves the caller handle",+ "rdkafka-hs-integration.public-contract.diagnostics.client print flushes and preserves the caller handle",+ "rdkafka-hs-integration.public-contract.diagnostics.failed fdopen releases the duplicate and preserves the original",+ "rdkafka-hs-integration.public-contract.diagnostics.failed native flush is reported after closing the duplicate",+ "rdkafka-hs-integration.public-contract.diagnostics.producer configuration dumps retain exact explicit and global settings",+ "rdkafka-hs-integration.public-contract.diagnostics.producer constructor log level overrides the global property on the native client",+ "rdkafka-hs-integration.public-contract.diagnostics.consumer configuration dump preserves global settings after subscription merge",+ "rdkafka-hs-integration.public-contract.diagnostics.native dump counter detects an unreleased array",+ "rdkafka-hs-integration.public-contract.diagnostics.global cancellation at native acquisition releases its array",+ "rdkafka-hs-integration.public-contract.diagnostics.topic cancellation at native acquisition releases its array",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata counter detects an unreleased result",+ "rdkafka-hs-integration.public-contract.metadata-contract.native topic-constructor failure survives metadata convenience queries",+ "rdkafka-hs-integration.public-contract.metadata-contract.empty native metadata remains empty and releases every result",+ "rdkafka-hs-integration.public-contract.metadata-contract.timestamp lookup preserves native overall errors",+ "rdkafka-hs-integration.public-contract.metadata-contract.watermark queries preserve unknown partition errors and empty provided metadata",+ "rdkafka-hs-integration.public-contract.metadata-contract.topic identity replica sets and exact watermarks",+ "rdkafka-hs-integration.public-contract.metadata-contract.distinct native metadata fields retain exact identities and errors",+ "rdkafka-hs-integration.public-contract.metadata-contract.provided metadata preserves partition failures in convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata partition failures survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.group query timeout preserves initial metadata wait failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.missing topic errors survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.timestamp lookup distinguishes before at and after actual record times",+ "rdkafka-hs-integration.public-contract.metadata-contract.mixed timestamp request preserves native partition failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata timeouts preserve the native error",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.groups native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.async group identity lifecycle and supported native states",+ "rdkafka-hs-integration.public-contract.metadata-contract.sync group identity lifecycle and supported native states"+ ],+ "passed": 279,+ "artifacts": {+ "darwin-asan-control.log": {+ "path": "dist-compatibility/expanded-source9/darwin-asan-control.log",+ "sha256": "7d3f29e4f75b0cb43aff9c863c81300e2851c4f2b8c958b4bf8c9113b8fb00ee"+ },+ "darwin-asan-candidate.log": {+ "path": "dist-compatibility/expanded-source9/darwin-asan-candidate.log",+ "sha256": "bed5ff95177992d5ec812468fa79432c938c50d61928bb88344f2a951a4b8d36"+ },+ "darwin-native-receipt.json": {+ "path": "dist-compatibility/expanded-source9/darwin-native-receipt.json",+ "sha256": "ab74ca68a62aa0a601d7d8f6782807c46fe5437bc102430b85ea79360bbb0b83"+ }+ },+ "limitations": [+ "Matched Apple clang AddressSanitizer native runtime; deliberate invalid access aborts and candidate has no findings. Leak detection disabled: no Darwin leak-freedom claim."+ ]+ }+ ],+ "artifacts": {+ "measured": {+ "path": "docs/testing/coverage-evidence.json",+ "sha256": "9a98d410cbeb3ef8ce0e3d99f39d989dbf145ee434db9aedf7aa771c52922ffe"+ }+ },+ "evidence": "docs/testing/deferred-public-contract-evidence.json"+ },+ {+ "id": "linux-arm64-ghc9141-native2160-apache440",+ "owner": 17,+ "required": true,+ "status": "passed",+ "source": {+ "project": "mori://shinzui/rdkafka-hs",+ "candidate_fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "execution_fingerprint": "74c7156e6fee8653bcec844001fd8f95d703bcf4d8e978a857a9f8f3560b6b0a",+ "revision": "bfa4f2e plus captured source",+ "archive": {+ "path": "dist-compatibility/expanded-source9/candidate.tar.gz",+ "sha256": "a70e4839d24c5e5179ff9a8be48643951e185d604cd8ba3401587730279f3b22"+ },+ "root_file_inventory": {+ "path": "dist-compatibility/expanded-source9/root-functional-files.json",+ "sha256": "69506c90cfc124f3a175a664873f5d8b49aff62a7426265c56c3dd64fcc84c21"+ },+ "archive_file_inventory": {+ "path": "dist-compatibility/expanded-source9/phase9-functional-files.json",+ "sha256": "d0e5d59aa49833ecd1305410c839cbebdbbb418679cecc6de0c2548b142dca4b"+ },+ "archive_comparison": {+ "changed_files": [],+ "added_files": [],+ "omitted_development_files": [+ ".envrc",+ "cabal.project",+ "flake.lock",+ "flake.module.nix",+ "flake.nix",+ "justfile",+ "nix/haskell.nix",+ "nix/pre-commit.nix",+ "nix/redpanda.nix",+ "nix/treefmt.nix"+ ],+ "omitted_project_configuration": {+ "path": "cabal.project",+ "content": "packages: .\n",+ "replacement": "Cabal implicit single package in clean extraction; same package set, no solver/compiler constraints in omitted file"+ },+ "execution_fingerprint": "74c7156e6fee8653bcec844001fd8f95d703bcf4d8e978a857a9f8f3560b6b0a",+ "root_fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ "configuration_sha256": "c6c0771e7da58c35d40170db3ec18cdd2439997e223ef4c088ac3f4e793707f9"+ },+ "environment": {+ "os": "PRETTY_NAME=\"Ubuntu 24.04.5 LTS\"\nNAME=\"Ubuntu\"\nVERSION_ID=\"24.04\"\nVERSION=\"24.04.5 LTS (Noble Numbat)\"\nVERSION_CODENAME=noble\nID=ubuntu\nID_LIKE=debian\nHOME_URL=\"https://www.ubuntu.com/\"\nSUPPORT_URL=\"https://help.ubuntu.com/\"\nBUG_REPORT_URL=\"https://bugs.launchpad.net/ubuntu/\"\nPRIVACY_POLICY_URL=\"https://www.ubuntu.com/legal/terms-and-policies/privacy-policy\"\nUBUNTU_CODENAME=noble\nLOGO=ubuntu-logo",+ "kernel": "Linux 6.18.15",+ "architecture": "aarch64",+ "ghc": "9.14.1",+ "cabal": "3.16.1.0",+ "java": "openjdk 21.0.12.1 2026-08-18\nOpenJDK Runtime Environment (build 21.0.12.1+1-1-24.04.4-Ubuntu)\nOpenJDK 64-Bit Server VM (build 21.0.12.1+1-1-24.04.4-Ubuntu, mixed mode, sharing)",+ "native_version": "2.16.0",+ "broker_version": "Apache Kafka 4.4.0",+ "loaded_native_identity": {+ "observed": "(\"2.16.0\",34603263)",+ "path": "/opt/librdkafka-2.16.0/lib/librdkafka.so.1",+ "sha256": "e4ebf0b82581b51a86a0d861a90c07004b0b1fec67ab71e409b572594846154f"+ },+ "broker_topology": "Three owned combined broker/controllers for inherited cases; separate ephemeral three-node fault and one-node secure fixtures. RF3/min ISR2 on fault topics."+ },+ "test_configuration": {+ "compiler": "GHC 9.14.1",+ "native_standard": "2.16.0",+ "broker": "Apache Kafka 4.4.0",+ "kafka_home": "/opt/kafka_2.13-4.4.0",+ "cabal_flags": [+ "examples",+ "integration"+ ],+ "fixture_processes": {+ "broker": 3,+ "security": 1+ },+ "broker_callback_modes": [+ "async",+ "sync"+ ],+ "protocols": [+ "range",+ "cooperative-sticky"+ ],+ "replicated_failure_topics": {+ "replication": 3,+ "min_ISR": 2+ },+ "security": "SASL/PLAIN over verified TLS, ephemeral users/ACLs/CA; secrets intentionally absent",+ "recipes": {+ "test-integration/Kafka/Compatibility/KafkaFixture.hs": "b3ffe1aab36ba7ba8523075383228676c5f4d7e5f837592dbbb32844beab4e1a",+ "test-integration/Kafka/Compatibility/SecurityFixture.hs": "bd46bf52a1919dee7042721820365f5765cd8c787a727ee3d9b7a8e541644921",+ "test-integration/Kafka/TestEnv.hs": "f82b4306c90317e713f7de107cd7bc281626c04fd7327ae421a49de10b1dc91a"+ }+ },+ "scenarios": [+ {+ "id": "released-linux-unit-build",+ "required": true,+ "status": "passed",+ "command": [+ "cabal",+ "test",+ "rdkafka-hs-test",+ "-f",+ "integration",+ "--test-show-details=direct",+ "--test-options=--quickcheck-tests=1000 --quickcheck-replay=20261024"+ ],+ "tests": [+ "rdkafka-hs.Callback owner.bridge allocation executes masked before ownership is recorded",+ "rdkafka-hs.Callback owner.installed and replaced bridges release exactly once",+ "rdkafka-hs.Callback owner.failed native install still owns its allocated bridge",+ "rdkafka-hs.Callback owner.failed allocation has no release",+ "rdkafka-hs.Callback owner.transfer preserves a callable bridge until client release",+ "rdkafka-hs.Callback owner.transferred and released owners reject reuse before allocating",+ "rdkafka-hs.Callback owner.release retry does not repeat completed releases",+ "rdkafka-hs.Callback owner.concurrent releases join before returning",+ "rdkafka-hs.Kafka.Consumer.ConsumerProperties.the poll mode defaults to async",+ "rdkafka-hs.Kafka.Consumer.ConsumerProperties.properties composed after the poll mode keep it",+ "rdkafka-hs.Kafka.Consumer.ConsumerProperties.properties composed before the poll mode keep it",+ "rdkafka-hs.Kafka.Consumer.ConsumerProperties.a later poll mode overrides an earlier one",+ "rdkafka-hs.Kafka.Consumer.ConsumerRecordMapSpec.should extract key",+ "rdkafka-hs.Kafka.Consumer.ConsumerRecordMapSpec.should extract value",+ "rdkafka-hs.Kafka.Consumer.ConsumerRecordMapSpec.should extract both key and value",+ "rdkafka-hs.Kafka.Consumer.ConsumerRecordTraverseSpec.should sequence",+ "rdkafka-hs.Kafka.Consumer.ConsumerRecordTraverseSpec.should traverse",+ "rdkafka-hs.Kafka.Consumer.ConsumerRecordTraverseSpec.should bisequence",+ "rdkafka-hs.Kafka.Consumer.ConsumerRecordTraverseSpec.should bitraverse",+ "rdkafka-hs.Kafka.Version.linked librdkafka is at least 2.15.0",+ "rdkafka-hs.Kafka.Version.version string agrees with the version number",+ "rdkafka-hs.Kafka.Version.decodes the hex version encoding",+ "rdkafka-hs.Producer properties generated.program follows last-write semantics",+ "rdkafka-hs.Producer properties generated.configuration has left and right identity",+ "rdkafka-hs.Producer properties generated.configuration composition is associative",+ "rdkafka-hs.Producer properties generated.composition appends writes in order",+ "rdkafka-hs.Producer properties generated.unrelated keys survive a conflicting write",+ "rdkafka-hs.Producer properties generated.last explicit log level wins",+ "rdkafka-hs.Producer properties generated.fixed empty duplicate and binary text values",+ "rdkafka-hs.Public properties.consumer composition.consumer program follows independent last-write model",+ "rdkafka-hs.Public properties.consumer composition.consumer identity preserves every observable field",+ "rdkafka-hs.Public properties.consumer composition.consumer association preserves writes and poll mode",+ "rdkafka-hs.Public properties.consumer composition.consumer composition appends programs",+ "rdkafka-hs.Public properties.consumer composition.unset poll mode preserves a prior explicit mode",+ "rdkafka-hs.Public properties.consumer composition.consumer helpers write exact native property names",+ "rdkafka-hs.Public properties.subscription.subscription follows last-write properties and topic union",+ "rdkafka-hs.Public properties.subscription.subscription identity and association retain topics and properties",+ "rdkafka-hs.Public properties.subscription.subscription composition appends property writes",+ "rdkafka-hs.Public properties.subscription.later subscription reset and explicit properties win",+ "rdkafka-hs.Public properties.headers.header list round-trip preserves duplicates and binary bytes",+ "rdkafka-hs.Public properties.headers.header concatenation follows list order",+ "rdkafka-hs.Public properties.headers.headers have two identities and associative concatenation",+ "rdkafka-hs.Public properties.headers.fixed duplicate empty and binary header values",+ "rdkafka-hs.Public properties.records.record functor identity",+ "rdkafka-hs.Public properties.records.record functor composition",+ "rdkafka-hs.Public properties.records.record bifunctor identity and composition",+ "rdkafka-hs.Public properties.records.record mapping preserves origin timestamp and headers",+ "rdkafka-hs.Public properties.records.record traversal identity and failure preserve the applicative contract",+ "rdkafka-hs.Public properties.records.record traversal composition preserves nested effects",+ "rdkafka-hs.Public properties.records.record bitraversal visits key before value",+ "rdkafka-hs.Public properties.records.record bitraversal composition preserves nested effects",+ "rdkafka-hs.Public properties.records.record folds retain key and value order",+ "rdkafka-hs.Public properties.records.deprecated record mapping remains equivalent",+ "rdkafka-hs.Public properties.records.deprecated traversal helpers preserve successful effects",+ "rdkafka-hs.Public properties.records.deprecated traversal helpers preserve failed effects",+ "rdkafka-hs.Public properties.representations.text newtypes preserve arbitrary represented text",+ "rdkafka-hs.Public properties.representations.integer newtypes preserve signed machine boundaries",+ "rdkafka-hs.Public properties.representations.offset and milliseconds preserve signed 64-bit boundaries",+ "rdkafka-hs.Public properties.representations.timestamp constructors retain their represented boundary",+ "rdkafka-hs.Public properties.representations.system topic classification requires two initial underscores",+ "rdkafka-hs.Public properties.representations.fixed empty underscore and signed numeric boundaries",+ "rdkafka-hs.Public properties.version.version bytes decode independently of prerelease byte",+ "rdkafka-hs.Public properties.version.version extraction agrees with arithmetic for every Int",+ "rdkafka-hs.Public properties.version.fixed zero and full version byte boundaries",+ "rdkafka-hs.Public properties.every compression debug and log enumeration has its native spelling",+ "rdkafka-hs.Public data contracts.builders.semigroup defaults retain writes callbacks and subscription union",+ "rdkafka-hs.Public data contracts.builders.consumer builders preserve exact settings and leave other fields unset",+ "rdkafka-hs.Public data contracts.builders.producer builders preserve global versus explicit topic placement",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs.Public data contracts.representations.numeric ordering and reads agree with represented signed values",+ "rdkafka-hs.Public data contracts.representations.numeric instances preserve primitive arithmetic including boundaries",+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.consumer variants retain fields and distinguish constructors",+ "rdkafka-hs.Public data contracts.representations.producer records delivery variants and topic requests retain exact fields",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs.Public data contracts.representations.every Kafka error preserves its Exception identity and generic form",+ "rdkafka-hs.Public data contracts.all linked native errors retain sparse numeric codes names and descriptions"+ ],+ "passed": 78,+ "artifacts": {+ "phase9-unit.log": {+ "path": "dist-compatibility/expanded-source9/phase9-unit.log",+ "sha256": "1e9125e7cda4a5a18944f368fde934dc8a4b1900d981189931e1fa0632fe7f09"+ },+ "phase9-build.log": {+ "path": "dist-compatibility/expanded-source9/phase9-build.log",+ "sha256": "15848881c353039514fedb23424160586241f4cc00332ac11283b414d901675d"+ },+ "phase9-package-check.log": {+ "path": "dist-compatibility/expanded-source9/phase9-package-check.log",+ "sha256": "a19b4064f1acadadad1e1f24beae3785b778a6c5baabde7f333e4dacb7191d30"+ },+ "phase9-loaded.log": {+ "path": "dist-compatibility/expanded-source9/phase9-loaded.log",+ "sha256": "0ea352a045eddd425369467d19eef2c60d2ca235538e1335b9557897a003d120"+ },+ "phase9-version.log": {+ "path": "dist-compatibility/expanded-source9/phase9-version.log",+ "sha256": "6ec9b644a82e1dd0a2ec1c57250b4e2d3043deb9a608d8384f7ec30026876a93"+ }+ },+ "limitations": []+ },+ {+ "id": "native-ownership-diagnostics",+ "required": true,+ "status": "passed",+ "command": [+ "valgrind",+ "--suppressions=/evidence/ghc914-rts.supp",+ "--error-exitcode=99",+ "--leak-check=full",+ "--show-leak-kinds=all",+ "--errors-for-leak-kinds=definite,indirect",+ "--trace-children=yes",+ "--log-file=/evidence/native-phase9.%p.valgrind",+ "/evidence/native-phase9-binary",+ "-p",+ "/producer-regressions/ || /callback-lifetime/ || (/public-contract/ && (/messages/ || /partition-list-ownership/ || /metadata-contract/ || /diagnostics/)) || /transaction-errors/ || /lifecycle/",+ "+RTS",+ "-N2",+ "-RTS"+ ],+ "tests": [+ "rdkafka-hs-integration.callback-lifetime.async throwing error callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing log callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing stats callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing rebalance callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing commit callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing error callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing log callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing stats callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing rebalance callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing commit callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async error callback releases after destroy with retained wrapper",+ "rdkafka-hs-integration.callback-lifetime.sync error callback releases after destroy with retained wrapper",+ "rdkafka-hs-integration.callback-lifetime.producer delivery callback releases after native finalization",+ "rdkafka-hs-integration.callback-lifetime.noncaptured control is collectible",+ "rdkafka-hs-integration.callback-lifetime.async log callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.async stats callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.sync log callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.sync stats callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.async construction failure releases callbacks: topic",+ "rdkafka-hs-integration.callback-lifetime.async construction failure releases callbacks: native",+ "rdkafka-hs-integration.callback-lifetime.async construction failure releases callbacks: redirect",+ "rdkafka-hs-integration.callback-lifetime.async construction failure releases callbacks: subscribe",+ "rdkafka-hs-integration.callback-lifetime.sync construction failure releases callbacks: topic",+ "rdkafka-hs-integration.callback-lifetime.sync construction failure releases callbacks: native",+ "rdkafka-hs-integration.callback-lifetime.sync construction failure releases callbacks: redirect",+ "rdkafka-hs-integration.callback-lifetime.sync construction failure releases callbacks: subscribe",+ "rdkafka-hs-integration.callback-lifetime.producer native construction failure releases callbacks",+ "rdkafka-hs-integration.callback-lifetime.async constructor exception at callback-install releases partial native ownership",+ "rdkafka-hs-integration.callback-lifetime.async constructor exception at post-native-loglevel releases partial native ownership",+ "rdkafka-hs-integration.callback-lifetime.sync constructor exception at callback-install releases partial native ownership",+ "rdkafka-hs-integration.callback-lifetime.sync constructor exception at post-native-loglevel releases partial native ownership",+ "rdkafka-hs-integration.callback-lifetime.async rebalance callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.async commit callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.sync rebalance callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.sync commit callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.replaced producer delivery callbacks both release",+ "rdkafka-hs-integration.callback-lifetime.async concurrent destruction joins at native entry",+ "rdkafka-hs-integration.callback-lifetime.async concurrent destruction joins at native completion",+ "rdkafka-hs-integration.callback-lifetime.async concurrent destruction joins at native shutdown callback",+ "rdkafka-hs-integration.callback-lifetime.sync concurrent destruction joins at native entry",+ "rdkafka-hs-integration.callback-lifetime.sync concurrent destruction joins at native completion",+ "rdkafka-hs-integration.callback-lifetime.sync concurrent destruction joins at native shutdown callback",+ "rdkafka-hs-integration.callback-lifetime.async cancellation at native entry preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.async cancellation at native completion preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.async cancellation at native shutdown callback preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation at native entry preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation at native completion preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation at native shutdown callback preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.async cancellation after poll stop and queue detachment preserves teardown",+ "rdkafka-hs-integration.callback-lifetime.producer constructor cancellation at partial registration releases its owner",+ "rdkafka-hs-integration.callback-lifetime.producer constructor cancellation at native acceptance releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-async constructor cancellation at partial registration releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-async constructor cancellation at native acceptance releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-sync constructor cancellation at partial registration releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-sync constructor cancellation at native acceptance releases its owner",+ "rdkafka-hs-integration.callback-lifetime.async cancellation while waiting for active callback permits retry",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation while waiting for active callback permits retry",+ "rdkafka-hs-integration.callback-lifetime.async closed consumer GC releases its registrations once",+ "rdkafka-hs-integration.callback-lifetime.sync closed consumer GC releases its registrations once",+ "rdkafka-hs-integration.callback-lifetime.producer error callback remains live through close and releases on GC",+ "rdkafka-hs-integration.callback-lifetime.producer log callback remains live through close and releases on GC",+ "rdkafka-hs-integration.callback-lifetime.producer stats callback remains live through close and releases on GC",+ "rdkafka-hs-integration.callback-lifetime.failed native construction releases the caller-owned duplicate config",+ "rdkafka-hs-integration.transaction-errors.transaction-error-leak-probe releases 300 immediate native errors",+ "rdkafka-hs-integration.transaction-errors.native allocation control detects the inherited three-error leak",+ "rdkafka-hs-integration.transaction-errors.initialization timeout destroys its native error on each retry",+ "rdkafka-hs-integration.transaction-errors.zero-timeout initialization resumes successfully against the broker",+ "rdkafka-hs-integration.transaction-errors.transaction state errors preserve empty commit and abort recovery",+ "rdkafka-hs-integration.transaction-errors.duplicate transactional IDs report a real fatal fencing error",+ "rdkafka-hs-integration.transaction-errors.broker-rejected delivery requires abort and permits a successful new transaction",+ "rdkafka-hs-integration.transaction-errors.init without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.begin without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.abort without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.commit without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.offset without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.init NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.begin NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.abort NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.commit NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.offset NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.init invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.begin invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.abort invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.commit invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.offset invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 0 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 1 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 2 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 3 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 4 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 5 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 6 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 7 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 0 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 1 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 2 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 3 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 4 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 5 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 6 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 7 before destruction",+ "rdkafka-hs-integration.transaction-errors.init cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.begin cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.abort cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 21 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 22 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 23 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 21 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 22 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 23 releases once",+ "rdkafka-hs-integration.transaction-errors.async commit publishes output and source next offset atomically; abort publishes neither",+ "rdkafka-hs-integration.transaction-errors.sync commit publishes output and source next offset atomically; abort publishes neither",+ "rdkafka-hs-integration.lifecycle.flushProducerTimeout times out, purgeProducer empties the queue",+ "rdkafka-hs-integration.lifecycle.consumerClosed is False until closeConsumer",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials replaces credentials on a consumer",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials replaces credentials on a producer",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials rejects NUL in username without changing producer or consumer identity",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials rejects NUL in password without changing producer or consumer identity",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials releases each actual native error after decoding its exact code",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials cancellation at error decoding releases the owned error",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials cancellation at error acquisition releases the owned error",+ "rdkafka-hs-integration.producer-regressions.explicit topic timeout expires an accepted message",+ "rdkafka-hs-integration.producer-regressions.global timeout still expires an accepted message",+ "rdkafka-hs-integration.producer-regressions.queue-full rejection releases callback capture without invoking it",+ "rdkafka-hs-integration.producer-regressions.accepted callback retains its capture until a purged report completes",+ "rdkafka-hs-integration.producer-regressions.throwing global callback preserves per-message delivery and releases capture",+ "rdkafka-hs-integration.producer-regressions.throwing per-message callback reports exception and releases capture",+ "rdkafka-hs-integration.producer-regressions.repeated queue-full rejections release every callback capture",+ "rdkafka-hs-integration.producer-regressions.cancellation at a rejected enqueue releases capture before unmasking",+ "rdkafka-hs-integration.producer-regressions.cancellation after native acceptance retains callback until its report",+ "rdkafka-hs-integration.producer-regressions.another poller can deliver before successful enqueue returns",+ "rdkafka-hs-integration.producer-regressions.running callback keeps its capture after the native root is released",+ "rdkafka-hs-integration.producer-regressions.native error decoding failure releases rejected callback capture",+ "rdkafka-hs-integration.producer-regressions.non-null native success-code error rejects and releases capture",+ "rdkafka-hs-integration.producer-regressions.unknown native error code is preserved instead of reading errno",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: defaults",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: global only",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: topic only",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: disjoint maps",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: explicit topic wins duplicate",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: last topic property wins",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: empty topic map preserves global",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: zero topic timeout is infinite",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: maximum native topic timeout",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: explicit topic wins native timeout alias",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: topic codec overrides global codec",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: global codec survives unrelated topic keys",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with NoCompression",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Gzip",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Snappy",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Lz4",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Zstd",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: none",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: inflight",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue+inflight",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue+nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: inflight+nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: all",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: none",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: inflight",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue+inflight",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue+nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: inflight+nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: all",+ "rdkafka-hs-integration.producer-regressions.bounded flush timeout recovers when the delayed response arrives",+ "rdkafka-hs-integration.producer-regressions.close retries a timed-out flush until the delayed delivery completes",+ "rdkafka-hs-integration.producer-regressions.oversized rejection releases capture without a delivery report",+ "rdkafka-hs-integration.producer-regressions.known invalid partition rejection releases capture",+ "rdkafka-hs-integration.producer-regressions.empty queue supports repeated flush and close",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: NUL topic name",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: NUL header name",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: maximum unrepresentable partition",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: minimum unrepresentable partition",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: unknown global key",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: unknown topic key",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: invalid topic timeout",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: excessive topic timeout",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: global-only key in topic map",+ "rdkafka-hs-integration.producer-regressions.later delivery callback replaces the earlier callback",+ "rdkafka-hs-integration.producer-regressions.null native delivery frame reports the generic errno fallback without dereferencing a message",+ "rdkafka-hs-integration.producer-regressions.native delivery without an opaque Haskell callback preserves the complete record",+ "rdkafka-hs-integration.producer-regressions.delivery header acquisition failure preserves the outcome with empty headers",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.counter detects a retained native list before explicit release",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.pair conversion failure releases the partial list before GC",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.offset conversion failure releases the partial list before GC",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.ordinary input lists release after exact native results",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.native logical offsets decode independently without losing partition identity",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.missing native partition queue preserves assignment and later forwarding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.assignment outputs release after exact decoding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.subscription outputs release after exact decoding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.subscription acquisition failure preserves the native error without a list",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.assignment decoder failure releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.subscription decoder failure releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.cancellation at input allocation releases the owned list",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.cancellation at assignment return releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.pair conversion failure releases the partial list before GC",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.offset conversion failure releases the partial list before GC",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.ordinary input lists release after exact native results",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.native logical offsets decode independently without losing partition identity",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.missing native partition queue preserves assignment and later forwarding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.assignment outputs release after exact decoding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.subscription outputs release after exact decoding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.subscription acquisition failure preserves the native error without a list",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.assignment decoder failure releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.subscription decoder failure releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.cancellation at input allocation releases the owned list",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.cancellation at assignment return releases the owned output",+ "rdkafka-hs-integration.public-contract.messages.batch conversion releases every returned native message",+ "rdkafka-hs-integration.public-contract.messages.native message counter detects a retained final object",+ "rdkafka-hs-integration.public-contract.messages.batch decoder exception releases unprocessed messages",+ "rdkafka-hs-integration.public-contract.messages.batch native header errors remain errors while later records are released",+ "rdkafka-hs-integration.public-contract.messages.batch cancellation at native return releases every acquired message",+ "rdkafka-hs-integration.public-contract.messages.batch cancellation at middle conversion releases every acquired message",+ "rdkafka-hs-integration.public-contract.messages.async single cancellation at native return releases its native message",+ "rdkafka-hs-integration.public-contract.messages.async single cancellation at inside conversion releases its native message",+ "rdkafka-hs-integration.public-contract.messages.sync single cancellation at native return releases its native message",+ "rdkafka-hs-integration.public-contract.messages.sync single cancellation at inside conversion releases its native message",+ "rdkafka-hs-integration.public-contract.messages.async header failure preserves the polled record origin",+ "rdkafka-hs-integration.public-contract.messages.sync header failure preserves the polled record origin",+ "rdkafka-hs-integration.public-contract.messages.async plain polling surfaces native header failure",+ "rdkafka-hs-integration.public-contract.messages.sync plain polling surfaces native header failure",+ "rdkafka-hs-integration.public-contract.messages.async attributed error preserves independently absent partition-and-offset",+ "rdkafka-hs-integration.public-contract.messages.async attributed error preserves independently absent offset",+ "rdkafka-hs-integration.public-contract.messages.async attributed error preserves independently absent partition",+ "rdkafka-hs-integration.public-contract.messages.sync attributed error preserves independently absent partition-and-offset",+ "rdkafka-hs-integration.public-contract.messages.sync attributed error preserves independently absent offset",+ "rdkafka-hs-integration.public-contract.messages.sync attributed error preserves independently absent partition",+ "rdkafka-hs-integration.public-contract.messages.callback-event polling cancellation releases a returned message",+ "rdkafka-hs-integration.public-contract.messages.callback buffer preserves attributed header failure",+ "rdkafka-hs-integration.public-contract.messages.callback buffer preserves plain header failure",+ "rdkafka-hs-integration.public-contract.messages.originless callback error survives seek filtering and a paused partition",+ "rdkafka-hs-integration.public-contract.messages.callback-event polling releases and discards a returned fatal frame",+ "rdkafka-hs-integration.public-contract.messages.zero batch size leaves the queued records available",+ "rdkafka-hs-integration.public-contract.messages.unsupported sync batch does not discard a record",+ "rdkafka-hs-integration.public-contract.messages.signed native batch failure preserves its error and queued data",+ "rdkafka-hs-integration.public-contract.messages.infinite batch timeout returns available records",+ "rdkafka-hs-integration.public-contract.messages.batch capacity 1 preserves complete ordered records across partial batches",+ "rdkafka-hs-integration.public-contract.messages.batch capacity 2 preserves complete ordered records across partial batches",+ "rdkafka-hs-integration.public-contract.messages.batch capacity 5 preserves complete ordered records across partial batches",+ "rdkafka-hs-integration.public-contract.messages.invalid batch array size is rejected before native acquisition: -1",+ "rdkafka-hs-integration.public-contract.messages.invalid batch array size is rejected before native acquisition: -9223372036854775808",+ "rdkafka-hs-integration.public-contract.messages.invalid batch array size is rejected before native acquisition: 9223372036854775807",+ "rdkafka-hs-integration.public-contract.messages.batch preserves complete records followed by exact partition EOF and idle timeout",+ "rdkafka-hs-integration.public-contract.messages.empty batch respects timeout 0",+ "rdkafka-hs-integration.public-contract.messages.empty batch respects timeout 100",+ "rdkafka-hs-integration.public-contract.diagnostics.supported-property print flushes and preserves the caller handle",+ "rdkafka-hs-integration.public-contract.diagnostics.client print flushes and preserves the caller handle",+ "rdkafka-hs-integration.public-contract.diagnostics.failed fdopen releases the duplicate and preserves the original",+ "rdkafka-hs-integration.public-contract.diagnostics.failed native flush is reported after closing the duplicate",+ "rdkafka-hs-integration.public-contract.diagnostics.producer configuration dumps retain exact explicit and global settings",+ "rdkafka-hs-integration.public-contract.diagnostics.producer constructor log level overrides the global property on the native client",+ "rdkafka-hs-integration.public-contract.diagnostics.consumer configuration dump preserves global settings after subscription merge",+ "rdkafka-hs-integration.public-contract.diagnostics.native dump counter detects an unreleased array",+ "rdkafka-hs-integration.public-contract.diagnostics.global cancellation at native acquisition releases its array",+ "rdkafka-hs-integration.public-contract.diagnostics.topic cancellation at native acquisition releases its array",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata counter detects an unreleased result",+ "rdkafka-hs-integration.public-contract.metadata-contract.native topic-constructor failure survives metadata convenience queries",+ "rdkafka-hs-integration.public-contract.metadata-contract.empty native metadata remains empty and releases every result",+ "rdkafka-hs-integration.public-contract.metadata-contract.timestamp lookup preserves native overall errors",+ "rdkafka-hs-integration.public-contract.metadata-contract.watermark queries preserve unknown partition errors and empty provided metadata",+ "rdkafka-hs-integration.public-contract.metadata-contract.topic identity replica sets and exact watermarks",+ "rdkafka-hs-integration.public-contract.metadata-contract.distinct native metadata fields retain exact identities and errors",+ "rdkafka-hs-integration.public-contract.metadata-contract.provided metadata preserves partition failures in convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata partition failures survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.group query timeout preserves initial metadata wait failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.missing topic errors survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.timestamp lookup distinguishes before at and after actual record times",+ "rdkafka-hs-integration.public-contract.metadata-contract.mixed timestamp request preserves native partition failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata timeouts preserve the native error",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.groups native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.async group identity lifecycle and supported native states",+ "rdkafka-hs-integration.public-contract.metadata-contract.sync group identity lifecycle and supported native states"+ ],+ "passed": 279,+ "artifacts": {+ "native-phase9.log": {+ "path": "dist-compatibility/expanded-source9/native-phase9.log",+ "sha256": "951b4b7b5d1b30800ea4699fe604aaf4a9e04a5a290570ff02afc1283569faf3"+ },+ "native-invalid9.valgrind": {+ "path": "dist-compatibility/expanded-source9/native-invalid9.valgrind",+ "sha256": "c5897519cc5a1b81b9bb0abd329746f2d1e80dd3d844b43da2344def8f8f10cb"+ },+ "native-header-stock9.valgrind": {+ "path": "dist-compatibility/expanded-source9/native-header-stock9.valgrind",+ "sha256": "b30e9245641fa29f53468b1b491ad4c62436ce4502a9ad9a6579ab54b78208c6"+ },+ "native-header-mutant9.valgrind": {+ "path": "dist-compatibility/expanded-source9/native-header-mutant9.valgrind",+ "sha256": "8501cc160b066a23f74d0c79ac66f7c3a61407b5db4c61fa62dbb85bc5098337"+ },+ "phase9-diagnostic-identity.log": {+ "path": "dist-compatibility/expanded-source9/phase9-diagnostic-identity.log",+ "sha256": "b5e947e38cfa999d968be7abd53685be88beb01ac33c6191db9c34ec24554a6d"+ }+ },+ "limitations": [+ "Only detached GHC worker-thread TLS stacks remain possibly lost (304 bytes per affected child); exact GHC 9.14.1 Task.c and posix/OSThreads.c are retained. The pure forkOn baseline did not reproduce this timing-dependent TLS observation. No project/native per-client stack is suppressed.",+ "All retained stacks containing librdkafka allocation frames lead exclusively through rd_kafka_sasl_cyrus_global_init into Cyrus SASL process-global initialization. Tagged 2.16.0 source intentionally omits sasl_done because another application may share SASL. These are not per-message/client owners.",+ "Diagnostic native differs only by three private test error-flag exports; exact identity and diff are recorded."+ ]+ },+ {+ "id": "actual-nonthreaded-runtime",+ "required": true,+ "status": "passed",+ "command": [+ "/work/phase9/dist-nonthreaded/build/aarch64-linux/ghc-9.14.1/rdkafka-hs-1.0.0.1/t/rdkafka-hs-integration/build/rdkafka-hs-integration/rdkafka-hs-integration",+ "-p",+ "/runtime-contract/"+ ],+ "tests": [+ "rdkafka-hs-integration.public-contract.runtime-contract.RTS capability is observed by async construction",+ "rdkafka-hs-integration.public-contract.runtime-contract.explicit async construction checks the runtime",+ "rdkafka-hs-integration.public-contract.runtime-contract.sync subscription delivers an exact record",+ "rdkafka-hs-integration.public-contract.runtime-contract.deprecated sync runner closes after an exact record"+ ],+ "passed": 4,+ "artifacts": {+ "nonthreaded-runtime9.log": {+ "path": "dist-compatibility/expanded-source9/nonthreaded-runtime9.log",+ "sha256": "64f2de222b1848528141d2f18cf942adeedf21ade725229e19805a236d33f516"+ },+ "nonthreaded-build9.log": {+ "path": "dist-compatibility/expanded-source9/nonthreaded-build9.log",+ "sha256": "367db75d4bd65ea9f4e08a4836567f2f60183e3fa7c14595da5c79e212b3a16f"+ },+ "nonthreaded-info9.log": {+ "path": "dist-compatibility/expanded-source9/nonthreaded-info9.log",+ "sha256": "4624cb69ac272748f36b86dca2969623bb2ce1a54d2f66dbbf5226ff74f36e3d"+ }+ },+ "limitations": []+ },+ {+ "id": "apache-topic-configuration-reject",+ "required": true,+ "status": "passed",+ "command": [+ "/evidence/native-phase9-binary",+ "-p",+ "/unsupported configuration follows/"+ ],+ "tests": [+ "rdkafka-hs-integration.topic-configuration.unsupported configuration follows the declared broker policy"+ ],+ "passed": 1,+ "artifacts": {+ "apache-policy9.log": {+ "path": "dist-compatibility/expanded-source9/apache-policy9.log",+ "sha256": "619f1dacc2a5c8f5e4fa510ce8d50ef9490183a6e2a9078da8c6a023eaecec7c"+ }+ },+ "limitations": []+ }+ ],+ "artifacts": {+ "configuration.json": {+ "path": "dist-compatibility/expanded-source9/configuration.json",+ "sha256": "c6c0771e7da58c35d40170db3ec18cdd2439997e223ef4c088ac3f4e793707f9"+ },+ "qualification9-results.json": {+ "path": "dist-compatibility/expanded-source9/qualification9-results.json",+ "sha256": "e0915ee5d4e748697d3ddab61599eea0ff74ea3db67aa1ae5c4e2b747491a7d1"+ },+ "fixture-cleanup.json": {+ "path": "dist-compatibility/expanded-source9/fixture-cleanup.json",+ "sha256": "22a1434a32c0b23c77e8cb0f788c46ca45dc4129ff55add57033437db77be5aa"+ }+ },+ "diagnostic_native": {+ "path": "/opt/librdkafka-diagnostics/lib/librdkafka.so.1",+ "sha256": "c6fdc93c4cdefaeeafd8f3fc9bb0ce49cc63746d57cddbaab2839a04c23b309c",+ "source": "Same tagged 2.16.0 C bodies, linker-map change exposes exactly three private error-flag fixture setters; no opaque native layout is copied",+ "exports_diff": {+ "path": "dist-compatibility/expanded-source9/native-diagnostic-exports.diff",+ "sha256": "ff6312086bba73e0e6891060f48f02540b38174dbcbc26c080b12b8655bceafb"+ },+ "loaded_identity": {+ "path": "dist-compatibility/expanded-source9/phase9-diagnostic-identity.log",+ "sha256": "b5e947e38cfa999d968be7abd53685be88beb01ac33c6191db9c34ec24554a6d"+ }+ },+ "evidence": "docs/testing/linux-tuple-evidence.json"+ },+ {+ "id": "linux-arm64-ghc9141-native2160-apache440-18",+ "owner": 18,+ "required": true,+ "status": "passed",+ "source": {+ "project": "mori://shinzui/rdkafka-hs",+ "candidate_fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "execution_fingerprint": "74c7156e6fee8653bcec844001fd8f95d703bcf4d8e978a857a9f8f3560b6b0a",+ "revision": "bfa4f2e plus captured source",+ "archive": {+ "path": "dist-compatibility/expanded-source9/candidate.tar.gz",+ "sha256": "a70e4839d24c5e5179ff9a8be48643951e185d604cd8ba3401587730279f3b22"+ },+ "root_file_inventory": {+ "path": "dist-compatibility/expanded-source9/root-functional-files.json",+ "sha256": "69506c90cfc124f3a175a664873f5d8b49aff62a7426265c56c3dd64fcc84c21"+ },+ "archive_file_inventory": {+ "path": "dist-compatibility/expanded-source9/phase9-functional-files.json",+ "sha256": "d0e5d59aa49833ecd1305410c839cbebdbbb418679cecc6de0c2548b142dca4b"+ },+ "archive_comparison": {+ "changed_files": [],+ "added_files": [],+ "omitted_development_files": [+ ".envrc",+ "cabal.project",+ "flake.lock",+ "flake.module.nix",+ "flake.nix",+ "justfile",+ "nix/haskell.nix",+ "nix/pre-commit.nix",+ "nix/redpanda.nix",+ "nix/treefmt.nix"+ ],+ "omitted_project_configuration": {+ "path": "cabal.project",+ "content": "packages: .\n",+ "replacement": "Cabal implicit single package in clean extraction; same package set, no solver/compiler constraints in omitted file"+ },+ "execution_fingerprint": "74c7156e6fee8653bcec844001fd8f95d703bcf4d8e978a857a9f8f3560b6b0a",+ "root_fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ "configuration_sha256": "c6c0771e7da58c35d40170db3ec18cdd2439997e223ef4c088ac3f4e793707f9"+ },+ "environment": {+ "os": "PRETTY_NAME=\"Ubuntu 24.04.5 LTS\"\nNAME=\"Ubuntu\"\nVERSION_ID=\"24.04\"\nVERSION=\"24.04.5 LTS (Noble Numbat)\"\nVERSION_CODENAME=noble\nID=ubuntu\nID_LIKE=debian\nHOME_URL=\"https://www.ubuntu.com/\"\nSUPPORT_URL=\"https://help.ubuntu.com/\"\nBUG_REPORT_URL=\"https://bugs.launchpad.net/ubuntu/\"\nPRIVACY_POLICY_URL=\"https://www.ubuntu.com/legal/terms-and-policies/privacy-policy\"\nUBUNTU_CODENAME=noble\nLOGO=ubuntu-logo",+ "kernel": "Linux 6.18.15",+ "architecture": "aarch64",+ "ghc": "9.14.1",+ "cabal": "3.16.1.0",+ "java": "openjdk 21.0.12.1 2026-08-18\nOpenJDK Runtime Environment (build 21.0.12.1+1-1-24.04.4-Ubuntu)\nOpenJDK 64-Bit Server VM (build 21.0.12.1+1-1-24.04.4-Ubuntu, mixed mode, sharing)",+ "native_version": "2.16.0",+ "broker_version": "Apache Kafka 4.4.0",+ "loaded_native_identity": {+ "observed": "(\"2.16.0\",34603263)",+ "path": "/opt/librdkafka-2.16.0/lib/librdkafka.so.1",+ "sha256": "e4ebf0b82581b51a86a0d861a90c07004b0b1fec67ab71e409b572594846154f"+ },+ "broker_topology": "run-owned three-node combined broker/controllers; ephemeral loopback ports; RF3/min ISR2 fault topics"+ },+ "test_configuration": {+ "compiler": "GHC 9.14.1",+ "native_standard": "2.16.0",+ "broker": "Apache Kafka 4.4.0",+ "kafka_home": "/opt/kafka_2.13-4.4.0",+ "cabal_flags": [+ "examples",+ "integration"+ ],+ "fixture_processes": {+ "broker": 3,+ "security": 1+ },+ "broker_callback_modes": [+ "async",+ "sync"+ ],+ "protocols": [+ "range",+ "cooperative-sticky"+ ],+ "replicated_failure_topics": {+ "replication": 3,+ "min_ISR": 2+ },+ "security": "SASL/PLAIN over verified TLS, ephemeral users/ACLs/CA; secrets intentionally absent",+ "recipes": {+ "test-integration/Kafka/Compatibility/KafkaFixture.hs": "b3ffe1aab36ba7ba8523075383228676c5f4d7e5f837592dbbb32844beab4e1a",+ "test-integration/Kafka/Compatibility/SecurityFixture.hs": "bd46bf52a1919dee7042721820365f5765cd8c787a727ee3d9b7a8e541644921",+ "test-integration/Kafka/TestEnv.hs": "f82b4306c90317e713f7de107cd7bc281626c04fd7327ae421a49de10b1dc91a"+ }+ },+ "scenarios": [+ {+ "id": "distributed-failure-recovery",+ "required": true,+ "status": "passed",+ "command": [+ "/evidence/native-phase9-binary",+ "--broker-qualification"+ ],+ "tests": [+ "broker-failure.async observed leader election preserves exact records and commits",+ "broker-failure.sync observed leader election preserves exact records and commits",+ "broker-failure.eager async handoff pause seek eviction and complete outage recover exact offsets",+ "broker-failure.eager sync handoff pause seek eviction and complete outage recover exact offsets",+ "broker-failure.cooperative async handoff pause seek eviction and complete outage recover exact offsets",+ "broker-failure.cooperative sync handoff pause seek eviction and complete outage recover exact offsets",+ "broker-failure.async transaction commit timeout across full outage retries and preserves read-committed visibility",+ "broker-failure.sync transaction commit timeout across full outage retries and preserves read-committed visibility",+ "broker-failure.cancellation during complete outage restores all owned brokers"+ ],+ "passed": 9,+ "artifacts": {+ "broker-final9.log": {+ "path": "dist-compatibility/expanded-source9/broker-final9.log",+ "sha256": "f9236628ae671ffa549c4c9ce17ba8ba1acaf5f69e066acfe4ebfe94bd303681"+ },+ "broker-final9-tests.txt": {+ "path": "dist-compatibility/expanded-source9/broker-final9-tests.txt",+ "sha256": "1b2270f302280d667a9a755787ee368fce03adc8f849ef070c54f02d99919b84"+ },+ "fixture-cleanup.json": {+ "path": "dist-compatibility/expanded-source9/fixture-cleanup.json",+ "sha256": "22a1434a32c0b23c77e8cb0f788c46ca45dc4129ff55add57033437db77be5aa"+ }+ },+ "limitations": []+ }+ ],+ "artifacts": {+ "context": {+ "path": "docs/testing/broker-qualification-context.json",+ "sha256": "d080bb062d1afed7d5a5b71ab37ed9b70b83fbe114d44650253af3999cc56c36"+ }+ },+ "evidence": "docs/testing/broker-failure-evidence.json"+ },+ {+ "id": "linux-arm64-ghc9141-native2160-apache440-19",+ "owner": 19,+ "required": true,+ "status": "passed",+ "source": {+ "project": "mori://shinzui/rdkafka-hs",+ "candidate_fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "execution_fingerprint": "74c7156e6fee8653bcec844001fd8f95d703bcf4d8e978a857a9f8f3560b6b0a",+ "revision": "bfa4f2e plus captured source",+ "archive": {+ "path": "dist-compatibility/expanded-source9/candidate.tar.gz",+ "sha256": "a70e4839d24c5e5179ff9a8be48643951e185d604cd8ba3401587730279f3b22"+ },+ "root_file_inventory": {+ "path": "dist-compatibility/expanded-source9/root-functional-files.json",+ "sha256": "69506c90cfc124f3a175a664873f5d8b49aff62a7426265c56c3dd64fcc84c21"+ },+ "archive_file_inventory": {+ "path": "dist-compatibility/expanded-source9/phase9-functional-files.json",+ "sha256": "d0e5d59aa49833ecd1305410c839cbebdbbb418679cecc6de0c2548b142dca4b"+ },+ "archive_comparison": {+ "changed_files": [],+ "added_files": [],+ "omitted_development_files": [+ ".envrc",+ "cabal.project",+ "flake.lock",+ "flake.module.nix",+ "flake.nix",+ "justfile",+ "nix/haskell.nix",+ "nix/pre-commit.nix",+ "nix/redpanda.nix",+ "nix/treefmt.nix"+ ],+ "omitted_project_configuration": {+ "path": "cabal.project",+ "content": "packages: .\n",+ "replacement": "Cabal implicit single package in clean extraction; same package set, no solver/compiler constraints in omitted file"+ },+ "execution_fingerprint": "74c7156e6fee8653bcec844001fd8f95d703bcf4d8e978a857a9f8f3560b6b0a",+ "root_fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ "configuration_sha256": "c6c0771e7da58c35d40170db3ec18cdd2439997e223ef4c088ac3f4e793707f9"+ },+ "environment": {+ "os": "PRETTY_NAME=\"Ubuntu 24.04.5 LTS\"\nNAME=\"Ubuntu\"\nVERSION_ID=\"24.04\"\nVERSION=\"24.04.5 LTS (Noble Numbat)\"\nVERSION_CODENAME=noble\nID=ubuntu\nID_LIKE=debian\nHOME_URL=\"https://www.ubuntu.com/\"\nSUPPORT_URL=\"https://help.ubuntu.com/\"\nBUG_REPORT_URL=\"https://bugs.launchpad.net/ubuntu/\"\nPRIVACY_POLICY_URL=\"https://www.ubuntu.com/legal/terms-and-policies/privacy-policy\"\nUBUNTU_CODENAME=noble\nLOGO=ubuntu-logo",+ "kernel": "Linux 6.18.15",+ "architecture": "aarch64",+ "ghc": "9.14.1",+ "cabal": "3.16.1.0",+ "java": "openjdk 21.0.12.1 2026-08-18\nOpenJDK Runtime Environment (build 21.0.12.1+1-1-24.04.4-Ubuntu)\nOpenJDK 64-Bit Server VM (build 21.0.12.1+1-1-24.04.4-Ubuntu, mixed mode, sharing)",+ "native_version": "2.16.0",+ "broker_version": "Apache Kafka 4.4.0",+ "loaded_native_identity": {+ "observed": "(\"2.16.0\",34603263)",+ "path": "/opt/librdkafka-2.16.0/lib/librdkafka.so.1",+ "sha256": "e4ebf0b82581b51a86a0d861a90c07004b0b1fec67ab71e409b572594846154f"+ },+ "broker_topology": "run-owned one-node combined broker/controller; ephemeral SASL_SSL listener; verified localhost CA; ephemeral PLAIN users and ACLs"+ },+ "test_configuration": {+ "mode": "--authentication-qualification",+ "callback_modes": [+ "async",+ "sync"+ ],+ "SASL": "PLAIN",+ "security_protocol": "SASL_SSL",+ "TLS_hostname_verification": "https",+ "server_SAN": "DNS:localhost",+ "credentials": "ephemeral, local private files only",+ "authorization": "Separate original/replacement writer/reader ACLs; Describe-only denied identity; group denial audited at FindCoordinator; admin allow/deny",+ "cleanup": "Owned ProcessHandles stopped, broker state/JAAS/passwords/private keys removed, retained textual logs scanned for generated passwords"+ },+ "scenarios": [+ {+ "id": "authentication-tls-acl-reconnect",+ "required": true,+ "status": "passed",+ "command": [+ "/evidence/native-phase9-binary",+ "--authentication-qualification"+ ],+ "tests": [+ "authentication-contract.verified TLS authenticated delivery and exact consume/commit in both modes",+ "authentication-contract.authenticated identity without topic ACL receives exact produce denial",+ "authentication-contract.invalid-password producer reports the exact connection failure and no delivery",+ "authentication-contract.untrusted-CA producer reports the exact connection failure and no delivery",+ "authentication-contract.hostname-mismatch producer reports the exact connection failure and no delivery",+ "authentication-contract.invalid-password async consumer reports the exact connection failure",+ "authentication-contract.invalid-password sync consumer reports the exact connection failure",+ "authentication-contract.untrusted-CA async consumer reports the exact connection failure",+ "authentication-contract.untrusted-CA sync consumer reports the exact connection failure",+ "authentication-contract.hostname-mismatch async consumer reports the exact connection failure",+ "authentication-contract.hostname-mismatch sync consumer reports the exact connection failure",+ "authentication-contract.async exact topic/group/admin authorization denials",+ "authentication-contract.sync exact topic/group/admin authorization denials",+ "authentication-contract.producer credential replacement authenticates a new identity after observed reconnect and recovers from invalid replacement",+ "authentication-contract.async consumer credential replacement authenticates after observed reconnect and recovers from invalid replacement",+ "authentication-contract.sync consumer credential replacement authenticates after observed reconnect and recovers from invalid replacement",+ "authentication-contract.interruption destroys owned secure processes, credentials, ACL state and private keys"+ ],+ "passed": 17,+ "artifacts": {+ "authentication-final9.log": {+ "path": "dist-compatibility/expanded-source9/authentication-final9.log",+ "sha256": "a9cc23df591ca6608c613090bf42ae57ece89c1dc3e3ede7bbc0dee1cbcd2457"+ },+ "authentication-final9-tests.txt": {+ "path": "dist-compatibility/expanded-source9/authentication-final9-tests.txt",+ "sha256": "e011f6a1ed4544904bc4117ebdd30e85339b33c096b3d0619bbff506f5e2e893"+ },+ "fixture-cleanup.json": {+ "path": "dist-compatibility/expanded-source9/fixture-cleanup.json",+ "sha256": "22a1434a32c0b23c77e8cb0f788c46ca45dc4129ff55add57033437db77be5aa"+ }+ },+ "limitations": [+ "SASL PLAIN only; no other SASL mechanism claim."+ ]+ }+ ],+ "artifacts": {+ "context": {+ "path": "docs/testing/authentication-qualification-context.json",+ "sha256": "bbd1b7edc15934382e7b7f4e516ecce5688f257c0ee9eb19277e3b42ef26c730"+ }+ },+ "evidence": "docs/testing/authentication-evidence.json"+ }+ ],+ "previous_checkpoint": {+ "candidate_fingerprint": "abbf4e69f7806356c083acb0bb163c3e24f1fc7b4b1b5d78d1f469b0653a8993",+ "tuples": [+ {+ "id": "linux-arm64-ghc9141-native2160-apache440",+ "owner": 17,+ "required": true,+ "status": "in-progress",+ "source": {+ "candidate_fingerprint": "eb6352fe62c75ec289a0a5f543ed0692106d24f3370ddb46ef31f0188410b14a",+ "archive_sha256": "b02206dc4621d86226f15f6b8b88768e8e9e494b51cb13ec6746805ae1d367ba"+ },+ "planned_environment": {+ "os": "Ubuntu 24.04 Linux",+ "architecture": "aarch64",+ "ghc": "9.14.1",+ "cabal": "3.16.1.0",+ "native": "2.16.0",+ "broker": "Apache Kafka 4.4.0"+ },+ "environment": {+ "os": "PRETTY_NAME=\"Ubuntu 24.04.5 LTS\"\nNAME=\"Ubuntu\"\nVERSION_ID=\"24.04\"\nVERSION=\"24.04.5 LTS (Noble Numbat)\"\nVERSION_CODENAME=noble\nID=ubuntu\nID_LIKE=debian\nHOME_URL=\"https://www.ubuntu.com/\"\nSUPPORT_URL=\"https://help.ubuntu.com/\"\nBUG_REPORT_URL=\"https://bugs.launchpad.net/ubuntu/\"\nPRIVACY_POLICY_URL=\"https://www.ubuntu.com/legal/terms-and-policies/privacy-policy\"\nUBUNTU_CODENAME=noble\nLOGO=ubuntu-logo\n",+ "kernel": "Linux 6.18.15 aarch64",+ "architecture": "aarch64",+ "ghc": "9.14.1",+ "cabal": "3.16.1.0",+ "loaded_libraries": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/loaded-libraries.log",+ "sha256": "1eadb3fce16b3a55fd4cc4a9a27eccefc277fd3e664fd3b76c75acccfa846e3a"+ },+ "native_binary": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/native-candidate.so.1",+ "sha256": "e4ebf0b82581b51a86a0d861a90c07004b0b1fec67ab71e409b572594846154f"+ },+ "native_version": "2.16.0",+ "loaded_native_identity": {+ "version": "2.16.0",+ "number": 34603263,+ "path": "/opt/librdkafka-2.16.0/lib/librdkafka.so.1",+ "sha256": "e4ebf0b82581b51a86a0d861a90c07004b0b1fec67ab71e409b572594846154f",+ "observed": "(\"2.16.0\",34603263)"+ },+ "broker_version": "Apache Kafka 4.4.0",+ "broker_topology": "Three owned combined broker/controllers, IDs 1/2/3 on loopback 41092/42092/43092; broker default min ISR 1 for single-replica inherited fixtures; failover topic replication 3 and min ISR 2"+ },+ "test_configuration": null,+ "scenarios": [+ {+ "id": "initial-broker-smoke",+ "required": true,+ "status": "passed",+ "tests": [+ "rdkafka-hs-integration.callback-lifetime.async error callback releases after destroy with retained wrapper",+ "rdkafka-hs-integration.callback-lifetime.sync error callback releases after destroy with retained wrapper",+ "rdkafka-hs-integration.transaction-errors.transaction-error-leak-probe releases 300 immediate native errors",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.native logical offsets decode independently without losing partition identity",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.native logical offsets decode independently without losing partition identity",+ "rdkafka-hs-integration.public-contract.messages.batch capacity 1 preserves complete ordered records across partial batches",+ "rdkafka-hs-integration.public-contract.messages.batch capacity 2 preserves complete ordered records across partial batches",+ "rdkafka-hs-integration.public-contract.messages.batch capacity 5 preserves complete ordered records across partial batches",+ "rdkafka-hs-integration.public-contract.runtime-contract.RTS capability is observed by async construction",+ "rdkafka-hs-integration.public-contract.runtime-contract.explicit async construction checks the runtime",+ "rdkafka-hs-integration.public-contract.runtime-contract.sync subscription delivers an exact record",+ "rdkafka-hs-integration.public-contract.runtime-contract.deprecated sync runner closes after an exact record",+ "rdkafka-hs-integration.seek-partitions.async.single seek replays exact record",+ "rdkafka-hs-integration.seek-partitions.sync.single seek replays exact record"+ ],+ "passed": 14,+ "artifacts": {+ "linux-smoke.log": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/linux-smoke.log",+ "sha256": "424fd29085e2e6e17a8ee6f090c5c4f748b41ba3014ae05e04c63f49de4f0468"+ },+ "linux-smoke-tests.json": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/linux-smoke-tests.json",+ "sha256": "50a4991e3ba780d80bb10559cb6c2bdd713f7d081da43513b379da4c798501d5"+ },+ "loaded-native.log": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/loaded-native.log",+ "sha256": "6ec9b644a82e1dd0a2ec1c57250b4e2d3043deb9a608d8384f7ec30026876a93"+ },+ "loaded-libraries.log": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/loaded-libraries.log",+ "sha256": "1eadb3fce16b3a55fd4cc4a9a27eccefc277fd3e664fd3b76c75acccfa846e3a"+ }+ },+ "command": [+ "python3",+ "/evidence/smoke.py"+ ],+ "limitations": [+ "Initial archive only; subsequent test/probe changes require source-bound replay."+ ]+ },+ {+ "id": "complete-native-ownership-diagnostics",+ "required": true,+ "status": "in-progress",+ "limitations": "Reachable RTS/library allocations are retained separately. Complete ownership scenarios, final quiescent runner and current candidate replay remain required."+ }+ ],+ "artifacts": {},+ "remaining": [+ "Promote and replay bounded native quiescence under the final source package",+ "Run every required native ownership/header scenario with effective controls",+ "Reconcile final source/configuration and package identity with all producer children"+ ],+ "evidence": "docs/testing/linux-tuple-evidence.json"+ },+ {+ "id": "apache-distributed-failure-group-transaction",+ "owner": 18,+ "required": true,+ "status": "in-progress",+ "remaining": [+ "Leader election and exact post-failure records",+ "Bounded full outage and callback/commit/poll recovery",+ "Eager/cooperative handoff and assignmentLost True",+ "Interrupted transaction recovery and read-committed visibility",+ "Actual unknown-topic configuration rejection"+ ],+ "environment": {+ "os": "PRETTY_NAME=\"Ubuntu 24.04.5 LTS\"\nNAME=\"Ubuntu\"\nVERSION_ID=\"24.04\"\nVERSION=\"24.04.5 LTS (Noble Numbat)\"\nVERSION_CODENAME=noble\nID=ubuntu\nID_LIKE=debian\nHOME_URL=\"https://www.ubuntu.com/\"\nSUPPORT_URL=\"https://help.ubuntu.com/\"\nBUG_REPORT_URL=\"https://bugs.launchpad.net/ubuntu/\"\nPRIVACY_POLICY_URL=\"https://www.ubuntu.com/legal/terms-and-policies/privacy-policy\"\nUBUNTU_CODENAME=noble\nLOGO=ubuntu-logo\n",+ "kernel": "Linux 6.18.15 aarch64",+ "architecture": "aarch64",+ "ghc": "9.14.1",+ "cabal": "3.16.1.0",+ "loaded_libraries": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/loaded-libraries.log",+ "sha256": "1eadb3fce16b3a55fd4cc4a9a27eccefc277fd3e664fd3b76c75acccfa846e3a"+ },+ "native_binary": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/native-candidate.so.1",+ "sha256": "e4ebf0b82581b51a86a0d861a90c07004b0b1fec67ab71e409b572594846154f"+ },+ "native_version": "2.16.0",+ "loaded_native_identity": {+ "version": "2.16.0",+ "number": 34603263,+ "path": "/opt/librdkafka-2.16.0/lib/librdkafka.so.1",+ "sha256": "e4ebf0b82581b51a86a0d861a90c07004b0b1fec67ab71e409b572594846154f",+ "observed": "(\"2.16.0\",34603263)"+ },+ "broker_version": "Apache Kafka 4.4.0",+ "broker_topology": "Three owned combined broker/controllers, IDs 1/2/3 on loopback 41092/42092/43092; broker default min ISR 1 for single-replica inherited fixtures; failover topic replication 3 and min ISR 2"+ },+ "evidence": "docs/testing/broker-failure-evidence.json"+ },+ {+ "id": "sasl-tls-acl-credential-reconnect",+ "owner": 19,+ "required": true,+ "status": "passed",+ "remaining": [],+ "source": {+ "candidate_fingerprint": "abbf4e69f7806356c083acb0bb163c3e24f1fc7b4b1b5d78d1f469b0653a8993",+ "execution_fingerprint": "2571e68979f3fd59c2b2e85c07c8e986787de49042d4b7645b59b17ea240cf49",+ "revision": "e29e2f7 plus captured uncommitted source",+ "archive": {+ "path": "dist-compatibility/owned-fixture-checkpoint/candidate-phase5.tar.gz",+ "sha256": "07b996694a93bd7fd1a19d649a64c7456adc0522adc66b5d31919b232a5d7167"+ },+ "root_file_inventory": {+ "path": "dist-compatibility/owned-fixture-checkpoint/root-fingerprint-files.json",+ "sha256": "4e82164f2a0fa9c56a85c2372aaa78eb79185770a0fe22f7e94cdb8a8bda9821"+ },+ "archive_file_inventory": {+ "path": "dist-compatibility/owned-fixture-checkpoint/phase5-fingerprint-files.json",+ "sha256": "479ad262d71dd40d6edfd9c1db3069744b8e26898f8d1f588d2db08cde38bda2"+ },+ "archive_comparison": {+ "changed_files": [],+ "added_files": [],+ "omitted_development_files": [+ ".envrc",+ "flake.lock",+ "flake.module.nix",+ "flake.nix",+ "justfile",+ "nix/haskell.nix",+ "nix/pre-commit.nix",+ "nix/redpanda.nix",+ "nix/treefmt.nix"+ ]+ },+ "configuration_sha256": "029db047ce9030f57c90485d05305cee35c9031f2651304434c226d586fcb653"+ },+ "environment": {+ "os": "PRETTY_NAME=\"Ubuntu 24.04.5 LTS\"\nNAME=\"Ubuntu\"\nVERSION_ID=\"24.04\"\nVERSION=\"24.04.5 LTS (Noble Numbat)\"\nVERSION_CODENAME=noble\nID=ubuntu\nID_LIKE=debian\nHOME_URL=\"https://www.ubuntu.com/\"\nSUPPORT_URL=\"https://help.ubuntu.com/\"\nBUG_REPORT_URL=\"https://bugs.launchpad.net/ubuntu/\"\nPRIVACY_POLICY_URL=\"https://www.ubuntu.com/legal/terms-and-policies/privacy-policy\"\nUBUNTU_CODENAME=noble\nLOGO=ubuntu-logo\n",+ "kernel": "Linux 6.18.15 aarch64",+ "architecture": "aarch64",+ "ghc": "9.14.1",+ "cabal": "3.16.1.0",+ "loaded_libraries": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/loaded-libraries.log",+ "sha256": "1eadb3fce16b3a55fd4cc4a9a27eccefc277fd3e664fd3b76c75acccfa846e3a"+ },+ "native_binary": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/native-candidate.so.1",+ "sha256": "e4ebf0b82581b51a86a0d861a90c07004b0b1fec67ab71e409b572594846154f"+ },+ "native_version": "2.16.0",+ "loaded_native_identity": {+ "version": "2.16.0",+ "number": 34603263,+ "path": "/opt/librdkafka-2.16.0/lib/librdkafka.so.1",+ "sha256": "e4ebf0b82581b51a86a0d861a90c07004b0b1fec67ab71e409b572594846154f",+ "observed": "(\"2.16.0\",34603263)"+ },+ "broker_version": "Apache Kafka 4.4.0",+ "broker_topology": "One owned Apache broker/controller. Separate internal loopback health/controller listener; explicit secure public listener used by all authentication clients."+ },+ "test_configuration": {+ "mode": "--authentication-qualification",+ "callback_modes": [+ "async",+ "sync"+ ],+ "SASL": "PLAIN",+ "security_protocol": "SASL_SSL",+ "TLS_hostname_verification": "https",+ "server_SAN": "DNS:localhost",+ "credentials": "ephemeral, local private files only",+ "authorization": "Separate original/replacement writer/reader ACLs; Describe-only denied identity; group denial audited at FindCoordinator; admin allow/deny",+ "cleanup": "Owned ProcessHandles stopped, broker state/JAAS/passwords/private keys removed, retained textual logs scanned for generated passwords"+ },+ "scenarios": [+ {+ "id": "authentication-tls-acl-reconnect-interruption",+ "required": true,+ "status": "passed",+ "command": [+ "rdkafka-hs-integration",+ "--authentication-qualification"+ ],+ "tests": [+ "authentication-contract.verified TLS authenticated delivery and exact consume/commit in both modes",+ "authentication-contract.authenticated identity without topic ACL receives exact produce denial",+ "authentication-contract.invalid-password producer reports the exact connection failure and no delivery",+ "authentication-contract.untrusted-CA producer reports the exact connection failure and no delivery",+ "authentication-contract.hostname-mismatch producer reports the exact connection failure and no delivery",+ "authentication-contract.invalid-password async consumer reports the exact connection failure",+ "authentication-contract.invalid-password sync consumer reports the exact connection failure",+ "authentication-contract.untrusted-CA async consumer reports the exact connection failure",+ "authentication-contract.untrusted-CA sync consumer reports the exact connection failure",+ "authentication-contract.hostname-mismatch async consumer reports the exact connection failure",+ "authentication-contract.hostname-mismatch sync consumer reports the exact connection failure",+ "authentication-contract.async exact topic/group/admin authorization denials",+ "authentication-contract.sync exact topic/group/admin authorization denials",+ "authentication-contract.producer credential replacement authenticates a new identity after observed reconnect and recovers from invalid replacement",+ "authentication-contract.async consumer credential replacement authenticates after observed reconnect and recovers from invalid replacement",+ "authentication-contract.sync consumer credential replacement authenticates after observed reconnect and recovers from invalid replacement",+ "authentication-contract.interruption destroys owned secure processes, credentials, ACL state and private keys"+ ],+ "passed": 17,+ "artifacts": {+ "security-phase5.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/security-phase5.log",+ "sha256": "79d2d93b7ec51860ef21c0947fe4993f94a513c63e6cb84f6881b5bbea4c8810"+ },+ "security-phase5-tests.txt": {+ "path": "dist-compatibility/owned-fixture-checkpoint/security-phase5-tests.txt",+ "sha256": "e011f6a1ed4544904bc4117ebdd30e85339b33c096b3d0619bbff506f5e2e893"+ },+ "security-phase5-cleanup.txt": {+ "path": "dist-compatibility/owned-fixture-checkpoint/security-phase5-cleanup.txt",+ "sha256": "e5881de7257c9d5594697bdc4ad6628ca1c54b2ee1ddda0fa84b5b76a8f2b4b0"+ },+ "phase5-normal-ldd.txt": {+ "path": "dist-compatibility/owned-fixture-checkpoint/phase5-normal-ldd.txt",+ "sha256": "ab1041dc9d2c9d876d269ca135985451af58aa02ac61b754d8f706a2363900c3"+ }+ },+ "limitations": [+ "SASL PLAIN only; other mechanisms are not claimed tested. Original/replacement ACLs distinguish authenticated identities."+ ]+ }+ ],+ "artifacts": {+ "candidate-phase5.tar.gz": {+ "path": "dist-compatibility/owned-fixture-checkpoint/candidate-phase5.tar.gz",+ "sha256": "07b996694a93bd7fd1a19d649a64c7456adc0522adc66b5d31919b232a5d7167"+ },+ "phase5-build.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/phase5-build.log",+ "sha256": "e2cb907393ef68a061bbd2bbb2406a369de8edf14678681b69f75042d4da1b4a"+ },+ "phase5-fingerprint.txt": {+ "path": "dist-compatibility/owned-fixture-checkpoint/phase5-fingerprint.txt",+ "sha256": "11f543eac0f314bd059eed35c4e325d0ab07d4aa131424287bc3ebadaefcf66e"+ },+ "phase5-fingerprint-files.json": {+ "path": "dist-compatibility/owned-fixture-checkpoint/phase5-fingerprint-files.json",+ "sha256": "479ad262d71dd40d6edfd9c1db3069744b8e26898f8d1f588d2db08cde38bda2"+ },+ "root-fingerprint-files.json": {+ "path": "dist-compatibility/owned-fixture-checkpoint/root-fingerprint-files.json",+ "sha256": "4e82164f2a0fa9c56a85c2372aaa78eb79185770a0fe22f7e94cdb8a8bda9821"+ },+ "phase5-normal-ldd.txt": {+ "path": "dist-compatibility/owned-fixture-checkpoint/phase5-normal-ldd.txt",+ "sha256": "ab1041dc9d2c9d876d269ca135985451af58aa02ac61b754d8f706a2363900c3"+ },+ "security-phase5.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/security-phase5.log",+ "sha256": "79d2d93b7ec51860ef21c0947fe4993f94a513c63e6cb84f6881b5bbea4c8810"+ },+ "security-phase5-tests.txt": {+ "path": "dist-compatibility/owned-fixture-checkpoint/security-phase5-tests.txt",+ "sha256": "e011f6a1ed4544904bc4117ebdd30e85339b33c096b3d0619bbff506f5e2e893"+ },+ "security-phase5-cleanup.txt": {+ "path": "dist-compatibility/owned-fixture-checkpoint/security-phase5-cleanup.txt",+ "sha256": "e5881de7257c9d5594697bdc4ad6628ca1c54b2ee1ddda0fa84b5b76a8f2b4b0"+ },+ "broker-phase5.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/broker-phase5.log",+ "sha256": "172c7b476e1e4868a75c17a54226fa1f4c2b57a3e05ce2bd7c58b15f746a4570"+ },+ "broker-phase5-tests.txt": {+ "path": "dist-compatibility/owned-fixture-checkpoint/broker-phase5-tests.txt",+ "sha256": "506f5bff1a6a34e7b328321480bb5cb7fc97cfee2ca1c7864dd270e0a37e50a4"+ }+ },+ "evidence": "docs/testing/authentication-evidence.json"+ }+ ]+ }+ }+}
+ docs/testing/compiler-forwarding-coverage-audit.json view
@@ -0,0 +1,57 @@+{+ "status": "source-backed partial M3 classification; reachable handwritten bodies remain measured",+ "baseline_fingerprint": "acc3974e02bc5dfc6d23b9291a865133b52f8019dcae4783219e8763029a82de",+ "keys": [+ "Kafka.Consumer.Types:194:TopLevelBox [\"<$\"]",+ "Kafka.Consumer.Types:198:TopLevelBox [\"elem\"]",+ "Kafka.Consumer.Types:198:TopLevelBox [\"fold\"]",+ "Kafka.Consumer.Types:198:TopLevelBox [\"foldMap'\"]",+ "Kafka.Consumer.Types:198:TopLevelBox [\"foldl\"]",+ "Kafka.Consumer.Types:198:TopLevelBox [\"foldl'\"]",+ "Kafka.Consumer.Types:198:TopLevelBox [\"foldl1\"]",+ "Kafka.Consumer.Types:198:TopLevelBox [\"foldr\"]",+ "Kafka.Consumer.Types:198:TopLevelBox [\"foldr'\"]",+ "Kafka.Consumer.Types:198:TopLevelBox [\"foldr1\"]",+ "Kafka.Consumer.Types:198:TopLevelBox [\"length\"]",+ "Kafka.Consumer.Types:198:TopLevelBox [\"maximum\"]",+ "Kafka.Consumer.Types:198:TopLevelBox [\"minimum\"]",+ "Kafka.Consumer.Types:198:TopLevelBox [\"null\"]",+ "Kafka.Consumer.Types:198:TopLevelBox [\"product\"]",+ "Kafka.Consumer.Types:198:TopLevelBox [\"sum\"]",+ "Kafka.Consumer.Types:198:TopLevelBox [\"toList\"]",+ "Kafka.Consumer.Types:202:TopLevelBox [\"mapM\"]",+ "Kafka.Consumer.Types:206:TopLevelBox [\"bifold\"]",+ "Kafka.Consumer.Types:206:TopLevelBox [\"bifoldl\"]",+ "Kafka.Consumer.Types:206:TopLevelBox [\"bifoldr\"]",+ "Kafka.Internal.RdKafka:134:ExpBox False",+ "Kafka.Internal.RdKafka:134:TopLevelBox [\"metadata'RdKafkaTopicPartitionT\"]",+ "Kafka.Internal.RdKafka:135:ExpBox False",+ "Kafka.Internal.RdKafka:135:TopLevelBox [\"metadataSize'RdKafkaTopicPartitionT\"]",+ "Kafka.Internal.RdKafka:136:ExpBox False",+ "Kafka.Internal.RdKafka:136:TopLevelBox [\"opaque'RdKafkaTopicPartitionT\"]",+ "Kafka.Internal.RdKafka:165:ExpBox False",+ "Kafka.Internal.RdKafka:165:TopLevelBox [\"size'RdKafkaTopicPartitionListT\"]",+ "Kafka.Internal.RdKafka:779:ExpBox False",+ "Kafka.Internal.RdKafka:779:TopLevelBox [\"broker'RdKafkaGroupInfoT\"]",+ "Kafka.Internal.Setup:90:ExpBox False",+ "Kafka.Internal.Setup:90:TopLevelBox [\"kcfgKafkaConfPtr\"]",+ "Kafka.Internal.Setup:92:ExpBox False",+ "Kafka.Internal.Setup:92:TopLevelBox [\"kcfgMessagesQueue\"]",+ "Kafka.Internal.Setup:97:ExpBox False",+ "Kafka.Internal.Setup:97:TopLevelBox [\"kcfgLifecycle\"]",+ "Kafka.Metadata:85:ExpBox False",+ "Kafka.Metadata:85:TopLevelBox [\"woTopicName\"]",+ "Kafka.Metadata:86:ExpBox False",+ "Kafka.Metadata:86:TopLevelBox [\"woPartitionId\"]",+ "Kafka.Metadata:87:ExpBox False",+ "Kafka.Metadata:87:TopLevelBox [\"woLowWatermark\"]",+ "Kafka.Version:22:ExpBox False",+ "Kafka.Version:22:TopLevelBox [\"versionMajor\"]",+ "Kafka.Version:23:ExpBox False",+ "Kafka.Version:23:TopLevelBox [\"versionMinor\"]",+ "Kafka.Version:24:ExpBox False",+ "Kafka.Version:24:TopLevelBox [\"versionRevision\"]"+ ],+ "baseline_missing_ticks": 49,+ "proof": "Each listed selector coordinate is a record field signature with no handwritten body. Each listed class default coordinate is an instance header, while its handwritten primitive is defined on a different measured line. Public types and custom method bodies retain their independent behavior tests."+}
+ docs/testing/config-string-evidence.json view
@@ -0,0 +1,59 @@+{+ "status": "accepted scoped configuration boundary checkpoint; EP-14 incomplete",+ "fingerprint": "000e3d963e8d19e51b91212653c94fe8c24026261240d28ef0b088ffce5823d9",+ "runs": {+ "normal": {+ "log": "/tmp/rdkafka-ep14-config-normal.log",+ "sha256": "db6c272664ef38ad6319622d498bd6c56c9bcbc1ea3813ac61ab057958da150d",+ "passed": 15+ },+ "instrumented-haskell": {+ "log": "/tmp/rdkafka-ep14-config-hpc.log",+ "sha256": "255e5b8e4681146a67656c6eb82b1f8f397dd7aed10a046b78f1e452beab0142",+ "passed": 15+ },+ "instrumented-native": {+ "log": "/tmp/rdkafka-ep14-config-asan.log",+ "sha256": "c82e05416a5cd2566f9edd5ebccf9d5e71dafda5771389bd99bbbe002aee8034",+ "passed": 15+ }+ },+ "mutations": "dist-mutations/20261024T184909Z-config-42371-0/results.json",+ "compiled_mutations_caught": 2,+ "controls": 1,+ "baseline": {+ "log": "/tmp/rdkafka-ep14-config-baseline.log",+ "malformed_cases_accepted": 12,+ "fixture_correction": "The initial empty client-id expectation was wrong: native librdkafka resets an empty value to its default. This thirteenth baseline failure is excluded from library defect evidence."+ },+ "discarded_mutation_runs": [+ {+ "path": "dist-mutations/20261024T184533Z-config-29163-0",+ "reason": "Removing only topic-setter validation is redundant for producer construction because its global setter also validates the explicit topic map; this mutation survived and is not counted."+ },+ {+ "path": "dist-mutations/20261024T184719Z-config-36024-0",+ "reason": "Both compiled regressions failed as intended, but the final candidate fingerprint check rejected concurrent metadata test edits. Those edits were restored before the accepted stable-candidate rerun."+ }+ ],+ "native_library": "mori://confluentinc/librdkafka",+ "native_version": "2.15.0",+ "native_diagnostic_control": "docs/testing/callback-native-diagnostics.json",+ "leak_instrumentation": false,+ "required_checks": {+ "log": "/tmp/rdkafka-ep14-config-check.log",+ "sha256": "ca090052dd4c05c2c6cdc120a2f57bf409582f3c653982a26a736374a2ec3c2d"+ },+ "scope": [+ "Producer global/topic NUL keys and values",+ "Consumer global/subscription NUL keys and values in both callback modes",+ "Native empty client-id default, exact ordinary Unicode client-id and native unknown-key rejection"+ ],+ "remaining": "CFG inventory row is reconciled. Remaining metadata/consumer contracts, saved deprecated-seek failure, handwritten misses and EP-15 environments remain open.",+ "full_mapped": {+ "manifest": "docs/testing/coverage-evidence.json",+ "fingerprint": "d640380b9a73fdbd8dabbaa2dc7139e11f2d982a946cf35d4c6614b3f28b51e9",+ "scoped_cases": 15,+ "registered": 611+ }+}
+ docs/testing/consumer-commit-evidence.json view
@@ -0,0 +1,51 @@+{+ "status": "accepted consumer-commit checkpoint; EP-14 incomplete",+ "fingerprint": "a76469420b092749fe23814d70bf8c7246c282602e41548eb016f84a1239ce31",+ "runs": {+ "normal": {+ "log": "/tmp/rdkafka-ep14-consumer-commit-normal-accepted.log",+ "sha256": "fdbfe736df28bd4845cd9f446722c4b19612c69584149ab1b733548034f33624",+ "passed": 8+ },+ "instrumented-haskell": {+ "log": "/tmp/rdkafka-ep14-consumer-commit-hpc.log",+ "sha256": "4eb6ab315352db6714c12b82fbbfe3c2ea268f265e89306f3d5f24c905307e5f",+ "passed": 8+ },+ "instrumented-native": {+ "log": "/tmp/rdkafka-ep14-consumer-commit-asan.log",+ "sha256": "43edb74bed796878c61744be64af8dd698e60ac96d5cfb75c4763468b54ff972",+ "passed": 8+ }+ },+ "mutations": "dist-mutations/20261024T204323Z-consumer-commit-16026-0/results.json",+ "compiled_mutations_caught": 4,+ "controls": 1,+ "scope": [+ "Native async/sync argument flags observed without altering calls/results",+ "Message-next, explicit and stored/all offset commits with exact callback offsets and broker reads",+ "Empty requests and NoOffset callbacks including null/empty partition lists",+ "Mixed commit failures retain successful broker effects",+ "Absent committed partition returns Invalid without error; unavailable coordinator returns TimedOut"+ ],+ "fixture_corrections": [+ {+ "log": "/tmp/rdkafka-ep14-consumer-commit-boundaries.log",+ "reason": "The initial mixed committed-offset query expected UnknownTopicOrPart. Native OffsetFetch reports the absent rejected partition as Invalid without error. Both initial assertion failures are excluded from defect evidence."+ },+ {+ "log": "/tmp/rdkafka-ep14-consumer-commit-mutations.log",+ "reason": "The callback mutation target matched both the rebalance call and offset callback. Restrict to the offset callback declaration before accepting the rerun."+ }+ ],+ "observer": "Mode zero is passthrough observation. Modes one through six retain the existing rebalance failure controls. The native rd_kafka_commit interposer records only the actual count/async argument for the selected consumer and calls the real function unchanged.",+ "native_library": "mori://confluentinc/librdkafka",+ "native_version": "2.15.0",+ "native_diagnostic_control": "docs/testing/callback-native-diagnostics.json",+ "leak_instrumentation": false,+ "required_checks": {+ "log": "/tmp/rdkafka-ep14-consumer-commit-check.log",+ "sha256": "f5a30e0a56d3b7f933df2e9944a226e1c5e0874b7329b216d5a760e46b0c9b9c"+ },+ "remaining": "Whole-candidate inventory refresh, deprecated wrappers/examples/input boundaries, saved deprecated-seek diagnosis, remaining handwritten misses and EP-15 environments remain open."+}
+ docs/testing/consumer-edges-evidence.json view
@@ -0,0 +1,57 @@+{+ "status": "accepted consumer/metadata edge checkpoint; EP-14 incomplete",+ "fingerprint": "d31e2f8bcfa21f38e94af350e957f10da603a8f7ffb90e670fabbc2f6f5091fb",+ "runs": {+ "normal": {+ "log": "/tmp/rdkafka-ep14-consumer-edges-normal-final2.log",+ "sha256": "1341cd1a04674cfce5dfcee17f4d0a2dcd183ad5f69c8977a4184909ae35fc75",+ "passed": 101+ },+ "instrumented-haskell": {+ "log": "/tmp/rdkafka-ep14-consumer-edges-hpc-final2.log",+ "sha256": "6f9521cbb1166b94aab04ce3883b7e6a1a2160fecb3c26289f82f38ac5fda2c4",+ "passed": 101+ },+ "instrumented-native": {+ "log": "/tmp/rdkafka-ep14-consumer-edges-asan.log",+ "sha256": "e4e51b0b619a0e52d6d6eead17f3af31ff2814de6c2f76f22dd2961caafc2446",+ "passed": 101+ }+ },+ "mutations": "dist-mutations/20261024T214954Z-consumer-edges-85409-0/results.json",+ "compiled_mutations_caught": 6,+ "controls": 3,+ "scope": [+ "Fourteen added cases cover metadata constructor/empty/overall-error boundaries, asynchronous assignment errors/recovery, integer boundaries, exact multi-topic subscriptions and multi-partition commit isolation",+ "Exported raw Kafka and configuration holders work through metadata/dump typeclass instances",+ "Existing static-fencing cases retain exact fatal cause and repeated plain/attributed/batch errors with checked cleanup",+ "Fencing cases move to the independent public-contract group; their original two cases remain registered",+ "Stored offsets at or behind committed positions do not cause commit-all to rewind; callbacks retain Invalid entries and broker offsets are checked independently"+ ],+ "native_library": "mori://confluentinc/librdkafka",+ "native_version": "2.15.0",+ "leak_instrumentation": false,+ "fixture_corrections": [+ {+ "log": "/tmp/rdkafka-ep14-consumer-edges-normal.log",+ "reason": "The initial callback oracle omitted Invalid entries, and an assignmentLost snapshot after callback processing was not a valid loss-phase oracle. The failed cases do not establish library defects."+ },+ {+ "log": "/tmp/rdkafka-ep14-consumer-edges-normal-accepted.log",+ "reason": "Backward local storage does not make commit-all rewind; a known-fatal client can return Fatal during close. The fixture now preserves these native semantics and still destroys the client."+ },+ {+ "log": "/tmp/rdkafka-ep14-consumer-edges-corrected-oracles.log",+ "reason": "Static-member fatal fencing need not deliver a revocation callback. The True loss-phase case remains open under the already planned EP-15 eviction work."+ },+ {+ "log": "/tmp/rdkafka-ep14-consumer-edges-mutations.log",+ "reason": "Discarded runner attempt stopped at an unchanged commit-control failure before the native storage oracle was corrected."+ }+ ],+ "remaining": "Whole-candidate recollection/inventory and shifted coverage-exception coordinates, queue-notification fixture strength, partition-list ownership, remaining reachable misses and the saved deprecated-seek failure remain open. Actual assignment-loss True evidence and the remaining environment matrix belong to EP-15.",+ "required_checks": {+ "log": "/tmp/rdkafka-ep14-consumer-edges-check.log",+ "sha256": "8adfc119bd99bf0607771a2669b702cb18bccfb892961370c495a4c055d91544"+ }+}
+ docs/testing/consumer-state-evidence.json view
@@ -0,0 +1,60 @@+{+ "status": "accepted M2 consumer-state checkpoint; EP-14 incomplete",+ "fingerprint": "74ec9986830adf22345722247d511b7b13879c9e4d9babb1f45225765f054917",+ "runs": {+ "normal": {+ "log": "/tmp/rdkafka-ep14-state-normal.log",+ "sha256": "654fbde5fcc7bb9f14abc45bc177a32b834f79b68dd80a75f06d873138363691",+ "passed": 26,+ "seconds": 32.19+ },+ "instrumented-haskell": {+ "log": "/tmp/rdkafka-ep14-state-hpc.log",+ "sha256": "abd72e4449544d55611aacfd0bce8e7943805e2cd042868491b33c9b5473428e",+ "passed": 26,+ "seconds": 32.34+ },+ "instrumented-native": {+ "log": "/tmp/rdkafka-ep14-state-asan.log",+ "sha256": "81d5c9d70b66b5b53e3a000847341332af96e56109fdb734bb41fbac7656eefa",+ "passed": 26,+ "seconds": 31.92+ }+ },+ "mutations": "dist-mutations/20261024T161830Z-state-32071-0/results.json",+ "compiled_mutations_caught": 4,+ "controls": 1,+ "scope": [+ "assignment replacement/unassignment and exact delivery",+ "pause/resume and mixed member failures with valid member effects retained",+ "local storage versus broker commits, exact next offsets, no automatic storage",+ "position before consumption, valid unknown-position sentinel and actual native member error",+ "empty requests",+ "explicit subscription override and preservation of globally supplied topic settings",+ "real run-owned regex subscription",+ "twenty deprecated seeks per callback mode with exact record replay"+ ],+ "fixture_correction": {+ "logs": [+ "/tmp/rdkafka-ep14-state-baseline.log",+ "/tmp/rdkafka-ep14-state-after.log"+ ],+ "note": "An unknown partition number may create local native state. Corrected pause/resume/store failure cases to use an absent topic; position uses native rejection of a 513-byte topic. Preserve the legitimate invalid-offset result for an ordinary unknown position in its own case. Initial failures based on the wrong native expectation are not accepted as defect evidence."+ },+ "native_library": "mori://confluentinc/librdkafka",+ "native_version": "2.15.0",+ "native_diagnostic_control": "docs/testing/callback-native-diagnostics.json",+ "leak_instrumentation": false,+ "required_checks": "/tmp/rdkafka-ep14-state-check.log",+ "remaining": "The saved intermittent deprecated-seek failure remains unexplained. Further consumer, metadata and diagnostics contracts, full mapped coverage/inventory reconciliation and EP-15 environments remain open.",+ "full-normal": {+ "revision": "e76cbc8",+ "fingerprint": "74ec9986830adf22345722247d511b7b13879c9e4d9babb1f45225765f054917",+ "log": "/tmp/rdkafka-ep14-state-full-normal.log",+ "sha256": "a583c03a165284670ba21f35b32c972fe9334ef66a9be5ee4bcfa98cf990b297",+ "unit": 65,+ "integration": 495,+ "seconds": 222.19,+ "scope": "Binary built before the subsequent diagnostic test additions."+ }+}
+ docs/testing/coverage-classification-remap.json view
@@ -0,0 +1,337 @@+{+ "status": "source-coordinate reconciliation; current full coverage still required",+ "baseline_revision": "d466235",+ "method": "Only exact, unchanged source lines in difflib equal blocks retain classifications. Changed lines lose their old classification and require review. Historical audit manifests retain their original baseline coordinates.",+ "preserved_keys": 334,+ "moved": [+ {+ "before": "Kafka.Consumer.Convert:139:ExpBox False",+ "after": "Kafka.Consumer.Convert:138:ExpBox False"+ },+ {+ "before": "Kafka.Consumer.Convert:144:ExpBox False",+ "after": "Kafka.Consumer.Convert:143:ExpBox False"+ },+ {+ "before": "Kafka.Consumer.Convert:144:LocalBox [\"toNativeTopicPartitionListNoDispose\",\"to\"]",+ "after": "Kafka.Consumer.Convert:143:LocalBox [\"toNativeTopicPartitionListNoDispose\",\"to\"]"+ },+ {+ "before": "Kafka.Consumer.Convert:143:ExpBox False",+ "after": "Kafka.Consumer.Convert:142:ExpBox False"+ },+ {+ "before": "Kafka.Consumer.Convert:142:ExpBox False",+ "after": "Kafka.Consumer.Convert:141:ExpBox False"+ },+ {+ "before": "Kafka.Consumer.Convert:145:ExpBox False",+ "after": "Kafka.Consumer.Convert:144:ExpBox False"+ },+ {+ "before": "Kafka.Consumer.Convert:145:LocalBox [\"toNativeTopicPartitionListNoDispose\",\"tnS\"]",+ "after": "Kafka.Consumer.Convert:144:LocalBox [\"toNativeTopicPartitionListNoDispose\",\"tnS\"]"+ },+ {+ "before": "Kafka.Consumer.Convert:146:ExpBox False",+ "after": "Kafka.Consumer.Convert:145:ExpBox False"+ },+ {+ "before": "Kafka.Consumer.Convert:147:ExpBox False",+ "after": "Kafka.Consumer.Convert:146:ExpBox False"+ },+ {+ "before": "Kafka.Consumer.Convert:141:ExpBox False",+ "after": "Kafka.Consumer.Convert:140:ExpBox False"+ },+ {+ "before": "Kafka.Consumer.Convert:149:ExpBox False",+ "after": "Kafka.Consumer.Convert:148:ExpBox False"+ },+ {+ "before": "Kafka.Consumer.Convert:140:ExpBox False",+ "after": "Kafka.Consumer.Convert:139:ExpBox False"+ },+ {+ "before": "Kafka.Consumer.Convert:150:ExpBox False",+ "after": "Kafka.Consumer.Convert:149:ExpBox False"+ },+ {+ "before": "Kafka.Consumer.Convert:138:ExpBox False",+ "after": "Kafka.Consumer.Convert:137:ExpBox False"+ },+ {+ "before": "Kafka.Consumer.Convert:138:TopLevelBox [\"toNativeTopicPartitionListNoDispose\"]",+ "after": "Kafka.Consumer.Convert:137:TopLevelBox [\"toNativeTopicPartitionListNoDispose\"]"+ },+ {+ "before": "Kafka.Internal.Shared:65:ExpBox False",+ "after": "Kafka.Internal.Shared:70:ExpBox False"+ },+ {+ "before": "Kafka.Internal.Shared:66:ExpBox False",+ "after": "Kafka.Internal.Shared:71:ExpBox False"+ },+ {+ "before": "Kafka.Internal.Shared:67:ExpBox False",+ "after": "Kafka.Internal.Shared:72:ExpBox False"+ },+ {+ "before": "Kafka.Internal.Shared:67:ExpBox True",+ "after": "Kafka.Internal.Shared:72:ExpBox True"+ },+ {+ "before": "Kafka.Internal.Shared:68:ExpBox False",+ "after": "Kafka.Internal.Shared:73:ExpBox False"+ },+ {+ "before": "Kafka.Internal.Shared:68:ExpBox True",+ "after": "Kafka.Internal.Shared:73:ExpBox True"+ },+ {+ "before": "Kafka.Internal.Shared:64:ExpBox False",+ "after": "Kafka.Internal.Shared:69:ExpBox False"+ },+ {+ "before": "Kafka.Internal.Shared:64:TopLevelBox [\"throwOnError\"]",+ "after": "Kafka.Internal.Shared:69:TopLevelBox [\"throwOnError\"]"+ },+ {+ "before": "Kafka.Internal.Shared:71:ExpBox False",+ "after": "Kafka.Internal.Shared:76:ExpBox False"+ },+ {+ "before": "Kafka.Internal.Shared:72:ExpBox True",+ "after": "Kafka.Internal.Shared:77:ExpBox True"+ },+ {+ "before": "Kafka.Internal.Shared:73:ExpBox True",+ "after": "Kafka.Internal.Shared:78:ExpBox True"+ },+ {+ "before": "Kafka.Internal.Shared:71:TopLevelBox [\"hasError\"]",+ "after": "Kafka.Internal.Shared:76:TopLevelBox [\"hasError\"]"+ },+ {+ "before": "Kafka.Internal.Shared:83:ExpBox False",+ "after": "Kafka.Internal.Shared:88:ExpBox False"+ },+ {+ "before": "Kafka.Internal.Shared:84:ExpBox False",+ "after": "Kafka.Internal.Shared:89:ExpBox False"+ },+ {+ "before": "Kafka.Internal.Shared:84:ExpBox True",+ "after": "Kafka.Internal.Shared:89:ExpBox True"+ },+ {+ "before": "Kafka.Internal.Shared:85:ExpBox False",+ "after": "Kafka.Internal.Shared:90:ExpBox False"+ },+ {+ "before": "Kafka.Internal.Shared:85:ExpBox True",+ "after": "Kafka.Internal.Shared:90:ExpBox True"+ },+ {+ "before": "Kafka.Internal.Shared:83:TopLevelBox [\"kafkaErrorToEither\"]",+ "after": "Kafka.Internal.Shared:88:TopLevelBox [\"kafkaErrorToEither\"]"+ }+ ],+ "dropped": [],+ "sources": {+ "Kafka.Internal.CallbackOwner": {+ "path": "src/Kafka/Internal/CallbackOwner.hs",+ "before_sha256": "f2fc3e162b3a953838c39f6b428cb19dd94ebdccf58c8346b611016859dbd308",+ "after_sha256": "f2fc3e162b3a953838c39f6b428cb19dd94ebdccf58c8346b611016859dbd308"+ },+ "Kafka.Internal.RdKafka": {+ "path": "src/Kafka/Internal/RdKafka.chs",+ "before_sha256": "95633699b8e19f1140bdb6154a2521ab6e27902b4fda4fc1f4a60dfa89b9a991",+ "after_sha256": "95633699b8e19f1140bdb6154a2521ab6e27902b4fda4fc1f4a60dfa89b9a991"+ },+ "Kafka.Consumer.Convert": {+ "path": "src/Kafka/Consumer/Convert.hs",+ "before_sha256": "61ce0505eaa2aead929700fc60b31dcf27125c095a944f92874146c1a15091e1",+ "after_sha256": "9bf267580d3ee008308585ee061e9364a1dbc6556090d78b5e5df0ef767b9115"+ },+ "Kafka.Internal.Shared": {+ "path": "src/Kafka/Internal/Shared.hs",+ "before_sha256": "da37bdff0d9cf6bd60109b63e563e4eec0d6a2c74b251df1d2e8244756c176a7",+ "after_sha256": "80f31071820c2ead3f90f3ffd6b3275d16375fe4d11eaec01a3a617ee3cc6d7b"+ },+ "Kafka.Producer.Convert": {+ "path": "src/Kafka/Producer/Convert.hs",+ "before_sha256": "9ba868c4ea7d938ab857f2e92f1a033a633b8f7b834da58502d6fb9831f99483",+ "after_sha256": "9ba868c4ea7d938ab857f2e92f1a033a633b8f7b834da58502d6fb9831f99483"+ },+ "Kafka.Consumer.Types": {+ "path": "src/Kafka/Consumer/Types.hs",+ "before_sha256": "e815e1744538de8e2bea589d138a887b2e4e254be89d0f0103dd7cdcc75ae7a9",+ "after_sha256": "e815e1744538de8e2bea589d138a887b2e4e254be89d0f0103dd7cdcc75ae7a9"+ },+ "Kafka.Internal.Setup": {+ "path": "src/Kafka/Internal/Setup.hs",+ "before_sha256": "69ef4227adf311f7dee3ec283825d42c1e3a2561df6f66bab29d2abb8b446188",+ "after_sha256": "69ef4227adf311f7dee3ec283825d42c1e3a2561df6f66bab29d2abb8b446188"+ },+ "Kafka.Metadata": {+ "path": "src/Kafka/Metadata.hs",+ "before_sha256": "fd84532b5f4c5588a07298f9f0bc3a0d9be3bfab3bb2664687b192a927e2bb00",+ "after_sha256": "abcfd0962c104901916c4b4a456b4e99b9905ffd430b74b4e2244e5a2744512f"+ },+ "Kafka.Version": {+ "path": "src/Kafka/Version.hs",+ "before_sha256": "1731e25b9b2afade15f0018291d033d7b4527c6538b4153a337736d3ef3b07e5",+ "after_sha256": "1731e25b9b2afade15f0018291d033d7b4527c6538b4153a337736d3ef3b07e5"+ }+ },+ "continuations": [+ {+ "baseline_revision": "e29e2f7",+ "reason": "Credential NUL validation and masked native error acquisition; consumer/producer Haddock describes representability. Full diff reviewed: previously classified functions and constant/unused expressions are otherwise unchanged. No classified changed source line is renewed.",+ "preserved_keys": 367,+ "moved": [+ {+ "before": "Kafka.Internal.Shared:70:ExpBox False",+ "after": "Kafka.Internal.Shared:73:ExpBox False"+ },+ {+ "before": "Kafka.Internal.Shared:71:ExpBox False",+ "after": "Kafka.Internal.Shared:74:ExpBox False"+ },+ {+ "before": "Kafka.Internal.Shared:72:ExpBox False",+ "after": "Kafka.Internal.Shared:75:ExpBox False"+ },+ {+ "before": "Kafka.Internal.Shared:72:ExpBox True",+ "after": "Kafka.Internal.Shared:75:ExpBox True"+ },+ {+ "before": "Kafka.Internal.Shared:73:ExpBox False",+ "after": "Kafka.Internal.Shared:76:ExpBox False"+ },+ {+ "before": "Kafka.Internal.Shared:73:ExpBox True",+ "after": "Kafka.Internal.Shared:76:ExpBox True"+ },+ {+ "before": "Kafka.Internal.Shared:69:ExpBox False",+ "after": "Kafka.Internal.Shared:72:ExpBox False"+ },+ {+ "before": "Kafka.Internal.Shared:69:TopLevelBox [\"throwOnError\"]",+ "after": "Kafka.Internal.Shared:72:TopLevelBox [\"throwOnError\"]"+ },+ {+ "before": "Kafka.Internal.Shared:76:ExpBox False",+ "after": "Kafka.Internal.Shared:79:ExpBox False"+ },+ {+ "before": "Kafka.Internal.Shared:77:ExpBox True",+ "after": "Kafka.Internal.Shared:80:ExpBox True"+ },+ {+ "before": "Kafka.Internal.Shared:78:ExpBox True",+ "after": "Kafka.Internal.Shared:81:ExpBox True"+ },+ {+ "before": "Kafka.Internal.Shared:76:TopLevelBox [\"hasError\"]",+ "after": "Kafka.Internal.Shared:79:TopLevelBox [\"hasError\"]"+ },+ {+ "before": "Kafka.Internal.Shared:88:ExpBox False",+ "after": "Kafka.Internal.Shared:91:ExpBox False"+ },+ {+ "before": "Kafka.Internal.Shared:89:ExpBox False",+ "after": "Kafka.Internal.Shared:92:ExpBox False"+ },+ {+ "before": "Kafka.Internal.Shared:89:ExpBox True",+ "after": "Kafka.Internal.Shared:92:ExpBox True"+ },+ {+ "before": "Kafka.Internal.Shared:90:ExpBox False",+ "after": "Kafka.Internal.Shared:93:ExpBox False"+ },+ {+ "before": "Kafka.Internal.Shared:90:ExpBox True",+ "after": "Kafka.Internal.Shared:93:ExpBox True"+ },+ {+ "before": "Kafka.Internal.Shared:88:TopLevelBox [\"kafkaErrorToEither\"]",+ "after": "Kafka.Internal.Shared:91:TopLevelBox [\"kafkaErrorToEither\"]"+ },+ {+ "before": "Kafka.Consumer:866:ExpBox False",+ "after": "Kafka.Consumer:868:ExpBox False"+ },+ {+ "before": "Kafka.Consumer:870:ExpBox False",+ "after": "Kafka.Consumer:872:ExpBox False"+ },+ {+ "before": "Kafka.Consumer:827:ExpBox False",+ "after": "Kafka.Consumer:829:ExpBox False"+ },+ {+ "before": "Kafka.Consumer:879:ExpBox False",+ "after": "Kafka.Consumer:881:ExpBox False"+ },+ {+ "before": "Kafka.Consumer:883:ExpBox False",+ "after": "Kafka.Consumer:885:ExpBox False"+ },+ {+ "before": "Kafka.Consumer:524:ExpBox False",+ "after": "Kafka.Consumer:526:ExpBox False"+ },+ {+ "before": "Kafka.Consumer:765:BinBox GuardBinBox False",+ "after": "Kafka.Consumer:767:BinBox GuardBinBox False"+ },+ {+ "before": "Kafka.Internal.Shared:159:BinBox GuardBinBox False",+ "after": "Kafka.Internal.Shared:162:BinBox GuardBinBox False"+ },+ {+ "before": "Kafka.Internal.Shared:171:BinBox GuardBinBox False",+ "after": "Kafka.Internal.Shared:174:BinBox GuardBinBox False"+ },+ {+ "before": "Kafka.Producer:290:BinBox GuardBinBox False",+ "after": "Kafka.Producer:292:BinBox GuardBinBox False"+ }+ ],+ "dropped": [],+ "sources": {+ "src/Kafka/Internal/RdKafka.chs": {+ "previous_sha256": "95633699b8e19f1140bdb6154a2521ab6e27902b4fda4fc1f4a60dfa89b9a991",+ "sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "src/Kafka/Internal/Shared.hs": {+ "previous_sha256": "80f31071820c2ead3f90f3ffd6b3275d16375fe4d11eaec01a3a617ee3cc6d7b",+ "sha256": "fb9eb7755af2a3da0db73b665a0e09a7c6ee3b1381aaac9e658a78f1ebd7e100"+ },+ "src/Kafka/Consumer.hs": {+ "previous_sha256": "66c4a21584ca6681523cd415be01f9ceb4cd8df13184bb884b70d6670050e39d",+ "sha256": "170ea8259f8b0279db807c48799f323a268e7636efcbc929ade003cd4e4bb70a"+ },+ "src/Kafka/Producer.hs": {+ "previous_sha256": "b433ed35ead2ec4504d3c392eb8f8958e23c4ceb83b9411682a71b3a30c9beb0",+ "sha256": "cce48116f5c80ea4c7d3c2af3bc3723e3e19dfd14c3c4a362a166c18201f93fc"+ }+ }+ },+ {+ "from_revision": "bfa4f2e",+ "method": "Renew only exact unchanged source lines in SequenceMatcher equal blocks; arbitrary rebalance error branch changed and has no inherited exemption.",+ "renewed_source_keys": [+ "Kafka.Consumer.Callbacks:100:ExpBox False"+ ],+ "moved": [],+ "dropped": []+ }+ ]+}
+ docs/testing/coverage-evidence.json view
@@ -0,0 +1,28991 @@+{+ "test_configuration": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ },+ "schema_version": 1,+ "revision": "bfa4f2ea641272ae71c7a3afa0fd056bb1add407",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "at": "2026-10-25T02:44:33.486542+00:00",+ "command": [+ "cabal",+ "test",+ "rdkafka-hs-test",+ "rdkafka-hs-integration",+ "-f",+ "integration",+ "--enable-coverage",+ "--builddir=dist-coverage",+ "--ghc-options=-fforce-recomp -F -pgmF scripts/coverage-preprocess.py",+ "--test-show-details=direct",+ "--test-options=--quickcheck-tests=1000 --quickcheck-replay=20261024"+ ],+ "suites": [+ "rdkafka-hs-test",+ "rdkafka-hs-integration"+ ],+ "tests": [+ "rdkafka-hs.Callback owner.bridge allocation executes masked before ownership is recorded",+ "rdkafka-hs.Callback owner.installed and replaced bridges release exactly once",+ "rdkafka-hs.Callback owner.failed native install still owns its allocated bridge",+ "rdkafka-hs.Callback owner.failed allocation has no release",+ "rdkafka-hs.Callback owner.transfer preserves a callable bridge until client release",+ "rdkafka-hs.Callback owner.transferred and released owners reject reuse before allocating",+ "rdkafka-hs.Callback owner.release retry does not repeat completed releases",+ "rdkafka-hs.Callback owner.concurrent releases join before returning",+ "rdkafka-hs.Kafka.Consumer.ConsumerProperties.the poll mode defaults to async",+ "rdkafka-hs.Kafka.Consumer.ConsumerProperties.properties composed after the poll mode keep it",+ "rdkafka-hs.Kafka.Consumer.ConsumerProperties.properties composed before the poll mode keep it",+ "rdkafka-hs.Kafka.Consumer.ConsumerProperties.a later poll mode overrides an earlier one",+ "rdkafka-hs.Kafka.Consumer.ConsumerRecordMapSpec.should extract key",+ "rdkafka-hs.Kafka.Consumer.ConsumerRecordMapSpec.should extract value",+ "rdkafka-hs.Kafka.Consumer.ConsumerRecordMapSpec.should extract both key and value",+ "rdkafka-hs.Kafka.Consumer.ConsumerRecordTraverseSpec.should sequence",+ "rdkafka-hs.Kafka.Consumer.ConsumerRecordTraverseSpec.should traverse",+ "rdkafka-hs.Kafka.Consumer.ConsumerRecordTraverseSpec.should bisequence",+ "rdkafka-hs.Kafka.Consumer.ConsumerRecordTraverseSpec.should bitraverse",+ "rdkafka-hs.Kafka.Version.linked librdkafka is at least 2.15.0",+ "rdkafka-hs.Kafka.Version.version string agrees with the version number",+ "rdkafka-hs.Kafka.Version.decodes the hex version encoding",+ "rdkafka-hs.Producer properties generated.program follows last-write semantics",+ "rdkafka-hs.Producer properties generated.configuration has left and right identity",+ "rdkafka-hs.Producer properties generated.configuration composition is associative",+ "rdkafka-hs.Producer properties generated.composition appends writes in order",+ "rdkafka-hs.Producer properties generated.unrelated keys survive a conflicting write",+ "rdkafka-hs.Producer properties generated.last explicit log level wins",+ "rdkafka-hs.Producer properties generated.fixed empty duplicate and binary text values",+ "rdkafka-hs.Public properties.consumer composition.consumer program follows independent last-write model",+ "rdkafka-hs.Public properties.consumer composition.consumer identity preserves every observable field",+ "rdkafka-hs.Public properties.consumer composition.consumer association preserves writes and poll mode",+ "rdkafka-hs.Public properties.consumer composition.consumer composition appends programs",+ "rdkafka-hs.Public properties.consumer composition.unset poll mode preserves a prior explicit mode",+ "rdkafka-hs.Public properties.consumer composition.consumer helpers write exact native property names",+ "rdkafka-hs.Public properties.subscription.subscription follows last-write properties and topic union",+ "rdkafka-hs.Public properties.subscription.subscription identity and association retain topics and properties",+ "rdkafka-hs.Public properties.subscription.subscription composition appends property writes",+ "rdkafka-hs.Public properties.subscription.later subscription reset and explicit properties win",+ "rdkafka-hs.Public properties.headers.header list round-trip preserves duplicates and binary bytes",+ "rdkafka-hs.Public properties.headers.header concatenation follows list order",+ "rdkafka-hs.Public properties.headers.headers have two identities and associative concatenation",+ "rdkafka-hs.Public properties.headers.fixed duplicate empty and binary header values",+ "rdkafka-hs.Public properties.records.record functor identity",+ "rdkafka-hs.Public properties.records.record functor composition",+ "rdkafka-hs.Public properties.records.record bifunctor identity and composition",+ "rdkafka-hs.Public properties.records.record mapping preserves origin timestamp and headers",+ "rdkafka-hs.Public properties.records.record traversal identity and failure preserve the applicative contract",+ "rdkafka-hs.Public properties.records.record traversal composition preserves nested effects",+ "rdkafka-hs.Public properties.records.record bitraversal visits key before value",+ "rdkafka-hs.Public properties.records.record bitraversal composition preserves nested effects",+ "rdkafka-hs.Public properties.records.record folds retain key and value order",+ "rdkafka-hs.Public properties.records.deprecated record mapping remains equivalent",+ "rdkafka-hs.Public properties.records.deprecated traversal helpers preserve successful effects",+ "rdkafka-hs.Public properties.records.deprecated traversal helpers preserve failed effects",+ "rdkafka-hs.Public properties.representations.text newtypes preserve arbitrary represented text",+ "rdkafka-hs.Public properties.representations.integer newtypes preserve signed machine boundaries",+ "rdkafka-hs.Public properties.representations.offset and milliseconds preserve signed 64-bit boundaries",+ "rdkafka-hs.Public properties.representations.timestamp constructors retain their represented boundary",+ "rdkafka-hs.Public properties.representations.system topic classification requires two initial underscores",+ "rdkafka-hs.Public properties.representations.fixed empty underscore and signed numeric boundaries",+ "rdkafka-hs.Public properties.version.version bytes decode independently of prerelease byte",+ "rdkafka-hs.Public properties.version.version extraction agrees with arithmetic for every Int",+ "rdkafka-hs.Public properties.version.fixed zero and full version byte boundaries",+ "rdkafka-hs.Public properties.every compression debug and log enumeration has its native spelling",+ "rdkafka-hs.Public data contracts.builders.semigroup defaults retain writes callbacks and subscription union",+ "rdkafka-hs.Public data contracts.builders.consumer builders preserve exact settings and leave other fields unset",+ "rdkafka-hs.Public data contracts.builders.producer builders preserve global versus explicit topic placement",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs.Public data contracts.representations.numeric ordering and reads agree with represented signed values",+ "rdkafka-hs.Public data contracts.representations.numeric instances preserve primitive arithmetic including boundaries",+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.consumer variants retain fields and distinguish constructors",+ "rdkafka-hs.Public data contracts.representations.producer records delivery variants and topic requests retain exact fields",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs.Public data contracts.representations.every Kafka error preserves its Exception identity and generic form",+ "rdkafka-hs.Public data contracts.all linked native errors retain sparse numeric codes names and descriptions",+ "rdkafka-hs-integration.Fixture error controls.immediate enqueue rejection propagates",+ "rdkafka-hs-integration.Fixture error controls.delivery failure propagates",+ "rdkafka-hs-integration.Fixture error controls.flush failure propagates",+ "rdkafka-hs-integration.Fixture error controls.missing delivery callback fails",+ "rdkafka-hs-integration.Fixture error controls.wrong delivery identity fails",+ "rdkafka-hs-integration.Fixture error controls.matching delivery succeeds",+ "rdkafka-hs-integration.Fixture error controls.unexpected poll error propagates",+ "rdkafka-hs-integration.Fixture error controls.missing record fails",+ "rdkafka-hs-integration.Fixture error controls.extra record fails",+ "rdkafka-hs-integration.Fixture error controls.idle before exact records is retried",+ "rdkafka-hs-integration.Fixture error controls.partial setup releases first resource",+ "rdkafka-hs-integration.Fixture error controls.interrupted partial setup releases first resource",+ "rdkafka-hs-integration.Fixture error controls.weak control retains while rooted and collects after release",+ "rdkafka-hs-integration.configuration.defaults to the private broker",+ "rdkafka-hs-integration.configuration.accepts another private endpoint",+ "rdkafka-hs-integration.configuration.accepts a list of private endpoints",+ "rdkafka-hs-integration.configuration.rejects an empty value",+ "rdkafka-hs-integration.configuration.rejects localhost:9092",+ "rdkafka-hs-integration.configuration.rejects 127.0.0.1:9092",+ "rdkafka-hs-integration.configuration.rejects [::1]:9092",+ "rdkafka-hs-integration.configuration.rejects a loopback host without a port",+ "rdkafka-hs-integration.configuration.rejects the shared broker anywhere in a list",+ "rdkafka-hs-integration.callback-lifetime.async throwing error callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing log callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing stats callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing rebalance callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing commit callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing error callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing log callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing stats callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing rebalance callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing commit callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async error callback releases after destroy with retained wrapper",+ "rdkafka-hs-integration.callback-lifetime.sync error callback releases after destroy with retained wrapper",+ "rdkafka-hs-integration.callback-lifetime.producer delivery callback releases after native finalization",+ "rdkafka-hs-integration.callback-lifetime.noncaptured control is collectible",+ "rdkafka-hs-integration.callback-lifetime.async log callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.async stats callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.sync log callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.sync stats callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.async construction failure releases callbacks: topic",+ "rdkafka-hs-integration.callback-lifetime.async construction failure releases callbacks: native",+ "rdkafka-hs-integration.callback-lifetime.async construction failure releases callbacks: redirect",+ "rdkafka-hs-integration.callback-lifetime.async construction failure releases callbacks: subscribe",+ "rdkafka-hs-integration.callback-lifetime.sync construction failure releases callbacks: topic",+ "rdkafka-hs-integration.callback-lifetime.sync construction failure releases callbacks: native",+ "rdkafka-hs-integration.callback-lifetime.sync construction failure releases callbacks: redirect",+ "rdkafka-hs-integration.callback-lifetime.sync construction failure releases callbacks: subscribe",+ "rdkafka-hs-integration.callback-lifetime.producer native construction failure releases callbacks",+ "rdkafka-hs-integration.callback-lifetime.async constructor exception at callback-install releases partial native ownership",+ "rdkafka-hs-integration.callback-lifetime.async constructor exception at post-native-loglevel releases partial native ownership",+ "rdkafka-hs-integration.callback-lifetime.sync constructor exception at callback-install releases partial native ownership",+ "rdkafka-hs-integration.callback-lifetime.sync constructor exception at post-native-loglevel releases partial native ownership",+ "rdkafka-hs-integration.callback-lifetime.async rebalance callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.async commit callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.sync rebalance callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.sync commit callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.replaced producer delivery callbacks both release",+ "rdkafka-hs-integration.callback-lifetime.async concurrent destruction joins at native entry",+ "rdkafka-hs-integration.callback-lifetime.async concurrent destruction joins at native completion",+ "rdkafka-hs-integration.callback-lifetime.async concurrent destruction joins at native shutdown callback",+ "rdkafka-hs-integration.callback-lifetime.sync concurrent destruction joins at native entry",+ "rdkafka-hs-integration.callback-lifetime.sync concurrent destruction joins at native completion",+ "rdkafka-hs-integration.callback-lifetime.sync concurrent destruction joins at native shutdown callback",+ "rdkafka-hs-integration.callback-lifetime.async cancellation at native entry preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.async cancellation at native completion preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.async cancellation at native shutdown callback preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation at native entry preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation at native completion preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation at native shutdown callback preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.async cancellation after poll stop and queue detachment preserves teardown",+ "rdkafka-hs-integration.callback-lifetime.producer constructor cancellation at partial registration releases its owner",+ "rdkafka-hs-integration.callback-lifetime.producer constructor cancellation at native acceptance releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-async constructor cancellation at partial registration releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-async constructor cancellation at native acceptance releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-sync constructor cancellation at partial registration releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-sync constructor cancellation at native acceptance releases its owner",+ "rdkafka-hs-integration.callback-lifetime.async cancellation while waiting for active callback permits retry",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation while waiting for active callback permits retry",+ "rdkafka-hs-integration.callback-lifetime.async closed consumer GC releases its registrations once",+ "rdkafka-hs-integration.callback-lifetime.sync closed consumer GC releases its registrations once",+ "rdkafka-hs-integration.callback-lifetime.producer error callback remains live through close and releases on GC",+ "rdkafka-hs-integration.callback-lifetime.producer log callback remains live through close and releases on GC",+ "rdkafka-hs-integration.callback-lifetime.producer stats callback remains live through close and releases on GC",+ "rdkafka-hs-integration.callback-lifetime.failed native construction releases the caller-owned duplicate config",+ "rdkafka-hs-integration.transaction-errors.transaction-error-leak-probe releases 300 immediate native errors",+ "rdkafka-hs-integration.transaction-errors.native allocation control detects the inherited three-error leak",+ "rdkafka-hs-integration.transaction-errors.initialization timeout destroys its native error on each retry",+ "rdkafka-hs-integration.transaction-errors.zero-timeout initialization resumes successfully against the broker",+ "rdkafka-hs-integration.transaction-errors.transaction state errors preserve empty commit and abort recovery",+ "rdkafka-hs-integration.transaction-errors.duplicate transactional IDs report a real fatal fencing error",+ "rdkafka-hs-integration.transaction-errors.broker-rejected delivery requires abort and permits a successful new transaction",+ "rdkafka-hs-integration.transaction-errors.init without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.begin without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.abort without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.commit without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.offset without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.init NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.begin NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.abort NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.commit NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.offset NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.init invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.begin invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.abort invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.commit invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.offset invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 0 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 1 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 2 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 3 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 4 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 5 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 6 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 7 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 0 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 1 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 2 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 3 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 4 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 5 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 6 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 7 before destruction",+ "rdkafka-hs-integration.transaction-errors.init cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.begin cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.abort cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 21 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 22 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 23 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 21 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 22 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 23 releases once",+ "rdkafka-hs-integration.transaction-errors.async commit publishes output and source next offset atomically; abort publishes neither",+ "rdkafka-hs-integration.transaction-errors.sync commit publishes output and source next offset atomically; abort publishes neither",+ "rdkafka-hs-integration.lifecycle.flushProducerTimeout times out, purgeProducer empties the queue",+ "rdkafka-hs-integration.lifecycle.consumerClosed is False until closeConsumer",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials replaces credentials on a consumer",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials replaces credentials on a producer",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials rejects NUL in username without changing producer or consumer identity",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials rejects NUL in password without changing producer or consumer identity",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials releases each actual native error after decoding its exact code",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials cancellation at error decoding releases the owned error",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials cancellation at error acquisition releases the owned error",+ "rdkafka-hs-integration.topic-configuration.singleton configuration reaches the broker",+ "rdkafka-hs-integration.topic-configuration.native allocation control detects a retained request",+ "rdkafka-hs-integration.topic-configuration.setter rejection releases allocated request before submission",+ "rdkafka-hs-integration.topic-configuration.interruption after allocation releases request before submission",+ "rdkafka-hs-integration.topic-configuration.multiple configuration entries reach the broker",+ "rdkafka-hs-integration.topic-configuration.broker-rejected values release requests and response events repeatedly",+ "rdkafka-hs-integration.topic-configuration.mismatched topic in an error response cannot report another topic's error",+ "rdkafka-hs-integration.topic-configuration.unrepresentable partition count never wraps to broker defaults",+ "rdkafka-hs-integration.topic-configuration.NUL in a topic name never creates a truncated topic",+ "rdkafka-hs-integration.topic-configuration.unresponsive broker preserves the native timeout error",+ "rdkafka-hs-integration.topic-configuration.empty configuration creates a usable topic",+ "rdkafka-hs-integration.topic-configuration.later setter rejection releases partially configured request",+ "rdkafka-hs-integration.topic-configuration.duplicate creation preserves the existing topic",+ "rdkafka-hs-integration.topic-configuration.deletion removes exactly the existing topic",+ "rdkafka-hs-integration.topic-configuration.missing topic deletion preserves its error and releases the request",+ "rdkafka-hs-integration.topic-configuration.NUL deletion cannot remove a truncated victim name",+ "rdkafka-hs-integration.topic-configuration.broker default partition and replication counts remain supported",+ "rdkafka-hs-integration.topic-configuration.replication above the available broker count is rejected",+ "rdkafka-hs-integration.topic-configuration.unsupported configuration follows the declared broker policy",+ "rdkafka-hs-integration.topic-configuration.minimum unrepresentable partition count is rejected",+ "rdkafka-hs-integration.topic-configuration.maximum unrepresentable replication count is rejected",+ "rdkafka-hs-integration.topic-configuration.minimum unrepresentable replication count is rejected",+ "rdkafka-hs-integration.topic-configuration.NUL configuration key is rejected before native allocation",+ "rdkafka-hs-integration.topic-configuration.NUL configuration value is rejected before native allocation",+ "rdkafka-hs-integration.topic-configuration.negative invalid partition count retains native validation",+ "rdkafka-hs-integration.topic-configuration.maximum C partition count retains native validation",+ "rdkafka-hs-integration.topic-configuration.negative invalid replication count retains native validation",+ "rdkafka-hs-integration.topic-configuration.maximum C replication count retains native validation",+ "rdkafka-hs-integration.topic-configuration.empty topic name is rejected by the broker",+ "rdkafka-hs-integration.topic-configuration.space in a topic name is rejected by the broker",+ "rdkafka-hs-integration.topic-configuration.overlong topic name is rejected by the broker",+ "rdkafka-hs-integration.topic-configuration.zero partition count is rejected by the broker",+ "rdkafka-hs-integration.topic-configuration.zero replication count is rejected by the broker",+ "rdkafka-hs-integration.topic-configuration.wrong event type fails and releases its event",+ "rdkafka-hs-integration.topic-configuration.empty response fails and releases its event",+ "rdkafka-hs-integration.topic-configuration.wrong topic response cannot report success",+ "rdkafka-hs-integration.topic-configuration.missing polled event reports a timeout",+ "rdkafka-hs-integration.topic-configuration.delayed response succeeds with balanced ownership",+ "rdkafka-hs-integration.topic-configuration.consumer administration applies settings in async mode",+ "rdkafka-hs-integration.topic-configuration.consumer administration applies settings in sync mode",+ "rdkafka-hs-integration.topic-configuration.consumer administration applies settings in async-closed mode",+ "rdkafka-hs-integration.topic-configuration.consumer administration applies settings in sync-closed mode",+ "rdkafka-hs-integration.topic-configuration.concurrent requests keep their own queues and responses",+ "rdkafka-hs-integration.topic-configuration.unresponsive deletion preserves the native timeout error",+ "rdkafka-hs-integration.topic-configuration.deletion rejects a wrong event type and releases it",+ "rdkafka-hs-integration.topic-configuration.deletion rejects an empty result and releases its event",+ "rdkafka-hs-integration.topic-configuration.deletion rejects a mismatched topic result",+ "rdkafka-hs-integration.topic-configuration.deletion reports a missing response as a timeout",+ "rdkafka-hs-integration.topic-configuration.missing native timeout configuration returns an error",+ "rdkafka-hs-integration.topic-configuration.malformed native timeout configuration returns an error",+ "rdkafka-hs-integration.topic-configuration.zero native timeout configuration returns an error",+ "rdkafka-hs-integration.topic-configuration.negative native timeout configuration returns an error",+ "rdkafka-hs-integration.topic-configuration.overflowing native timeout configuration returns an error",+ "rdkafka-hs-integration.topic-configuration.oversized native timeout configuration never reads a truncated buffer",+ "rdkafka-hs-integration.producer-regressions.explicit topic timeout expires an accepted message",+ "rdkafka-hs-integration.producer-regressions.global timeout still expires an accepted message",+ "rdkafka-hs-integration.producer-regressions.queue-full rejection releases callback capture without invoking it",+ "rdkafka-hs-integration.producer-regressions.accepted callback retains its capture until a purged report completes",+ "rdkafka-hs-integration.producer-regressions.throwing global callback preserves per-message delivery and releases capture",+ "rdkafka-hs-integration.producer-regressions.throwing per-message callback reports exception and releases capture",+ "rdkafka-hs-integration.producer-regressions.repeated queue-full rejections release every callback capture",+ "rdkafka-hs-integration.producer-regressions.cancellation at a rejected enqueue releases capture before unmasking",+ "rdkafka-hs-integration.producer-regressions.cancellation after native acceptance retains callback until its report",+ "rdkafka-hs-integration.producer-regressions.another poller can deliver before successful enqueue returns",+ "rdkafka-hs-integration.producer-regressions.running callback keeps its capture after the native root is released",+ "rdkafka-hs-integration.producer-regressions.native error decoding failure releases rejected callback capture",+ "rdkafka-hs-integration.producer-regressions.non-null native success-code error rejects and releases capture",+ "rdkafka-hs-integration.producer-regressions.unknown native error code is preserved instead of reading errno",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: defaults",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: global only",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: topic only",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: disjoint maps",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: explicit topic wins duplicate",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: last topic property wins",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: empty topic map preserves global",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: zero topic timeout is infinite",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: maximum native topic timeout",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: explicit topic wins native timeout alias",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: topic codec overrides global codec",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: global codec survives unrelated topic keys",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with NoCompression",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Gzip",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Snappy",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Lz4",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Zstd",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: none",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: inflight",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue+inflight",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue+nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: inflight+nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: all",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: none",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: inflight",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue+inflight",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue+nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: inflight+nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: all",+ "rdkafka-hs-integration.producer-regressions.bounded flush timeout recovers when the delayed response arrives",+ "rdkafka-hs-integration.producer-regressions.close retries a timed-out flush until the delayed delivery completes",+ "rdkafka-hs-integration.producer-regressions.oversized rejection releases capture without a delivery report",+ "rdkafka-hs-integration.producer-regressions.known invalid partition rejection releases capture",+ "rdkafka-hs-integration.producer-regressions.empty queue supports repeated flush and close",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: NUL topic name",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: NUL header name",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: maximum unrepresentable partition",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: minimum unrepresentable partition",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: unknown global key",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: unknown topic key",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: invalid topic timeout",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: excessive topic timeout",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: global-only key in topic map",+ "rdkafka-hs-integration.producer-regressions.later delivery callback replaces the earlier callback",+ "rdkafka-hs-integration.producer-regressions.null native delivery frame reports the generic errno fallback without dereferencing a message",+ "rdkafka-hs-integration.producer-regressions.native delivery without an opaque Haskell callback preserves the complete record",+ "rdkafka-hs-integration.producer-regressions.delivery header acquisition failure preserves the outcome with empty headers",+ "rdkafka-hs-integration.producer-properties.callback composition preserves order and identity",+ "rdkafka-hs-integration.consumer-properties.consumer callback composition preserves registration order and identity",+ "rdkafka-hs-integration.consumer-properties.generated source offsets reach native code as the representable next position",+ "rdkafka-hs-integration.consumer-properties.async later subscription reset reaches the native consumer",+ "rdkafka-hs-integration.consumer-properties.sync later subscription reset reaches the native consumer",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.counter detects a retained native list before explicit release",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.pair conversion failure releases the partial list before GC",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.offset conversion failure releases the partial list before GC",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.ordinary input lists release after exact native results",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.native logical offsets decode independently without losing partition identity",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.missing native partition queue preserves assignment and later forwarding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.assignment outputs release after exact decoding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.subscription outputs release after exact decoding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.subscription acquisition failure preserves the native error without a list",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.assignment decoder failure releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.subscription decoder failure releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.cancellation at input allocation releases the owned list",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.cancellation at assignment return releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.pair conversion failure releases the partial list before GC",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.offset conversion failure releases the partial list before GC",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.ordinary input lists release after exact native results",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.native logical offsets decode independently without losing partition identity",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.missing native partition queue preserves assignment and later forwarding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.assignment outputs release after exact decoding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.subscription outputs release after exact decoding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.subscription acquisition failure preserves the native error without a list",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.assignment decoder failure releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.subscription decoder failure releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.cancellation at input allocation releases the owned list",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.cancellation at assignment return releases the owned output",+ "rdkafka-hs-integration.public-contract.messages.batch conversion releases every returned native message",+ "rdkafka-hs-integration.public-contract.messages.native message counter detects a retained final object",+ "rdkafka-hs-integration.public-contract.messages.batch decoder exception releases unprocessed messages",+ "rdkafka-hs-integration.public-contract.messages.batch native header errors remain errors while later records are released",+ "rdkafka-hs-integration.public-contract.messages.batch cancellation at native return releases every acquired message",+ "rdkafka-hs-integration.public-contract.messages.batch cancellation at middle conversion releases every acquired message",+ "rdkafka-hs-integration.public-contract.messages.async single cancellation at native return releases its native message",+ "rdkafka-hs-integration.public-contract.messages.async single cancellation at inside conversion releases its native message",+ "rdkafka-hs-integration.public-contract.messages.sync single cancellation at native return releases its native message",+ "rdkafka-hs-integration.public-contract.messages.sync single cancellation at inside conversion releases its native message",+ "rdkafka-hs-integration.public-contract.messages.async header failure preserves the polled record origin",+ "rdkafka-hs-integration.public-contract.messages.sync header failure preserves the polled record origin",+ "rdkafka-hs-integration.public-contract.messages.async plain polling surfaces native header failure",+ "rdkafka-hs-integration.public-contract.messages.sync plain polling surfaces native header failure",+ "rdkafka-hs-integration.public-contract.messages.async attributed error preserves independently absent partition-and-offset",+ "rdkafka-hs-integration.public-contract.messages.async attributed error preserves independently absent offset",+ "rdkafka-hs-integration.public-contract.messages.async attributed error preserves independently absent partition",+ "rdkafka-hs-integration.public-contract.messages.sync attributed error preserves independently absent partition-and-offset",+ "rdkafka-hs-integration.public-contract.messages.sync attributed error preserves independently absent offset",+ "rdkafka-hs-integration.public-contract.messages.sync attributed error preserves independently absent partition",+ "rdkafka-hs-integration.public-contract.messages.callback-event polling cancellation releases a returned message",+ "rdkafka-hs-integration.public-contract.messages.callback buffer preserves attributed header failure",+ "rdkafka-hs-integration.public-contract.messages.callback buffer preserves plain header failure",+ "rdkafka-hs-integration.public-contract.messages.originless callback error survives seek filtering and a paused partition",+ "rdkafka-hs-integration.public-contract.messages.callback-event polling releases and discards a returned fatal frame",+ "rdkafka-hs-integration.public-contract.messages.zero batch size leaves the queued records available",+ "rdkafka-hs-integration.public-contract.messages.unsupported sync batch does not discard a record",+ "rdkafka-hs-integration.public-contract.messages.signed native batch failure preserves its error and queued data",+ "rdkafka-hs-integration.public-contract.messages.infinite batch timeout returns available records",+ "rdkafka-hs-integration.public-contract.messages.batch capacity 1 preserves complete ordered records across partial batches",+ "rdkafka-hs-integration.public-contract.messages.batch capacity 2 preserves complete ordered records across partial batches",+ "rdkafka-hs-integration.public-contract.messages.batch capacity 5 preserves complete ordered records across partial batches",+ "rdkafka-hs-integration.public-contract.messages.invalid batch array size is rejected before native acquisition: -1",+ "rdkafka-hs-integration.public-contract.messages.invalid batch array size is rejected before native acquisition: -9223372036854775808",+ "rdkafka-hs-integration.public-contract.messages.invalid batch array size is rejected before native acquisition: 9223372036854775807",+ "rdkafka-hs-integration.public-contract.messages.batch preserves complete records followed by exact partition EOF and idle timeout",+ "rdkafka-hs-integration.public-contract.messages.empty batch respects timeout 0",+ "rdkafka-hs-integration.public-contract.messages.empty batch respects timeout 100",+ "rdkafka-hs-integration.public-contract.rebalance-errors.native rebalance counter detects an undisposed error",+ "rdkafka-hs-integration.public-contract.rebalance-errors.async real cooperative assignment and revocation preserve records",+ "rdkafka-hs-integration.public-contract.rebalance-errors.sync real cooperative assignment and revocation preserve records",+ "rdkafka-hs-integration.public-contract.rebalance-errors.cooperative assign async native reports failure without a success event",+ "rdkafka-hs-integration.public-contract.rebalance-errors.cooperative assign async decode reports failure without a success event",+ "rdkafka-hs-integration.public-contract.rebalance-errors.cooperative assign sync native reports failure without a success event",+ "rdkafka-hs-integration.public-contract.rebalance-errors.cooperative assign sync decode reports failure without a success event",+ "rdkafka-hs-integration.public-contract.rebalance-errors.cooperative revoke async native reports failure without a success event",+ "rdkafka-hs-integration.public-contract.rebalance-errors.cooperative revoke async decode reports failure without a success event",+ "rdkafka-hs-integration.public-contract.rebalance-errors.cooperative revoke sync native reports failure without a success event",+ "rdkafka-hs-integration.public-contract.rebalance-errors.cooperative revoke sync decode reports failure without a success event",+ "rdkafka-hs-integration.public-contract.rebalance-errors.eager assign async native reports failure without a success event",+ "rdkafka-hs-integration.public-contract.rebalance-errors.eager assign sync native reports failure without a success event",+ "rdkafka-hs-integration.public-contract.rebalance-errors.eager revoke async native reports failure without a success event",+ "rdkafka-hs-integration.public-contract.rebalance-errors.eager revoke sync native reports failure without a success event",+ "rdkafka-hs-integration.public-contract.rebalance-errors.async unexpected rebalance error clears assignment and pending records",+ "rdkafka-hs-integration.public-contract.rebalance-errors.async unexpected rebalance error preserves state when native reset fails",+ "rdkafka-hs-integration.public-contract.rebalance-errors.sync unexpected rebalance error clears assignment and pending records",+ "rdkafka-hs-integration.public-contract.rebalance-errors.sync unexpected rebalance error preserves state when native reset fails",+ "rdkafka-hs-integration.public-contract.consumer-state.async.assignment-replacement",+ "rdkafka-hs-integration.public-contract.consumer-state.async.unknown-assignment-reports-through-error-callback-and-recovers",+ "rdkafka-hs-integration.public-contract.consumer-state.async.representable-partition-boundaries-keep-native-query-semantics",+ "rdkafka-hs-integration.public-contract.consumer-state.async.deprecated-seek-reports-unassigned-state-and-recovers-after-assignment",+ "rdkafka-hs-integration.public-contract.consumer-state.async.subscription-preserves-the-exact-multiple-topic-set",+ "rdkafka-hs-integration.public-contract.consumer-state.async.empty-requests-preserve-empty-assignment",+ "rdkafka-hs-integration.public-contract.consumer-state.async.unknown-position-is-invalid-without-native-error",+ "rdkafka-hs-integration.public-contract.consumer-state.async.multiple-assigned-partitions-retain-the-exact-topic-map",+ "rdkafka-hs-integration.public-contract.consumer-state.async.legacy-seek-constructor-failure-does-not-execute-an-earlier-valid-seek",+ "rdkafka-hs-integration.public-contract.consumer-state.async.pause-resume-preserves-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-event-poll-preserves-application-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-seek-replaces-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-reassignment-replaces-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-pause-defers-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-legacy-seek-replaces-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-legacy-partial-seek-keeps-success",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-paused-partition-does-not-block-another",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-unassignment-discards-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.pausing-one-partition-leaves-the-other-running",+ "rdkafka-hs-integration.public-contract.consumer-state.async.pause-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.async.resume-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.async.store-commit-next-offset",+ "rdkafka-hs-integration.public-contract.consumer-state.async.store-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.async.position-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.async.deprecated-seek-exact-repeated-replay",+ "rdkafka-hs-integration.public-contract.consumer-state.async.explicit-subscription-overrides-global-reset",+ "rdkafka-hs-integration.public-contract.consumer-state.async.regex-subscription-selects-run-owned-topic",+ "rdkafka-hs-integration.public-contract.consumer-state.async.global-topic-setting-survives-empty-subscription-properties",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.assignment-replacement",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.unknown-assignment-reports-through-error-callback-and-recovers",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.representable-partition-boundaries-keep-native-query-semantics",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.deprecated-seek-reports-unassigned-state-and-recovers-after-assignment",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.subscription-preserves-the-exact-multiple-topic-set",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.empty-requests-preserve-empty-assignment",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.unknown-position-is-invalid-without-native-error",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.multiple-assigned-partitions-retain-the-exact-topic-map",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.legacy-seek-constructor-failure-does-not-execute-an-earlier-valid-seek",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.pause-resume-preserves-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-event-poll-preserves-application-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-seek-replaces-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-reassignment-replaces-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-pause-defers-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-legacy-seek-replaces-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-legacy-partial-seek-keeps-success",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-paused-partition-does-not-block-another",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-unassignment-discards-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.pausing-one-partition-leaves-the-other-running",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.pause-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.resume-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.store-commit-next-offset",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.store-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.position-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.deprecated-seek-exact-repeated-replay",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.explicit-subscription-overrides-global-reset",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.regex-subscription-selects-run-owned-topic",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.global-topic-setting-survives-empty-subscription-properties",+ "rdkafka-hs-integration.public-contract.consumer-state.sync-buffer-fields-native-time",+ "rdkafka-hs-integration.public-contract.consumer-state.sync-buffer-fields-no-time",+ "rdkafka-hs-integration.public-contract.consumer-state.sync-buffer-fields-append-time",+ "rdkafka-hs-integration.public-contract.consumer-state.sync-buffer-fields-create-time",+ "rdkafka-hs-integration.public-contract.consumer-state.cooperative subset callbacks preserve unrelated buffers pauses and originless errors",+ "rdkafka-hs-integration.public-contract.consumer-state.sync callback mixed seek retains only the failed partition's copied records",+ "rdkafka-hs-integration.public-contract.consumer-commit.async commit modes preserve native flags callback offsets and broker state",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync commit modes preserve native flags callback offsets and broker state",+ "rdkafka-hs-integration.public-contract.consumer-commit.async message and stored commits preserve unrelated partition offsets",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync message and stored commits preserve unrelated partition offsets",+ "rdkafka-hs-integration.public-contract.consumer-commit.async empty commit requests preserve no-offset callbacks",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync empty commit requests preserve no-offset callbacks",+ "rdkafka-hs-integration.public-contract.consumer-commit.async mixed broker commit failures preserve successful offsets",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync mixed broker commit failures preserve successful offsets",+ "rdkafka-hs-integration.public-contract.consumer-commit.async committed query preserves an unavailable coordinator timeout",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync committed query preserves an unavailable coordinator timeout",+ "rdkafka-hs-integration.public-contract.diagnostics.supported-property print flushes and preserves the caller handle",+ "rdkafka-hs-integration.public-contract.diagnostics.client print flushes and preserves the caller handle",+ "rdkafka-hs-integration.public-contract.diagnostics.failed fdopen releases the duplicate and preserves the original",+ "rdkafka-hs-integration.public-contract.diagnostics.failed native flush is reported after closing the duplicate",+ "rdkafka-hs-integration.public-contract.diagnostics.producer configuration dumps retain exact explicit and global settings",+ "rdkafka-hs-integration.public-contract.diagnostics.producer constructor log level overrides the global property on the native client",+ "rdkafka-hs-integration.public-contract.diagnostics.consumer configuration dump preserves global settings after subscription merge",+ "rdkafka-hs-integration.public-contract.diagnostics.native dump counter detects an unreleased array",+ "rdkafka-hs-integration.public-contract.diagnostics.global cancellation at native acquisition releases its array",+ "rdkafka-hs-integration.public-contract.diagnostics.topic cancellation at native acquisition releases its array",+ "rdkafka-hs-integration.public-contract.input-boundaries.async assign rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async pause rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async resume rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async store rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async store-message rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async commit rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async commit-message rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async committed rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async position rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async legacy-seek rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async seek rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async timestamp rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async watermark rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async assign rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async pause rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async resume rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async store rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async store-message rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async commit rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async commit-message rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async committed rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async position rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async legacy-seek rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async seek rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async timestamp rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async watermark rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async assign rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async pause rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async resume rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async store rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async store-message rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async commit rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async commit-message rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async committed rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async position rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async legacy-seek rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async seek rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async timestamp rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async watermark rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync assign rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync pause rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync resume rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync store rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync store-message rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync commit rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync commit-message rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync committed rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync position rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync legacy-seek rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync seek rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync timestamp rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync watermark rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync assign rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync pause rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync resume rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync store rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync store-message rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync commit rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync commit-message rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync committed rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync position rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync legacy-seek rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync seek rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync timestamp rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync watermark rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync assign rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync pause rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync resume rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync store rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync store-message rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync commit rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync commit-message rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync committed rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync position rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync legacy-seek rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync seek rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync timestamp rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync watermark rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async string queries and subscription reject NUL before native effects",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync string queries and subscription reject NUL before native effects",+ "rdkafka-hs-integration.public-contract.deprecated-runners.producer flushes after Returned",+ "rdkafka-hs-integration.public-contract.deprecated-runners.producer flushes after Refused",+ "rdkafka-hs-integration.public-contract.deprecated-runners.producer flushes after Thrown",+ "rdkafka-hs-integration.public-contract.deprecated-runners.async consumer closes after Returned",+ "rdkafka-hs-integration.public-contract.deprecated-runners.async consumer closes after Refused",+ "rdkafka-hs-integration.public-contract.deprecated-runners.async consumer closes after Thrown",+ "rdkafka-hs-integration.public-contract.deprecated-runners.sync consumer closes after Returned",+ "rdkafka-hs-integration.public-contract.deprecated-runners.sync consumer closes after Refused",+ "rdkafka-hs-integration.public-contract.deprecated-runners.sync consumer closes after Thrown",+ "rdkafka-hs-integration.public-contract.deprecated-runners.producer preserves native construction failure without invoking handler",+ "rdkafka-hs-integration.public-contract.deprecated-runners.producer preserves configuration exceptions without invoking handler",+ "rdkafka-hs-integration.public-contract.deprecated-runners.async consumer preserves native construction failure",+ "rdkafka-hs-integration.public-contract.deprecated-runners.async consumer preserves configuration construction failure",+ "rdkafka-hs-integration.public-contract.deprecated-runners.sync consumer preserves native construction failure",+ "rdkafka-hs-integration.public-contract.deprecated-runners.sync consumer preserves configuration construction failure",+ "rdkafka-hs-integration.public-contract.fatal.async",+ "rdkafka-hs-integration.public-contract.fatal.sync",+ "rdkafka-hs-integration.public-contract.queue event.empty pipes are idle but invalid descriptor errors are preserved",+ "rdkafka-hs-integration.public-contract.queue event.async.wakes an idle consumer and stays quiet once disabled",+ "rdkafka-hs-integration.public-contract.queue event.async.finds records queued before it was enabled, then rearms",+ "rdkafka-hs-integration.public-contract.queue event.async.one wake-up covers several records, then rearms",+ "rdkafka-hs-integration.public-contract.queue event.async.binary payloads retain every byte and empty payloads preserve records",+ "rdkafka-hs-integration.public-contract.queue event.async.native record errors are never treated as idle",+ "rdkafka-hs-integration.public-contract.queue event.async.close stops notifications and keeps caller descriptors open",+ "rdkafka-hs-integration.public-contract.queue event.async.destroy stops notifications and keeps caller descriptors open",+ "rdkafka-hs-integration.public-contract.queue event.sync.wakes an idle consumer and stays quiet once disabled",+ "rdkafka-hs-integration.public-contract.queue event.sync.finds records queued before it was enabled, then rearms",+ "rdkafka-hs-integration.public-contract.queue event.sync.one wake-up covers several records, then rearms",+ "rdkafka-hs-integration.public-contract.queue event.sync.binary payloads retain every byte and empty payloads preserve records",+ "rdkafka-hs-integration.public-contract.queue event.sync.native record errors are never treated as idle",+ "rdkafka-hs-integration.public-contract.queue event.sync.close stops notifications and keeps caller descriptors open",+ "rdkafka-hs-integration.public-contract.queue event.sync.destroy stops notifications and keeps caller descriptors open",+ "rdkafka-hs-integration.public-contract.runtime-contract.RTS capability is observed by async construction",+ "rdkafka-hs-integration.public-contract.runtime-contract.explicit async construction checks the runtime",+ "rdkafka-hs-integration.public-contract.runtime-contract.sync subscription delivers an exact record",+ "rdkafka-hs-integration.public-contract.runtime-contract.deprecated sync runner closes after an exact record",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata counter detects an unreleased result",+ "rdkafka-hs-integration.public-contract.metadata-contract.native topic-constructor failure survives metadata convenience queries",+ "rdkafka-hs-integration.public-contract.metadata-contract.empty native metadata remains empty and releases every result",+ "rdkafka-hs-integration.public-contract.metadata-contract.timestamp lookup preserves native overall errors",+ "rdkafka-hs-integration.public-contract.metadata-contract.watermark queries preserve unknown partition errors and empty provided metadata",+ "rdkafka-hs-integration.public-contract.metadata-contract.topic identity replica sets and exact watermarks",+ "rdkafka-hs-integration.public-contract.metadata-contract.distinct native metadata fields retain exact identities and errors",+ "rdkafka-hs-integration.public-contract.metadata-contract.provided metadata preserves partition failures in convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata partition failures survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.group query timeout preserves initial metadata wait failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.missing topic errors survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.timestamp lookup distinguishes before at and after actual record times",+ "rdkafka-hs-integration.public-contract.metadata-contract.mixed timestamp request preserves native partition failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata timeouts preserve the native error",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.groups native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.async group identity lifecycle and supported native states",+ "rdkafka-hs-integration.public-contract.metadata-contract.sync group identity lifecycle and supported native states",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.empty producer client id retains the native default",+ "rdkafka-hs-integration.public-contract.config-strings.consumer ordinary UTF8 values remain exact",+ "rdkafka-hs-integration.public-contract.config-strings.empty global key retains native unknown-key rejection",+ "rdkafka-hs-integration.seek-partitions.async.unassigned member reports native error",+ "rdkafka-hs-integration.seek-partitions.async.empty list preserves top-level invalid argument",+ "rdkafka-hs-integration.seek-partitions.async.zero-timeout unassigned failure is immediate",+ "rdkafka-hs-integration.seek-partitions.async.empty zero-timeout preserves top-level error",+ "rdkafka-hs-integration.seek-partitions.async.rewind without assignment does not seek",+ "rdkafka-hs-integration.seek-partitions.async.top-level error precedes member error and is destroyed",+ "rdkafka-hs-integration.seek-partitions.async.first substantive error follows input order",+ "rdkafka-hs-integration.seek-partitions.async.reversed input selects the other substantive error",+ "rdkafka-hs-integration.seek-partitions.async.zero-timeout skips pending but reports later failure",+ "rdkafka-hs-integration.seek-partitions.async.nonzero-timeout preserves residual pending",+ "rdkafka-hs-integration.seek-partitions.async.zero-timeout all pending promises initiation only",+ "rdkafka-hs-integration.seek-partitions.async.nonzero-timeout all pending is not success",+ "rdkafka-hs-integration.seek-partitions.async.top-level decoder exception still destroys error object",+ "rdkafka-hs-integration.seek-partitions.async.rewind assignment failure prevents seek",+ "rdkafka-hs-integration.seek-partitions.async.single seek replays exact record",+ "rdkafka-hs-integration.seek-partitions.async.multiple successful seeks replay both partitions",+ "rdkafka-hs-integration.seek-partitions.async.mixed seek reports failure without rolling back success",+ "rdkafka-hs-integration.seek-partitions.async.mixed errors follow actual request order",+ "rdkafka-hs-integration.seek-partitions.async.zero-timeout valid seek is followed by synchronous replay",+ "rdkafka-hs-integration.seek-partitions.async.zero-timeout mixed request keeps immediate unknown error",+ "rdkafka-hs-integration.seek-partitions.async.zero-timeout logical offsets promise initiation only",+ "rdkafka-hs-integration.seek-partitions.async.infinite native timeout completes a valid seek",+ "rdkafka-hs-integration.seek-partitions.async.duplicate entries preserve residual native pending error",+ "rdkafka-hs-integration.seek-partitions.async.unassigned existing partition returns state error",+ "rdkafka-hs-integration.seek-partitions.async.unknown topic reports member error",+ "rdkafka-hs-integration.seek-partitions.async.stored sentinel is rejected without altering position",+ "rdkafka-hs-integration.seek-partitions.async.end and exact high watermark produce no record",+ "rdkafka-hs-integration.seek-partitions.async.seek before retained log range resets to actual low watermark",+ "rdkafka-hs-integration.seek-partitions.async.rewind without committed offset starts at beginning",+ "rdkafka-hs-integration.seek-partitions.async.rewind uses committed next offset exactly",+ "rdkafka-hs-integration.seek-partitions.async.rewind message commit resumes after committed message",+ "rdkafka-hs-integration.seek-partitions.async.rewind lookup failure prevents seek",+ "rdkafka-hs-integration.seek-partitions.async.rewind propagates assignment change after committed lookup",+ "rdkafka-hs-integration.seek-partitions.async.beginning sentinel replays offset zero",+ "rdkafka-hs-integration.seek-partitions.async.absolute low watermark replays offset zero",+ "rdkafka-hs-integration.seek-partitions.async.invalid sentinel uses configured earliest reset",+ "rdkafka-hs-integration.seek-partitions.async.above high watermark uses configured earliest reset",+ "rdkafka-hs-integration.seek-partitions.async.native tail sentinel replays final two records",+ "rdkafka-hs-integration.seek-partitions.sync.unassigned member reports native error",+ "rdkafka-hs-integration.seek-partitions.sync.empty list preserves top-level invalid argument",+ "rdkafka-hs-integration.seek-partitions.sync.zero-timeout unassigned failure is immediate",+ "rdkafka-hs-integration.seek-partitions.sync.empty zero-timeout preserves top-level error",+ "rdkafka-hs-integration.seek-partitions.sync.rewind without assignment does not seek",+ "rdkafka-hs-integration.seek-partitions.sync.top-level error precedes member error and is destroyed",+ "rdkafka-hs-integration.seek-partitions.sync.first substantive error follows input order",+ "rdkafka-hs-integration.seek-partitions.sync.reversed input selects the other substantive error",+ "rdkafka-hs-integration.seek-partitions.sync.zero-timeout skips pending but reports later failure",+ "rdkafka-hs-integration.seek-partitions.sync.nonzero-timeout preserves residual pending",+ "rdkafka-hs-integration.seek-partitions.sync.zero-timeout all pending promises initiation only",+ "rdkafka-hs-integration.seek-partitions.sync.nonzero-timeout all pending is not success",+ "rdkafka-hs-integration.seek-partitions.sync.top-level decoder exception still destroys error object",+ "rdkafka-hs-integration.seek-partitions.sync.rewind assignment failure prevents seek",+ "rdkafka-hs-integration.seek-partitions.sync.single seek replays exact record",+ "rdkafka-hs-integration.seek-partitions.sync.multiple successful seeks replay both partitions",+ "rdkafka-hs-integration.seek-partitions.sync.mixed seek reports failure without rolling back success",+ "rdkafka-hs-integration.seek-partitions.sync.mixed errors follow actual request order",+ "rdkafka-hs-integration.seek-partitions.sync.zero-timeout valid seek is followed by synchronous replay",+ "rdkafka-hs-integration.seek-partitions.sync.zero-timeout mixed request keeps immediate unknown error",+ "rdkafka-hs-integration.seek-partitions.sync.zero-timeout logical offsets promise initiation only",+ "rdkafka-hs-integration.seek-partitions.sync.infinite native timeout completes a valid seek",+ "rdkafka-hs-integration.seek-partitions.sync.duplicate entries preserve residual native pending error",+ "rdkafka-hs-integration.seek-partitions.sync.unassigned existing partition returns state error",+ "rdkafka-hs-integration.seek-partitions.sync.unknown topic reports member error",+ "rdkafka-hs-integration.seek-partitions.sync.stored sentinel is rejected without altering position",+ "rdkafka-hs-integration.seek-partitions.sync.end and exact high watermark produce no record",+ "rdkafka-hs-integration.seek-partitions.sync.seek before retained log range resets to actual low watermark",+ "rdkafka-hs-integration.seek-partitions.sync.rewind without committed offset starts at beginning",+ "rdkafka-hs-integration.seek-partitions.sync.rewind uses committed next offset exactly",+ "rdkafka-hs-integration.seek-partitions.sync.rewind message commit resumes after committed message",+ "rdkafka-hs-integration.seek-partitions.sync.rewind lookup failure prevents seek",+ "rdkafka-hs-integration.seek-partitions.sync.rewind propagates assignment change after committed lookup",+ "rdkafka-hs-integration.seek-partitions.sync.beginning sentinel replays offset zero",+ "rdkafka-hs-integration.seek-partitions.sync.absolute low watermark replays offset zero",+ "rdkafka-hs-integration.seek-partitions.sync.invalid sentinel uses configured earliest reset",+ "rdkafka-hs-integration.seek-partitions.sync.above high watermark uses configured earliest reset",+ "rdkafka-hs-integration.seek-partitions.sync.native tail sentinel replays final two records",+ "rdkafka-hs-integration.broker.Per-message commit.1. sends 2 messages to test topic",+ "rdkafka-hs-integration.broker.Per-message commit.2. should receive 2 messages",+ "rdkafka-hs-integration.broker.Per-message commit.3. sends 2 messages to test topic",+ "rdkafka-hs-integration.broker.Per-message commit.4. should receive 2 messages again",+ "rdkafka-hs-integration.broker.Store offsets.1. sends 2 messages to test topic",+ "rdkafka-hs-integration.broker.Store offsets.2. should receive 2 messages without storing",+ "rdkafka-hs-integration.broker.Store offsets.3. sends 2 messages to test topic",+ "rdkafka-hs-integration.broker.Store offsets.4. should receive 4 messages and store them",+ "rdkafka-hs-integration.broker.Store offsets.5. sends 2 messages to test topic",+ "rdkafka-hs-integration.broker.Store offsets.6. should receive 2 messages",+ "rdkafka-hs-integration.broker.Store offsets.Part 3 - Consume after committing stored offsets.5. sends 2 messages to test topic",+ "rdkafka-hs-integration.broker.Store offsets.Part 3 - Consume after committing stored offsets.6. should receive 2 messages",+ "rdkafka-hs-integration.broker.Consumer.Run producer.sends messages to test topic",+ "rdkafka-hs-integration.broker.Consumer.Run producer.sends messages with callback to test topic",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should receive messages",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should get committed",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should get position",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should get watermark offsets",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should return subscription",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should return assignment",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.assignment is not lost",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should return all topics metadata",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should return topic metadata",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should describe all consumer groups",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should describe a given consumer group",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should describe non-existent consumer group",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should read topic offsets for time",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should seek and return no error",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should seek to the beginning",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should seek to the end",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should respect out-of-bound offsets (invalid offset)",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should respect out-of-bound offsets (huge offset)",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should receive messages",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should get committed",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should get position",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should get watermark offsets",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should return subscription",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should return assignment",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.assignment is not lost",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should return all topics metadata",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should return topic metadata",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should describe all consumer groups",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should describe a given consumer group",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should describe non-existent consumer group",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should read topic offsets for time",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should seek and return no error",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should seek to the beginning",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should seek to the end",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should respect out-of-bound offsets (invalid offset)",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should respect out-of-bound offsets (huge offset)",+ "rdkafka-hs-integration.broker.Batch consumer.should consume first batch",+ "rdkafka-hs-integration.broker.Batch consumer.should consume second batch with not enough messages",+ "rdkafka-hs-integration.broker.Batch consumer.should consume empty batch when there are no messages",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessage sync.interleaved duplicate names keep wire order and last values",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessage sync.distinct names keep wire order",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessage sync.identical repeated pairs are not deduplicated",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessage sync.a single header round-trips",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessage sync.no headers decode as an empty list",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessage async.interleaved duplicate names keep wire order and last values",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessage async.distinct names keep wire order",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessage async.identical repeated pairs are not deduplicated",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessage async.a single header round-trips",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessage async.no headers decode as an empty list",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessageAttributed sync.interleaved duplicate names keep wire order and last values",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessageAttributed sync.distinct names keep wire order",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessageAttributed sync.identical repeated pairs are not deduplicated",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessageAttributed sync.a single header round-trips",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessageAttributed sync.no headers decode as an empty list",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessageAttributed async.interleaved duplicate names keep wire order and last values",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessageAttributed async.distinct names keep wire order",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessageAttributed async.identical repeated pairs are not deduplicated",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessageAttributed async.a single header round-trips",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessageAttributed async.no headers decode as an empty list",+ "rdkafka-hs-integration.broker.assign-only.async.newAssignedConsumer",+ "rdkafka-hs-integration.broker.assign-only.async.newConsumer with an empty subscription",+ "rdkafka-hs-integration.broker.assign-only.sync.newAssignedConsumer",+ "rdkafka-hs-integration.broker.assign-only.sync.newConsumer with an empty subscription",+ "rdkafka-hs-integration.broker.attributed.async",+ "rdkafka-hs-integration.broker.attributed.sync",+ "rdkafka-hs-integration.broker.destroy.async.closes broker connections within one second",+ "rdkafka-hs-integration.broker.destroy.async.is safe to repeat",+ "rdkafka-hs-integration.broker.destroy.async.concurrent destroys both return after cleanup",+ "rdkafka-hs-integration.broker.destroy.async.completes after an interrupted destroy",+ "rdkafka-hs-integration.broker.destroy.async.close then destroy, destroy then close",+ "rdkafka-hs-integration.broker.destroy.sync.closes broker connections within one second",+ "rdkafka-hs-integration.broker.destroy.sync.is safe to repeat",+ "rdkafka-hs-integration.broker.destroy.sync.concurrent destroys both return after cleanup",+ "rdkafka-hs-integration.broker.destroy.sync.completes after an interrupted destroy",+ "rdkafka-hs-integration.broker.destroy.sync.close then destroy, destroy then close",+ "rdkafka-hs-integration.broker.read_committed watermark stops before an open transaction",+ "rdkafka-hs-integration.broker.observer.async",+ "rdkafka-hs-integration.broker.observer.sync",+ "rdkafka-hs-integration.broker.Read all topics.should create a topic",+ "rdkafka-hs-integration.broker.Read all topics.should return all the topics",+ "rdkafka-hs-integration.broker.Read all topics.should delete this run's topics",+ "broker-failure.async observed leader election preserves exact records and commits",+ "broker-failure.sync observed leader election preserves exact records and commits",+ "broker-failure.eager async handoff pause seek eviction and complete outage recover exact offsets",+ "broker-failure.eager sync handoff pause seek eviction and complete outage recover exact offsets",+ "broker-failure.cooperative async handoff pause seek eviction and complete outage recover exact offsets",+ "broker-failure.cooperative sync handoff pause seek eviction and complete outage recover exact offsets",+ "broker-failure.async transaction commit timeout across full outage retries and preserves read-committed visibility",+ "broker-failure.sync transaction commit timeout across full outage retries and preserves read-committed visibility",+ "broker-failure.cancellation during complete outage restores all owned brokers",+ "authentication-contract.verified TLS authenticated delivery and exact consume/commit in both modes",+ "authentication-contract.authenticated identity without topic ACL receives exact produce denial",+ "authentication-contract.invalid-password producer reports the exact connection failure and no delivery",+ "authentication-contract.untrusted-CA producer reports the exact connection failure and no delivery",+ "authentication-contract.hostname-mismatch producer reports the exact connection failure and no delivery",+ "authentication-contract.invalid-password async consumer reports the exact connection failure",+ "authentication-contract.invalid-password sync consumer reports the exact connection failure",+ "authentication-contract.untrusted-CA async consumer reports the exact connection failure",+ "authentication-contract.untrusted-CA sync consumer reports the exact connection failure",+ "authentication-contract.hostname-mismatch async consumer reports the exact connection failure",+ "authentication-contract.hostname-mismatch sync consumer reports the exact connection failure",+ "authentication-contract.async exact topic/group/admin authorization denials",+ "authentication-contract.sync exact topic/group/admin authorization denials",+ "authentication-contract.producer credential replacement authenticates a new identity after observed reconnect and recovers from invalid replacement",+ "authentication-contract.async consumer credential replacement authenticates after observed reconnect and recovers from invalid replacement",+ "authentication-contract.sync consumer credential replacement authenticates after observed reconnect and recovers from invalid replacement",+ "authentication-contract.interruption destroys owned secure processes, credentials, ACL state and private keys"+ ],+ "passed_test_count": 857,+ "primary_passed_test_count": 831,+ "primary_tests": [+ "rdkafka-hs.Callback owner.bridge allocation executes masked before ownership is recorded",+ "rdkafka-hs.Callback owner.installed and replaced bridges release exactly once",+ "rdkafka-hs.Callback owner.failed native install still owns its allocated bridge",+ "rdkafka-hs.Callback owner.failed allocation has no release",+ "rdkafka-hs.Callback owner.transfer preserves a callable bridge until client release",+ "rdkafka-hs.Callback owner.transferred and released owners reject reuse before allocating",+ "rdkafka-hs.Callback owner.release retry does not repeat completed releases",+ "rdkafka-hs.Callback owner.concurrent releases join before returning",+ "rdkafka-hs.Kafka.Consumer.ConsumerProperties.the poll mode defaults to async",+ "rdkafka-hs.Kafka.Consumer.ConsumerProperties.properties composed after the poll mode keep it",+ "rdkafka-hs.Kafka.Consumer.ConsumerProperties.properties composed before the poll mode keep it",+ "rdkafka-hs.Kafka.Consumer.ConsumerProperties.a later poll mode overrides an earlier one",+ "rdkafka-hs.Kafka.Consumer.ConsumerRecordMapSpec.should extract key",+ "rdkafka-hs.Kafka.Consumer.ConsumerRecordMapSpec.should extract value",+ "rdkafka-hs.Kafka.Consumer.ConsumerRecordMapSpec.should extract both key and value",+ "rdkafka-hs.Kafka.Consumer.ConsumerRecordTraverseSpec.should sequence",+ "rdkafka-hs.Kafka.Consumer.ConsumerRecordTraverseSpec.should traverse",+ "rdkafka-hs.Kafka.Consumer.ConsumerRecordTraverseSpec.should bisequence",+ "rdkafka-hs.Kafka.Consumer.ConsumerRecordTraverseSpec.should bitraverse",+ "rdkafka-hs.Kafka.Version.linked librdkafka is at least 2.15.0",+ "rdkafka-hs.Kafka.Version.version string agrees with the version number",+ "rdkafka-hs.Kafka.Version.decodes the hex version encoding",+ "rdkafka-hs.Producer properties generated.program follows last-write semantics",+ "rdkafka-hs.Producer properties generated.configuration has left and right identity",+ "rdkafka-hs.Producer properties generated.configuration composition is associative",+ "rdkafka-hs.Producer properties generated.composition appends writes in order",+ "rdkafka-hs.Producer properties generated.unrelated keys survive a conflicting write",+ "rdkafka-hs.Producer properties generated.last explicit log level wins",+ "rdkafka-hs.Producer properties generated.fixed empty duplicate and binary text values",+ "rdkafka-hs.Public properties.consumer composition.consumer program follows independent last-write model",+ "rdkafka-hs.Public properties.consumer composition.consumer identity preserves every observable field",+ "rdkafka-hs.Public properties.consumer composition.consumer association preserves writes and poll mode",+ "rdkafka-hs.Public properties.consumer composition.consumer composition appends programs",+ "rdkafka-hs.Public properties.consumer composition.unset poll mode preserves a prior explicit mode",+ "rdkafka-hs.Public properties.consumer composition.consumer helpers write exact native property names",+ "rdkafka-hs.Public properties.subscription.subscription follows last-write properties and topic union",+ "rdkafka-hs.Public properties.subscription.subscription identity and association retain topics and properties",+ "rdkafka-hs.Public properties.subscription.subscription composition appends property writes",+ "rdkafka-hs.Public properties.subscription.later subscription reset and explicit properties win",+ "rdkafka-hs.Public properties.headers.header list round-trip preserves duplicates and binary bytes",+ "rdkafka-hs.Public properties.headers.header concatenation follows list order",+ "rdkafka-hs.Public properties.headers.headers have two identities and associative concatenation",+ "rdkafka-hs.Public properties.headers.fixed duplicate empty and binary header values",+ "rdkafka-hs.Public properties.records.record functor identity",+ "rdkafka-hs.Public properties.records.record functor composition",+ "rdkafka-hs.Public properties.records.record bifunctor identity and composition",+ "rdkafka-hs.Public properties.records.record mapping preserves origin timestamp and headers",+ "rdkafka-hs.Public properties.records.record traversal identity and failure preserve the applicative contract",+ "rdkafka-hs.Public properties.records.record traversal composition preserves nested effects",+ "rdkafka-hs.Public properties.records.record bitraversal visits key before value",+ "rdkafka-hs.Public properties.records.record bitraversal composition preserves nested effects",+ "rdkafka-hs.Public properties.records.record folds retain key and value order",+ "rdkafka-hs.Public properties.records.deprecated record mapping remains equivalent",+ "rdkafka-hs.Public properties.records.deprecated traversal helpers preserve successful effects",+ "rdkafka-hs.Public properties.records.deprecated traversal helpers preserve failed effects",+ "rdkafka-hs.Public properties.representations.text newtypes preserve arbitrary represented text",+ "rdkafka-hs.Public properties.representations.integer newtypes preserve signed machine boundaries",+ "rdkafka-hs.Public properties.representations.offset and milliseconds preserve signed 64-bit boundaries",+ "rdkafka-hs.Public properties.representations.timestamp constructors retain their represented boundary",+ "rdkafka-hs.Public properties.representations.system topic classification requires two initial underscores",+ "rdkafka-hs.Public properties.representations.fixed empty underscore and signed numeric boundaries",+ "rdkafka-hs.Public properties.version.version bytes decode independently of prerelease byte",+ "rdkafka-hs.Public properties.version.version extraction agrees with arithmetic for every Int",+ "rdkafka-hs.Public properties.version.fixed zero and full version byte boundaries",+ "rdkafka-hs.Public properties.every compression debug and log enumeration has its native spelling",+ "rdkafka-hs.Public data contracts.builders.semigroup defaults retain writes callbacks and subscription union",+ "rdkafka-hs.Public data contracts.builders.consumer builders preserve exact settings and leave other fields unset",+ "rdkafka-hs.Public data contracts.builders.producer builders preserve global versus explicit topic placement",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs.Public data contracts.representations.numeric ordering and reads agree with represented signed values",+ "rdkafka-hs.Public data contracts.representations.numeric instances preserve primitive arithmetic including boundaries",+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.consumer variants retain fields and distinguish constructors",+ "rdkafka-hs.Public data contracts.representations.producer records delivery variants and topic requests retain exact fields",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs.Public data contracts.representations.every Kafka error preserves its Exception identity and generic form",+ "rdkafka-hs.Public data contracts.all linked native errors retain sparse numeric codes names and descriptions",+ "rdkafka-hs-integration.Fixture error controls.immediate enqueue rejection propagates",+ "rdkafka-hs-integration.Fixture error controls.delivery failure propagates",+ "rdkafka-hs-integration.Fixture error controls.flush failure propagates",+ "rdkafka-hs-integration.Fixture error controls.missing delivery callback fails",+ "rdkafka-hs-integration.Fixture error controls.wrong delivery identity fails",+ "rdkafka-hs-integration.Fixture error controls.matching delivery succeeds",+ "rdkafka-hs-integration.Fixture error controls.unexpected poll error propagates",+ "rdkafka-hs-integration.Fixture error controls.missing record fails",+ "rdkafka-hs-integration.Fixture error controls.extra record fails",+ "rdkafka-hs-integration.Fixture error controls.idle before exact records is retried",+ "rdkafka-hs-integration.Fixture error controls.partial setup releases first resource",+ "rdkafka-hs-integration.Fixture error controls.interrupted partial setup releases first resource",+ "rdkafka-hs-integration.Fixture error controls.weak control retains while rooted and collects after release",+ "rdkafka-hs-integration.configuration.defaults to the private broker",+ "rdkafka-hs-integration.configuration.accepts another private endpoint",+ "rdkafka-hs-integration.configuration.accepts a list of private endpoints",+ "rdkafka-hs-integration.configuration.rejects an empty value",+ "rdkafka-hs-integration.configuration.rejects localhost:9092",+ "rdkafka-hs-integration.configuration.rejects 127.0.0.1:9092",+ "rdkafka-hs-integration.configuration.rejects [::1]:9092",+ "rdkafka-hs-integration.configuration.rejects a loopback host without a port",+ "rdkafka-hs-integration.configuration.rejects the shared broker anywhere in a list",+ "rdkafka-hs-integration.callback-lifetime.async throwing error callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing log callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing stats callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing rebalance callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing commit callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing error callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing log callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing stats callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing rebalance callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing commit callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async error callback releases after destroy with retained wrapper",+ "rdkafka-hs-integration.callback-lifetime.sync error callback releases after destroy with retained wrapper",+ "rdkafka-hs-integration.callback-lifetime.producer delivery callback releases after native finalization",+ "rdkafka-hs-integration.callback-lifetime.noncaptured control is collectible",+ "rdkafka-hs-integration.callback-lifetime.async log callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.async stats callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.sync log callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.sync stats callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.async construction failure releases callbacks: topic",+ "rdkafka-hs-integration.callback-lifetime.async construction failure releases callbacks: native",+ "rdkafka-hs-integration.callback-lifetime.async construction failure releases callbacks: redirect",+ "rdkafka-hs-integration.callback-lifetime.async construction failure releases callbacks: subscribe",+ "rdkafka-hs-integration.callback-lifetime.sync construction failure releases callbacks: topic",+ "rdkafka-hs-integration.callback-lifetime.sync construction failure releases callbacks: native",+ "rdkafka-hs-integration.callback-lifetime.sync construction failure releases callbacks: redirect",+ "rdkafka-hs-integration.callback-lifetime.sync construction failure releases callbacks: subscribe",+ "rdkafka-hs-integration.callback-lifetime.producer native construction failure releases callbacks",+ "rdkafka-hs-integration.callback-lifetime.async constructor exception at callback-install releases partial native ownership",+ "rdkafka-hs-integration.callback-lifetime.async constructor exception at post-native-loglevel releases partial native ownership",+ "rdkafka-hs-integration.callback-lifetime.sync constructor exception at callback-install releases partial native ownership",+ "rdkafka-hs-integration.callback-lifetime.sync constructor exception at post-native-loglevel releases partial native ownership",+ "rdkafka-hs-integration.callback-lifetime.async rebalance callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.async commit callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.sync rebalance callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.sync commit callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.replaced producer delivery callbacks both release",+ "rdkafka-hs-integration.callback-lifetime.async concurrent destruction joins at native entry",+ "rdkafka-hs-integration.callback-lifetime.async concurrent destruction joins at native completion",+ "rdkafka-hs-integration.callback-lifetime.async concurrent destruction joins at native shutdown callback",+ "rdkafka-hs-integration.callback-lifetime.sync concurrent destruction joins at native entry",+ "rdkafka-hs-integration.callback-lifetime.sync concurrent destruction joins at native completion",+ "rdkafka-hs-integration.callback-lifetime.sync concurrent destruction joins at native shutdown callback",+ "rdkafka-hs-integration.callback-lifetime.async cancellation at native entry preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.async cancellation at native completion preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.async cancellation at native shutdown callback preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation at native entry preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation at native completion preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation at native shutdown callback preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.async cancellation after poll stop and queue detachment preserves teardown",+ "rdkafka-hs-integration.callback-lifetime.producer constructor cancellation at partial registration releases its owner",+ "rdkafka-hs-integration.callback-lifetime.producer constructor cancellation at native acceptance releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-async constructor cancellation at partial registration releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-async constructor cancellation at native acceptance releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-sync constructor cancellation at partial registration releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-sync constructor cancellation at native acceptance releases its owner",+ "rdkafka-hs-integration.callback-lifetime.async cancellation while waiting for active callback permits retry",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation while waiting for active callback permits retry",+ "rdkafka-hs-integration.callback-lifetime.async closed consumer GC releases its registrations once",+ "rdkafka-hs-integration.callback-lifetime.sync closed consumer GC releases its registrations once",+ "rdkafka-hs-integration.callback-lifetime.producer error callback remains live through close and releases on GC",+ "rdkafka-hs-integration.callback-lifetime.producer log callback remains live through close and releases on GC",+ "rdkafka-hs-integration.callback-lifetime.producer stats callback remains live through close and releases on GC",+ "rdkafka-hs-integration.callback-lifetime.failed native construction releases the caller-owned duplicate config",+ "rdkafka-hs-integration.transaction-errors.transaction-error-leak-probe releases 300 immediate native errors",+ "rdkafka-hs-integration.transaction-errors.native allocation control detects the inherited three-error leak",+ "rdkafka-hs-integration.transaction-errors.initialization timeout destroys its native error on each retry",+ "rdkafka-hs-integration.transaction-errors.zero-timeout initialization resumes successfully against the broker",+ "rdkafka-hs-integration.transaction-errors.transaction state errors preserve empty commit and abort recovery",+ "rdkafka-hs-integration.transaction-errors.duplicate transactional IDs report a real fatal fencing error",+ "rdkafka-hs-integration.transaction-errors.broker-rejected delivery requires abort and permits a successful new transaction",+ "rdkafka-hs-integration.transaction-errors.init without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.begin without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.abort without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.commit without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.offset without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.init NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.begin NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.abort NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.commit NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.offset NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.init invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.begin invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.abort invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.commit invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.offset invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 0 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 1 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 2 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 3 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 4 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 5 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 6 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 7 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 0 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 1 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 2 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 3 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 4 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 5 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 6 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 7 before destruction",+ "rdkafka-hs-integration.transaction-errors.init cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.begin cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.abort cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 21 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 22 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 23 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 21 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 22 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 23 releases once",+ "rdkafka-hs-integration.transaction-errors.async commit publishes output and source next offset atomically; abort publishes neither",+ "rdkafka-hs-integration.transaction-errors.sync commit publishes output and source next offset atomically; abort publishes neither",+ "rdkafka-hs-integration.lifecycle.flushProducerTimeout times out, purgeProducer empties the queue",+ "rdkafka-hs-integration.lifecycle.consumerClosed is False until closeConsumer",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials replaces credentials on a consumer",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials replaces credentials on a producer",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials rejects NUL in username without changing producer or consumer identity",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials rejects NUL in password without changing producer or consumer identity",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials releases each actual native error after decoding its exact code",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials cancellation at error decoding releases the owned error",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials cancellation at error acquisition releases the owned error",+ "rdkafka-hs-integration.topic-configuration.singleton configuration reaches the broker",+ "rdkafka-hs-integration.topic-configuration.native allocation control detects a retained request",+ "rdkafka-hs-integration.topic-configuration.setter rejection releases allocated request before submission",+ "rdkafka-hs-integration.topic-configuration.interruption after allocation releases request before submission",+ "rdkafka-hs-integration.topic-configuration.multiple configuration entries reach the broker",+ "rdkafka-hs-integration.topic-configuration.broker-rejected values release requests and response events repeatedly",+ "rdkafka-hs-integration.topic-configuration.mismatched topic in an error response cannot report another topic's error",+ "rdkafka-hs-integration.topic-configuration.unrepresentable partition count never wraps to broker defaults",+ "rdkafka-hs-integration.topic-configuration.NUL in a topic name never creates a truncated topic",+ "rdkafka-hs-integration.topic-configuration.unresponsive broker preserves the native timeout error",+ "rdkafka-hs-integration.topic-configuration.empty configuration creates a usable topic",+ "rdkafka-hs-integration.topic-configuration.later setter rejection releases partially configured request",+ "rdkafka-hs-integration.topic-configuration.duplicate creation preserves the existing topic",+ "rdkafka-hs-integration.topic-configuration.deletion removes exactly the existing topic",+ "rdkafka-hs-integration.topic-configuration.missing topic deletion preserves its error and releases the request",+ "rdkafka-hs-integration.topic-configuration.NUL deletion cannot remove a truncated victim name",+ "rdkafka-hs-integration.topic-configuration.broker default partition and replication counts remain supported",+ "rdkafka-hs-integration.topic-configuration.replication above the available broker count is rejected",+ "rdkafka-hs-integration.topic-configuration.unsupported configuration follows the declared broker policy",+ "rdkafka-hs-integration.topic-configuration.minimum unrepresentable partition count is rejected",+ "rdkafka-hs-integration.topic-configuration.maximum unrepresentable replication count is rejected",+ "rdkafka-hs-integration.topic-configuration.minimum unrepresentable replication count is rejected",+ "rdkafka-hs-integration.topic-configuration.NUL configuration key is rejected before native allocation",+ "rdkafka-hs-integration.topic-configuration.NUL configuration value is rejected before native allocation",+ "rdkafka-hs-integration.topic-configuration.negative invalid partition count retains native validation",+ "rdkafka-hs-integration.topic-configuration.maximum C partition count retains native validation",+ "rdkafka-hs-integration.topic-configuration.negative invalid replication count retains native validation",+ "rdkafka-hs-integration.topic-configuration.maximum C replication count retains native validation",+ "rdkafka-hs-integration.topic-configuration.empty topic name is rejected by the broker",+ "rdkafka-hs-integration.topic-configuration.space in a topic name is rejected by the broker",+ "rdkafka-hs-integration.topic-configuration.overlong topic name is rejected by the broker",+ "rdkafka-hs-integration.topic-configuration.zero partition count is rejected by the broker",+ "rdkafka-hs-integration.topic-configuration.zero replication count is rejected by the broker",+ "rdkafka-hs-integration.topic-configuration.wrong event type fails and releases its event",+ "rdkafka-hs-integration.topic-configuration.empty response fails and releases its event",+ "rdkafka-hs-integration.topic-configuration.wrong topic response cannot report success",+ "rdkafka-hs-integration.topic-configuration.missing polled event reports a timeout",+ "rdkafka-hs-integration.topic-configuration.delayed response succeeds with balanced ownership",+ "rdkafka-hs-integration.topic-configuration.consumer administration applies settings in async mode",+ "rdkafka-hs-integration.topic-configuration.consumer administration applies settings in sync mode",+ "rdkafka-hs-integration.topic-configuration.consumer administration applies settings in async-closed mode",+ "rdkafka-hs-integration.topic-configuration.consumer administration applies settings in sync-closed mode",+ "rdkafka-hs-integration.topic-configuration.concurrent requests keep their own queues and responses",+ "rdkafka-hs-integration.topic-configuration.unresponsive deletion preserves the native timeout error",+ "rdkafka-hs-integration.topic-configuration.deletion rejects a wrong event type and releases it",+ "rdkafka-hs-integration.topic-configuration.deletion rejects an empty result and releases its event",+ "rdkafka-hs-integration.topic-configuration.deletion rejects a mismatched topic result",+ "rdkafka-hs-integration.topic-configuration.deletion reports a missing response as a timeout",+ "rdkafka-hs-integration.topic-configuration.missing native timeout configuration returns an error",+ "rdkafka-hs-integration.topic-configuration.malformed native timeout configuration returns an error",+ "rdkafka-hs-integration.topic-configuration.zero native timeout configuration returns an error",+ "rdkafka-hs-integration.topic-configuration.negative native timeout configuration returns an error",+ "rdkafka-hs-integration.topic-configuration.overflowing native timeout configuration returns an error",+ "rdkafka-hs-integration.topic-configuration.oversized native timeout configuration never reads a truncated buffer",+ "rdkafka-hs-integration.producer-regressions.explicit topic timeout expires an accepted message",+ "rdkafka-hs-integration.producer-regressions.global timeout still expires an accepted message",+ "rdkafka-hs-integration.producer-regressions.queue-full rejection releases callback capture without invoking it",+ "rdkafka-hs-integration.producer-regressions.accepted callback retains its capture until a purged report completes",+ "rdkafka-hs-integration.producer-regressions.throwing global callback preserves per-message delivery and releases capture",+ "rdkafka-hs-integration.producer-regressions.throwing per-message callback reports exception and releases capture",+ "rdkafka-hs-integration.producer-regressions.repeated queue-full rejections release every callback capture",+ "rdkafka-hs-integration.producer-regressions.cancellation at a rejected enqueue releases capture before unmasking",+ "rdkafka-hs-integration.producer-regressions.cancellation after native acceptance retains callback until its report",+ "rdkafka-hs-integration.producer-regressions.another poller can deliver before successful enqueue returns",+ "rdkafka-hs-integration.producer-regressions.running callback keeps its capture after the native root is released",+ "rdkafka-hs-integration.producer-regressions.native error decoding failure releases rejected callback capture",+ "rdkafka-hs-integration.producer-regressions.non-null native success-code error rejects and releases capture",+ "rdkafka-hs-integration.producer-regressions.unknown native error code is preserved instead of reading errno",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: defaults",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: global only",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: topic only",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: disjoint maps",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: explicit topic wins duplicate",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: last topic property wins",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: empty topic map preserves global",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: zero topic timeout is infinite",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: maximum native topic timeout",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: explicit topic wins native timeout alias",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: topic codec overrides global codec",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: global codec survives unrelated topic keys",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with NoCompression",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Gzip",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Snappy",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Lz4",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Zstd",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: none",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: inflight",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue+inflight",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue+nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: inflight+nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: all",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: none",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: inflight",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue+inflight",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue+nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: inflight+nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: all",+ "rdkafka-hs-integration.producer-regressions.bounded flush timeout recovers when the delayed response arrives",+ "rdkafka-hs-integration.producer-regressions.close retries a timed-out flush until the delayed delivery completes",+ "rdkafka-hs-integration.producer-regressions.oversized rejection releases capture without a delivery report",+ "rdkafka-hs-integration.producer-regressions.known invalid partition rejection releases capture",+ "rdkafka-hs-integration.producer-regressions.empty queue supports repeated flush and close",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: NUL topic name",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: NUL header name",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: maximum unrepresentable partition",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: minimum unrepresentable partition",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: unknown global key",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: unknown topic key",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: invalid topic timeout",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: excessive topic timeout",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: global-only key in topic map",+ "rdkafka-hs-integration.producer-regressions.later delivery callback replaces the earlier callback",+ "rdkafka-hs-integration.producer-regressions.null native delivery frame reports the generic errno fallback without dereferencing a message",+ "rdkafka-hs-integration.producer-regressions.native delivery without an opaque Haskell callback preserves the complete record",+ "rdkafka-hs-integration.producer-regressions.delivery header acquisition failure preserves the outcome with empty headers",+ "rdkafka-hs-integration.producer-properties.callback composition preserves order and identity",+ "rdkafka-hs-integration.consumer-properties.consumer callback composition preserves registration order and identity",+ "rdkafka-hs-integration.consumer-properties.generated source offsets reach native code as the representable next position",+ "rdkafka-hs-integration.consumer-properties.async later subscription reset reaches the native consumer",+ "rdkafka-hs-integration.consumer-properties.sync later subscription reset reaches the native consumer",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.counter detects a retained native list before explicit release",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.pair conversion failure releases the partial list before GC",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.offset conversion failure releases the partial list before GC",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.ordinary input lists release after exact native results",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.native logical offsets decode independently without losing partition identity",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.missing native partition queue preserves assignment and later forwarding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.assignment outputs release after exact decoding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.subscription outputs release after exact decoding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.subscription acquisition failure preserves the native error without a list",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.assignment decoder failure releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.subscription decoder failure releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.cancellation at input allocation releases the owned list",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.cancellation at assignment return releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.pair conversion failure releases the partial list before GC",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.offset conversion failure releases the partial list before GC",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.ordinary input lists release after exact native results",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.native logical offsets decode independently without losing partition identity",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.missing native partition queue preserves assignment and later forwarding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.assignment outputs release after exact decoding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.subscription outputs release after exact decoding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.subscription acquisition failure preserves the native error without a list",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.assignment decoder failure releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.subscription decoder failure releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.cancellation at input allocation releases the owned list",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.cancellation at assignment return releases the owned output",+ "rdkafka-hs-integration.public-contract.messages.batch conversion releases every returned native message",+ "rdkafka-hs-integration.public-contract.messages.native message counter detects a retained final object",+ "rdkafka-hs-integration.public-contract.messages.batch decoder exception releases unprocessed messages",+ "rdkafka-hs-integration.public-contract.messages.batch native header errors remain errors while later records are released",+ "rdkafka-hs-integration.public-contract.messages.batch cancellation at native return releases every acquired message",+ "rdkafka-hs-integration.public-contract.messages.batch cancellation at middle conversion releases every acquired message",+ "rdkafka-hs-integration.public-contract.messages.async single cancellation at native return releases its native message",+ "rdkafka-hs-integration.public-contract.messages.async single cancellation at inside conversion releases its native message",+ "rdkafka-hs-integration.public-contract.messages.sync single cancellation at native return releases its native message",+ "rdkafka-hs-integration.public-contract.messages.sync single cancellation at inside conversion releases its native message",+ "rdkafka-hs-integration.public-contract.messages.async header failure preserves the polled record origin",+ "rdkafka-hs-integration.public-contract.messages.sync header failure preserves the polled record origin",+ "rdkafka-hs-integration.public-contract.messages.async plain polling surfaces native header failure",+ "rdkafka-hs-integration.public-contract.messages.sync plain polling surfaces native header failure",+ "rdkafka-hs-integration.public-contract.messages.async attributed error preserves independently absent partition-and-offset",+ "rdkafka-hs-integration.public-contract.messages.async attributed error preserves independently absent offset",+ "rdkafka-hs-integration.public-contract.messages.async attributed error preserves independently absent partition",+ "rdkafka-hs-integration.public-contract.messages.sync attributed error preserves independently absent partition-and-offset",+ "rdkafka-hs-integration.public-contract.messages.sync attributed error preserves independently absent offset",+ "rdkafka-hs-integration.public-contract.messages.sync attributed error preserves independently absent partition",+ "rdkafka-hs-integration.public-contract.messages.callback-event polling cancellation releases a returned message",+ "rdkafka-hs-integration.public-contract.messages.callback buffer preserves attributed header failure",+ "rdkafka-hs-integration.public-contract.messages.callback buffer preserves plain header failure",+ "rdkafka-hs-integration.public-contract.messages.originless callback error survives seek filtering and a paused partition",+ "rdkafka-hs-integration.public-contract.messages.callback-event polling releases and discards a returned fatal frame",+ "rdkafka-hs-integration.public-contract.messages.zero batch size leaves the queued records available",+ "rdkafka-hs-integration.public-contract.messages.unsupported sync batch does not discard a record",+ "rdkafka-hs-integration.public-contract.messages.signed native batch failure preserves its error and queued data",+ "rdkafka-hs-integration.public-contract.messages.infinite batch timeout returns available records",+ "rdkafka-hs-integration.public-contract.messages.batch capacity 1 preserves complete ordered records across partial batches",+ "rdkafka-hs-integration.public-contract.messages.batch capacity 2 preserves complete ordered records across partial batches",+ "rdkafka-hs-integration.public-contract.messages.batch capacity 5 preserves complete ordered records across partial batches",+ "rdkafka-hs-integration.public-contract.messages.invalid batch array size is rejected before native acquisition: -1",+ "rdkafka-hs-integration.public-contract.messages.invalid batch array size is rejected before native acquisition: -9223372036854775808",+ "rdkafka-hs-integration.public-contract.messages.invalid batch array size is rejected before native acquisition: 9223372036854775807",+ "rdkafka-hs-integration.public-contract.messages.batch preserves complete records followed by exact partition EOF and idle timeout",+ "rdkafka-hs-integration.public-contract.messages.empty batch respects timeout 0",+ "rdkafka-hs-integration.public-contract.messages.empty batch respects timeout 100",+ "rdkafka-hs-integration.public-contract.rebalance-errors.native rebalance counter detects an undisposed error",+ "rdkafka-hs-integration.public-contract.rebalance-errors.async real cooperative assignment and revocation preserve records",+ "rdkafka-hs-integration.public-contract.rebalance-errors.sync real cooperative assignment and revocation preserve records",+ "rdkafka-hs-integration.public-contract.rebalance-errors.cooperative assign async native reports failure without a success event",+ "rdkafka-hs-integration.public-contract.rebalance-errors.cooperative assign async decode reports failure without a success event",+ "rdkafka-hs-integration.public-contract.rebalance-errors.cooperative assign sync native reports failure without a success event",+ "rdkafka-hs-integration.public-contract.rebalance-errors.cooperative assign sync decode reports failure without a success event",+ "rdkafka-hs-integration.public-contract.rebalance-errors.cooperative revoke async native reports failure without a success event",+ "rdkafka-hs-integration.public-contract.rebalance-errors.cooperative revoke async decode reports failure without a success event",+ "rdkafka-hs-integration.public-contract.rebalance-errors.cooperative revoke sync native reports failure without a success event",+ "rdkafka-hs-integration.public-contract.rebalance-errors.cooperative revoke sync decode reports failure without a success event",+ "rdkafka-hs-integration.public-contract.rebalance-errors.eager assign async native reports failure without a success event",+ "rdkafka-hs-integration.public-contract.rebalance-errors.eager assign sync native reports failure without a success event",+ "rdkafka-hs-integration.public-contract.rebalance-errors.eager revoke async native reports failure without a success event",+ "rdkafka-hs-integration.public-contract.rebalance-errors.eager revoke sync native reports failure without a success event",+ "rdkafka-hs-integration.public-contract.rebalance-errors.async unexpected rebalance error clears assignment and pending records",+ "rdkafka-hs-integration.public-contract.rebalance-errors.async unexpected rebalance error preserves state when native reset fails",+ "rdkafka-hs-integration.public-contract.rebalance-errors.sync unexpected rebalance error clears assignment and pending records",+ "rdkafka-hs-integration.public-contract.rebalance-errors.sync unexpected rebalance error preserves state when native reset fails",+ "rdkafka-hs-integration.public-contract.consumer-state.async.assignment-replacement",+ "rdkafka-hs-integration.public-contract.consumer-state.async.unknown-assignment-reports-through-error-callback-and-recovers",+ "rdkafka-hs-integration.public-contract.consumer-state.async.representable-partition-boundaries-keep-native-query-semantics",+ "rdkafka-hs-integration.public-contract.consumer-state.async.deprecated-seek-reports-unassigned-state-and-recovers-after-assignment",+ "rdkafka-hs-integration.public-contract.consumer-state.async.subscription-preserves-the-exact-multiple-topic-set",+ "rdkafka-hs-integration.public-contract.consumer-state.async.empty-requests-preserve-empty-assignment",+ "rdkafka-hs-integration.public-contract.consumer-state.async.unknown-position-is-invalid-without-native-error",+ "rdkafka-hs-integration.public-contract.consumer-state.async.multiple-assigned-partitions-retain-the-exact-topic-map",+ "rdkafka-hs-integration.public-contract.consumer-state.async.legacy-seek-constructor-failure-does-not-execute-an-earlier-valid-seek",+ "rdkafka-hs-integration.public-contract.consumer-state.async.pause-resume-preserves-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-event-poll-preserves-application-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-seek-replaces-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-reassignment-replaces-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-pause-defers-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-legacy-seek-replaces-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-legacy-partial-seek-keeps-success",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-paused-partition-does-not-block-another",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-unassignment-discards-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.pausing-one-partition-leaves-the-other-running",+ "rdkafka-hs-integration.public-contract.consumer-state.async.pause-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.async.resume-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.async.store-commit-next-offset",+ "rdkafka-hs-integration.public-contract.consumer-state.async.store-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.async.position-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.async.deprecated-seek-exact-repeated-replay",+ "rdkafka-hs-integration.public-contract.consumer-state.async.explicit-subscription-overrides-global-reset",+ "rdkafka-hs-integration.public-contract.consumer-state.async.regex-subscription-selects-run-owned-topic",+ "rdkafka-hs-integration.public-contract.consumer-state.async.global-topic-setting-survives-empty-subscription-properties",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.assignment-replacement",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.unknown-assignment-reports-through-error-callback-and-recovers",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.representable-partition-boundaries-keep-native-query-semantics",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.deprecated-seek-reports-unassigned-state-and-recovers-after-assignment",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.subscription-preserves-the-exact-multiple-topic-set",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.empty-requests-preserve-empty-assignment",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.unknown-position-is-invalid-without-native-error",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.multiple-assigned-partitions-retain-the-exact-topic-map",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.legacy-seek-constructor-failure-does-not-execute-an-earlier-valid-seek",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.pause-resume-preserves-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-event-poll-preserves-application-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-seek-replaces-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-reassignment-replaces-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-pause-defers-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-legacy-seek-replaces-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-legacy-partial-seek-keeps-success",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-paused-partition-does-not-block-another",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-unassignment-discards-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.pausing-one-partition-leaves-the-other-running",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.pause-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.resume-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.store-commit-next-offset",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.store-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.position-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.deprecated-seek-exact-repeated-replay",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.explicit-subscription-overrides-global-reset",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.regex-subscription-selects-run-owned-topic",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.global-topic-setting-survives-empty-subscription-properties",+ "rdkafka-hs-integration.public-contract.consumer-state.sync-buffer-fields-native-time",+ "rdkafka-hs-integration.public-contract.consumer-state.sync-buffer-fields-no-time",+ "rdkafka-hs-integration.public-contract.consumer-state.sync-buffer-fields-append-time",+ "rdkafka-hs-integration.public-contract.consumer-state.sync-buffer-fields-create-time",+ "rdkafka-hs-integration.public-contract.consumer-state.cooperative subset callbacks preserve unrelated buffers pauses and originless errors",+ "rdkafka-hs-integration.public-contract.consumer-state.sync callback mixed seek retains only the failed partition's copied records",+ "rdkafka-hs-integration.public-contract.consumer-commit.async commit modes preserve native flags callback offsets and broker state",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync commit modes preserve native flags callback offsets and broker state",+ "rdkafka-hs-integration.public-contract.consumer-commit.async message and stored commits preserve unrelated partition offsets",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync message and stored commits preserve unrelated partition offsets",+ "rdkafka-hs-integration.public-contract.consumer-commit.async empty commit requests preserve no-offset callbacks",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync empty commit requests preserve no-offset callbacks",+ "rdkafka-hs-integration.public-contract.consumer-commit.async mixed broker commit failures preserve successful offsets",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync mixed broker commit failures preserve successful offsets",+ "rdkafka-hs-integration.public-contract.consumer-commit.async committed query preserves an unavailable coordinator timeout",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync committed query preserves an unavailable coordinator timeout",+ "rdkafka-hs-integration.public-contract.diagnostics.supported-property print flushes and preserves the caller handle",+ "rdkafka-hs-integration.public-contract.diagnostics.client print flushes and preserves the caller handle",+ "rdkafka-hs-integration.public-contract.diagnostics.failed fdopen releases the duplicate and preserves the original",+ "rdkafka-hs-integration.public-contract.diagnostics.failed native flush is reported after closing the duplicate",+ "rdkafka-hs-integration.public-contract.diagnostics.producer configuration dumps retain exact explicit and global settings",+ "rdkafka-hs-integration.public-contract.diagnostics.producer constructor log level overrides the global property on the native client",+ "rdkafka-hs-integration.public-contract.diagnostics.consumer configuration dump preserves global settings after subscription merge",+ "rdkafka-hs-integration.public-contract.diagnostics.native dump counter detects an unreleased array",+ "rdkafka-hs-integration.public-contract.diagnostics.global cancellation at native acquisition releases its array",+ "rdkafka-hs-integration.public-contract.diagnostics.topic cancellation at native acquisition releases its array",+ "rdkafka-hs-integration.public-contract.input-boundaries.async assign rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async pause rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async resume rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async store rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async store-message rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async commit rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async commit-message rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async committed rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async position rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async legacy-seek rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async seek rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async timestamp rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async watermark rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async assign rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async pause rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async resume rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async store rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async store-message rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async commit rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async commit-message rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async committed rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async position rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async legacy-seek rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async seek rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async timestamp rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async watermark rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async assign rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async pause rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async resume rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async store rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async store-message rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async commit rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async commit-message rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async committed rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async position rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async legacy-seek rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async seek rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async timestamp rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async watermark rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync assign rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync pause rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync resume rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync store rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync store-message rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync commit rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync commit-message rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync committed rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync position rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync legacy-seek rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync seek rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync timestamp rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync watermark rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync assign rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync pause rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync resume rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync store rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync store-message rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync commit rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync commit-message rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync committed rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync position rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync legacy-seek rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync seek rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync timestamp rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync watermark rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync assign rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync pause rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync resume rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync store rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync store-message rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync commit rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync commit-message rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync committed rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync position rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync legacy-seek rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync seek rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync timestamp rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync watermark rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async string queries and subscription reject NUL before native effects",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync string queries and subscription reject NUL before native effects",+ "rdkafka-hs-integration.public-contract.deprecated-runners.producer flushes after Returned",+ "rdkafka-hs-integration.public-contract.deprecated-runners.producer flushes after Refused",+ "rdkafka-hs-integration.public-contract.deprecated-runners.producer flushes after Thrown",+ "rdkafka-hs-integration.public-contract.deprecated-runners.async consumer closes after Returned",+ "rdkafka-hs-integration.public-contract.deprecated-runners.async consumer closes after Refused",+ "rdkafka-hs-integration.public-contract.deprecated-runners.async consumer closes after Thrown",+ "rdkafka-hs-integration.public-contract.deprecated-runners.sync consumer closes after Returned",+ "rdkafka-hs-integration.public-contract.deprecated-runners.sync consumer closes after Refused",+ "rdkafka-hs-integration.public-contract.deprecated-runners.sync consumer closes after Thrown",+ "rdkafka-hs-integration.public-contract.deprecated-runners.producer preserves native construction failure without invoking handler",+ "rdkafka-hs-integration.public-contract.deprecated-runners.producer preserves configuration exceptions without invoking handler",+ "rdkafka-hs-integration.public-contract.deprecated-runners.async consumer preserves native construction failure",+ "rdkafka-hs-integration.public-contract.deprecated-runners.async consumer preserves configuration construction failure",+ "rdkafka-hs-integration.public-contract.deprecated-runners.sync consumer preserves native construction failure",+ "rdkafka-hs-integration.public-contract.deprecated-runners.sync consumer preserves configuration construction failure",+ "rdkafka-hs-integration.public-contract.fatal.async",+ "rdkafka-hs-integration.public-contract.fatal.sync",+ "rdkafka-hs-integration.public-contract.queue event.empty pipes are idle but invalid descriptor errors are preserved",+ "rdkafka-hs-integration.public-contract.queue event.async.wakes an idle consumer and stays quiet once disabled",+ "rdkafka-hs-integration.public-contract.queue event.async.finds records queued before it was enabled, then rearms",+ "rdkafka-hs-integration.public-contract.queue event.async.one wake-up covers several records, then rearms",+ "rdkafka-hs-integration.public-contract.queue event.async.binary payloads retain every byte and empty payloads preserve records",+ "rdkafka-hs-integration.public-contract.queue event.async.native record errors are never treated as idle",+ "rdkafka-hs-integration.public-contract.queue event.async.close stops notifications and keeps caller descriptors open",+ "rdkafka-hs-integration.public-contract.queue event.async.destroy stops notifications and keeps caller descriptors open",+ "rdkafka-hs-integration.public-contract.queue event.sync.wakes an idle consumer and stays quiet once disabled",+ "rdkafka-hs-integration.public-contract.queue event.sync.finds records queued before it was enabled, then rearms",+ "rdkafka-hs-integration.public-contract.queue event.sync.one wake-up covers several records, then rearms",+ "rdkafka-hs-integration.public-contract.queue event.sync.binary payloads retain every byte and empty payloads preserve records",+ "rdkafka-hs-integration.public-contract.queue event.sync.native record errors are never treated as idle",+ "rdkafka-hs-integration.public-contract.queue event.sync.close stops notifications and keeps caller descriptors open",+ "rdkafka-hs-integration.public-contract.queue event.sync.destroy stops notifications and keeps caller descriptors open",+ "rdkafka-hs-integration.public-contract.runtime-contract.RTS capability is observed by async construction",+ "rdkafka-hs-integration.public-contract.runtime-contract.explicit async construction checks the runtime",+ "rdkafka-hs-integration.public-contract.runtime-contract.sync subscription delivers an exact record",+ "rdkafka-hs-integration.public-contract.runtime-contract.deprecated sync runner closes after an exact record",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata counter detects an unreleased result",+ "rdkafka-hs-integration.public-contract.metadata-contract.native topic-constructor failure survives metadata convenience queries",+ "rdkafka-hs-integration.public-contract.metadata-contract.empty native metadata remains empty and releases every result",+ "rdkafka-hs-integration.public-contract.metadata-contract.timestamp lookup preserves native overall errors",+ "rdkafka-hs-integration.public-contract.metadata-contract.watermark queries preserve unknown partition errors and empty provided metadata",+ "rdkafka-hs-integration.public-contract.metadata-contract.topic identity replica sets and exact watermarks",+ "rdkafka-hs-integration.public-contract.metadata-contract.distinct native metadata fields retain exact identities and errors",+ "rdkafka-hs-integration.public-contract.metadata-contract.provided metadata preserves partition failures in convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata partition failures survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.group query timeout preserves initial metadata wait failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.missing topic errors survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.timestamp lookup distinguishes before at and after actual record times",+ "rdkafka-hs-integration.public-contract.metadata-contract.mixed timestamp request preserves native partition failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata timeouts preserve the native error",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.groups native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.async group identity lifecycle and supported native states",+ "rdkafka-hs-integration.public-contract.metadata-contract.sync group identity lifecycle and supported native states",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.empty producer client id retains the native default",+ "rdkafka-hs-integration.public-contract.config-strings.consumer ordinary UTF8 values remain exact",+ "rdkafka-hs-integration.public-contract.config-strings.empty global key retains native unknown-key rejection",+ "rdkafka-hs-integration.seek-partitions.async.unassigned member reports native error",+ "rdkafka-hs-integration.seek-partitions.async.empty list preserves top-level invalid argument",+ "rdkafka-hs-integration.seek-partitions.async.zero-timeout unassigned failure is immediate",+ "rdkafka-hs-integration.seek-partitions.async.empty zero-timeout preserves top-level error",+ "rdkafka-hs-integration.seek-partitions.async.rewind without assignment does not seek",+ "rdkafka-hs-integration.seek-partitions.async.top-level error precedes member error and is destroyed",+ "rdkafka-hs-integration.seek-partitions.async.first substantive error follows input order",+ "rdkafka-hs-integration.seek-partitions.async.reversed input selects the other substantive error",+ "rdkafka-hs-integration.seek-partitions.async.zero-timeout skips pending but reports later failure",+ "rdkafka-hs-integration.seek-partitions.async.nonzero-timeout preserves residual pending",+ "rdkafka-hs-integration.seek-partitions.async.zero-timeout all pending promises initiation only",+ "rdkafka-hs-integration.seek-partitions.async.nonzero-timeout all pending is not success",+ "rdkafka-hs-integration.seek-partitions.async.top-level decoder exception still destroys error object",+ "rdkafka-hs-integration.seek-partitions.async.rewind assignment failure prevents seek",+ "rdkafka-hs-integration.seek-partitions.async.single seek replays exact record",+ "rdkafka-hs-integration.seek-partitions.async.multiple successful seeks replay both partitions",+ "rdkafka-hs-integration.seek-partitions.async.mixed seek reports failure without rolling back success",+ "rdkafka-hs-integration.seek-partitions.async.mixed errors follow actual request order",+ "rdkafka-hs-integration.seek-partitions.async.zero-timeout valid seek is followed by synchronous replay",+ "rdkafka-hs-integration.seek-partitions.async.zero-timeout mixed request keeps immediate unknown error",+ "rdkafka-hs-integration.seek-partitions.async.zero-timeout logical offsets promise initiation only",+ "rdkafka-hs-integration.seek-partitions.async.infinite native timeout completes a valid seek",+ "rdkafka-hs-integration.seek-partitions.async.duplicate entries preserve residual native pending error",+ "rdkafka-hs-integration.seek-partitions.async.unassigned existing partition returns state error",+ "rdkafka-hs-integration.seek-partitions.async.unknown topic reports member error",+ "rdkafka-hs-integration.seek-partitions.async.stored sentinel is rejected without altering position",+ "rdkafka-hs-integration.seek-partitions.async.end and exact high watermark produce no record",+ "rdkafka-hs-integration.seek-partitions.async.seek before retained log range resets to actual low watermark",+ "rdkafka-hs-integration.seek-partitions.async.rewind without committed offset starts at beginning",+ "rdkafka-hs-integration.seek-partitions.async.rewind uses committed next offset exactly",+ "rdkafka-hs-integration.seek-partitions.async.rewind message commit resumes after committed message",+ "rdkafka-hs-integration.seek-partitions.async.rewind lookup failure prevents seek",+ "rdkafka-hs-integration.seek-partitions.async.rewind propagates assignment change after committed lookup",+ "rdkafka-hs-integration.seek-partitions.async.beginning sentinel replays offset zero",+ "rdkafka-hs-integration.seek-partitions.async.absolute low watermark replays offset zero",+ "rdkafka-hs-integration.seek-partitions.async.invalid sentinel uses configured earliest reset",+ "rdkafka-hs-integration.seek-partitions.async.above high watermark uses configured earliest reset",+ "rdkafka-hs-integration.seek-partitions.async.native tail sentinel replays final two records",+ "rdkafka-hs-integration.seek-partitions.sync.unassigned member reports native error",+ "rdkafka-hs-integration.seek-partitions.sync.empty list preserves top-level invalid argument",+ "rdkafka-hs-integration.seek-partitions.sync.zero-timeout unassigned failure is immediate",+ "rdkafka-hs-integration.seek-partitions.sync.empty zero-timeout preserves top-level error",+ "rdkafka-hs-integration.seek-partitions.sync.rewind without assignment does not seek",+ "rdkafka-hs-integration.seek-partitions.sync.top-level error precedes member error and is destroyed",+ "rdkafka-hs-integration.seek-partitions.sync.first substantive error follows input order",+ "rdkafka-hs-integration.seek-partitions.sync.reversed input selects the other substantive error",+ "rdkafka-hs-integration.seek-partitions.sync.zero-timeout skips pending but reports later failure",+ "rdkafka-hs-integration.seek-partitions.sync.nonzero-timeout preserves residual pending",+ "rdkafka-hs-integration.seek-partitions.sync.zero-timeout all pending promises initiation only",+ "rdkafka-hs-integration.seek-partitions.sync.nonzero-timeout all pending is not success",+ "rdkafka-hs-integration.seek-partitions.sync.top-level decoder exception still destroys error object",+ "rdkafka-hs-integration.seek-partitions.sync.rewind assignment failure prevents seek",+ "rdkafka-hs-integration.seek-partitions.sync.single seek replays exact record",+ "rdkafka-hs-integration.seek-partitions.sync.multiple successful seeks replay both partitions",+ "rdkafka-hs-integration.seek-partitions.sync.mixed seek reports failure without rolling back success",+ "rdkafka-hs-integration.seek-partitions.sync.mixed errors follow actual request order",+ "rdkafka-hs-integration.seek-partitions.sync.zero-timeout valid seek is followed by synchronous replay",+ "rdkafka-hs-integration.seek-partitions.sync.zero-timeout mixed request keeps immediate unknown error",+ "rdkafka-hs-integration.seek-partitions.sync.zero-timeout logical offsets promise initiation only",+ "rdkafka-hs-integration.seek-partitions.sync.infinite native timeout completes a valid seek",+ "rdkafka-hs-integration.seek-partitions.sync.duplicate entries preserve residual native pending error",+ "rdkafka-hs-integration.seek-partitions.sync.unassigned existing partition returns state error",+ "rdkafka-hs-integration.seek-partitions.sync.unknown topic reports member error",+ "rdkafka-hs-integration.seek-partitions.sync.stored sentinel is rejected without altering position",+ "rdkafka-hs-integration.seek-partitions.sync.end and exact high watermark produce no record",+ "rdkafka-hs-integration.seek-partitions.sync.seek before retained log range resets to actual low watermark",+ "rdkafka-hs-integration.seek-partitions.sync.rewind without committed offset starts at beginning",+ "rdkafka-hs-integration.seek-partitions.sync.rewind uses committed next offset exactly",+ "rdkafka-hs-integration.seek-partitions.sync.rewind message commit resumes after committed message",+ "rdkafka-hs-integration.seek-partitions.sync.rewind lookup failure prevents seek",+ "rdkafka-hs-integration.seek-partitions.sync.rewind propagates assignment change after committed lookup",+ "rdkafka-hs-integration.seek-partitions.sync.beginning sentinel replays offset zero",+ "rdkafka-hs-integration.seek-partitions.sync.absolute low watermark replays offset zero",+ "rdkafka-hs-integration.seek-partitions.sync.invalid sentinel uses configured earliest reset",+ "rdkafka-hs-integration.seek-partitions.sync.above high watermark uses configured earliest reset",+ "rdkafka-hs-integration.seek-partitions.sync.native tail sentinel replays final two records",+ "rdkafka-hs-integration.broker.Per-message commit.1. sends 2 messages to test topic",+ "rdkafka-hs-integration.broker.Per-message commit.2. should receive 2 messages",+ "rdkafka-hs-integration.broker.Per-message commit.3. sends 2 messages to test topic",+ "rdkafka-hs-integration.broker.Per-message commit.4. should receive 2 messages again",+ "rdkafka-hs-integration.broker.Store offsets.1. sends 2 messages to test topic",+ "rdkafka-hs-integration.broker.Store offsets.2. should receive 2 messages without storing",+ "rdkafka-hs-integration.broker.Store offsets.3. sends 2 messages to test topic",+ "rdkafka-hs-integration.broker.Store offsets.4. should receive 4 messages and store them",+ "rdkafka-hs-integration.broker.Store offsets.5. sends 2 messages to test topic",+ "rdkafka-hs-integration.broker.Store offsets.6. should receive 2 messages",+ "rdkafka-hs-integration.broker.Store offsets.Part 3 - Consume after committing stored offsets.5. sends 2 messages to test topic",+ "rdkafka-hs-integration.broker.Store offsets.Part 3 - Consume after committing stored offsets.6. should receive 2 messages",+ "rdkafka-hs-integration.broker.Consumer.Run producer.sends messages to test topic",+ "rdkafka-hs-integration.broker.Consumer.Run producer.sends messages with callback to test topic",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should receive messages",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should get committed",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should get position",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should get watermark offsets",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should return subscription",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should return assignment",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.assignment is not lost",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should return all topics metadata",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should return topic metadata",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should describe all consumer groups",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should describe a given consumer group",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should describe non-existent consumer group",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should read topic offsets for time",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should seek and return no error",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should seek to the beginning",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should seek to the end",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should respect out-of-bound offsets (invalid offset)",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should respect out-of-bound offsets (huge offset)",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should receive messages",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should get committed",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should get position",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should get watermark offsets",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should return subscription",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should return assignment",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.assignment is not lost",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should return all topics metadata",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should return topic metadata",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should describe all consumer groups",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should describe a given consumer group",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should describe non-existent consumer group",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should read topic offsets for time",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should seek and return no error",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should seek to the beginning",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should seek to the end",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should respect out-of-bound offsets (invalid offset)",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should respect out-of-bound offsets (huge offset)",+ "rdkafka-hs-integration.broker.Batch consumer.should consume first batch",+ "rdkafka-hs-integration.broker.Batch consumer.should consume second batch with not enough messages",+ "rdkafka-hs-integration.broker.Batch consumer.should consume empty batch when there are no messages",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessage sync.interleaved duplicate names keep wire order and last values",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessage sync.distinct names keep wire order",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessage sync.identical repeated pairs are not deduplicated",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessage sync.a single header round-trips",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessage sync.no headers decode as an empty list",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessage async.interleaved duplicate names keep wire order and last values",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessage async.distinct names keep wire order",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessage async.identical repeated pairs are not deduplicated",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessage async.a single header round-trips",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessage async.no headers decode as an empty list",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessageAttributed sync.interleaved duplicate names keep wire order and last values",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessageAttributed sync.distinct names keep wire order",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessageAttributed sync.identical repeated pairs are not deduplicated",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessageAttributed sync.a single header round-trips",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessageAttributed sync.no headers decode as an empty list",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessageAttributed async.interleaved duplicate names keep wire order and last values",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessageAttributed async.distinct names keep wire order",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessageAttributed async.identical repeated pairs are not deduplicated",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessageAttributed async.a single header round-trips",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessageAttributed async.no headers decode as an empty list",+ "rdkafka-hs-integration.broker.assign-only.async.newAssignedConsumer",+ "rdkafka-hs-integration.broker.assign-only.async.newConsumer with an empty subscription",+ "rdkafka-hs-integration.broker.assign-only.sync.newAssignedConsumer",+ "rdkafka-hs-integration.broker.assign-only.sync.newConsumer with an empty subscription",+ "rdkafka-hs-integration.broker.attributed.async",+ "rdkafka-hs-integration.broker.attributed.sync",+ "rdkafka-hs-integration.broker.destroy.async.closes broker connections within one second",+ "rdkafka-hs-integration.broker.destroy.async.is safe to repeat",+ "rdkafka-hs-integration.broker.destroy.async.concurrent destroys both return after cleanup",+ "rdkafka-hs-integration.broker.destroy.async.completes after an interrupted destroy",+ "rdkafka-hs-integration.broker.destroy.async.close then destroy, destroy then close",+ "rdkafka-hs-integration.broker.destroy.sync.closes broker connections within one second",+ "rdkafka-hs-integration.broker.destroy.sync.is safe to repeat",+ "rdkafka-hs-integration.broker.destroy.sync.concurrent destroys both return after cleanup",+ "rdkafka-hs-integration.broker.destroy.sync.completes after an interrupted destroy",+ "rdkafka-hs-integration.broker.destroy.sync.close then destroy, destroy then close",+ "rdkafka-hs-integration.broker.read_committed watermark stops before an open transaction",+ "rdkafka-hs-integration.broker.observer.async",+ "rdkafka-hs-integration.broker.observer.sync",+ "rdkafka-hs-integration.broker.Read all topics.should create a topic",+ "rdkafka-hs-integration.broker.Read all topics.should return all the topics",+ "rdkafka-hs-integration.broker.Read all topics.should delete this run's topics"+ ],+ "qualification_contexts": [+ {+ "kind": "qualification-context",+ "mode": "--broker-qualification",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "tests": [+ "broker-failure.async observed leader election preserves exact records and commits",+ "broker-failure.sync observed leader election preserves exact records and commits",+ "broker-failure.eager async handoff pause seek eviction and complete outage recover exact offsets",+ "broker-failure.eager sync handoff pause seek eviction and complete outage recover exact offsets",+ "broker-failure.cooperative async handoff pause seek eviction and complete outage recover exact offsets",+ "broker-failure.cooperative sync handoff pause seek eviction and complete outage recover exact offsets",+ "broker-failure.async transaction commit timeout across full outage retries and preserves read-committed visibility",+ "broker-failure.sync transaction commit timeout across full outage retries and preserves read-committed visibility",+ "broker-failure.cancellation during complete outage restores all owned brokers"+ ],+ "passed": 9,+ "command": [+ "/evidence/native-phase9-binary",+ "--broker-qualification"+ ],+ "environment": {+ "os": "PRETTY_NAME=\"Ubuntu 24.04.5 LTS\"\nNAME=\"Ubuntu\"\nVERSION_ID=\"24.04\"\nVERSION=\"24.04.5 LTS (Noble Numbat)\"\nVERSION_CODENAME=noble\nID=ubuntu\nID_LIKE=debian\nHOME_URL=\"https://www.ubuntu.com/\"\nSUPPORT_URL=\"https://help.ubuntu.com/\"\nBUG_REPORT_URL=\"https://bugs.launchpad.net/ubuntu/\"\nPRIVACY_POLICY_URL=\"https://www.ubuntu.com/legal/terms-and-policies/privacy-policy\"\nUBUNTU_CODENAME=noble\nLOGO=ubuntu-logo",+ "kernel": "Linux 6.18.15",+ "architecture": "aarch64",+ "ghc": "9.14.1",+ "cabal": "3.16.1.0",+ "java": "openjdk 21.0.12.1 2026-08-18\nOpenJDK Runtime Environment (build 21.0.12.1+1-1-24.04.4-Ubuntu)\nOpenJDK 64-Bit Server VM (build 21.0.12.1+1-1-24.04.4-Ubuntu, mixed mode, sharing)",+ "native_version": "2.16.0",+ "broker_version": "Apache Kafka 4.4.0",+ "loaded_native_identity": {+ "observed": "(\"2.16.0\",34603263)",+ "path": "/opt/librdkafka-2.16.0/lib/librdkafka.so.1",+ "sha256": "e4ebf0b82581b51a86a0d861a90c07004b0b1fec67ab71e409b572594846154f"+ },+ "broker_topology": "run-owned three-node combined broker/controllers; ephemeral loopback ports; RF3/min ISR2 fault topics"+ },+ "source": {+ "project": "mori://shinzui/rdkafka-hs",+ "candidate_fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "execution_fingerprint": "74c7156e6fee8653bcec844001fd8f95d703bcf4d8e978a857a9f8f3560b6b0a",+ "revision": "bfa4f2e plus captured source",+ "archive": {+ "path": "dist-compatibility/expanded-source9/candidate.tar.gz",+ "sha256": "a70e4839d24c5e5179ff9a8be48643951e185d604cd8ba3401587730279f3b22"+ },+ "root_file_inventory": {+ "path": "dist-compatibility/expanded-source9/root-functional-files.json",+ "sha256": "69506c90cfc124f3a175a664873f5d8b49aff62a7426265c56c3dd64fcc84c21"+ },+ "archive_file_inventory": {+ "path": "dist-compatibility/expanded-source9/phase9-functional-files.json",+ "sha256": "d0e5d59aa49833ecd1305410c839cbebdbbb418679cecc6de0c2548b142dca4b"+ },+ "archive_comparison": {+ "changed_files": [],+ "added_files": [],+ "omitted_development_files": [+ ".envrc",+ "cabal.project",+ "flake.lock",+ "flake.module.nix",+ "flake.nix",+ "justfile",+ "nix/haskell.nix",+ "nix/pre-commit.nix",+ "nix/redpanda.nix",+ "nix/treefmt.nix"+ ],+ "omitted_project_configuration": {+ "path": "cabal.project",+ "content": "packages: .\n",+ "replacement": "Cabal implicit single package in clean extraction; same package set, no solver/compiler constraints in omitted file"+ },+ "execution_fingerprint": "74c7156e6fee8653bcec844001fd8f95d703bcf4d8e978a857a9f8f3560b6b0a",+ "root_fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ "configuration_sha256": "c6c0771e7da58c35d40170db3ec18cdd2439997e223ef4c088ac3f4e793707f9"+ },+ "listing": "dist-compatibility/expanded-source9/broker-final9-tests.txt",+ "log": "dist-compatibility/expanded-source9/broker-final9.log",+ "artifacts": {+ "dist-compatibility/expanded-source9/broker-final9-tests.txt": "1b2270f302280d667a9a755787ee368fce03adc8f849ef070c54f02d99919b84",+ "dist-compatibility/expanded-source9/broker-final9.log": "f9236628ae671ffa549c4c9ce17ba8ba1acaf5f69e066acfe4ebfe94bd303681",+ "dist-compatibility/expanded-source9/candidate.tar.gz": "a70e4839d24c5e5179ff9a8be48643951e185d604cd8ba3401587730279f3b22",+ "dist-compatibility/expanded-source9/root-functional-files.json": "69506c90cfc124f3a175a664873f5d8b49aff62a7426265c56c3dd64fcc84c21",+ "dist-compatibility/expanded-source9/phase9-functional-files.json": "d0e5d59aa49833ecd1305410c839cbebdbbb418679cecc6de0c2548b142dca4b",+ "dist-compatibility/expanded-source9/source-comparison.json": "635403f708e286d4461d40a3d86842d4c670ac70862a9688e2b5fbd72801ace5",+ "dist-compatibility/expanded-source9/configuration.json": "c6c0771e7da58c35d40170db3ec18cdd2439997e223ef4c088ac3f4e793707f9",+ "dist-compatibility/expanded-source9/fixture-cleanup.json": "22a1434a32c0b23c77e8cb0f788c46ca45dc4129ff55add57033437db77be5aa",+ "dist-compatibility/expanded-source9/phase9-loaded.log": "0ea352a045eddd425369467d19eef2c60d2ca235538e1335b9557897a003d120",+ "dist-compatibility/expanded-source9/phase9-version.log": "6ec9b644a82e1dd0a2ec1c57250b4e2d3043deb9a608d8384f7ec30026876a93"+ }+ },+ {+ "kind": "qualification-context",+ "mode": "--authentication-qualification",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "tests": [+ "authentication-contract.verified TLS authenticated delivery and exact consume/commit in both modes",+ "authentication-contract.authenticated identity without topic ACL receives exact produce denial",+ "authentication-contract.invalid-password producer reports the exact connection failure and no delivery",+ "authentication-contract.untrusted-CA producer reports the exact connection failure and no delivery",+ "authentication-contract.hostname-mismatch producer reports the exact connection failure and no delivery",+ "authentication-contract.invalid-password async consumer reports the exact connection failure",+ "authentication-contract.invalid-password sync consumer reports the exact connection failure",+ "authentication-contract.untrusted-CA async consumer reports the exact connection failure",+ "authentication-contract.untrusted-CA sync consumer reports the exact connection failure",+ "authentication-contract.hostname-mismatch async consumer reports the exact connection failure",+ "authentication-contract.hostname-mismatch sync consumer reports the exact connection failure",+ "authentication-contract.async exact topic/group/admin authorization denials",+ "authentication-contract.sync exact topic/group/admin authorization denials",+ "authentication-contract.producer credential replacement authenticates a new identity after observed reconnect and recovers from invalid replacement",+ "authentication-contract.async consumer credential replacement authenticates after observed reconnect and recovers from invalid replacement",+ "authentication-contract.sync consumer credential replacement authenticates after observed reconnect and recovers from invalid replacement",+ "authentication-contract.interruption destroys owned secure processes, credentials, ACL state and private keys"+ ],+ "passed": 17,+ "command": [+ "/evidence/native-phase9-binary",+ "--authentication-qualification"+ ],+ "environment": {+ "os": "PRETTY_NAME=\"Ubuntu 24.04.5 LTS\"\nNAME=\"Ubuntu\"\nVERSION_ID=\"24.04\"\nVERSION=\"24.04.5 LTS (Noble Numbat)\"\nVERSION_CODENAME=noble\nID=ubuntu\nID_LIKE=debian\nHOME_URL=\"https://www.ubuntu.com/\"\nSUPPORT_URL=\"https://help.ubuntu.com/\"\nBUG_REPORT_URL=\"https://bugs.launchpad.net/ubuntu/\"\nPRIVACY_POLICY_URL=\"https://www.ubuntu.com/legal/terms-and-policies/privacy-policy\"\nUBUNTU_CODENAME=noble\nLOGO=ubuntu-logo",+ "kernel": "Linux 6.18.15",+ "architecture": "aarch64",+ "ghc": "9.14.1",+ "cabal": "3.16.1.0",+ "java": "openjdk 21.0.12.1 2026-08-18\nOpenJDK Runtime Environment (build 21.0.12.1+1-1-24.04.4-Ubuntu)\nOpenJDK 64-Bit Server VM (build 21.0.12.1+1-1-24.04.4-Ubuntu, mixed mode, sharing)",+ "native_version": "2.16.0",+ "broker_version": "Apache Kafka 4.4.0",+ "loaded_native_identity": {+ "observed": "(\"2.16.0\",34603263)",+ "path": "/opt/librdkafka-2.16.0/lib/librdkafka.so.1",+ "sha256": "e4ebf0b82581b51a86a0d861a90c07004b0b1fec67ab71e409b572594846154f"+ },+ "broker_topology": "run-owned one-node combined broker/controller; ephemeral SASL_SSL listener; verified localhost CA; ephemeral PLAIN users and ACLs"+ },+ "source": {+ "project": "mori://shinzui/rdkafka-hs",+ "candidate_fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "execution_fingerprint": "74c7156e6fee8653bcec844001fd8f95d703bcf4d8e978a857a9f8f3560b6b0a",+ "revision": "bfa4f2e plus captured source",+ "archive": {+ "path": "dist-compatibility/expanded-source9/candidate.tar.gz",+ "sha256": "a70e4839d24c5e5179ff9a8be48643951e185d604cd8ba3401587730279f3b22"+ },+ "root_file_inventory": {+ "path": "dist-compatibility/expanded-source9/root-functional-files.json",+ "sha256": "69506c90cfc124f3a175a664873f5d8b49aff62a7426265c56c3dd64fcc84c21"+ },+ "archive_file_inventory": {+ "path": "dist-compatibility/expanded-source9/phase9-functional-files.json",+ "sha256": "d0e5d59aa49833ecd1305410c839cbebdbbb418679cecc6de0c2548b142dca4b"+ },+ "archive_comparison": {+ "changed_files": [],+ "added_files": [],+ "omitted_development_files": [+ ".envrc",+ "cabal.project",+ "flake.lock",+ "flake.module.nix",+ "flake.nix",+ "justfile",+ "nix/haskell.nix",+ "nix/pre-commit.nix",+ "nix/redpanda.nix",+ "nix/treefmt.nix"+ ],+ "omitted_project_configuration": {+ "path": "cabal.project",+ "content": "packages: .\n",+ "replacement": "Cabal implicit single package in clean extraction; same package set, no solver/compiler constraints in omitted file"+ },+ "execution_fingerprint": "74c7156e6fee8653bcec844001fd8f95d703bcf4d8e978a857a9f8f3560b6b0a",+ "root_fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ "configuration_sha256": "c6c0771e7da58c35d40170db3ec18cdd2439997e223ef4c088ac3f4e793707f9"+ },+ "listing": "dist-compatibility/expanded-source9/authentication-final9-tests.txt",+ "log": "dist-compatibility/expanded-source9/authentication-final9.log",+ "artifacts": {+ "dist-compatibility/expanded-source9/authentication-final9-tests.txt": "e011f6a1ed4544904bc4117ebdd30e85339b33c096b3d0619bbff506f5e2e893",+ "dist-compatibility/expanded-source9/authentication-final9.log": "a9cc23df591ca6608c613090bf42ae57ece89c1dc3e3ede7bbc0dee1cbcd2457",+ "dist-compatibility/expanded-source9/candidate.tar.gz": "a70e4839d24c5e5179ff9a8be48643951e185d604cd8ba3401587730279f3b22",+ "dist-compatibility/expanded-source9/root-functional-files.json": "69506c90cfc124f3a175a664873f5d8b49aff62a7426265c56c3dd64fcc84c21",+ "dist-compatibility/expanded-source9/phase9-functional-files.json": "d0e5d59aa49833ecd1305410c839cbebdbbb418679cecc6de0c2548b142dca4b",+ "dist-compatibility/expanded-source9/source-comparison.json": "635403f708e286d4461d40a3d86842d4c670ac70862a9688e2b5fbd72801ace5",+ "dist-compatibility/expanded-source9/configuration.json": "c6c0771e7da58c35d40170db3ec18cdd2439997e223ef4c088ac3f4e793707f9",+ "dist-compatibility/expanded-source9/fixture-cleanup.json": "22a1434a32c0b23c77e8cb0f788c46ca45dc4129ff55add57033437db77be5aa",+ "dist-compatibility/expanded-source9/phase9-loaded.log": "0ea352a045eddd425369467d19eef2c60d2ca235538e1335b9557897a003d120",+ "dist-compatibility/expanded-source9/phase9-version.log": "6ec9b644a82e1dd0a2ec1c57250b4e2d3043deb9a608d8384f7ec30026876a93"+ }+ }+ ],+ "supplemental_runs": [+ {+ "kind": "nonthreaded-runtime",+ "rts_way": "rts_v",+ "tests": [+ "rdkafka-hs-integration.public-contract.runtime-contract.RTS capability is observed by async construction",+ "rdkafka-hs-integration.public-contract.runtime-contract.explicit async construction checks the runtime",+ "rdkafka-hs-integration.public-contract.runtime-contract.sync subscription delivers an exact record",+ "rdkafka-hs-integration.public-contract.runtime-contract.deprecated sync runner closes after an exact record"+ ],+ "passed": 4,+ "command": [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-coverage-nonthreaded/build/aarch64-osx/ghc-9.12.4/rdkafka-hs-1.0.0.1/t/rdkafka-hs-integration/build/rdkafka-hs-integration/rdkafka-hs-integration",+ "-p",+ "/runtime-contract/",+ "+RTS",+ "--read-tix-file=no",+ "-RTS"+ ],+ "build_command": [+ "cabal",+ "build",+ "rdkafka-hs-integration",+ "-f",+ "integration",+ "--enable-coverage",+ "--builddir=dist-coverage-nonthreaded",+ "--ghc-options=-fforce-recomp -F -pgmF scripts/coverage-preprocess.py -single-threaded -with-rtsopts=-T"+ ],+ "merged_modules": [+ "Kafka.Consumer"+ ],+ "raw_tix": "dist-coverage/reports/nonthreaded-runtime.tix",+ "tix": "dist-coverage/reports/nonthreaded-consumer.tix"+ }+ ],+ "toolchain": "9.12.4",+ "cabal": "3.16.1.0",+ "loaded_native": "(\"2.15.0\",34537727)",+ "broker_versions": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "native": "2.15.0",+ "broker": "127.0.0.1:39092",+ "misses": [+ {+ "module": "Kafka.Consumer",+ "source": "src/Kafka/Consumer.hs",+ "line": 868,+ "tick": 113,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer",+ "source": "src/Kafka/Consumer.hs",+ "line": 872,+ "tick": 124,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer",+ "source": "src/Kafka/Consumer.hs",+ "line": 829,+ "tick": 187,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer",+ "source": "src/Kafka/Consumer.hs",+ "line": 881,+ "tick": 392,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer",+ "source": "src/Kafka/Consumer.hs",+ "line": 885,+ "tick": 401,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer",+ "source": "src/Kafka/Consumer.hs",+ "line": 547,+ "tick": 778,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer",+ "source": "src/Kafka/Consumer.hs",+ "line": 547,+ "tick": 779,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer",+ "source": "src/Kafka/Consumer.hs",+ "line": 767,+ "tick": 867,+ "label": "BinBox GuardBinBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer",+ "source": "src/Kafka/Consumer.hs",+ "line": 526,+ "tick": 977,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer",+ "source": "src/Kafka/Consumer.hs",+ "line": 395,+ "tick": 1150,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer",+ "source": "src/Kafka/Consumer.hs",+ "line": 329,+ "tick": 1191,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer",+ "source": "src/Kafka/Consumer.hs",+ "line": 319,+ "tick": 1224,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer",+ "source": "src/Kafka/Consumer.hs",+ "line": 322,+ "tick": 1244,+ "label": "BinBox GuardBinBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer",+ "source": "src/Kafka/Consumer.hs",+ "line": 163,+ "tick": 1384,+ "label": "BinBox GuardBinBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer",+ "source": "src/Kafka/Consumer.hs",+ "line": 139,+ "tick": 1525,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer",+ "source": "src/Kafka/Consumer.hs",+ "line": 139,+ "tick": 1526,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer",+ "source": "src/Kafka/Consumer.hs",+ "line": 140,+ "tick": 1528,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Callbacks",+ "source": "src/Kafka/Consumer/Callbacks.hs",+ "line": 75,+ "tick": 25,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Callbacks",+ "source": "src/Kafka/Consumer/Callbacks.hs",+ "line": 100,+ "tick": 107,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.ConsumerProperties",+ "source": "src/Kafka/Consumer/ConsumerProperties.hs",+ "line": 63,+ "tick": 145,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.ConsumerProperties",+ "source": "src/Kafka/Consumer/ConsumerProperties.hs",+ "line": 63,+ "tick": 146,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.ConsumerProperties",+ "source": "src/Kafka/Consumer/ConsumerProperties.hs",+ "line": 63,+ "tick": 147,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.ConsumerProperties",+ "source": "src/Kafka/Consumer/ConsumerProperties.hs",+ "line": 63,+ "tick": 149,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Convert",+ "source": "src/Kafka/Consumer/Convert.hs",+ "line": 170,+ "tick": 189,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Convert",+ "source": "src/Kafka/Consumer/Convert.hs",+ "line": 84,+ "tick": 267,+ "label": "BinBox GuardBinBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Convert",+ "source": "src/Kafka/Consumer/Convert.hs",+ "line": 138,+ "tick": 374,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Convert",+ "source": "src/Kafka/Consumer/Convert.hs",+ "line": 138,+ "tick": 375,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Convert",+ "source": "src/Kafka/Consumer/Convert.hs",+ "line": 138,+ "tick": 376,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Convert",+ "source": "src/Kafka/Consumer/Convert.hs",+ "line": 143,+ "tick": 377,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Convert",+ "source": "src/Kafka/Consumer/Convert.hs",+ "line": 143,+ "tick": 378,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Convert",+ "source": "src/Kafka/Consumer/Convert.hs",+ "line": 143,+ "tick": 379,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Convert",+ "source": "src/Kafka/Consumer/Convert.hs",+ "line": 143,+ "tick": 380,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Convert",+ "source": "src/Kafka/Consumer/Convert.hs",+ "line": 143,+ "tick": 381,+ "label": "LocalBox [\"toNativeTopicPartitionListNoDispose\",\"to\"]",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Convert",+ "source": "src/Kafka/Consumer/Convert.hs",+ "line": 142,+ "tick": 382,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Convert",+ "source": "src/Kafka/Consumer/Convert.hs",+ "line": 142,+ "tick": 383,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Convert",+ "source": "src/Kafka/Consumer/Convert.hs",+ "line": 141,+ "tick": 384,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Convert",+ "source": "src/Kafka/Consumer/Convert.hs",+ "line": 141,+ "tick": 385,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Convert",+ "source": "src/Kafka/Consumer/Convert.hs",+ "line": 144,+ "tick": 386,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Convert",+ "source": "src/Kafka/Consumer/Convert.hs",+ "line": 144,+ "tick": 387,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Convert",+ "source": "src/Kafka/Consumer/Convert.hs",+ "line": 144,+ "tick": 388,+ "label": "LocalBox [\"toNativeTopicPartitionListNoDispose\",\"tnS\"]",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Convert",+ "source": "src/Kafka/Consumer/Convert.hs",+ "line": 145,+ "tick": 389,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Convert",+ "source": "src/Kafka/Consumer/Convert.hs",+ "line": 145,+ "tick": 390,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Convert",+ "source": "src/Kafka/Consumer/Convert.hs",+ "line": 145,+ "tick": 391,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Convert",+ "source": "src/Kafka/Consumer/Convert.hs",+ "line": 145,+ "tick": 392,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Convert",+ "source": "src/Kafka/Consumer/Convert.hs",+ "line": 146,+ "tick": 393,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Convert",+ "source": "src/Kafka/Consumer/Convert.hs",+ "line": 146,+ "tick": 394,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Convert",+ "source": "src/Kafka/Consumer/Convert.hs",+ "line": 146,+ "tick": 395,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Convert",+ "source": "src/Kafka/Consumer/Convert.hs",+ "line": 146,+ "tick": 396,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Convert",+ "source": "src/Kafka/Consumer/Convert.hs",+ "line": 146,+ "tick": 397,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Convert",+ "source": "src/Kafka/Consumer/Convert.hs",+ "line": 140,+ "tick": 398,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Convert",+ "source": "src/Kafka/Consumer/Convert.hs",+ "line": 140,+ "tick": 399,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Convert",+ "source": "src/Kafka/Consumer/Convert.hs",+ "line": 148,+ "tick": 400,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Convert",+ "source": "src/Kafka/Consumer/Convert.hs",+ "line": 139,+ "tick": 401,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Convert",+ "source": "src/Kafka/Consumer/Convert.hs",+ "line": 149,+ "tick": 402,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Convert",+ "source": "src/Kafka/Consumer/Convert.hs",+ "line": 149,+ "tick": 403,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Convert",+ "source": "src/Kafka/Consumer/Convert.hs",+ "line": 137,+ "tick": 404,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Convert",+ "source": "src/Kafka/Consumer/Convert.hs",+ "line": 137,+ "tick": 405,+ "label": "TopLevelBox [\"toNativeTopicPartitionListNoDispose\"]",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Convert",+ "source": "src/Kafka/Consumer/Convert.hs",+ "line": 63,+ "tick": 406,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Convert",+ "source": "src/Kafka/Consumer/Convert.hs",+ "line": 64,+ "tick": 407,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Convert",+ "source": "src/Kafka/Consumer/Convert.hs",+ "line": 64,+ "tick": 408,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Convert",+ "source": "src/Kafka/Consumer/Convert.hs",+ "line": 65,+ "tick": 409,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Convert",+ "source": "src/Kafka/Consumer/Convert.hs",+ "line": 66,+ "tick": 410,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Convert",+ "source": "src/Kafka/Consumer/Convert.hs",+ "line": 63,+ "tick": 411,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Convert",+ "source": "src/Kafka/Consumer/Convert.hs",+ "line": 62,+ "tick": 412,+ "label": "TopLevelBox [\"offsetSyncToInt\"]",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 188,+ "tick": 73,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 188,+ "tick": 77,+ "label": "TopLevelBox [\"readsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 188,+ "tick": 78,+ "label": "TopLevelBox [\"readList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 170,+ "tick": 84,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 170,+ "tick": 85,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 170,+ "tick": 86,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 170,+ "tick": 87,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 153,+ "tick": 90,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 153,+ "tick": 91,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 153,+ "tick": 92,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 153,+ "tick": 94,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 153,+ "tick": 95,+ "label": "TopLevelBox [\"from\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 153,+ "tick": 96,+ "label": "TopLevelBox [\"to\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 145,+ "tick": 97,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 145,+ "tick": 98,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 145,+ "tick": 99,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 137,+ "tick": 104,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 137,+ "tick": 105,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 137,+ "tick": 106,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 137,+ "tick": 108,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 137,+ "tick": 109,+ "label": "TopLevelBox [\"from\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 137,+ "tick": 110,+ "label": "TopLevelBox [\"to\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 127,+ "tick": 111,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 127,+ "tick": 112,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 127,+ "tick": 113,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 127,+ "tick": 115,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 119,+ "tick": 120,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 119,+ "tick": 123,+ "label": "TopLevelBox [\"readsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 119,+ "tick": 124,+ "label": "TopLevelBox [\"readList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 119,+ "tick": 126,+ "label": "TopLevelBox [\"readListPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 119,+ "tick": 127,+ "label": "TopLevelBox [\"from\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 119,+ "tick": 128,+ "label": "TopLevelBox [\"to\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 112,+ "tick": 129,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 112,+ "tick": 130,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 112,+ "tick": 131,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 112,+ "tick": 133,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 104,+ "tick": 138,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 104,+ "tick": 139,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 104,+ "tick": 140,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 95,+ "tick": 145,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 95,+ "tick": 146,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 95,+ "tick": 147,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 83,+ "tick": 150,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 83,+ "tick": 151,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 83,+ "tick": 152,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 83,+ "tick": 154,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 77,+ "tick": 161,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 77,+ "tick": 164,+ "label": "TopLevelBox [\"<=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 77,+ "tick": 166,+ "label": "TopLevelBox [\">=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 77,+ "tick": 167,+ "label": "TopLevelBox [\"max\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 77,+ "tick": 168,+ "label": "TopLevelBox [\"min\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 77,+ "tick": 169,+ "label": "TopLevelBox [\"readsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 77,+ "tick": 170,+ "label": "TopLevelBox [\"readList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 77,+ "tick": 173,+ "label": "TopLevelBox [\"from\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 77,+ "tick": 174,+ "label": "TopLevelBox [\"to\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 72,+ "tick": 175,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 72,+ "tick": 176,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 72,+ "tick": 177,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 72,+ "tick": 179,+ "label": "TopLevelBox [\"<\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 72,+ "tick": 180,+ "label": "TopLevelBox [\"<=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 72,+ "tick": 181,+ "label": "TopLevelBox [\">\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 72,+ "tick": 182,+ "label": "TopLevelBox [\">=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 72,+ "tick": 183,+ "label": "TopLevelBox [\"max\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 72,+ "tick": 184,+ "label": "TopLevelBox [\"min\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 72,+ "tick": 186,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 206,+ "tick": 206,+ "label": "TopLevelBox [\"bifold\"]",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 206,+ "tick": 215,+ "label": "TopLevelBox [\"bifoldr\"]",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 206,+ "tick": 216,+ "label": "TopLevelBox [\"bifoldl\"]",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 202,+ "tick": 228,+ "label": "TopLevelBox [\"mapM\"]",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 198,+ "tick": 230,+ "label": "TopLevelBox [\"fold\"]",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 198,+ "tick": 235,+ "label": "TopLevelBox [\"foldMap'\"]",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 198,+ "tick": 236,+ "label": "TopLevelBox [\"foldr\"]",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 198,+ "tick": 237,+ "label": "TopLevelBox [\"foldr'\"]",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 198,+ "tick": 238,+ "label": "TopLevelBox [\"foldl\"]",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 198,+ "tick": 239,+ "label": "TopLevelBox [\"foldl'\"]",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 198,+ "tick": 240,+ "label": "TopLevelBox [\"foldr1\"]",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 198,+ "tick": 241,+ "label": "TopLevelBox [\"foldl1\"]",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 198,+ "tick": 242,+ "label": "TopLevelBox [\"toList\"]",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 198,+ "tick": 243,+ "label": "TopLevelBox [\"null\"]",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 198,+ "tick": 244,+ "label": "TopLevelBox [\"length\"]",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 198,+ "tick": 245,+ "label": "TopLevelBox [\"elem\"]",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 198,+ "tick": 246,+ "label": "TopLevelBox [\"maximum\"]",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 198,+ "tick": 247,+ "label": "TopLevelBox [\"minimum\"]",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 198,+ "tick": 248,+ "label": "TopLevelBox [\"sum\"]",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 198,+ "tick": 249,+ "label": "TopLevelBox [\"product\"]",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Consumer.Types",+ "source": "src/Kafka/Consumer/Types.hs",+ "line": 194,+ "tick": 252,+ "label": "TopLevelBox [\"<$\"]",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Dump",+ "source": "src/Kafka/Dump.hs",+ "line": 82,+ "tick": 7,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Dump",+ "source": "src/Kafka/Dump.hs",+ "line": 82,+ "tick": 8,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.CallbackOwner",+ "source": "src/Kafka/Internal/CallbackOwner.hs",+ "line": 77,+ "tick": 19,+ "label": "ExpBox False",+ "generated": false,+ "contract": "F5",+ "owner": 11+ },+ {+ "module": "Kafka.Internal.CallbackOwner",+ "source": "src/Kafka/Internal/CallbackOwner.hs",+ "line": 71,+ "tick": 42,+ "label": "ExpBox False",+ "generated": false,+ "contract": "F5",+ "owner": 11+ },+ {+ "module": "Kafka.Internal.CallbackOwner",+ "source": "src/Kafka/Internal/CallbackOwner.hs",+ "line": 57,+ "tick": 62,+ "label": "ExpBox False",+ "generated": false,+ "contract": "F5",+ "owner": 11+ },+ {+ "module": "Kafka.Internal.CallbackOwner",+ "source": "src/Kafka/Internal/CallbackOwner.hs",+ "line": 57,+ "tick": 63,+ "label": "ExpBox False",+ "generated": false,+ "contract": "F5",+ "owner": 11+ },+ {+ "module": "Kafka.Internal.CallbackOwner",+ "source": "src/Kafka/Internal/CallbackOwner.hs",+ "line": 57,+ "tick": 64,+ "label": "ExpBox True",+ "generated": false,+ "contract": "F5",+ "owner": 11+ },+ {+ "module": "Kafka.Internal.CallbackOwner",+ "source": "src/Kafka/Internal/CallbackOwner.hs",+ "line": 51,+ "tick": 70,+ "label": "ExpBox False",+ "generated": false,+ "contract": "F5",+ "owner": 11+ },+ {+ "module": "Kafka.Internal.CallbackOwner",+ "source": "src/Kafka/Internal/CallbackOwner.hs",+ "line": 52,+ "tick": 72,+ "label": "ExpBox False",+ "generated": false,+ "contract": "F5",+ "owner": 11+ },+ {+ "module": "Kafka.Internal.CallbackOwner",+ "source": "src/Kafka/Internal/CallbackOwner.hs",+ "line": 52,+ "tick": 73,+ "label": "ExpBox False",+ "generated": false,+ "contract": "F5",+ "owner": 11+ },+ {+ "module": "Kafka.Internal.CallbackOwner",+ "source": "src/Kafka/Internal/CallbackOwner.hs",+ "line": 52,+ "tick": 74,+ "label": "ExpBox True",+ "generated": false,+ "contract": "F5",+ "owner": 11+ },+ {+ "module": "Kafka.Internal.CallbackOwner",+ "source": "src/Kafka/Internal/CallbackOwner.hs",+ "line": 44,+ "tick": 89,+ "label": "ExpBox False",+ "generated": false,+ "contract": "F5",+ "owner": 11+ },+ {+ "module": "Kafka.Internal.CallbackOwner",+ "source": "src/Kafka/Internal/CallbackOwner.hs",+ "line": 44,+ "tick": 90,+ "label": "ExpBox False",+ "generated": false,+ "contract": "F5",+ "owner": 11+ },+ {+ "module": "Kafka.Internal.CallbackOwner",+ "source": "src/Kafka/Internal/CallbackOwner.hs",+ "line": 44,+ "tick": 91,+ "label": "ExpBox True",+ "generated": false,+ "contract": "F5",+ "owner": 11+ },+ {+ "module": "Kafka.Internal.CallbackOwner",+ "source": "src/Kafka/Internal/CallbackOwner.hs",+ "line": 46,+ "tick": 94,+ "label": "ExpBox False",+ "generated": false,+ "contract": "F5",+ "owner": 11+ },+ {+ "module": "Kafka.Internal.CallbackOwner",+ "source": "src/Kafka/Internal/CallbackOwner.hs",+ "line": 46,+ "tick": 95,+ "label": "ExpBox False",+ "generated": false,+ "contract": "F5",+ "owner": 11+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1492,+ "tick": 103,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1444,+ "tick": 161,+ "label": "BinBox CondBinBox True",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1445,+ "tick": 164,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1445,+ "tick": 165,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1445,+ "tick": 166,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1445,+ "tick": 167,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1445,+ "tick": 168,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1445,+ "tick": 169,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1445,+ "tick": 170,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1416,+ "tick": 223,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1299,+ "tick": 466,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1151,+ "tick": 746,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1117,+ "tick": 789,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1107,+ "tick": 845,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1104,+ "tick": 851,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1104,+ "tick": 852,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1104,+ "tick": 853,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1104,+ "tick": 854,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1104,+ "tick": 855,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1104,+ "tick": 856,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1104,+ "tick": 857,+ "label": "LocalBox [\"rdKafkaOutqLen\",\"res'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1104,+ "tick": 858,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1104,+ "tick": 859,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1104,+ "tick": 860,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1104,+ "tick": 861,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1104,+ "tick": 862,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1104,+ "tick": 863,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1104,+ "tick": 864,+ "label": "TopLevelBox [\"rdKafkaOutqLen\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1101,+ "tick": 873,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1101,+ "tick": 874,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1101,+ "tick": 875,+ "label": "LocalBox [\"rdKafkaPoll\",\"res'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1101,+ "tick": 876,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1063,+ "tick": 984,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1063,+ "tick": 985,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1063,+ "tick": 986,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1063,+ "tick": 987,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1063,+ "tick": 988,+ "label": "LocalBox [\"rdKafkaProduceBatch\",\"a2'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1063,+ "tick": 989,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1063,+ "tick": 990,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1063,+ "tick": 991,+ "label": "LocalBox [\"rdKafkaProduceBatch\",\"a3'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1063,+ "tick": 992,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1063,+ "tick": 993,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1063,+ "tick": 994,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1063,+ "tick": 995,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1063,+ "tick": 996,+ "label": "LocalBox [\"rdKafkaProduceBatch\",\"a5'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1063,+ "tick": 997,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1063,+ "tick": 998,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1063,+ "tick": 999,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1063,+ "tick": 1000,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1063,+ "tick": 1001,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1063,+ "tick": 1002,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1063,+ "tick": 1003,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1063,+ "tick": 1004,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1063,+ "tick": 1005,+ "label": "LocalBox [\"rdKafkaProduceBatch\",\"res'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1063,+ "tick": 1006,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1063,+ "tick": 1007,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1063,+ "tick": 1008,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1063,+ "tick": 1009,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1063,+ "tick": 1010,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1063,+ "tick": 1011,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1063,+ "tick": 1012,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1063,+ "tick": 1013,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1063,+ "tick": 1014,+ "label": "TopLevelBox [\"rdKafkaProduceBatch\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1058,+ "tick": 1015,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1058,+ "tick": 1016,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1058,+ "tick": 1017,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1058,+ "tick": 1018,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1058,+ "tick": 1019,+ "label": "LocalBox [\"rdKafkaProduce\",\"a2'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1058,+ "tick": 1020,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1058,+ "tick": 1021,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1058,+ "tick": 1022,+ "label": "LocalBox [\"rdKafkaProduce\",\"a3'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1058,+ "tick": 1023,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1058,+ "tick": 1024,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1058,+ "tick": 1025,+ "label": "LocalBox [\"rdKafkaProduce\",\"a4'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1058,+ "tick": 1026,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1058,+ "tick": 1027,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1058,+ "tick": 1028,+ "label": "LocalBox [\"rdKafkaProduce\",\"a5'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1058,+ "tick": 1029,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1058,+ "tick": 1030,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1058,+ "tick": 1031,+ "label": "LocalBox [\"rdKafkaProduce\",\"a6'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1058,+ "tick": 1032,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1058,+ "tick": 1033,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1058,+ "tick": 1034,+ "label": "LocalBox [\"rdKafkaProduce\",\"a7'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1058,+ "tick": 1035,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1058,+ "tick": 1036,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1058,+ "tick": 1037,+ "label": "LocalBox [\"rdKafkaProduce\",\"a8'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1058,+ "tick": 1038,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1058,+ "tick": 1039,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1058,+ "tick": 1040,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1058,+ "tick": 1041,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1058,+ "tick": 1042,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1058,+ "tick": 1043,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1058,+ "tick": 1044,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1058,+ "tick": 1045,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1058,+ "tick": 1046,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1058,+ "tick": 1047,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1058,+ "tick": 1048,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1058,+ "tick": 1049,+ "label": "LocalBox [\"rdKafkaProduce\",\"res'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1058,+ "tick": 1050,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1058,+ "tick": 1051,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1058,+ "tick": 1052,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1058,+ "tick": 1053,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1058,+ "tick": 1054,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1058,+ "tick": 1055,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1058,+ "tick": 1056,+ "label": "TopLevelBox [\"rdKafkaProduce\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1048,+ "tick": 1076,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1048,+ "tick": 1077,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1048,+ "tick": 1078,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1048,+ "tick": 1079,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1048,+ "tick": 1080,+ "label": "LocalBox [\"rdKafkaOffsetStore\",\"a2'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1048,+ "tick": 1081,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1048,+ "tick": 1082,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1048,+ "tick": 1083,+ "label": "LocalBox [\"rdKafkaOffsetStore\",\"a3'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1048,+ "tick": 1084,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1048,+ "tick": 1085,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1048,+ "tick": 1086,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1048,+ "tick": 1087,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1048,+ "tick": 1088,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1048,+ "tick": 1089,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1048,+ "tick": 1090,+ "label": "LocalBox [\"rdKafkaOffsetStore\",\"res'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1048,+ "tick": 1091,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1048,+ "tick": 1092,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1048,+ "tick": 1093,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1048,+ "tick": 1094,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1048,+ "tick": 1095,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1048,+ "tick": 1096,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1048,+ "tick": 1097,+ "label": "TopLevelBox [\"rdKafkaOffsetStore\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1037,+ "tick": 1098,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1037,+ "tick": 1099,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1037,+ "tick": 1100,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1037,+ "tick": 1101,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1037,+ "tick": 1102,+ "label": "LocalBox [\"rdKafkaConsumeBatch\",\"a2'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1037,+ "tick": 1103,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1037,+ "tick": 1104,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1037,+ "tick": 1105,+ "label": "LocalBox [\"rdKafkaConsumeBatch\",\"a3'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1037,+ "tick": 1106,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1037,+ "tick": 1107,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1037,+ "tick": 1108,+ "label": "LocalBox [\"rdKafkaConsumeBatch\",\"a4'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1037,+ "tick": 1109,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1037,+ "tick": 1110,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1037,+ "tick": 1111,+ "label": "LocalBox [\"rdKafkaConsumeBatch\",\"a5'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1037,+ "tick": 1112,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1037,+ "tick": 1113,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1037,+ "tick": 1114,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1037,+ "tick": 1115,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1037,+ "tick": 1116,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1037,+ "tick": 1117,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1037,+ "tick": 1118,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1037,+ "tick": 1119,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1037,+ "tick": 1120,+ "label": "LocalBox [\"rdKafkaConsumeBatch\",\"res'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1037,+ "tick": 1121,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1037,+ "tick": 1122,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1037,+ "tick": 1123,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1037,+ "tick": 1124,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1037,+ "tick": 1125,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1037,+ "tick": 1126,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1037,+ "tick": 1127,+ "label": "TopLevelBox [\"rdKafkaConsumeBatch\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1034,+ "tick": 1128,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1034,+ "tick": 1129,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1034,+ "tick": 1130,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1034,+ "tick": 1131,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1034,+ "tick": 1132,+ "label": "LocalBox [\"rdKafkaConsume\",\"a2'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1034,+ "tick": 1133,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1034,+ "tick": 1134,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1034,+ "tick": 1135,+ "label": "LocalBox [\"rdKafkaConsume\",\"a3'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1034,+ "tick": 1136,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1034,+ "tick": 1137,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1034,+ "tick": 1138,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1034,+ "tick": 1139,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1034,+ "tick": 1140,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1034,+ "tick": 1141,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1034,+ "tick": 1142,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1034,+ "tick": 1143,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1034,+ "tick": 1144,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1034,+ "tick": 1145,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1034,+ "tick": 1146,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1034,+ "tick": 1147,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1034,+ "tick": 1148,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1034,+ "tick": 1149,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1034,+ "tick": 1150,+ "label": "TopLevelBox [\"rdKafkaConsume\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1028,+ "tick": 1177,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1028,+ "tick": 1178,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1028,+ "tick": 1179,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1028,+ "tick": 1180,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1028,+ "tick": 1181,+ "label": "LocalBox [\"rdKafkaConsumeStopInternal\",\"a2'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1028,+ "tick": 1182,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1028,+ "tick": 1183,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1028,+ "tick": 1184,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1028,+ "tick": 1185,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1028,+ "tick": 1186,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1028,+ "tick": 1187,+ "label": "LocalBox [\"rdKafkaConsumeStopInternal\",\"res'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1028,+ "tick": 1188,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1028,+ "tick": 1189,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1028,+ "tick": 1190,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1028,+ "tick": 1191,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1028,+ "tick": 1192,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1028,+ "tick": 1193,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1028,+ "tick": 1194,+ "label": "TopLevelBox [\"rdKafkaConsumeStopInternal\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1019,+ "tick": 1195,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1019,+ "tick": 1196,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1019,+ "tick": 1197,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1019,+ "tick": 1198,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1019,+ "tick": 1199,+ "label": "LocalBox [\"rdKafkaConsumeStartInternal\",\"a2'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1019,+ "tick": 1200,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1019,+ "tick": 1201,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1019,+ "tick": 1202,+ "label": "LocalBox [\"rdKafkaConsumeStartInternal\",\"a3'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1019,+ "tick": 1203,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1019,+ "tick": 1204,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1019,+ "tick": 1205,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1019,+ "tick": 1206,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1019,+ "tick": 1207,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1019,+ "tick": 1208,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1019,+ "tick": 1209,+ "label": "LocalBox [\"rdKafkaConsumeStartInternal\",\"res'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1019,+ "tick": 1210,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1019,+ "tick": 1211,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1019,+ "tick": 1212,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1019,+ "tick": 1213,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1019,+ "tick": 1214,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1019,+ "tick": 1215,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1019,+ "tick": 1216,+ "label": "TopLevelBox [\"rdKafkaConsumeStartInternal\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 992,+ "tick": 1225,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 989,+ "tick": 1231,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 989,+ "tick": 1232,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 989,+ "tick": 1233,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 989,+ "tick": 1234,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 989,+ "tick": 1235,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 989,+ "tick": 1236,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 989,+ "tick": 1237,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 989,+ "tick": 1238,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 989,+ "tick": 1239,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 989,+ "tick": 1240,+ "label": "LocalBox [\"rdKafkaBrokersAdd\",\"res'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 989,+ "tick": 1241,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 989,+ "tick": 1242,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 989,+ "tick": 1243,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 989,+ "tick": 1244,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 989,+ "tick": 1245,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 989,+ "tick": 1246,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 989,+ "tick": 1247,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 989,+ "tick": 1248,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 989,+ "tick": 1249,+ "label": "TopLevelBox [\"rdKafkaBrokersAdd\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 943,+ "tick": 1327,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 943,+ "tick": 1328,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 943,+ "tick": 1329,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 943,+ "tick": 1330,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 943,+ "tick": 1331,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 943,+ "tick": 1332,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 943,+ "tick": 1333,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 943,+ "tick": 1334,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 943,+ "tick": 1335,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 943,+ "tick": 1336,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 943,+ "tick": 1337,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 943,+ "tick": 1338,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 943,+ "tick": 1339,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 943,+ "tick": 1340,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 943,+ "tick": 1341,+ "label": "TopLevelBox [\"rdKafkaTopicConfDup\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 936,+ "tick": 1367,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 933,+ "tick": 1380,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 877,+ "tick": 1615,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 877,+ "tick": 1616,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 877,+ "tick": 1617,+ "label": "LocalBox [\"rdKafkaReadTimestamp'\",\"a1'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 877,+ "tick": 1618,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 877,+ "tick": 1619,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 877,+ "tick": 1620,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 877,+ "tick": 1621,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 877,+ "tick": 1622,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 877,+ "tick": 1623,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 877,+ "tick": 1624,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 877,+ "tick": 1625,+ "label": "LocalBox [\"rdKafkaReadTimestamp'\",\"res'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 877,+ "tick": 1626,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 877,+ "tick": 1627,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 877,+ "tick": 1628,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 877,+ "tick": 1629,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 877,+ "tick": 1630,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 877,+ "tick": 1631,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 877,+ "tick": 1632,+ "label": "TopLevelBox [\"rdKafkaReadTimestamp'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 733,+ "tick": 1800,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 733,+ "tick": 1801,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 733,+ "tick": 1802,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 733,+ "tick": 1803,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 733,+ "tick": 1804,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 733,+ "tick": 1805,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 733,+ "tick": 1806,+ "label": "LocalBox [\"rdKafkaCommitMessage\",\"a3'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 733,+ "tick": 1807,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 733,+ "tick": 1808,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 733,+ "tick": 1809,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 733,+ "tick": 1810,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 733,+ "tick": 1811,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 733,+ "tick": 1812,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 733,+ "tick": 1813,+ "label": "LocalBox [\"rdKafkaCommitMessage\",\"res'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 733,+ "tick": 1814,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 733,+ "tick": 1815,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 733,+ "tick": 1816,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 733,+ "tick": 1817,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 733,+ "tick": 1818,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 733,+ "tick": 1819,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 733,+ "tick": 1820,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 733,+ "tick": 1821,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 733,+ "tick": 1822,+ "label": "TopLevelBox [\"rdKafkaCommitMessage\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 691,+ "tick": 1979,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 691,+ "tick": 1980,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 691,+ "tick": 1981,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 692,+ "tick": 1982,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 692,+ "tick": 1983,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 692,+ "tick": 1984,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 692,+ "tick": 1985,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 693,+ "tick": 1986,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 693,+ "tick": 1987,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 694,+ "tick": 1988,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 694,+ "tick": 1989,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 692,+ "tick": 1990,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 692,+ "tick": 1991,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 692,+ "tick": 1992,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 692,+ "tick": 1993,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 695,+ "tick": 1994,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 695,+ "tick": 1995,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 690,+ "tick": 1996,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 690,+ "tick": 1997,+ "label": "TopLevelBox [\"pollRdKafkaConsumer\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 670,+ "tick": 2022,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 670,+ "tick": 2023,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 670,+ "tick": 2024,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 670,+ "tick": 2025,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 670,+ "tick": 2026,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 670,+ "tick": 2027,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 670,+ "tick": 2028,+ "label": "LocalBox [\"rdKafkaUnsubscribe\",\"res'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 670,+ "tick": 2029,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 670,+ "tick": 2030,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 670,+ "tick": 2031,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 670,+ "tick": 2032,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 670,+ "tick": 2033,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 670,+ "tick": 2034,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 670,+ "tick": 2035,+ "label": "TopLevelBox [\"rdKafkaUnsubscribe\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 634,+ "tick": 2112,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 603,+ "tick": 2215,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 603,+ "tick": 2216,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 603,+ "tick": 2217,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 603,+ "tick": 2218,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 603,+ "tick": 2219,+ "label": "LocalBox [\"rdKafkaQueueCbEventEnable\",\"a2'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 603,+ "tick": 2220,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 603,+ "tick": 2221,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 603,+ "tick": 2222,+ "label": "LocalBox [\"rdKafkaQueueCbEventEnable\",\"a3'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 603,+ "tick": 2223,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 603,+ "tick": 2224,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 603,+ "tick": 2225,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 603,+ "tick": 2226,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 603,+ "tick": 2227,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 603,+ "tick": 2228,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 603,+ "tick": 2229,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 603,+ "tick": 2230,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 603,+ "tick": 2231,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 603,+ "tick": 2232,+ "label": "TopLevelBox [\"rdKafkaQueueCbEventEnable\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 596,+ "tick": 2249,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 584,+ "tick": 2274,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 571,+ "tick": 2318,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 571,+ "tick": 2319,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 571,+ "tick": 2320,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 571,+ "tick": 2321,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 571,+ "tick": 2322,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 571,+ "tick": 2323,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 571,+ "tick": 2324,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 571,+ "tick": 2325,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 571,+ "tick": 2326,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 571,+ "tick": 2327,+ "label": "TopLevelBox [\"rdKafkaEventDestroy\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 556,+ "tick": 2366,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 556,+ "tick": 2367,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 556,+ "tick": 2368,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 556,+ "tick": 2369,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 556,+ "tick": 2370,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 556,+ "tick": 2371,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 556,+ "tick": 2372,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 556,+ "tick": 2373,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 556,+ "tick": 2374,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 556,+ "tick": 2375,+ "label": "TopLevelBox [\"rdKafkaYield\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 545,+ "tick": 2376,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 545,+ "tick": 2377,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 545,+ "tick": 2378,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 545,+ "tick": 2379,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 545,+ "tick": 2380,+ "label": "LocalBox [\"rdKafkaMsgPartitionerConsistentRandom\",\"a2'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 545,+ "tick": 2381,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 545,+ "tick": 2382,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 545,+ "tick": 2383,+ "label": "LocalBox [\"rdKafkaMsgPartitionerConsistentRandom\",\"a3'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 545,+ "tick": 2384,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 545,+ "tick": 2385,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 545,+ "tick": 2386,+ "label": "LocalBox [\"rdKafkaMsgPartitionerConsistentRandom\",\"a4'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 545,+ "tick": 2387,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 545,+ "tick": 2388,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 545,+ "tick": 2389,+ "label": "LocalBox [\"rdKafkaMsgPartitionerConsistentRandom\",\"a5'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 545,+ "tick": 2390,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 545,+ "tick": 2391,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 545,+ "tick": 2392,+ "label": "LocalBox [\"rdKafkaMsgPartitionerConsistentRandom\",\"a6'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 545,+ "tick": 2393,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 545,+ "tick": 2394,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 545,+ "tick": 2395,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 545,+ "tick": 2396,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 545,+ "tick": 2397,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 545,+ "tick": 2398,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 545,+ "tick": 2399,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 545,+ "tick": 2400,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 545,+ "tick": 2401,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 545,+ "tick": 2402,+ "label": "LocalBox [\"rdKafkaMsgPartitionerConsistentRandom\",\"res'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 545,+ "tick": 2403,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 545,+ "tick": 2404,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 545,+ "tick": 2405,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 545,+ "tick": 2406,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 545,+ "tick": 2407,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 545,+ "tick": 2408,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 545,+ "tick": 2409,+ "label": "TopLevelBox [\"rdKafkaMsgPartitionerConsistentRandom\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 536,+ "tick": 2410,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 536,+ "tick": 2411,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 536,+ "tick": 2412,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 536,+ "tick": 2413,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 536,+ "tick": 2414,+ "label": "LocalBox [\"rdKafkaMsgPartitionerConsistent\",\"a2'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 536,+ "tick": 2415,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 536,+ "tick": 2416,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 536,+ "tick": 2417,+ "label": "LocalBox [\"rdKafkaMsgPartitionerConsistent\",\"a3'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 536,+ "tick": 2418,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 536,+ "tick": 2419,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 536,+ "tick": 2420,+ "label": "LocalBox [\"rdKafkaMsgPartitionerConsistent\",\"a4'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 536,+ "tick": 2421,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 536,+ "tick": 2422,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 536,+ "tick": 2423,+ "label": "LocalBox [\"rdKafkaMsgPartitionerConsistent\",\"a5'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 536,+ "tick": 2424,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 536,+ "tick": 2425,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 536,+ "tick": 2426,+ "label": "LocalBox [\"rdKafkaMsgPartitionerConsistent\",\"a6'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 536,+ "tick": 2427,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 536,+ "tick": 2428,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 536,+ "tick": 2429,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 536,+ "tick": 2430,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 536,+ "tick": 2431,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 536,+ "tick": 2432,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 536,+ "tick": 2433,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 536,+ "tick": 2434,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 536,+ "tick": 2435,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 536,+ "tick": 2436,+ "label": "LocalBox [\"rdKafkaMsgPartitionerConsistent\",\"res'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 536,+ "tick": 2437,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 536,+ "tick": 2438,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 536,+ "tick": 2439,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 536,+ "tick": 2440,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 536,+ "tick": 2441,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 536,+ "tick": 2442,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 536,+ "tick": 2443,+ "label": "TopLevelBox [\"rdKafkaMsgPartitionerConsistent\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 527,+ "tick": 2444,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 527,+ "tick": 2445,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 527,+ "tick": 2446,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 527,+ "tick": 2447,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 527,+ "tick": 2448,+ "label": "LocalBox [\"rdKafkaMsgPartitionerRandom\",\"a2'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 527,+ "tick": 2449,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 527,+ "tick": 2450,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 527,+ "tick": 2451,+ "label": "LocalBox [\"rdKafkaMsgPartitionerRandom\",\"a3'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 527,+ "tick": 2452,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 527,+ "tick": 2453,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 527,+ "tick": 2454,+ "label": "LocalBox [\"rdKafkaMsgPartitionerRandom\",\"a4'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 527,+ "tick": 2455,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 527,+ "tick": 2456,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 527,+ "tick": 2457,+ "label": "LocalBox [\"rdKafkaMsgPartitionerRandom\",\"a5'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 527,+ "tick": 2458,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 527,+ "tick": 2459,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 527,+ "tick": 2460,+ "label": "LocalBox [\"rdKafkaMsgPartitionerRandom\",\"a6'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 527,+ "tick": 2461,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 527,+ "tick": 2462,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 527,+ "tick": 2463,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 527,+ "tick": 2464,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 527,+ "tick": 2465,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 527,+ "tick": 2466,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 527,+ "tick": 2467,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 527,+ "tick": 2468,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 527,+ "tick": 2469,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 527,+ "tick": 2470,+ "label": "LocalBox [\"rdKafkaMsgPartitionerRandom\",\"res'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 527,+ "tick": 2471,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 527,+ "tick": 2472,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 527,+ "tick": 2473,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 527,+ "tick": 2474,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 527,+ "tick": 2475,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 527,+ "tick": 2476,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 527,+ "tick": 2477,+ "label": "TopLevelBox [\"rdKafkaMsgPartitionerRandom\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 524,+ "tick": 2478,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 524,+ "tick": 2479,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 524,+ "tick": 2480,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 524,+ "tick": 2481,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 524,+ "tick": 2482,+ "label": "LocalBox [\"rdKafkaTopicPartitionAvailable\",\"a2'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 524,+ "tick": 2483,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 524,+ "tick": 2484,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 524,+ "tick": 2485,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 524,+ "tick": 2486,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 524,+ "tick": 2487,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 524,+ "tick": 2488,+ "label": "LocalBox [\"rdKafkaTopicPartitionAvailable\",\"res'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 524,+ "tick": 2489,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 524,+ "tick": 2490,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 524,+ "tick": 2491,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 524,+ "tick": 2492,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 524,+ "tick": 2493,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 524,+ "tick": 2494,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 524,+ "tick": 2495,+ "label": "TopLevelBox [\"rdKafkaTopicPartitionAvailable\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 518,+ "tick": 2496,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 519,+ "tick": 2497,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 519,+ "tick": 2498,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 519,+ "tick": 2499,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 519,+ "tick": 2500,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 519,+ "tick": 2501,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 519,+ "tick": 2502,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 519,+ "tick": 2503,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 519,+ "tick": 2504,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 519,+ "tick": 2505,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 519,+ "tick": 2506,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 518,+ "tick": 2507,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 518,+ "tick": 2508,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 518,+ "tick": 2509,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 520,+ "tick": 2510,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 520,+ "tick": 2511,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 520,+ "tick": 2512,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 520,+ "tick": 2513,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 520,+ "tick": 2514,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 520,+ "tick": 2515,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 520,+ "tick": 2516,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 519,+ "tick": 2517,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 518,+ "tick": 2518,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 517,+ "tick": 2519,+ "label": "TopLevelBox [\"rdKafkaTopicConfSetPartitionerCb\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 497,+ "tick": 2520,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 497,+ "tick": 2521,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 497,+ "tick": 2522,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 497,+ "tick": 2523,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 497,+ "tick": 2524,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 497,+ "tick": 2525,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 497,+ "tick": 2526,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 497,+ "tick": 2527,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 497,+ "tick": 2528,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 497,+ "tick": 2529,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 497,+ "tick": 2530,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 497,+ "tick": 2531,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 497,+ "tick": 2532,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 497,+ "tick": 2533,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 497,+ "tick": 2534,+ "label": "TopLevelBox [\"rdKafkaConfSetDefaultTopicConf\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 494,+ "tick": 2535,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 494,+ "tick": 2536,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 494,+ "tick": 2537,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 494,+ "tick": 2538,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 494,+ "tick": 2539,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 494,+ "tick": 2540,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 494,+ "tick": 2541,+ "label": "LocalBox [\"rdKafkaOpaque\",\"res'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 494,+ "tick": 2542,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 494,+ "tick": 2543,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 494,+ "tick": 2544,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 494,+ "tick": 2545,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 494,+ "tick": 2546,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 494,+ "tick": 2547,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 494,+ "tick": 2548,+ "label": "TopLevelBox [\"rdKafkaOpaque\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 491,+ "tick": 2549,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 491,+ "tick": 2550,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 491,+ "tick": 2551,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 491,+ "tick": 2552,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 491,+ "tick": 2553,+ "label": "LocalBox [\"rdKafkaConfSetOpaque\",\"a2'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 491,+ "tick": 2554,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 491,+ "tick": 2555,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 491,+ "tick": 2556,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 491,+ "tick": 2557,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 491,+ "tick": 2558,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 491,+ "tick": 2559,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 491,+ "tick": 2560,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 491,+ "tick": 2561,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 491,+ "tick": 2562,+ "label": "TopLevelBox [\"rdKafkaConfSetOpaque\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 488,+ "tick": 2563,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 488,+ "tick": 2564,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 488,+ "tick": 2565,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 488,+ "tick": 2566,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 488,+ "tick": 2567,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 488,+ "tick": 2568,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 488,+ "tick": 2569,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 488,+ "tick": 2570,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 488,+ "tick": 2571,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 488,+ "tick": 2572,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 488,+ "tick": 2573,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 488,+ "tick": 2574,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 489,+ "tick": 2575,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 489,+ "tick": 2576,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 489,+ "tick": 2577,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 489,+ "tick": 2578,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 489,+ "tick": 2579,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 489,+ "tick": 2580,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 489,+ "tick": 2581,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 488,+ "tick": 2582,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 488,+ "tick": 2583,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 487,+ "tick": 2584,+ "label": "TopLevelBox [\"rdKafkaConfSetSocketCb\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 474,+ "tick": 2592,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 459,+ "tick": 2619,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 441,+ "tick": 2640,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 441,+ "tick": 2641,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 441,+ "tick": 2642,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 441,+ "tick": 2643,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 441,+ "tick": 2644,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 441,+ "tick": 2645,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 441,+ "tick": 2646,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 441,+ "tick": 2647,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 441,+ "tick": 2648,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 441,+ "tick": 2649,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 441,+ "tick": 2650,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 442,+ "tick": 2651,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 442,+ "tick": 2652,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 442,+ "tick": 2653,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 442,+ "tick": 2654,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 442,+ "tick": 2655,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 442,+ "tick": 2656,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 442,+ "tick": 2657,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 441,+ "tick": 2658,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 441,+ "tick": 2659,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 440,+ "tick": 2660,+ "label": "TopLevelBox [\"rdKafkaConfSetThrottleCb\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 427,+ "tick": 2664,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 396,+ "tick": 2703,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 396,+ "tick": 2704,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 396,+ "tick": 2705,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 396,+ "tick": 2706,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 396,+ "tick": 2707,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 396,+ "tick": 2708,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 396,+ "tick": 2709,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 396,+ "tick": 2710,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 397,+ "tick": 2711,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 397,+ "tick": 2712,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 397,+ "tick": 2713,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 397,+ "tick": 2714,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 397,+ "tick": 2715,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 397,+ "tick": 2716,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 397,+ "tick": 2717,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 396,+ "tick": 2718,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 396,+ "tick": 2719,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 395,+ "tick": 2720,+ "label": "TopLevelBox [\"rdKafkaConfSetConsumeCb\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 382,+ "tick": 2722,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 348,+ "tick": 2773,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 348,+ "tick": 2774,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 348,+ "tick": 2775,+ "label": "LocalBox [\"rdKafkaTopicPartitionListSetOffset\",\"res'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 348,+ "tick": 2776,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 340,+ "tick": 2785,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 340,+ "tick": 2786,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 340,+ "tick": 2787,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 340,+ "tick": 2788,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 340,+ "tick": 2789,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 340,+ "tick": 2790,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 340,+ "tick": 2791,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 340,+ "tick": 2792,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 340,+ "tick": 2793,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 340,+ "tick": 2794,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 340,+ "tick": 2795,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 340,+ "tick": 2796,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 340,+ "tick": 2797,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 340,+ "tick": 2798,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 340,+ "tick": 2799,+ "label": "TopLevelBox [\"rdKafkaTopicPartitionListCopy\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 337,+ "tick": 2800,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 337,+ "tick": 2801,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 337,+ "tick": 2802,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 337,+ "tick": 2803,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 337,+ "tick": 2804,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 337,+ "tick": 2805,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 337,+ "tick": 2806,+ "label": "LocalBox [\"rdKafkaTopicPartitionListAddRange\",\"a3'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 337,+ "tick": 2807,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 337,+ "tick": 2808,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 337,+ "tick": 2809,+ "label": "LocalBox [\"rdKafkaTopicPartitionListAddRange\",\"a4'\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 337,+ "tick": 2810,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 337,+ "tick": 2811,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 337,+ "tick": 2812,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 337,+ "tick": 2813,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 337,+ "tick": 2814,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 337,+ "tick": 2815,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 337,+ "tick": 2816,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 337,+ "tick": 2817,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 337,+ "tick": 2818,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 337,+ "tick": 2819,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 337,+ "tick": 2820,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 337,+ "tick": 2821,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 337,+ "tick": 2822,+ "label": "TopLevelBox [\"rdKafkaTopicPartitionListAddRange\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 334,+ "tick": 2836,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 344,+ "tick": 2862,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 345,+ "tick": 2863,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 345,+ "tick": 2864,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 346,+ "tick": 2865,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 346,+ "tick": 2866,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 346,+ "tick": 2867,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 346,+ "tick": 2868,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 344,+ "tick": 2869,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 344,+ "tick": 2870,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 344,+ "tick": 2871,+ "label": "TopLevelBox [\"copyRdKafkaTopicPartitionList\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 323,+ "tick": 2929,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 110,+ "tick": 2941,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 110,+ "tick": 2942,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 110,+ "tick": 2943,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 110,+ "tick": 2944,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 110,+ "tick": 2945,+ "label": "TopLevelBox [\"peekCAText\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1024,+ "tick": 3037,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1024,+ "tick": 3038,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1024,+ "tick": 3039,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1024,+ "tick": 3040,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1024,+ "tick": 3041,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1024,+ "tick": 3042,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1025,+ "tick": 3043,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1026,+ "tick": 3044,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1026,+ "tick": 3045,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1026,+ "tick": 3046,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1026,+ "tick": 3047,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1026,+ "tick": 3048,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1027,+ "tick": 3049,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1027,+ "tick": 3050,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1025,+ "tick": 3051,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1023,+ "tick": 3052,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1023,+ "tick": 3053,+ "label": "TopLevelBox [\"rdKafkaConsumeStart\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1043,+ "tick": 3054,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1043,+ "tick": 3055,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1043,+ "tick": 3056,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1043,+ "tick": 3057,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1044,+ "tick": 3058,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1045,+ "tick": 3059,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1045,+ "tick": 3060,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1045,+ "tick": 3061,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1045,+ "tick": 3062,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1045,+ "tick": 3063,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1046,+ "tick": 3064,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1046,+ "tick": 3065,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1044,+ "tick": 3066,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1042,+ "tick": 3067,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1042,+ "tick": 3068,+ "label": "TopLevelBox [\"rdKafkaConsumeStop\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1127,+ "tick": 3072,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1371,+ "tick": 3237,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1371,+ "tick": 3238,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1372,+ "tick": 3239,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1372,+ "tick": 3240,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1372,+ "tick": 3241,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1372,+ "tick": 3242,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1372,+ "tick": 3243,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1372,+ "tick": 3244,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1372,+ "tick": 3245,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1373,+ "tick": 3246,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1373,+ "tick": 3247,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1374,+ "tick": 3248,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1374,+ "tick": 3249,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1374,+ "tick": 3250,+ "label": "BinBox CondBinBox True",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1374,+ "tick": 3251,+ "label": "BinBox CondBinBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1374,+ "tick": 3252,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1375,+ "tick": 3253,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1375,+ "tick": 3254,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1375,+ "tick": 3255,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1375,+ "tick": 3256,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1375,+ "tick": 3257,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1375,+ "tick": 3258,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1376,+ "tick": 3259,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1376,+ "tick": 3260,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1376,+ "tick": 3261,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1376,+ "tick": 3262,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1376,+ "tick": 3263,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1376,+ "tick": 3264,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1376,+ "tick": 3265,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1374,+ "tick": 3266,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1373,+ "tick": 3267,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1373,+ "tick": 3268,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1373,+ "tick": 3269,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1371,+ "tick": 3270,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1371,+ "tick": 3271,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1371,+ "tick": 3272,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1370,+ "tick": 3273,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1370,+ "tick": 3274,+ "label": "TopLevelBox [\"newRdKafkaNewTopic\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 85,+ "tick": 3311,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 85,+ "tick": 3312,+ "label": "TopLevelBox [\"rdKafkaMsgFlagFree\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 779,+ "tick": 3317,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 779,+ "tick": 3318,+ "label": "TopLevelBox [\"broker'RdKafkaGroupInfoT\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 165,+ "tick": 3405,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 165,+ "tick": 3406,+ "label": "TopLevelBox [\"size'RdKafkaTopicPartitionListT\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 134,+ "tick": 3415,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 134,+ "tick": 3416,+ "label": "TopLevelBox [\"metadata'RdKafkaTopicPartitionT\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 135,+ "tick": 3417,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 135,+ "tick": 3418,+ "label": "TopLevelBox [\"metadataSize'RdKafkaTopicPartitionT\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 136,+ "tick": 3419,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 136,+ "tick": 3420,+ "label": "TopLevelBox [\"opaque'RdKafkaTopicPartitionT\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1331,+ "tick": 3423,+ "label": "TopLevelBox [\"==\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1331,+ "tick": 3424,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1330,+ "tick": 3425,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1330,+ "tick": 3426,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1330,+ "tick": 3427,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1185,+ "tick": 3428,+ "label": "TopLevelBox [\"==\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1185,+ "tick": 3429,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1184,+ "tick": 3430,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1184,+ "tick": 3431,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1184,+ "tick": 3432,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 81,+ "tick": 3433,+ "label": "TopLevelBox [\"==\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 81,+ "tick": 3434,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 80,+ "tick": 3435,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 80,+ "tick": 3436,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 80,+ "tick": 3437,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 78,+ "tick": 3438,+ "label": "TopLevelBox [\"minBound\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 78,+ "tick": 3439,+ "label": "TopLevelBox [\"maxBound\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 76,+ "tick": 3442,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 76,+ "tick": 3443,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 76,+ "tick": 3444,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 73,+ "tick": 3447,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 73,+ "tick": 3448,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 73,+ "tick": 3449,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 71,+ "tick": 3450,+ "label": "TopLevelBox [\"==\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 71,+ "tick": 3451,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 70,+ "tick": 3452,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 70,+ "tick": 3453,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 70,+ "tick": 3454,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1183,+ "tick": 3455,+ "label": "TopLevelBox [\"succ\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1183,+ "tick": 3456,+ "label": "TopLevelBox [\"pred\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1183,+ "tick": 3457,+ "label": "TopLevelBox [\"toEnum\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1183,+ "tick": 3459,+ "label": "TopLevelBox [\"enumFrom\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1183,+ "tick": 3460,+ "label": "TopLevelBox [\"enumFromThen\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1183,+ "tick": 3461,+ "label": "TopLevelBox [\"enumFromTo\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1183,+ "tick": 3462,+ "label": "TopLevelBox [\"enumFromThenTo\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 299,+ "tick": 3463,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 299,+ "tick": 3464,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 299,+ "tick": 3465,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 299,+ "tick": 3466,+ "label": "TopLevelBox [\"==\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 299,+ "tick": 3467,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 278,+ "tick": 3468,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 278,+ "tick": 3469,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 278,+ "tick": 3470,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 278,+ "tick": 3471,+ "label": "TopLevelBox [\"==\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 278,+ "tick": 3472,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 254,+ "tick": 3473,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 254,+ "tick": 3474,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 254,+ "tick": 3475,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 254,+ "tick": 3476,+ "label": "TopLevelBox [\"==\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 254,+ "tick": 3477,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 231,+ "tick": 3478,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 231,+ "tick": 3479,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 231,+ "tick": 3480,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 231,+ "tick": 3481,+ "label": "TopLevelBox [\"==\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 231,+ "tick": 3482,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 198,+ "tick": 3483,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 198,+ "tick": 3484,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 198,+ "tick": 3485,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 198,+ "tick": 3486,+ "label": "TopLevelBox [\"==\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 198,+ "tick": 3487,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 168,+ "tick": 3488,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 168,+ "tick": 3489,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 168,+ "tick": 3490,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 168,+ "tick": 3491,+ "label": "TopLevelBox [\"==\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 168,+ "tick": 3492,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 139,+ "tick": 3493,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 139,+ "tick": 3494,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 139,+ "tick": 3495,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 139,+ "tick": 3496,+ "label": "TopLevelBox [\"==\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 139,+ "tick": 3497,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 79,+ "tick": 3498,+ "label": "TopLevelBox [\"succ\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 79,+ "tick": 3499,+ "label": "TopLevelBox [\"pred\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 79,+ "tick": 3501,+ "label": "TopLevelBox [\"fromEnum\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 79,+ "tick": 3502,+ "label": "TopLevelBox [\"enumFrom\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 79,+ "tick": 3503,+ "label": "TopLevelBox [\"enumFromThen\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 79,+ "tick": 3504,+ "label": "TopLevelBox [\"enumFromTo\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 79,+ "tick": 3505,+ "label": "TopLevelBox [\"enumFromThenTo\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 69,+ "tick": 3506,+ "label": "TopLevelBox [\"succ\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 69,+ "tick": 3507,+ "label": "TopLevelBox [\"pred\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 69,+ "tick": 3508,+ "label": "TopLevelBox [\"toEnum\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 69,+ "tick": 3510,+ "label": "TopLevelBox [\"enumFrom\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 69,+ "tick": 3511,+ "label": "TopLevelBox [\"enumFromThen\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 69,+ "tick": 3512,+ "label": "TopLevelBox [\"enumFromTo\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 69,+ "tick": 3513,+ "label": "TopLevelBox [\"enumFromThenTo\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3514,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3515,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3516,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3517,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3518,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3519,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3520,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3521,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3522,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3523,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3524,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3525,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3526,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3527,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3528,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3529,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3530,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3531,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3532,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3533,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3534,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3535,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3536,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3537,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3538,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3539,+ "label": "TopLevelBox [\"succ\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3540,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3541,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3542,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3543,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3544,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3545,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3546,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3547,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3548,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3549,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3550,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3551,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3552,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3553,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3554,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3555,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3556,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3557,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3558,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3559,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3560,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3561,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3562,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3563,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3564,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3565,+ "label": "TopLevelBox [\"pred\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3566,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3567,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3568,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3569,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3570,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3571,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3572,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3573,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3574,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3575,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3576,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3577,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3578,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3579,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3580,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3581,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3582,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3583,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3584,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3585,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3586,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3587,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3588,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3589,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3590,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3591,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3592,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3593,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3594,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3595,+ "label": "TopLevelBox [\"toEnum\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3597,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3598,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3599,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3600,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3601,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3602,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3603,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3604,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3605,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3606,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3607,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3608,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3609,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3610,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3611,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3612,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3613,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3614,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3615,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3616,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3617,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3618,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3619,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3621,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3622,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3623,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3624,+ "label": "TopLevelBox [\"enumFrom\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3625,+ "label": "TopLevelBox [\"enumFromThen\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3626,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3627,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3628,+ "label": "LocalBox [\"enumFromTo\",\"end\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3629,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3630,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3631,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3632,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3633,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3634,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3635,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3636,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3637,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3638,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3639,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3640,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3641,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3642,+ "label": "LocalBox [\"enumFromTo\",\"go\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3643,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3644,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3645,+ "label": "TopLevelBox [\"enumFromTo\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1329,+ "tick": 3646,+ "label": "TopLevelBox [\"enumFromThenTo\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1202,+ "tick": 3651,+ "label": "TopLevelBox [\"peekElemOff\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1202,+ "tick": 3653,+ "label": "TopLevelBox [\"peekByteOff\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1205,+ "tick": 3655,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1205,+ "tick": 3656,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1205,+ "tick": 3657,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1205,+ "tick": 3658,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1205,+ "tick": 3659,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1205,+ "tick": 3660,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1205,+ "tick": 3661,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1205,+ "tick": 3662,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1206,+ "tick": 3663,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1206,+ "tick": 3664,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1207,+ "tick": 3665,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1207,+ "tick": 3666,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1207,+ "tick": 3667,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1207,+ "tick": 3668,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1207,+ "tick": 3669,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1207,+ "tick": 3670,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1207,+ "tick": 3671,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1207,+ "tick": 3672,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1208,+ "tick": 3673,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1208,+ "tick": 3674,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1208,+ "tick": 3675,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1208,+ "tick": 3676,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1208,+ "tick": 3677,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1208,+ "tick": 3678,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1208,+ "tick": 3679,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1208,+ "tick": 3680,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1209,+ "tick": 3681,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1209,+ "tick": 3682,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1209,+ "tick": 3683,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1209,+ "tick": 3684,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1209,+ "tick": 3685,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1209,+ "tick": 3686,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1209,+ "tick": 3687,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1209,+ "tick": 3688,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1210,+ "tick": 3689,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1210,+ "tick": 3690,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1210,+ "tick": 3691,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1210,+ "tick": 3692,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1210,+ "tick": 3693,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1210,+ "tick": 3694,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1210,+ "tick": 3695,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1210,+ "tick": 3696,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1211,+ "tick": 3697,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1211,+ "tick": 3698,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1211,+ "tick": 3699,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1211,+ "tick": 3700,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1211,+ "tick": 3701,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1211,+ "tick": 3702,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1211,+ "tick": 3703,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1211,+ "tick": 3704,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1213,+ "tick": 3705,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1213,+ "tick": 3706,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1213,+ "tick": 3707,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1213,+ "tick": 3708,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1213,+ "tick": 3709,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1213,+ "tick": 3710,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1213,+ "tick": 3711,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1213,+ "tick": 3712,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1214,+ "tick": 3713,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1214,+ "tick": 3714,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1214,+ "tick": 3715,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1214,+ "tick": 3716,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1214,+ "tick": 3717,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1214,+ "tick": 3718,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1215,+ "tick": 3719,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1215,+ "tick": 3720,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1215,+ "tick": 3721,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1215,+ "tick": 3722,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1215,+ "tick": 3723,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1215,+ "tick": 3724,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1212,+ "tick": 3725,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1217,+ "tick": 3726,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1217,+ "tick": 3727,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1217,+ "tick": 3728,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1217,+ "tick": 3729,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1217,+ "tick": 3730,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1217,+ "tick": 3731,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1217,+ "tick": 3732,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1217,+ "tick": 3733,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1218,+ "tick": 3734,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1218,+ "tick": 3735,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1218,+ "tick": 3736,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1218,+ "tick": 3737,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1218,+ "tick": 3738,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1218,+ "tick": 3739,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1219,+ "tick": 3740,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1219,+ "tick": 3741,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1219,+ "tick": 3742,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1219,+ "tick": 3743,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1219,+ "tick": 3744,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1219,+ "tick": 3745,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1216,+ "tick": 3746,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1220,+ "tick": 3747,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1220,+ "tick": 3748,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1220,+ "tick": 3749,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1220,+ "tick": 3750,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1220,+ "tick": 3751,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1220,+ "tick": 3752,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1220,+ "tick": 3753,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1220,+ "tick": 3754,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1221,+ "tick": 3755,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1221,+ "tick": 3756,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1221,+ "tick": 3757,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1221,+ "tick": 3758,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1221,+ "tick": 3759,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1221,+ "tick": 3760,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1221,+ "tick": 3761,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1221,+ "tick": 3762,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1223,+ "tick": 3763,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1223,+ "tick": 3764,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1223,+ "tick": 3765,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1223,+ "tick": 3766,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1223,+ "tick": 3767,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1223,+ "tick": 3768,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1224,+ "tick": 3769,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1224,+ "tick": 3770,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1224,+ "tick": 3771,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1224,+ "tick": 3772,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1224,+ "tick": 3773,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1224,+ "tick": 3774,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1224,+ "tick": 3775,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1224,+ "tick": 3776,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1225,+ "tick": 3777,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1225,+ "tick": 3778,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1225,+ "tick": 3779,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1225,+ "tick": 3780,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1225,+ "tick": 3781,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1225,+ "tick": 3782,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1226,+ "tick": 3783,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1226,+ "tick": 3784,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1226,+ "tick": 3785,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1226,+ "tick": 3786,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1226,+ "tick": 3787,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1226,+ "tick": 3788,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1226,+ "tick": 3789,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1222,+ "tick": 3790,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1205,+ "tick": 3791,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1205,+ "tick": 3792,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1205,+ "tick": 3793,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1205,+ "tick": 3794,+ "label": "TopLevelBox [\"peek\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1228,+ "tick": 3795,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1228,+ "tick": 3796,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1228,+ "tick": 3797,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1228,+ "tick": 3798,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1228,+ "tick": 3799,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1228,+ "tick": 3800,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1228,+ "tick": 3801,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1228,+ "tick": 3802,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1228,+ "tick": 3803,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1233,+ "tick": 3822,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1233,+ "tick": 3823,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1233,+ "tick": 3824,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1233,+ "tick": 3825,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1233,+ "tick": 3826,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1233,+ "tick": 3827,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1233,+ "tick": 3828,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1233,+ "tick": 3829,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1233,+ "tick": 3830,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1234,+ "tick": 3831,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1234,+ "tick": 3832,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1234,+ "tick": 3833,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1234,+ "tick": 3834,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1234,+ "tick": 3835,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1234,+ "tick": 3836,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1234,+ "tick": 3837,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1234,+ "tick": 3838,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1232,+ "tick": 3839,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1242,+ "tick": 3876,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1242,+ "tick": 3877,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1242,+ "tick": 3878,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1242,+ "tick": 3879,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1242,+ "tick": 3880,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1242,+ "tick": 3881,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1242,+ "tick": 3882,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1242,+ "tick": 3883,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1242,+ "tick": 3884,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1243,+ "tick": 3885,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1243,+ "tick": 3886,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1243,+ "tick": 3887,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1243,+ "tick": 3888,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1243,+ "tick": 3889,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1243,+ "tick": 3890,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1243,+ "tick": 3891,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1243,+ "tick": 3892,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1241,+ "tick": 3893,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1245,+ "tick": 3894,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1245,+ "tick": 3895,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1245,+ "tick": 3896,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1245,+ "tick": 3897,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1245,+ "tick": 3898,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1245,+ "tick": 3899,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1245,+ "tick": 3900,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1245,+ "tick": 3901,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1245,+ "tick": 3902,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1246,+ "tick": 3903,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1246,+ "tick": 3904,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1246,+ "tick": 3905,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1246,+ "tick": 3906,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1246,+ "tick": 3907,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1246,+ "tick": 3908,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1246,+ "tick": 3909,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1246,+ "tick": 3910,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 1244,+ "tick": 3911,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 818,+ "tick": 4023,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 818,+ "tick": 4024,+ "label": "TopLevelBox [\"sizeOf\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 817,+ "tick": 4025,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 817,+ "tick": 4026,+ "label": "TopLevelBox [\"alignment\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 816,+ "tick": 4027,+ "label": "TopLevelBox [\"peekElemOff\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 816,+ "tick": 4028,+ "label": "TopLevelBox [\"pokeElemOff\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 816,+ "tick": 4029,+ "label": "TopLevelBox [\"peekByteOff\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 816,+ "tick": 4030,+ "label": "TopLevelBox [\"pokeByteOff\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 823,+ "tick": 4051,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 823,+ "tick": 4052,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 823,+ "tick": 4053,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 823,+ "tick": 4054,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 823,+ "tick": 4055,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 823,+ "tick": 4056,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 823,+ "tick": 4057,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 823,+ "tick": 4058,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 823,+ "tick": 4059,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 823,+ "tick": 4060,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 823,+ "tick": 4061,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 824,+ "tick": 4062,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 824,+ "tick": 4063,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 824,+ "tick": 4064,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 824,+ "tick": 4065,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 824,+ "tick": 4066,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 824,+ "tick": 4067,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 824,+ "tick": 4068,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 824,+ "tick": 4069,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 824,+ "tick": 4070,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 824,+ "tick": 4071,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 824,+ "tick": 4072,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 822,+ "tick": 4073,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 822,+ "tick": 4074,+ "label": "TopLevelBox [\"poke\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 789,+ "tick": 4077,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 789,+ "tick": 4078,+ "label": "TopLevelBox [\"alignment\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 788,+ "tick": 4080,+ "label": "TopLevelBox [\"pokeElemOff\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 788,+ "tick": 4082,+ "label": "TopLevelBox [\"pokeByteOff\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 792,+ "tick": 4084,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 801,+ "tick": 4157,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 801,+ "tick": 4158,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 801,+ "tick": 4159,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 801,+ "tick": 4160,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 801,+ "tick": 4161,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 801,+ "tick": 4162,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 801,+ "tick": 4163,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 801,+ "tick": 4164,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 801,+ "tick": 4165,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 801,+ "tick": 4166,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 801,+ "tick": 4167,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 802,+ "tick": 4168,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 802,+ "tick": 4169,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 802,+ "tick": 4170,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 802,+ "tick": 4171,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 802,+ "tick": 4172,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 802,+ "tick": 4173,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 802,+ "tick": 4174,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 802,+ "tick": 4175,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 802,+ "tick": 4176,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 802,+ "tick": 4177,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 802,+ "tick": 4178,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 803,+ "tick": 4179,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 803,+ "tick": 4180,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 803,+ "tick": 4181,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 803,+ "tick": 4182,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 803,+ "tick": 4183,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 803,+ "tick": 4184,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 803,+ "tick": 4185,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 803,+ "tick": 4186,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 803,+ "tick": 4187,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 803,+ "tick": 4188,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 803,+ "tick": 4189,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 804,+ "tick": 4190,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 804,+ "tick": 4191,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 804,+ "tick": 4192,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 804,+ "tick": 4193,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 804,+ "tick": 4194,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 804,+ "tick": 4195,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 804,+ "tick": 4196,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 804,+ "tick": 4197,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 804,+ "tick": 4198,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 804,+ "tick": 4199,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 804,+ "tick": 4200,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 805,+ "tick": 4201,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 805,+ "tick": 4202,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 805,+ "tick": 4203,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 805,+ "tick": 4204,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 805,+ "tick": 4205,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 805,+ "tick": 4206,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 805,+ "tick": 4207,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 805,+ "tick": 4208,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 805,+ "tick": 4209,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 805,+ "tick": 4210,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 805,+ "tick": 4211,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 806,+ "tick": 4212,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 806,+ "tick": 4213,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 806,+ "tick": 4214,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 806,+ "tick": 4215,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 806,+ "tick": 4216,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 806,+ "tick": 4217,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 806,+ "tick": 4218,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 806,+ "tick": 4219,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 806,+ "tick": 4220,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 806,+ "tick": 4221,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 806,+ "tick": 4222,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 807,+ "tick": 4223,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 807,+ "tick": 4224,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 807,+ "tick": 4225,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 807,+ "tick": 4226,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 807,+ "tick": 4227,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 807,+ "tick": 4228,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 807,+ "tick": 4229,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 807,+ "tick": 4230,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 807,+ "tick": 4231,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 807,+ "tick": 4232,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 807,+ "tick": 4233,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 808,+ "tick": 4234,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 808,+ "tick": 4235,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 808,+ "tick": 4236,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 808,+ "tick": 4237,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 808,+ "tick": 4238,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 808,+ "tick": 4239,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 808,+ "tick": 4240,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 808,+ "tick": 4241,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 808,+ "tick": 4242,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 808,+ "tick": 4243,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 808,+ "tick": 4244,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 800,+ "tick": 4245,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 800,+ "tick": 4246,+ "label": "TopLevelBox [\"poke\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 757,+ "tick": 4249,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 757,+ "tick": 4250,+ "label": "TopLevelBox [\"alignment\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 756,+ "tick": 4252,+ "label": "TopLevelBox [\"pokeElemOff\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 756,+ "tick": 4254,+ "label": "TopLevelBox [\"pokeByteOff\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 768,+ "tick": 4320,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 768,+ "tick": 4321,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 768,+ "tick": 4322,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 768,+ "tick": 4323,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 768,+ "tick": 4324,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 768,+ "tick": 4325,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 768,+ "tick": 4326,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 768,+ "tick": 4327,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 768,+ "tick": 4328,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 768,+ "tick": 4329,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 768,+ "tick": 4330,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 769,+ "tick": 4331,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 769,+ "tick": 4332,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 769,+ "tick": 4333,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 769,+ "tick": 4334,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 769,+ "tick": 4335,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 769,+ "tick": 4336,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 769,+ "tick": 4337,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 769,+ "tick": 4338,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 769,+ "tick": 4339,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 769,+ "tick": 4340,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 769,+ "tick": 4341,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 770,+ "tick": 4342,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 770,+ "tick": 4343,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 770,+ "tick": 4344,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 770,+ "tick": 4345,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 770,+ "tick": 4346,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 770,+ "tick": 4347,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 770,+ "tick": 4348,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 770,+ "tick": 4349,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 770,+ "tick": 4350,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 770,+ "tick": 4351,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 770,+ "tick": 4352,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 771,+ "tick": 4353,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 771,+ "tick": 4354,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 771,+ "tick": 4355,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 771,+ "tick": 4356,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 771,+ "tick": 4357,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 771,+ "tick": 4358,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 771,+ "tick": 4359,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 771,+ "tick": 4360,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 771,+ "tick": 4361,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 771,+ "tick": 4362,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 771,+ "tick": 4363,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 772,+ "tick": 4364,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 772,+ "tick": 4365,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 772,+ "tick": 4366,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 772,+ "tick": 4367,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 772,+ "tick": 4368,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 772,+ "tick": 4369,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 772,+ "tick": 4370,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 772,+ "tick": 4371,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 772,+ "tick": 4372,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 772,+ "tick": 4373,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 772,+ "tick": 4374,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 773,+ "tick": 4375,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 773,+ "tick": 4376,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 773,+ "tick": 4377,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 773,+ "tick": 4378,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 773,+ "tick": 4379,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 773,+ "tick": 4380,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 773,+ "tick": 4381,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 773,+ "tick": 4382,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 773,+ "tick": 4383,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 773,+ "tick": 4384,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 773,+ "tick": 4385,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 774,+ "tick": 4386,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 774,+ "tick": 4387,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 774,+ "tick": 4388,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 774,+ "tick": 4389,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 774,+ "tick": 4390,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 774,+ "tick": 4391,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 774,+ "tick": 4392,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 774,+ "tick": 4393,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 774,+ "tick": 4394,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 774,+ "tick": 4395,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 774,+ "tick": 4396,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 767,+ "tick": 4397,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 767,+ "tick": 4398,+ "label": "TopLevelBox [\"poke\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 303,+ "tick": 4399,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 303,+ "tick": 4400,+ "label": "TopLevelBox [\"sizeOf\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 302,+ "tick": 4401,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 302,+ "tick": 4402,+ "label": "TopLevelBox [\"alignment\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 301,+ "tick": 4403,+ "label": "TopLevelBox [\"peekElemOff\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 301,+ "tick": 4404,+ "label": "TopLevelBox [\"pokeElemOff\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 301,+ "tick": 4405,+ "label": "TopLevelBox [\"peekByteOff\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 301,+ "tick": 4406,+ "label": "TopLevelBox [\"pokeByteOff\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 310,+ "tick": 4454,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 310,+ "tick": 4455,+ "label": "TopLevelBox [\"poke\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 281,+ "tick": 4458,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 281,+ "tick": 4459,+ "label": "TopLevelBox [\"alignment\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 280,+ "tick": 4461,+ "label": "TopLevelBox [\"pokeElemOff\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 280,+ "tick": 4463,+ "label": "TopLevelBox [\"pokeByteOff\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 288,+ "tick": 4502,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 288,+ "tick": 4503,+ "label": "TopLevelBox [\"poke\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 257,+ "tick": 4506,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 257,+ "tick": 4507,+ "label": "TopLevelBox [\"alignment\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 256,+ "tick": 4509,+ "label": "TopLevelBox [\"pokeElemOff\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 256,+ "tick": 4511,+ "label": "TopLevelBox [\"pokeByteOff\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 268,+ "tick": 4577,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 268,+ "tick": 4578,+ "label": "TopLevelBox [\"poke\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 237,+ "tick": 4581,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 237,+ "tick": 4582,+ "label": "TopLevelBox [\"alignment\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 236,+ "tick": 4584,+ "label": "TopLevelBox [\"pokeElemOff\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 236,+ "tick": 4586,+ "label": "TopLevelBox [\"pokeByteOff\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 243,+ "tick": 4616,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 243,+ "tick": 4617,+ "label": "TopLevelBox [\"poke\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 202,+ "tick": 4618,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 202,+ "tick": 4619,+ "label": "TopLevelBox [\"sizeOf\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 201,+ "tick": 4620,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 201,+ "tick": 4621,+ "label": "TopLevelBox [\"alignment\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 200,+ "tick": 4622,+ "label": "TopLevelBox [\"peekElemOff\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 200,+ "tick": 4623,+ "label": "TopLevelBox [\"pokeElemOff\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 200,+ "tick": 4624,+ "label": "TopLevelBox [\"peekByteOff\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 200,+ "tick": 4625,+ "label": "TopLevelBox [\"pokeByteOff\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 214,+ "tick": 4709,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 214,+ "tick": 4710,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 214,+ "tick": 4711,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 214,+ "tick": 4712,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 214,+ "tick": 4713,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 214,+ "tick": 4714,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 214,+ "tick": 4715,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 214,+ "tick": 4716,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 214,+ "tick": 4717,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 214,+ "tick": 4718,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 214,+ "tick": 4719,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 215,+ "tick": 4720,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 215,+ "tick": 4721,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 215,+ "tick": 4722,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 215,+ "tick": 4723,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 215,+ "tick": 4724,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 215,+ "tick": 4725,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 215,+ "tick": 4726,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 215,+ "tick": 4727,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 215,+ "tick": 4728,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 215,+ "tick": 4729,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 215,+ "tick": 4730,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 216,+ "tick": 4731,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 216,+ "tick": 4732,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 216,+ "tick": 4733,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 216,+ "tick": 4734,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 216,+ "tick": 4735,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 216,+ "tick": 4736,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 216,+ "tick": 4737,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 216,+ "tick": 4738,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 216,+ "tick": 4739,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 216,+ "tick": 4740,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 216,+ "tick": 4741,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 217,+ "tick": 4742,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 217,+ "tick": 4743,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 217,+ "tick": 4744,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 217,+ "tick": 4745,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 217,+ "tick": 4746,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 217,+ "tick": 4747,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 217,+ "tick": 4748,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 217,+ "tick": 4749,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 217,+ "tick": 4750,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 217,+ "tick": 4751,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 217,+ "tick": 4752,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 218,+ "tick": 4753,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 218,+ "tick": 4754,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 218,+ "tick": 4755,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 218,+ "tick": 4756,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 218,+ "tick": 4757,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 218,+ "tick": 4758,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 218,+ "tick": 4759,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 218,+ "tick": 4760,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 218,+ "tick": 4761,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 218,+ "tick": 4762,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 218,+ "tick": 4763,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 219,+ "tick": 4764,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 219,+ "tick": 4765,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 219,+ "tick": 4766,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 219,+ "tick": 4767,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 219,+ "tick": 4768,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 219,+ "tick": 4769,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 219,+ "tick": 4770,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 219,+ "tick": 4771,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 219,+ "tick": 4772,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 219,+ "tick": 4773,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 219,+ "tick": 4774,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 220,+ "tick": 4775,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 220,+ "tick": 4776,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 220,+ "tick": 4777,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 220,+ "tick": 4778,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 220,+ "tick": 4779,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 220,+ "tick": 4780,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 220,+ "tick": 4781,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 220,+ "tick": 4782,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 220,+ "tick": 4783,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 220,+ "tick": 4784,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 220,+ "tick": 4785,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 221,+ "tick": 4786,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 221,+ "tick": 4787,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 221,+ "tick": 4788,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 221,+ "tick": 4789,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 221,+ "tick": 4790,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 221,+ "tick": 4791,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 221,+ "tick": 4792,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 221,+ "tick": 4793,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 221,+ "tick": 4794,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 221,+ "tick": 4795,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 221,+ "tick": 4796,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 222,+ "tick": 4797,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 222,+ "tick": 4798,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 222,+ "tick": 4799,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 222,+ "tick": 4800,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 222,+ "tick": 4801,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 222,+ "tick": 4802,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 222,+ "tick": 4803,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 222,+ "tick": 4804,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 222,+ "tick": 4805,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 222,+ "tick": 4806,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 222,+ "tick": 4807,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 213,+ "tick": 4808,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 213,+ "tick": 4809,+ "label": "TopLevelBox [\"poke\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 174,+ "tick": 4810,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 174,+ "tick": 4811,+ "label": "TopLevelBox [\"sizeOf\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 173,+ "tick": 4812,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 173,+ "tick": 4813,+ "label": "TopLevelBox [\"alignment\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 172,+ "tick": 4814,+ "label": "TopLevelBox [\"peekElemOff\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 172,+ "tick": 4815,+ "label": "TopLevelBox [\"pokeElemOff\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 172,+ "tick": 4816,+ "label": "TopLevelBox [\"peekByteOff\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 172,+ "tick": 4817,+ "label": "TopLevelBox [\"pokeByteOff\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 177,+ "tick": 4828,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 180,+ "tick": 4847,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 180,+ "tick": 4848,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 180,+ "tick": 4849,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 180,+ "tick": 4850,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 180,+ "tick": 4851,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 180,+ "tick": 4852,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 180,+ "tick": 4853,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 180,+ "tick": 4854,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 180,+ "tick": 4855,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 180,+ "tick": 4856,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 180,+ "tick": 4857,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 181,+ "tick": 4858,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 181,+ "tick": 4859,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 181,+ "tick": 4860,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 181,+ "tick": 4861,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 181,+ "tick": 4862,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 181,+ "tick": 4863,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 181,+ "tick": 4864,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 181,+ "tick": 4865,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 181,+ "tick": 4866,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 181,+ "tick": 4867,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 181,+ "tick": 4868,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 182,+ "tick": 4869,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 182,+ "tick": 4870,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 182,+ "tick": 4871,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 182,+ "tick": 4872,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 182,+ "tick": 4873,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 182,+ "tick": 4874,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 182,+ "tick": 4875,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 182,+ "tick": 4876,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 182,+ "tick": 4877,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 182,+ "tick": 4878,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 182,+ "tick": 4879,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 179,+ "tick": 4880,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 179,+ "tick": 4881,+ "label": "TopLevelBox [\"poke\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 142,+ "tick": 4884,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 142,+ "tick": 4885,+ "label": "TopLevelBox [\"alignment\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 141,+ "tick": 4887,+ "label": "TopLevelBox [\"pokeElemOff\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 141,+ "tick": 4889,+ "label": "TopLevelBox [\"pokeByteOff\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 148,+ "tick": 4918,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 149,+ "tick": 4927,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 150,+ "tick": 4936,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 153,+ "tick": 4955,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 153,+ "tick": 4956,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 153,+ "tick": 4957,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 153,+ "tick": 4958,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 153,+ "tick": 4959,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 153,+ "tick": 4960,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 153,+ "tick": 4961,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 153,+ "tick": 4962,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 153,+ "tick": 4963,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 153,+ "tick": 4964,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 153,+ "tick": 4965,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 154,+ "tick": 4966,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 154,+ "tick": 4967,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 154,+ "tick": 4968,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 154,+ "tick": 4969,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 154,+ "tick": 4970,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 154,+ "tick": 4971,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 154,+ "tick": 4972,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 154,+ "tick": 4973,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 154,+ "tick": 4974,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 154,+ "tick": 4975,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 154,+ "tick": 4976,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 155,+ "tick": 4977,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 155,+ "tick": 4978,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 155,+ "tick": 4979,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 155,+ "tick": 4980,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 155,+ "tick": 4981,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 155,+ "tick": 4982,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 155,+ "tick": 4983,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 155,+ "tick": 4984,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 155,+ "tick": 4985,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 155,+ "tick": 4986,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 155,+ "tick": 4987,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 156,+ "tick": 4988,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 156,+ "tick": 4989,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 156,+ "tick": 4990,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 156,+ "tick": 4991,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 156,+ "tick": 4992,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 156,+ "tick": 4993,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 156,+ "tick": 4994,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 156,+ "tick": 4995,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 156,+ "tick": 4996,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 156,+ "tick": 4997,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 156,+ "tick": 4998,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 157,+ "tick": 4999,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 157,+ "tick": 5000,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 157,+ "tick": 5001,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 157,+ "tick": 5002,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 157,+ "tick": 5003,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 157,+ "tick": 5004,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 157,+ "tick": 5005,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 157,+ "tick": 5006,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 157,+ "tick": 5007,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 157,+ "tick": 5008,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 157,+ "tick": 5009,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 158,+ "tick": 5010,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 158,+ "tick": 5011,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 158,+ "tick": 5012,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 158,+ "tick": 5013,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 158,+ "tick": 5014,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 158,+ "tick": 5015,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 158,+ "tick": 5016,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 158,+ "tick": 5017,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 158,+ "tick": 5018,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 158,+ "tick": 5019,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 158,+ "tick": 5020,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 159,+ "tick": 5021,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 159,+ "tick": 5022,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 159,+ "tick": 5023,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 159,+ "tick": 5024,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 159,+ "tick": 5025,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 159,+ "tick": 5026,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 159,+ "tick": 5027,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 159,+ "tick": 5028,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 159,+ "tick": 5029,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 159,+ "tick": 5030,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 159,+ "tick": 5031,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 152,+ "tick": 5032,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 152,+ "tick": 5033,+ "label": "TopLevelBox [\"poke\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 871,+ "tick": 5038,+ "label": "TopLevelBox [\"peekElemOff\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 871,+ "tick": 5039,+ "label": "TopLevelBox [\"pokeElemOff\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 871,+ "tick": 5040,+ "label": "TopLevelBox [\"peekByteOff\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 871,+ "tick": 5041,+ "label": "TopLevelBox [\"pokeByteOff\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 875,+ "tick": 5048,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 875,+ "tick": 5049,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 875,+ "tick": 5050,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 875,+ "tick": 5051,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 875,+ "tick": 5052,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 875,+ "tick": 5053,+ "label": "TopLevelBox [\"poke\"]",+ "generated": false,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5054,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5055,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5056,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5057,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5058,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5059,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5060,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5061,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5062,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5063,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5064,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5065,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5066,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5067,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5068,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5069,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5070,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5071,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5072,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5073,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5074,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5075,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5076,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5077,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5078,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5079,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5080,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5081,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5082,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5083,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5084,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5085,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5086,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5087,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5088,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5089,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5090,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5091,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5092,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5093,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5094,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5095,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5096,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5097,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5098,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5099,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5100,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5101,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5102,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5103,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5104,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5105,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5106,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5107,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5108,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5109,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5110,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5111,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5112,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5113,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5114,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5115,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5116,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5117,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5118,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5119,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5120,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5121,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5122,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5123,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5124,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5125,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5126,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5127,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5128,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5129,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5130,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5131,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5132,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5133,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5134,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5135,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5136,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5137,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5138,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5139,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5140,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5141,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5142,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5143,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5144,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5145,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5146,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5147,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5148,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5149,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5150,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5151,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5152,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5153,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5154,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5155,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5156,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5157,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5158,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5159,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5160,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5161,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5162,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5163,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5164,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5165,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5166,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5167,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5168,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5169,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5170,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5171,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5172,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5173,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5174,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5175,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5176,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5177,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5178,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5179,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5180,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5181,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5182,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5183,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5184,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5185,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5186,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5187,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5188,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5189,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5190,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5191,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5192,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5193,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5194,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5195,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5196,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5197,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5198,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5199,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5200,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5201,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5202,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5203,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5204,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5205,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5206,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5207,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5208,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5209,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5210,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5211,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5212,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5213,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5214,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5215,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5216,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5217,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5218,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5219,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5220,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5221,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5222,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5223,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5224,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5225,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5226,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5227,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5228,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5229,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5230,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5231,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5232,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5233,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5234,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5235,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5236,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5237,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5238,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5239,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5240,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5241,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5242,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5243,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5244,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5245,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5246,+ "label": "TopLevelBox [\"succ\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5247,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5248,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5249,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5250,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5251,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5252,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5253,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5254,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5255,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5256,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5257,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5258,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5259,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5260,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5261,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5262,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5263,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5264,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5265,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5266,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5267,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5268,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5269,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5270,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5271,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5272,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5273,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5274,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5275,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5276,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5277,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5278,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5279,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5280,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5281,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5282,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5283,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5284,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5285,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5286,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5287,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5288,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5289,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5290,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5291,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5292,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5293,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5294,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5295,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5296,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5297,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5298,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5299,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5300,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5301,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5302,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5303,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5304,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5305,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5306,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5307,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5308,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5309,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5310,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5311,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5312,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5313,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5314,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5315,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5316,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5317,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5318,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5319,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5320,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5321,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5322,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5323,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5324,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5325,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5326,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5327,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5328,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5329,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5330,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5331,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5332,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5333,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5334,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5335,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5336,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5337,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5338,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5339,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5340,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5341,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5342,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5343,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5344,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5345,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5346,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5347,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5348,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5349,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5350,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5351,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5352,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5353,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5354,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5355,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5356,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5357,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5358,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5359,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5360,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5361,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5362,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5363,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5364,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5365,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5366,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5367,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5368,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5369,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5370,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5371,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5372,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5373,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5374,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5375,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5376,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5377,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5378,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5379,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5380,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5381,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5382,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5383,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5384,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5385,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5386,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5387,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5388,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5389,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5390,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5391,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5392,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5393,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5394,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5395,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5396,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5397,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5398,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5399,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5400,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5401,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5402,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5403,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5404,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5405,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5406,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5407,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5408,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5409,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5410,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5411,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5412,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5413,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5414,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5415,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5416,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5417,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5418,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5419,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5420,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5421,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5422,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5423,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5424,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5425,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5426,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5427,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5428,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5429,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5430,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5431,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5432,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5433,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5434,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5435,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5436,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5437,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5438,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5439,+ "label": "TopLevelBox [\"pred\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5895,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5896,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5897,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5898,+ "label": "TopLevelBox [\"enumFrom\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5899,+ "label": "TopLevelBox [\"enumFromThen\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5900,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5901,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5902,+ "label": "LocalBox [\"enumFromTo\",\"end\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5903,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5904,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5905,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5906,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5907,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5908,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5909,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5910,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5911,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5912,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5913,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5914,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5915,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5916,+ "label": "LocalBox [\"enumFromTo\",\"go\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5917,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5918,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5919,+ "label": "TopLevelBox [\"enumFromTo\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 75,+ "tick": 5920,+ "label": "TopLevelBox [\"enumFromThenTo\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5921,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5922,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5923,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5924,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5925,+ "label": "TopLevelBox [\"succ\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5926,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5927,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5928,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5929,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5930,+ "label": "TopLevelBox [\"pred\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5934,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5935,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5936,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5937,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5938,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5940,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5941,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5942,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5943,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5944,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5945,+ "label": "TopLevelBox [\"fromEnum\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5946,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5947,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5948,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5949,+ "label": "TopLevelBox [\"enumFrom\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5950,+ "label": "TopLevelBox [\"enumFromThen\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5951,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5952,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5953,+ "label": "LocalBox [\"enumFromTo\",\"end\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5954,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5955,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5956,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5957,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5958,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5959,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5960,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5961,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5962,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5963,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5964,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5965,+ "label": "ExpBox True",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5966,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5967,+ "label": "LocalBox [\"enumFromTo\",\"go\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5968,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5969,+ "label": "ExpBox False",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5970,+ "label": "TopLevelBox [\"enumFromTo\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.RdKafka",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "line": 72,+ "tick": 5971,+ "label": "TopLevelBox [\"enumFromThenTo\"]",+ "generated": true,+ "contract": "OWN-binding-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Setup",+ "source": "src/Kafka/Internal/Setup.hs",+ "line": 228,+ "tick": 21,+ "label": "BinBox GuardBinBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Setup",+ "source": "src/Kafka/Internal/Setup.hs",+ "line": 228,+ "tick": 23,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Setup",+ "source": "src/Kafka/Internal/Setup.hs",+ "line": 194,+ "tick": 27,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Setup",+ "source": "src/Kafka/Internal/Setup.hs",+ "line": 90,+ "tick": 222,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Setup",+ "source": "src/Kafka/Internal/Setup.hs",+ "line": 90,+ "tick": 223,+ "label": "TopLevelBox [\"kcfgKafkaConfPtr\"]",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Setup",+ "source": "src/Kafka/Internal/Setup.hs",+ "line": 92,+ "tick": 224,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Setup",+ "source": "src/Kafka/Internal/Setup.hs",+ "line": 92,+ "tick": 225,+ "label": "TopLevelBox [\"kcfgMessagesQueue\"]",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Setup",+ "source": "src/Kafka/Internal/Setup.hs",+ "line": 97,+ "tick": 228,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Setup",+ "source": "src/Kafka/Internal/Setup.hs",+ "line": 97,+ "tick": 229,+ "label": "TopLevelBox [\"kcfgLifecycle\"]",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Setup",+ "source": "src/Kafka/Internal/Setup.hs",+ "line": 86,+ "tick": 238,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Setup",+ "source": "src/Kafka/Internal/Setup.hs",+ "line": 86,+ "tick": 239,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Setup",+ "source": "src/Kafka/Internal/Setup.hs",+ "line": 86,+ "tick": 240,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Setup",+ "source": "src/Kafka/Internal/Setup.hs",+ "line": 86,+ "tick": 241,+ "label": "TopLevelBox [\"==\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Setup",+ "source": "src/Kafka/Internal/Setup.hs",+ "line": 86,+ "tick": 242,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Setup",+ "source": "src/Kafka/Internal/Setup.hs",+ "line": 79,+ "tick": 243,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Setup",+ "source": "src/Kafka/Internal/Setup.hs",+ "line": 79,+ "tick": 244,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Setup",+ "source": "src/Kafka/Internal/Setup.hs",+ "line": 79,+ "tick": 245,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Setup",+ "source": "src/Kafka/Internal/Setup.hs",+ "line": 79,+ "tick": 246,+ "label": "TopLevelBox [\"==\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Setup",+ "source": "src/Kafka/Internal/Setup.hs",+ "line": 79,+ "tick": 247,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Setup",+ "source": "src/Kafka/Internal/Setup.hs",+ "line": 71,+ "tick": 248,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Setup",+ "source": "src/Kafka/Internal/Setup.hs",+ "line": 71,+ "tick": 249,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Setup",+ "source": "src/Kafka/Internal/Setup.hs",+ "line": 71,+ "tick": 250,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Setup",+ "source": "src/Kafka/Internal/Setup.hs",+ "line": 68,+ "tick": 251,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Setup",+ "source": "src/Kafka/Internal/Setup.hs",+ "line": 68,+ "tick": 252,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Setup",+ "source": "src/Kafka/Internal/Setup.hs",+ "line": 68,+ "tick": 253,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Setup",+ "source": "src/Kafka/Internal/Setup.hs",+ "line": 65,+ "tick": 254,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Setup",+ "source": "src/Kafka/Internal/Setup.hs",+ "line": 65,+ "tick": 255,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Setup",+ "source": "src/Kafka/Internal/Setup.hs",+ "line": 65,+ "tick": 256,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Setup",+ "source": "src/Kafka/Internal/Setup.hs",+ "line": 65,+ "tick": 257,+ "label": "TopLevelBox [\"==\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Setup",+ "source": "src/Kafka/Internal/Setup.hs",+ "line": 65,+ "tick": 258,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Setup",+ "source": "src/Kafka/Internal/Setup.hs",+ "line": 62,+ "tick": 259,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Setup",+ "source": "src/Kafka/Internal/Setup.hs",+ "line": 62,+ "tick": 260,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Setup",+ "source": "src/Kafka/Internal/Setup.hs",+ "line": 62,+ "tick": 261,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Setup",+ "source": "src/Kafka/Internal/Setup.hs",+ "line": 62,+ "tick": 262,+ "label": "TopLevelBox [\"==\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Setup",+ "source": "src/Kafka/Internal/Setup.hs",+ "line": 62,+ "tick": 263,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Shared",+ "source": "src/Kafka/Internal/Shared.hs",+ "line": 162,+ "tick": 13,+ "label": "BinBox GuardBinBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Shared",+ "source": "src/Kafka/Internal/Shared.hs",+ "line": 174,+ "tick": 42,+ "label": "BinBox GuardBinBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Shared",+ "source": "src/Kafka/Internal/Shared.hs",+ "line": 103,+ "tick": 85,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Shared",+ "source": "src/Kafka/Internal/Shared.hs",+ "line": 103,+ "tick": 86,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Shared",+ "source": "src/Kafka/Internal/Shared.hs",+ "line": 103,+ "tick": 87,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Shared",+ "source": "src/Kafka/Internal/Shared.hs",+ "line": 103,+ "tick": 88,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Shared",+ "source": "src/Kafka/Internal/Shared.hs",+ "line": 103,+ "tick": 89,+ "label": "TopLevelBox [\"maybeToLeft\"]",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Shared",+ "source": "src/Kafka/Internal/Shared.hs",+ "line": 91,+ "tick": 96,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Shared",+ "source": "src/Kafka/Internal/Shared.hs",+ "line": 92,+ "tick": 97,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Shared",+ "source": "src/Kafka/Internal/Shared.hs",+ "line": 92,+ "tick": 98,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Shared",+ "source": "src/Kafka/Internal/Shared.hs",+ "line": 93,+ "tick": 99,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Shared",+ "source": "src/Kafka/Internal/Shared.hs",+ "line": 93,+ "tick": 100,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Shared",+ "source": "src/Kafka/Internal/Shared.hs",+ "line": 91,+ "tick": 101,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Shared",+ "source": "src/Kafka/Internal/Shared.hs",+ "line": 91,+ "tick": 102,+ "label": "TopLevelBox [\"kafkaErrorToEither\"]",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Shared",+ "source": "src/Kafka/Internal/Shared.hs",+ "line": 79,+ "tick": 111,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Shared",+ "source": "src/Kafka/Internal/Shared.hs",+ "line": 80,+ "tick": 112,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Shared",+ "source": "src/Kafka/Internal/Shared.hs",+ "line": 81,+ "tick": 113,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Shared",+ "source": "src/Kafka/Internal/Shared.hs",+ "line": 79,+ "tick": 114,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Shared",+ "source": "src/Kafka/Internal/Shared.hs",+ "line": 79,+ "tick": 115,+ "label": "TopLevelBox [\"hasError\"]",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Shared",+ "source": "src/Kafka/Internal/Shared.hs",+ "line": 73,+ "tick": 116,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Shared",+ "source": "src/Kafka/Internal/Shared.hs",+ "line": 74,+ "tick": 117,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Shared",+ "source": "src/Kafka/Internal/Shared.hs",+ "line": 75,+ "tick": 118,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Shared",+ "source": "src/Kafka/Internal/Shared.hs",+ "line": 75,+ "tick": 119,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Shared",+ "source": "src/Kafka/Internal/Shared.hs",+ "line": 75,+ "tick": 120,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Shared",+ "source": "src/Kafka/Internal/Shared.hs",+ "line": 75,+ "tick": 121,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Shared",+ "source": "src/Kafka/Internal/Shared.hs",+ "line": 76,+ "tick": 122,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Shared",+ "source": "src/Kafka/Internal/Shared.hs",+ "line": 76,+ "tick": 123,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Shared",+ "source": "src/Kafka/Internal/Shared.hs",+ "line": 74,+ "tick": 124,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Shared",+ "source": "src/Kafka/Internal/Shared.hs",+ "line": 72,+ "tick": 125,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Shared",+ "source": "src/Kafka/Internal/Shared.hs",+ "line": 72,+ "tick": 126,+ "label": "TopLevelBox [\"throwOnError\"]",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Shared",+ "source": "src/Kafka/Internal/Shared.hs",+ "line": 148,+ "tick": 179,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Shared",+ "source": "src/Kafka/Internal/Shared.hs",+ "line": 148,+ "tick": 180,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Shared",+ "source": "src/Kafka/Internal/Shared.hs",+ "line": 59,+ "tick": 241,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Internal.Shared",+ "source": "src/Kafka/Internal/Shared.hs",+ "line": 52,+ "tick": 264,+ "label": "BinBox GuardBinBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 255,+ "tick": 231,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 149,+ "tick": 440,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 149,+ "tick": 441,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 85,+ "tick": 591,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 85,+ "tick": 592,+ "label": "TopLevelBox [\"woTopicName\"]",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 86,+ "tick": 593,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 86,+ "tick": 594,+ "label": "TopLevelBox [\"woPartitionId\"]",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 87,+ "tick": 595,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 87,+ "tick": 596,+ "label": "TopLevelBox [\"woLowWatermark\"]",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 131,+ "tick": 627,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 131,+ "tick": 628,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 131,+ "tick": 629,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 121,+ "tick": 638,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 121,+ "tick": 639,+ "label": "TopLevelBox [\"readsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 121,+ "tick": 640,+ "label": "TopLevelBox [\"readList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 121,+ "tick": 643,+ "label": "TopLevelBox [\"compare\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 121,+ "tick": 644,+ "label": "TopLevelBox [\"<\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 121,+ "tick": 645,+ "label": "TopLevelBox [\"<=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 121,+ "tick": 646,+ "label": "TopLevelBox [\">\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 121,+ "tick": 647,+ "label": "TopLevelBox [\">=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 121,+ "tick": 648,+ "label": "TopLevelBox [\"max\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 121,+ "tick": 649,+ "label": "TopLevelBox [\"min\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 121,+ "tick": 650,+ "label": "TopLevelBox [\"from\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 121,+ "tick": 651,+ "label": "TopLevelBox [\"to\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 108,+ "tick": 656,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 108,+ "tick": 657,+ "label": "TopLevelBox [\"readsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 108,+ "tick": 658,+ "label": "TopLevelBox [\"readList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 108,+ "tick": 662,+ "label": "TopLevelBox [\"<\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 108,+ "tick": 663,+ "label": "TopLevelBox [\"<=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 108,+ "tick": 664,+ "label": "TopLevelBox [\">\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 108,+ "tick": 665,+ "label": "TopLevelBox [\">=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 108,+ "tick": 666,+ "label": "TopLevelBox [\"max\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 108,+ "tick": 667,+ "label": "TopLevelBox [\"min\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 108,+ "tick": 668,+ "label": "TopLevelBox [\"from\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 108,+ "tick": 669,+ "label": "TopLevelBox [\"to\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 105,+ "tick": 674,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 105,+ "tick": 675,+ "label": "TopLevelBox [\"readsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 105,+ "tick": 676,+ "label": "TopLevelBox [\"readList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 105,+ "tick": 680,+ "label": "TopLevelBox [\"<\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 105,+ "tick": 681,+ "label": "TopLevelBox [\"<=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 105,+ "tick": 682,+ "label": "TopLevelBox [\">\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 105,+ "tick": 683,+ "label": "TopLevelBox [\">=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 105,+ "tick": 684,+ "label": "TopLevelBox [\"max\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 105,+ "tick": 685,+ "label": "TopLevelBox [\"min\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 105,+ "tick": 686,+ "label": "TopLevelBox [\"from\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 105,+ "tick": 687,+ "label": "TopLevelBox [\"to\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 102,+ "tick": 688,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 102,+ "tick": 689,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 102,+ "tick": 690,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 102,+ "tick": 692,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 93,+ "tick": 699,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 93,+ "tick": 700,+ "label": "TopLevelBox [\"readsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 93,+ "tick": 701,+ "label": "TopLevelBox [\"readList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 93,+ "tick": 705,+ "label": "TopLevelBox [\"<\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 93,+ "tick": 706,+ "label": "TopLevelBox [\"<=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 93,+ "tick": 707,+ "label": "TopLevelBox [\">\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 93,+ "tick": 708,+ "label": "TopLevelBox [\">=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 93,+ "tick": 709,+ "label": "TopLevelBox [\"max\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 93,+ "tick": 710,+ "label": "TopLevelBox [\"min\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 90,+ "tick": 711,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 90,+ "tick": 712,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 90,+ "tick": 713,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 90,+ "tick": 715,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 59,+ "tick": 718,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 59,+ "tick": 719,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 59,+ "tick": 720,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 59,+ "tick": 722,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 82,+ "tick": 725,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 82,+ "tick": 726,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 82,+ "tick": 727,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 82,+ "tick": 729,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 75,+ "tick": 732,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 75,+ "tick": 733,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 75,+ "tick": 734,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 75,+ "tick": 736,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 66,+ "tick": 739,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 66,+ "tick": 740,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 66,+ "tick": 741,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Metadata",+ "source": "src/Kafka/Metadata.hs",+ "line": 66,+ "tick": 743,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer",+ "source": "src/Kafka/Producer.hs",+ "line": 292,+ "tick": 93,+ "label": "BinBox GuardBinBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer",+ "source": "src/Kafka/Producer.hs",+ "line": 234,+ "tick": 141,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer",+ "source": "src/Kafka/Producer.hs",+ "line": 204,+ "tick": 201,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer",+ "source": "src/Kafka/Producer.hs",+ "line": 204,+ "tick": 202,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer",+ "source": "src/Kafka/Producer.hs",+ "line": 158,+ "tick": 277,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer",+ "source": "src/Kafka/Producer.hs",+ "line": 114,+ "tick": 362,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Convert",+ "source": "src/Kafka/Producer/Convert.hs",+ "line": 43,+ "tick": 0,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Convert",+ "source": "src/Kafka/Producer/Convert.hs",+ "line": 43,+ "tick": 1,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Convert",+ "source": "src/Kafka/Producer/Convert.hs",+ "line": 43,+ "tick": 2,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Convert",+ "source": "src/Kafka/Producer/Convert.hs",+ "line": 43,+ "tick": 3,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Convert",+ "source": "src/Kafka/Producer/Convert.hs",+ "line": 43,+ "tick": 4,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Convert",+ "source": "src/Kafka/Producer/Convert.hs",+ "line": 44,+ "tick": 5,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Convert",+ "source": "src/Kafka/Producer/Convert.hs",+ "line": 44,+ "tick": 6,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Convert",+ "source": "src/Kafka/Producer/Convert.hs",+ "line": 44,+ "tick": 7,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Convert",+ "source": "src/Kafka/Producer/Convert.hs",+ "line": 45,+ "tick": 8,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Convert",+ "source": "src/Kafka/Producer/Convert.hs",+ "line": 45,+ "tick": 9,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Convert",+ "source": "src/Kafka/Producer/Convert.hs",+ "line": 45,+ "tick": 10,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Convert",+ "source": "src/Kafka/Producer/Convert.hs",+ "line": 45,+ "tick": 11,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Convert",+ "source": "src/Kafka/Producer/Convert.hs",+ "line": 43,+ "tick": 12,+ "label": "TopLevelBox [\"handleProduceErr'\"]",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Convert",+ "source": "src/Kafka/Producer/Convert.hs",+ "line": 32,+ "tick": 21,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Convert",+ "source": "src/Kafka/Producer/Convert.hs",+ "line": 32,+ "tick": 22,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Convert",+ "source": "src/Kafka/Producer/Convert.hs",+ "line": 32,+ "tick": 23,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Convert",+ "source": "src/Kafka/Producer/Convert.hs",+ "line": 32,+ "tick": 24,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Convert",+ "source": "src/Kafka/Producer/Convert.hs",+ "line": 32,+ "tick": 25,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Convert",+ "source": "src/Kafka/Producer/Convert.hs",+ "line": 33,+ "tick": 26,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Convert",+ "source": "src/Kafka/Producer/Convert.hs",+ "line": 33,+ "tick": 27,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Convert",+ "source": "src/Kafka/Producer/Convert.hs",+ "line": 34,+ "tick": 28,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Convert",+ "source": "src/Kafka/Producer/Convert.hs",+ "line": 34,+ "tick": 29,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Convert",+ "source": "src/Kafka/Producer/Convert.hs",+ "line": 34,+ "tick": 30,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Convert",+ "source": "src/Kafka/Producer/Convert.hs",+ "line": 34,+ "tick": 31,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Convert",+ "source": "src/Kafka/Producer/Convert.hs",+ "line": 32,+ "tick": 32,+ "label": "TopLevelBox [\"handleProduceErr\"]",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Types",+ "source": "src/Kafka/Producer/Types.hs",+ "line": 91,+ "tick": 16,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Types",+ "source": "src/Kafka/Producer/Types.hs",+ "line": 91,+ "tick": 17,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Types",+ "source": "src/Kafka/Producer/Types.hs",+ "line": 91,+ "tick": 18,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Types",+ "source": "src/Kafka/Producer/Types.hs",+ "line": 91,+ "tick": 20,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Types",+ "source": "src/Kafka/Producer/Types.hs",+ "line": 91,+ "tick": 21,+ "label": "TopLevelBox [\"compare\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Types",+ "source": "src/Kafka/Producer/Types.hs",+ "line": 91,+ "tick": 22,+ "label": "TopLevelBox [\"<\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Types",+ "source": "src/Kafka/Producer/Types.hs",+ "line": 91,+ "tick": 23,+ "label": "TopLevelBox [\"<=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Types",+ "source": "src/Kafka/Producer/Types.hs",+ "line": 91,+ "tick": 24,+ "label": "TopLevelBox [\">\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Types",+ "source": "src/Kafka/Producer/Types.hs",+ "line": 91,+ "tick": 25,+ "label": "TopLevelBox [\">=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Types",+ "source": "src/Kafka/Producer/Types.hs",+ "line": 91,+ "tick": 26,+ "label": "TopLevelBox [\"max\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Types",+ "source": "src/Kafka/Producer/Types.hs",+ "line": 91,+ "tick": 27,+ "label": "TopLevelBox [\"min\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Types",+ "source": "src/Kafka/Producer/Types.hs",+ "line": 91,+ "tick": 28,+ "label": "TopLevelBox [\"succ\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Types",+ "source": "src/Kafka/Producer/Types.hs",+ "line": 91,+ "tick": 29,+ "label": "TopLevelBox [\"pred\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Types",+ "source": "src/Kafka/Producer/Types.hs",+ "line": 91,+ "tick": 32,+ "label": "TopLevelBox [\"enumFrom\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Types",+ "source": "src/Kafka/Producer/Types.hs",+ "line": 91,+ "tick": 33,+ "label": "TopLevelBox [\"enumFromThen\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Types",+ "source": "src/Kafka/Producer/Types.hs",+ "line": 91,+ "tick": 35,+ "label": "TopLevelBox [\"enumFromThenTo\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Types",+ "source": "src/Kafka/Producer/Types.hs",+ "line": 91,+ "tick": 38,+ "label": "TopLevelBox [\"from\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Types",+ "source": "src/Kafka/Producer/Types.hs",+ "line": 91,+ "tick": 39,+ "label": "TopLevelBox [\"to\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Types",+ "source": "src/Kafka/Producer/Types.hs",+ "line": 78,+ "tick": 40,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Types",+ "source": "src/Kafka/Producer/Types.hs",+ "line": 78,+ "tick": 41,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Types",+ "source": "src/Kafka/Producer/Types.hs",+ "line": 78,+ "tick": 42,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Types",+ "source": "src/Kafka/Producer/Types.hs",+ "line": 68,+ "tick": 48,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Types",+ "source": "src/Kafka/Producer/Types.hs",+ "line": 68,+ "tick": 49,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Types",+ "source": "src/Kafka/Producer/Types.hs",+ "line": 68,+ "tick": 51,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Types",+ "source": "src/Kafka/Producer/Types.hs",+ "line": 57,+ "tick": 53,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Types",+ "source": "src/Kafka/Producer/Types.hs",+ "line": 57,+ "tick": 54,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Types",+ "source": "src/Kafka/Producer/Types.hs",+ "line": 57,+ "tick": 55,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Types",+ "source": "src/Kafka/Producer/Types.hs",+ "line": 57,+ "tick": 56,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Types",+ "source": "src/Kafka/Producer/Types.hs",+ "line": 64,+ "tick": 59,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Types",+ "source": "src/Kafka/Producer/Types.hs",+ "line": 64,+ "tick": 60,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Types",+ "source": "src/Kafka/Producer/Types.hs",+ "line": 64,+ "tick": 61,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Types",+ "source": "src/Kafka/Producer/Types.hs",+ "line": 64,+ "tick": 64,+ "label": "TopLevelBox [\"compare\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Types",+ "source": "src/Kafka/Producer/Types.hs",+ "line": 64,+ "tick": 65,+ "label": "TopLevelBox [\"<\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Types",+ "source": "src/Kafka/Producer/Types.hs",+ "line": 64,+ "tick": 66,+ "label": "TopLevelBox [\"<=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Types",+ "source": "src/Kafka/Producer/Types.hs",+ "line": 64,+ "tick": 67,+ "label": "TopLevelBox [\">\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Types",+ "source": "src/Kafka/Producer/Types.hs",+ "line": 64,+ "tick": 68,+ "label": "TopLevelBox [\">=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Types",+ "source": "src/Kafka/Producer/Types.hs",+ "line": 64,+ "tick": 69,+ "label": "TopLevelBox [\"max\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Types",+ "source": "src/Kafka/Producer/Types.hs",+ "line": 64,+ "tick": 70,+ "label": "TopLevelBox [\"min\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Types",+ "source": "src/Kafka/Producer/Types.hs",+ "line": 64,+ "tick": 71,+ "label": "TopLevelBox [\"from\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Producer.Types",+ "source": "src/Kafka/Producer/Types.hs",+ "line": 64,+ "tick": 72,+ "label": "TopLevelBox [\"to\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Topic",+ "source": "src/Kafka/Topic.hs",+ "line": 196,+ "tick": 1,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Topic",+ "source": "src/Kafka/Topic.hs",+ "line": 147,+ "tick": 127,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Topic",+ "source": "src/Kafka/Topic.hs",+ "line": 114,+ "tick": 198,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Topic",+ "source": "src/Kafka/Topic.hs",+ "line": 114,+ "tick": 199,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Topic",+ "source": "src/Kafka/Topic.hs",+ "line": 114,+ "tick": 200,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Topic",+ "source": "src/Kafka/Topic.hs",+ "line": 114,+ "tick": 201,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Topic",+ "source": "src/Kafka/Topic.hs",+ "line": 114,+ "tick": 202,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Topic",+ "source": "src/Kafka/Topic.hs",+ "line": 114,+ "tick": 203,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Topic",+ "source": "src/Kafka/Topic.hs",+ "line": 114,+ "tick": 204,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Topic",+ "source": "src/Kafka/Topic.hs",+ "line": 107,+ "tick": 217,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Topic",+ "source": "src/Kafka/Topic.hs",+ "line": 107,+ "tick": 218,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Topic",+ "source": "src/Kafka/Topic.hs",+ "line": 107,+ "tick": 219,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Topic",+ "source": "src/Kafka/Topic.hs",+ "line": 107,+ "tick": 220,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Topic",+ "source": "src/Kafka/Topic.hs",+ "line": 75,+ "tick": 270,+ "label": "BinBox GuardBinBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Topic",+ "source": "src/Kafka/Topic.hs",+ "line": 86,+ "tick": 325,+ "label": "BinBox GuardBinBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Topic",+ "source": "src/Kafka/Topic.hs",+ "line": 61,+ "tick": 335,+ "label": "BinBox GuardBinBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Topic",+ "source": "src/Kafka/Topic.hs",+ "line": 66,+ "tick": 355,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Topic",+ "source": "src/Kafka/Topic.hs",+ "line": 66,+ "tick": 356,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Topic",+ "source": "src/Kafka/Topic.hs",+ "line": 66,+ "tick": 357,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Topic",+ "source": "src/Kafka/Topic.hs",+ "line": 66,+ "tick": 358,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Topic",+ "source": "src/Kafka/Topic.hs",+ "line": 66,+ "tick": 359,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Topic",+ "source": "src/Kafka/Topic.hs",+ "line": 65,+ "tick": 360,+ "label": "ExpBox True",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Topic",+ "source": "src/Kafka/Topic.hs",+ "line": 38,+ "tick": 380,+ "label": "BinBox GuardBinBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Topic.Types",+ "source": "src/Kafka/Topic/Types.hs",+ "line": 24,+ "tick": 12,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Topic.Types",+ "source": "src/Kafka/Topic/Types.hs",+ "line": 24,+ "tick": 13,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Topic.Types",+ "source": "src/Kafka/Topic/Types.hs",+ "line": 24,+ "tick": 14,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Topic.Types",+ "source": "src/Kafka/Topic/Types.hs",+ "line": 16,+ "tick": 15,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Topic.Types",+ "source": "src/Kafka/Topic/Types.hs",+ "line": 16,+ "tick": 16,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Topic.Types",+ "source": "src/Kafka/Topic/Types.hs",+ "line": 16,+ "tick": 17,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Topic.Types",+ "source": "src/Kafka/Topic/Types.hs",+ "line": 16,+ "tick": 18,+ "label": "TopLevelBox [\"==\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Topic.Types",+ "source": "src/Kafka/Topic/Types.hs",+ "line": 16,+ "tick": 19,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Topic.Types",+ "source": "src/Kafka/Topic/Types.hs",+ "line": 13,+ "tick": 20,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Topic.Types",+ "source": "src/Kafka/Topic/Types.hs",+ "line": 13,+ "tick": 21,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Topic.Types",+ "source": "src/Kafka/Topic/Types.hs",+ "line": 13,+ "tick": 22,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Topic.Types",+ "source": "src/Kafka/Topic/Types.hs",+ "line": 13,+ "tick": 23,+ "label": "TopLevelBox [\"==\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Topic.Types",+ "source": "src/Kafka/Topic/Types.hs",+ "line": 13,+ "tick": 24,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 200,+ "tick": 55,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 200,+ "tick": 59,+ "label": "TopLevelBox [\"readsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 200,+ "tick": 60,+ "label": "TopLevelBox [\"readList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 200,+ "tick": 63,+ "label": "TopLevelBox [\"from\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 200,+ "tick": 64,+ "label": "TopLevelBox [\"to\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 201,+ "tick": 66,+ "label": "TopLevelBox [\"sconcat\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 201,+ "tick": 67,+ "label": "TopLevelBox [\"stimes\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 201,+ "tick": 69,+ "label": "TopLevelBox [\"mappend\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 201,+ "tick": 70,+ "label": "TopLevelBox [\"mconcat\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 180,+ "tick": 71,+ "label": "TopLevelBox [\"==\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 180,+ "tick": 72,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 180,+ "tick": 75,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 180,+ "tick": 76,+ "label": "TopLevelBox [\"from\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 180,+ "tick": 77,+ "label": "TopLevelBox [\"to\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 151,+ "tick": 78,+ "label": "TopLevelBox [\"==\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 151,+ "tick": 79,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 151,+ "tick": 80,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 151,+ "tick": 81,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 151,+ "tick": 82,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 151,+ "tick": 83,+ "label": "TopLevelBox [\"from\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 151,+ "tick": 84,+ "label": "TopLevelBox [\"to\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 130,+ "tick": 86,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 130,+ "tick": 89,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 119,+ "tick": 94,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 119,+ "tick": 95,+ "label": "TopLevelBox [\"succ\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 119,+ "tick": 96,+ "label": "TopLevelBox [\"pred\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 119,+ "tick": 99,+ "label": "TopLevelBox [\"enumFrom\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 119,+ "tick": 100,+ "label": "TopLevelBox [\"enumFromThen\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 119,+ "tick": 102,+ "label": "TopLevelBox [\"enumFromThenTo\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 119,+ "tick": 104,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 107,+ "tick": 109,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 107,+ "tick": 110,+ "label": "TopLevelBox [\"readsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 107,+ "tick": 111,+ "label": "TopLevelBox [\"readList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 107,+ "tick": 114,+ "label": "TopLevelBox [\"from\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 107,+ "tick": 115,+ "label": "TopLevelBox [\"to\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 102,+ "tick": 116,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 102,+ "tick": 117,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 102,+ "tick": 118,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 102,+ "tick": 120,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 89,+ "tick": 128,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 89,+ "tick": 131,+ "label": "TopLevelBox [\"<=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 89,+ "tick": 134,+ "label": "TopLevelBox [\"max\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 89,+ "tick": 135,+ "label": "TopLevelBox [\"min\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 89,+ "tick": 136,+ "label": "TopLevelBox [\"readsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 89,+ "tick": 137,+ "label": "TopLevelBox [\"readList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 77,+ "tick": 143,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 77,+ "tick": 144,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 77,+ "tick": 145,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 77,+ "tick": 146,+ "label": "TopLevelBox [\"readsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 77,+ "tick": 147,+ "label": "TopLevelBox [\"readList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 77,+ "tick": 148,+ "label": "TopLevelBox [\"readPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 77,+ "tick": 149,+ "label": "TopLevelBox [\"readListPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 77,+ "tick": 151,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 77,+ "tick": 152,+ "label": "TopLevelBox [\"compare\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 77,+ "tick": 153,+ "label": "TopLevelBox [\"<\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 77,+ "tick": 154,+ "label": "TopLevelBox [\"<=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 77,+ "tick": 155,+ "label": "TopLevelBox [\">\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 77,+ "tick": 156,+ "label": "TopLevelBox [\">=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 77,+ "tick": 157,+ "label": "TopLevelBox [\"max\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 77,+ "tick": 158,+ "label": "TopLevelBox [\"min\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 77,+ "tick": 159,+ "label": "TopLevelBox [\"from\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 77,+ "tick": 160,+ "label": "TopLevelBox [\"to\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 68,+ "tick": 164,+ "label": "TopLevelBox [\"readsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 68,+ "tick": 165,+ "label": "TopLevelBox [\"readList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 68,+ "tick": 169,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 68,+ "tick": 171,+ "label": "TopLevelBox [\"<\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 68,+ "tick": 172,+ "label": "TopLevelBox [\"<=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 68,+ "tick": 173,+ "label": "TopLevelBox [\">\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 68,+ "tick": 174,+ "label": "TopLevelBox [\">=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 68,+ "tick": 175,+ "label": "TopLevelBox [\"max\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 68,+ "tick": 176,+ "label": "TopLevelBox [\"min\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 68,+ "tick": 177,+ "label": "TopLevelBox [\"from\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 68,+ "tick": 178,+ "label": "TopLevelBox [\"to\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 63,+ "tick": 186,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 63,+ "tick": 187,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 63,+ "tick": 188,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 63,+ "tick": 190,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 63,+ "tick": 192,+ "label": "TopLevelBox [\"<\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 63,+ "tick": 193,+ "label": "TopLevelBox [\"<=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 63,+ "tick": 194,+ "label": "TopLevelBox [\">\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 63,+ "tick": 195,+ "label": "TopLevelBox [\">=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 63,+ "tick": 196,+ "label": "TopLevelBox [\"max\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 63,+ "tick": 197,+ "label": "TopLevelBox [\"min\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 54,+ "tick": 204,+ "label": "TopLevelBox [\"readsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 54,+ "tick": 205,+ "label": "TopLevelBox [\"readList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 54,+ "tick": 209,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 54,+ "tick": 211,+ "label": "TopLevelBox [\"<\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 54,+ "tick": 212,+ "label": "TopLevelBox [\"<=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 54,+ "tick": 213,+ "label": "TopLevelBox [\">\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 54,+ "tick": 214,+ "label": "TopLevelBox [\">=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 54,+ "tick": 215,+ "label": "TopLevelBox [\"max\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 54,+ "tick": 216,+ "label": "TopLevelBox [\"min\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 54,+ "tick": 217,+ "label": "TopLevelBox [\"from\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 54,+ "tick": 218,+ "label": "TopLevelBox [\"to\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 49,+ "tick": 230,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 49,+ "tick": 231,+ "label": "TopLevelBox [\"readsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 49,+ "tick": 232,+ "label": "TopLevelBox [\"readList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 49,+ "tick": 237,+ "label": "TopLevelBox [\"<=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 49,+ "tick": 239,+ "label": "TopLevelBox [\">=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 49,+ "tick": 240,+ "label": "TopLevelBox [\"max\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 49,+ "tick": 241,+ "label": "TopLevelBox [\"min\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 49,+ "tick": 242,+ "label": "TopLevelBox [\"from\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 49,+ "tick": 243,+ "label": "TopLevelBox [\"to\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 50,+ "tick": 244,+ "label": "TopLevelBox [\"succ\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 50,+ "tick": 245,+ "label": "TopLevelBox [\"pred\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 50,+ "tick": 248,+ "label": "TopLevelBox [\"enumFrom\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 50,+ "tick": 249,+ "label": "TopLevelBox [\"enumFromThen\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 50,+ "tick": 250,+ "label": "TopLevelBox [\"enumFromTo\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 50,+ "tick": 251,+ "label": "TopLevelBox [\"enumFromThenTo\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 45,+ "tick": 256,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 45,+ "tick": 258,+ "label": "TopLevelBox [\"<\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 45,+ "tick": 259,+ "label": "TopLevelBox [\"<=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 45,+ "tick": 260,+ "label": "TopLevelBox [\">\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 45,+ "tick": 261,+ "label": "TopLevelBox [\">=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 45,+ "tick": 262,+ "label": "TopLevelBox [\"max\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 45,+ "tick": 263,+ "label": "TopLevelBox [\"min\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 45,+ "tick": 264,+ "label": "TopLevelBox [\"readsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 45,+ "tick": 265,+ "label": "TopLevelBox [\"readList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 45,+ "tick": 268,+ "label": "TopLevelBox [\"from\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Types",+ "source": "src/Kafka/Types.hs",+ "line": 45,+ "tick": 269,+ "label": "TopLevelBox [\"to\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Version",+ "source": "src/Kafka/Version.hs",+ "line": 22,+ "tick": 25,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Version",+ "source": "src/Kafka/Version.hs",+ "line": 22,+ "tick": 26,+ "label": "TopLevelBox [\"versionMajor\"]",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Version",+ "source": "src/Kafka/Version.hs",+ "line": 23,+ "tick": 27,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Version",+ "source": "src/Kafka/Version.hs",+ "line": 23,+ "tick": 28,+ "label": "TopLevelBox [\"versionMinor\"]",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Version",+ "source": "src/Kafka/Version.hs",+ "line": 24,+ "tick": 29,+ "label": "ExpBox False",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Version",+ "source": "src/Kafka/Version.hs",+ "line": 24,+ "tick": 30,+ "label": "TopLevelBox [\"versionRevision\"]",+ "generated": false,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Version",+ "source": "src/Kafka/Version.hs",+ "line": 26,+ "tick": 32,+ "label": "TopLevelBox [\"/=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Version",+ "source": "src/Kafka/Version.hs",+ "line": 26,+ "tick": 33,+ "label": "TopLevelBox [\"compare\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Version",+ "source": "src/Kafka/Version.hs",+ "line": 26,+ "tick": 34,+ "label": "TopLevelBox [\"<\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Version",+ "source": "src/Kafka/Version.hs",+ "line": 26,+ "tick": 35,+ "label": "TopLevelBox [\"<=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Version",+ "source": "src/Kafka/Version.hs",+ "line": 26,+ "tick": 36,+ "label": "TopLevelBox [\">\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Version",+ "source": "src/Kafka/Version.hs",+ "line": 26,+ "tick": 37,+ "label": "TopLevelBox [\">=\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Version",+ "source": "src/Kafka/Version.hs",+ "line": 26,+ "tick": 38,+ "label": "TopLevelBox [\"max\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Version",+ "source": "src/Kafka/Version.hs",+ "line": 26,+ "tick": 39,+ "label": "TopLevelBox [\"min\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Version",+ "source": "src/Kafka/Version.hs",+ "line": 26,+ "tick": 40,+ "label": "TopLevelBox [\"showsPrec\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Version",+ "source": "src/Kafka/Version.hs",+ "line": 26,+ "tick": 41,+ "label": "TopLevelBox [\"show\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ },+ {+ "module": "Kafka.Version",+ "source": "src/Kafka/Version.hs",+ "line": 26,+ "tick": 42,+ "label": "TopLevelBox [\"showList\"]",+ "generated": true,+ "contract": "OWN-source-coverage",+ "owner": 16+ }+ ],+ "module_tick_counts": {+ "Kafka.Callbacks": 40,+ "Kafka.Consumer": 1542,+ "Kafka.Consumer.Callbacks": 240,+ "Kafka.Consumer.ConsumerProperties": 175,+ "Kafka.Consumer.Convert": 413,+ "Kafka.Consumer.Subscription": 42,+ "Kafka.Consumer.Types": 270,+ "Kafka.Dump": 80,+ "Kafka.Internal.CallbackOwner": 116,+ "Kafka.Internal.RdKafka": 5972,+ "Kafka.Internal.Setup": 270,+ "Kafka.Internal.Shared": 279,+ "Kafka.Metadata": 746,+ "Kafka.Producer": 375,+ "Kafka.Producer.Callbacks": 147,+ "Kafka.Producer.Convert": 43,+ "Kafka.Producer.ProducerProperties": 127,+ "Kafka.Producer.Types": 79,+ "Kafka.Topic": 417,+ "Kafka.Topic.Types": 25,+ "Kafka.Transaction": 106,+ "Kafka.Types": 285,+ "Kafka.Version": 43+ },+ "measured_native_wrapper_ticks": 2752,+ "artifacts": {+ "dist-coverage/reports/test.log": "26bb750822aaad387120303d6c0f39724fca933f5439d10440e340548d6da96a",+ "dist-coverage/reports/unlinked-zero.tix": "6cac1eec544576f04eb7e830d6652339e5679cde2167c272fea2976ff45f470b",+ "dist-coverage/reports/nonthreaded-build.log": "491fc61f34626e69c8bb2925429142d66030e50201d3b7e1a9ce9cecd07dc5eb",+ "dist-coverage/reports/nonthreaded-rts.txt": "e30f15edf898c4f023cbf2f49a34315dfefee8daf9edb50281a7fa588c9f1638",+ "dist-coverage/reports/nonthreaded-runtime.log": "78784f276f037d38cda9bacf2e13ebd0ca999a913d9da9646a4d3fc042597126",+ "dist-coverage/reports/nonthreaded-runtime.tix": "ab3ec628261937eefbaf234fecc9e885aba6a93bb6fc105e671a295c305203df",+ "dist-coverage/reports/nonthreaded-consumer.tix": "edfbcb8d8b3d7d8f65fbaef63e8a7d1fb629217b659bd2dad085f4f008d238f9",+ "dist-coverage/children/lifetime-commit-async-3445840867802964827.tix": "21dd74c971992e54e0def5b71e3d2e3027d38d42250a785cac4cdf9d7815fda8",+ "dist-coverage/children/lifetime-commit-sync-1427711464913245544.tix": "21c494fde541be23934e8d0ac373ebd361d2dcb725314b9d82335b3c65fbfddf",+ "dist-coverage/children/lifetime-error-async-2153874117919261256.tix": "7930f08c6654ee788ad78d3010ef2d9f159f8c3f94cf1834080dd7eccf769c46",+ "dist-coverage/children/lifetime-error-sync-11445752217852166514.tix": "537327e6510367e7c2c8616d364e5586afe8984dee682276734e02f44240b65a",+ "dist-coverage/children/lifetime-log-async-14572504187711751284.tix": "a72b642581278b29477a419e2862e1384b0ab2d130ed4cac012d8c43ae8cda13",+ "dist-coverage/children/lifetime-log-sync-4345383553621594798.tix": "d39a706909abdceb6ee2a02441136a2a0d2ed1a6769a92c6391a8c8088c2a7b8",+ "dist-coverage/children/lifetime-rebalance-async-8190188771811667777.tix": "2f559a1dc44e5c56cbd41004646920f702db79723eda36ece36bc26b4fe744d4",+ "dist-coverage/children/lifetime-rebalance-sync-17149997365443858423.tix": "bf751e6df3b94839f63df4be97620846ea11e70a96384d3a84f0f16bc37b8852",+ "dist-coverage/children/lifetime-stats-async-7686762392776489018.tix": "5b7962230e73c18424c1793b2e6434f223e95a4e9b3a7d185eb5ac7f94fa3e4f",+ "dist-coverage/children/lifetime-stats-sync-7783921844223599292.tix": "9cba32eff42cf087132cf00b4c5de523eefe97b3ed00d3c1ce510f52640a2819",+ "dist-coverage/children/metadata-groups-5710435570244437146.tix": "7eec2b6399d7cde7e079d6cfe55fc841477835d32217404aae07254893039b5f",+ "dist-coverage/children/metadata-metadata-3627255582609216499.tix": "2fcb47357d614e67aade029d9c1ec541ecc656892ec40e4f685f390e83841404",+ "dist-coverage/children/producer-global-14694924957554744759.tix": "73adb06d2df5a4cef9d1bbaedf380eb9522eb0b0b247fb9217317220c2e3831e",+ "dist-coverage/children/producer-message-3347577244058732037.tix": "1ffc197d550d8ae150dae0cc3f21b6c791a63851b68483237b7f5d9067586873",+ "dist-coverage/children/rebalance-cooperative-assign-async-decode-11429113694600619038.tix": "50cf9c7eec53cd92570a96c85c9edb9f2223105451daafcda50d07f650c246f7",+ "dist-coverage/children/rebalance-cooperative-assign-async-native-16636766166812799660.tix": "72b40759d76fccf5b7cb19fc883da40c67c070b0cd4142a6044be5fd2cd6a20b",+ "dist-coverage/children/rebalance-cooperative-assign-sync-decode-11527071196657719464.tix": "30efa89d53bf89378519539657ce43b882d8624fb8fbe48a8440582fae6be879",+ "dist-coverage/children/rebalance-cooperative-assign-sync-native-241441106163866813.tix": "54f9fc47ccf99f752e6dd8a56b3c3ecf0d013f313c73c8b22f5f1621e1b58240",+ "dist-coverage/children/rebalance-cooperative-revoke-async-decode-9567704991314952527.tix": "da6095b2afa65577a25904ef702d3a3c4f3b7f05c1dcea4bb974c32315d3ba76",+ "dist-coverage/children/rebalance-cooperative-revoke-async-native-8369675418354549437.tix": "61ec19008d4c479e44cc427a9b3c49727c47e864a24924ff72716d476ee58be0",+ "dist-coverage/children/rebalance-cooperative-revoke-sync-decode-17475852808267486359.tix": "84cfbee785d5c07eb5a379ae760c0f41acd1aabdc697d89e92460801d95dfa2b",+ "dist-coverage/children/rebalance-cooperative-revoke-sync-native-14925682060783270698.tix": "943801b29a9f35e0b5910ebdfccde533d84310b74fc606f00943b7f1692751e9",+ "dist-coverage/children/rebalance-eager-assign-async-native-17096385521698601121.tix": "1149ce490af9119397f45fd9b303cc118fef3809e97b2ef9b782ee9ba3948c97",+ "dist-coverage/children/rebalance-eager-assign-sync-native-16867040414742754414.tix": "7b0e4be45ededa0ea8bdce9571732c8281ab2e50ea8f277074ca10e673624b3f",+ "dist-coverage/children/rebalance-eager-revoke-async-native-14526171231388420411.tix": "4619fa63aaaa83071608ae14b8f0356003e1c37487bb677fc420277484cc12de",+ "dist-coverage/children/rebalance-eager-revoke-sync-native-17648468782693871658.tix": "b0b6c7ee4a69952b4358e7d9aad1ef41be18a8f834dae6c992dc7f65488dcd33",+ "dist-coverage/children/rebalance-unexpected-async-native-1454587398926348834.tix": "6479d545923960310389bad46a65e85d617d425cda35ef6d5a30361a65bcd4dc",+ "dist-coverage/children/rebalance-unexpected-async-reset-failure-8979534833077043535.tix": "953fdbe7f9192dc2c3036f8234959107a7fba044fbf8c3a6e8c67e73d3fbc16f",+ "dist-coverage/children/rebalance-unexpected-sync-native-16000384628216553118.tix": "c7f891ffce987b043848aae2959b92a68a85abce677220727a19b0522b9d9d5d",+ "dist-coverage/children/rebalance-unexpected-sync-reset-failure-16094562768818342740.tix": "f452b60a5a8bcee718c4bc67cabc477a889df47973aa1e56678ad30f448f60ae",+ "dist-coverage/reports/rdkafka-hs-test.tix": "5b9364f563e093477222834e61cd993f3565e2ceb8f1aaa442b86b85077cf5d4",+ "dist-coverage/build/aarch64-osx/ghc-9.12.4/rdkafka-hs-1.0.0.1/t/rdkafka-hs-test/hpc/vanilla/tix/rdkafka-hs-test.tix": "7deba9fb301363be9ac532b25533c70f56aa6a8d09d810d9321945631325115c",+ "dist-coverage/reports/rdkafka-hs-test.txt": "007d458e3ae0249e5c0a4b7206b2a5c1a2fb193e8688d6d32532d4445910ade7",+ "dist-coverage/reports/rdkafka-hs-integration.tix": "697f15cad6076821123947f115e16db597fbd7dc55dfb1739c07827bdd2a1d28",+ "dist-coverage/build/aarch64-osx/ghc-9.12.4/rdkafka-hs-1.0.0.1/t/rdkafka-hs-integration/hpc/vanilla/tix/rdkafka-hs-integration.tix": "c733527a322463aee7dd2bc7bf0f9693ba8af3855e0bd6dc86a1fcaadb68b32f",+ "dist-coverage/reports/rdkafka-hs-integration.txt": "6244456fc79405f0e905a205ae28ff086bb422f29679ce2639fbbe01d4d569c7",+ "dist-coverage/reports/combined.tix": "860b5130828b9b3e66e87bb371b29a2958a16741821aa158150b920ebfc6b270",+ "dist-coverage/reports/combined.txt": "ab73ce2a398ba6ee90edc2b388ee02e4c2ab9d50dbb240ddf0203503b5f3c453",+ "dist-coverage/reports/combined.xml": "2e1c5351a29e6a6ebacb2195dce71af2cc59958fb52650f925430230c0b62d55",+ "dist-coverage/reports/ticks.txt": "1ec22a94f25f02fa01aa87c87c4d4fe06faa891fd0c23474ee0255f656c14bd8",+ "dist-coverage/build/aarch64-osx/ghc-9.12.4/rdkafka-hs-1.0.0.1/build/Kafka/Internal/RdKafka.hs.coverage-map.json": "bae27da1702bc7f779573b43f79af0d874bdfeb94dcb56200b9d17842892fe1e",+ "dist-coverage/reports/classified-metrics.json": "df125856ebb63c844a32a3c16cf7bdbbcf5f0cc9c883fd3a7af9de51cbd7ea15",+ "dist-coverage/reports/unexercised-functions.json": "d847c1ccdd19e2c0f1a479d50fa9aaa702748b405087e1870591b5ceab9f99c3",+ "dist-coverage/reports/misses.json": "8e77977577cf0332efeda04cde874b69c498b567edd911ecc45eaff86f8daae2",+ "docs/testing/broker-qualification-context.json": "d080bb062d1afed7d5a5b71ab37ed9b70b83fbe114d44650253af3999cc56c36",+ "dist-compatibility/expanded-source9/broker-final9-tests.txt": "1b2270f302280d667a9a755787ee368fce03adc8f849ef070c54f02d99919b84",+ "dist-compatibility/expanded-source9/broker-final9.log": "f9236628ae671ffa549c4c9ce17ba8ba1acaf5f69e066acfe4ebfe94bd303681",+ "dist-compatibility/expanded-source9/candidate.tar.gz": "a70e4839d24c5e5179ff9a8be48643951e185d604cd8ba3401587730279f3b22",+ "dist-compatibility/expanded-source9/root-functional-files.json": "69506c90cfc124f3a175a664873f5d8b49aff62a7426265c56c3dd64fcc84c21",+ "dist-compatibility/expanded-source9/phase9-functional-files.json": "d0e5d59aa49833ecd1305410c839cbebdbbb418679cecc6de0c2548b142dca4b",+ "dist-compatibility/expanded-source9/source-comparison.json": "635403f708e286d4461d40a3d86842d4c670ac70862a9688e2b5fbd72801ace5",+ "dist-compatibility/expanded-source9/configuration.json": "c6c0771e7da58c35d40170db3ec18cdd2439997e223ef4c088ac3f4e793707f9",+ "dist-compatibility/expanded-source9/fixture-cleanup.json": "22a1434a32c0b23c77e8cb0f788c46ca45dc4129ff55add57033437db77be5aa",+ "dist-compatibility/expanded-source9/phase9-loaded.log": "0ea352a045eddd425369467d19eef2c60d2ca235538e1335b9557897a003d120",+ "dist-compatibility/expanded-source9/phase9-version.log": "6ec9b644a82e1dd0a2ec1c57250b4e2d3043deb9a608d8384f7ec30026876a93",+ "docs/testing/authentication-qualification-context.json": "bbd1b7edc15934382e7b7f4e516ecce5688f257c0ee9eb19277e3b42ef26c730",+ "dist-compatibility/expanded-source9/authentication-final9-tests.txt": "e011f6a1ed4544904bc4117ebdd30e85339b33c096b3d0619bbff506f5e2e893",+ "dist-compatibility/expanded-source9/authentication-final9.log": "a9cc23df591ca6608c613090bf42ae57ece89c1dc3e3ede7bbc0dee1cbcd2457"+ },+ "qualification_registration": {+ "at": "2026-10-25T03:02:42.103167+00:00",+ "commands": [+ [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-coverage/build/aarch64-osx/ghc-9.12.4/rdkafka-hs-1.0.0.1/t/rdkafka-hs-integration/build/rdkafka-hs-integration/rdkafka-hs-integration",+ "--broker-qualification",+ "--list-tests",+ "+RTS",+ "--read-tix-file=no",+ "-RTS"+ ],+ [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-coverage/build/aarch64-osx/ghc-9.12.4/rdkafka-hs-1.0.0.1/t/rdkafka-hs-integration/build/rdkafka-hs-integration/rdkafka-hs-integration",+ "--authentication-qualification",+ "--list-tests",+ "+RTS",+ "--read-tix-file=no",+ "-RTS"+ ]+ ],+ "method": "Validate source-identical external behavior logs/listings against the actual primary binary registration; import no HPC ticks",+ "reproduce": [+ "python3",+ "scripts/collect-coverage.py",+ "--context",+ "docs/testing/broker-qualification-context.json",+ "--context",+ "docs/testing/authentication-qualification-context.json"+ ]+ }+}
+ docs/testing/coverage-matrix.json view
@@ -0,0 +1,14213 @@+{+ "schema_version": 1,+ "exports": {+ "Kafka.Consumer": [+ {+ "symbol": "Kafka.Callbacks.errorCallback",+ "members": []+ },+ {+ "symbol": "Kafka.Callbacks.logCallback",+ "members": []+ },+ {+ "symbol": "Kafka.Callbacks.statsCallback",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.Callbacks.offsetCommitCallback",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.Callbacks.rebalanceCallback",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.ConsumerProperties.CallbackPollMode",+ "members": [+ "Kafka.Consumer.ConsumerProperties.CallbackPollModeAsync",+ "Kafka.Consumer.ConsumerProperties.CallbackPollModeSync"+ ]+ },+ {+ "symbol": "Kafka.Consumer.ConsumerProperties.ConsumerProperties",+ "members": [+ "Kafka.Consumer.ConsumerProperties.ConsumerProperties",+ "Kafka.Consumer.ConsumerProperties.cpCallbackPollMode",+ "Kafka.Consumer.ConsumerProperties.cpCallbacks",+ "Kafka.Consumer.ConsumerProperties.cpLogLevel",+ "Kafka.Consumer.ConsumerProperties.cpProps"+ ]+ },+ {+ "symbol": "Kafka.Consumer.ConsumerProperties.autoCommit",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.ConsumerProperties.brokersList",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.ConsumerProperties.callbackPollMode",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.ConsumerProperties.clientId",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.ConsumerProperties.compression",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.ConsumerProperties.debugOptions",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.ConsumerProperties.effectiveCallbackPollMode",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.ConsumerProperties.extraProp",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.ConsumerProperties.extraProps",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.ConsumerProperties.groupId",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.ConsumerProperties.logLevel",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.ConsumerProperties.noAutoCommit",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.ConsumerProperties.noAutoOffsetStore",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.ConsumerProperties.queuedMaxMessagesKBytes",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.ConsumerProperties.setCallback",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.ConsumerProperties.statisticsInterval",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.ConsumerProperties.suppressDisconnectLogs",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.Subscription.Subscription",+ "members": [+ "Kafka.Consumer.Subscription.Subscription"+ ]+ },+ {+ "symbol": "Kafka.Consumer.Subscription.extraSubscriptionProps",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.Subscription.offsetReset",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.Subscription.topics",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.Types.ConsumerGroupId",+ "members": [+ "Kafka.Consumer.Types.ConsumerGroupId",+ "Kafka.Consumer.Types.unConsumerGroupId"+ ]+ },+ {+ "symbol": "Kafka.Consumer.Types.ConsumerMessageError",+ "members": [+ "Kafka.Consumer.Types.ConsumerMessageError",+ "Kafka.Consumer.Types.cmeError",+ "Kafka.Consumer.Types.cmeOffset",+ "Kafka.Consumer.Types.cmePartition",+ "Kafka.Consumer.Types.cmeTopic"+ ]+ },+ {+ "symbol": "Kafka.Consumer.Types.ConsumerRecord",+ "members": [+ "Kafka.Consumer.Types.ConsumerRecord",+ "Kafka.Consumer.Types.crHeaders",+ "Kafka.Consumer.Types.crKey",+ "Kafka.Consumer.Types.crOffset",+ "Kafka.Consumer.Types.crPartition",+ "Kafka.Consumer.Types.crTimestamp",+ "Kafka.Consumer.Types.crTopic",+ "Kafka.Consumer.Types.crValue"+ ]+ },+ {+ "symbol": "Kafka.Consumer.Types.KafkaConsumer",+ "members": [+ "Kafka.Consumer.Types.kcKafkaConf",+ "Kafka.Consumer.Types.kcKafkaPtr"+ ]+ },+ {+ "symbol": "Kafka.Consumer.Types.Offset",+ "members": [+ "Kafka.Consumer.Types.Offset",+ "Kafka.Consumer.Types.unOffset"+ ]+ },+ {+ "symbol": "Kafka.Consumer.Types.OffsetCommit",+ "members": [+ "Kafka.Consumer.Types.OffsetCommit",+ "Kafka.Consumer.Types.OffsetCommitAsync"+ ]+ },+ {+ "symbol": "Kafka.Consumer.Types.OffsetReset",+ "members": [+ "Kafka.Consumer.Types.Earliest",+ "Kafka.Consumer.Types.Latest"+ ]+ },+ {+ "symbol": "Kafka.Consumer.Types.OffsetStoreMethod",+ "members": [+ "Kafka.Consumer.Types.OffsetStoreBroker",+ "Kafka.Consumer.Types.OffsetStoreFile"+ ]+ },+ {+ "symbol": "Kafka.Consumer.Types.OffsetStoreSync",+ "members": [+ "Kafka.Consumer.Types.OffsetSyncDisable",+ "Kafka.Consumer.Types.OffsetSyncImmediate",+ "Kafka.Consumer.Types.OffsetSyncInterval"+ ]+ },+ {+ "symbol": "Kafka.Consumer.Types.PartitionOffset",+ "members": [+ "Kafka.Consumer.Types.PartitionOffset",+ "Kafka.Consumer.Types.PartitionOffsetBeginning",+ "Kafka.Consumer.Types.PartitionOffsetEnd",+ "Kafka.Consumer.Types.PartitionOffsetInvalid",+ "Kafka.Consumer.Types.PartitionOffsetStored"+ ]+ },+ {+ "symbol": "Kafka.Consumer.Types.RebalanceEvent",+ "members": [+ "Kafka.Consumer.Types.RebalanceAssign",+ "Kafka.Consumer.Types.RebalanceBeforeAssign",+ "Kafka.Consumer.Types.RebalanceBeforeRevoke",+ "Kafka.Consumer.Types.RebalanceRevoke"+ ]+ },+ {+ "symbol": "Kafka.Consumer.Types.SubscribedPartitions",+ "members": [+ "Kafka.Consumer.Types.SubscribedPartitions",+ "Kafka.Consumer.Types.SubscribedPartitionsAll"+ ]+ },+ {+ "symbol": "Kafka.Consumer.Types.Timestamp",+ "members": [+ "Kafka.Consumer.Types.CreateTime",+ "Kafka.Consumer.Types.LogAppendTime",+ "Kafka.Consumer.Types.NoTimestamp"+ ]+ },+ {+ "symbol": "Kafka.Consumer.Types.TopicPartition",+ "members": [+ "Kafka.Consumer.Types.TopicPartition",+ "Kafka.Consumer.Types.tpOffset",+ "Kafka.Consumer.Types.tpPartition",+ "Kafka.Consumer.Types.tpTopicName"+ ]+ },+ {+ "symbol": "Kafka.Consumer.Types.bitraverseM",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.Types.crMapKV",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.Types.crMapKey",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.Types.crMapValue",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.Types.sequenceFirst",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.Types.traverseFirst",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.Types.traverseFirstM",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.Types.traverseM",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.assign",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.assignment",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.assignmentLost",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.closeConsumer",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.commitAllOffsets",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.commitOffsetMessage",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.commitPartitionsOffsets",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.committed",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.consumerClosed",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.consumerFatalError",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.destroyConsumer",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.newAssignedConsumer",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.newConsumer",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.pausePartitions",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.pollConsumerEvents",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.pollMessage",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.pollMessageAttributed",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.pollMessageBatch",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.position",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.resumePartitions",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.rewindConsumer",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.runConsumer",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.seek",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.seekPartitions",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.setConsumerQueueIOEvent",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.setSaslCredentials",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.storeOffsetMessage",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.storeOffsets",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.subscription",+ "members": []+ },+ {+ "symbol": "Kafka.Internal.RdKafka.RdKafkaRespErrT",+ "members": [+ "Kafka.Internal.RdKafka.RdKafkaRespErrAllBrokersDown",+ "Kafka.Internal.RdKafka.RdKafkaRespErrApplication",+ "Kafka.Internal.RdKafka.RdKafkaRespErrAssignPartitions",+ "Kafka.Internal.RdKafka.RdKafkaRespErrAssignmentLost",+ "Kafka.Internal.RdKafka.RdKafkaRespErrAuthentication",+ "Kafka.Internal.RdKafka.RdKafkaRespErrAutoOffsetReset",+ "Kafka.Internal.RdKafka.RdKafkaRespErrBadCompression",+ "Kafka.Internal.RdKafka.RdKafkaRespErrBadMsg",+ "Kafka.Internal.RdKafka.RdKafkaRespErrBegin",+ "Kafka.Internal.RdKafka.RdKafkaRespErrBrokerNotAvailable",+ "Kafka.Internal.RdKafka.RdKafkaRespErrClusterAuthorizationFailed",+ "Kafka.Internal.RdKafka.RdKafkaRespErrConcurrentTransactions",+ "Kafka.Internal.RdKafka.RdKafkaRespErrConflict",+ "Kafka.Internal.RdKafka.RdKafkaRespErrCoordinatorLoadInProgress",+ "Kafka.Internal.RdKafka.RdKafkaRespErrCoordinatorNotAvailable",+ "Kafka.Internal.RdKafka.RdKafkaRespErrCritSysResource",+ "Kafka.Internal.RdKafka.RdKafkaRespErrDelegationTokenAuthDisabled",+ "Kafka.Internal.RdKafka.RdKafkaRespErrDelegationTokenAuthorizationFailed",+ "Kafka.Internal.RdKafka.RdKafkaRespErrDelegationTokenExpired",+ "Kafka.Internal.RdKafka.RdKafkaRespErrDelegationTokenNotFound",+ "Kafka.Internal.RdKafka.RdKafkaRespErrDelegationTokenOwnerMismatch",+ "Kafka.Internal.RdKafka.RdKafkaRespErrDelegationTokenRequestNotAllowed",+ "Kafka.Internal.RdKafka.RdKafkaRespErrDestroy",+ "Kafka.Internal.RdKafka.RdKafkaRespErrDestroyBroker",+ "Kafka.Internal.RdKafka.RdKafkaRespErrDuplicateResource",+ "Kafka.Internal.RdKafka.RdKafkaRespErrDuplicateSequenceNumber",+ "Kafka.Internal.RdKafka.RdKafkaRespErrDuplicateVoter",+ "Kafka.Internal.RdKafka.RdKafkaRespErrElectionNotNeeded",+ "Kafka.Internal.RdKafka.RdKafkaRespErrEligibleLeadersNotAvailable",+ "Kafka.Internal.RdKafka.RdKafkaRespErrEnd",+ "Kafka.Internal.RdKafka.RdKafkaRespErrEndAll",+ "Kafka.Internal.RdKafka.RdKafkaRespErrExistingSubscription",+ "Kafka.Internal.RdKafka.RdKafkaRespErrFail",+ "Kafka.Internal.RdKafka.RdKafkaRespErrFatal",+ "Kafka.Internal.RdKafka.RdKafkaRespErrFeatureUpdateFailed",+ "Kafka.Internal.RdKafka.RdKafkaRespErrFenced",+ "Kafka.Internal.RdKafka.RdKafkaRespErrFencedInstanceId",+ "Kafka.Internal.RdKafka.RdKafkaRespErrFencedLeaderEpoch",+ "Kafka.Internal.RdKafka.RdKafkaRespErrFencedMemberEpoch",+ "Kafka.Internal.RdKafka.RdKafkaRespErrFencedStateEpoch",+ "Kafka.Internal.RdKafka.RdKafkaRespErrFetchSessionIdNotFound",+ "Kafka.Internal.RdKafka.RdKafkaRespErrFs",+ "Kafka.Internal.RdKafka.RdKafkaRespErrGaplessGuarantee",+ "Kafka.Internal.RdKafka.RdKafkaRespErrGroupAuthorizationFailed",+ "Kafka.Internal.RdKafka.RdKafkaRespErrGroupIdNotFound",+ "Kafka.Internal.RdKafka.RdKafkaRespErrGroupMaxSizeReached",+ "Kafka.Internal.RdKafka.RdKafkaRespErrGroupSubscribedToTopic",+ "Kafka.Internal.RdKafka.RdKafkaRespErrIllegalGeneration",+ "Kafka.Internal.RdKafka.RdKafkaRespErrIllegalSaslState",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInProgress",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInconsistent",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInconsistentGroupProtocol",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInconsistentTopicId",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInconsistentVoterSet",+ "Kafka.Internal.RdKafka.RdKafkaRespErrIntr",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidArg",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidCommitOffsetSize",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidConfig",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidDifferentRecord",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidFetchSessionEpoch",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidGroupId",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidMsg",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidMsgSize",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidPartitions",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidPrincipalType",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidProducerEpoch",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidProducerIdMapping",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidRecord",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidRecordState",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidRegistration",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidRegularExpression",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidReplicaAssignment",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidReplicationFactor",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidRequest",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidRequiredAcks",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidSessionTimeout",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidShareSessionEpoch",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidTimestamp",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidTransactionTimeout",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidTxnState",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidType",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidUpdateVersion",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidVoterKey",+ "Kafka.Internal.RdKafka.RdKafkaRespErrIsrInsuff",+ "Kafka.Internal.RdKafka.RdKafkaRespErrKafkaStorageError",+ "Kafka.Internal.RdKafka.RdKafkaRespErrKeyDeserialization",+ "Kafka.Internal.RdKafka.RdKafkaRespErrKeySerialization",+ "Kafka.Internal.RdKafka.RdKafkaRespErrLeaderNotAvailable",+ "Kafka.Internal.RdKafka.RdKafkaRespErrListenerNotFound",+ "Kafka.Internal.RdKafka.RdKafkaRespErrLogDirNotFound",+ "Kafka.Internal.RdKafka.RdKafkaRespErrLogTruncation",+ "Kafka.Internal.RdKafka.RdKafkaRespErrMaxPollExceeded",+ "Kafka.Internal.RdKafka.RdKafkaRespErrMemberIdRequired",+ "Kafka.Internal.RdKafka.RdKafkaRespErrMismatchedEndpointType",+ "Kafka.Internal.RdKafka.RdKafkaRespErrMsgSizeTooLarge",+ "Kafka.Internal.RdKafka.RdKafkaRespErrMsgTimedOut",+ "Kafka.Internal.RdKafka.RdKafkaRespErrNetworkException",+ "Kafka.Internal.RdKafka.RdKafkaRespErrNoError",+ "Kafka.Internal.RdKafka.RdKafkaRespErrNoOffset",+ "Kafka.Internal.RdKafka.RdKafkaRespErrNoReassignmentInProgress",+ "Kafka.Internal.RdKafka.RdKafkaRespErrNodeUpdate",+ "Kafka.Internal.RdKafka.RdKafkaRespErrNoent",+ "Kafka.Internal.RdKafka.RdKafkaRespErrNonEmptyGroup",+ "Kafka.Internal.RdKafka.RdKafkaRespErrNoop",+ "Kafka.Internal.RdKafka.RdKafkaRespErrNotConfigured",+ "Kafka.Internal.RdKafka.RdKafkaRespErrNotController",+ "Kafka.Internal.RdKafka.RdKafkaRespErrNotCoordinator",+ "Kafka.Internal.RdKafka.RdKafkaRespErrNotEnoughReplicas",+ "Kafka.Internal.RdKafka.RdKafkaRespErrNotEnoughReplicasAfterAppend",+ "Kafka.Internal.RdKafka.RdKafkaRespErrNotImplemented",+ "Kafka.Internal.RdKafka.RdKafkaRespErrNotLeaderForPartition",+ "Kafka.Internal.RdKafka.RdKafkaRespErrOffsetMetadataTooLarge",+ "Kafka.Internal.RdKafka.RdKafkaRespErrOffsetNotAvailable",+ "Kafka.Internal.RdKafka.RdKafkaRespErrOffsetOutOfRange",+ "Kafka.Internal.RdKafka.RdKafkaRespErrOperationNotAttempted",+ "Kafka.Internal.RdKafka.RdKafkaRespErrOutOfOrderSequenceNumber",+ "Kafka.Internal.RdKafka.RdKafkaRespErrOutdated",+ "Kafka.Internal.RdKafka.RdKafkaRespErrPartial",+ "Kafka.Internal.RdKafka.RdKafkaRespErrPartitionEof",+ "Kafka.Internal.RdKafka.RdKafkaRespErrPolicyViolation",+ "Kafka.Internal.RdKafka.RdKafkaRespErrPreferredLeaderNotAvailable",+ "Kafka.Internal.RdKafka.RdKafkaRespErrPrevInProgress",+ "Kafka.Internal.RdKafka.RdKafkaRespErrPrincipalDeserializationFailure",+ "Kafka.Internal.RdKafka.RdKafkaRespErrProducerFenced",+ "Kafka.Internal.RdKafka.RdKafkaRespErrPurgeInflight",+ "Kafka.Internal.RdKafka.RdKafkaRespErrPurgeQueue",+ "Kafka.Internal.RdKafka.RdKafkaRespErrQueueFull",+ "Kafka.Internal.RdKafka.RdKafkaRespErrReadOnly",+ "Kafka.Internal.RdKafka.RdKafkaRespErrReassignmentInProgress",+ "Kafka.Internal.RdKafka.RdKafkaRespErrRebalanceInProgress",+ "Kafka.Internal.RdKafka.RdKafkaRespErrRebootstrapRequired",+ "Kafka.Internal.RdKafka.RdKafkaRespErrRecordListTooLarge",+ "Kafka.Internal.RdKafka.RdKafkaRespErrReplicaNotAvailable",+ "Kafka.Internal.RdKafka.RdKafkaRespErrRequestTimedOut",+ "Kafka.Internal.RdKafka.RdKafkaRespErrResolve",+ "Kafka.Internal.RdKafka.RdKafkaRespErrResourceNotFound",+ "Kafka.Internal.RdKafka.RdKafkaRespErrRetry",+ "Kafka.Internal.RdKafka.RdKafkaRespErrRevokePartitions",+ "Kafka.Internal.RdKafka.RdKafkaRespErrSaslAuthenticationFailed",+ "Kafka.Internal.RdKafka.RdKafkaRespErrSecurityDisabled",+ "Kafka.Internal.RdKafka.RdKafkaRespErrShareSessionLimitReached",+ "Kafka.Internal.RdKafka.RdKafkaRespErrShareSessionNotFound",+ "Kafka.Internal.RdKafka.RdKafkaRespErrSsl",+ "Kafka.Internal.RdKafka.RdKafkaRespErrStaleBrokerEpoch",+ "Kafka.Internal.RdKafka.RdKafkaRespErrStaleCtrlEpoch",+ "Kafka.Internal.RdKafka.RdKafkaRespErrStaleMemberEpoch",+ "Kafka.Internal.RdKafka.RdKafkaRespErrState",+ "Kafka.Internal.RdKafka.RdKafkaRespErrStreamsInvalidTopology",+ "Kafka.Internal.RdKafka.RdKafkaRespErrStreamsInvalidTopologyEpoch",+ "Kafka.Internal.RdKafka.RdKafkaRespErrStreamsTopologyFenced",+ "Kafka.Internal.RdKafka.RdKafkaRespErrTelemetryTooLarge",+ "Kafka.Internal.RdKafka.RdKafkaRespErrThrottlingQuotaExceeded",+ "Kafka.Internal.RdKafka.RdKafkaRespErrTimedOut",+ "Kafka.Internal.RdKafka.RdKafkaRespErrTimedOutQueue",+ "Kafka.Internal.RdKafka.RdKafkaRespErrTopicAlreadyExists",+ "Kafka.Internal.RdKafka.RdKafkaRespErrTopicAuthorizationFailed",+ "Kafka.Internal.RdKafka.RdKafkaRespErrTopicDeletionDisabled",+ "Kafka.Internal.RdKafka.RdKafkaRespErrTopicException",+ "Kafka.Internal.RdKafka.RdKafkaRespErrTransactionAbortable",+ "Kafka.Internal.RdKafka.RdKafkaRespErrTransactionCoordinatorFenced",+ "Kafka.Internal.RdKafka.RdKafkaRespErrTransactionalIdAuthorizationFailed",+ "Kafka.Internal.RdKafka.RdKafkaRespErrTransport",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnacceptableCredential",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnderflow",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnknown",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnknownBroker",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnknownControllerId",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnknownGroup",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnknownLeaderEpoch",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnknownMemberId",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnknownPartition",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnknownProducerId",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnknownProtocol",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnknownSubscriptionId",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnknownTopic",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnknownTopicId",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnknownTopicOrPart",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnreleasedInstanceId",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnstableOffsetCommit",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnsupportedAssignor",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnsupportedCompressionType",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnsupportedEndpointType",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnsupportedFeature",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnsupportedForMessageFormat",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnsupportedSaslMechanism",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnsupportedVersion",+ "Kafka.Internal.RdKafka.RdKafkaRespErrValueDeserialization",+ "Kafka.Internal.RdKafka.RdKafkaRespErrValueSerialization",+ "Kafka.Internal.RdKafka.RdKafkaRespErrVoterNotFound",+ "Kafka.Internal.RdKafka.RdKafkaRespErrWaitCache",+ "Kafka.Internal.RdKafka.RdKafkaRespErrWaitCoord"+ ]+ },+ {+ "symbol": "Kafka.Internal.Setup.Callback",+ "members": []+ },+ {+ "symbol": "Kafka.Types.BatchSize",+ "members": [+ "Kafka.Types.BatchSize",+ "Kafka.Types.unBatchSize"+ ]+ },+ {+ "symbol": "Kafka.Types.BrokerAddress",+ "members": [+ "Kafka.Types.BrokerAddress",+ "Kafka.Types.unBrokerAddress"+ ]+ },+ {+ "symbol": "Kafka.Types.BrokerId",+ "members": [+ "Kafka.Types.BrokerId",+ "Kafka.Types.unBrokerId"+ ]+ },+ {+ "symbol": "Kafka.Types.ClientId",+ "members": [+ "Kafka.Types.ClientId",+ "Kafka.Types.unClientId"+ ]+ },+ {+ "symbol": "Kafka.Types.Headers",+ "members": []+ },+ {+ "symbol": "Kafka.Types.KafkaCompressionCodec",+ "members": [+ "Kafka.Types.Gzip",+ "Kafka.Types.Lz4",+ "Kafka.Types.NoCompression",+ "Kafka.Types.Snappy",+ "Kafka.Types.Zstd"+ ]+ },+ {+ "symbol": "Kafka.Types.KafkaDebug",+ "members": [+ "Kafka.Types.DebugAll",+ "Kafka.Types.DebugBroker",+ "Kafka.Types.DebugCgrp",+ "Kafka.Types.DebugFeature",+ "Kafka.Types.DebugFetch",+ "Kafka.Types.DebugGeneric",+ "Kafka.Types.DebugMetadata",+ "Kafka.Types.DebugMsg",+ "Kafka.Types.DebugProtocol",+ "Kafka.Types.DebugQueue",+ "Kafka.Types.DebugSecurity",+ "Kafka.Types.DebugTopic"+ ]+ },+ {+ "symbol": "Kafka.Types.KafkaError",+ "members": [+ "Kafka.Types.KafkaBadConfiguration",+ "Kafka.Types.KafkaBadSpecification",+ "Kafka.Types.KafkaError",+ "Kafka.Types.KafkaInvalidConfigurationValue",+ "Kafka.Types.KafkaInvalidReturnValue",+ "Kafka.Types.KafkaResponseError",+ "Kafka.Types.KafkaUnknownConfigurationKey"+ ]+ },+ {+ "symbol": "Kafka.Types.KafkaLogLevel",+ "members": [+ "Kafka.Types.KafkaLogAlert",+ "Kafka.Types.KafkaLogCrit",+ "Kafka.Types.KafkaLogDebug",+ "Kafka.Types.KafkaLogEmerg",+ "Kafka.Types.KafkaLogErr",+ "Kafka.Types.KafkaLogInfo",+ "Kafka.Types.KafkaLogNotice",+ "Kafka.Types.KafkaLogWarning"+ ]+ },+ {+ "symbol": "Kafka.Types.Millis",+ "members": [+ "Kafka.Types.Millis",+ "Kafka.Types.unMillis"+ ]+ },+ {+ "symbol": "Kafka.Types.PartitionId",+ "members": [+ "Kafka.Types.PartitionId",+ "Kafka.Types.unPartitionId"+ ]+ },+ {+ "symbol": "Kafka.Types.Timeout",+ "members": [+ "Kafka.Types.Timeout",+ "Kafka.Types.unTimeout"+ ]+ },+ {+ "symbol": "Kafka.Types.TopicName",+ "members": [+ "Kafka.Types.TopicName",+ "Kafka.Types.unTopicName"+ ]+ },+ {+ "symbol": "Kafka.Types.TopicType",+ "members": [+ "Kafka.Types.System",+ "Kafka.Types.User"+ ]+ },+ {+ "symbol": "Kafka.Types.headersFromList",+ "members": []+ },+ {+ "symbol": "Kafka.Types.headersToList",+ "members": []+ },+ {+ "symbol": "Kafka.Types.kafkaCompressionCodecToText",+ "members": []+ },+ {+ "symbol": "Kafka.Types.kafkaDebugToText",+ "members": []+ },+ {+ "symbol": "Kafka.Types.topicType",+ "members": []+ }+ ],+ "Kafka.Consumer.ConsumerProperties": [+ {+ "symbol": "Kafka.Callbacks.errorCallback",+ "members": []+ },+ {+ "symbol": "Kafka.Callbacks.logCallback",+ "members": []+ },+ {+ "symbol": "Kafka.Callbacks.statsCallback",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.Callbacks.offsetCommitCallback",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.Callbacks.rebalanceCallback",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.ConsumerProperties.CallbackPollMode",+ "members": [+ "Kafka.Consumer.ConsumerProperties.CallbackPollModeAsync",+ "Kafka.Consumer.ConsumerProperties.CallbackPollModeSync"+ ]+ },+ {+ "symbol": "Kafka.Consumer.ConsumerProperties.ConsumerProperties",+ "members": [+ "Kafka.Consumer.ConsumerProperties.ConsumerProperties",+ "Kafka.Consumer.ConsumerProperties.cpCallbackPollMode",+ "Kafka.Consumer.ConsumerProperties.cpCallbacks",+ "Kafka.Consumer.ConsumerProperties.cpLogLevel",+ "Kafka.Consumer.ConsumerProperties.cpProps"+ ]+ },+ {+ "symbol": "Kafka.Consumer.ConsumerProperties.autoCommit",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.ConsumerProperties.brokersList",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.ConsumerProperties.callbackPollMode",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.ConsumerProperties.clientId",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.ConsumerProperties.compression",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.ConsumerProperties.debugOptions",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.ConsumerProperties.effectiveCallbackPollMode",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.ConsumerProperties.extraProp",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.ConsumerProperties.extraProps",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.ConsumerProperties.groupId",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.ConsumerProperties.logLevel",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.ConsumerProperties.noAutoCommit",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.ConsumerProperties.noAutoOffsetStore",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.ConsumerProperties.queuedMaxMessagesKBytes",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.ConsumerProperties.setCallback",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.ConsumerProperties.statisticsInterval",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.ConsumerProperties.suppressDisconnectLogs",+ "members": []+ },+ {+ "symbol": "Kafka.Internal.Setup.Callback",+ "members": []+ }+ ],+ "Kafka.Consumer.Subscription": [+ {+ "symbol": "Kafka.Consumer.Subscription.Subscription",+ "members": [+ "Kafka.Consumer.Subscription.Subscription"+ ]+ },+ {+ "symbol": "Kafka.Consumer.Subscription.extraSubscriptionProps",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.Subscription.offsetReset",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.Subscription.topics",+ "members": []+ }+ ],+ "Kafka.Consumer.Types": [+ {+ "symbol": "Kafka.Consumer.Types.ConsumerGroupId",+ "members": [+ "Kafka.Consumer.Types.ConsumerGroupId",+ "Kafka.Consumer.Types.unConsumerGroupId"+ ]+ },+ {+ "symbol": "Kafka.Consumer.Types.ConsumerMessageError",+ "members": [+ "Kafka.Consumer.Types.ConsumerMessageError",+ "Kafka.Consumer.Types.cmeError",+ "Kafka.Consumer.Types.cmeOffset",+ "Kafka.Consumer.Types.cmePartition",+ "Kafka.Consumer.Types.cmeTopic"+ ]+ },+ {+ "symbol": "Kafka.Consumer.Types.ConsumerRecord",+ "members": [+ "Kafka.Consumer.Types.ConsumerRecord",+ "Kafka.Consumer.Types.crHeaders",+ "Kafka.Consumer.Types.crKey",+ "Kafka.Consumer.Types.crOffset",+ "Kafka.Consumer.Types.crPartition",+ "Kafka.Consumer.Types.crTimestamp",+ "Kafka.Consumer.Types.crTopic",+ "Kafka.Consumer.Types.crValue"+ ]+ },+ {+ "symbol": "Kafka.Consumer.Types.KafkaConsumer",+ "members": [+ "Kafka.Consumer.Types.KafkaConsumer",+ "Kafka.Consumer.Types.kcKafkaConf",+ "Kafka.Consumer.Types.kcKafkaPtr"+ ]+ },+ {+ "symbol": "Kafka.Consumer.Types.Offset",+ "members": [+ "Kafka.Consumer.Types.Offset",+ "Kafka.Consumer.Types.unOffset"+ ]+ },+ {+ "symbol": "Kafka.Consumer.Types.OffsetCommit",+ "members": [+ "Kafka.Consumer.Types.OffsetCommit",+ "Kafka.Consumer.Types.OffsetCommitAsync"+ ]+ },+ {+ "symbol": "Kafka.Consumer.Types.OffsetReset",+ "members": [+ "Kafka.Consumer.Types.Earliest",+ "Kafka.Consumer.Types.Latest"+ ]+ },+ {+ "symbol": "Kafka.Consumer.Types.OffsetStoreMethod",+ "members": [+ "Kafka.Consumer.Types.OffsetStoreBroker",+ "Kafka.Consumer.Types.OffsetStoreFile"+ ]+ },+ {+ "symbol": "Kafka.Consumer.Types.OffsetStoreSync",+ "members": [+ "Kafka.Consumer.Types.OffsetSyncDisable",+ "Kafka.Consumer.Types.OffsetSyncImmediate",+ "Kafka.Consumer.Types.OffsetSyncInterval"+ ]+ },+ {+ "symbol": "Kafka.Consumer.Types.PartitionOffset",+ "members": [+ "Kafka.Consumer.Types.PartitionOffset",+ "Kafka.Consumer.Types.PartitionOffsetBeginning",+ "Kafka.Consumer.Types.PartitionOffsetEnd",+ "Kafka.Consumer.Types.PartitionOffsetInvalid",+ "Kafka.Consumer.Types.PartitionOffsetStored"+ ]+ },+ {+ "symbol": "Kafka.Consumer.Types.RebalanceEvent",+ "members": [+ "Kafka.Consumer.Types.RebalanceAssign",+ "Kafka.Consumer.Types.RebalanceBeforeAssign",+ "Kafka.Consumer.Types.RebalanceBeforeRevoke",+ "Kafka.Consumer.Types.RebalanceRevoke"+ ]+ },+ {+ "symbol": "Kafka.Consumer.Types.SubscribedPartitions",+ "members": [+ "Kafka.Consumer.Types.SubscribedPartitions",+ "Kafka.Consumer.Types.SubscribedPartitionsAll"+ ]+ },+ {+ "symbol": "Kafka.Consumer.Types.Timestamp",+ "members": [+ "Kafka.Consumer.Types.CreateTime",+ "Kafka.Consumer.Types.LogAppendTime",+ "Kafka.Consumer.Types.NoTimestamp"+ ]+ },+ {+ "symbol": "Kafka.Consumer.Types.TopicPartition",+ "members": [+ "Kafka.Consumer.Types.TopicPartition",+ "Kafka.Consumer.Types.tpOffset",+ "Kafka.Consumer.Types.tpPartition",+ "Kafka.Consumer.Types.tpTopicName"+ ]+ },+ {+ "symbol": "Kafka.Consumer.Types.bitraverseM",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.Types.crMapKV",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.Types.crMapKey",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.Types.crMapValue",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.Types.sequenceFirst",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.Types.traverseFirst",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.Types.traverseFirstM",+ "members": []+ },+ {+ "symbol": "Kafka.Consumer.Types.traverseM",+ "members": []+ }+ ],+ "Kafka.Dump": [+ {+ "symbol": "Kafka.Dump.dumpKafkaConf",+ "members": []+ },+ {+ "symbol": "Kafka.Dump.dumpTopicConf",+ "members": []+ },+ {+ "symbol": "Kafka.Dump.hPrintKafka",+ "members": []+ },+ {+ "symbol": "Kafka.Dump.hPrintSupportedKafkaConf",+ "members": []+ }+ ],+ "Kafka.Metadata": [+ {+ "symbol": "Kafka.Metadata.BrokerMetadata",+ "members": [+ "Kafka.Metadata.BrokerMetadata",+ "Kafka.Metadata.bmBrokerHost",+ "Kafka.Metadata.bmBrokerId",+ "Kafka.Metadata.bmBrokerPort"+ ]+ },+ {+ "symbol": "Kafka.Metadata.GroupInfo",+ "members": [+ "Kafka.Metadata.GroupInfo",+ "Kafka.Metadata.giError",+ "Kafka.Metadata.giGroup",+ "Kafka.Metadata.giMembers",+ "Kafka.Metadata.giProtocol",+ "Kafka.Metadata.giProtocolType",+ "Kafka.Metadata.giState"+ ]+ },+ {+ "symbol": "Kafka.Metadata.GroupMemberId",+ "members": [+ "Kafka.Metadata.GroupMemberId"+ ]+ },+ {+ "symbol": "Kafka.Metadata.GroupMemberInfo",+ "members": [+ "Kafka.Metadata.GroupMemberInfo",+ "Kafka.Metadata.gmiAssignment",+ "Kafka.Metadata.gmiClientHost",+ "Kafka.Metadata.gmiClientId",+ "Kafka.Metadata.gmiMemberId",+ "Kafka.Metadata.gmiMetadata"+ ]+ },+ {+ "symbol": "Kafka.Metadata.GroupProtocol",+ "members": [+ "Kafka.Metadata.GroupProtocol"+ ]+ },+ {+ "symbol": "Kafka.Metadata.GroupProtocolType",+ "members": [+ "Kafka.Metadata.GroupProtocolType"+ ]+ },+ {+ "symbol": "Kafka.Metadata.GroupState",+ "members": [+ "Kafka.Metadata.GroupAwaitingSync",+ "Kafka.Metadata.GroupDead",+ "Kafka.Metadata.GroupEmpty",+ "Kafka.Metadata.GroupPreparingRebalance",+ "Kafka.Metadata.GroupStable"+ ]+ },+ {+ "symbol": "Kafka.Metadata.KafkaMetadata",+ "members": [+ "Kafka.Metadata.KafkaMetadata",+ "Kafka.Metadata.kmBrokers",+ "Kafka.Metadata.kmOrigBroker",+ "Kafka.Metadata.kmTopics"+ ]+ },+ {+ "symbol": "Kafka.Metadata.PartitionMetadata",+ "members": [+ "Kafka.Metadata.PartitionMetadata",+ "Kafka.Metadata.pmError",+ "Kafka.Metadata.pmInSyncReplicas",+ "Kafka.Metadata.pmLeader",+ "Kafka.Metadata.pmPartitionId",+ "Kafka.Metadata.pmReplicas"+ ]+ },+ {+ "symbol": "Kafka.Metadata.TopicMetadata",+ "members": [+ "Kafka.Metadata.TopicMetadata",+ "Kafka.Metadata.tmError",+ "Kafka.Metadata.tmPartitions",+ "Kafka.Metadata.tmTopicName"+ ]+ },+ {+ "symbol": "Kafka.Metadata.WatermarkOffsets",+ "members": [+ "Kafka.Metadata.WatermarkOffsets",+ "Kafka.Metadata.woHighWatermark",+ "Kafka.Metadata.woLowWatermark",+ "Kafka.Metadata.woPartitionId",+ "Kafka.Metadata.woTopicName"+ ]+ },+ {+ "symbol": "Kafka.Metadata.allConsumerGroupsInfo",+ "members": []+ },+ {+ "symbol": "Kafka.Metadata.allTopicsMetadata",+ "members": []+ },+ {+ "symbol": "Kafka.Metadata.consumerGroupInfo",+ "members": []+ },+ {+ "symbol": "Kafka.Metadata.offsetsForTime",+ "members": []+ },+ {+ "symbol": "Kafka.Metadata.offsetsForTime'",+ "members": []+ },+ {+ "symbol": "Kafka.Metadata.partitionWatermarkOffsets",+ "members": []+ },+ {+ "symbol": "Kafka.Metadata.topicMetadata",+ "members": []+ },+ {+ "symbol": "Kafka.Metadata.topicOffsetsForTime",+ "members": []+ },+ {+ "symbol": "Kafka.Metadata.watermarkOffsets",+ "members": []+ },+ {+ "symbol": "Kafka.Metadata.watermarkOffsets'",+ "members": []+ }+ ],+ "Kafka.Producer": [+ {+ "symbol": "Kafka.Callbacks.errorCallback",+ "members": []+ },+ {+ "symbol": "Kafka.Callbacks.logCallback",+ "members": []+ },+ {+ "symbol": "Kafka.Callbacks.statsCallback",+ "members": []+ },+ {+ "symbol": "Kafka.Internal.RdKafka.RdKafkaRespErrT",+ "members": [+ "Kafka.Internal.RdKafka.RdKafkaRespErrAllBrokersDown",+ "Kafka.Internal.RdKafka.RdKafkaRespErrApplication",+ "Kafka.Internal.RdKafka.RdKafkaRespErrAssignPartitions",+ "Kafka.Internal.RdKafka.RdKafkaRespErrAssignmentLost",+ "Kafka.Internal.RdKafka.RdKafkaRespErrAuthentication",+ "Kafka.Internal.RdKafka.RdKafkaRespErrAutoOffsetReset",+ "Kafka.Internal.RdKafka.RdKafkaRespErrBadCompression",+ "Kafka.Internal.RdKafka.RdKafkaRespErrBadMsg",+ "Kafka.Internal.RdKafka.RdKafkaRespErrBegin",+ "Kafka.Internal.RdKafka.RdKafkaRespErrBrokerNotAvailable",+ "Kafka.Internal.RdKafka.RdKafkaRespErrClusterAuthorizationFailed",+ "Kafka.Internal.RdKafka.RdKafkaRespErrConcurrentTransactions",+ "Kafka.Internal.RdKafka.RdKafkaRespErrConflict",+ "Kafka.Internal.RdKafka.RdKafkaRespErrCoordinatorLoadInProgress",+ "Kafka.Internal.RdKafka.RdKafkaRespErrCoordinatorNotAvailable",+ "Kafka.Internal.RdKafka.RdKafkaRespErrCritSysResource",+ "Kafka.Internal.RdKafka.RdKafkaRespErrDelegationTokenAuthDisabled",+ "Kafka.Internal.RdKafka.RdKafkaRespErrDelegationTokenAuthorizationFailed",+ "Kafka.Internal.RdKafka.RdKafkaRespErrDelegationTokenExpired",+ "Kafka.Internal.RdKafka.RdKafkaRespErrDelegationTokenNotFound",+ "Kafka.Internal.RdKafka.RdKafkaRespErrDelegationTokenOwnerMismatch",+ "Kafka.Internal.RdKafka.RdKafkaRespErrDelegationTokenRequestNotAllowed",+ "Kafka.Internal.RdKafka.RdKafkaRespErrDestroy",+ "Kafka.Internal.RdKafka.RdKafkaRespErrDestroyBroker",+ "Kafka.Internal.RdKafka.RdKafkaRespErrDuplicateResource",+ "Kafka.Internal.RdKafka.RdKafkaRespErrDuplicateSequenceNumber",+ "Kafka.Internal.RdKafka.RdKafkaRespErrDuplicateVoter",+ "Kafka.Internal.RdKafka.RdKafkaRespErrElectionNotNeeded",+ "Kafka.Internal.RdKafka.RdKafkaRespErrEligibleLeadersNotAvailable",+ "Kafka.Internal.RdKafka.RdKafkaRespErrEnd",+ "Kafka.Internal.RdKafka.RdKafkaRespErrEndAll",+ "Kafka.Internal.RdKafka.RdKafkaRespErrExistingSubscription",+ "Kafka.Internal.RdKafka.RdKafkaRespErrFail",+ "Kafka.Internal.RdKafka.RdKafkaRespErrFatal",+ "Kafka.Internal.RdKafka.RdKafkaRespErrFeatureUpdateFailed",+ "Kafka.Internal.RdKafka.RdKafkaRespErrFenced",+ "Kafka.Internal.RdKafka.RdKafkaRespErrFencedInstanceId",+ "Kafka.Internal.RdKafka.RdKafkaRespErrFencedLeaderEpoch",+ "Kafka.Internal.RdKafka.RdKafkaRespErrFencedMemberEpoch",+ "Kafka.Internal.RdKafka.RdKafkaRespErrFencedStateEpoch",+ "Kafka.Internal.RdKafka.RdKafkaRespErrFetchSessionIdNotFound",+ "Kafka.Internal.RdKafka.RdKafkaRespErrFs",+ "Kafka.Internal.RdKafka.RdKafkaRespErrGaplessGuarantee",+ "Kafka.Internal.RdKafka.RdKafkaRespErrGroupAuthorizationFailed",+ "Kafka.Internal.RdKafka.RdKafkaRespErrGroupIdNotFound",+ "Kafka.Internal.RdKafka.RdKafkaRespErrGroupMaxSizeReached",+ "Kafka.Internal.RdKafka.RdKafkaRespErrGroupSubscribedToTopic",+ "Kafka.Internal.RdKafka.RdKafkaRespErrIllegalGeneration",+ "Kafka.Internal.RdKafka.RdKafkaRespErrIllegalSaslState",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInProgress",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInconsistent",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInconsistentGroupProtocol",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInconsistentTopicId",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInconsistentVoterSet",+ "Kafka.Internal.RdKafka.RdKafkaRespErrIntr",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidArg",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidCommitOffsetSize",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidConfig",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidDifferentRecord",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidFetchSessionEpoch",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidGroupId",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidMsg",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidMsgSize",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidPartitions",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidPrincipalType",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidProducerEpoch",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidProducerIdMapping",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidRecord",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidRecordState",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidRegistration",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidRegularExpression",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidReplicaAssignment",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidReplicationFactor",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidRequest",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidRequiredAcks",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidSessionTimeout",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidShareSessionEpoch",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidTimestamp",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidTransactionTimeout",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidTxnState",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidType",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidUpdateVersion",+ "Kafka.Internal.RdKafka.RdKafkaRespErrInvalidVoterKey",+ "Kafka.Internal.RdKafka.RdKafkaRespErrIsrInsuff",+ "Kafka.Internal.RdKafka.RdKafkaRespErrKafkaStorageError",+ "Kafka.Internal.RdKafka.RdKafkaRespErrKeyDeserialization",+ "Kafka.Internal.RdKafka.RdKafkaRespErrKeySerialization",+ "Kafka.Internal.RdKafka.RdKafkaRespErrLeaderNotAvailable",+ "Kafka.Internal.RdKafka.RdKafkaRespErrListenerNotFound",+ "Kafka.Internal.RdKafka.RdKafkaRespErrLogDirNotFound",+ "Kafka.Internal.RdKafka.RdKafkaRespErrLogTruncation",+ "Kafka.Internal.RdKafka.RdKafkaRespErrMaxPollExceeded",+ "Kafka.Internal.RdKafka.RdKafkaRespErrMemberIdRequired",+ "Kafka.Internal.RdKafka.RdKafkaRespErrMismatchedEndpointType",+ "Kafka.Internal.RdKafka.RdKafkaRespErrMsgSizeTooLarge",+ "Kafka.Internal.RdKafka.RdKafkaRespErrMsgTimedOut",+ "Kafka.Internal.RdKafka.RdKafkaRespErrNetworkException",+ "Kafka.Internal.RdKafka.RdKafkaRespErrNoError",+ "Kafka.Internal.RdKafka.RdKafkaRespErrNoOffset",+ "Kafka.Internal.RdKafka.RdKafkaRespErrNoReassignmentInProgress",+ "Kafka.Internal.RdKafka.RdKafkaRespErrNodeUpdate",+ "Kafka.Internal.RdKafka.RdKafkaRespErrNoent",+ "Kafka.Internal.RdKafka.RdKafkaRespErrNonEmptyGroup",+ "Kafka.Internal.RdKafka.RdKafkaRespErrNoop",+ "Kafka.Internal.RdKafka.RdKafkaRespErrNotConfigured",+ "Kafka.Internal.RdKafka.RdKafkaRespErrNotController",+ "Kafka.Internal.RdKafka.RdKafkaRespErrNotCoordinator",+ "Kafka.Internal.RdKafka.RdKafkaRespErrNotEnoughReplicas",+ "Kafka.Internal.RdKafka.RdKafkaRespErrNotEnoughReplicasAfterAppend",+ "Kafka.Internal.RdKafka.RdKafkaRespErrNotImplemented",+ "Kafka.Internal.RdKafka.RdKafkaRespErrNotLeaderForPartition",+ "Kafka.Internal.RdKafka.RdKafkaRespErrOffsetMetadataTooLarge",+ "Kafka.Internal.RdKafka.RdKafkaRespErrOffsetNotAvailable",+ "Kafka.Internal.RdKafka.RdKafkaRespErrOffsetOutOfRange",+ "Kafka.Internal.RdKafka.RdKafkaRespErrOperationNotAttempted",+ "Kafka.Internal.RdKafka.RdKafkaRespErrOutOfOrderSequenceNumber",+ "Kafka.Internal.RdKafka.RdKafkaRespErrOutdated",+ "Kafka.Internal.RdKafka.RdKafkaRespErrPartial",+ "Kafka.Internal.RdKafka.RdKafkaRespErrPartitionEof",+ "Kafka.Internal.RdKafka.RdKafkaRespErrPolicyViolation",+ "Kafka.Internal.RdKafka.RdKafkaRespErrPreferredLeaderNotAvailable",+ "Kafka.Internal.RdKafka.RdKafkaRespErrPrevInProgress",+ "Kafka.Internal.RdKafka.RdKafkaRespErrPrincipalDeserializationFailure",+ "Kafka.Internal.RdKafka.RdKafkaRespErrProducerFenced",+ "Kafka.Internal.RdKafka.RdKafkaRespErrPurgeInflight",+ "Kafka.Internal.RdKafka.RdKafkaRespErrPurgeQueue",+ "Kafka.Internal.RdKafka.RdKafkaRespErrQueueFull",+ "Kafka.Internal.RdKafka.RdKafkaRespErrReadOnly",+ "Kafka.Internal.RdKafka.RdKafkaRespErrReassignmentInProgress",+ "Kafka.Internal.RdKafka.RdKafkaRespErrRebalanceInProgress",+ "Kafka.Internal.RdKafka.RdKafkaRespErrRebootstrapRequired",+ "Kafka.Internal.RdKafka.RdKafkaRespErrRecordListTooLarge",+ "Kafka.Internal.RdKafka.RdKafkaRespErrReplicaNotAvailable",+ "Kafka.Internal.RdKafka.RdKafkaRespErrRequestTimedOut",+ "Kafka.Internal.RdKafka.RdKafkaRespErrResolve",+ "Kafka.Internal.RdKafka.RdKafkaRespErrResourceNotFound",+ "Kafka.Internal.RdKafka.RdKafkaRespErrRetry",+ "Kafka.Internal.RdKafka.RdKafkaRespErrRevokePartitions",+ "Kafka.Internal.RdKafka.RdKafkaRespErrSaslAuthenticationFailed",+ "Kafka.Internal.RdKafka.RdKafkaRespErrSecurityDisabled",+ "Kafka.Internal.RdKafka.RdKafkaRespErrShareSessionLimitReached",+ "Kafka.Internal.RdKafka.RdKafkaRespErrShareSessionNotFound",+ "Kafka.Internal.RdKafka.RdKafkaRespErrSsl",+ "Kafka.Internal.RdKafka.RdKafkaRespErrStaleBrokerEpoch",+ "Kafka.Internal.RdKafka.RdKafkaRespErrStaleCtrlEpoch",+ "Kafka.Internal.RdKafka.RdKafkaRespErrStaleMemberEpoch",+ "Kafka.Internal.RdKafka.RdKafkaRespErrState",+ "Kafka.Internal.RdKafka.RdKafkaRespErrStreamsInvalidTopology",+ "Kafka.Internal.RdKafka.RdKafkaRespErrStreamsInvalidTopologyEpoch",+ "Kafka.Internal.RdKafka.RdKafkaRespErrStreamsTopologyFenced",+ "Kafka.Internal.RdKafka.RdKafkaRespErrTelemetryTooLarge",+ "Kafka.Internal.RdKafka.RdKafkaRespErrThrottlingQuotaExceeded",+ "Kafka.Internal.RdKafka.RdKafkaRespErrTimedOut",+ "Kafka.Internal.RdKafka.RdKafkaRespErrTimedOutQueue",+ "Kafka.Internal.RdKafka.RdKafkaRespErrTopicAlreadyExists",+ "Kafka.Internal.RdKafka.RdKafkaRespErrTopicAuthorizationFailed",+ "Kafka.Internal.RdKafka.RdKafkaRespErrTopicDeletionDisabled",+ "Kafka.Internal.RdKafka.RdKafkaRespErrTopicException",+ "Kafka.Internal.RdKafka.RdKafkaRespErrTransactionAbortable",+ "Kafka.Internal.RdKafka.RdKafkaRespErrTransactionCoordinatorFenced",+ "Kafka.Internal.RdKafka.RdKafkaRespErrTransactionalIdAuthorizationFailed",+ "Kafka.Internal.RdKafka.RdKafkaRespErrTransport",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnacceptableCredential",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnderflow",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnknown",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnknownBroker",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnknownControllerId",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnknownGroup",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnknownLeaderEpoch",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnknownMemberId",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnknownPartition",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnknownProducerId",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnknownProtocol",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnknownSubscriptionId",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnknownTopic",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnknownTopicId",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnknownTopicOrPart",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnreleasedInstanceId",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnstableOffsetCommit",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnsupportedAssignor",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnsupportedCompressionType",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnsupportedEndpointType",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnsupportedFeature",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnsupportedForMessageFormat",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnsupportedSaslMechanism",+ "Kafka.Internal.RdKafka.RdKafkaRespErrUnsupportedVersion",+ "Kafka.Internal.RdKafka.RdKafkaRespErrValueDeserialization",+ "Kafka.Internal.RdKafka.RdKafkaRespErrValueSerialization",+ "Kafka.Internal.RdKafka.RdKafkaRespErrVoterNotFound",+ "Kafka.Internal.RdKafka.RdKafkaRespErrWaitCache",+ "Kafka.Internal.RdKafka.RdKafkaRespErrWaitCoord"+ ]+ },+ {+ "symbol": "Kafka.Internal.Setup.Callback",+ "members": []+ },+ {+ "symbol": "Kafka.Producer.Callbacks.deliveryCallback",+ "members": []+ },+ {+ "symbol": "Kafka.Producer.ProducerProperties.ProducerProperties",+ "members": [+ "Kafka.Producer.ProducerProperties.ProducerProperties",+ "Kafka.Producer.ProducerProperties.ppCallbacks",+ "Kafka.Producer.ProducerProperties.ppKafkaProps",+ "Kafka.Producer.ProducerProperties.ppLogLevel",+ "Kafka.Producer.ProducerProperties.ppTopicProps"+ ]+ },+ {+ "symbol": "Kafka.Producer.ProducerProperties.brokersList",+ "members": []+ },+ {+ "symbol": "Kafka.Producer.ProducerProperties.compression",+ "members": []+ },+ {+ "symbol": "Kafka.Producer.ProducerProperties.debugOptions",+ "members": []+ },+ {+ "symbol": "Kafka.Producer.ProducerProperties.extraProp",+ "members": []+ },+ {+ "symbol": "Kafka.Producer.ProducerProperties.extraProps",+ "members": []+ },+ {+ "symbol": "Kafka.Producer.ProducerProperties.extraTopicProps",+ "members": []+ },+ {+ "symbol": "Kafka.Producer.ProducerProperties.logLevel",+ "members": []+ },+ {+ "symbol": "Kafka.Producer.ProducerProperties.sendTimeout",+ "members": []+ },+ {+ "symbol": "Kafka.Producer.ProducerProperties.setCallback",+ "members": []+ },+ {+ "symbol": "Kafka.Producer.ProducerProperties.statisticsInterval",+ "members": []+ },+ {+ "symbol": "Kafka.Producer.ProducerProperties.suppressDisconnectLogs",+ "members": []+ },+ {+ "symbol": "Kafka.Producer.ProducerProperties.topicCompression",+ "members": []+ },+ {+ "symbol": "Kafka.Producer.Types.DeliveryReport",+ "members": [+ "Kafka.Producer.Types.DeliveryFailure",+ "Kafka.Producer.Types.DeliverySuccess",+ "Kafka.Producer.Types.NoMessageError"+ ]+ },+ {+ "symbol": "Kafka.Producer.Types.ImmediateError",+ "members": [+ "Kafka.Producer.Types.ImmediateError"+ ]+ },+ {+ "symbol": "Kafka.Producer.Types.KafkaProducer",+ "members": [+ "Kafka.Producer.Types.kpKafkaConf",+ "Kafka.Producer.Types.kpKafkaPtr",+ "Kafka.Producer.Types.kpTopicConf"+ ]+ },+ {+ "symbol": "Kafka.Producer.Types.ProducePartition",+ "members": [+ "Kafka.Producer.Types.SpecifiedPartition",+ "Kafka.Producer.Types.UnassignedPartition"+ ]+ },+ {+ "symbol": "Kafka.Producer.Types.ProducerRecord",+ "members": [+ "Kafka.Producer.Types.ProducerRecord",+ "Kafka.Producer.Types.prHeaders",+ "Kafka.Producer.Types.prKey",+ "Kafka.Producer.Types.prPartition",+ "Kafka.Producer.Types.prTopic",+ "Kafka.Producer.Types.prValue"+ ]+ },+ {+ "symbol": "Kafka.Producer.Types.PurgeFlag",+ "members": [+ "Kafka.Producer.Types.PurgeInFlight",+ "Kafka.Producer.Types.PurgeNonBlocking",+ "Kafka.Producer.Types.PurgeQueue"+ ]+ },+ {+ "symbol": "Kafka.Producer.closeProducer",+ "members": []+ },+ {+ "symbol": "Kafka.Producer.flushProducer",+ "members": []+ },+ {+ "symbol": "Kafka.Producer.flushProducerTimeout",+ "members": []+ },+ {+ "symbol": "Kafka.Producer.newProducer",+ "members": []+ },+ {+ "symbol": "Kafka.Producer.produceMessage",+ "members": []+ },+ {+ "symbol": "Kafka.Producer.produceMessage'",+ "members": []+ },+ {+ "symbol": "Kafka.Producer.purgeProducer",+ "members": []+ },+ {+ "symbol": "Kafka.Producer.runProducer",+ "members": []+ },+ {+ "symbol": "Kafka.Producer.setSaslCredentials",+ "members": []+ },+ {+ "symbol": "Kafka.Types.BatchSize",+ "members": [+ "Kafka.Types.BatchSize",+ "Kafka.Types.unBatchSize"+ ]+ },+ {+ "symbol": "Kafka.Types.BrokerAddress",+ "members": [+ "Kafka.Types.BrokerAddress",+ "Kafka.Types.unBrokerAddress"+ ]+ },+ {+ "symbol": "Kafka.Types.BrokerId",+ "members": [+ "Kafka.Types.BrokerId",+ "Kafka.Types.unBrokerId"+ ]+ },+ {+ "symbol": "Kafka.Types.ClientId",+ "members": [+ "Kafka.Types.ClientId",+ "Kafka.Types.unClientId"+ ]+ },+ {+ "symbol": "Kafka.Types.Headers",+ "members": []+ },+ {+ "symbol": "Kafka.Types.KafkaCompressionCodec",+ "members": [+ "Kafka.Types.Gzip",+ "Kafka.Types.Lz4",+ "Kafka.Types.NoCompression",+ "Kafka.Types.Snappy",+ "Kafka.Types.Zstd"+ ]+ },+ {+ "symbol": "Kafka.Types.KafkaDebug",+ "members": [+ "Kafka.Types.DebugAll",+ "Kafka.Types.DebugBroker",+ "Kafka.Types.DebugCgrp",+ "Kafka.Types.DebugFeature",+ "Kafka.Types.DebugFetch",+ "Kafka.Types.DebugGeneric",+ "Kafka.Types.DebugMetadata",+ "Kafka.Types.DebugMsg",+ "Kafka.Types.DebugProtocol",+ "Kafka.Types.DebugQueue",+ "Kafka.Types.DebugSecurity",+ "Kafka.Types.DebugTopic"+ ]+ },+ {+ "symbol": "Kafka.Types.KafkaError",+ "members": [+ "Kafka.Types.KafkaBadConfiguration",+ "Kafka.Types.KafkaBadSpecification",+ "Kafka.Types.KafkaError",+ "Kafka.Types.KafkaInvalidConfigurationValue",+ "Kafka.Types.KafkaInvalidReturnValue",+ "Kafka.Types.KafkaResponseError",+ "Kafka.Types.KafkaUnknownConfigurationKey"+ ]+ },+ {+ "symbol": "Kafka.Types.KafkaLogLevel",+ "members": [+ "Kafka.Types.KafkaLogAlert",+ "Kafka.Types.KafkaLogCrit",+ "Kafka.Types.KafkaLogDebug",+ "Kafka.Types.KafkaLogEmerg",+ "Kafka.Types.KafkaLogErr",+ "Kafka.Types.KafkaLogInfo",+ "Kafka.Types.KafkaLogNotice",+ "Kafka.Types.KafkaLogWarning"+ ]+ },+ {+ "symbol": "Kafka.Types.Millis",+ "members": [+ "Kafka.Types.Millis",+ "Kafka.Types.unMillis"+ ]+ },+ {+ "symbol": "Kafka.Types.PartitionId",+ "members": [+ "Kafka.Types.PartitionId",+ "Kafka.Types.unPartitionId"+ ]+ },+ {+ "symbol": "Kafka.Types.Timeout",+ "members": [+ "Kafka.Types.Timeout",+ "Kafka.Types.unTimeout"+ ]+ },+ {+ "symbol": "Kafka.Types.TopicName",+ "members": [+ "Kafka.Types.TopicName",+ "Kafka.Types.unTopicName"+ ]+ },+ {+ "symbol": "Kafka.Types.TopicType",+ "members": [+ "Kafka.Types.System",+ "Kafka.Types.User"+ ]+ },+ {+ "symbol": "Kafka.Types.headersFromList",+ "members": []+ },+ {+ "symbol": "Kafka.Types.headersToList",+ "members": []+ },+ {+ "symbol": "Kafka.Types.kafkaCompressionCodecToText",+ "members": []+ },+ {+ "symbol": "Kafka.Types.kafkaDebugToText",+ "members": []+ },+ {+ "symbol": "Kafka.Types.topicType",+ "members": []+ }+ ],+ "Kafka.Producer.ProducerProperties": [+ {+ "symbol": "Kafka.Callbacks.errorCallback",+ "members": []+ },+ {+ "symbol": "Kafka.Callbacks.logCallback",+ "members": []+ },+ {+ "symbol": "Kafka.Callbacks.statsCallback",+ "members": []+ },+ {+ "symbol": "Kafka.Internal.Setup.Callback",+ "members": []+ },+ {+ "symbol": "Kafka.Producer.Callbacks.deliveryCallback",+ "members": []+ },+ {+ "symbol": "Kafka.Producer.ProducerProperties.ProducerProperties",+ "members": [+ "Kafka.Producer.ProducerProperties.ProducerProperties",+ "Kafka.Producer.ProducerProperties.ppCallbacks",+ "Kafka.Producer.ProducerProperties.ppKafkaProps",+ "Kafka.Producer.ProducerProperties.ppLogLevel",+ "Kafka.Producer.ProducerProperties.ppTopicProps"+ ]+ },+ {+ "symbol": "Kafka.Producer.ProducerProperties.brokersList",+ "members": []+ },+ {+ "symbol": "Kafka.Producer.ProducerProperties.compression",+ "members": []+ },+ {+ "symbol": "Kafka.Producer.ProducerProperties.debugOptions",+ "members": []+ },+ {+ "symbol": "Kafka.Producer.ProducerProperties.extraProp",+ "members": []+ },+ {+ "symbol": "Kafka.Producer.ProducerProperties.extraProps",+ "members": []+ },+ {+ "symbol": "Kafka.Producer.ProducerProperties.extraTopicProps",+ "members": []+ },+ {+ "symbol": "Kafka.Producer.ProducerProperties.logLevel",+ "members": []+ },+ {+ "symbol": "Kafka.Producer.ProducerProperties.sendTimeout",+ "members": []+ },+ {+ "symbol": "Kafka.Producer.ProducerProperties.setCallback",+ "members": []+ },+ {+ "symbol": "Kafka.Producer.ProducerProperties.statisticsInterval",+ "members": []+ },+ {+ "symbol": "Kafka.Producer.ProducerProperties.suppressDisconnectLogs",+ "members": []+ },+ {+ "symbol": "Kafka.Producer.ProducerProperties.topicCompression",+ "members": []+ }+ ],+ "Kafka.Producer.Types": [+ {+ "symbol": "Kafka.Producer.Types.DeliveryReport",+ "members": [+ "Kafka.Producer.Types.DeliveryFailure",+ "Kafka.Producer.Types.DeliverySuccess",+ "Kafka.Producer.Types.NoMessageError"+ ]+ },+ {+ "symbol": "Kafka.Producer.Types.ImmediateError",+ "members": [+ "Kafka.Producer.Types.ImmediateError"+ ]+ },+ {+ "symbol": "Kafka.Producer.Types.KafkaProducer",+ "members": [+ "Kafka.Producer.Types.KafkaProducer",+ "Kafka.Producer.Types.kpKafkaConf",+ "Kafka.Producer.Types.kpKafkaPtr",+ "Kafka.Producer.Types.kpTopicConf"+ ]+ },+ {+ "symbol": "Kafka.Producer.Types.ProducePartition",+ "members": [+ "Kafka.Producer.Types.SpecifiedPartition",+ "Kafka.Producer.Types.UnassignedPartition"+ ]+ },+ {+ "symbol": "Kafka.Producer.Types.ProducerRecord",+ "members": [+ "Kafka.Producer.Types.ProducerRecord",+ "Kafka.Producer.Types.prHeaders",+ "Kafka.Producer.Types.prKey",+ "Kafka.Producer.Types.prPartition",+ "Kafka.Producer.Types.prTopic",+ "Kafka.Producer.Types.prValue"+ ]+ },+ {+ "symbol": "Kafka.Producer.Types.PurgeFlag",+ "members": [+ "Kafka.Producer.Types.PurgeInFlight",+ "Kafka.Producer.Types.PurgeNonBlocking",+ "Kafka.Producer.Types.PurgeQueue"+ ]+ }+ ],+ "Kafka.Topic": [+ {+ "symbol": "Kafka.Topic.Types.NewTopic",+ "members": [+ "Kafka.Topic.Types.NewTopic",+ "Kafka.Topic.Types.topicConfig",+ "Kafka.Topic.Types.topicName",+ "Kafka.Topic.Types.topicPartitionCount",+ "Kafka.Topic.Types.topicReplicationFactor"+ ]+ },+ {+ "symbol": "Kafka.Topic.Types.PartitionCount",+ "members": [+ "Kafka.Topic.Types.PartitionCount",+ "Kafka.Topic.Types.unPartitionCount"+ ]+ },+ {+ "symbol": "Kafka.Topic.Types.ReplicationFactor",+ "members": [+ "Kafka.Topic.Types.ReplicationFactor",+ "Kafka.Topic.Types.unReplicationFactor"+ ]+ },+ {+ "symbol": "Kafka.Topic.createTopic",+ "members": []+ },+ {+ "symbol": "Kafka.Topic.deleteTopic",+ "members": []+ },+ {+ "symbol": "Kafka.Types.BatchSize",+ "members": [+ "Kafka.Types.BatchSize",+ "Kafka.Types.unBatchSize"+ ]+ },+ {+ "symbol": "Kafka.Types.BrokerAddress",+ "members": [+ "Kafka.Types.BrokerAddress",+ "Kafka.Types.unBrokerAddress"+ ]+ },+ {+ "symbol": "Kafka.Types.BrokerId",+ "members": [+ "Kafka.Types.BrokerId",+ "Kafka.Types.unBrokerId"+ ]+ },+ {+ "symbol": "Kafka.Types.ClientId",+ "members": [+ "Kafka.Types.ClientId",+ "Kafka.Types.unClientId"+ ]+ },+ {+ "symbol": "Kafka.Types.Headers",+ "members": []+ },+ {+ "symbol": "Kafka.Types.KafkaCompressionCodec",+ "members": [+ "Kafka.Types.Gzip",+ "Kafka.Types.Lz4",+ "Kafka.Types.NoCompression",+ "Kafka.Types.Snappy",+ "Kafka.Types.Zstd"+ ]+ },+ {+ "symbol": "Kafka.Types.KafkaDebug",+ "members": [+ "Kafka.Types.DebugAll",+ "Kafka.Types.DebugBroker",+ "Kafka.Types.DebugCgrp",+ "Kafka.Types.DebugFeature",+ "Kafka.Types.DebugFetch",+ "Kafka.Types.DebugGeneric",+ "Kafka.Types.DebugMetadata",+ "Kafka.Types.DebugMsg",+ "Kafka.Types.DebugProtocol",+ "Kafka.Types.DebugQueue",+ "Kafka.Types.DebugSecurity",+ "Kafka.Types.DebugTopic"+ ]+ },+ {+ "symbol": "Kafka.Types.KafkaError",+ "members": [+ "Kafka.Types.KafkaBadConfiguration",+ "Kafka.Types.KafkaBadSpecification",+ "Kafka.Types.KafkaError",+ "Kafka.Types.KafkaInvalidConfigurationValue",+ "Kafka.Types.KafkaInvalidReturnValue",+ "Kafka.Types.KafkaResponseError",+ "Kafka.Types.KafkaUnknownConfigurationKey"+ ]+ },+ {+ "symbol": "Kafka.Types.KafkaLogLevel",+ "members": [+ "Kafka.Types.KafkaLogAlert",+ "Kafka.Types.KafkaLogCrit",+ "Kafka.Types.KafkaLogDebug",+ "Kafka.Types.KafkaLogEmerg",+ "Kafka.Types.KafkaLogErr",+ "Kafka.Types.KafkaLogInfo",+ "Kafka.Types.KafkaLogNotice",+ "Kafka.Types.KafkaLogWarning"+ ]+ },+ {+ "symbol": "Kafka.Types.Millis",+ "members": [+ "Kafka.Types.Millis",+ "Kafka.Types.unMillis"+ ]+ },+ {+ "symbol": "Kafka.Types.PartitionId",+ "members": [+ "Kafka.Types.PartitionId",+ "Kafka.Types.unPartitionId"+ ]+ },+ {+ "symbol": "Kafka.Types.Timeout",+ "members": [+ "Kafka.Types.Timeout",+ "Kafka.Types.unTimeout"+ ]+ },+ {+ "symbol": "Kafka.Types.TopicName",+ "members": [+ "Kafka.Types.TopicName",+ "Kafka.Types.unTopicName"+ ]+ },+ {+ "symbol": "Kafka.Types.TopicType",+ "members": [+ "Kafka.Types.System",+ "Kafka.Types.User"+ ]+ },+ {+ "symbol": "Kafka.Types.headersFromList",+ "members": []+ },+ {+ "symbol": "Kafka.Types.headersToList",+ "members": []+ },+ {+ "symbol": "Kafka.Types.kafkaCompressionCodecToText",+ "members": []+ },+ {+ "symbol": "Kafka.Types.kafkaDebugToText",+ "members": []+ },+ {+ "symbol": "Kafka.Types.topicType",+ "members": []+ }+ ],+ "Kafka.Topic.Types": [+ {+ "symbol": "Kafka.Topic.Types.NewTopic",+ "members": [+ "Kafka.Topic.Types.NewTopic",+ "Kafka.Topic.Types.topicConfig",+ "Kafka.Topic.Types.topicName",+ "Kafka.Topic.Types.topicPartitionCount",+ "Kafka.Topic.Types.topicReplicationFactor"+ ]+ },+ {+ "symbol": "Kafka.Topic.Types.PartitionCount",+ "members": [+ "Kafka.Topic.Types.PartitionCount",+ "Kafka.Topic.Types.unPartitionCount"+ ]+ },+ {+ "symbol": "Kafka.Topic.Types.ReplicationFactor",+ "members": [+ "Kafka.Topic.Types.ReplicationFactor",+ "Kafka.Topic.Types.unReplicationFactor"+ ]+ }+ ],+ "Kafka.Transaction": [+ {+ "symbol": "Kafka.Transaction.TxError",+ "members": []+ },+ {+ "symbol": "Kafka.Transaction.abortTransaction",+ "members": []+ },+ {+ "symbol": "Kafka.Transaction.beginTransaction",+ "members": []+ },+ {+ "symbol": "Kafka.Transaction.commitOffsetMessageTransaction",+ "members": []+ },+ {+ "symbol": "Kafka.Transaction.commitTransaction",+ "members": []+ },+ {+ "symbol": "Kafka.Transaction.getKafkaError",+ "members": []+ },+ {+ "symbol": "Kafka.Transaction.initTransactions",+ "members": []+ },+ {+ "symbol": "Kafka.Transaction.kafkaErrorIsFatal",+ "members": []+ },+ {+ "symbol": "Kafka.Transaction.kafkaErrorIsRetriable",+ "members": []+ },+ {+ "symbol": "Kafka.Transaction.kafkaErrorTxnRequiresAbort",+ "members": []+ }+ ],+ "Kafka.Types": [+ {+ "symbol": "Kafka.Types.BatchSize",+ "members": [+ "Kafka.Types.BatchSize",+ "Kafka.Types.unBatchSize"+ ]+ },+ {+ "symbol": "Kafka.Types.BrokerAddress",+ "members": [+ "Kafka.Types.BrokerAddress",+ "Kafka.Types.unBrokerAddress"+ ]+ },+ {+ "symbol": "Kafka.Types.BrokerId",+ "members": [+ "Kafka.Types.BrokerId",+ "Kafka.Types.unBrokerId"+ ]+ },+ {+ "symbol": "Kafka.Types.ClientId",+ "members": [+ "Kafka.Types.ClientId",+ "Kafka.Types.unClientId"+ ]+ },+ {+ "symbol": "Kafka.Types.Headers",+ "members": []+ },+ {+ "symbol": "Kafka.Types.KafkaCompressionCodec",+ "members": [+ "Kafka.Types.Gzip",+ "Kafka.Types.Lz4",+ "Kafka.Types.NoCompression",+ "Kafka.Types.Snappy",+ "Kafka.Types.Zstd"+ ]+ },+ {+ "symbol": "Kafka.Types.KafkaDebug",+ "members": [+ "Kafka.Types.DebugAll",+ "Kafka.Types.DebugBroker",+ "Kafka.Types.DebugCgrp",+ "Kafka.Types.DebugFeature",+ "Kafka.Types.DebugFetch",+ "Kafka.Types.DebugGeneric",+ "Kafka.Types.DebugMetadata",+ "Kafka.Types.DebugMsg",+ "Kafka.Types.DebugProtocol",+ "Kafka.Types.DebugQueue",+ "Kafka.Types.DebugSecurity",+ "Kafka.Types.DebugTopic"+ ]+ },+ {+ "symbol": "Kafka.Types.KafkaError",+ "members": [+ "Kafka.Types.KafkaBadConfiguration",+ "Kafka.Types.KafkaBadSpecification",+ "Kafka.Types.KafkaError",+ "Kafka.Types.KafkaInvalidConfigurationValue",+ "Kafka.Types.KafkaInvalidReturnValue",+ "Kafka.Types.KafkaResponseError",+ "Kafka.Types.KafkaUnknownConfigurationKey"+ ]+ },+ {+ "symbol": "Kafka.Types.KafkaLogLevel",+ "members": [+ "Kafka.Types.KafkaLogAlert",+ "Kafka.Types.KafkaLogCrit",+ "Kafka.Types.KafkaLogDebug",+ "Kafka.Types.KafkaLogEmerg",+ "Kafka.Types.KafkaLogErr",+ "Kafka.Types.KafkaLogInfo",+ "Kafka.Types.KafkaLogNotice",+ "Kafka.Types.KafkaLogWarning"+ ]+ },+ {+ "symbol": "Kafka.Types.Millis",+ "members": [+ "Kafka.Types.Millis",+ "Kafka.Types.unMillis"+ ]+ },+ {+ "symbol": "Kafka.Types.PartitionId",+ "members": [+ "Kafka.Types.PartitionId",+ "Kafka.Types.unPartitionId"+ ]+ },+ {+ "symbol": "Kafka.Types.Timeout",+ "members": [+ "Kafka.Types.Timeout",+ "Kafka.Types.unTimeout"+ ]+ },+ {+ "symbol": "Kafka.Types.TopicName",+ "members": [+ "Kafka.Types.TopicName",+ "Kafka.Types.unTopicName"+ ]+ },+ {+ "symbol": "Kafka.Types.TopicType",+ "members": [+ "Kafka.Types.System",+ "Kafka.Types.User"+ ]+ },+ {+ "symbol": "Kafka.Types.headersFromList",+ "members": []+ },+ {+ "symbol": "Kafka.Types.headersToList",+ "members": []+ },+ {+ "symbol": "Kafka.Types.kafkaCompressionCodecToText",+ "members": []+ },+ {+ "symbol": "Kafka.Types.kafkaDebugToText",+ "members": []+ },+ {+ "symbol": "Kafka.Types.topicType",+ "members": []+ }+ ],+ "Kafka.Version": [+ {+ "symbol": "Kafka.Version.LibrdkafkaVersion",+ "members": [+ "Kafka.Version.LibrdkafkaVersion",+ "Kafka.Version.versionMajor",+ "Kafka.Version.versionMinor",+ "Kafka.Version.versionRevision"+ ]+ },+ {+ "symbol": "Kafka.Version.decodeLibrdkafkaVersion",+ "members": []+ },+ {+ "symbol": "Kafka.Version.librdkafkaVersion",+ "members": []+ },+ {+ "symbol": "Kafka.Version.librdkafkaVersionNumber",+ "members": []+ },+ {+ "symbol": "Kafka.Version.librdkafkaVersionParts",+ "members": []+ }+ ]+ },+ "contracts": [+ {+ "id": "F1",+ "symbols": [+ "Kafka.Topic.createTopic"+ ],+ "owner": 8,+ "behavior": "Topic creation applies every supplied configuration before submission and reports native failures",+ "inputs": "empty/singleton/multiple maps; rejected known values; declared unknown-key policy; valid/default/invalid counts and names; C representation boundaries",+ "expected": "Exact effective known properties and requested topic metadata; unrecognized keys follow the declared broker policy with exact setter arguments; native/local failures preserve their error conventions",+ "modes": "producer; async/sync consumers, including after graceful close",+ "ownership": "NewTopic, admin options, queue, event allocated/acquired then released on success, rejection and exception",+ "tests": [+ "rdkafka-hs-integration.topic-configuration.singleton configuration reaches the broker",+ "rdkafka-hs-integration.topic-configuration.native allocation control detects a retained request",+ "rdkafka-hs-integration.topic-configuration.setter rejection releases allocated request before submission",+ "rdkafka-hs-integration.topic-configuration.interruption after allocation releases request before submission",+ "rdkafka-hs-integration.topic-configuration.multiple configuration entries reach the broker",+ "rdkafka-hs-integration.topic-configuration.broker-rejected values release requests and response events repeatedly",+ "rdkafka-hs-integration.topic-configuration.unrepresentable partition count never wraps to broker defaults",+ "rdkafka-hs-integration.topic-configuration.NUL in a topic name never creates a truncated topic",+ "rdkafka-hs-integration.topic-configuration.unresponsive broker preserves the native timeout error",+ "rdkafka-hs-integration.topic-configuration.empty configuration creates a usable topic",+ "rdkafka-hs-integration.topic-configuration.later setter rejection releases partially configured request",+ "rdkafka-hs-integration.topic-configuration.duplicate creation preserves the existing topic",+ "rdkafka-hs-integration.topic-configuration.deletion removes exactly the existing topic",+ "rdkafka-hs-integration.topic-configuration.missing topic deletion preserves its error and releases the request",+ "rdkafka-hs-integration.topic-configuration.NUL deletion cannot remove a truncated victim name",+ "rdkafka-hs-integration.topic-configuration.broker default partition and replication counts remain supported",+ "rdkafka-hs-integration.topic-configuration.replication above the available broker count is rejected",+ "rdkafka-hs-integration.topic-configuration.unsupported configuration follows the declared broker policy",+ "rdkafka-hs-integration.topic-configuration.minimum unrepresentable partition count is rejected",+ "rdkafka-hs-integration.topic-configuration.maximum unrepresentable replication count is rejected",+ "rdkafka-hs-integration.topic-configuration.minimum unrepresentable replication count is rejected",+ "rdkafka-hs-integration.topic-configuration.NUL configuration key is rejected before native allocation",+ "rdkafka-hs-integration.topic-configuration.NUL configuration value is rejected before native allocation",+ "rdkafka-hs-integration.topic-configuration.negative invalid partition count retains native validation",+ "rdkafka-hs-integration.topic-configuration.maximum C partition count retains native validation",+ "rdkafka-hs-integration.topic-configuration.negative invalid replication count retains native validation",+ "rdkafka-hs-integration.topic-configuration.maximum C replication count retains native validation",+ "rdkafka-hs-integration.topic-configuration.empty topic name is rejected by the broker",+ "rdkafka-hs-integration.topic-configuration.space in a topic name is rejected by the broker",+ "rdkafka-hs-integration.topic-configuration.overlong topic name is rejected by the broker",+ "rdkafka-hs-integration.topic-configuration.zero partition count is rejected by the broker",+ "rdkafka-hs-integration.topic-configuration.zero replication count is rejected by the broker",+ "rdkafka-hs-integration.topic-configuration.wrong event type fails and releases its event",+ "rdkafka-hs-integration.topic-configuration.empty response fails and releases its event",+ "rdkafka-hs-integration.topic-configuration.wrong topic response cannot report success",+ "rdkafka-hs-integration.topic-configuration.missing polled event reports a timeout",+ "rdkafka-hs-integration.topic-configuration.delayed response succeeds with balanced ownership",+ "rdkafka-hs-integration.topic-configuration.consumer administration applies settings in async mode",+ "rdkafka-hs-integration.topic-configuration.consumer administration applies settings in sync mode",+ "rdkafka-hs-integration.topic-configuration.consumer administration applies settings in async-closed mode",+ "rdkafka-hs-integration.topic-configuration.consumer administration applies settings in sync-closed mode",+ "rdkafka-hs-integration.topic-configuration.concurrent requests keep their own queues and responses",+ "rdkafka-hs-integration.topic-configuration.unresponsive deletion preserves the native timeout error",+ "rdkafka-hs-integration.topic-configuration.deletion rejects a wrong event type and releases it",+ "rdkafka-hs-integration.topic-configuration.deletion rejects an empty result and releases its event",+ "rdkafka-hs-integration.topic-configuration.deletion rejects a mismatched topic result",+ "rdkafka-hs-integration.topic-configuration.deletion reports a missing response as a timeout",+ "rdkafka-hs-integration.topic-configuration.missing native timeout configuration returns an error",+ "rdkafka-hs-integration.topic-configuration.malformed native timeout configuration returns an error",+ "rdkafka-hs-integration.topic-configuration.zero native timeout configuration returns an error",+ "rdkafka-hs-integration.topic-configuration.negative native timeout configuration returns an error",+ "rdkafka-hs-integration.topic-configuration.overflowing native timeout configuration returns an error",+ "rdkafka-hs-integration.topic-configuration.oversized native timeout configuration never reads a truncated buffer"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "F2",+ "symbols": [+ "Kafka.Producer.ProducerProperties.extraTopicProps",+ "Kafka.Producer.ProducerProperties.sendTimeout",+ "Kafka.Producer.ProducerProperties.topicCompression",+ "Kafka.Producer.newProducer"+ ],+ "owner": 9,+ "behavior": "Global topic defaults are preserved; explicit topic settings override conflicting defaults",+ "inputs": "global-only, explicit-only, conflicting, unrelated global topic defaults; timeout/compression boundary and invalid settings",+ "expected": "Actual native client timeout/configuration reflects merged precedence; rejected config never silently succeeds",+ "modes": "all supported modes",+ "ownership": "Configuration allocated, copied/transferred exactly once; producer retains configured defaults",+ "tests": [+ "rdkafka-hs-integration.producer-regressions.explicit topic timeout expires an accepted message",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: defaults",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: global only",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: topic only",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: disjoint maps",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: explicit topic wins duplicate",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: last topic property wins",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: empty topic map preserves global",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: zero topic timeout is infinite",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: maximum native topic timeout",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: explicit topic wins native timeout alias",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: topic codec overrides global codec",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: global codec survives unrelated topic keys",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with NoCompression",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Gzip",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Snappy",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Lz4",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Zstd",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: unknown global key",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: unknown topic key",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: invalid topic timeout",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: excessive topic timeout",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: global-only key in topic map",+ "rdkafka-hs.Producer properties generated.program follows last-write semantics",+ "rdkafka-hs.Producer properties generated.configuration has left and right identity",+ "rdkafka-hs.Producer properties generated.configuration composition is associative",+ "rdkafka-hs.Producer properties generated.composition appends writes in order",+ "rdkafka-hs.Producer properties generated.unrelated keys survive a conflicting write",+ "rdkafka-hs.Producer properties generated.last explicit log level wins",+ "rdkafka-hs.Producer properties generated.fixed empty duplicate and binary text values",+ "rdkafka-hs-integration.producer-properties.callback composition preserves order and identity"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "F3",+ "symbols": [+ "Kafka.Consumer.seekPartitions"+ ],+ "owner": 10,+ "behavior": "Seek reports each failed partition while retaining valid partition behavior",+ "inputs": "valid, invalid and mixed partitions; empty list; timeout; beginning/end/stored/invalid/large offsets",+ "expected": "Failure is surfaced through existing return type; valid partition offset and next record agree",+ "modes": "async and sync callback modes; zero-timeout initiation and synchronous completion",+ "ownership": "One native list ForeignPtr retains elements through call and error inspection; overall error object is destroyed once, including decoder exceptions",+ "tests": [+ "rdkafka-hs-integration.seek-partitions.async.unassigned member reports native error",+ "rdkafka-hs-integration.seek-partitions.async.empty list preserves top-level invalid argument",+ "rdkafka-hs-integration.seek-partitions.async.zero-timeout unassigned failure is immediate",+ "rdkafka-hs-integration.seek-partitions.async.empty zero-timeout preserves top-level error",+ "rdkafka-hs-integration.seek-partitions.async.top-level error precedes member error and is destroyed",+ "rdkafka-hs-integration.seek-partitions.async.first substantive error follows input order",+ "rdkafka-hs-integration.seek-partitions.async.reversed input selects the other substantive error",+ "rdkafka-hs-integration.seek-partitions.async.zero-timeout skips pending but reports later failure",+ "rdkafka-hs-integration.seek-partitions.async.nonzero-timeout preserves residual pending",+ "rdkafka-hs-integration.seek-partitions.async.zero-timeout all pending promises initiation only",+ "rdkafka-hs-integration.seek-partitions.async.nonzero-timeout all pending is not success",+ "rdkafka-hs-integration.seek-partitions.async.top-level decoder exception still destroys error object",+ "rdkafka-hs-integration.seek-partitions.async.single seek replays exact record",+ "rdkafka-hs-integration.seek-partitions.async.multiple successful seeks replay both partitions",+ "rdkafka-hs-integration.seek-partitions.async.mixed seek reports failure without rolling back success",+ "rdkafka-hs-integration.seek-partitions.async.mixed errors follow actual request order",+ "rdkafka-hs-integration.seek-partitions.async.zero-timeout valid seek is followed by synchronous replay",+ "rdkafka-hs-integration.seek-partitions.async.zero-timeout mixed request keeps immediate unknown error",+ "rdkafka-hs-integration.seek-partitions.async.zero-timeout logical offsets promise initiation only",+ "rdkafka-hs-integration.seek-partitions.async.infinite native timeout completes a valid seek",+ "rdkafka-hs-integration.seek-partitions.async.duplicate entries preserve residual native pending error",+ "rdkafka-hs-integration.seek-partitions.async.unassigned existing partition returns state error",+ "rdkafka-hs-integration.seek-partitions.async.unknown topic reports member error",+ "rdkafka-hs-integration.seek-partitions.async.stored sentinel is rejected without altering position",+ "rdkafka-hs-integration.seek-partitions.async.end and exact high watermark produce no record",+ "rdkafka-hs-integration.seek-partitions.async.seek before retained log range resets to actual low watermark",+ "rdkafka-hs-integration.seek-partitions.async.beginning sentinel replays offset zero",+ "rdkafka-hs-integration.seek-partitions.async.absolute low watermark replays offset zero",+ "rdkafka-hs-integration.seek-partitions.async.invalid sentinel uses configured earliest reset",+ "rdkafka-hs-integration.seek-partitions.async.above high watermark uses configured earliest reset",+ "rdkafka-hs-integration.seek-partitions.async.native tail sentinel replays final two records",+ "rdkafka-hs-integration.seek-partitions.sync.unassigned member reports native error",+ "rdkafka-hs-integration.seek-partitions.sync.empty list preserves top-level invalid argument",+ "rdkafka-hs-integration.seek-partitions.sync.zero-timeout unassigned failure is immediate",+ "rdkafka-hs-integration.seek-partitions.sync.empty zero-timeout preserves top-level error",+ "rdkafka-hs-integration.seek-partitions.sync.top-level error precedes member error and is destroyed",+ "rdkafka-hs-integration.seek-partitions.sync.first substantive error follows input order",+ "rdkafka-hs-integration.seek-partitions.sync.reversed input selects the other substantive error",+ "rdkafka-hs-integration.seek-partitions.sync.zero-timeout skips pending but reports later failure",+ "rdkafka-hs-integration.seek-partitions.sync.nonzero-timeout preserves residual pending",+ "rdkafka-hs-integration.seek-partitions.sync.zero-timeout all pending promises initiation only",+ "rdkafka-hs-integration.seek-partitions.sync.nonzero-timeout all pending is not success",+ "rdkafka-hs-integration.seek-partitions.sync.top-level decoder exception still destroys error object",+ "rdkafka-hs-integration.seek-partitions.sync.single seek replays exact record",+ "rdkafka-hs-integration.seek-partitions.sync.multiple successful seeks replay both partitions",+ "rdkafka-hs-integration.seek-partitions.sync.mixed seek reports failure without rolling back success",+ "rdkafka-hs-integration.seek-partitions.sync.mixed errors follow actual request order",+ "rdkafka-hs-integration.seek-partitions.sync.zero-timeout valid seek is followed by synchronous replay",+ "rdkafka-hs-integration.seek-partitions.sync.zero-timeout mixed request keeps immediate unknown error",+ "rdkafka-hs-integration.seek-partitions.sync.zero-timeout logical offsets promise initiation only",+ "rdkafka-hs-integration.seek-partitions.sync.infinite native timeout completes a valid seek",+ "rdkafka-hs-integration.seek-partitions.sync.duplicate entries preserve residual native pending error",+ "rdkafka-hs-integration.seek-partitions.sync.unassigned existing partition returns state error",+ "rdkafka-hs-integration.seek-partitions.sync.unknown topic reports member error",+ "rdkafka-hs-integration.seek-partitions.sync.stored sentinel is rejected without altering position",+ "rdkafka-hs-integration.seek-partitions.sync.end and exact high watermark produce no record",+ "rdkafka-hs-integration.seek-partitions.sync.seek before retained log range resets to actual low watermark",+ "rdkafka-hs-integration.seek-partitions.sync.beginning sentinel replays offset zero",+ "rdkafka-hs-integration.seek-partitions.sync.absolute low watermark replays offset zero",+ "rdkafka-hs-integration.seek-partitions.sync.invalid sentinel uses configured earliest reset",+ "rdkafka-hs-integration.seek-partitions.sync.above high watermark uses configured earliest reset",+ "rdkafka-hs-integration.seek-partitions.sync.native tail sentinel replays final two records"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence": "docs/testing/seek-evidence.json",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "F4",+ "symbols": [+ "Kafka.Producer.produceMessage",+ "Kafka.Producer.produceMessage'"+ ],+ "owner": 9,+ "behavior": "Per-message callback ownership transfers only for an accepted enqueue",+ "inputs": "queue full, oversized/invalid record, valid record, delivery failure, purge; repeated rejection and concurrent enqueue",+ "expected": "Immediate rejection never invokes callback and permits capture collection; accepted callback retained until exactly one matching report",+ "modes": "all supported modes",+ "ownership": "StablePtr allocated before enqueue; freed on rejection or after delivery callback; no double free",+ "tests": [+ "rdkafka-hs-integration.producer-regressions.explicit topic timeout expires an accepted message",+ "rdkafka-hs-integration.producer-regressions.global timeout still expires an accepted message",+ "rdkafka-hs-integration.producer-regressions.queue-full rejection releases callback capture without invoking it",+ "rdkafka-hs-integration.producer-regressions.accepted callback retains its capture until a purged report completes",+ "rdkafka-hs-integration.producer-regressions.throwing global callback preserves per-message delivery and releases capture",+ "rdkafka-hs-integration.producer-regressions.throwing per-message callback reports exception and releases capture",+ "rdkafka-hs-integration.producer-regressions.repeated queue-full rejections release every callback capture",+ "rdkafka-hs-integration.producer-regressions.cancellation at a rejected enqueue releases capture before unmasking",+ "rdkafka-hs-integration.producer-regressions.cancellation after native acceptance retains callback until its report",+ "rdkafka-hs-integration.producer-regressions.another poller can deliver before successful enqueue returns",+ "rdkafka-hs-integration.producer-regressions.running callback keeps its capture after the native root is released",+ "rdkafka-hs-integration.producer-regressions.native error decoding failure releases rejected callback capture",+ "rdkafka-hs-integration.producer-regressions.non-null native success-code error rejects and releases capture",+ "rdkafka-hs-integration.producer-regressions.unknown native error code is preserved instead of reading errno",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with NoCompression",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Gzip",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Snappy",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Lz4",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Zstd",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: none",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: inflight",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue+inflight",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue+nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: inflight+nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: all",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: none",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: inflight",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue+inflight",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue+nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: inflight+nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: all",+ "rdkafka-hs-integration.producer-regressions.bounded flush timeout recovers when the delayed response arrives",+ "rdkafka-hs-integration.producer-regressions.oversized rejection releases capture without a delivery report",+ "rdkafka-hs-integration.producer-regressions.known invalid partition rejection releases capture",+ "rdkafka-hs-integration.producer-regressions.empty queue supports repeated flush and close",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: NUL topic name",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: NUL header name",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: maximum unrepresentable partition",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: minimum unrepresentable partition",+ "rdkafka-hs-integration.producer-regressions.later delivery callback replaces the earlier callback"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "F5",+ "symbols": [+ "Kafka.Callbacks.errorCallback",+ "Kafka.Callbacks.logCallback",+ "Kafka.Callbacks.statsCallback",+ "Kafka.Consumer.Callbacks.offsetCommitCallback",+ "Kafka.Consumer.Callbacks.rebalanceCallback",+ "Kafka.Consumer.closeConsumer",+ "Kafka.Consumer.destroyConsumer",+ "Kafka.Consumer.newAssignedConsumer",+ "Kafka.Consumer.newConsumer",+ "Kafka.Internal.Setup.Callback",+ "Kafka.Producer.Callbacks.deliveryCallback",+ "Kafka.Producer.closeProducer"+ ],+ "owner": 11,+ "behavior": "Native callback registrations remain callable until native destruction and are then freed",+ "inputs": "constructor failure; repeated registration; replacement; explicit close/destroy; GC finalizer; exceptions and concurrent teardown",+ "expected": "Positive retention and post-release collection controls; exactly one deallocator; callbacks safe during native teardown",+ "modes": "producer and consumer; async/sync; explicit/GC teardown",+ "ownership": "FunPtr registrations owned separately from per-message StablePtrs; native destruction precedes registration release",+ "tests": [+ "rdkafka-hs.Callback owner.bridge allocation executes masked before ownership is recorded",+ "rdkafka-hs.Callback owner.installed and replaced bridges release exactly once",+ "rdkafka-hs.Callback owner.failed native install still owns its allocated bridge",+ "rdkafka-hs.Callback owner.failed allocation has no release",+ "rdkafka-hs.Callback owner.transfer preserves a callable bridge until client release",+ "rdkafka-hs.Callback owner.transferred and released owners reject reuse before allocating",+ "rdkafka-hs.Callback owner.release retry does not repeat completed releases",+ "rdkafka-hs.Callback owner.concurrent releases join before returning",+ "rdkafka-hs-integration.callback-lifetime.async throwing error callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing log callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing stats callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing rebalance callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing commit callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing error callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing log callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing stats callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing rebalance callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing commit callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async error callback releases after destroy with retained wrapper",+ "rdkafka-hs-integration.callback-lifetime.sync error callback releases after destroy with retained wrapper",+ "rdkafka-hs-integration.callback-lifetime.producer delivery callback releases after native finalization",+ "rdkafka-hs-integration.callback-lifetime.noncaptured control is collectible",+ "rdkafka-hs-integration.callback-lifetime.async log callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.async stats callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.sync log callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.sync stats callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.async construction failure releases callbacks: topic",+ "rdkafka-hs-integration.callback-lifetime.async construction failure releases callbacks: native",+ "rdkafka-hs-integration.callback-lifetime.sync construction failure releases callbacks: topic",+ "rdkafka-hs-integration.callback-lifetime.sync construction failure releases callbacks: native",+ "rdkafka-hs-integration.callback-lifetime.producer native construction failure releases callbacks",+ "rdkafka-hs-integration.callback-lifetime.async rebalance callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.async commit callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.sync rebalance callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.sync commit callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.replaced producer delivery callbacks both release",+ "rdkafka-hs-integration.callback-lifetime.async concurrent destruction joins at native entry",+ "rdkafka-hs-integration.callback-lifetime.async concurrent destruction joins at native completion",+ "rdkafka-hs-integration.callback-lifetime.async concurrent destruction joins at native shutdown callback",+ "rdkafka-hs-integration.callback-lifetime.sync concurrent destruction joins at native entry",+ "rdkafka-hs-integration.callback-lifetime.sync concurrent destruction joins at native completion",+ "rdkafka-hs-integration.callback-lifetime.sync concurrent destruction joins at native shutdown callback",+ "rdkafka-hs-integration.callback-lifetime.async cancellation at native entry preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.async cancellation at native completion preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.async cancellation at native shutdown callback preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation at native entry preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation at native completion preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation at native shutdown callback preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.async cancellation after poll stop and queue detachment preserves teardown",+ "rdkafka-hs-integration.callback-lifetime.producer constructor cancellation at partial registration releases its owner",+ "rdkafka-hs-integration.callback-lifetime.producer constructor cancellation at native acceptance releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-async constructor cancellation at partial registration releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-async constructor cancellation at native acceptance releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-sync constructor cancellation at partial registration releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-sync constructor cancellation at native acceptance releases its owner",+ "rdkafka-hs-integration.callback-lifetime.async cancellation while waiting for active callback permits retry",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation while waiting for active callback permits retry",+ "rdkafka-hs-integration.callback-lifetime.async closed consumer GC releases its registrations once",+ "rdkafka-hs-integration.callback-lifetime.sync closed consumer GC releases its registrations once",+ "rdkafka-hs-integration.callback-lifetime.producer error callback remains live through close and releases on GC",+ "rdkafka-hs-integration.callback-lifetime.producer log callback remains live through close and releases on GC",+ "rdkafka-hs-integration.callback-lifetime.producer stats callback remains live through close and releases on GC",+ "rdkafka-hs-integration.callback-lifetime.failed native construction releases the caller-owned duplicate config"+ ],+ "status": "tested",+ "native_diagnostics": "docs/testing/callback-native-diagnostics.json",+ "mutations": "dist-mutations/20261024T135134Z-callback-6370-0/results.json",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "F6",+ "symbols": [+ "Kafka.Transaction.abortTransaction",+ "Kafka.Transaction.beginTransaction",+ "Kafka.Transaction.initTransactions"+ ],+ "owner": 12,+ "behavior": "All transaction error pointers are decoded and released",+ "inputs": "success/null, nontransactional state errors, unavailable broker/timeout, retriable/fatal/abortable errors; repeated calls",+ "expected": "Existing TxError structure preserved; allocation/release balance with positive native leak control",+ "modes": "all supported modes",+ "ownership": "Call-scoped rd_kafka_error_t allocated by native API, copied into Haskell, destroyed exactly once",+ "tests": [+ "rdkafka-hs-integration.transaction-errors.transaction-error-leak-probe releases 300 immediate native errors",+ "rdkafka-hs-integration.transaction-errors.native allocation control detects the inherited three-error leak",+ "rdkafka-hs-integration.transaction-errors.initialization timeout destroys its native error on each retry",+ "rdkafka-hs-integration.transaction-errors.zero-timeout initialization resumes successfully against the broker",+ "rdkafka-hs-integration.transaction-errors.transaction state errors preserve empty commit and abort recovery",+ "rdkafka-hs-integration.transaction-errors.duplicate transactional IDs report a real fatal fencing error",+ "rdkafka-hs-integration.transaction-errors.broker-rejected delivery requires abort and permits a successful new transaction",+ "rdkafka-hs-integration.transaction-errors.init without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.begin without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.abort without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.init NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.begin NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.abort NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.init invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.begin invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.abort invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.init cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.begin cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.abort cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.async commit publishes output and source next offset atomically; abort publishes neither",+ "rdkafka-hs-integration.transaction-errors.sync commit publishes output and source next offset atomically; abort publishes neither"+ ],+ "status": "tested",+ "mutations": "dist-mutations/20261024T141053Z-transaction-39758-0/results.json",+ "native_diagnostics": "docs/testing/transaction-native-diagnostics.json",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-ConsumerProperties-CallbackPollMode",+ "symbols": [+ "Kafka.Consumer.ConsumerProperties.CallbackPollMode"+ ],+ "owner": 14,+ "behavior": "CallbackPollMode constructs/composes the documented effective settings",+ "inputs": "identity, repeated/conflicting settings, left/right precedence, empty/nonempty lists and boundary numeric/text values",+ "expected": "Exact effective map, callback/poll mode/log level; native validation preserved for invalid values",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.consumer composition.consumer program follows independent last-write model",+ "rdkafka-hs.Public properties.consumer composition.consumer identity preserves every observable field",+ "rdkafka-hs.Public properties.consumer composition.consumer association preserves writes and poll mode",+ "rdkafka-hs.Public properties.consumer composition.consumer composition appends programs",+ "rdkafka-hs.Public properties.consumer composition.unset poll mode preserves a prior explicit mode",+ "rdkafka-hs.Public properties.consumer composition.consumer helpers write exact native property names",+ "rdkafka-hs.Public data contracts.builders.semigroup defaults retain writes callbacks and subscription union",+ "rdkafka-hs.Public data contracts.builders.consumer builders preserve exact settings and leave other fields unset",+ "rdkafka-hs.Public data contracts.builders.producer builders preserve global versus explicit topic placement",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: invalid topic timeout",+ "rdkafka-hs-integration.consumer-properties.consumer callback composition preserves registration order and identity",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.empty producer client id retains the native default",+ "rdkafka-hs-integration.public-contract.config-strings.consumer ordinary UTF8 values remain exact",+ "rdkafka-hs-integration.public-contract.config-strings.empty global key retains native unknown-key rejection"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-ConsumerProperties-ConsumerProperties",+ "symbols": [+ "Kafka.Consumer.ConsumerProperties.ConsumerProperties"+ ],+ "owner": 14,+ "behavior": "ConsumerProperties constructs/composes the documented effective settings",+ "inputs": "identity, repeated/conflicting settings, left/right precedence, empty/nonempty lists and boundary numeric/text values",+ "expected": "Exact effective map, callback/poll mode/log level; native validation preserved for invalid values",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.consumer composition.consumer program follows independent last-write model",+ "rdkafka-hs.Public properties.consumer composition.consumer identity preserves every observable field",+ "rdkafka-hs.Public properties.consumer composition.consumer association preserves writes and poll mode",+ "rdkafka-hs.Public properties.consumer composition.consumer composition appends programs",+ "rdkafka-hs.Public properties.consumer composition.unset poll mode preserves a prior explicit mode",+ "rdkafka-hs.Public properties.consumer composition.consumer helpers write exact native property names",+ "rdkafka-hs.Public data contracts.builders.semigroup defaults retain writes callbacks and subscription union",+ "rdkafka-hs.Public data contracts.builders.consumer builders preserve exact settings and leave other fields unset",+ "rdkafka-hs.Public data contracts.builders.producer builders preserve global versus explicit topic placement",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: invalid topic timeout",+ "rdkafka-hs-integration.consumer-properties.consumer callback composition preserves registration order and identity",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.empty producer client id retains the native default",+ "rdkafka-hs-integration.public-contract.config-strings.consumer ordinary UTF8 values remain exact",+ "rdkafka-hs-integration.public-contract.config-strings.empty global key retains native unknown-key rejection"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-ConsumerProperties-autoCommit",+ "symbols": [+ "Kafka.Consumer.ConsumerProperties.autoCommit"+ ],+ "owner": 14,+ "behavior": "autoCommit constructs/composes the documented effective settings",+ "inputs": "identity, repeated/conflicting settings, left/right precedence, empty/nonempty lists and boundary numeric/text values",+ "expected": "Exact effective map, callback/poll mode/log level; native validation preserved for invalid values",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.consumer composition.consumer program follows independent last-write model",+ "rdkafka-hs.Public properties.consumer composition.consumer identity preserves every observable field",+ "rdkafka-hs.Public properties.consumer composition.consumer association preserves writes and poll mode",+ "rdkafka-hs.Public properties.consumer composition.consumer composition appends programs",+ "rdkafka-hs.Public properties.consumer composition.unset poll mode preserves a prior explicit mode",+ "rdkafka-hs.Public properties.consumer composition.consumer helpers write exact native property names",+ "rdkafka-hs.Public data contracts.builders.semigroup defaults retain writes callbacks and subscription union",+ "rdkafka-hs.Public data contracts.builders.consumer builders preserve exact settings and leave other fields unset",+ "rdkafka-hs.Public data contracts.builders.producer builders preserve global versus explicit topic placement",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: invalid topic timeout",+ "rdkafka-hs-integration.consumer-properties.consumer callback composition preserves registration order and identity",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.empty producer client id retains the native default",+ "rdkafka-hs-integration.public-contract.config-strings.consumer ordinary UTF8 values remain exact",+ "rdkafka-hs-integration.public-contract.config-strings.empty global key retains native unknown-key rejection"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-ConsumerProperties-brokersList",+ "symbols": [+ "Kafka.Consumer.ConsumerProperties.brokersList"+ ],+ "owner": 14,+ "behavior": "brokersList constructs/composes the documented effective settings",+ "inputs": "identity, repeated/conflicting settings, left/right precedence, empty/nonempty lists and boundary numeric/text values",+ "expected": "Exact effective map, callback/poll mode/log level; native validation preserved for invalid values",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.consumer composition.consumer program follows independent last-write model",+ "rdkafka-hs.Public properties.consumer composition.consumer identity preserves every observable field",+ "rdkafka-hs.Public properties.consumer composition.consumer association preserves writes and poll mode",+ "rdkafka-hs.Public properties.consumer composition.consumer composition appends programs",+ "rdkafka-hs.Public properties.consumer composition.unset poll mode preserves a prior explicit mode",+ "rdkafka-hs.Public properties.consumer composition.consumer helpers write exact native property names",+ "rdkafka-hs.Public data contracts.builders.semigroup defaults retain writes callbacks and subscription union",+ "rdkafka-hs.Public data contracts.builders.consumer builders preserve exact settings and leave other fields unset",+ "rdkafka-hs.Public data contracts.builders.producer builders preserve global versus explicit topic placement",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: invalid topic timeout",+ "rdkafka-hs-integration.consumer-properties.consumer callback composition preserves registration order and identity",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.empty producer client id retains the native default",+ "rdkafka-hs-integration.public-contract.config-strings.consumer ordinary UTF8 values remain exact",+ "rdkafka-hs-integration.public-contract.config-strings.empty global key retains native unknown-key rejection"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-ConsumerProperties-callbackPollMode",+ "symbols": [+ "Kafka.Consumer.ConsumerProperties.callbackPollMode"+ ],+ "owner": 14,+ "behavior": "callbackPollMode constructs/composes the documented effective settings",+ "inputs": "identity, repeated/conflicting settings, left/right precedence, empty/nonempty lists and boundary numeric/text values",+ "expected": "Exact effective map, callback/poll mode/log level; native validation preserved for invalid values",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.consumer composition.consumer program follows independent last-write model",+ "rdkafka-hs.Public properties.consumer composition.consumer identity preserves every observable field",+ "rdkafka-hs.Public properties.consumer composition.consumer association preserves writes and poll mode",+ "rdkafka-hs.Public properties.consumer composition.consumer composition appends programs",+ "rdkafka-hs.Public properties.consumer composition.unset poll mode preserves a prior explicit mode",+ "rdkafka-hs.Public properties.consumer composition.consumer helpers write exact native property names",+ "rdkafka-hs.Public data contracts.builders.semigroup defaults retain writes callbacks and subscription union",+ "rdkafka-hs.Public data contracts.builders.consumer builders preserve exact settings and leave other fields unset",+ "rdkafka-hs.Public data contracts.builders.producer builders preserve global versus explicit topic placement",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: invalid topic timeout",+ "rdkafka-hs-integration.consumer-properties.consumer callback composition preserves registration order and identity",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.empty producer client id retains the native default",+ "rdkafka-hs-integration.public-contract.config-strings.consumer ordinary UTF8 values remain exact",+ "rdkafka-hs-integration.public-contract.config-strings.empty global key retains native unknown-key rejection"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-ConsumerProperties-clientId",+ "symbols": [+ "Kafka.Consumer.ConsumerProperties.clientId"+ ],+ "owner": 14,+ "behavior": "clientId constructs/composes the documented effective settings",+ "inputs": "identity, repeated/conflicting settings, left/right precedence, empty/nonempty lists and boundary numeric/text values",+ "expected": "Exact effective map, callback/poll mode/log level; native validation preserved for invalid values",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.consumer composition.consumer program follows independent last-write model",+ "rdkafka-hs.Public properties.consumer composition.consumer identity preserves every observable field",+ "rdkafka-hs.Public properties.consumer composition.consumer association preserves writes and poll mode",+ "rdkafka-hs.Public properties.consumer composition.consumer composition appends programs",+ "rdkafka-hs.Public properties.consumer composition.unset poll mode preserves a prior explicit mode",+ "rdkafka-hs.Public properties.consumer composition.consumer helpers write exact native property names",+ "rdkafka-hs.Public data contracts.builders.semigroup defaults retain writes callbacks and subscription union",+ "rdkafka-hs.Public data contracts.builders.consumer builders preserve exact settings and leave other fields unset",+ "rdkafka-hs.Public data contracts.builders.producer builders preserve global versus explicit topic placement",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: invalid topic timeout",+ "rdkafka-hs-integration.consumer-properties.consumer callback composition preserves registration order and identity",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.empty producer client id retains the native default",+ "rdkafka-hs-integration.public-contract.config-strings.consumer ordinary UTF8 values remain exact",+ "rdkafka-hs-integration.public-contract.config-strings.empty global key retains native unknown-key rejection"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-ConsumerProperties-compression",+ "symbols": [+ "Kafka.Consumer.ConsumerProperties.compression"+ ],+ "owner": 14,+ "behavior": "compression constructs/composes the documented effective settings",+ "inputs": "identity, repeated/conflicting settings, left/right precedence, empty/nonempty lists and boundary numeric/text values",+ "expected": "Exact effective map, callback/poll mode/log level; native validation preserved for invalid values",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.consumer composition.consumer program follows independent last-write model",+ "rdkafka-hs.Public properties.consumer composition.consumer identity preserves every observable field",+ "rdkafka-hs.Public properties.consumer composition.consumer association preserves writes and poll mode",+ "rdkafka-hs.Public properties.consumer composition.consumer composition appends programs",+ "rdkafka-hs.Public properties.consumer composition.unset poll mode preserves a prior explicit mode",+ "rdkafka-hs.Public properties.consumer composition.consumer helpers write exact native property names",+ "rdkafka-hs.Public data contracts.builders.semigroup defaults retain writes callbacks and subscription union",+ "rdkafka-hs.Public data contracts.builders.consumer builders preserve exact settings and leave other fields unset",+ "rdkafka-hs.Public data contracts.builders.producer builders preserve global versus explicit topic placement",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: invalid topic timeout",+ "rdkafka-hs-integration.consumer-properties.consumer callback composition preserves registration order and identity",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.empty producer client id retains the native default",+ "rdkafka-hs-integration.public-contract.config-strings.consumer ordinary UTF8 values remain exact",+ "rdkafka-hs-integration.public-contract.config-strings.empty global key retains native unknown-key rejection"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-ConsumerProperties-debugOptions",+ "symbols": [+ "Kafka.Consumer.ConsumerProperties.debugOptions"+ ],+ "owner": 14,+ "behavior": "debugOptions constructs/composes the documented effective settings",+ "inputs": "identity, repeated/conflicting settings, left/right precedence, empty/nonempty lists and boundary numeric/text values",+ "expected": "Exact effective map, callback/poll mode/log level; native validation preserved for invalid values",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.consumer composition.consumer program follows independent last-write model",+ "rdkafka-hs.Public properties.consumer composition.consumer identity preserves every observable field",+ "rdkafka-hs.Public properties.consumer composition.consumer association preserves writes and poll mode",+ "rdkafka-hs.Public properties.consumer composition.consumer composition appends programs",+ "rdkafka-hs.Public properties.consumer composition.unset poll mode preserves a prior explicit mode",+ "rdkafka-hs.Public properties.consumer composition.consumer helpers write exact native property names",+ "rdkafka-hs.Public data contracts.builders.semigroup defaults retain writes callbacks and subscription union",+ "rdkafka-hs.Public data contracts.builders.consumer builders preserve exact settings and leave other fields unset",+ "rdkafka-hs.Public data contracts.builders.producer builders preserve global versus explicit topic placement",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: invalid topic timeout",+ "rdkafka-hs-integration.consumer-properties.consumer callback composition preserves registration order and identity",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.empty producer client id retains the native default",+ "rdkafka-hs-integration.public-contract.config-strings.consumer ordinary UTF8 values remain exact",+ "rdkafka-hs-integration.public-contract.config-strings.empty global key retains native unknown-key rejection"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-ConsumerProperties-effectiveCallbackPollMode",+ "symbols": [+ "Kafka.Consumer.ConsumerProperties.effectiveCallbackPollMode"+ ],+ "owner": 14,+ "behavior": "effectiveCallbackPollMode constructs/composes the documented effective settings",+ "inputs": "identity, repeated/conflicting settings, left/right precedence, empty/nonempty lists and boundary numeric/text values",+ "expected": "Exact effective map, callback/poll mode/log level; native validation preserved for invalid values",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.consumer composition.consumer program follows independent last-write model",+ "rdkafka-hs.Public properties.consumer composition.consumer identity preserves every observable field",+ "rdkafka-hs.Public properties.consumer composition.consumer association preserves writes and poll mode",+ "rdkafka-hs.Public properties.consumer composition.consumer composition appends programs",+ "rdkafka-hs.Public properties.consumer composition.unset poll mode preserves a prior explicit mode",+ "rdkafka-hs.Public properties.consumer composition.consumer helpers write exact native property names",+ "rdkafka-hs.Public data contracts.builders.semigroup defaults retain writes callbacks and subscription union",+ "rdkafka-hs.Public data contracts.builders.consumer builders preserve exact settings and leave other fields unset",+ "rdkafka-hs.Public data contracts.builders.producer builders preserve global versus explicit topic placement",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: invalid topic timeout",+ "rdkafka-hs-integration.consumer-properties.consumer callback composition preserves registration order and identity",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.empty producer client id retains the native default",+ "rdkafka-hs-integration.public-contract.config-strings.consumer ordinary UTF8 values remain exact",+ "rdkafka-hs-integration.public-contract.config-strings.empty global key retains native unknown-key rejection"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-ConsumerProperties-extraProp",+ "symbols": [+ "Kafka.Consumer.ConsumerProperties.extraProp"+ ],+ "owner": 14,+ "behavior": "extraProp constructs/composes the documented effective settings",+ "inputs": "identity, repeated/conflicting settings, left/right precedence, empty/nonempty lists and boundary numeric/text values",+ "expected": "Exact effective map, callback/poll mode/log level; native validation preserved for invalid values",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.consumer composition.consumer program follows independent last-write model",+ "rdkafka-hs.Public properties.consumer composition.consumer identity preserves every observable field",+ "rdkafka-hs.Public properties.consumer composition.consumer association preserves writes and poll mode",+ "rdkafka-hs.Public properties.consumer composition.consumer composition appends programs",+ "rdkafka-hs.Public properties.consumer composition.unset poll mode preserves a prior explicit mode",+ "rdkafka-hs.Public properties.consumer composition.consumer helpers write exact native property names",+ "rdkafka-hs.Public data contracts.builders.semigroup defaults retain writes callbacks and subscription union",+ "rdkafka-hs.Public data contracts.builders.consumer builders preserve exact settings and leave other fields unset",+ "rdkafka-hs.Public data contracts.builders.producer builders preserve global versus explicit topic placement",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: invalid topic timeout",+ "rdkafka-hs-integration.consumer-properties.consumer callback composition preserves registration order and identity",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.empty producer client id retains the native default",+ "rdkafka-hs-integration.public-contract.config-strings.consumer ordinary UTF8 values remain exact",+ "rdkafka-hs-integration.public-contract.config-strings.empty global key retains native unknown-key rejection"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-ConsumerProperties-extraProps",+ "symbols": [+ "Kafka.Consumer.ConsumerProperties.extraProps"+ ],+ "owner": 14,+ "behavior": "extraProps constructs/composes the documented effective settings",+ "inputs": "identity, repeated/conflicting settings, left/right precedence, empty/nonempty lists and boundary numeric/text values",+ "expected": "Exact effective map, callback/poll mode/log level; native validation preserved for invalid values",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.consumer composition.consumer program follows independent last-write model",+ "rdkafka-hs.Public properties.consumer composition.consumer identity preserves every observable field",+ "rdkafka-hs.Public properties.consumer composition.consumer association preserves writes and poll mode",+ "rdkafka-hs.Public properties.consumer composition.consumer composition appends programs",+ "rdkafka-hs.Public properties.consumer composition.unset poll mode preserves a prior explicit mode",+ "rdkafka-hs.Public properties.consumer composition.consumer helpers write exact native property names",+ "rdkafka-hs.Public data contracts.builders.semigroup defaults retain writes callbacks and subscription union",+ "rdkafka-hs.Public data contracts.builders.consumer builders preserve exact settings and leave other fields unset",+ "rdkafka-hs.Public data contracts.builders.producer builders preserve global versus explicit topic placement",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: invalid topic timeout",+ "rdkafka-hs-integration.consumer-properties.consumer callback composition preserves registration order and identity",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.empty producer client id retains the native default",+ "rdkafka-hs-integration.public-contract.config-strings.consumer ordinary UTF8 values remain exact",+ "rdkafka-hs-integration.public-contract.config-strings.empty global key retains native unknown-key rejection"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-ConsumerProperties-groupId",+ "symbols": [+ "Kafka.Consumer.ConsumerProperties.groupId"+ ],+ "owner": 14,+ "behavior": "groupId constructs/composes the documented effective settings",+ "inputs": "identity, repeated/conflicting settings, left/right precedence, empty/nonempty lists and boundary numeric/text values",+ "expected": "Exact effective map, callback/poll mode/log level; native validation preserved for invalid values",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.consumer composition.consumer program follows independent last-write model",+ "rdkafka-hs.Public properties.consumer composition.consumer identity preserves every observable field",+ "rdkafka-hs.Public properties.consumer composition.consumer association preserves writes and poll mode",+ "rdkafka-hs.Public properties.consumer composition.consumer composition appends programs",+ "rdkafka-hs.Public properties.consumer composition.unset poll mode preserves a prior explicit mode",+ "rdkafka-hs.Public properties.consumer composition.consumer helpers write exact native property names",+ "rdkafka-hs.Public data contracts.builders.semigroup defaults retain writes callbacks and subscription union",+ "rdkafka-hs.Public data contracts.builders.consumer builders preserve exact settings and leave other fields unset",+ "rdkafka-hs.Public data contracts.builders.producer builders preserve global versus explicit topic placement",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: invalid topic timeout",+ "rdkafka-hs-integration.consumer-properties.consumer callback composition preserves registration order and identity",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.empty producer client id retains the native default",+ "rdkafka-hs-integration.public-contract.config-strings.consumer ordinary UTF8 values remain exact",+ "rdkafka-hs-integration.public-contract.config-strings.empty global key retains native unknown-key rejection"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-ConsumerProperties-logLevel",+ "symbols": [+ "Kafka.Consumer.ConsumerProperties.logLevel"+ ],+ "owner": 14,+ "behavior": "logLevel constructs/composes the documented effective settings",+ "inputs": "identity, repeated/conflicting settings, left/right precedence, empty/nonempty lists and boundary numeric/text values",+ "expected": "Exact effective map, callback/poll mode/log level; native validation preserved for invalid values",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.consumer composition.consumer program follows independent last-write model",+ "rdkafka-hs.Public properties.consumer composition.consumer identity preserves every observable field",+ "rdkafka-hs.Public properties.consumer composition.consumer association preserves writes and poll mode",+ "rdkafka-hs.Public properties.consumer composition.consumer composition appends programs",+ "rdkafka-hs.Public properties.consumer composition.unset poll mode preserves a prior explicit mode",+ "rdkafka-hs.Public properties.consumer composition.consumer helpers write exact native property names",+ "rdkafka-hs.Public data contracts.builders.semigroup defaults retain writes callbacks and subscription union",+ "rdkafka-hs.Public data contracts.builders.consumer builders preserve exact settings and leave other fields unset",+ "rdkafka-hs.Public data contracts.builders.producer builders preserve global versus explicit topic placement",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: invalid topic timeout",+ "rdkafka-hs-integration.consumer-properties.consumer callback composition preserves registration order and identity",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.empty producer client id retains the native default",+ "rdkafka-hs-integration.public-contract.config-strings.consumer ordinary UTF8 values remain exact",+ "rdkafka-hs-integration.public-contract.config-strings.empty global key retains native unknown-key rejection"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-ConsumerProperties-noAutoCommit",+ "symbols": [+ "Kafka.Consumer.ConsumerProperties.noAutoCommit"+ ],+ "owner": 14,+ "behavior": "noAutoCommit constructs/composes the documented effective settings",+ "inputs": "identity, repeated/conflicting settings, left/right precedence, empty/nonempty lists and boundary numeric/text values",+ "expected": "Exact effective map, callback/poll mode/log level; native validation preserved for invalid values",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.consumer composition.consumer program follows independent last-write model",+ "rdkafka-hs.Public properties.consumer composition.consumer identity preserves every observable field",+ "rdkafka-hs.Public properties.consumer composition.consumer association preserves writes and poll mode",+ "rdkafka-hs.Public properties.consumer composition.consumer composition appends programs",+ "rdkafka-hs.Public properties.consumer composition.unset poll mode preserves a prior explicit mode",+ "rdkafka-hs.Public properties.consumer composition.consumer helpers write exact native property names",+ "rdkafka-hs.Public data contracts.builders.semigroup defaults retain writes callbacks and subscription union",+ "rdkafka-hs.Public data contracts.builders.consumer builders preserve exact settings and leave other fields unset",+ "rdkafka-hs.Public data contracts.builders.producer builders preserve global versus explicit topic placement",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: invalid topic timeout",+ "rdkafka-hs-integration.consumer-properties.consumer callback composition preserves registration order and identity",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.empty producer client id retains the native default",+ "rdkafka-hs-integration.public-contract.config-strings.consumer ordinary UTF8 values remain exact",+ "rdkafka-hs-integration.public-contract.config-strings.empty global key retains native unknown-key rejection"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-ConsumerProperties-noAutoOffsetStore",+ "symbols": [+ "Kafka.Consumer.ConsumerProperties.noAutoOffsetStore"+ ],+ "owner": 14,+ "behavior": "noAutoOffsetStore constructs/composes the documented effective settings",+ "inputs": "identity, repeated/conflicting settings, left/right precedence, empty/nonempty lists and boundary numeric/text values",+ "expected": "Exact effective map, callback/poll mode/log level; native validation preserved for invalid values",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.consumer composition.consumer program follows independent last-write model",+ "rdkafka-hs.Public properties.consumer composition.consumer identity preserves every observable field",+ "rdkafka-hs.Public properties.consumer composition.consumer association preserves writes and poll mode",+ "rdkafka-hs.Public properties.consumer composition.consumer composition appends programs",+ "rdkafka-hs.Public properties.consumer composition.unset poll mode preserves a prior explicit mode",+ "rdkafka-hs.Public properties.consumer composition.consumer helpers write exact native property names",+ "rdkafka-hs.Public data contracts.builders.semigroup defaults retain writes callbacks and subscription union",+ "rdkafka-hs.Public data contracts.builders.consumer builders preserve exact settings and leave other fields unset",+ "rdkafka-hs.Public data contracts.builders.producer builders preserve global versus explicit topic placement",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: invalid topic timeout",+ "rdkafka-hs-integration.consumer-properties.consumer callback composition preserves registration order and identity",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.empty producer client id retains the native default",+ "rdkafka-hs-integration.public-contract.config-strings.consumer ordinary UTF8 values remain exact",+ "rdkafka-hs-integration.public-contract.config-strings.empty global key retains native unknown-key rejection"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-ConsumerProperties-queuedMaxMessagesKBytes",+ "symbols": [+ "Kafka.Consumer.ConsumerProperties.queuedMaxMessagesKBytes"+ ],+ "owner": 14,+ "behavior": "queuedMaxMessagesKBytes constructs/composes the documented effective settings",+ "inputs": "identity, repeated/conflicting settings, left/right precedence, empty/nonempty lists and boundary numeric/text values",+ "expected": "Exact effective map, callback/poll mode/log level; native validation preserved for invalid values",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.consumer composition.consumer program follows independent last-write model",+ "rdkafka-hs.Public properties.consumer composition.consumer identity preserves every observable field",+ "rdkafka-hs.Public properties.consumer composition.consumer association preserves writes and poll mode",+ "rdkafka-hs.Public properties.consumer composition.consumer composition appends programs",+ "rdkafka-hs.Public properties.consumer composition.unset poll mode preserves a prior explicit mode",+ "rdkafka-hs.Public properties.consumer composition.consumer helpers write exact native property names",+ "rdkafka-hs.Public data contracts.builders.semigroup defaults retain writes callbacks and subscription union",+ "rdkafka-hs.Public data contracts.builders.consumer builders preserve exact settings and leave other fields unset",+ "rdkafka-hs.Public data contracts.builders.producer builders preserve global versus explicit topic placement",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: invalid topic timeout",+ "rdkafka-hs-integration.consumer-properties.consumer callback composition preserves registration order and identity",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.empty producer client id retains the native default",+ "rdkafka-hs-integration.public-contract.config-strings.consumer ordinary UTF8 values remain exact",+ "rdkafka-hs-integration.public-contract.config-strings.empty global key retains native unknown-key rejection"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-ConsumerProperties-setCallback",+ "symbols": [+ "Kafka.Consumer.ConsumerProperties.setCallback"+ ],+ "owner": 14,+ "behavior": "setCallback constructs/composes the documented effective settings",+ "inputs": "identity, repeated/conflicting settings, left/right precedence, empty/nonempty lists and boundary numeric/text values",+ "expected": "Exact effective map, callback/poll mode/log level; native validation preserved for invalid values",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.consumer composition.consumer program follows independent last-write model",+ "rdkafka-hs.Public properties.consumer composition.consumer identity preserves every observable field",+ "rdkafka-hs.Public properties.consumer composition.consumer association preserves writes and poll mode",+ "rdkafka-hs.Public properties.consumer composition.consumer composition appends programs",+ "rdkafka-hs.Public properties.consumer composition.unset poll mode preserves a prior explicit mode",+ "rdkafka-hs.Public properties.consumer composition.consumer helpers write exact native property names",+ "rdkafka-hs.Public data contracts.builders.semigroup defaults retain writes callbacks and subscription union",+ "rdkafka-hs.Public data contracts.builders.consumer builders preserve exact settings and leave other fields unset",+ "rdkafka-hs.Public data contracts.builders.producer builders preserve global versus explicit topic placement",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: invalid topic timeout",+ "rdkafka-hs-integration.consumer-properties.consumer callback composition preserves registration order and identity",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.empty producer client id retains the native default",+ "rdkafka-hs-integration.public-contract.config-strings.consumer ordinary UTF8 values remain exact",+ "rdkafka-hs-integration.public-contract.config-strings.empty global key retains native unknown-key rejection"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-ConsumerProperties-statisticsInterval",+ "symbols": [+ "Kafka.Consumer.ConsumerProperties.statisticsInterval"+ ],+ "owner": 14,+ "behavior": "statisticsInterval constructs/composes the documented effective settings",+ "inputs": "identity, repeated/conflicting settings, left/right precedence, empty/nonempty lists and boundary numeric/text values",+ "expected": "Exact effective map, callback/poll mode/log level; native validation preserved for invalid values",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.consumer composition.consumer program follows independent last-write model",+ "rdkafka-hs.Public properties.consumer composition.consumer identity preserves every observable field",+ "rdkafka-hs.Public properties.consumer composition.consumer association preserves writes and poll mode",+ "rdkafka-hs.Public properties.consumer composition.consumer composition appends programs",+ "rdkafka-hs.Public properties.consumer composition.unset poll mode preserves a prior explicit mode",+ "rdkafka-hs.Public properties.consumer composition.consumer helpers write exact native property names",+ "rdkafka-hs.Public data contracts.builders.semigroup defaults retain writes callbacks and subscription union",+ "rdkafka-hs.Public data contracts.builders.consumer builders preserve exact settings and leave other fields unset",+ "rdkafka-hs.Public data contracts.builders.producer builders preserve global versus explicit topic placement",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: invalid topic timeout",+ "rdkafka-hs-integration.consumer-properties.consumer callback composition preserves registration order and identity",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.empty producer client id retains the native default",+ "rdkafka-hs-integration.public-contract.config-strings.consumer ordinary UTF8 values remain exact",+ "rdkafka-hs-integration.public-contract.config-strings.empty global key retains native unknown-key rejection"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-ConsumerProperties-suppressDisconnectLogs",+ "symbols": [+ "Kafka.Consumer.ConsumerProperties.suppressDisconnectLogs"+ ],+ "owner": 14,+ "behavior": "suppressDisconnectLogs constructs/composes the documented effective settings",+ "inputs": "identity, repeated/conflicting settings, left/right precedence, empty/nonempty lists and boundary numeric/text values",+ "expected": "Exact effective map, callback/poll mode/log level; native validation preserved for invalid values",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.consumer composition.consumer program follows independent last-write model",+ "rdkafka-hs.Public properties.consumer composition.consumer identity preserves every observable field",+ "rdkafka-hs.Public properties.consumer composition.consumer association preserves writes and poll mode",+ "rdkafka-hs.Public properties.consumer composition.consumer composition appends programs",+ "rdkafka-hs.Public properties.consumer composition.unset poll mode preserves a prior explicit mode",+ "rdkafka-hs.Public properties.consumer composition.consumer helpers write exact native property names",+ "rdkafka-hs.Public data contracts.builders.semigroup defaults retain writes callbacks and subscription union",+ "rdkafka-hs.Public data contracts.builders.consumer builders preserve exact settings and leave other fields unset",+ "rdkafka-hs.Public data contracts.builders.producer builders preserve global versus explicit topic placement",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: invalid topic timeout",+ "rdkafka-hs-integration.consumer-properties.consumer callback composition preserves registration order and identity",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.empty producer client id retains the native default",+ "rdkafka-hs-integration.public-contract.config-strings.consumer ordinary UTF8 values remain exact",+ "rdkafka-hs-integration.public-contract.config-strings.empty global key retains native unknown-key rejection"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-Subscription-Subscription",+ "symbols": [+ "Kafka.Consumer.Subscription.Subscription"+ ],+ "owner": 14,+ "behavior": "Subscription constructs/composes the documented effective settings",+ "inputs": "identity, repeated/conflicting settings, left/right precedence, empty/nonempty lists and boundary numeric/text values",+ "expected": "Exact effective map, callback/poll mode/log level; native validation preserved for invalid values",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.subscription.subscription follows last-write properties and topic union",+ "rdkafka-hs.Public properties.subscription.subscription identity and association retain topics and properties",+ "rdkafka-hs.Public properties.subscription.subscription composition appends property writes",+ "rdkafka-hs.Public properties.subscription.later subscription reset and explicit properties win",+ "rdkafka-hs.Public data contracts.builders.semigroup defaults retain writes callbacks and subscription union",+ "rdkafka-hs-integration.consumer-properties.async later subscription reset reaches the native consumer",+ "rdkafka-hs-integration.consumer-properties.sync later subscription reset reaches the native consumer",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.empty producer client id retains the native default",+ "rdkafka-hs-integration.public-contract.config-strings.consumer ordinary UTF8 values remain exact",+ "rdkafka-hs-integration.public-contract.config-strings.empty global key retains native unknown-key rejection"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-Subscription-extraSubscriptionProps",+ "symbols": [+ "Kafka.Consumer.Subscription.extraSubscriptionProps"+ ],+ "owner": 14,+ "behavior": "extraSubscriptionProps constructs/composes the documented effective settings",+ "inputs": "identity, repeated/conflicting settings, left/right precedence, empty/nonempty lists and boundary numeric/text values",+ "expected": "Exact effective map, callback/poll mode/log level; native validation preserved for invalid values",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.subscription.subscription follows last-write properties and topic union",+ "rdkafka-hs.Public properties.subscription.subscription identity and association retain topics and properties",+ "rdkafka-hs.Public properties.subscription.subscription composition appends property writes",+ "rdkafka-hs.Public properties.subscription.later subscription reset and explicit properties win",+ "rdkafka-hs.Public data contracts.builders.semigroup defaults retain writes callbacks and subscription union",+ "rdkafka-hs-integration.consumer-properties.async later subscription reset reaches the native consumer",+ "rdkafka-hs-integration.consumer-properties.sync later subscription reset reaches the native consumer",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.empty producer client id retains the native default",+ "rdkafka-hs-integration.public-contract.config-strings.consumer ordinary UTF8 values remain exact",+ "rdkafka-hs-integration.public-contract.config-strings.empty global key retains native unknown-key rejection"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-Subscription-offsetReset",+ "symbols": [+ "Kafka.Consumer.Subscription.offsetReset"+ ],+ "owner": 14,+ "behavior": "offsetReset constructs/composes the documented effective settings",+ "inputs": "identity, repeated/conflicting settings, left/right precedence, empty/nonempty lists and boundary numeric/text values",+ "expected": "Exact effective map, callback/poll mode/log level; native validation preserved for invalid values",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.subscription.subscription follows last-write properties and topic union",+ "rdkafka-hs.Public properties.subscription.subscription identity and association retain topics and properties",+ "rdkafka-hs.Public properties.subscription.subscription composition appends property writes",+ "rdkafka-hs.Public properties.subscription.later subscription reset and explicit properties win",+ "rdkafka-hs.Public data contracts.builders.semigroup defaults retain writes callbacks and subscription union",+ "rdkafka-hs-integration.consumer-properties.async later subscription reset reaches the native consumer",+ "rdkafka-hs-integration.consumer-properties.sync later subscription reset reaches the native consumer",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.empty producer client id retains the native default",+ "rdkafka-hs-integration.public-contract.config-strings.consumer ordinary UTF8 values remain exact",+ "rdkafka-hs-integration.public-contract.config-strings.empty global key retains native unknown-key rejection"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-Subscription-topics",+ "symbols": [+ "Kafka.Consumer.Subscription.topics"+ ],+ "owner": 14,+ "behavior": "topics constructs/composes the documented effective settings",+ "inputs": "identity, repeated/conflicting settings, left/right precedence, empty/nonempty lists and boundary numeric/text values",+ "expected": "Exact effective map, callback/poll mode/log level; native validation preserved for invalid values",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.subscription.subscription follows last-write properties and topic union",+ "rdkafka-hs.Public properties.subscription.subscription identity and association retain topics and properties",+ "rdkafka-hs.Public properties.subscription.subscription composition appends property writes",+ "rdkafka-hs.Public properties.subscription.later subscription reset and explicit properties win",+ "rdkafka-hs.Public data contracts.builders.semigroup defaults retain writes callbacks and subscription union",+ "rdkafka-hs-integration.consumer-properties.async later subscription reset reaches the native consumer",+ "rdkafka-hs-integration.consumer-properties.sync later subscription reset reaches the native consumer",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.empty producer client id retains the native default",+ "rdkafka-hs-integration.public-contract.config-strings.consumer ordinary UTF8 values remain exact",+ "rdkafka-hs-integration.public-contract.config-strings.empty global key retains native unknown-key rejection"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-Types-ConsumerGroupId",+ "symbols": [+ "Kafka.Consumer.Types.ConsumerGroupId"+ ],+ "owner": 14,+ "behavior": "ConsumerGroupId exposes its documented constructors, record selectors and typeclass laws",+ "inputs": "Every exported constructor/member in the compiler export inventory; generated boundary and ordinary field values",+ "expected": "Construction/selection round trips; declared equality/order/show/enum/functor/traversal instances obey their documented laws",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.representations.text newtypes preserve arbitrary represented text",+ "rdkafka-hs.Public properties.representations.integer newtypes preserve signed machine boundaries",+ "rdkafka-hs.Public properties.representations.offset and milliseconds preserve signed 64-bit boundaries",+ "rdkafka-hs.Public properties.representations.timestamp constructors retain their represented boundary",+ "rdkafka-hs.Public properties.representations.system topic classification requires two initial underscores",+ "rdkafka-hs.Public properties.representations.fixed empty underscore and signed numeric boundaries",+ "rdkafka-hs.Public data contracts.representations.numeric ordering and reads agree with represented signed values",+ "rdkafka-hs.Public data contracts.representations.numeric instances preserve primitive arithmetic including boundaries",+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.consumer variants retain fields and distinguish constructors",+ "rdkafka-hs.Public data contracts.representations.producer records delivery variants and topic requests retain exact fields",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs.Public data contracts.representations.every Kafka error preserves its Exception identity and generic form"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-Types-ConsumerMessageError",+ "symbols": [+ "Kafka.Consumer.Types.ConsumerMessageError"+ ],+ "owner": 14,+ "behavior": "ConsumerMessageError exposes its documented constructors, record selectors and typeclass laws",+ "inputs": "Every exported constructor/member in the compiler export inventory; generated boundary and ordinary field values",+ "expected": "Construction/selection round trips; declared equality/order/show/enum/functor/traversal instances obey their documented laws",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.representations.text newtypes preserve arbitrary represented text",+ "rdkafka-hs.Public properties.representations.integer newtypes preserve signed machine boundaries",+ "rdkafka-hs.Public properties.representations.offset and milliseconds preserve signed 64-bit boundaries",+ "rdkafka-hs.Public properties.representations.timestamp constructors retain their represented boundary",+ "rdkafka-hs.Public properties.representations.system topic classification requires two initial underscores",+ "rdkafka-hs.Public properties.representations.fixed empty underscore and signed numeric boundaries",+ "rdkafka-hs.Public data contracts.representations.numeric ordering and reads agree with represented signed values",+ "rdkafka-hs.Public data contracts.representations.numeric instances preserve primitive arithmetic including boundaries",+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.consumer variants retain fields and distinguish constructors",+ "rdkafka-hs.Public data contracts.representations.producer records delivery variants and topic requests retain exact fields",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs.Public data contracts.representations.every Kafka error preserves its Exception identity and generic form"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-Types-ConsumerRecord",+ "symbols": [+ "Kafka.Consumer.Types.ConsumerRecord"+ ],+ "owner": 14,+ "behavior": "ConsumerRecord exposes its documented constructors, record selectors and typeclass laws",+ "inputs": "Every exported constructor/member in the compiler export inventory; generated boundary and ordinary field values",+ "expected": "Construction/selection round trips; declared equality/order/show/enum/functor/traversal instances obey their documented laws",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.records.record functor identity",+ "rdkafka-hs.Public properties.records.record functor composition",+ "rdkafka-hs.Public properties.records.record bifunctor identity and composition",+ "rdkafka-hs.Public properties.records.record mapping preserves origin timestamp and headers",+ "rdkafka-hs.Public properties.records.record traversal identity and failure preserve the applicative contract",+ "rdkafka-hs.Public properties.records.record traversal composition preserves nested effects",+ "rdkafka-hs.Public properties.records.record bitraversal visits key before value",+ "rdkafka-hs.Public properties.records.record bitraversal composition preserves nested effects",+ "rdkafka-hs.Public properties.records.record folds retain key and value order",+ "rdkafka-hs.Public properties.records.deprecated record mapping remains equivalent",+ "rdkafka-hs.Public properties.records.deprecated traversal helpers preserve successful effects",+ "rdkafka-hs.Public properties.records.deprecated traversal helpers preserve failed effects"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-Types-KafkaConsumer",+ "symbols": [+ "Kafka.Consumer.Types.KafkaConsumer"+ ],+ "owner": 14,+ "behavior": "KafkaConsumer exposes its documented constructors, record selectors and typeclass laws",+ "inputs": "Every exported constructor/member in the compiler export inventory; generated boundary and ordinary field values",+ "expected": "Construction/selection round trips; declared equality/order/show/enum/functor/traversal instances obey their documented laws",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs-integration.public-contract.deprecated-runners.async consumer closes after Returned",+ "rdkafka-hs-integration.public-contract.deprecated-runners.async consumer closes after Refused",+ "rdkafka-hs-integration.public-contract.deprecated-runners.async consumer closes after Thrown",+ "rdkafka-hs-integration.public-contract.deprecated-runners.sync consumer closes after Returned",+ "rdkafka-hs-integration.public-contract.deprecated-runners.sync consumer closes after Refused",+ "rdkafka-hs-integration.public-contract.deprecated-runners.sync consumer closes after Thrown",+ "rdkafka-hs-integration.public-contract.deprecated-runners.async consumer preserves native construction failure",+ "rdkafka-hs-integration.public-contract.deprecated-runners.async consumer preserves configuration construction failure",+ "rdkafka-hs-integration.public-contract.deprecated-runners.sync consumer preserves native construction failure",+ "rdkafka-hs-integration.public-contract.deprecated-runners.sync consumer preserves configuration construction failure"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ {+ "id": "API-Kafka-Consumer-Types-Offset",+ "symbols": [+ "Kafka.Consumer.Types.Offset"+ ],+ "owner": 14,+ "behavior": "Offset exposes its documented constructors, record selectors and typeclass laws",+ "inputs": "Every exported constructor/member in the compiler export inventory; generated boundary and ordinary field values",+ "expected": "Construction/selection round trips; declared equality/order/show/enum/functor/traversal instances obey their documented laws",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.representations.text newtypes preserve arbitrary represented text",+ "rdkafka-hs.Public properties.representations.integer newtypes preserve signed machine boundaries",+ "rdkafka-hs.Public properties.representations.offset and milliseconds preserve signed 64-bit boundaries",+ "rdkafka-hs.Public properties.representations.timestamp constructors retain their represented boundary",+ "rdkafka-hs.Public properties.representations.system topic classification requires two initial underscores",+ "rdkafka-hs.Public properties.representations.fixed empty underscore and signed numeric boundaries",+ "rdkafka-hs.Public data contracts.representations.numeric ordering and reads agree with represented signed values",+ "rdkafka-hs.Public data contracts.representations.numeric instances preserve primitive arithmetic including boundaries",+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.consumer variants retain fields and distinguish constructors",+ "rdkafka-hs.Public data contracts.representations.producer records delivery variants and topic requests retain exact fields",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs.Public data contracts.representations.every Kafka error preserves its Exception identity and generic form"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-Types-OffsetCommit",+ "symbols": [+ "Kafka.Consumer.Types.OffsetCommit"+ ],+ "owner": 14,+ "behavior": "OffsetCommit exposes its documented constructors, record selectors and typeclass laws",+ "inputs": "Every exported constructor/member in the compiler export inventory; generated boundary and ordinary field values",+ "expected": "Construction/selection round trips; declared equality/order/show/enum/functor/traversal instances obey their documented laws",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.representations.text newtypes preserve arbitrary represented text",+ "rdkafka-hs.Public properties.representations.integer newtypes preserve signed machine boundaries",+ "rdkafka-hs.Public properties.representations.offset and milliseconds preserve signed 64-bit boundaries",+ "rdkafka-hs.Public properties.representations.timestamp constructors retain their represented boundary",+ "rdkafka-hs.Public properties.representations.system topic classification requires two initial underscores",+ "rdkafka-hs.Public properties.representations.fixed empty underscore and signed numeric boundaries",+ "rdkafka-hs.Public data contracts.representations.numeric ordering and reads agree with represented signed values",+ "rdkafka-hs.Public data contracts.representations.numeric instances preserve primitive arithmetic including boundaries",+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.consumer variants retain fields and distinguish constructors",+ "rdkafka-hs.Public data contracts.representations.producer records delivery variants and topic requests retain exact fields",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs.Public data contracts.representations.every Kafka error preserves its Exception identity and generic form"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-Types-OffsetReset",+ "symbols": [+ "Kafka.Consumer.Types.OffsetReset"+ ],+ "owner": 14,+ "behavior": "OffsetReset exposes its documented constructors, record selectors and typeclass laws",+ "inputs": "Every exported constructor/member in the compiler export inventory; generated boundary and ordinary field values",+ "expected": "Construction/selection round trips; declared equality/order/show/enum/functor/traversal instances obey their documented laws",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.representations.text newtypes preserve arbitrary represented text",+ "rdkafka-hs.Public properties.representations.integer newtypes preserve signed machine boundaries",+ "rdkafka-hs.Public properties.representations.offset and milliseconds preserve signed 64-bit boundaries",+ "rdkafka-hs.Public properties.representations.timestamp constructors retain their represented boundary",+ "rdkafka-hs.Public properties.representations.system topic classification requires two initial underscores",+ "rdkafka-hs.Public properties.representations.fixed empty underscore and signed numeric boundaries",+ "rdkafka-hs.Public data contracts.representations.numeric ordering and reads agree with represented signed values",+ "rdkafka-hs.Public data contracts.representations.numeric instances preserve primitive arithmetic including boundaries",+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.consumer variants retain fields and distinguish constructors",+ "rdkafka-hs.Public data contracts.representations.producer records delivery variants and topic requests retain exact fields",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs.Public data contracts.representations.every Kafka error preserves its Exception identity and generic form"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-Types-OffsetStoreMethod",+ "symbols": [+ "Kafka.Consumer.Types.OffsetStoreMethod"+ ],+ "owner": 14,+ "behavior": "OffsetStoreMethod exposes its documented constructors, record selectors and typeclass laws",+ "inputs": "Every exported constructor/member in the compiler export inventory; generated boundary and ordinary field values",+ "expected": "Construction/selection round trips; declared equality/order/show/enum/functor/traversal instances obey their documented laws",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.representations.text newtypes preserve arbitrary represented text",+ "rdkafka-hs.Public properties.representations.integer newtypes preserve signed machine boundaries",+ "rdkafka-hs.Public properties.representations.offset and milliseconds preserve signed 64-bit boundaries",+ "rdkafka-hs.Public properties.representations.timestamp constructors retain their represented boundary",+ "rdkafka-hs.Public properties.representations.system topic classification requires two initial underscores",+ "rdkafka-hs.Public properties.representations.fixed empty underscore and signed numeric boundaries",+ "rdkafka-hs.Public data contracts.representations.numeric ordering and reads agree with represented signed values",+ "rdkafka-hs.Public data contracts.representations.numeric instances preserve primitive arithmetic including boundaries",+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.consumer variants retain fields and distinguish constructors",+ "rdkafka-hs.Public data contracts.representations.producer records delivery variants and topic requests retain exact fields",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs.Public data contracts.representations.every Kafka error preserves its Exception identity and generic form"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-Types-OffsetStoreSync",+ "symbols": [+ "Kafka.Consumer.Types.OffsetStoreSync"+ ],+ "owner": 14,+ "behavior": "OffsetStoreSync exposes its documented constructors, record selectors and typeclass laws",+ "inputs": "Every exported constructor/member in the compiler export inventory; generated boundary and ordinary field values",+ "expected": "Construction/selection round trips; declared equality/order/show/enum/functor/traversal instances obey their documented laws",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.representations.text newtypes preserve arbitrary represented text",+ "rdkafka-hs.Public properties.representations.integer newtypes preserve signed machine boundaries",+ "rdkafka-hs.Public properties.representations.offset and milliseconds preserve signed 64-bit boundaries",+ "rdkafka-hs.Public properties.representations.timestamp constructors retain their represented boundary",+ "rdkafka-hs.Public properties.representations.system topic classification requires two initial underscores",+ "rdkafka-hs.Public properties.representations.fixed empty underscore and signed numeric boundaries",+ "rdkafka-hs.Public data contracts.representations.numeric ordering and reads agree with represented signed values",+ "rdkafka-hs.Public data contracts.representations.numeric instances preserve primitive arithmetic including boundaries",+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.consumer variants retain fields and distinguish constructors",+ "rdkafka-hs.Public data contracts.representations.producer records delivery variants and topic requests retain exact fields",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs.Public data contracts.representations.every Kafka error preserves its Exception identity and generic form"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-Types-PartitionOffset",+ "symbols": [+ "Kafka.Consumer.Types.PartitionOffset"+ ],+ "owner": 14,+ "behavior": "PartitionOffset exposes its documented constructors, record selectors and typeclass laws",+ "inputs": "Every exported constructor/member in the compiler export inventory; generated boundary and ordinary field values",+ "expected": "Construction/selection round trips; declared equality/order/show/enum/functor/traversal instances obey their documented laws",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.representations.text newtypes preserve arbitrary represented text",+ "rdkafka-hs.Public properties.representations.integer newtypes preserve signed machine boundaries",+ "rdkafka-hs.Public properties.representations.offset and milliseconds preserve signed 64-bit boundaries",+ "rdkafka-hs.Public properties.representations.timestamp constructors retain their represented boundary",+ "rdkafka-hs.Public properties.representations.system topic classification requires two initial underscores",+ "rdkafka-hs.Public properties.representations.fixed empty underscore and signed numeric boundaries",+ "rdkafka-hs.Public data contracts.representations.numeric ordering and reads agree with represented signed values",+ "rdkafka-hs.Public data contracts.representations.numeric instances preserve primitive arithmetic including boundaries",+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.consumer variants retain fields and distinguish constructors",+ "rdkafka-hs.Public data contracts.representations.producer records delivery variants and topic requests retain exact fields",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs.Public data contracts.representations.every Kafka error preserves its Exception identity and generic form"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-Types-RebalanceEvent",+ "symbols": [+ "Kafka.Consumer.Types.RebalanceEvent"+ ],+ "owner": 14,+ "behavior": "RebalanceEvent exposes its documented constructors, record selectors and typeclass laws",+ "inputs": "Every exported constructor/member in the compiler export inventory; generated boundary and ordinary field values",+ "expected": "Construction/selection round trips; declared equality/order/show/enum/functor/traversal instances obey their documented laws",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.representations.text newtypes preserve arbitrary represented text",+ "rdkafka-hs.Public properties.representations.integer newtypes preserve signed machine boundaries",+ "rdkafka-hs.Public properties.representations.offset and milliseconds preserve signed 64-bit boundaries",+ "rdkafka-hs.Public properties.representations.timestamp constructors retain their represented boundary",+ "rdkafka-hs.Public properties.representations.system topic classification requires two initial underscores",+ "rdkafka-hs.Public properties.representations.fixed empty underscore and signed numeric boundaries",+ "rdkafka-hs.Public data contracts.representations.numeric ordering and reads agree with represented signed values",+ "rdkafka-hs.Public data contracts.representations.numeric instances preserve primitive arithmetic including boundaries",+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.consumer variants retain fields and distinguish constructors",+ "rdkafka-hs.Public data contracts.representations.producer records delivery variants and topic requests retain exact fields",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs.Public data contracts.representations.every Kafka error preserves its Exception identity and generic form"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-Types-SubscribedPartitions",+ "symbols": [+ "Kafka.Consumer.Types.SubscribedPartitions"+ ],+ "owner": 14,+ "behavior": "SubscribedPartitions exposes its documented constructors, record selectors and typeclass laws",+ "inputs": "Every exported constructor/member in the compiler export inventory; generated boundary and ordinary field values",+ "expected": "Construction/selection round trips; declared equality/order/show/enum/functor/traversal instances obey their documented laws",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.representations.text newtypes preserve arbitrary represented text",+ "rdkafka-hs.Public properties.representations.integer newtypes preserve signed machine boundaries",+ "rdkafka-hs.Public properties.representations.offset and milliseconds preserve signed 64-bit boundaries",+ "rdkafka-hs.Public properties.representations.timestamp constructors retain their represented boundary",+ "rdkafka-hs.Public properties.representations.system topic classification requires two initial underscores",+ "rdkafka-hs.Public properties.representations.fixed empty underscore and signed numeric boundaries",+ "rdkafka-hs.Public data contracts.representations.numeric ordering and reads agree with represented signed values",+ "rdkafka-hs.Public data contracts.representations.numeric instances preserve primitive arithmetic including boundaries",+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.consumer variants retain fields and distinguish constructors",+ "rdkafka-hs.Public data contracts.representations.producer records delivery variants and topic requests retain exact fields",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs.Public data contracts.representations.every Kafka error preserves its Exception identity and generic form"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-Types-Timestamp",+ "symbols": [+ "Kafka.Consumer.Types.Timestamp"+ ],+ "owner": 14,+ "behavior": "Timestamp exposes its documented constructors, record selectors and typeclass laws",+ "inputs": "Every exported constructor/member in the compiler export inventory; generated boundary and ordinary field values",+ "expected": "Construction/selection round trips; declared equality/order/show/enum/functor/traversal instances obey their documented laws",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.representations.text newtypes preserve arbitrary represented text",+ "rdkafka-hs.Public properties.representations.integer newtypes preserve signed machine boundaries",+ "rdkafka-hs.Public properties.representations.offset and milliseconds preserve signed 64-bit boundaries",+ "rdkafka-hs.Public properties.representations.timestamp constructors retain their represented boundary",+ "rdkafka-hs.Public properties.representations.system topic classification requires two initial underscores",+ "rdkafka-hs.Public properties.representations.fixed empty underscore and signed numeric boundaries",+ "rdkafka-hs.Public data contracts.representations.numeric ordering and reads agree with represented signed values",+ "rdkafka-hs.Public data contracts.representations.numeric instances preserve primitive arithmetic including boundaries",+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.consumer variants retain fields and distinguish constructors",+ "rdkafka-hs.Public data contracts.representations.producer records delivery variants and topic requests retain exact fields",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs.Public data contracts.representations.every Kafka error preserves its Exception identity and generic form"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-Types-TopicPartition",+ "symbols": [+ "Kafka.Consumer.Types.TopicPartition"+ ],+ "owner": 14,+ "behavior": "TopicPartition exposes its documented constructors, record selectors and typeclass laws",+ "inputs": "Every exported constructor/member in the compiler export inventory; generated boundary and ordinary field values",+ "expected": "Construction/selection round trips; declared equality/order/show/enum/functor/traversal instances obey their documented laws",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.representations.text newtypes preserve arbitrary represented text",+ "rdkafka-hs.Public properties.representations.integer newtypes preserve signed machine boundaries",+ "rdkafka-hs.Public properties.representations.offset and milliseconds preserve signed 64-bit boundaries",+ "rdkafka-hs.Public properties.representations.timestamp constructors retain their represented boundary",+ "rdkafka-hs.Public properties.representations.system topic classification requires two initial underscores",+ "rdkafka-hs.Public properties.representations.fixed empty underscore and signed numeric boundaries",+ "rdkafka-hs.Public data contracts.representations.numeric ordering and reads agree with represented signed values",+ "rdkafka-hs.Public data contracts.representations.numeric instances preserve primitive arithmetic including boundaries",+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.consumer variants retain fields and distinguish constructors",+ "rdkafka-hs.Public data contracts.representations.producer records delivery variants and topic requests retain exact fields",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs.Public data contracts.representations.every Kafka error preserves its Exception identity and generic form"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-Types-bitraverseM",+ "symbols": [+ "Kafka.Consumer.Types.bitraverseM"+ ],+ "owner": 14,+ "behavior": "bitraverseM preserves its documented pure mapping/conversion behavior",+ "inputs": "generated empty/nonempty values; every constructor case; identity/composition and effects in traversal order",+ "expected": "Exact output and typeclass laws, with replay seed for generated failures",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.records.record functor identity",+ "rdkafka-hs.Public properties.records.record functor composition",+ "rdkafka-hs.Public properties.records.record bifunctor identity and composition",+ "rdkafka-hs.Public properties.records.record mapping preserves origin timestamp and headers",+ "rdkafka-hs.Public properties.records.record traversal identity and failure preserve the applicative contract",+ "rdkafka-hs.Public properties.records.record traversal composition preserves nested effects",+ "rdkafka-hs.Public properties.records.record bitraversal visits key before value",+ "rdkafka-hs.Public properties.records.record bitraversal composition preserves nested effects",+ "rdkafka-hs.Public properties.records.record folds retain key and value order",+ "rdkafka-hs.Public properties.records.deprecated record mapping remains equivalent",+ "rdkafka-hs.Public properties.records.deprecated traversal helpers preserve successful effects",+ "rdkafka-hs.Public properties.records.deprecated traversal helpers preserve failed effects"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-Types-crMapKV",+ "symbols": [+ "Kafka.Consumer.Types.crMapKV"+ ],+ "owner": 14,+ "behavior": "crMapKV preserves its documented pure mapping/conversion behavior",+ "inputs": "generated empty/nonempty values; every constructor case; identity/composition and effects in traversal order",+ "expected": "Exact output and typeclass laws, with replay seed for generated failures",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.records.record functor identity",+ "rdkafka-hs.Public properties.records.record functor composition",+ "rdkafka-hs.Public properties.records.record bifunctor identity and composition",+ "rdkafka-hs.Public properties.records.record mapping preserves origin timestamp and headers",+ "rdkafka-hs.Public properties.records.record traversal identity and failure preserve the applicative contract",+ "rdkafka-hs.Public properties.records.record traversal composition preserves nested effects",+ "rdkafka-hs.Public properties.records.record bitraversal visits key before value",+ "rdkafka-hs.Public properties.records.record bitraversal composition preserves nested effects",+ "rdkafka-hs.Public properties.records.record folds retain key and value order",+ "rdkafka-hs.Public properties.records.deprecated record mapping remains equivalent",+ "rdkafka-hs.Public properties.records.deprecated traversal helpers preserve successful effects",+ "rdkafka-hs.Public properties.records.deprecated traversal helpers preserve failed effects"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-Types-crMapKey",+ "symbols": [+ "Kafka.Consumer.Types.crMapKey"+ ],+ "owner": 14,+ "behavior": "crMapKey preserves its documented pure mapping/conversion behavior",+ "inputs": "generated empty/nonempty values; every constructor case; identity/composition and effects in traversal order",+ "expected": "Exact output and typeclass laws, with replay seed for generated failures",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.records.record functor identity",+ "rdkafka-hs.Public properties.records.record functor composition",+ "rdkafka-hs.Public properties.records.record bifunctor identity and composition",+ "rdkafka-hs.Public properties.records.record mapping preserves origin timestamp and headers",+ "rdkafka-hs.Public properties.records.record traversal identity and failure preserve the applicative contract",+ "rdkafka-hs.Public properties.records.record traversal composition preserves nested effects",+ "rdkafka-hs.Public properties.records.record bitraversal visits key before value",+ "rdkafka-hs.Public properties.records.record bitraversal composition preserves nested effects",+ "rdkafka-hs.Public properties.records.record folds retain key and value order",+ "rdkafka-hs.Public properties.records.deprecated record mapping remains equivalent",+ "rdkafka-hs.Public properties.records.deprecated traversal helpers preserve successful effects",+ "rdkafka-hs.Public properties.records.deprecated traversal helpers preserve failed effects"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-Types-crMapValue",+ "symbols": [+ "Kafka.Consumer.Types.crMapValue"+ ],+ "owner": 14,+ "behavior": "crMapValue preserves its documented pure mapping/conversion behavior",+ "inputs": "generated empty/nonempty values; every constructor case; identity/composition and effects in traversal order",+ "expected": "Exact output and typeclass laws, with replay seed for generated failures",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.records.record functor identity",+ "rdkafka-hs.Public properties.records.record functor composition",+ "rdkafka-hs.Public properties.records.record bifunctor identity and composition",+ "rdkafka-hs.Public properties.records.record mapping preserves origin timestamp and headers",+ "rdkafka-hs.Public properties.records.record traversal identity and failure preserve the applicative contract",+ "rdkafka-hs.Public properties.records.record traversal composition preserves nested effects",+ "rdkafka-hs.Public properties.records.record bitraversal visits key before value",+ "rdkafka-hs.Public properties.records.record bitraversal composition preserves nested effects",+ "rdkafka-hs.Public properties.records.record folds retain key and value order",+ "rdkafka-hs.Public properties.records.deprecated record mapping remains equivalent",+ "rdkafka-hs.Public properties.records.deprecated traversal helpers preserve successful effects",+ "rdkafka-hs.Public properties.records.deprecated traversal helpers preserve failed effects"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-Types-sequenceFirst",+ "symbols": [+ "Kafka.Consumer.Types.sequenceFirst"+ ],+ "owner": 14,+ "behavior": "sequenceFirst preserves its documented pure mapping/conversion behavior",+ "inputs": "generated empty/nonempty values; every constructor case; identity/composition and effects in traversal order",+ "expected": "Exact output and typeclass laws, with replay seed for generated failures",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.records.record functor identity",+ "rdkafka-hs.Public properties.records.record functor composition",+ "rdkafka-hs.Public properties.records.record bifunctor identity and composition",+ "rdkafka-hs.Public properties.records.record mapping preserves origin timestamp and headers",+ "rdkafka-hs.Public properties.records.record traversal identity and failure preserve the applicative contract",+ "rdkafka-hs.Public properties.records.record traversal composition preserves nested effects",+ "rdkafka-hs.Public properties.records.record bitraversal visits key before value",+ "rdkafka-hs.Public properties.records.record bitraversal composition preserves nested effects",+ "rdkafka-hs.Public properties.records.record folds retain key and value order",+ "rdkafka-hs.Public properties.records.deprecated record mapping remains equivalent",+ "rdkafka-hs.Public properties.records.deprecated traversal helpers preserve successful effects",+ "rdkafka-hs.Public properties.records.deprecated traversal helpers preserve failed effects"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-Types-traverseFirst",+ "symbols": [+ "Kafka.Consumer.Types.traverseFirst"+ ],+ "owner": 14,+ "behavior": "traverseFirst preserves its documented pure mapping/conversion behavior",+ "inputs": "generated empty/nonempty values; every constructor case; identity/composition and effects in traversal order",+ "expected": "Exact output and typeclass laws, with replay seed for generated failures",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.records.record functor identity",+ "rdkafka-hs.Public properties.records.record functor composition",+ "rdkafka-hs.Public properties.records.record bifunctor identity and composition",+ "rdkafka-hs.Public properties.records.record mapping preserves origin timestamp and headers",+ "rdkafka-hs.Public properties.records.record traversal identity and failure preserve the applicative contract",+ "rdkafka-hs.Public properties.records.record traversal composition preserves nested effects",+ "rdkafka-hs.Public properties.records.record bitraversal visits key before value",+ "rdkafka-hs.Public properties.records.record bitraversal composition preserves nested effects",+ "rdkafka-hs.Public properties.records.record folds retain key and value order",+ "rdkafka-hs.Public properties.records.deprecated record mapping remains equivalent",+ "rdkafka-hs.Public properties.records.deprecated traversal helpers preserve successful effects",+ "rdkafka-hs.Public properties.records.deprecated traversal helpers preserve failed effects"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-Types-traverseFirstM",+ "symbols": [+ "Kafka.Consumer.Types.traverseFirstM"+ ],+ "owner": 14,+ "behavior": "traverseFirstM preserves its documented pure mapping/conversion behavior",+ "inputs": "generated empty/nonempty values; every constructor case; identity/composition and effects in traversal order",+ "expected": "Exact output and typeclass laws, with replay seed for generated failures",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.records.record functor identity",+ "rdkafka-hs.Public properties.records.record functor composition",+ "rdkafka-hs.Public properties.records.record bifunctor identity and composition",+ "rdkafka-hs.Public properties.records.record mapping preserves origin timestamp and headers",+ "rdkafka-hs.Public properties.records.record traversal identity and failure preserve the applicative contract",+ "rdkafka-hs.Public properties.records.record traversal composition preserves nested effects",+ "rdkafka-hs.Public properties.records.record bitraversal visits key before value",+ "rdkafka-hs.Public properties.records.record bitraversal composition preserves nested effects",+ "rdkafka-hs.Public properties.records.record folds retain key and value order",+ "rdkafka-hs.Public properties.records.deprecated record mapping remains equivalent",+ "rdkafka-hs.Public properties.records.deprecated traversal helpers preserve successful effects",+ "rdkafka-hs.Public properties.records.deprecated traversal helpers preserve failed effects"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-Types-traverseM",+ "symbols": [+ "Kafka.Consumer.Types.traverseM"+ ],+ "owner": 14,+ "behavior": "traverseM preserves its documented pure mapping/conversion behavior",+ "inputs": "generated empty/nonempty values; every constructor case; identity/composition and effects in traversal order",+ "expected": "Exact output and typeclass laws, with replay seed for generated failures",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.records.record functor identity",+ "rdkafka-hs.Public properties.records.record functor composition",+ "rdkafka-hs.Public properties.records.record bifunctor identity and composition",+ "rdkafka-hs.Public properties.records.record mapping preserves origin timestamp and headers",+ "rdkafka-hs.Public properties.records.record traversal identity and failure preserve the applicative contract",+ "rdkafka-hs.Public properties.records.record traversal composition preserves nested effects",+ "rdkafka-hs.Public properties.records.record bitraversal visits key before value",+ "rdkafka-hs.Public properties.records.record bitraversal composition preserves nested effects",+ "rdkafka-hs.Public properties.records.record folds retain key and value order",+ "rdkafka-hs.Public properties.records.deprecated record mapping remains equivalent",+ "rdkafka-hs.Public properties.records.deprecated traversal helpers preserve successful effects",+ "rdkafka-hs.Public properties.records.deprecated traversal helpers preserve failed effects"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-assign",+ "symbols": [+ "Kafka.Consumer.assign"+ ],+ "owner": 16,+ "behavior": "Subscription/manual assignment replaces the exact partition set and preserves records",+ "inputs": "empty, one/multiple partitions, invalid partition, repeated/reassignment",+ "expected": "Exact assignment and no record loss/duplication",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs-integration.public-contract.consumer-state.async.assignment-replacement",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-reassignment-replaces-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-unassignment-discards-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.unknown-assignment-reports-through-error-callback-and-recovers",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.assignment-replacement",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-reassignment-replaces-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-unassignment-discards-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.unknown-assignment-reports-through-error-callback-and-recovers",+ "rdkafka-hs-integration.public-contract.input-boundaries.async assign rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async assign rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async assign rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync assign rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync assign rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync assign rejects underflow-partition"+ ],+ "status": "tested",+ "previous_owner": 14,+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ {+ "id": "API-Kafka-Consumer-assignment",+ "symbols": [+ "Kafka.Consumer.assignment"+ ],+ "owner": 14,+ "behavior": "Report exact current assignment",+ "inputs": "unassigned, subscribed, manually assigned, reassigned",+ "expected": "Exact topic-to-partition mapping",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs-integration.public-contract.consumer-state.async.assignment-replacement",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.assignment-replacement",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should return assignment",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should return assignment",+ "rdkafka-hs-integration.public-contract.consumer-state.async.empty-requests-preserve-empty-assignment",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.empty-requests-preserve-empty-assignment"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-assignmentLost",+ "symbols": [+ "Kafka.Consumer.assignmentLost"+ ],+ "owner": 18,+ "behavior": "Report group ownership loss",+ "inputs": "healthy assignment plus actual group eviction/loss; observe the True value in RebalanceBeforeRevoke before native unassignment clears it",+ "expected": "False when valid; True on lost assignment",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "broker-failure.eager async handoff pause seek eviction and complete outage recover exact offsets",+ "broker-failure.eager sync handoff pause seek eviction and complete outage recover exact offsets",+ "broker-failure.cooperative async handoff pause seek eviction and complete outage recover exact offsets",+ "broker-failure.cooperative sync handoff pause seek eviction and complete outage recover exact offsets",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.assignment is not lost",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.assignment is not lost"+ ],+ "status": "tested",+ "rationale": "EP-14 verifies healthy False results. The accepted MasterPlan and EP-15 M1 own actual group eviction/handoff behavior; static-member fatal fencing alone does not guarantee an assignment-loss callback. The True case remains open under EP-15.",+ "previous_owner": 15,+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence": [+ "docs/testing/coverage-evidence.json",+ "docs/testing/compatibility-matrix.json"+ ]+ },+ {+ "id": "API-Kafka-Consumer-commitAllOffsets",+ "symbols": [+ "Kafka.Consumer.commitAllOffsets"+ ],+ "owner": 16,+ "behavior": "Commit consumed/stored offsets according to mode",+ "inputs": "no offsets, multiple records/partitions, sync/async, broker failure",+ "expected": "Exact committed offsets and reported errors",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs-integration.public-contract.consumer-commit.async commit modes preserve native flags callback offsets and broker state",+ "rdkafka-hs-integration.public-contract.consumer-commit.async committed query preserves an unavailable coordinator timeout",+ "rdkafka-hs-integration.public-contract.consumer-commit.async empty commit requests preserve no-offset callbacks",+ "rdkafka-hs-integration.public-contract.consumer-commit.async message and stored commits preserve unrelated partition offsets",+ "rdkafka-hs-integration.public-contract.consumer-commit.async mixed broker commit failures preserve successful offsets",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync commit modes preserve native flags callback offsets and broker state",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync committed query preserves an unavailable coordinator timeout",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync empty commit requests preserve no-offset callbacks",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync message and stored commits preserve unrelated partition offsets",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync mixed broker commit failures preserve successful offsets",+ "broker-failure.eager async handoff pause seek eviction and complete outage recover exact offsets",+ "broker-failure.eager sync handoff pause seek eviction and complete outage recover exact offsets",+ "broker-failure.cooperative async handoff pause seek eviction and complete outage recover exact offsets",+ "broker-failure.cooperative sync handoff pause seek eviction and complete outage recover exact offsets"+ ],+ "status": "tested",+ "previous_owner": 14,+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence": [+ "docs/testing/coverage-evidence.json",+ "docs/testing/compatibility-matrix.json"+ ]+ },+ {+ "id": "API-Kafka-Consumer-commitOffsetMessage",+ "symbols": [+ "Kafka.Consumer.commitOffsetMessage"+ ],+ "owner": 16,+ "behavior": "Commit one record at its next offset",+ "inputs": "multiple partitions and sync/async",+ "expected": "Only requested record partition advances to offset + 1",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs-integration.public-contract.consumer-commit.async commit modes preserve native flags callback offsets and broker state",+ "rdkafka-hs-integration.public-contract.consumer-commit.async committed query preserves an unavailable coordinator timeout",+ "rdkafka-hs-integration.public-contract.consumer-commit.async empty commit requests preserve no-offset callbacks",+ "rdkafka-hs-integration.public-contract.consumer-commit.async message and stored commits preserve unrelated partition offsets",+ "rdkafka-hs-integration.public-contract.consumer-commit.async mixed broker commit failures preserve successful offsets",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync commit modes preserve native flags callback offsets and broker state",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync committed query preserves an unavailable coordinator timeout",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync empty commit requests preserve no-offset callbacks",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync message and stored commits preserve unrelated partition offsets",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync mixed broker commit failures preserve successful offsets",+ "rdkafka-hs-integration.public-contract.input-boundaries.async commit-message rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async commit-message rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async commit-message rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync commit-message rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync commit-message rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync commit-message rejects underflow-partition"+ ],+ "status": "tested",+ "previous_owner": 14,+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ {+ "id": "API-Kafka-Consumer-commitPartitionsOffsets",+ "symbols": [+ "Kafka.Consumer.commitPartitionsOffsets"+ ],+ "owner": 14,+ "behavior": "Commit an explicit set of offsets",+ "inputs": "empty, valid, invalid and mixed partitions; sync/async",+ "expected": "Exact committed values or surfaced failure",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs-integration.public-contract.consumer-commit.async commit modes preserve native flags callback offsets and broker state",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync commit modes preserve native flags callback offsets and broker state",+ "rdkafka-hs-integration.public-contract.consumer-commit.async empty commit requests preserve no-offset callbacks",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync empty commit requests preserve no-offset callbacks",+ "rdkafka-hs-integration.public-contract.consumer-commit.async mixed broker commit failures preserve successful offsets",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync mixed broker commit failures preserve successful offsets",+ "rdkafka-hs-integration.public-contract.consumer-commit.async committed query preserves an unavailable coordinator timeout",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync committed query preserves an unavailable coordinator timeout"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ {+ "id": "API-Kafka-Consumer-committed",+ "symbols": [+ "Kafka.Consumer.committed"+ ],+ "owner": 14,+ "behavior": "Fetch group committed offsets",+ "inputs": "empty, stored, missing offsets, unavailable broker",+ "expected": "Exact per-partition committed offset/error",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs-integration.public-contract.consumer-commit.async commit modes preserve native flags callback offsets and broker state",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync commit modes preserve native flags callback offsets and broker state",+ "rdkafka-hs-integration.public-contract.consumer-commit.async empty commit requests preserve no-offset callbacks",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync empty commit requests preserve no-offset callbacks",+ "rdkafka-hs-integration.public-contract.consumer-commit.async mixed broker commit failures preserve successful offsets",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync mixed broker commit failures preserve successful offsets",+ "rdkafka-hs-integration.public-contract.consumer-commit.async committed query preserves an unavailable coordinator timeout",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync committed query preserves an unavailable coordinator timeout"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ {+ "id": "API-Kafka-Consumer-consumerClosed",+ "symbols": [+ "Kafka.Consumer.consumerClosed"+ ],+ "owner": 14,+ "behavior": "Observe close state",+ "inputs": "new, closed, destroyed and repeated close",+ "expected": "False before close; True afterwards",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs-integration.lifecycle.consumerClosed is False until closeConsumer",+ "rdkafka-hs-integration.public-contract.runtime-contract.deprecated sync runner closes after an exact record"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-consumerFatalError",+ "symbols": [+ "Kafka.Consumer.consumerFatalError"+ ],+ "owner": 14,+ "behavior": "Observe fatal error without manufacturing one",+ "inputs": "healthy and broker-fenced consumers",+ "expected": "Nothing on healthy consumer; exact fatal error on fenced client",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs-integration.public-contract.fatal.async",+ "rdkafka-hs-integration.public-contract.fatal.sync",+ "rdkafka-hs-integration.public-contract.deprecated-runners.async consumer closes after Returned",+ "rdkafka-hs-integration.public-contract.deprecated-runners.async consumer closes after Refused",+ "rdkafka-hs-integration.public-contract.deprecated-runners.async consumer closes after Thrown",+ "rdkafka-hs-integration.public-contract.deprecated-runners.sync consumer closes after Returned",+ "rdkafka-hs-integration.public-contract.deprecated-runners.sync consumer closes after Refused",+ "rdkafka-hs-integration.public-contract.deprecated-runners.sync consumer closes after Thrown",+ "rdkafka-hs-integration.public-contract.deprecated-runners.async consumer preserves native construction failure",+ "rdkafka-hs-integration.public-contract.deprecated-runners.async consumer preserves configuration construction failure",+ "rdkafka-hs-integration.public-contract.deprecated-runners.sync consumer preserves native construction failure",+ "rdkafka-hs-integration.public-contract.deprecated-runners.sync consumer preserves configuration construction failure"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ {+ "id": "API-Kafka-Consumer-pausePartitions",+ "symbols": [+ "Kafka.Consumer.pausePartitions"+ ],+ "owner": 14,+ "behavior": "Pause only requested partitions",+ "inputs": "empty, valid, invalid and mixed; repeated pause/resume",+ "expected": "Paused partitions yield no records; others continue; errors surfaced",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs-integration.public-contract.messages.callback-event polling cancellation releases a returned message",+ "rdkafka-hs-integration.public-contract.messages.callback buffer preserves attributed header failure",+ "rdkafka-hs-integration.public-contract.messages.callback buffer preserves plain header failure",+ "rdkafka-hs-integration.public-contract.consumer-state.async.assignment-replacement",+ "rdkafka-hs-integration.public-contract.consumer-state.async.empty-requests-preserve-empty-assignment",+ "rdkafka-hs-integration.public-contract.consumer-state.async.unknown-position-is-invalid-without-native-error",+ "rdkafka-hs-integration.public-contract.consumer-state.async.pause-resume-preserves-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-event-poll-preserves-application-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-seek-replaces-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-reassignment-replaces-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-pause-defers-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-legacy-seek-replaces-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-legacy-partial-seek-keeps-success",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-paused-partition-does-not-block-another",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-unassignment-discards-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.pausing-one-partition-leaves-the-other-running",+ "rdkafka-hs-integration.public-contract.consumer-state.async.pause-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.async.resume-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.async.store-commit-next-offset",+ "rdkafka-hs-integration.public-contract.consumer-state.async.store-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.async.position-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.async.deprecated-seek-exact-repeated-replay",+ "rdkafka-hs-integration.public-contract.consumer-state.async.explicit-subscription-overrides-global-reset",+ "rdkafka-hs-integration.public-contract.consumer-state.async.regex-subscription-selects-run-owned-topic",+ "rdkafka-hs-integration.public-contract.consumer-state.async.global-topic-setting-survives-empty-subscription-properties",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.assignment-replacement",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.empty-requests-preserve-empty-assignment",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.unknown-position-is-invalid-without-native-error",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.pause-resume-preserves-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-event-poll-preserves-application-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-seek-replaces-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-reassignment-replaces-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-pause-defers-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-legacy-seek-replaces-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-legacy-partial-seek-keeps-success",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-paused-partition-does-not-block-another",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-unassignment-discards-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.pausing-one-partition-leaves-the-other-running",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.pause-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.resume-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.store-commit-next-offset",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.store-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.position-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.deprecated-seek-exact-repeated-replay",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.explicit-subscription-overrides-global-reset",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.regex-subscription-selects-run-owned-topic",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.global-topic-setting-survives-empty-subscription-properties",+ "rdkafka-hs-integration.public-contract.consumer-state.sync-buffer-fields-native-time",+ "rdkafka-hs-integration.public-contract.consumer-state.sync-buffer-fields-no-time",+ "rdkafka-hs-integration.public-contract.consumer-state.sync-buffer-fields-append-time",+ "rdkafka-hs-integration.public-contract.consumer-state.sync-buffer-fields-create-time",+ "rdkafka-hs-integration.public-contract.runtime-contract.RTS capability is observed by async construction",+ "rdkafka-hs-integration.public-contract.runtime-contract.explicit async construction checks the runtime",+ "rdkafka-hs-integration.public-contract.runtime-contract.sync subscription delivers an exact record",+ "rdkafka-hs-integration.public-contract.runtime-contract.deprecated sync runner closes after an exact record"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-pollConsumerEvents",+ "symbols": [+ "Kafka.Consumer.pollConsumerEvents"+ ],+ "owner": 14,+ "behavior": "Drive callbacks without dropping application records",+ "inputs": "zero/finite/infinite timeout; pending callbacks/records",+ "expected": "Callbacks served in sync mode; record destination retains every record",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs-integration.public-contract.messages.callback-event polling cancellation releases a returned message",+ "rdkafka-hs-integration.public-contract.messages.callback buffer preserves attributed header failure",+ "rdkafka-hs-integration.public-contract.messages.callback buffer preserves plain header failure",+ "rdkafka-hs-integration.public-contract.consumer-state.async.assignment-replacement",+ "rdkafka-hs-integration.public-contract.consumer-state.async.empty-requests-preserve-empty-assignment",+ "rdkafka-hs-integration.public-contract.consumer-state.async.unknown-position-is-invalid-without-native-error",+ "rdkafka-hs-integration.public-contract.consumer-state.async.pause-resume-preserves-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-event-poll-preserves-application-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-seek-replaces-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-reassignment-replaces-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-pause-defers-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-legacy-seek-replaces-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-legacy-partial-seek-keeps-success",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-paused-partition-does-not-block-another",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-unassignment-discards-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.pausing-one-partition-leaves-the-other-running",+ "rdkafka-hs-integration.public-contract.consumer-state.async.pause-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.async.resume-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.async.store-commit-next-offset",+ "rdkafka-hs-integration.public-contract.consumer-state.async.store-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.async.position-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.async.deprecated-seek-exact-repeated-replay",+ "rdkafka-hs-integration.public-contract.consumer-state.async.explicit-subscription-overrides-global-reset",+ "rdkafka-hs-integration.public-contract.consumer-state.async.regex-subscription-selects-run-owned-topic",+ "rdkafka-hs-integration.public-contract.consumer-state.async.global-topic-setting-survives-empty-subscription-properties",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.assignment-replacement",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.empty-requests-preserve-empty-assignment",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.unknown-position-is-invalid-without-native-error",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.pause-resume-preserves-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-event-poll-preserves-application-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-seek-replaces-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-reassignment-replaces-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-pause-defers-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-legacy-seek-replaces-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-legacy-partial-seek-keeps-success",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-paused-partition-does-not-block-another",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-unassignment-discards-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.pausing-one-partition-leaves-the-other-running",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.pause-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.resume-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.store-commit-next-offset",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.store-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.position-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.deprecated-seek-exact-repeated-replay",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.explicit-subscription-overrides-global-reset",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.regex-subscription-selects-run-owned-topic",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.global-topic-setting-survives-empty-subscription-properties",+ "rdkafka-hs-integration.public-contract.consumer-state.sync-buffer-fields-native-time",+ "rdkafka-hs-integration.public-contract.consumer-state.sync-buffer-fields-no-time",+ "rdkafka-hs-integration.public-contract.consumer-state.sync-buffer-fields-append-time",+ "rdkafka-hs-integration.public-contract.consumer-state.sync-buffer-fields-create-time",+ "rdkafka-hs-integration.public-contract.runtime-contract.RTS capability is observed by async construction",+ "rdkafka-hs-integration.public-contract.runtime-contract.explicit async construction checks the runtime",+ "rdkafka-hs-integration.public-contract.runtime-contract.sync subscription delivers an exact record",+ "rdkafka-hs-integration.public-contract.runtime-contract.deprecated sync runner closes after an exact record"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-pollMessage",+ "symbols": [+ "Kafka.Consumer.pollMessage"+ ],+ "owner": 16,+ "behavior": "Return complete records and distinguish idle/error outcomes",+ "inputs": "null key/value, headers, timestamp, offset, EOF, timeout, fatal and broker failure",+ "expected": "Exact topic/partition/offset/key/value/header/time; errors preserved",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs-integration.broker.Headers wire order.pollMessage async.a single header round-trips",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessage async.distinct names keep wire order",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessage async.identical repeated pairs are not deduplicated",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessage async.interleaved duplicate names keep wire order and last values",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessage async.no headers decode as an empty list",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessage sync.a single header round-trips",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessage sync.distinct names keep wire order",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessage sync.identical repeated pairs are not deduplicated",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessage sync.interleaved duplicate names keep wire order and last values",+ "rdkafka-hs-integration.broker.Headers wire order.pollMessage sync.no headers decode as an empty list",+ "rdkafka-hs-integration.public-contract.consumer-state.sync-buffer-fields-append-time",+ "rdkafka-hs-integration.public-contract.consumer-state.sync-buffer-fields-create-time",+ "rdkafka-hs-integration.public-contract.consumer-state.sync-buffer-fields-native-time",+ "rdkafka-hs-integration.public-contract.consumer-state.sync-buffer-fields-no-time",+ "rdkafka-hs-integration.public-contract.fatal.async",+ "rdkafka-hs-integration.public-contract.fatal.sync",+ "broker-failure.eager async handoff pause seek eviction and complete outage recover exact offsets",+ "broker-failure.eager sync handoff pause seek eviction and complete outage recover exact offsets",+ "broker-failure.cooperative async handoff pause seek eviction and complete outage recover exact offsets",+ "broker-failure.cooperative sync handoff pause seek eviction and complete outage recover exact offsets"+ ],+ "status": "tested",+ "previous_owner": 14,+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence": [+ "docs/testing/coverage-evidence.json",+ "docs/testing/compatibility-matrix.json"+ ]+ },+ {+ "id": "API-Kafka-Consumer-pollMessageAttributed",+ "symbols": [+ "Kafka.Consumer.pollMessageAttributed"+ ],+ "owner": 16,+ "behavior": "Return record or error with native attribution",+ "inputs": "ordinary record; timeout; partition EOF; fatal/partition error",+ "expected": "Attribution fields preserved where provided and absent otherwise",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs-integration.broker.attributed.async",+ "rdkafka-hs-integration.broker.attributed.sync",+ "rdkafka-hs-integration.public-contract.messages.async attributed error preserves independently absent offset",+ "rdkafka-hs-integration.public-contract.messages.async attributed error preserves independently absent partition",+ "rdkafka-hs-integration.public-contract.messages.async attributed error preserves independently absent partition-and-offset",+ "rdkafka-hs-integration.public-contract.messages.async header failure preserves the polled record origin",+ "rdkafka-hs-integration.public-contract.messages.callback buffer preserves attributed header failure",+ "rdkafka-hs-integration.public-contract.messages.sync attributed error preserves independently absent offset",+ "rdkafka-hs-integration.public-contract.messages.sync attributed error preserves independently absent partition",+ "rdkafka-hs-integration.public-contract.messages.sync attributed error preserves independently absent partition-and-offset",+ "rdkafka-hs-integration.public-contract.messages.sync header failure preserves the polled record origin",+ "rdkafka-hs-integration.public-contract.messages.originless callback error survives seek filtering and a paused partition"+ ],+ "status": "tested",+ "previous_owner": 14,+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence": [+ "docs/testing/coverage-evidence.json",+ "docs/testing/compatibility-matrix.json"+ ]+ },+ {+ "id": "API-Kafka-Consumer-pollMessageBatch",+ "symbols": [+ "Kafka.Consumer.pollMessageBatch"+ ],+ "owner": 16,+ "behavior": "Return at most requested complete records",+ "inputs": "zero/one/large batch, empty topic, partial batch, partition/error events",+ "expected": "Exact count, identity, order and per-element errors",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs-integration.public-contract.messages.batch conversion releases every returned native message",+ "rdkafka-hs-integration.public-contract.messages.native message counter detects a retained final object",+ "rdkafka-hs-integration.public-contract.messages.batch decoder exception releases unprocessed messages",+ "rdkafka-hs-integration.public-contract.messages.batch native header errors remain errors while later records are released",+ "rdkafka-hs-integration.public-contract.messages.batch cancellation at native return releases every acquired message",+ "rdkafka-hs-integration.public-contract.messages.batch cancellation at middle conversion releases every acquired message",+ "rdkafka-hs-integration.public-contract.messages.async single cancellation at native return releases its native message",+ "rdkafka-hs-integration.public-contract.messages.async single cancellation at inside conversion releases its native message",+ "rdkafka-hs-integration.public-contract.messages.sync single cancellation at native return releases its native message",+ "rdkafka-hs-integration.public-contract.messages.sync single cancellation at inside conversion releases its native message",+ "rdkafka-hs-integration.public-contract.messages.async header failure preserves the polled record origin",+ "rdkafka-hs-integration.public-contract.messages.sync header failure preserves the polled record origin",+ "rdkafka-hs-integration.public-contract.messages.async plain polling surfaces native header failure",+ "rdkafka-hs-integration.public-contract.messages.sync plain polling surfaces native header failure",+ "rdkafka-hs-integration.public-contract.messages.async attributed error preserves independently absent partition-and-offset",+ "rdkafka-hs-integration.public-contract.messages.async attributed error preserves independently absent offset",+ "rdkafka-hs-integration.public-contract.messages.async attributed error preserves independently absent partition",+ "rdkafka-hs-integration.public-contract.messages.sync attributed error preserves independently absent partition-and-offset",+ "rdkafka-hs-integration.public-contract.messages.sync attributed error preserves independently absent offset",+ "rdkafka-hs-integration.public-contract.messages.sync attributed error preserves independently absent partition",+ "rdkafka-hs-integration.public-contract.messages.callback-event polling cancellation releases a returned message",+ "rdkafka-hs-integration.public-contract.messages.callback buffer preserves attributed header failure",+ "rdkafka-hs-integration.public-contract.messages.callback buffer preserves plain header failure",+ "rdkafka-hs-integration.public-contract.messages.zero batch size leaves the queued records available",+ "rdkafka-hs-integration.public-contract.messages.unsupported sync batch does not discard a record",+ "rdkafka-hs-integration.public-contract.messages.signed native batch failure preserves its error and queued data",+ "rdkafka-hs-integration.public-contract.messages.infinite batch timeout returns available records",+ "rdkafka-hs-integration.public-contract.messages.batch capacity 1 preserves complete ordered records across partial batches",+ "rdkafka-hs-integration.public-contract.messages.batch capacity 2 preserves complete ordered records across partial batches",+ "rdkafka-hs-integration.public-contract.messages.batch capacity 5 preserves complete ordered records across partial batches",+ "rdkafka-hs-integration.public-contract.messages.invalid batch array size is rejected before native acquisition: -1",+ "rdkafka-hs-integration.public-contract.messages.invalid batch array size is rejected before native acquisition: -9223372036854775808",+ "rdkafka-hs-integration.public-contract.messages.invalid batch array size is rejected before native acquisition: 9223372036854775807",+ "rdkafka-hs-integration.public-contract.messages.empty batch respects timeout 0",+ "rdkafka-hs-integration.public-contract.messages.empty batch respects timeout 100",+ "rdkafka-hs-integration.public-contract.messages.batch preserves complete records followed by exact partition EOF and idle timeout"+ ],+ "status": "tested",+ "previous_owner": 14,+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence": [+ "docs/testing/coverage-evidence.json",+ "docs/testing/compatibility-matrix.json"+ ]+ },+ {+ "id": "API-Kafka-Consumer-position",+ "symbols": [+ "Kafka.Consumer.position"+ ],+ "owner": 16,+ "behavior": "Fetch next consume position",+ "inputs": "before/after poll, explicit seek, missing partition",+ "expected": "Exact next offsets and error conventions",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs-integration.public-contract.consumer-state.async.pause-resume-preserves-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.position-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.async.representable-partition-boundaries-keep-native-query-semantics",+ "rdkafka-hs-integration.public-contract.consumer-state.async.store-commit-next-offset",+ "rdkafka-hs-integration.public-contract.consumer-state.async.unknown-position-is-invalid-without-native-error",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.pause-resume-preserves-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.position-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.representable-partition-boundaries-keep-native-query-semantics",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.store-commit-next-offset",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.unknown-position-is-invalid-without-native-error",+ "rdkafka-hs-integration.public-contract.input-boundaries.async position rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async position rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async position rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync position rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync position rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync position rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-seek-replaces-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-seek-replaces-pending-records"+ ],+ "status": "tested",+ "previous_owner": 14,+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ {+ "id": "API-Kafka-Consumer-resumePartitions",+ "symbols": [+ "Kafka.Consumer.resumePartitions"+ ],+ "owner": 14,+ "behavior": "Resume paused partitions without offset loss",+ "inputs": "paused/unpaused, empty, invalid, repeated calls",+ "expected": "Exact subsequent record sequence and errors",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs-integration.public-contract.messages.callback-event polling cancellation releases a returned message",+ "rdkafka-hs-integration.public-contract.messages.callback buffer preserves attributed header failure",+ "rdkafka-hs-integration.public-contract.messages.callback buffer preserves plain header failure",+ "rdkafka-hs-integration.public-contract.consumer-state.async.assignment-replacement",+ "rdkafka-hs-integration.public-contract.consumer-state.async.empty-requests-preserve-empty-assignment",+ "rdkafka-hs-integration.public-contract.consumer-state.async.unknown-position-is-invalid-without-native-error",+ "rdkafka-hs-integration.public-contract.consumer-state.async.pause-resume-preserves-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-event-poll-preserves-application-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-seek-replaces-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-reassignment-replaces-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-pause-defers-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-legacy-seek-replaces-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-legacy-partial-seek-keeps-success",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-paused-partition-does-not-block-another",+ "rdkafka-hs-integration.public-contract.consumer-state.async.callback-buffer-unassignment-discards-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.async.pausing-one-partition-leaves-the-other-running",+ "rdkafka-hs-integration.public-contract.consumer-state.async.pause-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.async.resume-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.async.store-commit-next-offset",+ "rdkafka-hs-integration.public-contract.consumer-state.async.store-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.async.position-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.async.deprecated-seek-exact-repeated-replay",+ "rdkafka-hs-integration.public-contract.consumer-state.async.explicit-subscription-overrides-global-reset",+ "rdkafka-hs-integration.public-contract.consumer-state.async.regex-subscription-selects-run-owned-topic",+ "rdkafka-hs-integration.public-contract.consumer-state.async.global-topic-setting-survives-empty-subscription-properties",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.assignment-replacement",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.empty-requests-preserve-empty-assignment",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.unknown-position-is-invalid-without-native-error",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.pause-resume-preserves-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-event-poll-preserves-application-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-seek-replaces-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-reassignment-replaces-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-pause-defers-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-legacy-seek-replaces-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-legacy-partial-seek-keeps-success",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-paused-partition-does-not-block-another",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.callback-buffer-unassignment-discards-pending-records",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.pausing-one-partition-leaves-the-other-running",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.pause-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.resume-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.store-commit-next-offset",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.store-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.position-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.deprecated-seek-exact-repeated-replay",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.explicit-subscription-overrides-global-reset",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.regex-subscription-selects-run-owned-topic",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.global-topic-setting-survives-empty-subscription-properties",+ "rdkafka-hs-integration.public-contract.consumer-state.sync-buffer-fields-native-time",+ "rdkafka-hs-integration.public-contract.consumer-state.sync-buffer-fields-no-time",+ "rdkafka-hs-integration.public-contract.consumer-state.sync-buffer-fields-append-time",+ "rdkafka-hs-integration.public-contract.consumer-state.sync-buffer-fields-create-time",+ "rdkafka-hs-integration.public-contract.runtime-contract.RTS capability is observed by async construction",+ "rdkafka-hs-integration.public-contract.runtime-contract.explicit async construction checks the runtime",+ "rdkafka-hs-integration.public-contract.runtime-contract.sync subscription delivers an exact record",+ "rdkafka-hs-integration.public-contract.runtime-contract.deprecated sync runner closes after an exact record"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-rewindConsumer",+ "symbols": [+ "Kafka.Consumer.rewindConsumer"+ ],+ "owner": 10,+ "behavior": "Rewind the current assignment to its last committed next offsets",+ "inputs": "no assignment; missing/known committed offsets; lookup failure; assignment changes before seek; seek failure",+ "expected": "No assignment is a no-op; failures propagate; successful replay begins at the exact committed next offset",+ "modes": "async and sync callback modes",+ "ownership": "One native list ForeignPtr retains elements through call and error inspection; overall error object is destroyed once, including decoder exceptions",+ "tests": [+ "rdkafka-hs-integration.seek-partitions.async.rewind without assignment does not seek",+ "rdkafka-hs-integration.seek-partitions.async.rewind assignment failure prevents seek",+ "rdkafka-hs-integration.seek-partitions.async.rewind without committed offset starts at beginning",+ "rdkafka-hs-integration.seek-partitions.async.rewind uses committed next offset exactly",+ "rdkafka-hs-integration.seek-partitions.async.rewind message commit resumes after committed message",+ "rdkafka-hs-integration.seek-partitions.async.rewind lookup failure prevents seek",+ "rdkafka-hs-integration.seek-partitions.async.rewind propagates assignment change after committed lookup",+ "rdkafka-hs-integration.seek-partitions.sync.rewind without assignment does not seek",+ "rdkafka-hs-integration.seek-partitions.sync.rewind assignment failure prevents seek",+ "rdkafka-hs-integration.seek-partitions.sync.rewind without committed offset starts at beginning",+ "rdkafka-hs-integration.seek-partitions.sync.rewind uses committed next offset exactly",+ "rdkafka-hs-integration.seek-partitions.sync.rewind message commit resumes after committed message",+ "rdkafka-hs-integration.seek-partitions.sync.rewind lookup failure prevents seek",+ "rdkafka-hs-integration.seek-partitions.sync.rewind propagates assignment change after committed lookup"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence": "docs/testing/seek-evidence.json",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Consumer-runConsumer",+ "symbols": [+ "Kafka.Consumer.runConsumer"+ ],+ "owner": 14,+ "behavior": "Deprecated wrapper preserves callback result and closes after success/failure",+ "inputs": "valid/invalid config, callback exception",+ "expected": "Same construction result and cleanup as newConsumer/closeConsumer",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs-integration.public-contract.deprecated-runners.async consumer closes after Returned",+ "rdkafka-hs-integration.public-contract.deprecated-runners.async consumer closes after Refused",+ "rdkafka-hs-integration.public-contract.deprecated-runners.async consumer closes after Thrown",+ "rdkafka-hs-integration.public-contract.deprecated-runners.sync consumer closes after Returned",+ "rdkafka-hs-integration.public-contract.deprecated-runners.sync consumer closes after Refused",+ "rdkafka-hs-integration.public-contract.deprecated-runners.sync consumer closes after Thrown",+ "rdkafka-hs-integration.public-contract.deprecated-runners.async consumer preserves native construction failure",+ "rdkafka-hs-integration.public-contract.deprecated-runners.async consumer preserves configuration construction failure",+ "rdkafka-hs-integration.public-contract.deprecated-runners.sync consumer preserves native construction failure",+ "rdkafka-hs-integration.public-contract.deprecated-runners.sync consumer preserves configuration construction failure"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ {+ "id": "API-Kafka-Consumer-setConsumerQueueIOEvent",+ "symbols": [+ "Kafka.Consumer.setConsumerQueueIOEvent"+ ],+ "owner": 16,+ "behavior": "Notify readable queue transitions and disable safely",+ "inputs": "pending-before-enable, empty-to-nonempty, rearm, disable, close and destroy",+ "expected": "Descriptor receives expected wakeup; queued records preserved; no notification after disable",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs-integration.public-contract.queue event.async.binary payloads retain every byte and empty payloads preserve records",+ "rdkafka-hs-integration.public-contract.queue event.async.close stops notifications and keeps caller descriptors open",+ "rdkafka-hs-integration.public-contract.queue event.async.destroy stops notifications and keeps caller descriptors open",+ "rdkafka-hs-integration.public-contract.queue event.async.finds records queued before it was enabled, then rearms",+ "rdkafka-hs-integration.public-contract.queue event.async.native record errors are never treated as idle",+ "rdkafka-hs-integration.public-contract.queue event.async.one wake-up covers several records, then rearms",+ "rdkafka-hs-integration.public-contract.queue event.async.wakes an idle consumer and stays quiet once disabled",+ "rdkafka-hs-integration.public-contract.queue event.empty pipes are idle but invalid descriptor errors are preserved",+ "rdkafka-hs-integration.public-contract.queue event.sync.binary payloads retain every byte and empty payloads preserve records",+ "rdkafka-hs-integration.public-contract.queue event.sync.close stops notifications and keeps caller descriptors open",+ "rdkafka-hs-integration.public-contract.queue event.sync.destroy stops notifications and keeps caller descriptors open",+ "rdkafka-hs-integration.public-contract.queue event.sync.finds records queued before it was enabled, then rearms",+ "rdkafka-hs-integration.public-contract.queue event.sync.native record errors are never treated as idle",+ "rdkafka-hs-integration.public-contract.queue event.sync.one wake-up covers several records, then rearms",+ "rdkafka-hs-integration.public-contract.queue event.sync.wakes an idle consumer and stays quiet once disabled"+ ],+ "status": "tested",+ "previous_owner": 14,+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ {+ "id": "API-Kafka-Consumer-setSaslCredentials",+ "symbols": [+ "Kafka.Consumer.setSaslCredentials"+ ],+ "owner": 19,+ "behavior": "Replace credentials used by live authentication",+ "inputs": "valid, invalid and replacement credentials against isolated SASL broker",+ "expected": "Authenticated broker access succeeds/fails for actual credentials",+ "modes": "producer and consumer with actual SASL authentication/authorization",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs-integration.lifecycle.setSaslCredentials replaces credentials on a consumer",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials replaces credentials on a producer",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials rejects NUL in username without changing producer or consumer identity",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials rejects NUL in password without changing producer or consumer identity",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials releases each actual native error after decoding its exact code",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials cancellation at error decoding releases the owned error",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials cancellation at error acquisition releases the owned error",+ "authentication-contract.async consumer credential replacement authenticates after observed reconnect and recovers from invalid replacement",+ "authentication-contract.sync consumer credential replacement authenticates after observed reconnect and recovers from invalid replacement"+ ],+ "status": "tested",+ "previous_owner": 15,+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence": [+ "docs/testing/coverage-evidence.json",+ "docs/testing/compatibility-matrix.json"+ ]+ },+ {+ "id": "API-Kafka-Consumer-storeOffsetMessage",+ "symbols": [+ "Kafka.Consumer.storeOffsetMessage"+ ],+ "owner": 16,+ "behavior": "Store next offset for one record",+ "inputs": "noAutoOffsetStore; multiple records/partitions; failed commit",+ "expected": "Exact stored-then-committed offset + 1; no unrelated advancement",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs-integration.public-contract.consumer-commit.async commit modes preserve native flags callback offsets and broker state",+ "rdkafka-hs-integration.public-contract.consumer-commit.async committed query preserves an unavailable coordinator timeout",+ "rdkafka-hs-integration.public-contract.consumer-commit.async empty commit requests preserve no-offset callbacks",+ "rdkafka-hs-integration.public-contract.consumer-commit.async message and stored commits preserve unrelated partition offsets",+ "rdkafka-hs-integration.public-contract.consumer-commit.async mixed broker commit failures preserve successful offsets",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync commit modes preserve native flags callback offsets and broker state",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync committed query preserves an unavailable coordinator timeout",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync empty commit requests preserve no-offset callbacks",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync message and stored commits preserve unrelated partition offsets",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync mixed broker commit failures preserve successful offsets",+ "rdkafka-hs-integration.public-contract.consumer-state.async.store-commit-next-offset",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.store-commit-next-offset",+ "rdkafka-hs-integration.public-contract.input-boundaries.async store-message rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async store-message rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async store-message rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync store-message rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync store-message rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync store-message rejects underflow-partition"+ ],+ "status": "tested",+ "previous_owner": 14,+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ {+ "id": "API-Kafka-Consumer-storeOffsets",+ "symbols": [+ "Kafka.Consumer.storeOffsets"+ ],+ "owner": 16,+ "behavior": "Store explicit per-partition offsets",+ "inputs": "empty, valid, invalid and mixed partitions",+ "expected": "Exact later committed offsets; surfaced per-partition errors",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs-integration.public-contract.consumer-commit.async commit modes preserve native flags callback offsets and broker state",+ "rdkafka-hs-integration.public-contract.consumer-commit.async committed query preserves an unavailable coordinator timeout",+ "rdkafka-hs-integration.public-contract.consumer-commit.async empty commit requests preserve no-offset callbacks",+ "rdkafka-hs-integration.public-contract.consumer-commit.async message and stored commits preserve unrelated partition offsets",+ "rdkafka-hs-integration.public-contract.consumer-commit.async mixed broker commit failures preserve successful offsets",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync commit modes preserve native flags callback offsets and broker state",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync committed query preserves an unavailable coordinator timeout",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync empty commit requests preserve no-offset callbacks",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync message and stored commits preserve unrelated partition offsets",+ "rdkafka-hs-integration.public-contract.consumer-commit.sync mixed broker commit failures preserve successful offsets",+ "rdkafka-hs-integration.public-contract.consumer-state.async.empty-requests-preserve-empty-assignment",+ "rdkafka-hs-integration.public-contract.consumer-state.async.store-mixed-member-error",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.empty-requests-preserve-empty-assignment",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.store-mixed-member-error",+ "rdkafka-hs-integration.public-contract.input-boundaries.async store rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async store rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async store rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync store rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync store rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync store rejects underflow-partition"+ ],+ "status": "tested",+ "previous_owner": 14,+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ {+ "id": "API-Kafka-Consumer-subscription",+ "symbols": [+ "Kafka.Consumer.subscription"+ ],+ "owner": 16,+ "behavior": "Return current subscribed topic set",+ "inputs": "empty, one/multiple topics and patterns",+ "expected": "Exact requested set and matching topic behavior",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs-integration.public-contract.consumer-state.async.assignment-replacement",+ "rdkafka-hs-integration.public-contract.consumer-state.async.regex-subscription-selects-run-owned-topic",+ "rdkafka-hs-integration.public-contract.consumer-state.async.subscription-preserves-the-exact-multiple-topic-set",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.assignment-replacement",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.regex-subscription-selects-run-owned-topic",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.subscription-preserves-the-exact-multiple-topic-set",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.subscription acquisition failure preserves the native error without a list",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.subscription decoder failure releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.subscription outputs release after exact decoding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.subscription acquisition failure preserves the native error without a list",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.subscription decoder failure releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.subscription outputs release after exact decoding"+ ],+ "status": "tested",+ "previous_owner": 14,+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ {+ "id": "API-Kafka-Dump-dumpKafkaConf",+ "symbols": [+ "Kafka.Dump.dumpKafkaConf"+ ],+ "owner": 14,+ "behavior": "dumpKafkaConf reports effective native configuration or client diagnostics",+ "inputs": "default and overridden configuration; caller-owned output handle",+ "expected": "Known supplied settings and diagnostic fields appear; output handle remains usable; no native dump allocation leak",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs-integration.public-contract.diagnostics.supported-property print flushes and preserves the caller handle",+ "rdkafka-hs-integration.public-contract.diagnostics.client print flushes and preserves the caller handle",+ "rdkafka-hs-integration.public-contract.diagnostics.failed fdopen releases the duplicate and preserves the original",+ "rdkafka-hs-integration.public-contract.diagnostics.failed native flush is reported after closing the duplicate",+ "rdkafka-hs-integration.public-contract.diagnostics.producer configuration dumps retain exact explicit and global settings",+ "rdkafka-hs-integration.public-contract.diagnostics.consumer configuration dump preserves global settings after subscription merge",+ "rdkafka-hs-integration.public-contract.diagnostics.native dump counter detects an unreleased array",+ "rdkafka-hs-integration.public-contract.diagnostics.global cancellation at native acquisition releases its array",+ "rdkafka-hs-integration.public-contract.diagnostics.topic cancellation at native acquisition releases its array"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Dump-dumpTopicConf",+ "symbols": [+ "Kafka.Dump.dumpTopicConf"+ ],+ "owner": 14,+ "behavior": "dumpTopicConf reports effective native configuration or client diagnostics",+ "inputs": "default and overridden configuration; caller-owned output handle",+ "expected": "Known supplied settings and diagnostic fields appear; output handle remains usable; no native dump allocation leak",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs-integration.public-contract.diagnostics.supported-property print flushes and preserves the caller handle",+ "rdkafka-hs-integration.public-contract.diagnostics.client print flushes and preserves the caller handle",+ "rdkafka-hs-integration.public-contract.diagnostics.failed fdopen releases the duplicate and preserves the original",+ "rdkafka-hs-integration.public-contract.diagnostics.failed native flush is reported after closing the duplicate",+ "rdkafka-hs-integration.public-contract.diagnostics.producer configuration dumps retain exact explicit and global settings",+ "rdkafka-hs-integration.public-contract.diagnostics.consumer configuration dump preserves global settings after subscription merge",+ "rdkafka-hs-integration.public-contract.diagnostics.native dump counter detects an unreleased array",+ "rdkafka-hs-integration.public-contract.diagnostics.global cancellation at native acquisition releases its array",+ "rdkafka-hs-integration.public-contract.diagnostics.topic cancellation at native acquisition releases its array"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Dump-hPrintKafka",+ "symbols": [+ "Kafka.Dump.hPrintKafka"+ ],+ "owner": 14,+ "behavior": "hPrintKafka reports effective native configuration or client diagnostics",+ "inputs": "default and overridden configuration; caller-owned output handle",+ "expected": "Known supplied settings and diagnostic fields appear; output handle remains usable; no native dump allocation leak",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs-integration.public-contract.diagnostics.supported-property print flushes and preserves the caller handle",+ "rdkafka-hs-integration.public-contract.diagnostics.client print flushes and preserves the caller handle",+ "rdkafka-hs-integration.public-contract.diagnostics.failed fdopen releases the duplicate and preserves the original",+ "rdkafka-hs-integration.public-contract.diagnostics.failed native flush is reported after closing the duplicate",+ "rdkafka-hs-integration.public-contract.diagnostics.producer configuration dumps retain exact explicit and global settings",+ "rdkafka-hs-integration.public-contract.diagnostics.consumer configuration dump preserves global settings after subscription merge",+ "rdkafka-hs-integration.public-contract.diagnostics.native dump counter detects an unreleased array",+ "rdkafka-hs-integration.public-contract.diagnostics.global cancellation at native acquisition releases its array",+ "rdkafka-hs-integration.public-contract.diagnostics.topic cancellation at native acquisition releases its array"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Dump-hPrintSupportedKafkaConf",+ "symbols": [+ "Kafka.Dump.hPrintSupportedKafkaConf"+ ],+ "owner": 14,+ "behavior": "hPrintSupportedKafkaConf reports effective native configuration or client diagnostics",+ "inputs": "default and overridden configuration; caller-owned output handle",+ "expected": "Known supplied settings and diagnostic fields appear; output handle remains usable; no native dump allocation leak",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs-integration.public-contract.diagnostics.supported-property print flushes and preserves the caller handle",+ "rdkafka-hs-integration.public-contract.diagnostics.client print flushes and preserves the caller handle",+ "rdkafka-hs-integration.public-contract.diagnostics.failed fdopen releases the duplicate and preserves the original",+ "rdkafka-hs-integration.public-contract.diagnostics.failed native flush is reported after closing the duplicate",+ "rdkafka-hs-integration.public-contract.diagnostics.producer configuration dumps retain exact explicit and global settings",+ "rdkafka-hs-integration.public-contract.diagnostics.consumer configuration dump preserves global settings after subscription merge",+ "rdkafka-hs-integration.public-contract.diagnostics.native dump counter detects an unreleased array",+ "rdkafka-hs-integration.public-contract.diagnostics.global cancellation at native acquisition releases its array",+ "rdkafka-hs-integration.public-contract.diagnostics.topic cancellation at native acquisition releases its array"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Internal-RdKafka-RdKafkaRespErrT",+ "symbols": [+ "Kafka.Internal.RdKafka.RdKafkaRespErrT"+ ],+ "owner": 14,+ "behavior": "RdKafkaRespErrT exposes its documented constructors, record selectors and typeclass laws",+ "inputs": "Every exported constructor/member in the compiler export inventory; generated boundary and ordinary field values",+ "expected": "Construction/selection round trips; declared equality/order/show/enum/functor/traversal instances obey their documented laws",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public data contracts.all linked native errors retain sparse numeric codes names and descriptions"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Metadata-BrokerMetadata",+ "symbols": [+ "Kafka.Metadata.BrokerMetadata"+ ],+ "owner": 14,+ "behavior": "BrokerMetadata preserves metadata identity and native per-entity errors",+ "inputs": "empty, existing, missing and invalid topics/groups/partitions; time bounds; unavailable broker; deprecated aliases where present",+ "expected": "Exact broker/topic/partition/group identities, offsets and error details; no success-only or length-only assertion",+ "modes": "all supported modes",+ "ownership": "Temporary topic/metadata/group-list/partition-list handles released after decoding on success and error",+ "tests": [+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata counter detects an unreleased result",+ "rdkafka-hs-integration.public-contract.metadata-contract.topic identity replica sets and exact watermarks",+ "rdkafka-hs-integration.public-contract.metadata-contract.distinct native metadata fields retain exact identities and errors",+ "rdkafka-hs-integration.public-contract.metadata-contract.provided metadata preserves partition failures in convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata partition failures survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.group query timeout preserves initial metadata wait failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.missing topic errors survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.timestamp lookup distinguishes before at and after actual record times",+ "rdkafka-hs-integration.public-contract.metadata-contract.mixed timestamp request preserves native partition failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata timeouts preserve the native error",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.groups native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.async group identity lifecycle and supported native states",+ "rdkafka-hs-integration.public-contract.metadata-contract.sync group identity lifecycle and supported native states"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ {+ "id": "API-Kafka-Metadata-GroupInfo",+ "symbols": [+ "Kafka.Metadata.GroupInfo"+ ],+ "owner": 14,+ "behavior": "GroupInfo preserves metadata identity and native per-entity errors",+ "inputs": "empty, existing, missing and invalid topics/groups/partitions; time bounds; unavailable broker; deprecated aliases where present",+ "expected": "Exact broker/topic/partition/group identities, offsets and error details; no success-only or length-only assertion",+ "modes": "all supported modes",+ "ownership": "Temporary topic/metadata/group-list/partition-list handles released after decoding on success and error",+ "tests": [+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata counter detects an unreleased result",+ "rdkafka-hs-integration.public-contract.metadata-contract.topic identity replica sets and exact watermarks",+ "rdkafka-hs-integration.public-contract.metadata-contract.distinct native metadata fields retain exact identities and errors",+ "rdkafka-hs-integration.public-contract.metadata-contract.provided metadata preserves partition failures in convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata partition failures survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.group query timeout preserves initial metadata wait failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.missing topic errors survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.timestamp lookup distinguishes before at and after actual record times",+ "rdkafka-hs-integration.public-contract.metadata-contract.mixed timestamp request preserves native partition failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata timeouts preserve the native error",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.groups native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.async group identity lifecycle and supported native states",+ "rdkafka-hs-integration.public-contract.metadata-contract.sync group identity lifecycle and supported native states"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ {+ "id": "API-Kafka-Metadata-GroupMemberId",+ "symbols": [+ "Kafka.Metadata.GroupMemberId"+ ],+ "owner": 14,+ "behavior": "GroupMemberId preserves metadata identity and native per-entity errors",+ "inputs": "empty, existing, missing and invalid topics/groups/partitions; time bounds; unavailable broker; deprecated aliases where present",+ "expected": "Exact broker/topic/partition/group identities, offsets and error details; no success-only or length-only assertion",+ "modes": "all supported modes",+ "ownership": "Temporary topic/metadata/group-list/partition-list handles released after decoding on success and error",+ "tests": [+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata counter detects an unreleased result",+ "rdkafka-hs-integration.public-contract.metadata-contract.topic identity replica sets and exact watermarks",+ "rdkafka-hs-integration.public-contract.metadata-contract.provided metadata preserves partition failures in convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata partition failures survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.group query timeout preserves initial metadata wait failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.missing topic errors survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.timestamp lookup distinguishes before at and after actual record times",+ "rdkafka-hs-integration.public-contract.metadata-contract.mixed timestamp request preserves native partition failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata timeouts preserve the native error",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.groups native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.async group identity lifecycle and supported native states",+ "rdkafka-hs-integration.public-contract.metadata-contract.sync group identity lifecycle and supported native states"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Metadata-GroupMemberInfo",+ "symbols": [+ "Kafka.Metadata.GroupMemberInfo"+ ],+ "owner": 14,+ "behavior": "GroupMemberInfo preserves metadata identity and native per-entity errors",+ "inputs": "empty, existing, missing and invalid topics/groups/partitions; time bounds; unavailable broker; deprecated aliases where present",+ "expected": "Exact broker/topic/partition/group identities, offsets and error details; no success-only or length-only assertion",+ "modes": "all supported modes",+ "ownership": "Temporary topic/metadata/group-list/partition-list handles released after decoding on success and error",+ "tests": [+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata counter detects an unreleased result",+ "rdkafka-hs-integration.public-contract.metadata-contract.topic identity replica sets and exact watermarks",+ "rdkafka-hs-integration.public-contract.metadata-contract.provided metadata preserves partition failures in convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata partition failures survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.group query timeout preserves initial metadata wait failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.missing topic errors survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.timestamp lookup distinguishes before at and after actual record times",+ "rdkafka-hs-integration.public-contract.metadata-contract.mixed timestamp request preserves native partition failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata timeouts preserve the native error",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.groups native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.async group identity lifecycle and supported native states",+ "rdkafka-hs-integration.public-contract.metadata-contract.sync group identity lifecycle and supported native states"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Metadata-GroupProtocol",+ "symbols": [+ "Kafka.Metadata.GroupProtocol"+ ],+ "owner": 14,+ "behavior": "GroupProtocol preserves metadata identity and native per-entity errors",+ "inputs": "empty, existing, missing and invalid topics/groups/partitions; time bounds; unavailable broker; deprecated aliases where present",+ "expected": "Exact broker/topic/partition/group identities, offsets and error details; no success-only or length-only assertion",+ "modes": "all supported modes",+ "ownership": "Temporary topic/metadata/group-list/partition-list handles released after decoding on success and error",+ "tests": [+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata counter detects an unreleased result",+ "rdkafka-hs-integration.public-contract.metadata-contract.topic identity replica sets and exact watermarks",+ "rdkafka-hs-integration.public-contract.metadata-contract.distinct native metadata fields retain exact identities and errors",+ "rdkafka-hs-integration.public-contract.metadata-contract.provided metadata preserves partition failures in convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata partition failures survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.group query timeout preserves initial metadata wait failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.missing topic errors survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.timestamp lookup distinguishes before at and after actual record times",+ "rdkafka-hs-integration.public-contract.metadata-contract.mixed timestamp request preserves native partition failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata timeouts preserve the native error",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.groups native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.async group identity lifecycle and supported native states",+ "rdkafka-hs-integration.public-contract.metadata-contract.sync group identity lifecycle and supported native states"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ {+ "id": "API-Kafka-Metadata-GroupProtocolType",+ "symbols": [+ "Kafka.Metadata.GroupProtocolType"+ ],+ "owner": 14,+ "behavior": "GroupProtocolType preserves metadata identity and native per-entity errors",+ "inputs": "empty, existing, missing and invalid topics/groups/partitions; time bounds; unavailable broker; deprecated aliases where present",+ "expected": "Exact broker/topic/partition/group identities, offsets and error details; no success-only or length-only assertion",+ "modes": "all supported modes",+ "ownership": "Temporary topic/metadata/group-list/partition-list handles released after decoding on success and error",+ "tests": [+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata counter detects an unreleased result",+ "rdkafka-hs-integration.public-contract.metadata-contract.topic identity replica sets and exact watermarks",+ "rdkafka-hs-integration.public-contract.metadata-contract.provided metadata preserves partition failures in convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata partition failures survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.group query timeout preserves initial metadata wait failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.missing topic errors survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.timestamp lookup distinguishes before at and after actual record times",+ "rdkafka-hs-integration.public-contract.metadata-contract.mixed timestamp request preserves native partition failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata timeouts preserve the native error",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.groups native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.async group identity lifecycle and supported native states",+ "rdkafka-hs-integration.public-contract.metadata-contract.sync group identity lifecycle and supported native states"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Metadata-GroupState",+ "symbols": [+ "Kafka.Metadata.GroupState"+ ],+ "owner": 14,+ "behavior": "GroupState preserves metadata identity and native per-entity errors",+ "inputs": "empty, existing, missing and invalid topics/groups/partitions; time bounds; unavailable broker; deprecated aliases where present",+ "expected": "Exact broker/topic/partition/group identities, offsets and error details; no success-only or length-only assertion",+ "modes": "all supported modes",+ "ownership": "Temporary topic/metadata/group-list/partition-list handles released after decoding on success and error",+ "tests": [+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata counter detects an unreleased result",+ "rdkafka-hs-integration.public-contract.metadata-contract.topic identity replica sets and exact watermarks",+ "rdkafka-hs-integration.public-contract.metadata-contract.provided metadata preserves partition failures in convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata partition failures survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.group query timeout preserves initial metadata wait failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.missing topic errors survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.timestamp lookup distinguishes before at and after actual record times",+ "rdkafka-hs-integration.public-contract.metadata-contract.mixed timestamp request preserves native partition failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata timeouts preserve the native error",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.groups native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.async group identity lifecycle and supported native states",+ "rdkafka-hs-integration.public-contract.metadata-contract.sync group identity lifecycle and supported native states"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Metadata-KafkaMetadata",+ "symbols": [+ "Kafka.Metadata.KafkaMetadata"+ ],+ "owner": 14,+ "behavior": "KafkaMetadata preserves metadata identity and native per-entity errors",+ "inputs": "empty, existing, missing and invalid topics/groups/partitions; time bounds; unavailable broker; deprecated aliases where present",+ "expected": "Exact broker/topic/partition/group identities, offsets and error details; no success-only or length-only assertion",+ "modes": "all supported modes",+ "ownership": "Temporary topic/metadata/group-list/partition-list handles released after decoding on success and error",+ "tests": [+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata counter detects an unreleased result",+ "rdkafka-hs-integration.public-contract.metadata-contract.topic identity replica sets and exact watermarks",+ "rdkafka-hs-integration.public-contract.metadata-contract.distinct native metadata fields retain exact identities and errors",+ "rdkafka-hs-integration.public-contract.metadata-contract.provided metadata preserves partition failures in convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata partition failures survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.group query timeout preserves initial metadata wait failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.missing topic errors survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.timestamp lookup distinguishes before at and after actual record times",+ "rdkafka-hs-integration.public-contract.metadata-contract.mixed timestamp request preserves native partition failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata timeouts preserve the native error",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.groups native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.async group identity lifecycle and supported native states",+ "rdkafka-hs-integration.public-contract.metadata-contract.sync group identity lifecycle and supported native states"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ {+ "id": "API-Kafka-Metadata-PartitionMetadata",+ "symbols": [+ "Kafka.Metadata.PartitionMetadata"+ ],+ "owner": 14,+ "behavior": "PartitionMetadata preserves metadata identity and native per-entity errors",+ "inputs": "empty, existing, missing and invalid topics/groups/partitions; time bounds; unavailable broker; deprecated aliases where present",+ "expected": "Exact broker/topic/partition/group identities, offsets and error details; no success-only or length-only assertion",+ "modes": "all supported modes",+ "ownership": "Temporary topic/metadata/group-list/partition-list handles released after decoding on success and error",+ "tests": [+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata counter detects an unreleased result",+ "rdkafka-hs-integration.public-contract.metadata-contract.topic identity replica sets and exact watermarks",+ "rdkafka-hs-integration.public-contract.metadata-contract.distinct native metadata fields retain exact identities and errors",+ "rdkafka-hs-integration.public-contract.metadata-contract.provided metadata preserves partition failures in convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata partition failures survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.group query timeout preserves initial metadata wait failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.missing topic errors survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.timestamp lookup distinguishes before at and after actual record times",+ "rdkafka-hs-integration.public-contract.metadata-contract.mixed timestamp request preserves native partition failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata timeouts preserve the native error",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.groups native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.async group identity lifecycle and supported native states",+ "rdkafka-hs-integration.public-contract.metadata-contract.sync group identity lifecycle and supported native states"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ {+ "id": "API-Kafka-Metadata-TopicMetadata",+ "symbols": [+ "Kafka.Metadata.TopicMetadata"+ ],+ "owner": 14,+ "behavior": "TopicMetadata preserves metadata identity and native per-entity errors",+ "inputs": "empty, existing, missing and invalid topics/groups/partitions; time bounds; unavailable broker; deprecated aliases where present",+ "expected": "Exact broker/topic/partition/group identities, offsets and error details; no success-only or length-only assertion",+ "modes": "all supported modes",+ "ownership": "Temporary topic/metadata/group-list/partition-list handles released after decoding on success and error",+ "tests": [+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata counter detects an unreleased result",+ "rdkafka-hs-integration.public-contract.metadata-contract.topic identity replica sets and exact watermarks",+ "rdkafka-hs-integration.public-contract.metadata-contract.distinct native metadata fields retain exact identities and errors",+ "rdkafka-hs-integration.public-contract.metadata-contract.provided metadata preserves partition failures in convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata partition failures survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.group query timeout preserves initial metadata wait failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.missing topic errors survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.timestamp lookup distinguishes before at and after actual record times",+ "rdkafka-hs-integration.public-contract.metadata-contract.mixed timestamp request preserves native partition failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata timeouts preserve the native error",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.groups native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.async group identity lifecycle and supported native states",+ "rdkafka-hs-integration.public-contract.metadata-contract.sync group identity lifecycle and supported native states"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ {+ "id": "API-Kafka-Metadata-WatermarkOffsets",+ "symbols": [+ "Kafka.Metadata.WatermarkOffsets"+ ],+ "owner": 14,+ "behavior": "WatermarkOffsets preserves metadata identity and native per-entity errors",+ "inputs": "empty, existing, missing and invalid topics/groups/partitions; time bounds; unavailable broker; deprecated aliases where present",+ "expected": "Exact broker/topic/partition/group identities, offsets and error details; no success-only or length-only assertion",+ "modes": "all supported modes",+ "ownership": "Temporary topic/metadata/group-list/partition-list handles released after decoding on success and error",+ "tests": [+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata counter detects an unreleased result",+ "rdkafka-hs-integration.public-contract.metadata-contract.topic identity replica sets and exact watermarks",+ "rdkafka-hs-integration.public-contract.metadata-contract.distinct native metadata fields retain exact identities and errors",+ "rdkafka-hs-integration.public-contract.metadata-contract.provided metadata preserves partition failures in convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata partition failures survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.group query timeout preserves initial metadata wait failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.missing topic errors survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.timestamp lookup distinguishes before at and after actual record times",+ "rdkafka-hs-integration.public-contract.metadata-contract.mixed timestamp request preserves native partition failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata timeouts preserve the native error",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.groups native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.async group identity lifecycle and supported native states",+ "rdkafka-hs-integration.public-contract.metadata-contract.sync group identity lifecycle and supported native states"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ {+ "id": "API-Kafka-Metadata-allConsumerGroupsInfo",+ "symbols": [+ "Kafka.Metadata.allConsumerGroupsInfo"+ ],+ "owner": 16,+ "behavior": "allConsumerGroupsInfo preserves metadata identity and native per-entity errors",+ "inputs": "empty, existing, missing and invalid topics/groups/partitions; time bounds; unavailable broker; deprecated aliases where present",+ "expected": "Exact broker/topic/partition/group identities, offsets and error details; no success-only or length-only assertion",+ "modes": "all supported modes",+ "ownership": "Temporary topic/metadata/group-list/partition-list handles released after decoding on success and error",+ "tests": [+ "rdkafka-hs-integration.public-contract.input-boundaries.async string queries and subscription reject NUL before native effects",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync string queries and subscription reject NUL before native effects",+ "rdkafka-hs-integration.public-contract.metadata-contract.async group identity lifecycle and supported native states",+ "rdkafka-hs-integration.public-contract.metadata-contract.group query timeout preserves initial metadata wait failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.groups native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.sync group identity lifecycle and supported native states"+ ],+ "status": "tested",+ "previous_owner": 14,+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ {+ "id": "API-Kafka-Metadata-allTopicsMetadata",+ "symbols": [+ "Kafka.Metadata.allTopicsMetadata"+ ],+ "owner": 16,+ "behavior": "allTopicsMetadata preserves metadata identity and native per-entity errors",+ "inputs": "empty, existing, missing and invalid topics/groups/partitions; time bounds; unavailable broker; deprecated aliases where present",+ "expected": "Exact broker/topic/partition/group identities, offsets and error details; no success-only or length-only assertion",+ "modes": "all supported modes",+ "ownership": "Temporary topic/metadata/group-list/partition-list handles released after decoding on success and error",+ "tests": [+ "rdkafka-hs-integration.public-contract.input-boundaries.async string queries and subscription reject NUL before native effects",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync string queries and subscription reject NUL before native effects",+ "rdkafka-hs-integration.public-contract.metadata-contract.distinct native metadata fields retain exact identities and errors",+ "rdkafka-hs-integration.public-contract.metadata-contract.empty native metadata remains empty and releases every result",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata timeouts preserve the native error",+ "rdkafka-hs-integration.public-contract.metadata-contract.missing topic errors survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.native topic-constructor failure survives metadata convenience queries",+ "rdkafka-hs-integration.public-contract.metadata-contract.topic identity replica sets and exact watermarks"+ ],+ "status": "tested",+ "previous_owner": 14,+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ {+ "id": "API-Kafka-Metadata-consumerGroupInfo",+ "symbols": [+ "Kafka.Metadata.consumerGroupInfo"+ ],+ "owner": 16,+ "behavior": "consumerGroupInfo preserves metadata identity and native per-entity errors",+ "inputs": "empty, existing, missing and invalid topics/groups/partitions; time bounds; unavailable broker; deprecated aliases where present",+ "expected": "Exact broker/topic/partition/group identities, offsets and error details; no success-only or length-only assertion",+ "modes": "all supported modes",+ "ownership": "Temporary topic/metadata/group-list/partition-list handles released after decoding on success and error",+ "tests": [+ "rdkafka-hs-integration.public-contract.input-boundaries.async string queries and subscription reject NUL before native effects",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync string queries and subscription reject NUL before native effects",+ "rdkafka-hs-integration.public-contract.metadata-contract.async group identity lifecycle and supported native states",+ "rdkafka-hs-integration.public-contract.metadata-contract.group query timeout preserves initial metadata wait failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.groups native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.sync group identity lifecycle and supported native states"+ ],+ "status": "tested",+ "previous_owner": 14,+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ {+ "id": "API-Kafka-Metadata-offsetsForTime",+ "symbols": [+ "Kafka.Metadata.offsetsForTime"+ ],+ "owner": 16,+ "behavior": "offsetsForTime preserves metadata identity and native per-entity errors",+ "inputs": "empty, existing, missing and invalid topics/groups/partitions; time bounds; unavailable broker; deprecated aliases where present",+ "expected": "Exact broker/topic/partition/group identities, offsets and error details; no success-only or length-only assertion",+ "modes": "all supported modes",+ "ownership": "Temporary topic/metadata/group-list/partition-list handles released after decoding on success and error",+ "tests": [+ "rdkafka-hs-integration.public-contract.input-boundaries.async string queries and subscription reject NUL before native effects",+ "rdkafka-hs-integration.public-contract.input-boundaries.async timestamp rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async timestamp rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async timestamp rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync string queries and subscription reject NUL before native effects",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync timestamp rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync timestamp rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync timestamp rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.metadata-contract.empty native metadata remains empty and releases every result",+ "rdkafka-hs-integration.public-contract.metadata-contract.missing topic errors survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.mixed timestamp request preserves native partition failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata partition failures survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.native topic-constructor failure survives metadata convenience queries",+ "rdkafka-hs-integration.public-contract.metadata-contract.provided metadata preserves partition failures in convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.timestamp lookup distinguishes before at and after actual record times",+ "rdkafka-hs-integration.public-contract.metadata-contract.timestamp lookup preserves native overall errors",+ "rdkafka-hs-integration.public-contract.metadata-contract.watermark queries preserve unknown partition errors and empty provided metadata"+ ],+ "status": "tested",+ "previous_owner": 14,+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ {+ "id": "API-Kafka-Metadata-offsetsForTime-prime",+ "symbols": [+ "Kafka.Metadata.offsetsForTime'"+ ],+ "owner": 16,+ "behavior": "offsetsForTime' preserves metadata identity and native per-entity errors",+ "inputs": "empty, existing, missing and invalid topics/groups/partitions; time bounds; unavailable broker; deprecated aliases where present",+ "expected": "Exact broker/topic/partition/group identities, offsets and error details; no success-only or length-only assertion",+ "modes": "all supported modes",+ "ownership": "Temporary topic/metadata/group-list/partition-list handles released after decoding on success and error",+ "tests": [+ "rdkafka-hs-integration.public-contract.input-boundaries.async string queries and subscription reject NUL before native effects",+ "rdkafka-hs-integration.public-contract.input-boundaries.async timestamp rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async timestamp rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async timestamp rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync string queries and subscription reject NUL before native effects",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync timestamp rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync timestamp rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync timestamp rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.metadata-contract.empty native metadata remains empty and releases every result",+ "rdkafka-hs-integration.public-contract.metadata-contract.missing topic errors survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.mixed timestamp request preserves native partition failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata partition failures survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.native topic-constructor failure survives metadata convenience queries",+ "rdkafka-hs-integration.public-contract.metadata-contract.provided metadata preserves partition failures in convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.timestamp lookup distinguishes before at and after actual record times",+ "rdkafka-hs-integration.public-contract.metadata-contract.timestamp lookup preserves native overall errors",+ "rdkafka-hs-integration.public-contract.metadata-contract.watermark queries preserve unknown partition errors and empty provided metadata"+ ],+ "status": "tested",+ "previous_owner": 14,+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ {+ "id": "API-Kafka-Metadata-partitionWatermarkOffsets",+ "symbols": [+ "Kafka.Metadata.partitionWatermarkOffsets"+ ],+ "owner": 16,+ "behavior": "partitionWatermarkOffsets preserves metadata identity and native per-entity errors",+ "inputs": "empty, existing, missing and invalid topics/groups/partitions; time bounds; unavailable broker; deprecated aliases where present",+ "expected": "Exact broker/topic/partition/group identities, offsets and error details; no success-only or length-only assertion",+ "modes": "all supported modes",+ "ownership": "Temporary topic/metadata/group-list/partition-list handles released after decoding on success and error",+ "tests": [+ "rdkafka-hs-integration.public-contract.input-boundaries.async watermark rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async watermark rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async watermark rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync watermark rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync watermark rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync watermark rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.metadata-contract.topic identity replica sets and exact watermarks",+ "rdkafka-hs-integration.public-contract.metadata-contract.watermark queries preserve unknown partition errors and empty provided metadata"+ ],+ "status": "tested",+ "previous_owner": 14,+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ {+ "id": "API-Kafka-Metadata-topicMetadata",+ "symbols": [+ "Kafka.Metadata.topicMetadata"+ ],+ "owner": 16,+ "behavior": "topicMetadata preserves metadata identity and native per-entity errors",+ "inputs": "empty, existing, missing and invalid topics/groups/partitions; time bounds; unavailable broker; deprecated aliases where present",+ "expected": "Exact broker/topic/partition/group identities, offsets and error details; no success-only or length-only assertion",+ "modes": "all supported modes",+ "ownership": "Temporary topic/metadata/group-list/partition-list handles released after decoding on success and error",+ "tests": [+ "rdkafka-hs-integration.public-contract.input-boundaries.async string queries and subscription reject NUL before native effects",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync string queries and subscription reject NUL before native effects",+ "rdkafka-hs-integration.public-contract.metadata-contract.distinct native metadata fields retain exact identities and errors",+ "rdkafka-hs-integration.public-contract.metadata-contract.empty native metadata remains empty and releases every result",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata timeouts preserve the native error",+ "rdkafka-hs-integration.public-contract.metadata-contract.missing topic errors survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.native topic-constructor failure survives metadata convenience queries",+ "rdkafka-hs-integration.public-contract.metadata-contract.topic identity replica sets and exact watermarks"+ ],+ "status": "tested",+ "previous_owner": 14,+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ {+ "id": "API-Kafka-Metadata-topicOffsetsForTime",+ "symbols": [+ "Kafka.Metadata.topicOffsetsForTime"+ ],+ "owner": 16,+ "behavior": "topicOffsetsForTime preserves metadata identity and native per-entity errors",+ "inputs": "empty, existing, missing and invalid topics/groups/partitions; time bounds; unavailable broker; deprecated aliases where present",+ "expected": "Exact broker/topic/partition/group identities, offsets and error details; no success-only or length-only assertion",+ "modes": "all supported modes",+ "ownership": "Temporary topic/metadata/group-list/partition-list handles released after decoding on success and error",+ "tests": [+ "rdkafka-hs-integration.public-contract.input-boundaries.async string queries and subscription reject NUL before native effects",+ "rdkafka-hs-integration.public-contract.input-boundaries.async timestamp rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.async timestamp rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.async timestamp rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync string queries and subscription reject NUL before native effects",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync timestamp rejects nul-topic",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync timestamp rejects overflow-partition",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync timestamp rejects underflow-partition",+ "rdkafka-hs-integration.public-contract.metadata-contract.empty native metadata remains empty and releases every result",+ "rdkafka-hs-integration.public-contract.metadata-contract.missing topic errors survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.mixed timestamp request preserves native partition failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata partition failures survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.native topic-constructor failure survives metadata convenience queries",+ "rdkafka-hs-integration.public-contract.metadata-contract.provided metadata preserves partition failures in convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.timestamp lookup distinguishes before at and after actual record times",+ "rdkafka-hs-integration.public-contract.metadata-contract.timestamp lookup preserves native overall errors",+ "rdkafka-hs-integration.public-contract.metadata-contract.watermark queries preserve unknown partition errors and empty provided metadata"+ ],+ "status": "tested",+ "previous_owner": 14,+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ {+ "id": "API-Kafka-Metadata-watermarkOffsets",+ "symbols": [+ "Kafka.Metadata.watermarkOffsets"+ ],+ "owner": 16,+ "behavior": "watermarkOffsets preserves metadata identity and native per-entity errors",+ "inputs": "empty, existing, missing and invalid topics/groups/partitions; time bounds; unavailable broker; deprecated aliases where present",+ "expected": "Exact broker/topic/partition/group identities, offsets and error details; no success-only or length-only assertion",+ "modes": "all supported modes",+ "ownership": "Temporary topic/metadata/group-list/partition-list handles released after decoding on success and error",+ "tests": [+ "rdkafka-hs-integration.public-contract.input-boundaries.async string queries and subscription reject NUL before native effects",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync string queries and subscription reject NUL before native effects",+ "rdkafka-hs-integration.public-contract.metadata-contract.empty native metadata remains empty and releases every result",+ "rdkafka-hs-integration.public-contract.metadata-contract.missing topic errors survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata partition failures survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.native topic-constructor failure survives metadata convenience queries",+ "rdkafka-hs-integration.public-contract.metadata-contract.provided metadata preserves partition failures in convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.topic identity replica sets and exact watermarks",+ "rdkafka-hs-integration.public-contract.metadata-contract.watermark queries preserve unknown partition errors and empty provided metadata"+ ],+ "status": "tested",+ "previous_owner": 14,+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ {+ "id": "API-Kafka-Metadata-watermarkOffsets-prime",+ "symbols": [+ "Kafka.Metadata.watermarkOffsets'"+ ],+ "owner": 16,+ "behavior": "watermarkOffsets' preserves metadata identity and native per-entity errors",+ "inputs": "empty, existing, missing and invalid topics/groups/partitions; time bounds; unavailable broker; deprecated aliases where present",+ "expected": "Exact broker/topic/partition/group identities, offsets and error details; no success-only or length-only assertion",+ "modes": "all supported modes",+ "ownership": "Temporary topic/metadata/group-list/partition-list handles released after decoding on success and error",+ "tests": [+ "rdkafka-hs-integration.public-contract.input-boundaries.async string queries and subscription reject NUL before native effects",+ "rdkafka-hs-integration.public-contract.input-boundaries.sync string queries and subscription reject NUL before native effects",+ "rdkafka-hs-integration.public-contract.metadata-contract.empty native metadata remains empty and releases every result",+ "rdkafka-hs-integration.public-contract.metadata-contract.missing topic errors survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata partition failures survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.native topic-constructor failure survives metadata convenience queries",+ "rdkafka-hs-integration.public-contract.metadata-contract.provided metadata preserves partition failures in convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.topic identity replica sets and exact watermarks",+ "rdkafka-hs-integration.public-contract.metadata-contract.watermark queries preserve unknown partition errors and empty provided metadata"+ ],+ "status": "tested",+ "previous_owner": 14,+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ {+ "id": "API-Kafka-Producer-ProducerProperties-ProducerProperties",+ "symbols": [+ "Kafka.Producer.ProducerProperties.ProducerProperties"+ ],+ "owner": 14,+ "behavior": "ProducerProperties constructs/composes the documented effective settings",+ "inputs": "identity, repeated/conflicting settings, left/right precedence, empty/nonempty lists and boundary numeric/text values",+ "expected": "Exact effective map, callback/poll mode/log level; native validation preserved for invalid values",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Producer properties generated.program follows last-write semantics",+ "rdkafka-hs.Producer properties generated.configuration has left and right identity",+ "rdkafka-hs.Producer properties generated.configuration composition is associative",+ "rdkafka-hs.Producer properties generated.composition appends writes in order",+ "rdkafka-hs.Producer properties generated.unrelated keys survive a conflicting write",+ "rdkafka-hs.Producer properties generated.last explicit log level wins",+ "rdkafka-hs.Producer properties generated.fixed empty duplicate and binary text values",+ "rdkafka-hs.Public data contracts.builders.semigroup defaults retain writes callbacks and subscription union",+ "rdkafka-hs.Public data contracts.builders.consumer builders preserve exact settings and leave other fields unset",+ "rdkafka-hs.Public data contracts.builders.producer builders preserve global versus explicit topic placement",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: invalid topic timeout",+ "rdkafka-hs-integration.producer-properties.callback composition preserves order and identity",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.empty producer client id retains the native default",+ "rdkafka-hs-integration.public-contract.config-strings.consumer ordinary UTF8 values remain exact",+ "rdkafka-hs-integration.public-contract.config-strings.empty global key retains native unknown-key rejection"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Producer-ProducerProperties-brokersList",+ "symbols": [+ "Kafka.Producer.ProducerProperties.brokersList"+ ],+ "owner": 14,+ "behavior": "brokersList constructs/composes the documented effective settings",+ "inputs": "identity, repeated/conflicting settings, left/right precedence, empty/nonempty lists and boundary numeric/text values",+ "expected": "Exact effective map, callback/poll mode/log level; native validation preserved for invalid values",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Producer properties generated.program follows last-write semantics",+ "rdkafka-hs.Producer properties generated.configuration has left and right identity",+ "rdkafka-hs.Producer properties generated.configuration composition is associative",+ "rdkafka-hs.Producer properties generated.composition appends writes in order",+ "rdkafka-hs.Producer properties generated.unrelated keys survive a conflicting write",+ "rdkafka-hs.Producer properties generated.last explicit log level wins",+ "rdkafka-hs.Producer properties generated.fixed empty duplicate and binary text values",+ "rdkafka-hs.Public data contracts.builders.semigroup defaults retain writes callbacks and subscription union",+ "rdkafka-hs.Public data contracts.builders.consumer builders preserve exact settings and leave other fields unset",+ "rdkafka-hs.Public data contracts.builders.producer builders preserve global versus explicit topic placement",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: invalid topic timeout",+ "rdkafka-hs-integration.producer-properties.callback composition preserves order and identity",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.empty producer client id retains the native default",+ "rdkafka-hs-integration.public-contract.config-strings.consumer ordinary UTF8 values remain exact",+ "rdkafka-hs-integration.public-contract.config-strings.empty global key retains native unknown-key rejection"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Producer-ProducerProperties-compression",+ "symbols": [+ "Kafka.Producer.ProducerProperties.compression"+ ],+ "owner": 14,+ "behavior": "compression constructs/composes the documented effective settings",+ "inputs": "identity, repeated/conflicting settings, left/right precedence, empty/nonempty lists and boundary numeric/text values",+ "expected": "Exact effective map, callback/poll mode/log level; native validation preserved for invalid values",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Producer properties generated.program follows last-write semantics",+ "rdkafka-hs.Producer properties generated.configuration has left and right identity",+ "rdkafka-hs.Producer properties generated.configuration composition is associative",+ "rdkafka-hs.Producer properties generated.composition appends writes in order",+ "rdkafka-hs.Producer properties generated.unrelated keys survive a conflicting write",+ "rdkafka-hs.Producer properties generated.last explicit log level wins",+ "rdkafka-hs.Producer properties generated.fixed empty duplicate and binary text values",+ "rdkafka-hs.Public data contracts.builders.semigroup defaults retain writes callbacks and subscription union",+ "rdkafka-hs.Public data contracts.builders.consumer builders preserve exact settings and leave other fields unset",+ "rdkafka-hs.Public data contracts.builders.producer builders preserve global versus explicit topic placement",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: invalid topic timeout",+ "rdkafka-hs-integration.producer-properties.callback composition preserves order and identity",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.empty producer client id retains the native default",+ "rdkafka-hs-integration.public-contract.config-strings.consumer ordinary UTF8 values remain exact",+ "rdkafka-hs-integration.public-contract.config-strings.empty global key retains native unknown-key rejection"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Producer-ProducerProperties-debugOptions",+ "symbols": [+ "Kafka.Producer.ProducerProperties.debugOptions"+ ],+ "owner": 14,+ "behavior": "debugOptions constructs/composes the documented effective settings",+ "inputs": "identity, repeated/conflicting settings, left/right precedence, empty/nonempty lists and boundary numeric/text values",+ "expected": "Exact effective map, callback/poll mode/log level; native validation preserved for invalid values",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Producer properties generated.program follows last-write semantics",+ "rdkafka-hs.Producer properties generated.configuration has left and right identity",+ "rdkafka-hs.Producer properties generated.configuration composition is associative",+ "rdkafka-hs.Producer properties generated.composition appends writes in order",+ "rdkafka-hs.Producer properties generated.unrelated keys survive a conflicting write",+ "rdkafka-hs.Producer properties generated.last explicit log level wins",+ "rdkafka-hs.Producer properties generated.fixed empty duplicate and binary text values",+ "rdkafka-hs.Public data contracts.builders.semigroup defaults retain writes callbacks and subscription union",+ "rdkafka-hs.Public data contracts.builders.consumer builders preserve exact settings and leave other fields unset",+ "rdkafka-hs.Public data contracts.builders.producer builders preserve global versus explicit topic placement",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: invalid topic timeout",+ "rdkafka-hs-integration.producer-properties.callback composition preserves order and identity",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.empty producer client id retains the native default",+ "rdkafka-hs-integration.public-contract.config-strings.consumer ordinary UTF8 values remain exact",+ "rdkafka-hs-integration.public-contract.config-strings.empty global key retains native unknown-key rejection"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Producer-ProducerProperties-extraProp",+ "symbols": [+ "Kafka.Producer.ProducerProperties.extraProp"+ ],+ "owner": 14,+ "behavior": "extraProp constructs/composes the documented effective settings",+ "inputs": "identity, repeated/conflicting settings, left/right precedence, empty/nonempty lists and boundary numeric/text values",+ "expected": "Exact effective map, callback/poll mode/log level; native validation preserved for invalid values",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Producer properties generated.program follows last-write semantics",+ "rdkafka-hs.Producer properties generated.configuration has left and right identity",+ "rdkafka-hs.Producer properties generated.configuration composition is associative",+ "rdkafka-hs.Producer properties generated.composition appends writes in order",+ "rdkafka-hs.Producer properties generated.unrelated keys survive a conflicting write",+ "rdkafka-hs.Producer properties generated.last explicit log level wins",+ "rdkafka-hs.Producer properties generated.fixed empty duplicate and binary text values",+ "rdkafka-hs.Public data contracts.builders.semigroup defaults retain writes callbacks and subscription union",+ "rdkafka-hs.Public data contracts.builders.consumer builders preserve exact settings and leave other fields unset",+ "rdkafka-hs.Public data contracts.builders.producer builders preserve global versus explicit topic placement",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: invalid topic timeout",+ "rdkafka-hs-integration.producer-properties.callback composition preserves order and identity",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.empty producer client id retains the native default",+ "rdkafka-hs-integration.public-contract.config-strings.consumer ordinary UTF8 values remain exact",+ "rdkafka-hs-integration.public-contract.config-strings.empty global key retains native unknown-key rejection"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Producer-ProducerProperties-extraProps",+ "symbols": [+ "Kafka.Producer.ProducerProperties.extraProps"+ ],+ "owner": 14,+ "behavior": "extraProps constructs/composes the documented effective settings",+ "inputs": "identity, repeated/conflicting settings, left/right precedence, empty/nonempty lists and boundary numeric/text values",+ "expected": "Exact effective map, callback/poll mode/log level; native validation preserved for invalid values",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Producer properties generated.program follows last-write semantics",+ "rdkafka-hs.Producer properties generated.configuration has left and right identity",+ "rdkafka-hs.Producer properties generated.configuration composition is associative",+ "rdkafka-hs.Producer properties generated.composition appends writes in order",+ "rdkafka-hs.Producer properties generated.unrelated keys survive a conflicting write",+ "rdkafka-hs.Producer properties generated.last explicit log level wins",+ "rdkafka-hs.Producer properties generated.fixed empty duplicate and binary text values",+ "rdkafka-hs.Public data contracts.builders.semigroup defaults retain writes callbacks and subscription union",+ "rdkafka-hs.Public data contracts.builders.consumer builders preserve exact settings and leave other fields unset",+ "rdkafka-hs.Public data contracts.builders.producer builders preserve global versus explicit topic placement",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: invalid topic timeout",+ "rdkafka-hs-integration.producer-properties.callback composition preserves order and identity",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.empty producer client id retains the native default",+ "rdkafka-hs-integration.public-contract.config-strings.consumer ordinary UTF8 values remain exact",+ "rdkafka-hs-integration.public-contract.config-strings.empty global key retains native unknown-key rejection"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Producer-ProducerProperties-logLevel",+ "symbols": [+ "Kafka.Producer.ProducerProperties.logLevel"+ ],+ "owner": 14,+ "behavior": "logLevel constructs/composes the documented effective settings",+ "inputs": "identity, repeated/conflicting settings, left/right precedence, empty/nonempty lists and boundary numeric/text values",+ "expected": "Exact effective map, callback/poll mode/log level; native validation preserved for invalid values",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Producer properties generated.program follows last-write semantics",+ "rdkafka-hs.Producer properties generated.configuration has left and right identity",+ "rdkafka-hs.Producer properties generated.configuration composition is associative",+ "rdkafka-hs.Producer properties generated.composition appends writes in order",+ "rdkafka-hs.Producer properties generated.unrelated keys survive a conflicting write",+ "rdkafka-hs.Producer properties generated.last explicit log level wins",+ "rdkafka-hs.Producer properties generated.fixed empty duplicate and binary text values",+ "rdkafka-hs.Public data contracts.builders.semigroup defaults retain writes callbacks and subscription union",+ "rdkafka-hs.Public data contracts.builders.consumer builders preserve exact settings and leave other fields unset",+ "rdkafka-hs.Public data contracts.builders.producer builders preserve global versus explicit topic placement",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: invalid topic timeout",+ "rdkafka-hs-integration.producer-properties.callback composition preserves order and identity",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.empty producer client id retains the native default",+ "rdkafka-hs-integration.public-contract.config-strings.consumer ordinary UTF8 values remain exact",+ "rdkafka-hs-integration.public-contract.config-strings.empty global key retains native unknown-key rejection"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Producer-ProducerProperties-setCallback",+ "symbols": [+ "Kafka.Producer.ProducerProperties.setCallback"+ ],+ "owner": 14,+ "behavior": "setCallback constructs/composes the documented effective settings",+ "inputs": "identity, repeated/conflicting settings, left/right precedence, empty/nonempty lists and boundary numeric/text values",+ "expected": "Exact effective map, callback/poll mode/log level; native validation preserved for invalid values",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Producer properties generated.program follows last-write semantics",+ "rdkafka-hs.Producer properties generated.configuration has left and right identity",+ "rdkafka-hs.Producer properties generated.configuration composition is associative",+ "rdkafka-hs.Producer properties generated.composition appends writes in order",+ "rdkafka-hs.Producer properties generated.unrelated keys survive a conflicting write",+ "rdkafka-hs.Producer properties generated.last explicit log level wins",+ "rdkafka-hs.Producer properties generated.fixed empty duplicate and binary text values",+ "rdkafka-hs.Public data contracts.builders.semigroup defaults retain writes callbacks and subscription union",+ "rdkafka-hs.Public data contracts.builders.consumer builders preserve exact settings and leave other fields unset",+ "rdkafka-hs.Public data contracts.builders.producer builders preserve global versus explicit topic placement",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: invalid topic timeout",+ "rdkafka-hs-integration.producer-properties.callback composition preserves order and identity",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.empty producer client id retains the native default",+ "rdkafka-hs-integration.public-contract.config-strings.consumer ordinary UTF8 values remain exact",+ "rdkafka-hs-integration.public-contract.config-strings.empty global key retains native unknown-key rejection"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Producer-ProducerProperties-statisticsInterval",+ "symbols": [+ "Kafka.Producer.ProducerProperties.statisticsInterval"+ ],+ "owner": 14,+ "behavior": "statisticsInterval constructs/composes the documented effective settings",+ "inputs": "identity, repeated/conflicting settings, left/right precedence, empty/nonempty lists and boundary numeric/text values",+ "expected": "Exact effective map, callback/poll mode/log level; native validation preserved for invalid values",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Producer properties generated.program follows last-write semantics",+ "rdkafka-hs.Producer properties generated.configuration has left and right identity",+ "rdkafka-hs.Producer properties generated.configuration composition is associative",+ "rdkafka-hs.Producer properties generated.composition appends writes in order",+ "rdkafka-hs.Producer properties generated.unrelated keys survive a conflicting write",+ "rdkafka-hs.Producer properties generated.last explicit log level wins",+ "rdkafka-hs.Producer properties generated.fixed empty duplicate and binary text values",+ "rdkafka-hs.Public data contracts.builders.semigroup defaults retain writes callbacks and subscription union",+ "rdkafka-hs.Public data contracts.builders.consumer builders preserve exact settings and leave other fields unset",+ "rdkafka-hs.Public data contracts.builders.producer builders preserve global versus explicit topic placement",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: invalid topic timeout",+ "rdkafka-hs-integration.producer-properties.callback composition preserves order and identity",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.empty producer client id retains the native default",+ "rdkafka-hs-integration.public-contract.config-strings.consumer ordinary UTF8 values remain exact",+ "rdkafka-hs-integration.public-contract.config-strings.empty global key retains native unknown-key rejection"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Producer-ProducerProperties-suppressDisconnectLogs",+ "symbols": [+ "Kafka.Producer.ProducerProperties.suppressDisconnectLogs"+ ],+ "owner": 14,+ "behavior": "suppressDisconnectLogs constructs/composes the documented effective settings",+ "inputs": "identity, repeated/conflicting settings, left/right precedence, empty/nonempty lists and boundary numeric/text values",+ "expected": "Exact effective map, callback/poll mode/log level; native validation preserved for invalid values",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Producer properties generated.program follows last-write semantics",+ "rdkafka-hs.Producer properties generated.configuration has left and right identity",+ "rdkafka-hs.Producer properties generated.configuration composition is associative",+ "rdkafka-hs.Producer properties generated.composition appends writes in order",+ "rdkafka-hs.Producer properties generated.unrelated keys survive a conflicting write",+ "rdkafka-hs.Producer properties generated.last explicit log level wins",+ "rdkafka-hs.Producer properties generated.fixed empty duplicate and binary text values",+ "rdkafka-hs.Public data contracts.builders.semigroup defaults retain writes callbacks and subscription union",+ "rdkafka-hs.Public data contracts.builders.consumer builders preserve exact settings and leave other fields unset",+ "rdkafka-hs.Public data contracts.builders.producer builders preserve global versus explicit topic placement",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: invalid topic timeout",+ "rdkafka-hs-integration.producer-properties.callback composition preserves order and identity",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.empty producer client id retains the native default",+ "rdkafka-hs-integration.public-contract.config-strings.consumer ordinary UTF8 values remain exact",+ "rdkafka-hs-integration.public-contract.config-strings.empty global key retains native unknown-key rejection"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Producer-Types-DeliveryReport",+ "symbols": [+ "Kafka.Producer.Types.DeliveryReport"+ ],+ "owner": 14,+ "behavior": "DeliveryReport exposes its documented constructors, record selectors and typeclass laws",+ "inputs": "Every exported constructor/member in the compiler export inventory; generated boundary and ordinary field values",+ "expected": "Construction/selection round trips; declared equality/order/show/enum/functor/traversal instances obey their documented laws",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.representations.text newtypes preserve arbitrary represented text",+ "rdkafka-hs.Public properties.representations.integer newtypes preserve signed machine boundaries",+ "rdkafka-hs.Public properties.representations.offset and milliseconds preserve signed 64-bit boundaries",+ "rdkafka-hs.Public properties.representations.timestamp constructors retain their represented boundary",+ "rdkafka-hs.Public properties.representations.system topic classification requires two initial underscores",+ "rdkafka-hs.Public properties.representations.fixed empty underscore and signed numeric boundaries",+ "rdkafka-hs.Public data contracts.representations.numeric ordering and reads agree with represented signed values",+ "rdkafka-hs.Public data contracts.representations.numeric instances preserve primitive arithmetic including boundaries",+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.consumer variants retain fields and distinguish constructors",+ "rdkafka-hs.Public data contracts.representations.producer records delivery variants and topic requests retain exact fields",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs.Public data contracts.representations.every Kafka error preserves its Exception identity and generic form"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Producer-Types-ImmediateError",+ "symbols": [+ "Kafka.Producer.Types.ImmediateError"+ ],+ "owner": 16,+ "behavior": "ImmediateError exposes its documented constructors, record selectors and typeclass laws",+ "inputs": "Every exported constructor/member in the compiler export inventory; generated boundary and ordinary field values",+ "expected": "Construction/selection round trips; declared equality/order/show/enum/functor/traversal instances obey their documented laws",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public data contracts.representations.producer records delivery variants and topic requests retain exact fields"+ ],+ "status": "tested",+ "previous_owner": 14,+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ {+ "id": "API-Kafka-Producer-Types-KafkaProducer",+ "symbols": [+ "Kafka.Producer.Types.KafkaProducer"+ ],+ "owner": 14,+ "behavior": "KafkaProducer exposes its documented constructors, record selectors and typeclass laws",+ "inputs": "Every exported constructor/member in the compiler export inventory; generated boundary and ordinary field values",+ "expected": "Construction/selection round trips; declared equality/order/show/enum/functor/traversal instances obey their documented laws",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs-integration.public-contract.deprecated-runners.producer flushes after Returned",+ "rdkafka-hs-integration.public-contract.deprecated-runners.producer flushes after Refused",+ "rdkafka-hs-integration.public-contract.deprecated-runners.producer flushes after Thrown",+ "rdkafka-hs-integration.public-contract.deprecated-runners.producer preserves native construction failure without invoking handler",+ "rdkafka-hs-integration.public-contract.deprecated-runners.producer preserves configuration exceptions without invoking handler"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ {+ "id": "API-Kafka-Producer-Types-ProducePartition",+ "symbols": [+ "Kafka.Producer.Types.ProducePartition"+ ],+ "owner": 14,+ "behavior": "ProducePartition exposes its documented constructors, record selectors and typeclass laws",+ "inputs": "Every exported constructor/member in the compiler export inventory; generated boundary and ordinary field values",+ "expected": "Construction/selection round trips; declared equality/order/show/enum/functor/traversal instances obey their documented laws",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.representations.text newtypes preserve arbitrary represented text",+ "rdkafka-hs.Public properties.representations.integer newtypes preserve signed machine boundaries",+ "rdkafka-hs.Public properties.representations.offset and milliseconds preserve signed 64-bit boundaries",+ "rdkafka-hs.Public properties.representations.timestamp constructors retain their represented boundary",+ "rdkafka-hs.Public properties.representations.system topic classification requires two initial underscores",+ "rdkafka-hs.Public properties.representations.fixed empty underscore and signed numeric boundaries",+ "rdkafka-hs.Public data contracts.representations.numeric ordering and reads agree with represented signed values",+ "rdkafka-hs.Public data contracts.representations.numeric instances preserve primitive arithmetic including boundaries",+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.consumer variants retain fields and distinguish constructors",+ "rdkafka-hs.Public data contracts.representations.producer records delivery variants and topic requests retain exact fields",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs.Public data contracts.representations.every Kafka error preserves its Exception identity and generic form"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Producer-Types-ProducerRecord",+ "symbols": [+ "Kafka.Producer.Types.ProducerRecord"+ ],+ "owner": 14,+ "behavior": "ProducerRecord exposes its documented constructors, record selectors and typeclass laws",+ "inputs": "Every exported constructor/member in the compiler export inventory; generated boundary and ordinary field values",+ "expected": "Construction/selection round trips; declared equality/order/show/enum/functor/traversal instances obey their documented laws",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.representations.text newtypes preserve arbitrary represented text",+ "rdkafka-hs.Public properties.representations.integer newtypes preserve signed machine boundaries",+ "rdkafka-hs.Public properties.representations.offset and milliseconds preserve signed 64-bit boundaries",+ "rdkafka-hs.Public properties.representations.timestamp constructors retain their represented boundary",+ "rdkafka-hs.Public properties.representations.system topic classification requires two initial underscores",+ "rdkafka-hs.Public properties.representations.fixed empty underscore and signed numeric boundaries",+ "rdkafka-hs.Public data contracts.representations.numeric ordering and reads agree with represented signed values",+ "rdkafka-hs.Public data contracts.representations.numeric instances preserve primitive arithmetic including boundaries",+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.consumer variants retain fields and distinguish constructors",+ "rdkafka-hs.Public data contracts.representations.producer records delivery variants and topic requests retain exact fields",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs.Public data contracts.representations.every Kafka error preserves its Exception identity and generic form"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Producer-Types-PurgeFlag",+ "symbols": [+ "Kafka.Producer.Types.PurgeFlag"+ ],+ "owner": 14,+ "behavior": "PurgeFlag exposes its documented constructors, record selectors and typeclass laws",+ "inputs": "Every exported constructor/member in the compiler export inventory; generated boundary and ordinary field values",+ "expected": "Construction/selection round trips; declared equality/order/show/enum/functor/traversal instances obey their documented laws",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.representations.text newtypes preserve arbitrary represented text",+ "rdkafka-hs.Public properties.representations.integer newtypes preserve signed machine boundaries",+ "rdkafka-hs.Public properties.representations.offset and milliseconds preserve signed 64-bit boundaries",+ "rdkafka-hs.Public properties.representations.timestamp constructors retain their represented boundary",+ "rdkafka-hs.Public properties.representations.system topic classification requires two initial underscores",+ "rdkafka-hs.Public properties.representations.fixed empty underscore and signed numeric boundaries",+ "rdkafka-hs.Public data contracts.representations.numeric ordering and reads agree with represented signed values",+ "rdkafka-hs.Public data contracts.representations.numeric instances preserve primitive arithmetic including boundaries",+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.consumer variants retain fields and distinguish constructors",+ "rdkafka-hs.Public data contracts.representations.producer records delivery variants and topic requests retain exact fields",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs.Public data contracts.representations.every Kafka error preserves its Exception identity and generic form"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Producer-flushProducer",+ "symbols": [+ "Kafka.Producer.flushProducer"+ ],+ "owner": 14,+ "behavior": "Flush until accepted records report completion",+ "inputs": "empty, multiple records, delivery failure",+ "expected": "Queue drains; matching callbacks all served",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs-integration.producer-regressions.accepted callback retains its capture until a purged report completes",+ "rdkafka-hs-integration.producer-regressions.throwing global callback preserves per-message delivery and releases capture",+ "rdkafka-hs-integration.producer-regressions.throwing per-message callback reports exception and releases capture",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: none",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: inflight",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue+inflight",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue+nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: inflight+nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: all",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: none",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: inflight",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue+inflight",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue+nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: inflight+nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: all",+ "rdkafka-hs-integration.producer-regressions.bounded flush timeout recovers when the delayed response arrives",+ "rdkafka-hs-integration.producer-regressions.empty queue supports repeated flush and close"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Producer-flushProducerTimeout",+ "symbols": [+ "Kafka.Producer.flushProducerTimeout"+ ],+ "owner": 14,+ "behavior": "Bound producer flush and report remaining work",+ "inputs": "empty, pending/unreachable, zero/short/positive timeout",+ "expected": "Nothing iff drained; exact timeout otherwise; elapsed time bounded",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs-integration.producer-regressions.accepted callback retains its capture until a purged report completes",+ "rdkafka-hs-integration.producer-regressions.throwing global callback preserves per-message delivery and releases capture",+ "rdkafka-hs-integration.producer-regressions.throwing per-message callback reports exception and releases capture",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: none",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: inflight",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue+inflight",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue+nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: inflight+nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: all",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: none",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: inflight",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue+inflight",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue+nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: inflight+nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: all",+ "rdkafka-hs-integration.producer-regressions.bounded flush timeout recovers when the delayed response arrives",+ "rdkafka-hs-integration.producer-regressions.empty queue supports repeated flush and close"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Producer-purgeProducer",+ "symbols": [+ "Kafka.Producer.purgeProducer"+ ],+ "owner": 14,+ "behavior": "Purge selected outbound queue stages",+ "inputs": "empty flags, queued, inflight, both, nonblocking, repeated purge",+ "expected": "Exact delivery purge errors for affected records; unaffected work retained",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs-integration.producer-regressions.accepted callback retains its capture until a purged report completes",+ "rdkafka-hs-integration.producer-regressions.throwing global callback preserves per-message delivery and releases capture",+ "rdkafka-hs-integration.producer-regressions.throwing per-message callback reports exception and releases capture",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: none",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: inflight",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue+inflight",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue+nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: inflight+nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: all",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: none",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: inflight",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue+inflight",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue+nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: inflight+nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: all",+ "rdkafka-hs-integration.producer-regressions.bounded flush timeout recovers when the delayed response arrives",+ "rdkafka-hs-integration.producer-regressions.empty queue supports repeated flush and close"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Producer-runProducer",+ "symbols": [+ "Kafka.Producer.runProducer"+ ],+ "owner": 14,+ "behavior": "Deprecated wrapper preserves callback result and flushes on cleanup",+ "inputs": "valid/invalid config and callback exception",+ "expected": "Equivalent construction/cleanup behavior and returned result",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs-integration.public-contract.deprecated-runners.producer flushes after Returned",+ "rdkafka-hs-integration.public-contract.deprecated-runners.producer flushes after Refused",+ "rdkafka-hs-integration.public-contract.deprecated-runners.producer flushes after Thrown",+ "rdkafka-hs-integration.public-contract.deprecated-runners.producer preserves native construction failure without invoking handler",+ "rdkafka-hs-integration.public-contract.deprecated-runners.producer preserves configuration exceptions without invoking handler"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ {+ "id": "API-Kafka-Producer-setSaslCredentials",+ "symbols": [+ "Kafka.Producer.setSaslCredentials"+ ],+ "owner": 19,+ "behavior": "Replace credentials used by live authentication",+ "inputs": "valid, invalid and replacement credentials against isolated SASL broker",+ "expected": "Authenticated broker access succeeds/fails for actual credentials",+ "modes": "producer and consumer with actual SASL authentication/authorization",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs-integration.lifecycle.setSaslCredentials replaces credentials on a consumer",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials replaces credentials on a producer",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials rejects NUL in username without changing producer or consumer identity",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials rejects NUL in password without changing producer or consumer identity",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials releases each actual native error after decoding its exact code",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials cancellation at error decoding releases the owned error",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials cancellation at error acquisition releases the owned error",+ "authentication-contract.producer credential replacement authenticates a new identity after observed reconnect and recovers from invalid replacement"+ ],+ "status": "tested",+ "previous_owner": 15,+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence": [+ "docs/testing/coverage-evidence.json",+ "docs/testing/compatibility-matrix.json"+ ]+ },+ {+ "id": "API-Kafka-Topic-Types-NewTopic",+ "symbols": [+ "Kafka.Topic.Types.NewTopic"+ ],+ "owner": 14,+ "behavior": "NewTopic exposes its documented constructors, record selectors and typeclass laws",+ "inputs": "Every exported constructor/member in the compiler export inventory; generated boundary and ordinary field values",+ "expected": "Construction/selection round trips; declared equality/order/show/enum/functor/traversal instances obey their documented laws",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.representations.text newtypes preserve arbitrary represented text",+ "rdkafka-hs.Public properties.representations.integer newtypes preserve signed machine boundaries",+ "rdkafka-hs.Public properties.representations.offset and milliseconds preserve signed 64-bit boundaries",+ "rdkafka-hs.Public properties.representations.timestamp constructors retain their represented boundary",+ "rdkafka-hs.Public properties.representations.system topic classification requires two initial underscores",+ "rdkafka-hs.Public properties.representations.fixed empty underscore and signed numeric boundaries",+ "rdkafka-hs.Public data contracts.representations.numeric ordering and reads agree with represented signed values",+ "rdkafka-hs.Public data contracts.representations.numeric instances preserve primitive arithmetic including boundaries",+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.consumer variants retain fields and distinguish constructors",+ "rdkafka-hs.Public data contracts.representations.producer records delivery variants and topic requests retain exact fields",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs.Public data contracts.representations.every Kafka error preserves its Exception identity and generic form"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Topic-Types-PartitionCount",+ "symbols": [+ "Kafka.Topic.Types.PartitionCount"+ ],+ "owner": 14,+ "behavior": "PartitionCount exposes its documented constructors, record selectors and typeclass laws",+ "inputs": "Every exported constructor/member in the compiler export inventory; generated boundary and ordinary field values",+ "expected": "Construction/selection round trips; declared equality/order/show/enum/functor/traversal instances obey their documented laws",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.representations.text newtypes preserve arbitrary represented text",+ "rdkafka-hs.Public properties.representations.integer newtypes preserve signed machine boundaries",+ "rdkafka-hs.Public properties.representations.offset and milliseconds preserve signed 64-bit boundaries",+ "rdkafka-hs.Public properties.representations.timestamp constructors retain their represented boundary",+ "rdkafka-hs.Public properties.representations.system topic classification requires two initial underscores",+ "rdkafka-hs.Public properties.representations.fixed empty underscore and signed numeric boundaries",+ "rdkafka-hs.Public data contracts.representations.numeric ordering and reads agree with represented signed values",+ "rdkafka-hs.Public data contracts.representations.numeric instances preserve primitive arithmetic including boundaries",+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.consumer variants retain fields and distinguish constructors",+ "rdkafka-hs.Public data contracts.representations.producer records delivery variants and topic requests retain exact fields",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs.Public data contracts.representations.every Kafka error preserves its Exception identity and generic form"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Topic-Types-ReplicationFactor",+ "symbols": [+ "Kafka.Topic.Types.ReplicationFactor"+ ],+ "owner": 14,+ "behavior": "ReplicationFactor exposes its documented constructors, record selectors and typeclass laws",+ "inputs": "Every exported constructor/member in the compiler export inventory; generated boundary and ordinary field values",+ "expected": "Construction/selection round trips; declared equality/order/show/enum/functor/traversal instances obey their documented laws",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.representations.text newtypes preserve arbitrary represented text",+ "rdkafka-hs.Public properties.representations.integer newtypes preserve signed machine boundaries",+ "rdkafka-hs.Public properties.representations.offset and milliseconds preserve signed 64-bit boundaries",+ "rdkafka-hs.Public properties.representations.timestamp constructors retain their represented boundary",+ "rdkafka-hs.Public properties.representations.system topic classification requires two initial underscores",+ "rdkafka-hs.Public properties.representations.fixed empty underscore and signed numeric boundaries",+ "rdkafka-hs.Public data contracts.representations.numeric ordering and reads agree with represented signed values",+ "rdkafka-hs.Public data contracts.representations.numeric instances preserve primitive arithmetic including boundaries",+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.consumer variants retain fields and distinguish constructors",+ "rdkafka-hs.Public data contracts.representations.producer records delivery variants and topic requests retain exact fields",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs.Public data contracts.representations.every Kafka error preserves its Exception identity and generic form"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Topic-deleteTopic",+ "symbols": [+ "Kafka.Topic.deleteTopic"+ ],+ "owner": 8,+ "behavior": "Delete only the named run-owned topic and report broker/admin errors",+ "inputs": "existing/missing topic; invalid NUL name; request timeout; malformed event/result; producer and async/sync consumer clients before/after graceful close",+ "expected": "Exact deleted topic and verified absence; unrelated topic survives; errors retain native codes; all owned references released",+ "modes": "all supported modes",+ "ownership": "DeleteTopic/admin options/queue/event released on success, error and exception",+ "tests": [+ "rdkafka-hs-integration.topic-configuration.singleton configuration reaches the broker",+ "rdkafka-hs-integration.topic-configuration.deletion removes exactly the existing topic",+ "rdkafka-hs-integration.topic-configuration.missing topic deletion preserves its error and releases the request",+ "rdkafka-hs-integration.topic-configuration.NUL deletion cannot remove a truncated victim name",+ "rdkafka-hs-integration.topic-configuration.consumer administration applies settings in async mode",+ "rdkafka-hs-integration.topic-configuration.consumer administration applies settings in sync mode",+ "rdkafka-hs-integration.topic-configuration.consumer administration applies settings in async-closed mode",+ "rdkafka-hs-integration.topic-configuration.consumer administration applies settings in sync-closed mode",+ "rdkafka-hs-integration.topic-configuration.unresponsive deletion preserves the native timeout error",+ "rdkafka-hs-integration.topic-configuration.deletion rejects a wrong event type and releases it",+ "rdkafka-hs-integration.topic-configuration.deletion rejects an empty result and releases its event",+ "rdkafka-hs-integration.topic-configuration.deletion rejects a mismatched topic result",+ "rdkafka-hs-integration.topic-configuration.deletion reports a missing response as a timeout"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Transaction-TxError",+ "symbols": [+ "Kafka.Transaction.TxError"+ ],+ "owner": 12,+ "behavior": "TxError preserves transaction error code and classification",+ "inputs": "null/success; ordinary, retriable, fatal and abort-required native errors",+ "expected": "Exact Haskell error and native predicate flags; no dangling error pointer",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs-integration.transaction-errors.transaction state errors preserve empty commit and abort recovery",+ "rdkafka-hs-integration.transaction-errors.duplicate transactional IDs report a real fatal fencing error",+ "rdkafka-hs-integration.transaction-errors.broker-rejected delivery requires abort and permits a successful new transaction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 0 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 1 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 2 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 3 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 4 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 5 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 6 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 7 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 0 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 1 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 2 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 3 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 4 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 5 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 6 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 7 before destruction"+ ],+ "status": "tested",+ "mutations": "dist-mutations/20261024T141053Z-transaction-39758-0/results.json",+ "native_diagnostics": "docs/testing/transaction-native-diagnostics.json",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Transaction-commitOffsetMessageTransaction",+ "symbols": [+ "Kafka.Transaction.commitOffsetMessageTransaction"+ ],+ "owner": 12,+ "behavior": "Commit consumer next offsets with transaction",+ "inputs": "commit, abort, invalid state, missing metadata and broker failure",+ "expected": "Group offset advances to record offset + 1 only on successful transaction commit",+ "modes": "all supported modes",+ "ownership": "Call-scoped transaction error and temporary group metadata/partition list released on every exit",+ "tests": [+ "rdkafka-hs-integration.transaction-errors.offset without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.offset NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.offset invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 0 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 1 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 2 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 3 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 4 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 5 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 6 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 7 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 21 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 22 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 23 releases once",+ "rdkafka-hs-integration.transaction-errors.async commit publishes output and source next offset atomically; abort publishes neither",+ "rdkafka-hs-integration.transaction-errors.sync commit publishes output and source next offset atomically; abort publishes neither"+ ],+ "status": "tested",+ "mutations": "dist-mutations/20261024T141053Z-transaction-39758-0/results.json",+ "native_diagnostics": "docs/testing/transaction-native-diagnostics.json",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Transaction-commitTransaction",+ "symbols": [+ "Kafka.Transaction.commitTransaction"+ ],+ "owner": 12,+ "behavior": "Commit produced records atomically",+ "inputs": "success, no transaction, timeout, retriable/fatal/abortable failure",+ "expected": "Committed records visible only after success; exact TxError classification",+ "modes": "all supported modes",+ "ownership": "Call-scoped transaction error and temporary group metadata/partition list released on every exit",+ "tests": [+ "rdkafka-hs-integration.transaction-errors.zero-timeout initialization resumes successfully against the broker",+ "rdkafka-hs-integration.transaction-errors.transaction state errors preserve empty commit and abort recovery",+ "rdkafka-hs-integration.transaction-errors.duplicate transactional IDs report a real fatal fencing error",+ "rdkafka-hs-integration.transaction-errors.commit without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.commit NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.commit invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 0 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 1 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 2 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 3 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 4 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 5 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 6 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 7 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 21 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 22 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 23 releases once",+ "rdkafka-hs-integration.transaction-errors.async commit publishes output and source next offset atomically; abort publishes neither",+ "rdkafka-hs-integration.transaction-errors.sync commit publishes output and source next offset atomically; abort publishes neither"+ ],+ "status": "tested",+ "mutations": "dist-mutations/20261024T141053Z-transaction-39758-0/results.json",+ "native_diagnostics": "docs/testing/transaction-native-diagnostics.json",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Transaction-getKafkaError",+ "symbols": [+ "Kafka.Transaction.getKafkaError"+ ],+ "owner": 12,+ "behavior": "getKafkaError preserves transaction error code and classification",+ "inputs": "null/success; ordinary, retriable, fatal and abort-required native errors",+ "expected": "Exact Haskell error and native predicate flags; no dangling error pointer",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs-integration.transaction-errors.transaction state errors preserve empty commit and abort recovery",+ "rdkafka-hs-integration.transaction-errors.duplicate transactional IDs report a real fatal fencing error",+ "rdkafka-hs-integration.transaction-errors.broker-rejected delivery requires abort and permits a successful new transaction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 0 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 1 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 2 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 3 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 4 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 5 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 6 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 7 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 0 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 1 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 2 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 3 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 4 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 5 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 6 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 7 before destruction"+ ],+ "status": "tested",+ "mutations": "dist-mutations/20261024T141053Z-transaction-39758-0/results.json",+ "native_diagnostics": "docs/testing/transaction-native-diagnostics.json",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Transaction-kafkaErrorIsFatal",+ "symbols": [+ "Kafka.Transaction.kafkaErrorIsFatal"+ ],+ "owner": 12,+ "behavior": "kafkaErrorIsFatal preserves transaction error code and classification",+ "inputs": "null/success; ordinary, retriable, fatal and abort-required native errors",+ "expected": "Exact Haskell error and native predicate flags; no dangling error pointer",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs-integration.transaction-errors.transaction state errors preserve empty commit and abort recovery",+ "rdkafka-hs-integration.transaction-errors.duplicate transactional IDs report a real fatal fencing error",+ "rdkafka-hs-integration.transaction-errors.broker-rejected delivery requires abort and permits a successful new transaction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 0 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 1 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 2 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 3 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 4 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 5 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 6 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 7 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 0 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 1 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 2 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 3 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 4 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 5 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 6 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 7 before destruction"+ ],+ "status": "tested",+ "mutations": "dist-mutations/20261024T141053Z-transaction-39758-0/results.json",+ "native_diagnostics": "docs/testing/transaction-native-diagnostics.json",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Transaction-kafkaErrorIsRetriable",+ "symbols": [+ "Kafka.Transaction.kafkaErrorIsRetriable"+ ],+ "owner": 12,+ "behavior": "kafkaErrorIsRetriable preserves transaction error code and classification",+ "inputs": "null/success; ordinary, retriable, fatal and abort-required native errors",+ "expected": "Exact Haskell error and native predicate flags; no dangling error pointer",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs-integration.transaction-errors.transaction state errors preserve empty commit and abort recovery",+ "rdkafka-hs-integration.transaction-errors.duplicate transactional IDs report a real fatal fencing error",+ "rdkafka-hs-integration.transaction-errors.broker-rejected delivery requires abort and permits a successful new transaction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 0 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 1 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 2 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 3 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 4 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 5 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 6 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 7 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 0 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 1 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 2 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 3 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 4 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 5 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 6 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 7 before destruction"+ ],+ "status": "tested",+ "mutations": "dist-mutations/20261024T141053Z-transaction-39758-0/results.json",+ "native_diagnostics": "docs/testing/transaction-native-diagnostics.json",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Transaction-kafkaErrorTxnRequiresAbort",+ "symbols": [+ "Kafka.Transaction.kafkaErrorTxnRequiresAbort"+ ],+ "owner": 12,+ "behavior": "kafkaErrorTxnRequiresAbort preserves transaction error code and classification",+ "inputs": "null/success; ordinary, retriable, fatal and abort-required native errors",+ "expected": "Exact Haskell error and native predicate flags; no dangling error pointer",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs-integration.transaction-errors.transaction state errors preserve empty commit and abort recovery",+ "rdkafka-hs-integration.transaction-errors.duplicate transactional IDs report a real fatal fencing error",+ "rdkafka-hs-integration.transaction-errors.broker-rejected delivery requires abort and permits a successful new transaction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 0 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 1 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 2 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 3 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 4 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 5 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 6 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 7 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 0 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 1 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 2 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 3 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 4 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 5 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 6 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 7 before destruction"+ ],+ "status": "tested",+ "mutations": "dist-mutations/20261024T141053Z-transaction-39758-0/results.json",+ "native_diagnostics": "docs/testing/transaction-native-diagnostics.json",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Types-BatchSize",+ "symbols": [+ "Kafka.Types.BatchSize"+ ],+ "owner": 14,+ "behavior": "BatchSize exposes its documented constructors, record selectors and typeclass laws",+ "inputs": "Every exported constructor/member in the compiler export inventory; generated boundary and ordinary field values",+ "expected": "Construction/selection round trips; declared equality/order/show/enum/functor/traversal instances obey their documented laws",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.representations.text newtypes preserve arbitrary represented text",+ "rdkafka-hs.Public properties.representations.integer newtypes preserve signed machine boundaries",+ "rdkafka-hs.Public properties.representations.offset and milliseconds preserve signed 64-bit boundaries",+ "rdkafka-hs.Public properties.representations.timestamp constructors retain their represented boundary",+ "rdkafka-hs.Public properties.representations.system topic classification requires two initial underscores",+ "rdkafka-hs.Public properties.representations.fixed empty underscore and signed numeric boundaries",+ "rdkafka-hs.Public data contracts.representations.numeric ordering and reads agree with represented signed values",+ "rdkafka-hs.Public data contracts.representations.numeric instances preserve primitive arithmetic including boundaries",+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.consumer variants retain fields and distinguish constructors",+ "rdkafka-hs.Public data contracts.representations.producer records delivery variants and topic requests retain exact fields",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs.Public data contracts.representations.every Kafka error preserves its Exception identity and generic form"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Types-BrokerAddress",+ "symbols": [+ "Kafka.Types.BrokerAddress"+ ],+ "owner": 14,+ "behavior": "BrokerAddress exposes its documented constructors, record selectors and typeclass laws",+ "inputs": "Every exported constructor/member in the compiler export inventory; generated boundary and ordinary field values",+ "expected": "Construction/selection round trips; declared equality/order/show/enum/functor/traversal instances obey their documented laws",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.representations.text newtypes preserve arbitrary represented text",+ "rdkafka-hs.Public properties.representations.integer newtypes preserve signed machine boundaries",+ "rdkafka-hs.Public properties.representations.offset and milliseconds preserve signed 64-bit boundaries",+ "rdkafka-hs.Public properties.representations.timestamp constructors retain their represented boundary",+ "rdkafka-hs.Public properties.representations.system topic classification requires two initial underscores",+ "rdkafka-hs.Public properties.representations.fixed empty underscore and signed numeric boundaries",+ "rdkafka-hs.Public data contracts.representations.numeric ordering and reads agree with represented signed values",+ "rdkafka-hs.Public data contracts.representations.numeric instances preserve primitive arithmetic including boundaries",+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.consumer variants retain fields and distinguish constructors",+ "rdkafka-hs.Public data contracts.representations.producer records delivery variants and topic requests retain exact fields",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs.Public data contracts.representations.every Kafka error preserves its Exception identity and generic form"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Types-BrokerId",+ "symbols": [+ "Kafka.Types.BrokerId"+ ],+ "owner": 14,+ "behavior": "BrokerId exposes its documented constructors, record selectors and typeclass laws",+ "inputs": "Every exported constructor/member in the compiler export inventory; generated boundary and ordinary field values",+ "expected": "Construction/selection round trips; declared equality/order/show/enum/functor/traversal instances obey their documented laws",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.representations.text newtypes preserve arbitrary represented text",+ "rdkafka-hs.Public properties.representations.integer newtypes preserve signed machine boundaries",+ "rdkafka-hs.Public properties.representations.offset and milliseconds preserve signed 64-bit boundaries",+ "rdkafka-hs.Public properties.representations.timestamp constructors retain their represented boundary",+ "rdkafka-hs.Public properties.representations.system topic classification requires two initial underscores",+ "rdkafka-hs.Public properties.representations.fixed empty underscore and signed numeric boundaries",+ "rdkafka-hs.Public data contracts.representations.numeric ordering and reads agree with represented signed values",+ "rdkafka-hs.Public data contracts.representations.numeric instances preserve primitive arithmetic including boundaries",+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.consumer variants retain fields and distinguish constructors",+ "rdkafka-hs.Public data contracts.representations.producer records delivery variants and topic requests retain exact fields",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs.Public data contracts.representations.every Kafka error preserves its Exception identity and generic form"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Types-ClientId",+ "symbols": [+ "Kafka.Types.ClientId"+ ],+ "owner": 14,+ "behavior": "ClientId exposes its documented constructors, record selectors and typeclass laws",+ "inputs": "Every exported constructor/member in the compiler export inventory; generated boundary and ordinary field values",+ "expected": "Construction/selection round trips; declared equality/order/show/enum/functor/traversal instances obey their documented laws",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.representations.text newtypes preserve arbitrary represented text",+ "rdkafka-hs.Public properties.representations.integer newtypes preserve signed machine boundaries",+ "rdkafka-hs.Public properties.representations.offset and milliseconds preserve signed 64-bit boundaries",+ "rdkafka-hs.Public properties.representations.timestamp constructors retain their represented boundary",+ "rdkafka-hs.Public properties.representations.system topic classification requires two initial underscores",+ "rdkafka-hs.Public properties.representations.fixed empty underscore and signed numeric boundaries",+ "rdkafka-hs.Public data contracts.representations.numeric ordering and reads agree with represented signed values",+ "rdkafka-hs.Public data contracts.representations.numeric instances preserve primitive arithmetic including boundaries",+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.consumer variants retain fields and distinguish constructors",+ "rdkafka-hs.Public data contracts.representations.producer records delivery variants and topic requests retain exact fields",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs.Public data contracts.representations.every Kafka error preserves its Exception identity and generic form"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Types-Headers",+ "symbols": [+ "Kafka.Types.Headers"+ ],+ "owner": 14,+ "behavior": "Headers exposes its documented constructors, record selectors and typeclass laws",+ "inputs": "Every exported constructor/member in the compiler export inventory; generated boundary and ordinary field values",+ "expected": "Construction/selection round trips; declared equality/order/show/enum/functor/traversal instances obey their documented laws",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.headers.header list round-trip preserves duplicates and binary bytes",+ "rdkafka-hs.Public properties.headers.header concatenation follows list order",+ "rdkafka-hs.Public properties.headers.headers have two identities and associative concatenation",+ "rdkafka-hs.Public properties.headers.fixed duplicate empty and binary header values",+ "rdkafka-hs.Public properties.records.record functor identity",+ "rdkafka-hs.Public properties.records.record functor composition",+ "rdkafka-hs.Public properties.records.record bifunctor identity and composition",+ "rdkafka-hs.Public properties.records.record mapping preserves origin timestamp and headers",+ "rdkafka-hs.Public properties.records.record traversal identity and failure preserve the applicative contract",+ "rdkafka-hs.Public properties.records.record traversal composition preserves nested effects",+ "rdkafka-hs.Public properties.records.record bitraversal visits key before value",+ "rdkafka-hs.Public properties.records.record bitraversal composition preserves nested effects",+ "rdkafka-hs.Public properties.records.record folds retain key and value order",+ "rdkafka-hs.Public properties.records.deprecated record mapping remains equivalent",+ "rdkafka-hs.Public properties.records.deprecated traversal helpers preserve successful effects",+ "rdkafka-hs.Public properties.records.deprecated traversal helpers preserve failed effects"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Types-KafkaCompressionCodec",+ "symbols": [+ "Kafka.Types.KafkaCompressionCodec"+ ],+ "owner": 14,+ "behavior": "KafkaCompressionCodec exposes its documented constructors, record selectors and typeclass laws",+ "inputs": "Every exported constructor/member in the compiler export inventory; generated boundary and ordinary field values",+ "expected": "Construction/selection round trips; declared equality/order/show/enum/functor/traversal instances obey their documented laws",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.representations.text newtypes preserve arbitrary represented text",+ "rdkafka-hs.Public properties.representations.integer newtypes preserve signed machine boundaries",+ "rdkafka-hs.Public properties.representations.offset and milliseconds preserve signed 64-bit boundaries",+ "rdkafka-hs.Public properties.representations.timestamp constructors retain their represented boundary",+ "rdkafka-hs.Public properties.representations.system topic classification requires two initial underscores",+ "rdkafka-hs.Public properties.representations.fixed empty underscore and signed numeric boundaries",+ "rdkafka-hs.Public data contracts.representations.numeric ordering and reads agree with represented signed values",+ "rdkafka-hs.Public data contracts.representations.numeric instances preserve primitive arithmetic including boundaries",+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.consumer variants retain fields and distinguish constructors",+ "rdkafka-hs.Public data contracts.representations.producer records delivery variants and topic requests retain exact fields",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs.Public data contracts.representations.every Kafka error preserves its Exception identity and generic form",+ "rdkafka-hs.Public properties.every compression debug and log enumeration has its native spelling",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Types-KafkaDebug",+ "symbols": [+ "Kafka.Types.KafkaDebug"+ ],+ "owner": 14,+ "behavior": "KafkaDebug exposes its documented constructors, record selectors and typeclass laws",+ "inputs": "Every exported constructor/member in the compiler export inventory; generated boundary and ordinary field values",+ "expected": "Construction/selection round trips; declared equality/order/show/enum/functor/traversal instances obey their documented laws",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.representations.text newtypes preserve arbitrary represented text",+ "rdkafka-hs.Public properties.representations.integer newtypes preserve signed machine boundaries",+ "rdkafka-hs.Public properties.representations.offset and milliseconds preserve signed 64-bit boundaries",+ "rdkafka-hs.Public properties.representations.timestamp constructors retain their represented boundary",+ "rdkafka-hs.Public properties.representations.system topic classification requires two initial underscores",+ "rdkafka-hs.Public properties.representations.fixed empty underscore and signed numeric boundaries",+ "rdkafka-hs.Public data contracts.representations.numeric ordering and reads agree with represented signed values",+ "rdkafka-hs.Public data contracts.representations.numeric instances preserve primitive arithmetic including boundaries",+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.consumer variants retain fields and distinguish constructors",+ "rdkafka-hs.Public data contracts.representations.producer records delivery variants and topic requests retain exact fields",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs.Public data contracts.representations.every Kafka error preserves its Exception identity and generic form",+ "rdkafka-hs.Public properties.every compression debug and log enumeration has its native spelling",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Types-KafkaError",+ "symbols": [+ "Kafka.Types.KafkaError"+ ],+ "owner": 14,+ "behavior": "KafkaError exposes its documented constructors, record selectors and typeclass laws",+ "inputs": "Every exported constructor/member in the compiler export inventory; generated boundary and ordinary field values",+ "expected": "Construction/selection round trips; declared equality/order/show/enum/functor/traversal instances obey their documented laws",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.representations.text newtypes preserve arbitrary represented text",+ "rdkafka-hs.Public properties.representations.integer newtypes preserve signed machine boundaries",+ "rdkafka-hs.Public properties.representations.offset and milliseconds preserve signed 64-bit boundaries",+ "rdkafka-hs.Public properties.representations.timestamp constructors retain their represented boundary",+ "rdkafka-hs.Public properties.representations.system topic classification requires two initial underscores",+ "rdkafka-hs.Public properties.representations.fixed empty underscore and signed numeric boundaries",+ "rdkafka-hs.Public data contracts.representations.numeric ordering and reads agree with represented signed values",+ "rdkafka-hs.Public data contracts.representations.numeric instances preserve primitive arithmetic including boundaries",+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.consumer variants retain fields and distinguish constructors",+ "rdkafka-hs.Public data contracts.representations.producer records delivery variants and topic requests retain exact fields",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs.Public data contracts.representations.every Kafka error preserves its Exception identity and generic form",+ "rdkafka-hs.Public properties.every compression debug and log enumeration has its native spelling",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs.Public data contracts.all linked native errors retain sparse numeric codes names and descriptions"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Types-KafkaLogLevel",+ "symbols": [+ "Kafka.Types.KafkaLogLevel"+ ],+ "owner": 14,+ "behavior": "KafkaLogLevel exposes its documented constructors, record selectors and typeclass laws",+ "inputs": "Every exported constructor/member in the compiler export inventory; generated boundary and ordinary field values",+ "expected": "Construction/selection round trips; declared equality/order/show/enum/functor/traversal instances obey their documented laws",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.representations.text newtypes preserve arbitrary represented text",+ "rdkafka-hs.Public properties.representations.integer newtypes preserve signed machine boundaries",+ "rdkafka-hs.Public properties.representations.offset and milliseconds preserve signed 64-bit boundaries",+ "rdkafka-hs.Public properties.representations.timestamp constructors retain their represented boundary",+ "rdkafka-hs.Public properties.representations.system topic classification requires two initial underscores",+ "rdkafka-hs.Public properties.representations.fixed empty underscore and signed numeric boundaries",+ "rdkafka-hs.Public data contracts.representations.numeric ordering and reads agree with represented signed values",+ "rdkafka-hs.Public data contracts.representations.numeric instances preserve primitive arithmetic including boundaries",+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.consumer variants retain fields and distinguish constructors",+ "rdkafka-hs.Public data contracts.representations.producer records delivery variants and topic requests retain exact fields",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs.Public data contracts.representations.every Kafka error preserves its Exception identity and generic form",+ "rdkafka-hs.Public properties.every compression debug and log enumeration has its native spelling",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs.Public data contracts.all linked native errors retain sparse numeric codes names and descriptions"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Types-Millis",+ "symbols": [+ "Kafka.Types.Millis"+ ],+ "owner": 14,+ "behavior": "Millis exposes its documented constructors, record selectors and typeclass laws",+ "inputs": "Every exported constructor/member in the compiler export inventory; generated boundary and ordinary field values",+ "expected": "Construction/selection round trips; declared equality/order/show/enum/functor/traversal instances obey their documented laws",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.representations.text newtypes preserve arbitrary represented text",+ "rdkafka-hs.Public properties.representations.integer newtypes preserve signed machine boundaries",+ "rdkafka-hs.Public properties.representations.offset and milliseconds preserve signed 64-bit boundaries",+ "rdkafka-hs.Public properties.representations.timestamp constructors retain their represented boundary",+ "rdkafka-hs.Public properties.representations.system topic classification requires two initial underscores",+ "rdkafka-hs.Public properties.representations.fixed empty underscore and signed numeric boundaries",+ "rdkafka-hs.Public data contracts.representations.numeric ordering and reads agree with represented signed values",+ "rdkafka-hs.Public data contracts.representations.numeric instances preserve primitive arithmetic including boundaries",+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.consumer variants retain fields and distinguish constructors",+ "rdkafka-hs.Public data contracts.representations.producer records delivery variants and topic requests retain exact fields",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs.Public data contracts.representations.every Kafka error preserves its Exception identity and generic form",+ "rdkafka-hs.Public properties.every compression debug and log enumeration has its native spelling",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs.Public data contracts.all linked native errors retain sparse numeric codes names and descriptions"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Types-PartitionId",+ "symbols": [+ "Kafka.Types.PartitionId"+ ],+ "owner": 14,+ "behavior": "PartitionId exposes its documented constructors, record selectors and typeclass laws",+ "inputs": "Every exported constructor/member in the compiler export inventory; generated boundary and ordinary field values",+ "expected": "Construction/selection round trips; declared equality/order/show/enum/functor/traversal instances obey their documented laws",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.representations.text newtypes preserve arbitrary represented text",+ "rdkafka-hs.Public properties.representations.integer newtypes preserve signed machine boundaries",+ "rdkafka-hs.Public properties.representations.offset and milliseconds preserve signed 64-bit boundaries",+ "rdkafka-hs.Public properties.representations.timestamp constructors retain their represented boundary",+ "rdkafka-hs.Public properties.representations.system topic classification requires two initial underscores",+ "rdkafka-hs.Public properties.representations.fixed empty underscore and signed numeric boundaries",+ "rdkafka-hs.Public data contracts.representations.numeric ordering and reads agree with represented signed values",+ "rdkafka-hs.Public data contracts.representations.numeric instances preserve primitive arithmetic including boundaries",+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.consumer variants retain fields and distinguish constructors",+ "rdkafka-hs.Public data contracts.representations.producer records delivery variants and topic requests retain exact fields",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs.Public data contracts.representations.every Kafka error preserves its Exception identity and generic form",+ "rdkafka-hs.Public properties.every compression debug and log enumeration has its native spelling",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs.Public data contracts.all linked native errors retain sparse numeric codes names and descriptions"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Types-Timeout",+ "symbols": [+ "Kafka.Types.Timeout"+ ],+ "owner": 14,+ "behavior": "Timeout exposes its documented constructors, record selectors and typeclass laws",+ "inputs": "Every exported constructor/member in the compiler export inventory; generated boundary and ordinary field values",+ "expected": "Construction/selection round trips; declared equality/order/show/enum/functor/traversal instances obey their documented laws",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.representations.text newtypes preserve arbitrary represented text",+ "rdkafka-hs.Public properties.representations.integer newtypes preserve signed machine boundaries",+ "rdkafka-hs.Public properties.representations.offset and milliseconds preserve signed 64-bit boundaries",+ "rdkafka-hs.Public properties.representations.timestamp constructors retain their represented boundary",+ "rdkafka-hs.Public properties.representations.system topic classification requires two initial underscores",+ "rdkafka-hs.Public properties.representations.fixed empty underscore and signed numeric boundaries",+ "rdkafka-hs.Public data contracts.representations.numeric ordering and reads agree with represented signed values",+ "rdkafka-hs.Public data contracts.representations.numeric instances preserve primitive arithmetic including boundaries",+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.consumer variants retain fields and distinguish constructors",+ "rdkafka-hs.Public data contracts.representations.producer records delivery variants and topic requests retain exact fields",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs.Public data contracts.representations.every Kafka error preserves its Exception identity and generic form",+ "rdkafka-hs.Public properties.every compression debug and log enumeration has its native spelling",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs.Public data contracts.all linked native errors retain sparse numeric codes names and descriptions"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Types-TopicName",+ "symbols": [+ "Kafka.Types.TopicName"+ ],+ "owner": 14,+ "behavior": "TopicName exposes its documented constructors, record selectors and typeclass laws",+ "inputs": "Every exported constructor/member in the compiler export inventory; generated boundary and ordinary field values",+ "expected": "Construction/selection round trips; declared equality/order/show/enum/functor/traversal instances obey their documented laws",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.representations.text newtypes preserve arbitrary represented text",+ "rdkafka-hs.Public properties.representations.integer newtypes preserve signed machine boundaries",+ "rdkafka-hs.Public properties.representations.offset and milliseconds preserve signed 64-bit boundaries",+ "rdkafka-hs.Public properties.representations.timestamp constructors retain their represented boundary",+ "rdkafka-hs.Public properties.representations.system topic classification requires two initial underscores",+ "rdkafka-hs.Public properties.representations.fixed empty underscore and signed numeric boundaries",+ "rdkafka-hs.Public data contracts.representations.numeric ordering and reads agree with represented signed values",+ "rdkafka-hs.Public data contracts.representations.numeric instances preserve primitive arithmetic including boundaries",+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.consumer variants retain fields and distinguish constructors",+ "rdkafka-hs.Public data contracts.representations.producer records delivery variants and topic requests retain exact fields",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs.Public data contracts.representations.every Kafka error preserves its Exception identity and generic form",+ "rdkafka-hs.Public properties.every compression debug and log enumeration has its native spelling",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs.Public data contracts.all linked native errors retain sparse numeric codes names and descriptions"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Types-TopicType",+ "symbols": [+ "Kafka.Types.TopicType"+ ],+ "owner": 14,+ "behavior": "TopicType exposes its documented constructors, record selectors and typeclass laws",+ "inputs": "Every exported constructor/member in the compiler export inventory; generated boundary and ordinary field values",+ "expected": "Construction/selection round trips; declared equality/order/show/enum/functor/traversal instances obey their documented laws",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.representations.text newtypes preserve arbitrary represented text",+ "rdkafka-hs.Public properties.representations.integer newtypes preserve signed machine boundaries",+ "rdkafka-hs.Public properties.representations.offset and milliseconds preserve signed 64-bit boundaries",+ "rdkafka-hs.Public properties.representations.timestamp constructors retain their represented boundary",+ "rdkafka-hs.Public properties.representations.system topic classification requires two initial underscores",+ "rdkafka-hs.Public properties.representations.fixed empty underscore and signed numeric boundaries",+ "rdkafka-hs.Public data contracts.representations.numeric ordering and reads agree with represented signed values",+ "rdkafka-hs.Public data contracts.representations.numeric instances preserve primitive arithmetic including boundaries",+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.consumer variants retain fields and distinguish constructors",+ "rdkafka-hs.Public data contracts.representations.producer records delivery variants and topic requests retain exact fields",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs.Public data contracts.representations.every Kafka error preserves its Exception identity and generic form",+ "rdkafka-hs.Public properties.every compression debug and log enumeration has its native spelling",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs.Public data contracts.all linked native errors retain sparse numeric codes names and descriptions"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Types-headersFromList",+ "symbols": [+ "Kafka.Types.headersFromList"+ ],+ "owner": 14,+ "behavior": "headersFromList preserves its documented pure mapping/conversion behavior",+ "inputs": "generated empty/nonempty values; every constructor case; identity/composition and effects in traversal order",+ "expected": "Exact output and typeclass laws, with replay seed for generated failures",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.representations.text newtypes preserve arbitrary represented text",+ "rdkafka-hs.Public properties.representations.integer newtypes preserve signed machine boundaries",+ "rdkafka-hs.Public properties.representations.offset and milliseconds preserve signed 64-bit boundaries",+ "rdkafka-hs.Public properties.representations.timestamp constructors retain their represented boundary",+ "rdkafka-hs.Public properties.representations.system topic classification requires two initial underscores",+ "rdkafka-hs.Public properties.representations.fixed empty underscore and signed numeric boundaries",+ "rdkafka-hs.Public data contracts.representations.numeric ordering and reads agree with represented signed values",+ "rdkafka-hs.Public data contracts.representations.numeric instances preserve primitive arithmetic including boundaries",+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.consumer variants retain fields and distinguish constructors",+ "rdkafka-hs.Public data contracts.representations.producer records delivery variants and topic requests retain exact fields",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs.Public data contracts.representations.every Kafka error preserves its Exception identity and generic form",+ "rdkafka-hs.Public properties.every compression debug and log enumeration has its native spelling",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs.Public data contracts.all linked native errors retain sparse numeric codes names and descriptions"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Types-headersToList",+ "symbols": [+ "Kafka.Types.headersToList"+ ],+ "owner": 14,+ "behavior": "headersToList preserves its documented pure mapping/conversion behavior",+ "inputs": "generated empty/nonempty values; every constructor case; identity/composition and effects in traversal order",+ "expected": "Exact output and typeclass laws, with replay seed for generated failures",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.representations.text newtypes preserve arbitrary represented text",+ "rdkafka-hs.Public properties.representations.integer newtypes preserve signed machine boundaries",+ "rdkafka-hs.Public properties.representations.offset and milliseconds preserve signed 64-bit boundaries",+ "rdkafka-hs.Public properties.representations.timestamp constructors retain their represented boundary",+ "rdkafka-hs.Public properties.representations.system topic classification requires two initial underscores",+ "rdkafka-hs.Public properties.representations.fixed empty underscore and signed numeric boundaries",+ "rdkafka-hs.Public data contracts.representations.numeric ordering and reads agree with represented signed values",+ "rdkafka-hs.Public data contracts.representations.numeric instances preserve primitive arithmetic including boundaries",+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.consumer variants retain fields and distinguish constructors",+ "rdkafka-hs.Public data contracts.representations.producer records delivery variants and topic requests retain exact fields",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs.Public data contracts.representations.every Kafka error preserves its Exception identity and generic form",+ "rdkafka-hs.Public properties.every compression debug and log enumeration has its native spelling",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs.Public data contracts.all linked native errors retain sparse numeric codes names and descriptions"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Types-kafkaCompressionCodecToText",+ "symbols": [+ "Kafka.Types.kafkaCompressionCodecToText"+ ],+ "owner": 14,+ "behavior": "kafkaCompressionCodecToText preserves its documented pure mapping/conversion behavior",+ "inputs": "generated empty/nonempty values; every constructor case; identity/composition and effects in traversal order",+ "expected": "Exact output and typeclass laws, with replay seed for generated failures",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.representations.text newtypes preserve arbitrary represented text",+ "rdkafka-hs.Public properties.representations.integer newtypes preserve signed machine boundaries",+ "rdkafka-hs.Public properties.representations.offset and milliseconds preserve signed 64-bit boundaries",+ "rdkafka-hs.Public properties.representations.timestamp constructors retain their represented boundary",+ "rdkafka-hs.Public properties.representations.system topic classification requires two initial underscores",+ "rdkafka-hs.Public properties.representations.fixed empty underscore and signed numeric boundaries",+ "rdkafka-hs.Public data contracts.representations.numeric ordering and reads agree with represented signed values",+ "rdkafka-hs.Public data contracts.representations.numeric instances preserve primitive arithmetic including boundaries",+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.consumer variants retain fields and distinguish constructors",+ "rdkafka-hs.Public data contracts.representations.producer records delivery variants and topic requests retain exact fields",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs.Public data contracts.representations.every Kafka error preserves its Exception identity and generic form",+ "rdkafka-hs.Public properties.every compression debug and log enumeration has its native spelling",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs.Public data contracts.all linked native errors retain sparse numeric codes names and descriptions"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Types-kafkaDebugToText",+ "symbols": [+ "Kafka.Types.kafkaDebugToText"+ ],+ "owner": 14,+ "behavior": "kafkaDebugToText preserves its documented pure mapping/conversion behavior",+ "inputs": "generated empty/nonempty values; every constructor case; identity/composition and effects in traversal order",+ "expected": "Exact output and typeclass laws, with replay seed for generated failures",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.representations.text newtypes preserve arbitrary represented text",+ "rdkafka-hs.Public properties.representations.integer newtypes preserve signed machine boundaries",+ "rdkafka-hs.Public properties.representations.offset and milliseconds preserve signed 64-bit boundaries",+ "rdkafka-hs.Public properties.representations.timestamp constructors retain their represented boundary",+ "rdkafka-hs.Public properties.representations.system topic classification requires two initial underscores",+ "rdkafka-hs.Public properties.representations.fixed empty underscore and signed numeric boundaries",+ "rdkafka-hs.Public data contracts.representations.numeric ordering and reads agree with represented signed values",+ "rdkafka-hs.Public data contracts.representations.numeric instances preserve primitive arithmetic including boundaries",+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.consumer variants retain fields and distinguish constructors",+ "rdkafka-hs.Public data contracts.representations.producer records delivery variants and topic requests retain exact fields",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs.Public data contracts.representations.every Kafka error preserves its Exception identity and generic form",+ "rdkafka-hs.Public properties.every compression debug and log enumeration has its native spelling",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs.Public data contracts.all linked native errors retain sparse numeric codes names and descriptions"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Types-topicType",+ "symbols": [+ "Kafka.Types.topicType"+ ],+ "owner": 14,+ "behavior": "topicType preserves its documented pure mapping/conversion behavior",+ "inputs": "generated empty/nonempty values; every constructor case; identity/composition and effects in traversal order",+ "expected": "Exact output and typeclass laws, with replay seed for generated failures",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Public properties.representations.text newtypes preserve arbitrary represented text",+ "rdkafka-hs.Public properties.representations.integer newtypes preserve signed machine boundaries",+ "rdkafka-hs.Public properties.representations.offset and milliseconds preserve signed 64-bit boundaries",+ "rdkafka-hs.Public properties.representations.timestamp constructors retain their represented boundary",+ "rdkafka-hs.Public properties.representations.system topic classification requires two initial underscores",+ "rdkafka-hs.Public properties.representations.fixed empty underscore and signed numeric boundaries",+ "rdkafka-hs.Public data contracts.representations.numeric ordering and reads agree with represented signed values",+ "rdkafka-hs.Public data contracts.representations.numeric instances preserve primitive arithmetic including boundaries",+ "rdkafka-hs.Public data contracts.representations.text ordering string conversion reads and generic representations round-trip",+ "rdkafka-hs.Public data contracts.representations.consumer variants retain fields and distinguish constructors",+ "rdkafka-hs.Public data contracts.representations.producer records delivery variants and topic requests retain exact fields",+ "rdkafka-hs.Public data contracts.representations.metadata structures retain identities states members and binary data",+ "rdkafka-hs.Public data contracts.representations.every Kafka error preserves its Exception identity and generic form",+ "rdkafka-hs.Public properties.every compression debug and log enumeration has its native spelling",+ "rdkafka-hs.Public data contracts.builders.all codecs have independently specified builder spellings",+ "rdkafka-hs.Public data contracts.builders.debug contexts preserve order duplicates and the empty-list identity",+ "rdkafka-hs.Public data contracts.all linked native errors retain sparse numeric codes names and descriptions"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Version-LibrdkafkaVersion",+ "symbols": [+ "Kafka.Version.LibrdkafkaVersion"+ ],+ "owner": 14,+ "behavior": "LibrdkafkaVersion reports or decodes librdkafka packed version",+ "inputs": "loaded native version; generated major/minor/patch/prerelease bytes including zero/max values",+ "expected": "Exact packed-bit fields and textual/loaded version agree",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Kafka.Version.linked librdkafka is at least 2.15.0",+ "rdkafka-hs.Kafka.Version.version string agrees with the version number",+ "rdkafka-hs.Kafka.Version.decodes the hex version encoding",+ "rdkafka-hs.Public properties.version.version bytes decode independently of prerelease byte",+ "rdkafka-hs.Public properties.version.version extraction agrees with arithmetic for every Int",+ "rdkafka-hs.Public properties.version.fixed zero and full version byte boundaries"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Version-decodeLibrdkafkaVersion",+ "symbols": [+ "Kafka.Version.decodeLibrdkafkaVersion"+ ],+ "owner": 14,+ "behavior": "decodeLibrdkafkaVersion reports or decodes librdkafka packed version",+ "inputs": "loaded native version; generated major/minor/patch/prerelease bytes including zero/max values",+ "expected": "Exact packed-bit fields and textual/loaded version agree",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Kafka.Version.linked librdkafka is at least 2.15.0",+ "rdkafka-hs.Kafka.Version.version string agrees with the version number",+ "rdkafka-hs.Kafka.Version.decodes the hex version encoding",+ "rdkafka-hs.Public properties.version.version bytes decode independently of prerelease byte",+ "rdkafka-hs.Public properties.version.version extraction agrees with arithmetic for every Int",+ "rdkafka-hs.Public properties.version.fixed zero and full version byte boundaries"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Version-librdkafkaVersion",+ "symbols": [+ "Kafka.Version.librdkafkaVersion"+ ],+ "owner": 14,+ "behavior": "librdkafkaVersion reports or decodes librdkafka packed version",+ "inputs": "loaded native version; generated major/minor/patch/prerelease bytes including zero/max values",+ "expected": "Exact packed-bit fields and textual/loaded version agree",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Kafka.Version.linked librdkafka is at least 2.15.0",+ "rdkafka-hs.Kafka.Version.version string agrees with the version number",+ "rdkafka-hs.Kafka.Version.decodes the hex version encoding",+ "rdkafka-hs.Public properties.version.version bytes decode independently of prerelease byte",+ "rdkafka-hs.Public properties.version.version extraction agrees with arithmetic for every Int",+ "rdkafka-hs.Public properties.version.fixed zero and full version byte boundaries"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Version-librdkafkaVersionNumber",+ "symbols": [+ "Kafka.Version.librdkafkaVersionNumber"+ ],+ "owner": 14,+ "behavior": "librdkafkaVersionNumber reports or decodes librdkafka packed version",+ "inputs": "loaded native version; generated major/minor/patch/prerelease bytes including zero/max values",+ "expected": "Exact packed-bit fields and textual/loaded version agree",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Kafka.Version.linked librdkafka is at least 2.15.0",+ "rdkafka-hs.Kafka.Version.version string agrees with the version number",+ "rdkafka-hs.Kafka.Version.decodes the hex version encoding",+ "rdkafka-hs.Public properties.version.version bytes decode independently of prerelease byte",+ "rdkafka-hs.Public properties.version.version extraction agrees with arithmetic for every Int",+ "rdkafka-hs.Public properties.version.fixed zero and full version byte boundaries"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "API-Kafka-Version-librdkafkaVersionParts",+ "symbols": [+ "Kafka.Version.librdkafkaVersionParts"+ ],+ "owner": 14,+ "behavior": "librdkafkaVersionParts reports or decodes librdkafka packed version",+ "inputs": "loaded native version; generated major/minor/patch/prerelease bytes including zero/max values",+ "expected": "Exact packed-bit fields and textual/loaded version agree",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [+ "rdkafka-hs.Kafka.Version.linked librdkafka is at least 2.15.0",+ "rdkafka-hs.Kafka.Version.version string agrees with the version number",+ "rdkafka-hs.Kafka.Version.decodes the hex version encoding",+ "rdkafka-hs.Public properties.version.version bytes decode independently of prerelease byte",+ "rdkafka-hs.Public properties.version.version extraction agrees with arithmetic for every Int",+ "rdkafka-hs.Public properties.version.fixed zero and full version byte boundaries"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "OWN-config",+ "symbols": [],+ "owner": 11,+ "behavior": "Configuration creation failure and native client creation transfer",+ "inputs": "success, injected failure, interruption, repeated calls and boundaries",+ "expected": "Exact behavior or allocation balance with effective negative controls",+ "modes": "all supported modes",+ "ownership": "Configuration allocated -> native transfer or failure cleanup; callback registry freed only after native ownership ends",+ "tests": [+ "rdkafka-hs.Callback owner.bridge allocation executes masked before ownership is recorded",+ "rdkafka-hs.Callback owner.installed and replaced bridges release exactly once",+ "rdkafka-hs.Callback owner.failed native install still owns its allocated bridge",+ "rdkafka-hs.Callback owner.failed allocation has no release",+ "rdkafka-hs.Callback owner.transfer preserves a callable bridge until client release",+ "rdkafka-hs.Callback owner.transferred and released owners reject reuse before allocating",+ "rdkafka-hs.Callback owner.release retry does not repeat completed releases",+ "rdkafka-hs.Callback owner.concurrent releases join before returning",+ "rdkafka-hs-integration.callback-lifetime.async construction failure releases callbacks: topic",+ "rdkafka-hs-integration.callback-lifetime.async construction failure releases callbacks: native",+ "rdkafka-hs-integration.callback-lifetime.sync construction failure releases callbacks: topic",+ "rdkafka-hs-integration.callback-lifetime.sync construction failure releases callbacks: native",+ "rdkafka-hs-integration.callback-lifetime.producer native construction failure releases callbacks",+ "rdkafka-hs-integration.callback-lifetime.replaced producer delivery callbacks both release",+ "rdkafka-hs-integration.callback-lifetime.producer constructor cancellation at partial registration releases its owner",+ "rdkafka-hs-integration.callback-lifetime.producer constructor cancellation at native acceptance releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-async constructor cancellation at partial registration releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-async constructor cancellation at native acceptance releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-sync constructor cancellation at partial registration releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-sync constructor cancellation at native acceptance releases its owner",+ "rdkafka-hs-integration.callback-lifetime.async closed consumer GC releases its registrations once",+ "rdkafka-hs-integration.callback-lifetime.sync closed consumer GC releases its registrations once",+ "rdkafka-hs-integration.callback-lifetime.failed native construction releases the caller-owned duplicate config"+ ],+ "status": "tested",+ "native_diagnostics": "docs/testing/callback-native-diagnostics.json",+ "mutations": "dist-mutations/20261024T135134Z-callback-6370-0/results.json",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "OWN-topic",+ "symbols": [],+ "owner": 8,+ "behavior": "Topic admin construction, event decode and submission errors",+ "inputs": "success, injected failure, interruption, repeated calls and boundaries",+ "expected": "Observed native application allocation/release balance on success, local/broker errors, post-allocation interruption, malformed responses and overlap; retained-request positive control and cleanup-removal mutations fail",+ "modes": "all supported modes",+ "ownership": "Raw NewTopic bracket owns its manual destroy; DeleteTopic/options/queue/event scopes consume their ForeignPtr finalizer once; borrowed configuration and event payloads retain their parent and receive no native deallocator",+ "tests": [+ "rdkafka-hs-integration.topic-configuration.singleton configuration reaches the broker",+ "rdkafka-hs-integration.topic-configuration.native allocation control detects a retained request",+ "rdkafka-hs-integration.topic-configuration.setter rejection releases allocated request before submission",+ "rdkafka-hs-integration.topic-configuration.interruption after allocation releases request before submission",+ "rdkafka-hs-integration.topic-configuration.multiple configuration entries reach the broker",+ "rdkafka-hs-integration.topic-configuration.broker-rejected values release requests and response events repeatedly",+ "rdkafka-hs-integration.topic-configuration.unrepresentable partition count never wraps to broker defaults",+ "rdkafka-hs-integration.topic-configuration.NUL in a topic name never creates a truncated topic",+ "rdkafka-hs-integration.topic-configuration.unresponsive broker preserves the native timeout error",+ "rdkafka-hs-integration.topic-configuration.empty configuration creates a usable topic",+ "rdkafka-hs-integration.topic-configuration.later setter rejection releases partially configured request",+ "rdkafka-hs-integration.topic-configuration.duplicate creation preserves the existing topic",+ "rdkafka-hs-integration.topic-configuration.deletion removes exactly the existing topic",+ "rdkafka-hs-integration.topic-configuration.missing topic deletion preserves its error and releases the request",+ "rdkafka-hs-integration.topic-configuration.NUL deletion cannot remove a truncated victim name",+ "rdkafka-hs-integration.topic-configuration.broker default partition and replication counts remain supported",+ "rdkafka-hs-integration.topic-configuration.replication above the available broker count is rejected",+ "rdkafka-hs-integration.topic-configuration.unsupported configuration follows the declared broker policy",+ "rdkafka-hs-integration.topic-configuration.minimum unrepresentable partition count is rejected",+ "rdkafka-hs-integration.topic-configuration.maximum unrepresentable replication count is rejected",+ "rdkafka-hs-integration.topic-configuration.minimum unrepresentable replication count is rejected",+ "rdkafka-hs-integration.topic-configuration.NUL configuration key is rejected before native allocation",+ "rdkafka-hs-integration.topic-configuration.NUL configuration value is rejected before native allocation",+ "rdkafka-hs-integration.topic-configuration.negative invalid partition count retains native validation",+ "rdkafka-hs-integration.topic-configuration.maximum C partition count retains native validation",+ "rdkafka-hs-integration.topic-configuration.negative invalid replication count retains native validation",+ "rdkafka-hs-integration.topic-configuration.maximum C replication count retains native validation",+ "rdkafka-hs-integration.topic-configuration.empty topic name is rejected by the broker",+ "rdkafka-hs-integration.topic-configuration.space in a topic name is rejected by the broker",+ "rdkafka-hs-integration.topic-configuration.overlong topic name is rejected by the broker",+ "rdkafka-hs-integration.topic-configuration.zero partition count is rejected by the broker",+ "rdkafka-hs-integration.topic-configuration.zero replication count is rejected by the broker",+ "rdkafka-hs-integration.topic-configuration.wrong event type fails and releases its event",+ "rdkafka-hs-integration.topic-configuration.empty response fails and releases its event",+ "rdkafka-hs-integration.topic-configuration.wrong topic response cannot report success",+ "rdkafka-hs-integration.topic-configuration.missing polled event reports a timeout",+ "rdkafka-hs-integration.topic-configuration.delayed response succeeds with balanced ownership",+ "rdkafka-hs-integration.topic-configuration.consumer administration applies settings in async mode",+ "rdkafka-hs-integration.topic-configuration.consumer administration applies settings in sync mode",+ "rdkafka-hs-integration.topic-configuration.consumer administration applies settings in async-closed mode",+ "rdkafka-hs-integration.topic-configuration.consumer administration applies settings in sync-closed mode",+ "rdkafka-hs-integration.topic-configuration.concurrent requests keep their own queues and responses",+ "rdkafka-hs-integration.topic-configuration.unresponsive deletion preserves the native timeout error",+ "rdkafka-hs-integration.topic-configuration.deletion rejects a wrong event type and releases it",+ "rdkafka-hs-integration.topic-configuration.deletion rejects an empty result and releases its event",+ "rdkafka-hs-integration.topic-configuration.deletion rejects a mismatched topic result",+ "rdkafka-hs-integration.topic-configuration.deletion reports a missing response as a timeout",+ "rdkafka-hs-integration.topic-configuration.missing native timeout configuration returns an error",+ "rdkafka-hs-integration.topic-configuration.malformed native timeout configuration returns an error",+ "rdkafka-hs-integration.topic-configuration.zero native timeout configuration returns an error",+ "rdkafka-hs-integration.topic-configuration.negative native timeout configuration returns an error",+ "rdkafka-hs-integration.topic-configuration.overflowing native timeout configuration returns an error",+ "rdkafka-hs-integration.topic-configuration.oversized native timeout configuration never reads a truncated buffer"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "OWN-headers",+ "symbols": [],+ "owner": 9,+ "behavior": "Header bytes remain live through enqueue and native copies preserve order and values",+ "inputs": "duplicate/binary/empty headers on success, immediate rejection, observed cancellation before/after native acceptance, purge and report completion",+ "expected": "Byte-exact ordered header reports and broker round trips; dropping headers fails a compiled semantic mutation; borrowed buffers never outlive their call scope",+ "modes": "all supported modes",+ "ownership": "withMany/ByteString/C-string scopes retain borrowed names and values through produceva; the wrapper owns no RdKafkaHeaders handle; native internal header allocation/release diagnostics remain separately owned by EP-15",+ "tests": [+ "rdkafka-hs-integration.producer-regressions.queue-full rejection releases callback capture without invoking it",+ "rdkafka-hs-integration.producer-regressions.accepted callback retains its capture until a purged report completes",+ "rdkafka-hs-integration.producer-regressions.repeated queue-full rejections release every callback capture",+ "rdkafka-hs-integration.producer-regressions.cancellation at a rejected enqueue releases capture before unmasking",+ "rdkafka-hs-integration.producer-regressions.cancellation after native acceptance retains callback until its report",+ "rdkafka-hs-integration.producer-regressions.another poller can deliver before successful enqueue returns",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with NoCompression",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Gzip",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Snappy",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Lz4",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Zstd",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: none",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: inflight",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue+inflight",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue+nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: inflight+nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: all",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: none",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: inflight",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue+inflight",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue+nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: inflight+nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: all",+ "rdkafka-hs-integration.producer-regressions.oversized rejection releases capture without a delivery report",+ "rdkafka-hs-integration.producer-regressions.known invalid partition rejection releases capture"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "OWN-partition-list",+ "symbols": [],+ "owner": 16,+ "behavior": "Partition list conversion and native error decoding",+ "inputs": "success, injected failure, interruption, repeated calls and boundaries",+ "expected": "Exact behavior or allocation balance with effective negative controls",+ "modes": "all supported modes",+ "ownership": "Every temporary list freed; per-element errors never silently erased",+ "tests": [+ "rdkafka-hs-integration.public-contract.partition-list-ownership.counter detects a retained native list before explicit release",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.pair conversion failure releases the partial list before GC",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.offset conversion failure releases the partial list before GC",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.ordinary input lists release after exact native results",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.native logical offsets decode independently without losing partition identity",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.missing native partition queue preserves assignment and later forwarding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.assignment outputs release after exact decoding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.subscription outputs release after exact decoding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.subscription acquisition failure preserves the native error without a list",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.assignment decoder failure releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.subscription decoder failure releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.cancellation at input allocation releases the owned list",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.cancellation at assignment return releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.pair conversion failure releases the partial list before GC",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.offset conversion failure releases the partial list before GC",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.ordinary input lists release after exact native results",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.native logical offsets decode independently without losing partition identity",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.missing native partition queue preserves assignment and later forwarding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.assignment outputs release after exact decoding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.subscription outputs release after exact decoding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.subscription acquisition failure preserves the native error without a list",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.assignment decoder failure releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.subscription decoder failure releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.cancellation at input allocation releases the owned list",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.cancellation at assignment return releases the owned output"+ ],+ "status": "tested",+ "previous_owner": 14,+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ {+ "id": "OWN-queues",+ "symbols": [],+ "owner": 11,+ "behavior": "Consumer queue forwarding, polling and teardown",+ "inputs": "success, injected failure, interruption, repeated calls and boundaries",+ "expected": "Exact behavior or allocation balance with effective negative controls",+ "modes": "all supported modes",+ "ownership": "Acquired queue references released once; destination routing preserved through assign/rebalance/close/destroy",+ "tests": [+ "rdkafka-hs-integration.callback-lifetime.async throwing rebalance callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing rebalance callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async error callback releases after destroy with retained wrapper",+ "rdkafka-hs-integration.callback-lifetime.sync error callback releases after destroy with retained wrapper",+ "rdkafka-hs-integration.callback-lifetime.async rebalance callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.sync rebalance callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.async concurrent destruction joins at native entry",+ "rdkafka-hs-integration.callback-lifetime.async concurrent destruction joins at native completion",+ "rdkafka-hs-integration.callback-lifetime.async concurrent destruction joins at native shutdown callback",+ "rdkafka-hs-integration.callback-lifetime.sync concurrent destruction joins at native entry",+ "rdkafka-hs-integration.callback-lifetime.sync concurrent destruction joins at native completion",+ "rdkafka-hs-integration.callback-lifetime.sync concurrent destruction joins at native shutdown callback",+ "rdkafka-hs-integration.callback-lifetime.async cancellation at native entry preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.async cancellation at native completion preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.async cancellation at native shutdown callback preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation at native entry preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation at native completion preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation at native shutdown callback preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.async cancellation after poll stop and queue detachment preserves teardown",+ "rdkafka-hs-integration.callback-lifetime.producer constructor cancellation at partial registration releases its owner",+ "rdkafka-hs-integration.callback-lifetime.producer constructor cancellation at native acceptance releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-async constructor cancellation at partial registration releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-async constructor cancellation at native acceptance releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-sync constructor cancellation at partial registration releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-sync constructor cancellation at native acceptance releases its owner",+ "rdkafka-hs-integration.callback-lifetime.async cancellation while waiting for active callback permits retry",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation while waiting for active callback permits retry",+ "rdkafka-hs-integration.public-contract.queue event.async.wakes an idle consumer and stays quiet once disabled",+ "rdkafka-hs-integration.public-contract.queue event.async.finds records queued before it was enabled, then rearms",+ "rdkafka-hs-integration.public-contract.queue event.async.one wake-up covers several records, then rearms",+ "rdkafka-hs-integration.public-contract.queue event.sync.wakes an idle consumer and stays quiet once disabled",+ "rdkafka-hs-integration.public-contract.queue event.sync.finds records queued before it was enabled, then rearms",+ "rdkafka-hs-integration.public-contract.queue event.sync.one wake-up covers several records, then rearms",+ "rdkafka-hs-integration.broker.destroy.async.closes broker connections within one second",+ "rdkafka-hs-integration.broker.destroy.async.is safe to repeat",+ "rdkafka-hs-integration.broker.destroy.async.concurrent destroys both return after cleanup",+ "rdkafka-hs-integration.broker.destroy.async.completes after an interrupted destroy",+ "rdkafka-hs-integration.broker.destroy.async.close then destroy, destroy then close",+ "rdkafka-hs-integration.broker.destroy.sync.closes broker connections within one second",+ "rdkafka-hs-integration.broker.destroy.sync.is safe to repeat",+ "rdkafka-hs-integration.broker.destroy.sync.concurrent destroys both return after cleanup",+ "rdkafka-hs-integration.broker.destroy.sync.completes after an interrupted destroy",+ "rdkafka-hs-integration.broker.destroy.sync.close then destroy, destroy then close"+ ],+ "status": "tested",+ "native_diagnostics": "docs/testing/callback-native-diagnostics.json",+ "mutations": "dist-mutations/20261024T135134Z-callback-6370-0/results.json",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "OWN-tx-group-metadata",+ "symbols": [],+ "owner": 12,+ "behavior": "Transactional consumer group metadata acquisition",+ "inputs": "success, injected failure, interruption, repeated calls and boundaries",+ "expected": "Exact behavior or allocation balance with effective negative controls",+ "modes": "all supported modes",+ "ownership": "Group metadata released on success and native error before result escapes",+ "tests": [+ "rdkafka-hs-integration.transaction-errors.offset without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.offset NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.offset invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 0 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 1 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 2 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 3 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 4 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 5 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 6 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 7 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 21 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 22 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 23 releases once"+ ],+ "status": "tested",+ "mutations": "dist-mutations/20261024T141053Z-transaction-39758-0/results.json",+ "native_diagnostics": "docs/testing/transaction-native-diagnostics.json",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "ENV-primary",+ "symbols": [],+ "owner": 17,+ "behavior": "Primary Darwin/Redpanda behavior and native diagnostics",+ "inputs": "success, injected failure, interruption, repeated calls and boundaries",+ "expected": "Exact behavior or allocation balance with effective negative controls",+ "modes": "all supported modes",+ "ownership": "Exact compiler/native/broker tuple, source fingerprint and native allocation positive controls",+ "tests": [+ "rdkafka-hs-integration.public-contract.runtime-contract.RTS capability is observed by async construction",+ "rdkafka-hs-integration.public-contract.runtime-contract.explicit async construction checks the runtime",+ "rdkafka-hs-integration.public-contract.runtime-contract.sync subscription delivers an exact record",+ "rdkafka-hs-integration.public-contract.runtime-contract.deprecated sync runner closes after an exact record",+ "rdkafka-hs-integration.callback-lifetime.async throwing error callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing log callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing stats callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing rebalance callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing commit callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing error callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing log callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing stats callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing rebalance callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing commit callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async error callback releases after destroy with retained wrapper",+ "rdkafka-hs-integration.callback-lifetime.sync error callback releases after destroy with retained wrapper",+ "rdkafka-hs-integration.callback-lifetime.producer delivery callback releases after native finalization",+ "rdkafka-hs-integration.callback-lifetime.noncaptured control is collectible",+ "rdkafka-hs-integration.callback-lifetime.async log callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.async stats callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.sync log callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.sync stats callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.async construction failure releases callbacks: topic",+ "rdkafka-hs-integration.callback-lifetime.async construction failure releases callbacks: native",+ "rdkafka-hs-integration.callback-lifetime.async construction failure releases callbacks: redirect",+ "rdkafka-hs-integration.callback-lifetime.async construction failure releases callbacks: subscribe",+ "rdkafka-hs-integration.callback-lifetime.sync construction failure releases callbacks: topic",+ "rdkafka-hs-integration.callback-lifetime.sync construction failure releases callbacks: native",+ "rdkafka-hs-integration.callback-lifetime.sync construction failure releases callbacks: redirect",+ "rdkafka-hs-integration.callback-lifetime.sync construction failure releases callbacks: subscribe",+ "rdkafka-hs-integration.callback-lifetime.producer native construction failure releases callbacks",+ "rdkafka-hs-integration.callback-lifetime.async constructor exception at callback-install releases partial native ownership",+ "rdkafka-hs-integration.callback-lifetime.async constructor exception at post-native-loglevel releases partial native ownership",+ "rdkafka-hs-integration.callback-lifetime.sync constructor exception at callback-install releases partial native ownership",+ "rdkafka-hs-integration.callback-lifetime.sync constructor exception at post-native-loglevel releases partial native ownership",+ "rdkafka-hs-integration.callback-lifetime.async rebalance callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.async commit callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.sync rebalance callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.sync commit callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.replaced producer delivery callbacks both release",+ "rdkafka-hs-integration.callback-lifetime.async concurrent destruction joins at native entry",+ "rdkafka-hs-integration.callback-lifetime.async concurrent destruction joins at native completion",+ "rdkafka-hs-integration.callback-lifetime.async concurrent destruction joins at native shutdown callback",+ "rdkafka-hs-integration.callback-lifetime.sync concurrent destruction joins at native entry",+ "rdkafka-hs-integration.callback-lifetime.sync concurrent destruction joins at native completion",+ "rdkafka-hs-integration.callback-lifetime.sync concurrent destruction joins at native shutdown callback",+ "rdkafka-hs-integration.callback-lifetime.async cancellation at native entry preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.async cancellation at native completion preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.async cancellation at native shutdown callback preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation at native entry preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation at native completion preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation at native shutdown callback preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.async cancellation after poll stop and queue detachment preserves teardown",+ "rdkafka-hs-integration.callback-lifetime.producer constructor cancellation at partial registration releases its owner",+ "rdkafka-hs-integration.callback-lifetime.producer constructor cancellation at native acceptance releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-async constructor cancellation at partial registration releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-async constructor cancellation at native acceptance releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-sync constructor cancellation at partial registration releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-sync constructor cancellation at native acceptance releases its owner",+ "rdkafka-hs-integration.callback-lifetime.async cancellation while waiting for active callback permits retry",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation while waiting for active callback permits retry",+ "rdkafka-hs-integration.callback-lifetime.async closed consumer GC releases its registrations once",+ "rdkafka-hs-integration.callback-lifetime.sync closed consumer GC releases its registrations once",+ "rdkafka-hs-integration.callback-lifetime.producer error callback remains live through close and releases on GC",+ "rdkafka-hs-integration.callback-lifetime.producer log callback remains live through close and releases on GC",+ "rdkafka-hs-integration.callback-lifetime.producer stats callback remains live through close and releases on GC",+ "rdkafka-hs-integration.callback-lifetime.failed native construction releases the caller-owned duplicate config"+ ],+ "status": "tested",+ "previous_owner": 15,+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence": [+ "docs/testing/coverage-evidence.json",+ "docs/testing/compatibility-matrix.json"+ ]+ },+ {+ "id": "ENV-linux",+ "symbols": [],+ "owner": 17,+ "behavior": "Linux build, representative broker behavior and native diagnostics",+ "inputs": "success, injected failure, interruption, repeated calls and boundaries",+ "expected": "Exact behavior or allocation balance with effective negative controls",+ "modes": "all supported modes",+ "ownership": "Actual Linux execution including leak/invalid-access positive controls",+ "tests": [+ "rdkafka-hs-integration.callback-lifetime.async throwing error callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing log callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing stats callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing rebalance callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing commit callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing error callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing log callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing stats callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing rebalance callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing commit callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async error callback releases after destroy with retained wrapper",+ "rdkafka-hs-integration.callback-lifetime.sync error callback releases after destroy with retained wrapper",+ "rdkafka-hs-integration.callback-lifetime.producer delivery callback releases after native finalization",+ "rdkafka-hs-integration.callback-lifetime.noncaptured control is collectible",+ "rdkafka-hs-integration.callback-lifetime.async log callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.async stats callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.sync log callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.sync stats callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.async construction failure releases callbacks: topic",+ "rdkafka-hs-integration.callback-lifetime.async construction failure releases callbacks: native",+ "rdkafka-hs-integration.callback-lifetime.async construction failure releases callbacks: redirect",+ "rdkafka-hs-integration.callback-lifetime.async construction failure releases callbacks: subscribe",+ "rdkafka-hs-integration.callback-lifetime.sync construction failure releases callbacks: topic",+ "rdkafka-hs-integration.callback-lifetime.sync construction failure releases callbacks: native",+ "rdkafka-hs-integration.callback-lifetime.sync construction failure releases callbacks: redirect",+ "rdkafka-hs-integration.callback-lifetime.sync construction failure releases callbacks: subscribe",+ "rdkafka-hs-integration.callback-lifetime.producer native construction failure releases callbacks",+ "rdkafka-hs-integration.callback-lifetime.async constructor exception at callback-install releases partial native ownership",+ "rdkafka-hs-integration.callback-lifetime.async constructor exception at post-native-loglevel releases partial native ownership",+ "rdkafka-hs-integration.callback-lifetime.sync constructor exception at callback-install releases partial native ownership",+ "rdkafka-hs-integration.callback-lifetime.sync constructor exception at post-native-loglevel releases partial native ownership",+ "rdkafka-hs-integration.callback-lifetime.async rebalance callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.async commit callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.sync rebalance callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.sync commit callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.replaced producer delivery callbacks both release",+ "rdkafka-hs-integration.callback-lifetime.async concurrent destruction joins at native entry",+ "rdkafka-hs-integration.callback-lifetime.async concurrent destruction joins at native completion",+ "rdkafka-hs-integration.callback-lifetime.async concurrent destruction joins at native shutdown callback",+ "rdkafka-hs-integration.callback-lifetime.sync concurrent destruction joins at native entry",+ "rdkafka-hs-integration.callback-lifetime.sync concurrent destruction joins at native completion",+ "rdkafka-hs-integration.callback-lifetime.sync concurrent destruction joins at native shutdown callback",+ "rdkafka-hs-integration.callback-lifetime.async cancellation at native entry preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.async cancellation at native completion preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.async cancellation at native shutdown callback preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation at native entry preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation at native completion preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation at native shutdown callback preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.async cancellation after poll stop and queue detachment preserves teardown",+ "rdkafka-hs-integration.callback-lifetime.producer constructor cancellation at partial registration releases its owner",+ "rdkafka-hs-integration.callback-lifetime.producer constructor cancellation at native acceptance releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-async constructor cancellation at partial registration releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-async constructor cancellation at native acceptance releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-sync constructor cancellation at partial registration releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-sync constructor cancellation at native acceptance releases its owner",+ "rdkafka-hs-integration.callback-lifetime.async cancellation while waiting for active callback permits retry",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation while waiting for active callback permits retry",+ "rdkafka-hs-integration.callback-lifetime.async closed consumer GC releases its registrations once",+ "rdkafka-hs-integration.callback-lifetime.sync closed consumer GC releases its registrations once",+ "rdkafka-hs-integration.callback-lifetime.producer error callback remains live through close and releases on GC",+ "rdkafka-hs-integration.callback-lifetime.producer log callback remains live through close and releases on GC",+ "rdkafka-hs-integration.callback-lifetime.producer stats callback remains live through close and releases on GC",+ "rdkafka-hs-integration.callback-lifetime.failed native construction releases the caller-owned duplicate config",+ "rdkafka-hs-integration.transaction-errors.transaction-error-leak-probe releases 300 immediate native errors",+ "rdkafka-hs-integration.transaction-errors.native allocation control detects the inherited three-error leak",+ "rdkafka-hs-integration.transaction-errors.initialization timeout destroys its native error on each retry",+ "rdkafka-hs-integration.transaction-errors.zero-timeout initialization resumes successfully against the broker",+ "rdkafka-hs-integration.transaction-errors.transaction state errors preserve empty commit and abort recovery",+ "rdkafka-hs-integration.transaction-errors.duplicate transactional IDs report a real fatal fencing error",+ "rdkafka-hs-integration.transaction-errors.broker-rejected delivery requires abort and permits a successful new transaction",+ "rdkafka-hs-integration.transaction-errors.init without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.begin without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.abort without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.commit without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.offset without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.init NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.begin NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.abort NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.commit NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.offset NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.init invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.begin invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.abort invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.commit invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.offset invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 0 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 1 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 2 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 3 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 4 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 5 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 6 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 7 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 0 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 1 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 2 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 3 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 4 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 5 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 6 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 7 before destruction",+ "rdkafka-hs-integration.transaction-errors.init cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.begin cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.abort cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 21 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 22 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 23 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 21 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 22 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 23 releases once",+ "rdkafka-hs-integration.transaction-errors.async commit publishes output and source next offset atomically; abort publishes neither",+ "rdkafka-hs-integration.transaction-errors.sync commit publishes output and source next offset atomically; abort publishes neither",+ "rdkafka-hs-integration.lifecycle.flushProducerTimeout times out, purgeProducer empties the queue",+ "rdkafka-hs-integration.lifecycle.consumerClosed is False until closeConsumer",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials replaces credentials on a consumer",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials replaces credentials on a producer",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials rejects NUL in username without changing producer or consumer identity",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials rejects NUL in password without changing producer or consumer identity",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials releases each actual native error after decoding its exact code",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials cancellation at error decoding releases the owned error",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials cancellation at error acquisition releases the owned error",+ "rdkafka-hs-integration.producer-regressions.explicit topic timeout expires an accepted message",+ "rdkafka-hs-integration.producer-regressions.global timeout still expires an accepted message",+ "rdkafka-hs-integration.producer-regressions.queue-full rejection releases callback capture without invoking it",+ "rdkafka-hs-integration.producer-regressions.accepted callback retains its capture until a purged report completes",+ "rdkafka-hs-integration.producer-regressions.throwing global callback preserves per-message delivery and releases capture",+ "rdkafka-hs-integration.producer-regressions.throwing per-message callback reports exception and releases capture",+ "rdkafka-hs-integration.producer-regressions.repeated queue-full rejections release every callback capture",+ "rdkafka-hs-integration.producer-regressions.cancellation at a rejected enqueue releases capture before unmasking",+ "rdkafka-hs-integration.producer-regressions.cancellation after native acceptance retains callback until its report",+ "rdkafka-hs-integration.producer-regressions.another poller can deliver before successful enqueue returns",+ "rdkafka-hs-integration.producer-regressions.running callback keeps its capture after the native root is released",+ "rdkafka-hs-integration.producer-regressions.native error decoding failure releases rejected callback capture",+ "rdkafka-hs-integration.producer-regressions.non-null native success-code error rejects and releases capture",+ "rdkafka-hs-integration.producer-regressions.unknown native error code is preserved instead of reading errno",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: defaults",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: global only",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: topic only",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: disjoint maps",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: explicit topic wins duplicate",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: last topic property wins",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: empty topic map preserves global",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: zero topic timeout is infinite",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: maximum native topic timeout",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: explicit topic wins native timeout alias",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: topic codec overrides global codec",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: global codec survives unrelated topic keys",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with NoCompression",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Gzip",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Snappy",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Lz4",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Zstd",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: none",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: inflight",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue+inflight",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue+nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: inflight+nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: all",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: none",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: inflight",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue+inflight",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue+nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: inflight+nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: all",+ "rdkafka-hs-integration.producer-regressions.bounded flush timeout recovers when the delayed response arrives",+ "rdkafka-hs-integration.producer-regressions.close retries a timed-out flush until the delayed delivery completes",+ "rdkafka-hs-integration.producer-regressions.oversized rejection releases capture without a delivery report",+ "rdkafka-hs-integration.producer-regressions.known invalid partition rejection releases capture",+ "rdkafka-hs-integration.producer-regressions.empty queue supports repeated flush and close",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: NUL topic name",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: NUL header name",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: maximum unrepresentable partition",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: minimum unrepresentable partition",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: unknown global key",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: unknown topic key",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: invalid topic timeout",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: excessive topic timeout",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: global-only key in topic map",+ "rdkafka-hs-integration.producer-regressions.later delivery callback replaces the earlier callback",+ "rdkafka-hs-integration.producer-regressions.null native delivery frame reports the generic errno fallback without dereferencing a message",+ "rdkafka-hs-integration.producer-regressions.native delivery without an opaque Haskell callback preserves the complete record",+ "rdkafka-hs-integration.producer-regressions.delivery header acquisition failure preserves the outcome with empty headers",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.counter detects a retained native list before explicit release",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.pair conversion failure releases the partial list before GC",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.offset conversion failure releases the partial list before GC",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.ordinary input lists release after exact native results",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.native logical offsets decode independently without losing partition identity",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.missing native partition queue preserves assignment and later forwarding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.assignment outputs release after exact decoding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.subscription outputs release after exact decoding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.subscription acquisition failure preserves the native error without a list",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.assignment decoder failure releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.subscription decoder failure releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.cancellation at input allocation releases the owned list",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.cancellation at assignment return releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.pair conversion failure releases the partial list before GC",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.offset conversion failure releases the partial list before GC",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.ordinary input lists release after exact native results",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.native logical offsets decode independently without losing partition identity",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.missing native partition queue preserves assignment and later forwarding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.assignment outputs release after exact decoding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.subscription outputs release after exact decoding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.subscription acquisition failure preserves the native error without a list",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.assignment decoder failure releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.subscription decoder failure releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.cancellation at input allocation releases the owned list",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.cancellation at assignment return releases the owned output",+ "rdkafka-hs-integration.public-contract.messages.batch conversion releases every returned native message",+ "rdkafka-hs-integration.public-contract.messages.native message counter detects a retained final object",+ "rdkafka-hs-integration.public-contract.messages.batch decoder exception releases unprocessed messages",+ "rdkafka-hs-integration.public-contract.messages.batch native header errors remain errors while later records are released",+ "rdkafka-hs-integration.public-contract.messages.batch cancellation at native return releases every acquired message",+ "rdkafka-hs-integration.public-contract.messages.batch cancellation at middle conversion releases every acquired message",+ "rdkafka-hs-integration.public-contract.messages.async single cancellation at native return releases its native message",+ "rdkafka-hs-integration.public-contract.messages.async single cancellation at inside conversion releases its native message",+ "rdkafka-hs-integration.public-contract.messages.sync single cancellation at native return releases its native message",+ "rdkafka-hs-integration.public-contract.messages.sync single cancellation at inside conversion releases its native message",+ "rdkafka-hs-integration.public-contract.messages.async header failure preserves the polled record origin",+ "rdkafka-hs-integration.public-contract.messages.sync header failure preserves the polled record origin",+ "rdkafka-hs-integration.public-contract.messages.async plain polling surfaces native header failure",+ "rdkafka-hs-integration.public-contract.messages.sync plain polling surfaces native header failure",+ "rdkafka-hs-integration.public-contract.messages.async attributed error preserves independently absent partition-and-offset",+ "rdkafka-hs-integration.public-contract.messages.async attributed error preserves independently absent offset",+ "rdkafka-hs-integration.public-contract.messages.async attributed error preserves independently absent partition",+ "rdkafka-hs-integration.public-contract.messages.sync attributed error preserves independently absent partition-and-offset",+ "rdkafka-hs-integration.public-contract.messages.sync attributed error preserves independently absent offset",+ "rdkafka-hs-integration.public-contract.messages.sync attributed error preserves independently absent partition",+ "rdkafka-hs-integration.public-contract.messages.callback-event polling cancellation releases a returned message",+ "rdkafka-hs-integration.public-contract.messages.callback buffer preserves attributed header failure",+ "rdkafka-hs-integration.public-contract.messages.callback buffer preserves plain header failure",+ "rdkafka-hs-integration.public-contract.messages.originless callback error survives seek filtering and a paused partition",+ "rdkafka-hs-integration.public-contract.messages.callback-event polling releases and discards a returned fatal frame",+ "rdkafka-hs-integration.public-contract.messages.zero batch size leaves the queued records available",+ "rdkafka-hs-integration.public-contract.messages.unsupported sync batch does not discard a record",+ "rdkafka-hs-integration.public-contract.messages.signed native batch failure preserves its error and queued data",+ "rdkafka-hs-integration.public-contract.messages.infinite batch timeout returns available records",+ "rdkafka-hs-integration.public-contract.messages.batch capacity 1 preserves complete ordered records across partial batches",+ "rdkafka-hs-integration.public-contract.messages.batch capacity 2 preserves complete ordered records across partial batches",+ "rdkafka-hs-integration.public-contract.messages.batch capacity 5 preserves complete ordered records across partial batches",+ "rdkafka-hs-integration.public-contract.messages.invalid batch array size is rejected before native acquisition: -1",+ "rdkafka-hs-integration.public-contract.messages.invalid batch array size is rejected before native acquisition: -9223372036854775808",+ "rdkafka-hs-integration.public-contract.messages.invalid batch array size is rejected before native acquisition: 9223372036854775807",+ "rdkafka-hs-integration.public-contract.messages.batch preserves complete records followed by exact partition EOF and idle timeout",+ "rdkafka-hs-integration.public-contract.messages.empty batch respects timeout 0",+ "rdkafka-hs-integration.public-contract.messages.empty batch respects timeout 100",+ "rdkafka-hs-integration.public-contract.diagnostics.supported-property print flushes and preserves the caller handle",+ "rdkafka-hs-integration.public-contract.diagnostics.client print flushes and preserves the caller handle",+ "rdkafka-hs-integration.public-contract.diagnostics.failed fdopen releases the duplicate and preserves the original",+ "rdkafka-hs-integration.public-contract.diagnostics.failed native flush is reported after closing the duplicate",+ "rdkafka-hs-integration.public-contract.diagnostics.producer configuration dumps retain exact explicit and global settings",+ "rdkafka-hs-integration.public-contract.diagnostics.producer constructor log level overrides the global property on the native client",+ "rdkafka-hs-integration.public-contract.diagnostics.consumer configuration dump preserves global settings after subscription merge",+ "rdkafka-hs-integration.public-contract.diagnostics.native dump counter detects an unreleased array",+ "rdkafka-hs-integration.public-contract.diagnostics.global cancellation at native acquisition releases its array",+ "rdkafka-hs-integration.public-contract.diagnostics.topic cancellation at native acquisition releases its array",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata counter detects an unreleased result",+ "rdkafka-hs-integration.public-contract.metadata-contract.native topic-constructor failure survives metadata convenience queries",+ "rdkafka-hs-integration.public-contract.metadata-contract.empty native metadata remains empty and releases every result",+ "rdkafka-hs-integration.public-contract.metadata-contract.timestamp lookup preserves native overall errors",+ "rdkafka-hs-integration.public-contract.metadata-contract.watermark queries preserve unknown partition errors and empty provided metadata",+ "rdkafka-hs-integration.public-contract.metadata-contract.topic identity replica sets and exact watermarks",+ "rdkafka-hs-integration.public-contract.metadata-contract.distinct native metadata fields retain exact identities and errors",+ "rdkafka-hs-integration.public-contract.metadata-contract.provided metadata preserves partition failures in convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata partition failures survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.group query timeout preserves initial metadata wait failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.missing topic errors survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.timestamp lookup distinguishes before at and after actual record times",+ "rdkafka-hs-integration.public-contract.metadata-contract.mixed timestamp request preserves native partition failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata timeouts preserve the native error",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.groups native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.async group identity lifecycle and supported native states",+ "rdkafka-hs-integration.public-contract.metadata-contract.sync group identity lifecycle and supported native states",+ "rdkafka-hs-integration.public-contract.runtime-contract.RTS capability is observed by async construction",+ "rdkafka-hs-integration.public-contract.runtime-contract.explicit async construction checks the runtime",+ "rdkafka-hs-integration.public-contract.runtime-contract.sync subscription delivers an exact record",+ "rdkafka-hs-integration.public-contract.runtime-contract.deprecated sync runner closes after an exact record"+ ],+ "status": "tested",+ "previous_owner": 15,+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence": [+ "docs/testing/coverage-evidence.json",+ "docs/testing/compatibility-matrix.json"+ ]+ },+ {+ "id": "ENV-kafka",+ "symbols": [],+ "owner": 18,+ "behavior": "Apache Kafka security, transactions, leader failover and broker outages",+ "inputs": "success, injected failure, interruption, repeated calls and boundaries",+ "expected": "Exact behavior or allocation balance with effective negative controls",+ "modes": "all supported modes",+ "ownership": "Run-owned multi-broker/security fixtures restored after interruption; exact recovered record and group state",+ "tests": [+ "broker-failure.async observed leader election preserves exact records and commits",+ "broker-failure.sync observed leader election preserves exact records and commits",+ "broker-failure.eager async handoff pause seek eviction and complete outage recover exact offsets",+ "broker-failure.eager sync handoff pause seek eviction and complete outage recover exact offsets",+ "broker-failure.cooperative async handoff pause seek eviction and complete outage recover exact offsets",+ "broker-failure.cooperative sync handoff pause seek eviction and complete outage recover exact offsets",+ "broker-failure.async transaction commit timeout across full outage retries and preserves read-committed visibility",+ "broker-failure.sync transaction commit timeout across full outage retries and preserves read-committed visibility",+ "broker-failure.cancellation during complete outage restores all owned brokers",+ "authentication-contract.verified TLS authenticated delivery and exact consume/commit in both modes",+ "authentication-contract.authenticated identity without topic ACL receives exact produce denial",+ "authentication-contract.invalid-password producer reports the exact connection failure and no delivery",+ "authentication-contract.untrusted-CA producer reports the exact connection failure and no delivery",+ "authentication-contract.hostname-mismatch producer reports the exact connection failure and no delivery",+ "authentication-contract.invalid-password async consumer reports the exact connection failure",+ "authentication-contract.invalid-password sync consumer reports the exact connection failure",+ "authentication-contract.untrusted-CA async consumer reports the exact connection failure",+ "authentication-contract.untrusted-CA sync consumer reports the exact connection failure",+ "authentication-contract.hostname-mismatch async consumer reports the exact connection failure",+ "authentication-contract.hostname-mismatch sync consumer reports the exact connection failure",+ "authentication-contract.async exact topic/group/admin authorization denials",+ "authentication-contract.sync exact topic/group/admin authorization denials",+ "authentication-contract.producer credential replacement authenticates a new identity after observed reconnect and recovers from invalid replacement",+ "authentication-contract.async consumer credential replacement authenticates after observed reconnect and recovers from invalid replacement",+ "authentication-contract.sync consumer credential replacement authenticates after observed reconnect and recovers from invalid replacement",+ "authentication-contract.interruption destroys owned secure processes, credentials, ACL state and private keys",+ "rdkafka-hs-integration.transaction-errors.transaction-error-leak-probe releases 300 immediate native errors",+ "rdkafka-hs-integration.transaction-errors.native allocation control detects the inherited three-error leak",+ "rdkafka-hs-integration.transaction-errors.initialization timeout destroys its native error on each retry",+ "rdkafka-hs-integration.transaction-errors.zero-timeout initialization resumes successfully against the broker",+ "rdkafka-hs-integration.transaction-errors.transaction state errors preserve empty commit and abort recovery",+ "rdkafka-hs-integration.transaction-errors.duplicate transactional IDs report a real fatal fencing error",+ "rdkafka-hs-integration.transaction-errors.broker-rejected delivery requires abort and permits a successful new transaction",+ "rdkafka-hs-integration.transaction-errors.init without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.begin without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.abort without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.commit without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.offset without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.init NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.begin NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.abort NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.commit NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.offset NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.init invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.begin invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.abort invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.commit invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.offset invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 0 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 1 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 2 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 3 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 4 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 5 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 6 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 7 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 0 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 1 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 2 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 3 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 4 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 5 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 6 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 7 before destruction",+ "rdkafka-hs-integration.transaction-errors.init cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.begin cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.abort cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 21 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 22 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 23 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 21 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 22 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 23 releases once",+ "rdkafka-hs-integration.transaction-errors.async commit publishes output and source next offset atomically; abort publishes neither",+ "rdkafka-hs-integration.transaction-errors.sync commit publishes output and source next offset atomically; abort publishes neither",+ "rdkafka-hs-integration.topic-configuration.unsupported configuration follows the declared broker policy"+ ],+ "status": "tested",+ "previous_owner": 15,+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence": [+ "docs/testing/coverage-evidence.json",+ "docs/testing/compatibility-matrix.json"+ ]+ },+ {+ "id": "ENV-newer",+ "symbols": [],+ "owner": 17,+ "behavior": "Newer compatible released compiler/native version",+ "inputs": "success, injected failure, interruption, repeated calls and boundaries",+ "expected": "Exact behavior or allocation balance with effective negative controls",+ "modes": "all supported modes",+ "ownership": "Registry/tag-verified concrete compatible tuple; actual build and representative execution",+ "tests": [+ "rdkafka-hs-integration.callback-lifetime.async throwing error callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing log callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing stats callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing rebalance callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing commit callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing error callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing log callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing stats callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing rebalance callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing commit callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async error callback releases after destroy with retained wrapper",+ "rdkafka-hs-integration.callback-lifetime.sync error callback releases after destroy with retained wrapper",+ "rdkafka-hs-integration.callback-lifetime.producer delivery callback releases after native finalization",+ "rdkafka-hs-integration.callback-lifetime.noncaptured control is collectible",+ "rdkafka-hs-integration.callback-lifetime.async log callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.async stats callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.sync log callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.sync stats callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.async construction failure releases callbacks: topic",+ "rdkafka-hs-integration.callback-lifetime.async construction failure releases callbacks: native",+ "rdkafka-hs-integration.callback-lifetime.async construction failure releases callbacks: redirect",+ "rdkafka-hs-integration.callback-lifetime.async construction failure releases callbacks: subscribe",+ "rdkafka-hs-integration.callback-lifetime.sync construction failure releases callbacks: topic",+ "rdkafka-hs-integration.callback-lifetime.sync construction failure releases callbacks: native",+ "rdkafka-hs-integration.callback-lifetime.sync construction failure releases callbacks: redirect",+ "rdkafka-hs-integration.callback-lifetime.sync construction failure releases callbacks: subscribe",+ "rdkafka-hs-integration.callback-lifetime.producer native construction failure releases callbacks",+ "rdkafka-hs-integration.callback-lifetime.async constructor exception at callback-install releases partial native ownership",+ "rdkafka-hs-integration.callback-lifetime.async constructor exception at post-native-loglevel releases partial native ownership",+ "rdkafka-hs-integration.callback-lifetime.sync constructor exception at callback-install releases partial native ownership",+ "rdkafka-hs-integration.callback-lifetime.sync constructor exception at post-native-loglevel releases partial native ownership",+ "rdkafka-hs-integration.callback-lifetime.async rebalance callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.async commit callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.sync rebalance callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.sync commit callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.replaced producer delivery callbacks both release",+ "rdkafka-hs-integration.callback-lifetime.async concurrent destruction joins at native entry",+ "rdkafka-hs-integration.callback-lifetime.async concurrent destruction joins at native completion",+ "rdkafka-hs-integration.callback-lifetime.async concurrent destruction joins at native shutdown callback",+ "rdkafka-hs-integration.callback-lifetime.sync concurrent destruction joins at native entry",+ "rdkafka-hs-integration.callback-lifetime.sync concurrent destruction joins at native completion",+ "rdkafka-hs-integration.callback-lifetime.sync concurrent destruction joins at native shutdown callback",+ "rdkafka-hs-integration.callback-lifetime.async cancellation at native entry preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.async cancellation at native completion preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.async cancellation at native shutdown callback preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation at native entry preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation at native completion preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation at native shutdown callback preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.async cancellation after poll stop and queue detachment preserves teardown",+ "rdkafka-hs-integration.callback-lifetime.producer constructor cancellation at partial registration releases its owner",+ "rdkafka-hs-integration.callback-lifetime.producer constructor cancellation at native acceptance releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-async constructor cancellation at partial registration releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-async constructor cancellation at native acceptance releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-sync constructor cancellation at partial registration releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-sync constructor cancellation at native acceptance releases its owner",+ "rdkafka-hs-integration.callback-lifetime.async cancellation while waiting for active callback permits retry",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation while waiting for active callback permits retry",+ "rdkafka-hs-integration.callback-lifetime.async closed consumer GC releases its registrations once",+ "rdkafka-hs-integration.callback-lifetime.sync closed consumer GC releases its registrations once",+ "rdkafka-hs-integration.callback-lifetime.producer error callback remains live through close and releases on GC",+ "rdkafka-hs-integration.callback-lifetime.producer log callback remains live through close and releases on GC",+ "rdkafka-hs-integration.callback-lifetime.producer stats callback remains live through close and releases on GC",+ "rdkafka-hs-integration.callback-lifetime.failed native construction releases the caller-owned duplicate config",+ "rdkafka-hs-integration.transaction-errors.transaction-error-leak-probe releases 300 immediate native errors",+ "rdkafka-hs-integration.transaction-errors.native allocation control detects the inherited three-error leak",+ "rdkafka-hs-integration.transaction-errors.initialization timeout destroys its native error on each retry",+ "rdkafka-hs-integration.transaction-errors.zero-timeout initialization resumes successfully against the broker",+ "rdkafka-hs-integration.transaction-errors.transaction state errors preserve empty commit and abort recovery",+ "rdkafka-hs-integration.transaction-errors.duplicate transactional IDs report a real fatal fencing error",+ "rdkafka-hs-integration.transaction-errors.broker-rejected delivery requires abort and permits a successful new transaction",+ "rdkafka-hs-integration.transaction-errors.init without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.begin without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.abort without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.commit without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.offset without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.init NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.begin NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.abort NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.commit NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.offset NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.init invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.begin invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.abort invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.commit invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.offset invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 0 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 1 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 2 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 3 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 4 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 5 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 6 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 7 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 0 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 1 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 2 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 3 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 4 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 5 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 6 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 7 before destruction",+ "rdkafka-hs-integration.transaction-errors.init cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.begin cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.abort cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 21 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 22 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 23 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 21 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 22 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 23 releases once",+ "rdkafka-hs-integration.transaction-errors.async commit publishes output and source next offset atomically; abort publishes neither",+ "rdkafka-hs-integration.transaction-errors.sync commit publishes output and source next offset atomically; abort publishes neither",+ "rdkafka-hs-integration.lifecycle.flushProducerTimeout times out, purgeProducer empties the queue",+ "rdkafka-hs-integration.lifecycle.consumerClosed is False until closeConsumer",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials replaces credentials on a consumer",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials replaces credentials on a producer",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials rejects NUL in username without changing producer or consumer identity",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials rejects NUL in password without changing producer or consumer identity",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials releases each actual native error after decoding its exact code",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials cancellation at error decoding releases the owned error",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials cancellation at error acquisition releases the owned error",+ "rdkafka-hs-integration.producer-regressions.explicit topic timeout expires an accepted message",+ "rdkafka-hs-integration.producer-regressions.global timeout still expires an accepted message",+ "rdkafka-hs-integration.producer-regressions.queue-full rejection releases callback capture without invoking it",+ "rdkafka-hs-integration.producer-regressions.accepted callback retains its capture until a purged report completes",+ "rdkafka-hs-integration.producer-regressions.throwing global callback preserves per-message delivery and releases capture",+ "rdkafka-hs-integration.producer-regressions.throwing per-message callback reports exception and releases capture",+ "rdkafka-hs-integration.producer-regressions.repeated queue-full rejections release every callback capture",+ "rdkafka-hs-integration.producer-regressions.cancellation at a rejected enqueue releases capture before unmasking",+ "rdkafka-hs-integration.producer-regressions.cancellation after native acceptance retains callback until its report",+ "rdkafka-hs-integration.producer-regressions.another poller can deliver before successful enqueue returns",+ "rdkafka-hs-integration.producer-regressions.running callback keeps its capture after the native root is released",+ "rdkafka-hs-integration.producer-regressions.native error decoding failure releases rejected callback capture",+ "rdkafka-hs-integration.producer-regressions.non-null native success-code error rejects and releases capture",+ "rdkafka-hs-integration.producer-regressions.unknown native error code is preserved instead of reading errno",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: defaults",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: global only",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: topic only",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: disjoint maps",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: explicit topic wins duplicate",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: last topic property wins",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: empty topic map preserves global",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: zero topic timeout is infinite",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: maximum native topic timeout",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: explicit topic wins native timeout alias",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: topic codec overrides global codec",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: global codec survives unrelated topic keys",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with NoCompression",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Gzip",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Snappy",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Lz4",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Zstd",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: none",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: inflight",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue+inflight",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue+nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: inflight+nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: all",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: none",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: inflight",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue+inflight",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue+nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: inflight+nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: all",+ "rdkafka-hs-integration.producer-regressions.bounded flush timeout recovers when the delayed response arrives",+ "rdkafka-hs-integration.producer-regressions.close retries a timed-out flush until the delayed delivery completes",+ "rdkafka-hs-integration.producer-regressions.oversized rejection releases capture without a delivery report",+ "rdkafka-hs-integration.producer-regressions.known invalid partition rejection releases capture",+ "rdkafka-hs-integration.producer-regressions.empty queue supports repeated flush and close",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: NUL topic name",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: NUL header name",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: maximum unrepresentable partition",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: minimum unrepresentable partition",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: unknown global key",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: unknown topic key",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: invalid topic timeout",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: excessive topic timeout",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: global-only key in topic map",+ "rdkafka-hs-integration.producer-regressions.later delivery callback replaces the earlier callback",+ "rdkafka-hs-integration.producer-regressions.null native delivery frame reports the generic errno fallback without dereferencing a message",+ "rdkafka-hs-integration.producer-regressions.native delivery without an opaque Haskell callback preserves the complete record",+ "rdkafka-hs-integration.producer-regressions.delivery header acquisition failure preserves the outcome with empty headers",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.counter detects a retained native list before explicit release",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.pair conversion failure releases the partial list before GC",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.offset conversion failure releases the partial list before GC",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.ordinary input lists release after exact native results",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.native logical offsets decode independently without losing partition identity",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.missing native partition queue preserves assignment and later forwarding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.assignment outputs release after exact decoding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.subscription outputs release after exact decoding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.subscription acquisition failure preserves the native error without a list",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.assignment decoder failure releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.subscription decoder failure releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.cancellation at input allocation releases the owned list",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.cancellation at assignment return releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.pair conversion failure releases the partial list before GC",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.offset conversion failure releases the partial list before GC",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.ordinary input lists release after exact native results",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.native logical offsets decode independently without losing partition identity",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.missing native partition queue preserves assignment and later forwarding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.assignment outputs release after exact decoding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.subscription outputs release after exact decoding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.subscription acquisition failure preserves the native error without a list",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.assignment decoder failure releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.subscription decoder failure releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.cancellation at input allocation releases the owned list",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.cancellation at assignment return releases the owned output",+ "rdkafka-hs-integration.public-contract.messages.batch conversion releases every returned native message",+ "rdkafka-hs-integration.public-contract.messages.native message counter detects a retained final object",+ "rdkafka-hs-integration.public-contract.messages.batch decoder exception releases unprocessed messages",+ "rdkafka-hs-integration.public-contract.messages.batch native header errors remain errors while later records are released",+ "rdkafka-hs-integration.public-contract.messages.batch cancellation at native return releases every acquired message",+ "rdkafka-hs-integration.public-contract.messages.batch cancellation at middle conversion releases every acquired message",+ "rdkafka-hs-integration.public-contract.messages.async single cancellation at native return releases its native message",+ "rdkafka-hs-integration.public-contract.messages.async single cancellation at inside conversion releases its native message",+ "rdkafka-hs-integration.public-contract.messages.sync single cancellation at native return releases its native message",+ "rdkafka-hs-integration.public-contract.messages.sync single cancellation at inside conversion releases its native message",+ "rdkafka-hs-integration.public-contract.messages.async header failure preserves the polled record origin",+ "rdkafka-hs-integration.public-contract.messages.sync header failure preserves the polled record origin",+ "rdkafka-hs-integration.public-contract.messages.async plain polling surfaces native header failure",+ "rdkafka-hs-integration.public-contract.messages.sync plain polling surfaces native header failure",+ "rdkafka-hs-integration.public-contract.messages.async attributed error preserves independently absent partition-and-offset",+ "rdkafka-hs-integration.public-contract.messages.async attributed error preserves independently absent offset",+ "rdkafka-hs-integration.public-contract.messages.async attributed error preserves independently absent partition",+ "rdkafka-hs-integration.public-contract.messages.sync attributed error preserves independently absent partition-and-offset",+ "rdkafka-hs-integration.public-contract.messages.sync attributed error preserves independently absent offset",+ "rdkafka-hs-integration.public-contract.messages.sync attributed error preserves independently absent partition",+ "rdkafka-hs-integration.public-contract.messages.callback-event polling cancellation releases a returned message",+ "rdkafka-hs-integration.public-contract.messages.callback buffer preserves attributed header failure",+ "rdkafka-hs-integration.public-contract.messages.callback buffer preserves plain header failure",+ "rdkafka-hs-integration.public-contract.messages.originless callback error survives seek filtering and a paused partition",+ "rdkafka-hs-integration.public-contract.messages.callback-event polling releases and discards a returned fatal frame",+ "rdkafka-hs-integration.public-contract.messages.zero batch size leaves the queued records available",+ "rdkafka-hs-integration.public-contract.messages.unsupported sync batch does not discard a record",+ "rdkafka-hs-integration.public-contract.messages.signed native batch failure preserves its error and queued data",+ "rdkafka-hs-integration.public-contract.messages.infinite batch timeout returns available records",+ "rdkafka-hs-integration.public-contract.messages.batch capacity 1 preserves complete ordered records across partial batches",+ "rdkafka-hs-integration.public-contract.messages.batch capacity 2 preserves complete ordered records across partial batches",+ "rdkafka-hs-integration.public-contract.messages.batch capacity 5 preserves complete ordered records across partial batches",+ "rdkafka-hs-integration.public-contract.messages.invalid batch array size is rejected before native acquisition: -1",+ "rdkafka-hs-integration.public-contract.messages.invalid batch array size is rejected before native acquisition: -9223372036854775808",+ "rdkafka-hs-integration.public-contract.messages.invalid batch array size is rejected before native acquisition: 9223372036854775807",+ "rdkafka-hs-integration.public-contract.messages.batch preserves complete records followed by exact partition EOF and idle timeout",+ "rdkafka-hs-integration.public-contract.messages.empty batch respects timeout 0",+ "rdkafka-hs-integration.public-contract.messages.empty batch respects timeout 100",+ "rdkafka-hs-integration.public-contract.diagnostics.supported-property print flushes and preserves the caller handle",+ "rdkafka-hs-integration.public-contract.diagnostics.client print flushes and preserves the caller handle",+ "rdkafka-hs-integration.public-contract.diagnostics.failed fdopen releases the duplicate and preserves the original",+ "rdkafka-hs-integration.public-contract.diagnostics.failed native flush is reported after closing the duplicate",+ "rdkafka-hs-integration.public-contract.diagnostics.producer configuration dumps retain exact explicit and global settings",+ "rdkafka-hs-integration.public-contract.diagnostics.producer constructor log level overrides the global property on the native client",+ "rdkafka-hs-integration.public-contract.diagnostics.consumer configuration dump preserves global settings after subscription merge",+ "rdkafka-hs-integration.public-contract.diagnostics.native dump counter detects an unreleased array",+ "rdkafka-hs-integration.public-contract.diagnostics.global cancellation at native acquisition releases its array",+ "rdkafka-hs-integration.public-contract.diagnostics.topic cancellation at native acquisition releases its array",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata counter detects an unreleased result",+ "rdkafka-hs-integration.public-contract.metadata-contract.native topic-constructor failure survives metadata convenience queries",+ "rdkafka-hs-integration.public-contract.metadata-contract.empty native metadata remains empty and releases every result",+ "rdkafka-hs-integration.public-contract.metadata-contract.timestamp lookup preserves native overall errors",+ "rdkafka-hs-integration.public-contract.metadata-contract.watermark queries preserve unknown partition errors and empty provided metadata",+ "rdkafka-hs-integration.public-contract.metadata-contract.topic identity replica sets and exact watermarks",+ "rdkafka-hs-integration.public-contract.metadata-contract.distinct native metadata fields retain exact identities and errors",+ "rdkafka-hs-integration.public-contract.metadata-contract.provided metadata preserves partition failures in convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata partition failures survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.group query timeout preserves initial metadata wait failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.missing topic errors survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.timestamp lookup distinguishes before at and after actual record times",+ "rdkafka-hs-integration.public-contract.metadata-contract.mixed timestamp request preserves native partition failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata timeouts preserve the native error",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.groups native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.async group identity lifecycle and supported native states",+ "rdkafka-hs-integration.public-contract.metadata-contract.sync group identity lifecycle and supported native states",+ "rdkafka-hs-integration.public-contract.runtime-contract.RTS capability is observed by async construction",+ "rdkafka-hs-integration.public-contract.runtime-contract.explicit async construction checks the runtime",+ "rdkafka-hs-integration.public-contract.runtime-contract.sync subscription delivers an exact record",+ "rdkafka-hs-integration.public-contract.runtime-contract.deprecated sync runner closes after an exact record"+ ],+ "status": "tested",+ "previous_owner": 15,+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence": [+ "docs/testing/coverage-evidence.json",+ "docs/testing/compatibility-matrix.json"+ ]+ },+ {+ "id": "OWN-source-coverage",+ "symbols": [],+ "owner": 16,+ "behavior": "Every unexercised hand-written Haskell tick/function has a contract-specific test or a source-backed unreachable/inapplicable explanation",+ "inputs": "all source-attributed misses in the combined HPC report",+ "expected": "No unexplained miss and all critical error/ownership branches exercised",+ "modes": "normal optimized and instrumented builds",+ "ownership": "Coverage does not prove C allocation balance; dedicated ownership controls remain required",+ "tests": [],+ "status": "unimplemented",+ "previous_owner": 14,+ "remaining": "Only Producer.hs:204 exception-only StablePtr cleanup remains: two unexecuted ticks. No source exemption or allocation-exhaustion injection is claimed. All other current handwritten misses have individual source-bound classifications."+ },+ {+ "id": "OWN-binding-coverage",+ "symbols": [],+ "owner": 16,+ "behavior": "Hand-written c2hs wrapper coverage is source-mapped separately from generated marshalling; every missing hand-written tick/function is classified",+ "inputs": "all source-attributed misses in the combined HPC report",+ "expected": "No unexplained miss and all critical error/ownership branches exercised",+ "modes": "normal optimized and instrumented builds",+ "ownership": "Coverage does not prove C allocation balance; dedicated ownership controls remain required",+ "tests": [+ "rdkafka-hs-integration.public-contract.partition-list-ownership.counter detects a retained native list before explicit release",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.pair conversion failure releases the partial list before GC",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.offset conversion failure releases the partial list before GC",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.ordinary input lists release after exact native results",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.native logical offsets decode independently without losing partition identity",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.missing native partition queue preserves assignment and later forwarding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.assignment outputs release after exact decoding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.subscription outputs release after exact decoding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.subscription acquisition failure preserves the native error without a list",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.assignment decoder failure releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.subscription decoder failure releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.cancellation at input allocation releases the owned list",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.cancellation at assignment return releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.pair conversion failure releases the partial list before GC",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.offset conversion failure releases the partial list before GC",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.ordinary input lists release after exact native results",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.native logical offsets decode independently without losing partition identity",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.missing native partition queue preserves assignment and later forwarding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.assignment outputs release after exact decoding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.subscription outputs release after exact decoding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.subscription acquisition failure preserves the native error without a list",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.assignment decoder failure releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.subscription decoder failure releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.cancellation at input allocation releases the owned list",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.cancellation at assignment return releases the owned output",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata counter detects an unreleased result",+ "rdkafka-hs-integration.public-contract.metadata-contract.native topic-constructor failure survives metadata convenience queries",+ "rdkafka-hs-integration.public-contract.metadata-contract.empty native metadata remains empty and releases every result",+ "rdkafka-hs-integration.public-contract.metadata-contract.timestamp lookup preserves native overall errors",+ "rdkafka-hs-integration.public-contract.metadata-contract.watermark queries preserve unknown partition errors and empty provided metadata",+ "rdkafka-hs-integration.public-contract.metadata-contract.topic identity replica sets and exact watermarks",+ "rdkafka-hs-integration.public-contract.metadata-contract.distinct native metadata fields retain exact identities and errors",+ "rdkafka-hs-integration.public-contract.metadata-contract.provided metadata preserves partition failures in convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata partition failures survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.group query timeout preserves initial metadata wait failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.missing topic errors survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.timestamp lookup distinguishes before at and after actual record times",+ "rdkafka-hs-integration.public-contract.metadata-contract.mixed timestamp request preserves native partition failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata timeouts preserve the native error",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.groups native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.async group identity lifecycle and supported native states",+ "rdkafka-hs-integration.public-contract.metadata-contract.sync group identity lifecycle and supported native states",+ "rdkafka-hs-integration.transaction-errors.transaction-error-leak-probe releases 300 immediate native errors",+ "rdkafka-hs-integration.transaction-errors.native allocation control detects the inherited three-error leak",+ "rdkafka-hs-integration.transaction-errors.initialization timeout destroys its native error on each retry",+ "rdkafka-hs-integration.transaction-errors.zero-timeout initialization resumes successfully against the broker",+ "rdkafka-hs-integration.transaction-errors.transaction state errors preserve empty commit and abort recovery",+ "rdkafka-hs-integration.transaction-errors.duplicate transactional IDs report a real fatal fencing error",+ "rdkafka-hs-integration.transaction-errors.broker-rejected delivery requires abort and permits a successful new transaction",+ "rdkafka-hs-integration.transaction-errors.init without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.begin without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.abort without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.commit without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.offset without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.init NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.begin NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.abort NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.commit NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.offset NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.init invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.begin invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.abort invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.commit invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.offset invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 0 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 1 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 2 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 3 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 4 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 5 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 6 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 7 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 0 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 1 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 2 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 3 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 4 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 5 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 6 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 7 before destruction",+ "rdkafka-hs-integration.transaction-errors.init cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.begin cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.abort cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 21 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 22 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 23 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 21 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 22 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 23 releases once",+ "rdkafka-hs-integration.transaction-errors.async commit publishes output and source next offset atomically; abort publishes neither",+ "rdkafka-hs-integration.transaction-errors.sync commit publishes output and source next offset atomically; abort publishes neither",+ "rdkafka-hs-integration.public-contract.diagnostics.supported-property print flushes and preserves the caller handle",+ "rdkafka-hs-integration.public-contract.diagnostics.client print flushes and preserves the caller handle",+ "rdkafka-hs-integration.public-contract.diagnostics.failed fdopen releases the duplicate and preserves the original",+ "rdkafka-hs-integration.public-contract.diagnostics.failed native flush is reported after closing the duplicate",+ "rdkafka-hs-integration.public-contract.diagnostics.producer configuration dumps retain exact explicit and global settings",+ "rdkafka-hs-integration.public-contract.diagnostics.producer constructor log level overrides the global property on the native client",+ "rdkafka-hs-integration.public-contract.diagnostics.consumer configuration dump preserves global settings after subscription merge",+ "rdkafka-hs-integration.public-contract.diagnostics.native dump counter detects an unreleased array",+ "rdkafka-hs-integration.public-contract.diagnostics.global cancellation at native acquisition releases its array",+ "rdkafka-hs-integration.public-contract.diagnostics.topic cancellation at native acquisition releases its array"+ ],+ "status": "tested",+ "previous_owner": 14,+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence": [+ "docs/testing/coverage-evidence.json",+ "docs/testing/compatibility-matrix.json"+ ]+ },+ {+ "id": "HARNESS-fixtures",+ "symbols": [],+ "owner": 13,+ "behavior": "Fixtures preserve enqueue/delivery/poll errors, require exact records, and release partial acquisitions with observed interruption and weak-reference controls",+ "inputs": "immediate rejection; delivery/flush failure; missing/wrong report; poll error; missing/extra records; idle before records; setup exception; interrupted second acquisition; retained/released root",+ "expected": "Each injected error is observable; exact successful records/reports pass; partial first resource is released; weak references prove retention then collection",+ "modes": "test-only injectable algorithms plus real broker scenarios in both callback modes",+ "ownership": "First resource released if second setup fails; consumer close then destroy; producer purge then bounded flush; scoped root retained until release",+ "tests": [+ "rdkafka-hs-integration.Fixture error controls.immediate enqueue rejection propagates",+ "rdkafka-hs-integration.Fixture error controls.delivery failure propagates",+ "rdkafka-hs-integration.Fixture error controls.flush failure propagates",+ "rdkafka-hs-integration.Fixture error controls.missing delivery callback fails",+ "rdkafka-hs-integration.Fixture error controls.wrong delivery identity fails",+ "rdkafka-hs-integration.Fixture error controls.matching delivery succeeds",+ "rdkafka-hs-integration.Fixture error controls.unexpected poll error propagates",+ "rdkafka-hs-integration.Fixture error controls.missing record fails",+ "rdkafka-hs-integration.Fixture error controls.extra record fails",+ "rdkafka-hs-integration.Fixture error controls.idle before exact records is retried",+ "rdkafka-hs-integration.Fixture error controls.partial setup releases first resource",+ "rdkafka-hs-integration.Fixture error controls.interrupted partial setup releases first resource",+ "rdkafka-hs-integration.Fixture error controls.weak control retains while rooted and collects after release"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "TOPIC-input-representation",+ "symbols": [+ "Kafka.Topic.createTopic",+ "Kafka.Topic.deleteTopic"+ ],+ "owner": 8,+ "behavior": "Topic C-string and integer marshalling never truncates or wraps into another valid operation",+ "inputs": "NUL names/keys/values; C-unrepresentable high/low counts; representable native invalid boundaries",+ "expected": "KafkaBadSpecification before allocation for unrepresentable inputs; native validation retained for ordinary representable values; NUL deletion preserves the victim",+ "modes": "producer; consumer async/sync; native failure injection where required",+ "ownership": "Scoped application-owned native resources with client/event retention for borrowed views",+ "tests": [+ "rdkafka-hs-integration.topic-configuration.unrepresentable partition count never wraps to broker defaults",+ "rdkafka-hs-integration.topic-configuration.NUL in a topic name never creates a truncated topic",+ "rdkafka-hs-integration.topic-configuration.NUL deletion cannot remove a truncated victim name",+ "rdkafka-hs-integration.topic-configuration.minimum unrepresentable partition count is rejected",+ "rdkafka-hs-integration.topic-configuration.maximum unrepresentable replication count is rejected",+ "rdkafka-hs-integration.topic-configuration.minimum unrepresentable replication count is rejected",+ "rdkafka-hs-integration.topic-configuration.NUL configuration key is rejected before native allocation",+ "rdkafka-hs-integration.topic-configuration.NUL configuration value is rejected before native allocation",+ "rdkafka-hs-integration.topic-configuration.negative invalid partition count retains native validation",+ "rdkafka-hs-integration.topic-configuration.maximum C partition count retains native validation",+ "rdkafka-hs-integration.topic-configuration.negative invalid replication count retains native validation",+ "rdkafka-hs-integration.topic-configuration.maximum C replication count retains native validation"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "TOPIC-request-results",+ "symbols": [+ "Kafka.Topic.createTopic",+ "Kafka.Topic.deleteTopic"+ ],+ "owner": 8,+ "behavior": "Single-topic admin calls preserve request and per-topic errors and require matching complete results",+ "inputs": "native global timeout; wrong event type; empty/mismatched result; missing/delayed poll; malformed native timeout getter",+ "expected": "Exact native errors or KafkaInvalidReturnValue; configured monotonic deadline; actual broker state observed and run-owned topics removed",+ "modes": "producer; consumer async/sync; native failure injection where required",+ "ownership": "Scoped application-owned native resources with client/event retention for borrowed views",+ "tests": [+ "rdkafka-hs-integration.topic-configuration.broker-rejected values release requests and response events repeatedly",+ "rdkafka-hs-integration.topic-configuration.unresponsive broker preserves the native timeout error",+ "rdkafka-hs-integration.topic-configuration.wrong event type fails and releases its event",+ "rdkafka-hs-integration.topic-configuration.empty response fails and releases its event",+ "rdkafka-hs-integration.topic-configuration.wrong topic response cannot report success",+ "rdkafka-hs-integration.topic-configuration.missing polled event reports a timeout",+ "rdkafka-hs-integration.topic-configuration.delayed response succeeds with balanced ownership",+ "rdkafka-hs-integration.topic-configuration.concurrent requests keep their own queues and responses",+ "rdkafka-hs-integration.topic-configuration.unresponsive deletion preserves the native timeout error",+ "rdkafka-hs-integration.topic-configuration.deletion rejects a wrong event type and releases it",+ "rdkafka-hs-integration.topic-configuration.deletion rejects an empty result and releases its event",+ "rdkafka-hs-integration.topic-configuration.deletion reports a missing response as a timeout",+ "rdkafka-hs-integration.topic-configuration.missing native timeout configuration returns an error",+ "rdkafka-hs-integration.topic-configuration.malformed native timeout configuration returns an error",+ "rdkafka-hs-integration.topic-configuration.zero native timeout configuration returns an error",+ "rdkafka-hs-integration.topic-configuration.negative native timeout configuration returns an error",+ "rdkafka-hs-integration.topic-configuration.overflowing native timeout configuration returns an error",+ "rdkafka-hs-integration.topic-configuration.oversized native timeout configuration never reads a truncated buffer"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "TOPIC-client-lifetimes",+ "symbols": [+ "Kafka.Topic.createTopic",+ "Kafka.Topic.deleteTopic"+ ],+ "owner": 8,+ "behavior": "Producer and consumer admin calls keep the client and independent scoped queues alive",+ "inputs": "both consumer callback modes before/after close; observed post-allocation interruption; 20 concurrent requests with overlapping native queue ownership",+ "expected": "Exact independent topic responses and metadata; observed kill delivery boundary; every owned resource released once",+ "modes": "producer; consumer async/sync; native failure injection where required",+ "ownership": "Scoped application-owned native resources with client/event retention for borrowed views",+ "tests": [+ "rdkafka-hs-integration.topic-configuration.native allocation control detects a retained request",+ "rdkafka-hs-integration.topic-configuration.interruption after allocation releases request before submission",+ "rdkafka-hs-integration.topic-configuration.consumer administration applies settings in async mode",+ "rdkafka-hs-integration.topic-configuration.consumer administration applies settings in sync mode",+ "rdkafka-hs-integration.topic-configuration.consumer administration applies settings in async-closed mode",+ "rdkafka-hs-integration.topic-configuration.consumer administration applies settings in sync-closed mode",+ "rdkafka-hs-integration.topic-configuration.concurrent requests keep their own queues and responses"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "ENV-topic-configuration-policy",+ "symbols": [],+ "owner": 18,+ "behavior": "Unrecognized topic configuration follows each actual broker fixture policy",+ "inputs": "primary Redpanda ignore policy and Apache Kafka reject policy, declared explicitly for each compatibility tuple",+ "expected": "The same named native-argument/effective-property test passes under both actual declared broker policies",+ "modes": "required broker compatibility tuples",+ "ownership": "Configuration forwarding and native error resources retain EP-8 scopes",+ "tests": [+ "rdkafka-hs-integration.topic-configuration.unsupported configuration follows the declared broker policy"+ ],+ "status": "tested",+ "previous_owner": 15,+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence": [+ "docs/testing/coverage-evidence.json",+ "docs/testing/compatibility-matrix.json"+ ]+ },+ {+ "id": "ENV-producer-native-headers",+ "symbols": [],+ "owner": 17,+ "behavior": "Native internal header allocations survive the required lifetime and are released on every message path",+ "inputs": "success, immediate queue-full/oversize rejection, observed cancellation and queued/in-flight purge under native heap diagnostics",+ "expected": "Leak/invalid-access diagnostic detects an intentional native cleanup mutation and finds no unexplained candidate allocation or access defects",+ "modes": "required native diagnostic compatibility tuple",+ "ownership": "librdkafka owns header objects created inside produceva; Haskell supplies scoped borrowed name/value buffers",+ "tests": [+ "rdkafka-hs-integration.producer-regressions.explicit topic timeout expires an accepted message",+ "rdkafka-hs-integration.producer-regressions.global timeout still expires an accepted message",+ "rdkafka-hs-integration.producer-regressions.queue-full rejection releases callback capture without invoking it",+ "rdkafka-hs-integration.producer-regressions.accepted callback retains its capture until a purged report completes",+ "rdkafka-hs-integration.producer-regressions.throwing global callback preserves per-message delivery and releases capture",+ "rdkafka-hs-integration.producer-regressions.throwing per-message callback reports exception and releases capture",+ "rdkafka-hs-integration.producer-regressions.repeated queue-full rejections release every callback capture",+ "rdkafka-hs-integration.producer-regressions.cancellation at a rejected enqueue releases capture before unmasking",+ "rdkafka-hs-integration.producer-regressions.cancellation after native acceptance retains callback until its report",+ "rdkafka-hs-integration.producer-regressions.another poller can deliver before successful enqueue returns",+ "rdkafka-hs-integration.producer-regressions.running callback keeps its capture after the native root is released",+ "rdkafka-hs-integration.producer-regressions.native error decoding failure releases rejected callback capture",+ "rdkafka-hs-integration.producer-regressions.non-null native success-code error rejects and releases capture",+ "rdkafka-hs-integration.producer-regressions.unknown native error code is preserved instead of reading errno",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: defaults",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: global only",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: topic only",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: disjoint maps",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: explicit topic wins duplicate",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: last topic property wins",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: empty topic map preserves global",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: zero topic timeout is infinite",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: maximum native topic timeout",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: explicit topic wins native timeout alias",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: topic codec overrides global codec",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: global codec survives unrelated topic keys",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with NoCompression",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Gzip",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Snappy",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Lz4",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Zstd",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: none",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: inflight",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue+inflight",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue+nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: inflight+nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: all",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: none",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: inflight",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue+inflight",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue+nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: inflight+nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: all",+ "rdkafka-hs-integration.producer-regressions.bounded flush timeout recovers when the delayed response arrives",+ "rdkafka-hs-integration.producer-regressions.close retries a timed-out flush until the delayed delivery completes",+ "rdkafka-hs-integration.producer-regressions.oversized rejection releases capture without a delivery report",+ "rdkafka-hs-integration.producer-regressions.known invalid partition rejection releases capture",+ "rdkafka-hs-integration.producer-regressions.empty queue supports repeated flush and close",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: NUL topic name",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: NUL header name",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: maximum unrepresentable partition",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: minimum unrepresentable partition",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: unknown global key",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: unknown topic key",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: invalid topic timeout",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: excessive topic timeout",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: global-only key in topic map",+ "rdkafka-hs-integration.producer-regressions.later delivery callback replaces the earlier callback",+ "rdkafka-hs-integration.producer-regressions.null native delivery frame reports the generic errno fallback without dereferencing a message",+ "rdkafka-hs-integration.producer-regressions.native delivery without an opaque Haskell callback preserves the complete record",+ "rdkafka-hs-integration.producer-regressions.delivery header acquisition failure preserves the outcome with empty headers"+ ],+ "status": "tested",+ "previous_owner": 15,+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence": [+ "docs/testing/coverage-evidence.json",+ "docs/testing/compatibility-matrix.json"+ ]+ },+ {+ "id": "API-Kafka-Consumer-seek",+ "symbols": [+ "Kafka.Consumer.seek"+ ],+ "owner": 16,+ "behavior": "Deprecated seek retains its documented replay and error behavior",+ "inputs": "valid/invalid partitions and offset sentinels; synchronous/asynchronous callback modes; investigate saved intermittent synchronous State failure",+ "expected": "Exact next-record offsets after successful seeks and exact native errors for unsupported state; saved failure must be explained rather than erased by successful reruns",+ "modes": "async and sync callback modes",+ "ownership": "Temporary managed topic handles and their native client remain alive through native seeking; callback-capable finalization belongs to EP-11",+ "tests": [+ "rdkafka-hs-integration.public-contract.consumer-state.async.deprecated-seek-reports-unassigned-state-and-recovers-after-assignment",+ "rdkafka-hs-integration.public-contract.consumer-state.async.legacy-seek-constructor-failure-does-not-execute-an-earlier-valid-seek",+ "rdkafka-hs-integration.public-contract.consumer-state.async.deprecated-seek-exact-repeated-replay",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.deprecated-seek-reports-unassigned-state-and-recovers-after-assignment",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.legacy-seek-constructor-failure-does-not-execute-an-earlier-valid-seek",+ "rdkafka-hs-integration.public-contract.consumer-state.sync.deprecated-seek-exact-repeated-replay",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should seek and return no error",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should seek to the beginning",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should seek to the end",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should respect out-of-bound offsets (invalid offset)",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with async polling.should respect out-of-bound offsets (huge offset)",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should seek and return no error",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should seek to the beginning",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should seek to the end",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should respect out-of-bound offsets (invalid offset)",+ "rdkafka-hs-integration.broker.Consumer.Run consumer with sync polling.should respect out-of-bound offsets (huge offset)"+ ],+ "status": "tested",+ "previous_owner": 14,+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence": [+ "docs/testing/legacy-seek-evidence.json",+ "docs/testing/deferred-public-contract-evidence.json"+ ],+ "historical_diagnosis": "Causal native-only historical reconstruction: late old topic finalizer writes through reused parent memory, removes the active topic from lookup and directs seek to a new never-started partition. Isolated explicit lifetime scoping passes all 182 historical tests; current source already implements that repair."+ },+ {+ "id": "PRODUCER-data-boundaries",+ "symbols": [],+ "owner": 9,+ "behavior": "Producing preserves exact record bytes and rejects C representation loss",+ "inputs": "absent/empty/binary keys and values; tombstones; repeated/empty/binary headers; all five codecs; specified/unassigned partitions; oversize and invalid names/numbers",+ "expected": "Exact delivery and broker-consumed identities and offsets; immediate errors have no native enqueue or callback",+ "modes": "normal optimized and instrumented primary tuple",+ "ownership": "Borrowed record buffers live through enqueue; accepted messages retain native copies and their per-message root",+ "tests": [+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with NoCompression",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Gzip",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Snappy",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Lz4",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Zstd",+ "rdkafka-hs-integration.producer-regressions.oversized rejection releases capture without a delivery report",+ "rdkafka-hs-integration.producer-regressions.known invalid partition rejection releases capture",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: NUL topic name",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: NUL header name",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: maximum unrepresentable partition",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: minimum unrepresentable partition"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "PRODUCER-flush-purge-protocol",+ "symbols": [],+ "owner": 9,+ "behavior": "Each purge flag selects only its outbound queue stage and bounded flush can recover",+ "inputs": "all eight flag subsets with queued and observed in-flight messages; empty queue; timeout then delayed native protocol response",+ "expected": "Exact one failure report per purged record; unselected stages remain pending; recovery yields exact success and offset; repeated flush/close is safe",+ "modes": "normal optimized and instrumented primary tuple",+ "ownership": "Per-message roots release after callback scheduling; native mock cluster and callback-free anchor have scoped destruction",+ "tests": [+ "rdkafka-hs-integration.producer-regressions.queued purge flags: none",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: inflight",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue+inflight",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue+nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: inflight+nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: all",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: none",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: inflight",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue+inflight",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue+nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: inflight+nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: all",+ "rdkafka-hs-integration.producer-regressions.bounded flush timeout recovers when the delayed response arrives",+ "rdkafka-hs-integration.producer-regressions.empty queue supports repeated flush and close"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "PRODUCER-delivery-exceptions",+ "symbols": [],+ "owner": 9,+ "behavior": "Delivery exceptions remain in Haskell while preserving per-message scheduling",+ "inputs": "throwing global/per-message callbacks; running forked callback; callback replacement order",+ "expected": "Isolated process succeeds, runtime handler receives expected exception, one exact per-message report completes, and capture collects afterward",+ "modes": "normal optimized and instrumented primary tuple",+ "ownership": "Delivery root is bracketed before global invocation; forked callback retains closure and runs unmasked",+ "tests": [+ "rdkafka-hs-integration.producer-regressions.throwing global callback preserves per-message delivery and releases capture",+ "rdkafka-hs-integration.producer-regressions.throwing per-message callback reports exception and releases capture",+ "rdkafka-hs-integration.producer-regressions.running callback keeps its capture after the native root is released",+ "rdkafka-hs-integration.producer-regressions.native error decoding failure releases rejected callback capture",+ "rdkafka-hs-integration.producer-regressions.non-null native success-code error rejects and releases capture",+ "rdkafka-hs-integration.producer-regressions.unknown native error code is preserved instead of reading errno",+ "rdkafka-hs-integration.producer-regressions.later delivery callback replaces the earlier callback"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "PRODUCER-ownership-concurrency",+ "symbols": [],+ "owner": 9,+ "behavior": "Enqueue ownership is conditional and safe against cancellation and concurrent polling",+ "inputs": "native barrier before rejection and after real acceptance; killer blocked in throwTo; delivery before enqueue returns; running callback",+ "expected": "Rejected capture collects and is never invoked; accepted capture remains until one report completes; unsafe transfer/mask mutations fail",+ "modes": "normal optimized and instrumented primary tuple",+ "ownership": "Masked caller owns root until immediate result; accepted root transfers to native delivery, then to forked Haskell closure",+ "tests": [+ "rdkafka-hs-integration.producer-regressions.cancellation at a rejected enqueue releases capture before unmasking",+ "rdkafka-hs-integration.producer-regressions.cancellation after native acceptance retains callback until its report",+ "rdkafka-hs-integration.producer-regressions.another poller can deliver before successful enqueue returns",+ "rdkafka-hs-integration.producer-regressions.running callback keeps its capture after the native root is released",+ "rdkafka-hs-integration.producer-regressions.native error decoding failure releases rejected callback capture"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "PROPERTY-producer-composition",+ "symbols": [],+ "owner": 14,+ "behavior": "Producer maps and log levels follow monoid/last-write laws, while callback composition is observed through native delivery",+ "inputs": "generated empty/conflicting/disjoint programs, binary/empty text, log levels, callback partitions and association/identity; fixed edge examples",+ "expected": "Independent write model and exact callback order agree; four reversed-bias mutations shrink and replay their failure tokens",+ "modes": "broker-free pure tests and native callback observations; normal and instrumented primary tuple",+ "ownership": "Generated native clients purge and flush before release; persistent registration lifetime remains EP-11",+ "tests": [+ "rdkafka-hs.Producer properties generated.program follows last-write semantics",+ "rdkafka-hs.Producer properties generated.configuration has left and right identity",+ "rdkafka-hs.Producer properties generated.configuration composition is associative",+ "rdkafka-hs.Producer properties generated.composition appends writes in order",+ "rdkafka-hs.Producer properties generated.unrelated keys survive a conflicting write",+ "rdkafka-hs.Producer properties generated.last explicit log level wins",+ "rdkafka-hs.Producer properties generated.fixed empty duplicate and binary text values",+ "rdkafka-hs-integration.producer-properties.callback composition preserves order and identity"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ },+ {+ "id": "CFG-C-string-boundaries",+ "symbols": [],+ "owner": 14,+ "behavior": "Shared producer/consumer configuration validation rejects C-string representation loss",+ "inputs": "empty and ordinary keys/values, embedded NUL in a known-name prefix or value, producer and consumer construction",+ "expected": "Exact ordinary settings and typed constructor rejection for malformed C-string inputs; no silent truncation",+ "modes": "public constructor/property entry points",+ "ownership": "Rejected construction releases configuration resources; persistent callback registration cleanup belongs to EP-11",+ "tests": [+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.producer topic rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync consumer global rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.async subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL key",+ "rdkafka-hs-integration.public-contract.config-strings.sync subscription rejects NUL value",+ "rdkafka-hs-integration.public-contract.config-strings.empty producer client id retains the native default",+ "rdkafka-hs-integration.public-contract.config-strings.consumer ordinary UTF8 values remain exact",+ "rdkafka-hs-integration.public-contract.config-strings.empty global key retains native unknown-key rejection"+ ],+ "status": "tested",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "evidence_revision": "542b0d782caeca7e7d3b1e91baaf177280bc0885",+ "evidence_configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ }+ }+ ],+ "miss_classifications": {+ "Kafka.Internal.CallbackOwner:77:ExpBox False": {+ "status": "inapplicable",+ "rationale": "This tick is the ignored unit value in pure () on the exhausted pointer list. The branch and drain execute, but no caller demands this value. Live native callbacks, post-destroy weak collection, exactly-once counted frees and the removed-release mutation verify the cleanup effects.",+ "evidence": "test/Kafka/Internal/CallbackOwnerSpec.hs; docs/testing/callback-ownership-inventory.json",+ "source": "src/Kafka/Internal/CallbackOwner.hs",+ "source_sha256": "f2fc3e162b3a953838c39f6b428cb19dd94ebdccf58c8346b611016859dbd308"+ },+ "Kafka.Internal.CallbackOwner:71:ExpBox False": {+ "status": "inapplicable",+ "rationale": "These expression ticks are the lazy Released and current result values passed to pure, not the predicate or drain actions. Production stores the phase and no subsequent public operation inspects a released owner. Counted unit tests force the same source state through reuse/retry checks; native barriers and semantic mutations verify that release completes before publication.",+ "evidence": "test/Kafka/Internal/CallbackOwnerSpec.hs; docs/testing/callback-ownership-inventory.json",+ "source": "src/Kafka/Internal/CallbackOwner.hs",+ "source_sha256": "f2fc3e162b3a953838c39f6b428cb19dd94ebdccf58c8346b611016859dbd308"+ },+ "Kafka.Internal.CallbackOwner:57:ExpBox False": {+ "status": "unreachable",+ "rationale": "Only successful native construction attaches the fresh private owner, once, after the Building check while masked. No exposed route can attach the owner again. The counted test-local copy of the identical source explicitly exercises double transfer rejection.",+ "evidence": "test/Kafka/Internal/CallbackOwnerSpec.hs; docs/testing/callback-ownership-inventory.json",+ "source": "src/Kafka/Internal/CallbackOwner.hs",+ "source_sha256": "f2fc3e162b3a953838c39f6b428cb19dd94ebdccf58c8346b611016859dbd308"+ },+ "Kafka.Internal.CallbackOwner:57:ExpBox True": {+ "status": "unreachable",+ "rationale": "Only successful native construction attaches the fresh private owner, once, after the Building check while masked. No exposed route can attach the owner again. The counted test-local copy of the identical source explicitly exercises double transfer rejection.",+ "evidence": "test/Kafka/Internal/CallbackOwnerSpec.hs; docs/testing/callback-ownership-inventory.json",+ "source": "src/Kafka/Internal/CallbackOwner.hs",+ "source_sha256": "f2fc3e162b3a953838c39f6b428cb19dd94ebdccf58c8346b611016859dbd308"+ },+ "Kafka.Internal.CallbackOwner:51:ExpBox False": {+ "status": "inapplicable",+ "rationale": "This tick is the lazy unit value in pure (). The Building check executes on every native construction; its ignored unit result need not be evaluated. Constructors and counted bridge tests establish the executed check and subsequent transfer.",+ "evidence": "test/Kafka/Internal/CallbackOwnerSpec.hs; docs/testing/callback-ownership-inventory.json",+ "source": "src/Kafka/Internal/CallbackOwner.hs",+ "source_sha256": "f2fc3e162b3a953838c39f6b428cb19dd94ebdccf58c8346b611016859dbd308"+ },+ "Kafka.Internal.CallbackOwner:52:ExpBox False": {+ "status": "unreachable",+ "rationale": "An exposed constructor creates a new private configuration; no public route constructs another native client from an attached/released internal configuration. The identical source is also compiled in the counted unit suite, where transferred and released owners reject reuse before allocation.",+ "evidence": "test/Kafka/Internal/CallbackOwnerSpec.hs; docs/testing/callback-ownership-inventory.json",+ "source": "src/Kafka/Internal/CallbackOwner.hs",+ "source_sha256": "f2fc3e162b3a953838c39f6b428cb19dd94ebdccf58c8346b611016859dbd308"+ },+ "Kafka.Internal.CallbackOwner:52:ExpBox True": {+ "status": "unreachable",+ "rationale": "An exposed constructor creates a new private configuration; no public route constructs another native client from an attached/released internal configuration. The identical source is also compiled in the counted unit suite, where transferred and released owners reject reuse before allocation.",+ "evidence": "test/Kafka/Internal/CallbackOwnerSpec.hs; docs/testing/callback-ownership-inventory.json",+ "source": "src/Kafka/Internal/CallbackOwner.hs",+ "source_sha256": "f2fc3e162b3a953838c39f6b428cb19dd94ebdccf58c8346b611016859dbd308"+ },+ "Kafka.Internal.CallbackOwner:44:ExpBox False": {+ "status": "unreachable",+ "rationale": "Public constructors own a fresh configuration privately through callback installation and transfer. No public operation concurrently releases or attaches its owner between the Building check and registration. The hidden registry guard rejects internal misuse; test-local tests compile the identical source and verify reuse rejection.",+ "evidence": "test/Kafka/Internal/CallbackOwnerSpec.hs; docs/testing/callback-ownership-inventory.json",+ "source": "src/Kafka/Internal/CallbackOwner.hs",+ "source_sha256": "f2fc3e162b3a953838c39f6b428cb19dd94ebdccf58c8346b611016859dbd308"+ },+ "Kafka.Internal.CallbackOwner:44:ExpBox True": {+ "status": "unreachable",+ "rationale": "Public constructors own a fresh configuration privately through callback installation and transfer. No public operation concurrently releases or attaches its owner between the Building check and registration. The hidden registry guard rejects internal misuse; test-local tests compile the identical source and verify reuse rejection.",+ "evidence": "test/Kafka/Internal/CallbackOwnerSpec.hs; docs/testing/callback-ownership-inventory.json",+ "source": "src/Kafka/Internal/CallbackOwner.hs",+ "source_sha256": "f2fc3e162b3a953838c39f6b428cb19dd94ebdccf58c8346b611016859dbd308"+ },+ "Kafka.Internal.CallbackOwner:46:ExpBox False": {+ "status": "unreachable",+ "rationale": "The only registration exception cleanup is guarded by the phase check at line 44. Fresh constructor-private ownership and masked installation exclude a phase change there through public routes; no user code runs in the registry update. Ordinary installation/allocation failure cleanup is exercised separately by counted real bridge tests.",+ "evidence": "test/Kafka/Internal/CallbackOwnerSpec.hs; docs/testing/callback-ownership-inventory.json",+ "source": "src/Kafka/Internal/CallbackOwner.hs",+ "source_sha256": "f2fc3e162b3a953838c39f6b428cb19dd94ebdccf58c8346b611016859dbd308"+ },+ "Kafka.Internal.RdKafka:1202:TopLevelBox [\"peekElemOff\"]": {+ "status": "inapplicable",+ "rationale": "GHC synthesizes this Storable default-method forwarding wrapper at the instance declaration. It is not a handwritten implementation; public conversions use the explicit peek/poke or relevant array methods. No native pointer API exposes this private Storable instance to callers.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1202:TopLevelBox [\"peekByteOff\"]": {+ "status": "inapplicable",+ "rationale": "GHC synthesizes this Storable default-method forwarding wrapper at the instance declaration. It is not a handwritten implementation; public conversions use the explicit peek/poke or relevant array methods. No native pointer API exposes this private Storable instance to callers.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:818:ExpBox False": {+ "status": "inapplicable",+ "rationale": "This private Storable size/alignment capability is not needed by the corresponding public conversion. Native code allocates the object; singleton readers call peek directly, while array readers use the applicable sizeOf methods. The missed capability is never requested by library call sites. Outbound RdKafkaVuT allocation remains measured separately.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:818:TopLevelBox [\"sizeOf\"]": {+ "status": "inapplicable",+ "rationale": "This private Storable size/alignment capability is not needed by the corresponding public conversion. Native code allocates the object; singleton readers call peek directly, while array readers use the applicable sizeOf methods. The missed capability is never requested by library call sites. Outbound RdKafkaVuT allocation remains measured separately.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:817:ExpBox False": {+ "status": "inapplicable",+ "rationale": "This private Storable size/alignment capability is not needed by the corresponding public conversion. Native code allocates the object; singleton readers call peek directly, while array readers use the applicable sizeOf methods. The missed capability is never requested by library call sites. Outbound RdKafkaVuT allocation remains measured separately.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:817:TopLevelBox [\"alignment\"]": {+ "status": "inapplicable",+ "rationale": "This private Storable size/alignment capability is not needed by the corresponding public conversion. Native code allocates the object; singleton readers call peek directly, while array readers use the applicable sizeOf methods. The missed capability is never requested by library call sites. Outbound RdKafkaVuT allocation remains measured separately.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:816:TopLevelBox [\"peekElemOff\"]": {+ "status": "inapplicable",+ "rationale": "GHC synthesizes this Storable default-method forwarding wrapper at the instance declaration. It is not a handwritten implementation; public conversions use the explicit peek/poke or relevant array methods. No native pointer API exposes this private Storable instance to callers.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:816:TopLevelBox [\"pokeElemOff\"]": {+ "status": "inapplicable",+ "rationale": "GHC synthesizes this Storable default-method forwarding wrapper at the instance declaration. It is not a handwritten implementation; public conversions use the explicit peek/poke or relevant array methods. No native pointer API exposes this private Storable instance to callers.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:816:TopLevelBox [\"peekByteOff\"]": {+ "status": "inapplicable",+ "rationale": "GHC synthesizes this Storable default-method forwarding wrapper at the instance declaration. It is not a handwritten implementation; public conversions use the explicit peek/poke or relevant array methods. No native pointer API exposes this private Storable instance to callers.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:816:TopLevelBox [\"pokeByteOff\"]": {+ "status": "inapplicable",+ "rationale": "GHC synthesizes this Storable default-method forwarding wrapper at the instance declaration. It is not a handwritten implementation; public conversions use the explicit peek/poke or relevant array methods. No native pointer API exposes this private Storable instance to callers.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:823:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:824:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:822:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:822:TopLevelBox [\"poke\"]": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:789:ExpBox False": {+ "status": "inapplicable",+ "rationale": "This private Storable size/alignment capability is not needed by the corresponding public conversion. Native code allocates the object; singleton readers call peek directly, while array readers use the applicable sizeOf methods. The missed capability is never requested by library call sites. Outbound RdKafkaVuT allocation remains measured separately.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:789:TopLevelBox [\"alignment\"]": {+ "status": "inapplicable",+ "rationale": "This private Storable size/alignment capability is not needed by the corresponding public conversion. Native code allocates the object; singleton readers call peek directly, while array readers use the applicable sizeOf methods. The missed capability is never requested by library call sites. Outbound RdKafkaVuT allocation remains measured separately.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:788:TopLevelBox [\"pokeElemOff\"]": {+ "status": "inapplicable",+ "rationale": "GHC synthesizes this Storable default-method forwarding wrapper at the instance declaration. It is not a handwritten implementation; public conversions use the explicit peek/poke or relevant array methods. No native pointer API exposes this private Storable instance to callers.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:788:TopLevelBox [\"pokeByteOff\"]": {+ "status": "inapplicable",+ "rationale": "GHC synthesizes this Storable default-method forwarding wrapper at the instance declaration. It is not a handwritten implementation; public conversions use the explicit peek/poke or relevant array methods. No native pointer API exposes this private Storable instance to callers.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:801:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:802:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:803:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:804:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:805:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:806:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:807:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:808:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:800:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:800:TopLevelBox [\"poke\"]": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:757:ExpBox False": {+ "status": "inapplicable",+ "rationale": "This private Storable size/alignment capability is not needed by the corresponding public conversion. Native code allocates the object; singleton readers call peek directly, while array readers use the applicable sizeOf methods. The missed capability is never requested by library call sites. Outbound RdKafkaVuT allocation remains measured separately.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:757:TopLevelBox [\"alignment\"]": {+ "status": "inapplicable",+ "rationale": "This private Storable size/alignment capability is not needed by the corresponding public conversion. Native code allocates the object; singleton readers call peek directly, while array readers use the applicable sizeOf methods. The missed capability is never requested by library call sites. Outbound RdKafkaVuT allocation remains measured separately.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:756:TopLevelBox [\"pokeElemOff\"]": {+ "status": "inapplicable",+ "rationale": "GHC synthesizes this Storable default-method forwarding wrapper at the instance declaration. It is not a handwritten implementation; public conversions use the explicit peek/poke or relevant array methods. No native pointer API exposes this private Storable instance to callers.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:756:TopLevelBox [\"pokeByteOff\"]": {+ "status": "inapplicable",+ "rationale": "GHC synthesizes this Storable default-method forwarding wrapper at the instance declaration. It is not a handwritten implementation; public conversions use the explicit peek/poke or relevant array methods. No native pointer API exposes this private Storable instance to callers.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:768:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:769:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:770:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:771:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:772:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:773:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:774:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:767:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:767:TopLevelBox [\"poke\"]": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:303:ExpBox False": {+ "status": "inapplicable",+ "rationale": "This private Storable size/alignment capability is not needed by the corresponding public conversion. Native code allocates the object; singleton readers call peek directly, while array readers use the applicable sizeOf methods. The missed capability is never requested by library call sites. Outbound RdKafkaVuT allocation remains measured separately.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:303:TopLevelBox [\"sizeOf\"]": {+ "status": "inapplicable",+ "rationale": "This private Storable size/alignment capability is not needed by the corresponding public conversion. Native code allocates the object; singleton readers call peek directly, while array readers use the applicable sizeOf methods. The missed capability is never requested by library call sites. Outbound RdKafkaVuT allocation remains measured separately.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:302:ExpBox False": {+ "status": "inapplicable",+ "rationale": "This private Storable size/alignment capability is not needed by the corresponding public conversion. Native code allocates the object; singleton readers call peek directly, while array readers use the applicable sizeOf methods. The missed capability is never requested by library call sites. Outbound RdKafkaVuT allocation remains measured separately.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:302:TopLevelBox [\"alignment\"]": {+ "status": "inapplicable",+ "rationale": "This private Storable size/alignment capability is not needed by the corresponding public conversion. Native code allocates the object; singleton readers call peek directly, while array readers use the applicable sizeOf methods. The missed capability is never requested by library call sites. Outbound RdKafkaVuT allocation remains measured separately.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:301:TopLevelBox [\"peekElemOff\"]": {+ "status": "inapplicable",+ "rationale": "GHC synthesizes this Storable default-method forwarding wrapper at the instance declaration. It is not a handwritten implementation; public conversions use the explicit peek/poke or relevant array methods. No native pointer API exposes this private Storable instance to callers.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:301:TopLevelBox [\"pokeElemOff\"]": {+ "status": "inapplicable",+ "rationale": "GHC synthesizes this Storable default-method forwarding wrapper at the instance declaration. It is not a handwritten implementation; public conversions use the explicit peek/poke or relevant array methods. No native pointer API exposes this private Storable instance to callers.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:301:TopLevelBox [\"peekByteOff\"]": {+ "status": "inapplicable",+ "rationale": "GHC synthesizes this Storable default-method forwarding wrapper at the instance declaration. It is not a handwritten implementation; public conversions use the explicit peek/poke or relevant array methods. No native pointer API exposes this private Storable instance to callers.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:301:TopLevelBox [\"pokeByteOff\"]": {+ "status": "inapplicable",+ "rationale": "GHC synthesizes this Storable default-method forwarding wrapper at the instance declaration. It is not a handwritten implementation; public conversions use the explicit peek/poke or relevant array methods. No native pointer API exposes this private Storable instance to callers.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:310:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:310:TopLevelBox [\"poke\"]": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:281:ExpBox False": {+ "status": "inapplicable",+ "rationale": "This private Storable size/alignment capability is not needed by the corresponding public conversion. Native code allocates the object; singleton readers call peek directly, while array readers use the applicable sizeOf methods. The missed capability is never requested by library call sites. Outbound RdKafkaVuT allocation remains measured separately.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:281:TopLevelBox [\"alignment\"]": {+ "status": "inapplicable",+ "rationale": "This private Storable size/alignment capability is not needed by the corresponding public conversion. Native code allocates the object; singleton readers call peek directly, while array readers use the applicable sizeOf methods. The missed capability is never requested by library call sites. Outbound RdKafkaVuT allocation remains measured separately.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:280:TopLevelBox [\"pokeElemOff\"]": {+ "status": "inapplicable",+ "rationale": "GHC synthesizes this Storable default-method forwarding wrapper at the instance declaration. It is not a handwritten implementation; public conversions use the explicit peek/poke or relevant array methods. No native pointer API exposes this private Storable instance to callers.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:280:TopLevelBox [\"pokeByteOff\"]": {+ "status": "inapplicable",+ "rationale": "GHC synthesizes this Storable default-method forwarding wrapper at the instance declaration. It is not a handwritten implementation; public conversions use the explicit peek/poke or relevant array methods. No native pointer API exposes this private Storable instance to callers.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:288:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:288:TopLevelBox [\"poke\"]": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:257:ExpBox False": {+ "status": "inapplicable",+ "rationale": "This private Storable size/alignment capability is not needed by the corresponding public conversion. Native code allocates the object; singleton readers call peek directly, while array readers use the applicable sizeOf methods. The missed capability is never requested by library call sites. Outbound RdKafkaVuT allocation remains measured separately.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:257:TopLevelBox [\"alignment\"]": {+ "status": "inapplicable",+ "rationale": "This private Storable size/alignment capability is not needed by the corresponding public conversion. Native code allocates the object; singleton readers call peek directly, while array readers use the applicable sizeOf methods. The missed capability is never requested by library call sites. Outbound RdKafkaVuT allocation remains measured separately.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:256:TopLevelBox [\"pokeElemOff\"]": {+ "status": "inapplicable",+ "rationale": "GHC synthesizes this Storable default-method forwarding wrapper at the instance declaration. It is not a handwritten implementation; public conversions use the explicit peek/poke or relevant array methods. No native pointer API exposes this private Storable instance to callers.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:256:TopLevelBox [\"pokeByteOff\"]": {+ "status": "inapplicable",+ "rationale": "GHC synthesizes this Storable default-method forwarding wrapper at the instance declaration. It is not a handwritten implementation; public conversions use the explicit peek/poke or relevant array methods. No native pointer API exposes this private Storable instance to callers.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:268:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:268:TopLevelBox [\"poke\"]": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:237:ExpBox False": {+ "status": "inapplicable",+ "rationale": "This private Storable size/alignment capability is not needed by the corresponding public conversion. Native code allocates the object; singleton readers call peek directly, while array readers use the applicable sizeOf methods. The missed capability is never requested by library call sites. Outbound RdKafkaVuT allocation remains measured separately.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:237:TopLevelBox [\"alignment\"]": {+ "status": "inapplicable",+ "rationale": "This private Storable size/alignment capability is not needed by the corresponding public conversion. Native code allocates the object; singleton readers call peek directly, while array readers use the applicable sizeOf methods. The missed capability is never requested by library call sites. Outbound RdKafkaVuT allocation remains measured separately.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:236:TopLevelBox [\"pokeElemOff\"]": {+ "status": "inapplicable",+ "rationale": "GHC synthesizes this Storable default-method forwarding wrapper at the instance declaration. It is not a handwritten implementation; public conversions use the explicit peek/poke or relevant array methods. No native pointer API exposes this private Storable instance to callers.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:236:TopLevelBox [\"pokeByteOff\"]": {+ "status": "inapplicable",+ "rationale": "GHC synthesizes this Storable default-method forwarding wrapper at the instance declaration. It is not a handwritten implementation; public conversions use the explicit peek/poke or relevant array methods. No native pointer API exposes this private Storable instance to callers.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:243:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:243:TopLevelBox [\"poke\"]": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:202:ExpBox False": {+ "status": "inapplicable",+ "rationale": "This private Storable size/alignment capability is not needed by the corresponding public conversion. Native code allocates the object; singleton readers call peek directly, while array readers use the applicable sizeOf methods. The missed capability is never requested by library call sites. Outbound RdKafkaVuT allocation remains measured separately.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:202:TopLevelBox [\"sizeOf\"]": {+ "status": "inapplicable",+ "rationale": "This private Storable size/alignment capability is not needed by the corresponding public conversion. Native code allocates the object; singleton readers call peek directly, while array readers use the applicable sizeOf methods. The missed capability is never requested by library call sites. Outbound RdKafkaVuT allocation remains measured separately.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:201:ExpBox False": {+ "status": "inapplicable",+ "rationale": "This private Storable size/alignment capability is not needed by the corresponding public conversion. Native code allocates the object; singleton readers call peek directly, while array readers use the applicable sizeOf methods. The missed capability is never requested by library call sites. Outbound RdKafkaVuT allocation remains measured separately.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:201:TopLevelBox [\"alignment\"]": {+ "status": "inapplicable",+ "rationale": "This private Storable size/alignment capability is not needed by the corresponding public conversion. Native code allocates the object; singleton readers call peek directly, while array readers use the applicable sizeOf methods. The missed capability is never requested by library call sites. Outbound RdKafkaVuT allocation remains measured separately.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:200:TopLevelBox [\"peekElemOff\"]": {+ "status": "inapplicable",+ "rationale": "GHC synthesizes this Storable default-method forwarding wrapper at the instance declaration. It is not a handwritten implementation; public conversions use the explicit peek/poke or relevant array methods. No native pointer API exposes this private Storable instance to callers.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:200:TopLevelBox [\"pokeElemOff\"]": {+ "status": "inapplicable",+ "rationale": "GHC synthesizes this Storable default-method forwarding wrapper at the instance declaration. It is not a handwritten implementation; public conversions use the explicit peek/poke or relevant array methods. No native pointer API exposes this private Storable instance to callers.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:200:TopLevelBox [\"peekByteOff\"]": {+ "status": "inapplicable",+ "rationale": "GHC synthesizes this Storable default-method forwarding wrapper at the instance declaration. It is not a handwritten implementation; public conversions use the explicit peek/poke or relevant array methods. No native pointer API exposes this private Storable instance to callers.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:200:TopLevelBox [\"pokeByteOff\"]": {+ "status": "inapplicable",+ "rationale": "GHC synthesizes this Storable default-method forwarding wrapper at the instance declaration. It is not a handwritten implementation; public conversions use the explicit peek/poke or relevant array methods. No native pointer API exposes this private Storable instance to callers.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:214:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:215:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:216:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:217:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:218:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:219:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:220:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:221:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:222:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:213:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:213:TopLevelBox [\"poke\"]": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:174:ExpBox False": {+ "status": "inapplicable",+ "rationale": "This private Storable size/alignment capability is not needed by the corresponding public conversion. Native code allocates the object; singleton readers call peek directly, while array readers use the applicable sizeOf methods. The missed capability is never requested by library call sites. Outbound RdKafkaVuT allocation remains measured separately.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:174:TopLevelBox [\"sizeOf\"]": {+ "status": "inapplicable",+ "rationale": "This private Storable size/alignment capability is not needed by the corresponding public conversion. Native code allocates the object; singleton readers call peek directly, while array readers use the applicable sizeOf methods. The missed capability is never requested by library call sites. Outbound RdKafkaVuT allocation remains measured separately.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:173:ExpBox False": {+ "status": "inapplicable",+ "rationale": "This private Storable size/alignment capability is not needed by the corresponding public conversion. Native code allocates the object; singleton readers call peek directly, while array readers use the applicable sizeOf methods. The missed capability is never requested by library call sites. Outbound RdKafkaVuT allocation remains measured separately.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:173:TopLevelBox [\"alignment\"]": {+ "status": "inapplicable",+ "rationale": "This private Storable size/alignment capability is not needed by the corresponding public conversion. Native code allocates the object; singleton readers call peek directly, while array readers use the applicable sizeOf methods. The missed capability is never requested by library call sites. Outbound RdKafkaVuT allocation remains measured separately.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:172:TopLevelBox [\"peekElemOff\"]": {+ "status": "inapplicable",+ "rationale": "GHC synthesizes this Storable default-method forwarding wrapper at the instance declaration. It is not a handwritten implementation; public conversions use the explicit peek/poke or relevant array methods. No native pointer API exposes this private Storable instance to callers.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:172:TopLevelBox [\"pokeElemOff\"]": {+ "status": "inapplicable",+ "rationale": "GHC synthesizes this Storable default-method forwarding wrapper at the instance declaration. It is not a handwritten implementation; public conversions use the explicit peek/poke or relevant array methods. No native pointer API exposes this private Storable instance to callers.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:172:TopLevelBox [\"peekByteOff\"]": {+ "status": "inapplicable",+ "rationale": "GHC synthesizes this Storable default-method forwarding wrapper at the instance declaration. It is not a handwritten implementation; public conversions use the explicit peek/poke or relevant array methods. No native pointer API exposes this private Storable instance to callers.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:172:TopLevelBox [\"pokeByteOff\"]": {+ "status": "inapplicable",+ "rationale": "GHC synthesizes this Storable default-method forwarding wrapper at the instance declaration. It is not a handwritten implementation; public conversions use the explicit peek/poke or relevant array methods. No native pointer API exposes this private Storable instance to callers.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:180:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:181:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:182:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:179:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:179:TopLevelBox [\"poke\"]": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:142:ExpBox False": {+ "status": "inapplicable",+ "rationale": "This private Storable size/alignment capability is not needed by the corresponding public conversion. Native code allocates the object; singleton readers call peek directly, while array readers use the applicable sizeOf methods. The missed capability is never requested by library call sites. Outbound RdKafkaVuT allocation remains measured separately.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:142:TopLevelBox [\"alignment\"]": {+ "status": "inapplicable",+ "rationale": "This private Storable size/alignment capability is not needed by the corresponding public conversion. Native code allocates the object; singleton readers call peek directly, while array readers use the applicable sizeOf methods. The missed capability is never requested by library call sites. Outbound RdKafkaVuT allocation remains measured separately.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:141:TopLevelBox [\"pokeElemOff\"]": {+ "status": "inapplicable",+ "rationale": "GHC synthesizes this Storable default-method forwarding wrapper at the instance declaration. It is not a handwritten implementation; public conversions use the explicit peek/poke or relevant array methods. No native pointer API exposes this private Storable instance to callers.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:141:TopLevelBox [\"pokeByteOff\"]": {+ "status": "inapplicable",+ "rationale": "GHC synthesizes this Storable default-method forwarding wrapper at the instance declaration. It is not a handwritten implementation; public conversions use the explicit peek/poke or relevant array methods. No native pointer API exposes this private Storable instance to callers.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:153:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:154:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:155:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:156:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:157:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:158:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:159:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:152:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:152:TopLevelBox [\"poke\"]": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:871:TopLevelBox [\"peekElemOff\"]": {+ "status": "inapplicable",+ "rationale": "GHC synthesizes this Storable default-method forwarding wrapper at the instance declaration. It is not a handwritten implementation; public conversions use the explicit peek/poke or relevant array methods. No native pointer API exposes this private Storable instance to callers.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:871:TopLevelBox [\"pokeElemOff\"]": {+ "status": "inapplicable",+ "rationale": "GHC synthesizes this Storable default-method forwarding wrapper at the instance declaration. It is not a handwritten implementation; public conversions use the explicit peek/poke or relevant array methods. No native pointer API exposes this private Storable instance to callers.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:871:TopLevelBox [\"peekByteOff\"]": {+ "status": "inapplicable",+ "rationale": "GHC synthesizes this Storable default-method forwarding wrapper at the instance declaration. It is not a handwritten implementation; public conversions use the explicit peek/poke or relevant array methods. No native pointer API exposes this private Storable instance to callers.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:871:TopLevelBox [\"pokeByteOff\"]": {+ "status": "inapplicable",+ "rationale": "GHC synthesizes this Storable default-method forwarding wrapper at the instance declaration. It is not a handwritten implementation; public conversions use the explicit peek/poke or relevant array methods. No native pointer API exposes this private Storable instance to callers.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:875:ExpBox False": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:875:TopLevelBox [\"poke\"]": {+ "status": "unreachable",+ "rationale": "These private Storable write methods are not called by any public path. Native APIs allocate/populate messages, partition lists and metadata/group results; the library reads them and uses native list setters. The only aggregate Haskell write path is the distinct outbound RdKafkaVuT array. Explicit unsupported metadata poke methods are likewise outside the public API.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Consumer/Convert.hs; src/Kafka/Metadata.hs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:691:ExpBox False": {+ "status": "unreachable",+ "rationale": "pollRdKafkaConsumer is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:692:ExpBox False": {+ "status": "unreachable",+ "rationale": "pollRdKafkaConsumer is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:693:ExpBox False": {+ "status": "unreachable",+ "rationale": "pollRdKafkaConsumer is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:694:ExpBox False": {+ "status": "unreachable",+ "rationale": "pollRdKafkaConsumer is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:695:ExpBox False": {+ "status": "unreachable",+ "rationale": "pollRdKafkaConsumer is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:690:ExpBox False": {+ "status": "unreachable",+ "rationale": "pollRdKafkaConsumer is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:690:TopLevelBox [\"pollRdKafkaConsumer\"]": {+ "status": "unreachable",+ "rationale": "pollRdKafkaConsumer is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:518:ExpBox False": {+ "status": "unreachable",+ "rationale": "rdKafkaTopicConfSetPartitionerCb is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:519:ExpBox False": {+ "status": "unreachable",+ "rationale": "rdKafkaTopicConfSetPartitionerCb is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:520:ExpBox False": {+ "status": "unreachable",+ "rationale": "rdKafkaTopicConfSetPartitionerCb is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:517:TopLevelBox [\"rdKafkaTopicConfSetPartitionerCb\"]": {+ "status": "unreachable",+ "rationale": "rdKafkaTopicConfSetPartitionerCb is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:488:ExpBox False": {+ "status": "unreachable",+ "rationale": "rdKafkaConfSetSocketCb is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:489:ExpBox False": {+ "status": "unreachable",+ "rationale": "rdKafkaConfSetSocketCb is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:487:TopLevelBox [\"rdKafkaConfSetSocketCb\"]": {+ "status": "unreachable",+ "rationale": "rdKafkaConfSetSocketCb is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:441:ExpBox False": {+ "status": "unreachable",+ "rationale": "rdKafkaConfSetThrottleCb is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:442:ExpBox False": {+ "status": "unreachable",+ "rationale": "rdKafkaConfSetThrottleCb is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:440:TopLevelBox [\"rdKafkaConfSetThrottleCb\"]": {+ "status": "unreachable",+ "rationale": "rdKafkaConfSetThrottleCb is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:396:ExpBox False": {+ "status": "unreachable",+ "rationale": "rdKafkaConfSetConsumeCb is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:397:ExpBox False": {+ "status": "unreachable",+ "rationale": "rdKafkaConfSetConsumeCb is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:395:TopLevelBox [\"rdKafkaConfSetConsumeCb\"]": {+ "status": "unreachable",+ "rationale": "rdKafkaConfSetConsumeCb is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:343:ExpBox False": {+ "status": "unreachable",+ "rationale": "copyRdKafkaTopicPartitionList is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:344:ExpBox False": {+ "status": "unreachable",+ "rationale": "copyRdKafkaTopicPartitionList is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:345:ExpBox False": {+ "status": "unreachable",+ "rationale": "copyRdKafkaTopicPartitionList is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:346:ExpBox False": {+ "status": "unreachable",+ "rationale": "copyRdKafkaTopicPartitionList is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:344:TopLevelBox [\"copyRdKafkaTopicPartitionList\"]": {+ "status": "unreachable",+ "rationale": "copyRdKafkaTopicPartitionList is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1024:ExpBox False": {+ "status": "unreachable",+ "rationale": "rdKafkaConsumeStart is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1025:ExpBox False": {+ "status": "unreachable",+ "rationale": "rdKafkaConsumeStart is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1026:ExpBox False": {+ "status": "unreachable",+ "rationale": "rdKafkaConsumeStart is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1026:ExpBox True": {+ "status": "unreachable",+ "rationale": "rdKafkaConsumeStart is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1027:ExpBox False": {+ "status": "unreachable",+ "rationale": "rdKafkaConsumeStart is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1027:ExpBox True": {+ "status": "unreachable",+ "rationale": "rdKafkaConsumeStart is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1023:ExpBox False": {+ "status": "unreachable",+ "rationale": "rdKafkaConsumeStart is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1023:TopLevelBox [\"rdKafkaConsumeStart\"]": {+ "status": "unreachable",+ "rationale": "rdKafkaConsumeStart is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1043:ExpBox False": {+ "status": "unreachable",+ "rationale": "rdKafkaConsumeStop is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1044:ExpBox False": {+ "status": "unreachable",+ "rationale": "rdKafkaConsumeStop is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1045:ExpBox False": {+ "status": "unreachable",+ "rationale": "rdKafkaConsumeStop is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1045:ExpBox True": {+ "status": "unreachable",+ "rationale": "rdKafkaConsumeStop is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1046:ExpBox False": {+ "status": "unreachable",+ "rationale": "rdKafkaConsumeStop is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1046:ExpBox True": {+ "status": "unreachable",+ "rationale": "rdKafkaConsumeStop is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1042:ExpBox False": {+ "status": "unreachable",+ "rationale": "rdKafkaConsumeStop is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1042:TopLevelBox [\"rdKafkaConsumeStop\"]": {+ "status": "unreachable",+ "rationale": "rdKafkaConsumeStop is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1371:ExpBox False": {+ "status": "unreachable",+ "rationale": "newRdKafkaNewTopic is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1372:ExpBox False": {+ "status": "unreachable",+ "rationale": "newRdKafkaNewTopic is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1373:ExpBox False": {+ "status": "unreachable",+ "rationale": "newRdKafkaNewTopic is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1374:ExpBox False": {+ "status": "unreachable",+ "rationale": "newRdKafkaNewTopic is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1374:BinBox CondBinBox True": {+ "status": "unreachable",+ "rationale": "newRdKafkaNewTopic is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1374:BinBox CondBinBox False": {+ "status": "unreachable",+ "rationale": "newRdKafkaNewTopic is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1375:ExpBox False": {+ "status": "unreachable",+ "rationale": "newRdKafkaNewTopic is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1375:ExpBox True": {+ "status": "unreachable",+ "rationale": "newRdKafkaNewTopic is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1376:ExpBox False": {+ "status": "unreachable",+ "rationale": "newRdKafkaNewTopic is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1376:ExpBox True": {+ "status": "unreachable",+ "rationale": "newRdKafkaNewTopic is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1370:ExpBox False": {+ "status": "unreachable",+ "rationale": "newRdKafkaNewTopic is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1370:TopLevelBox [\"newRdKafkaNewTopic\"]": {+ "status": "unreachable",+ "rationale": "newRdKafkaNewTopic is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:85:ExpBox False": {+ "status": "unreachable",+ "rationale": "rdKafkaMsgFlagFree is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:85:TopLevelBox [\"rdKafkaMsgFlagFree\"]": {+ "status": "unreachable",+ "rationale": "rdKafkaMsgFlagFree is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:84:ExpBox False": {+ "status": "unreachable",+ "rationale": "rdKafkaMsgFlagFree is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:84:ExpBox True": {+ "status": "unreachable",+ "rationale": "rdKafkaMsgFlagFree is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:85:ExpBox True": {+ "status": "unreachable",+ "rationale": "rdKafkaMsgFlagFree is an unused helper in the private Kafka.Internal.RdKafka module. Its name occurs only in its declaration/definition and internal setter call, with no caller under src. The module is not exposed by Cabal. Public producers/consumers/admin use the distinct active implementations; none invokes this legacy or unexposed capability.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; rdkafka-hs.cabal; docs/testing/private-binding-coverage-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1205:ExpBox False": {+ "status": "unreachable",+ "rationale": "RdKafkaVuT is only an outbound argument union. Public producers construct values that withArrayLen writes for rd_kafka_produceva; no src call reads this private union with peek. Native test observers inspect C arguments directly and do not use this Haskell reader.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1206:ExpBox False": {+ "status": "unreachable",+ "rationale": "RdKafkaVuT is only an outbound argument union. Public producers construct values that withArrayLen writes for rd_kafka_produceva; no src call reads this private union with peek. Native test observers inspect C arguments directly and do not use this Haskell reader.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1206:ExpBox True": {+ "status": "unreachable",+ "rationale": "RdKafkaVuT is only an outbound argument union. Public producers construct values that withArrayLen writes for rd_kafka_produceva; no src call reads this private union with peek. Native test observers inspect C arguments directly and do not use this Haskell reader.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1207:ExpBox False": {+ "status": "unreachable",+ "rationale": "RdKafkaVuT is only an outbound argument union. Public producers construct values that withArrayLen writes for rd_kafka_produceva; no src call reads this private union with peek. Native test observers inspect C arguments directly and do not use this Haskell reader.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1207:ExpBox True": {+ "status": "unreachable",+ "rationale": "RdKafkaVuT is only an outbound argument union. Public producers construct values that withArrayLen writes for rd_kafka_produceva; no src call reads this private union with peek. Native test observers inspect C arguments directly and do not use this Haskell reader.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1208:ExpBox False": {+ "status": "unreachable",+ "rationale": "RdKafkaVuT is only an outbound argument union. Public producers construct values that withArrayLen writes for rd_kafka_produceva; no src call reads this private union with peek. Native test observers inspect C arguments directly and do not use this Haskell reader.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1208:ExpBox True": {+ "status": "unreachable",+ "rationale": "RdKafkaVuT is only an outbound argument union. Public producers construct values that withArrayLen writes for rd_kafka_produceva; no src call reads this private union with peek. Native test observers inspect C arguments directly and do not use this Haskell reader.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1209:ExpBox False": {+ "status": "unreachable",+ "rationale": "RdKafkaVuT is only an outbound argument union. Public producers construct values that withArrayLen writes for rd_kafka_produceva; no src call reads this private union with peek. Native test observers inspect C arguments directly and do not use this Haskell reader.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1209:ExpBox True": {+ "status": "unreachable",+ "rationale": "RdKafkaVuT is only an outbound argument union. Public producers construct values that withArrayLen writes for rd_kafka_produceva; no src call reads this private union with peek. Native test observers inspect C arguments directly and do not use this Haskell reader.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1210:ExpBox False": {+ "status": "unreachable",+ "rationale": "RdKafkaVuT is only an outbound argument union. Public producers construct values that withArrayLen writes for rd_kafka_produceva; no src call reads this private union with peek. Native test observers inspect C arguments directly and do not use this Haskell reader.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1210:ExpBox True": {+ "status": "unreachable",+ "rationale": "RdKafkaVuT is only an outbound argument union. Public producers construct values that withArrayLen writes for rd_kafka_produceva; no src call reads this private union with peek. Native test observers inspect C arguments directly and do not use this Haskell reader.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1211:ExpBox False": {+ "status": "unreachable",+ "rationale": "RdKafkaVuT is only an outbound argument union. Public producers construct values that withArrayLen writes for rd_kafka_produceva; no src call reads this private union with peek. Native test observers inspect C arguments directly and do not use this Haskell reader.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1211:ExpBox True": {+ "status": "unreachable",+ "rationale": "RdKafkaVuT is only an outbound argument union. Public producers construct values that withArrayLen writes for rd_kafka_produceva; no src call reads this private union with peek. Native test observers inspect C arguments directly and do not use this Haskell reader.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1213:ExpBox False": {+ "status": "unreachable",+ "rationale": "RdKafkaVuT is only an outbound argument union. Public producers construct values that withArrayLen writes for rd_kafka_produceva; no src call reads this private union with peek. Native test observers inspect C arguments directly and do not use this Haskell reader.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1214:ExpBox False": {+ "status": "unreachable",+ "rationale": "RdKafkaVuT is only an outbound argument union. Public producers construct values that withArrayLen writes for rd_kafka_produceva; no src call reads this private union with peek. Native test observers inspect C arguments directly and do not use this Haskell reader.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1215:ExpBox False": {+ "status": "unreachable",+ "rationale": "RdKafkaVuT is only an outbound argument union. Public producers construct values that withArrayLen writes for rd_kafka_produceva; no src call reads this private union with peek. Native test observers inspect C arguments directly and do not use this Haskell reader.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1212:ExpBox True": {+ "status": "unreachable",+ "rationale": "RdKafkaVuT is only an outbound argument union. Public producers construct values that withArrayLen writes for rd_kafka_produceva; no src call reads this private union with peek. Native test observers inspect C arguments directly and do not use this Haskell reader.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1217:ExpBox False": {+ "status": "unreachable",+ "rationale": "RdKafkaVuT is only an outbound argument union. Public producers construct values that withArrayLen writes for rd_kafka_produceva; no src call reads this private union with peek. Native test observers inspect C arguments directly and do not use this Haskell reader.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1218:ExpBox False": {+ "status": "unreachable",+ "rationale": "RdKafkaVuT is only an outbound argument union. Public producers construct values that withArrayLen writes for rd_kafka_produceva; no src call reads this private union with peek. Native test observers inspect C arguments directly and do not use this Haskell reader.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1219:ExpBox False": {+ "status": "unreachable",+ "rationale": "RdKafkaVuT is only an outbound argument union. Public producers construct values that withArrayLen writes for rd_kafka_produceva; no src call reads this private union with peek. Native test observers inspect C arguments directly and do not use this Haskell reader.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1216:ExpBox True": {+ "status": "unreachable",+ "rationale": "RdKafkaVuT is only an outbound argument union. Public producers construct values that withArrayLen writes for rd_kafka_produceva; no src call reads this private union with peek. Native test observers inspect C arguments directly and do not use this Haskell reader.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1220:ExpBox False": {+ "status": "unreachable",+ "rationale": "RdKafkaVuT is only an outbound argument union. Public producers construct values that withArrayLen writes for rd_kafka_produceva; no src call reads this private union with peek. Native test observers inspect C arguments directly and do not use this Haskell reader.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1220:ExpBox True": {+ "status": "unreachable",+ "rationale": "RdKafkaVuT is only an outbound argument union. Public producers construct values that withArrayLen writes for rd_kafka_produceva; no src call reads this private union with peek. Native test observers inspect C arguments directly and do not use this Haskell reader.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1221:ExpBox False": {+ "status": "unreachable",+ "rationale": "RdKafkaVuT is only an outbound argument union. Public producers construct values that withArrayLen writes for rd_kafka_produceva; no src call reads this private union with peek. Native test observers inspect C arguments directly and do not use this Haskell reader.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1221:ExpBox True": {+ "status": "unreachable",+ "rationale": "RdKafkaVuT is only an outbound argument union. Public producers construct values that withArrayLen writes for rd_kafka_produceva; no src call reads this private union with peek. Native test observers inspect C arguments directly and do not use this Haskell reader.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1223:ExpBox False": {+ "status": "unreachable",+ "rationale": "RdKafkaVuT is only an outbound argument union. Public producers construct values that withArrayLen writes for rd_kafka_produceva; no src call reads this private union with peek. Native test observers inspect C arguments directly and do not use this Haskell reader.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1224:ExpBox False": {+ "status": "unreachable",+ "rationale": "RdKafkaVuT is only an outbound argument union. Public producers construct values that withArrayLen writes for rd_kafka_produceva; no src call reads this private union with peek. Native test observers inspect C arguments directly and do not use this Haskell reader.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1225:ExpBox False": {+ "status": "unreachable",+ "rationale": "RdKafkaVuT is only an outbound argument union. Public producers construct values that withArrayLen writes for rd_kafka_produceva; no src call reads this private union with peek. Native test observers inspect C arguments directly and do not use this Haskell reader.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1226:ExpBox False": {+ "status": "unreachable",+ "rationale": "RdKafkaVuT is only an outbound argument union. Public producers construct values that withArrayLen writes for rd_kafka_produceva; no src call reads this private union with peek. Native test observers inspect C arguments directly and do not use this Haskell reader.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1222:ExpBox True": {+ "status": "unreachable",+ "rationale": "RdKafkaVuT is only an outbound argument union. Public producers construct values that withArrayLen writes for rd_kafka_produceva; no src call reads this private union with peek. Native test observers inspect C arguments directly and do not use this Haskell reader.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1205:TopLevelBox [\"peek\"]": {+ "status": "unreachable",+ "rationale": "RdKafkaVuT is only an outbound argument union. Public producers construct values that withArrayLen writes for rd_kafka_produceva; no src call reads this private union with peek. Native test observers inspect C arguments directly and do not use this Haskell reader.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1228:ExpBox False": {+ "status": "unreachable",+ "rationale": "The outbound argument array supplies an explicit count, so public producers do not construct an End terminator.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1228:ExpBox True": {+ "status": "unreachable",+ "rationale": "The outbound argument array supplies an explicit count, so public producers do not construct an End terminator.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1233:ExpBox False": {+ "status": "unreachable",+ "rationale": "ProducerRecord has no per-record timestamp input. No src call constructs the private Timestamp union variant.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1234:ExpBox False": {+ "status": "unreachable",+ "rationale": "ProducerRecord has no per-record timestamp input. No src call constructs the private Timestamp union variant.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1232:ExpBox True": {+ "status": "unreachable",+ "rationale": "ProducerRecord has no per-record timestamp input. No src call constructs the private Timestamp union variant.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1242:ExpBox False": {+ "status": "unreachable",+ "rationale": "Public Headers are ordered byte pairs converted to individual Header union entries; no src call supplies a prebuilt native header-list pointer.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1243:ExpBox False": {+ "status": "unreachable",+ "rationale": "Public Headers are ordered byte pairs converted to individual Header union entries; no src call supplies a prebuilt native header-list pointer.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1241:ExpBox True": {+ "status": "unreachable",+ "rationale": "Public Headers are ordered byte pairs converted to individual Header union entries; no src call supplies a prebuilt native header-list pointer.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1245:ExpBox False": {+ "status": "unreachable",+ "rationale": "Public ProducerRecord selects a TopicName, not a native topic handle. No src call constructs this private union variant.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1246:ExpBox False": {+ "status": "unreachable",+ "rationale": "Public ProducerRecord selects a TopicName, not a native topic handle. No src call constructs this private union variant.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1244:ExpBox True": {+ "status": "unreachable",+ "rationale": "Public ProducerRecord selects a TopicName, not a native topic handle. No src call constructs this private union variant.",+ "evidence": "src/Kafka/Internal/RdKafka.chs; src/Kafka/Producer.hs; rdkafka-hs.cabal (private other-modules)",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Consumer.Convert:63:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Consumer/Convert.hs:62-66: private offsetSyncToInt has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Consumer/Convert.hs",+ "source_sha256": "9bf267580d3ee008308585ee061e9364a1dbc6556090d78b5e5df0ef767b9115"+ },+ "Kafka.Consumer.Convert:64:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Consumer/Convert.hs:62-66: private offsetSyncToInt has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Consumer/Convert.hs",+ "source_sha256": "9bf267580d3ee008308585ee061e9364a1dbc6556090d78b5e5df0ef767b9115"+ },+ "Kafka.Consumer.Convert:64:ExpBox True": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Consumer/Convert.hs:62-66: private offsetSyncToInt has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Consumer/Convert.hs",+ "source_sha256": "9bf267580d3ee008308585ee061e9364a1dbc6556090d78b5e5df0ef767b9115"+ },+ "Kafka.Consumer.Convert:65:ExpBox True": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Consumer/Convert.hs:62-66: private offsetSyncToInt has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Consumer/Convert.hs",+ "source_sha256": "9bf267580d3ee008308585ee061e9364a1dbc6556090d78b5e5df0ef767b9115"+ },+ "Kafka.Consumer.Convert:66:ExpBox True": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Consumer/Convert.hs:62-66: private offsetSyncToInt has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Consumer/Convert.hs",+ "source_sha256": "9bf267580d3ee008308585ee061e9364a1dbc6556090d78b5e5df0ef767b9115"+ },+ "Kafka.Consumer.Convert:62:TopLevelBox [\"offsetSyncToInt\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Consumer/Convert.hs:62-66: private offsetSyncToInt has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Consumer/Convert.hs",+ "source_sha256": "9bf267580d3ee008308585ee061e9364a1dbc6556090d78b5e5df0ef767b9115"+ },+ "Kafka.Consumer.Convert:138:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Consumer/Convert.hs:138-150: private toNativeTopicPartitionListNoDispose has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Consumer/Convert.hs",+ "source_sha256": "9bf267580d3ee008308585ee061e9364a1dbc6556090d78b5e5df0ef767b9115"+ },+ "Kafka.Consumer.Convert:143:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Consumer/Convert.hs:138-150: private toNativeTopicPartitionListNoDispose has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Consumer/Convert.hs",+ "source_sha256": "9bf267580d3ee008308585ee061e9364a1dbc6556090d78b5e5df0ef767b9115"+ },+ "Kafka.Consumer.Convert:143:LocalBox [\"toNativeTopicPartitionListNoDispose\",\"to\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Consumer/Convert.hs:138-150: private toNativeTopicPartitionListNoDispose has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Consumer/Convert.hs",+ "source_sha256": "9bf267580d3ee008308585ee061e9364a1dbc6556090d78b5e5df0ef767b9115"+ },+ "Kafka.Consumer.Convert:142:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Consumer/Convert.hs:138-150: private toNativeTopicPartitionListNoDispose has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Consumer/Convert.hs",+ "source_sha256": "9bf267580d3ee008308585ee061e9364a1dbc6556090d78b5e5df0ef767b9115"+ },+ "Kafka.Consumer.Convert:141:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Consumer/Convert.hs:138-150: private toNativeTopicPartitionListNoDispose has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Consumer/Convert.hs",+ "source_sha256": "9bf267580d3ee008308585ee061e9364a1dbc6556090d78b5e5df0ef767b9115"+ },+ "Kafka.Consumer.Convert:144:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Consumer/Convert.hs:138-150: private toNativeTopicPartitionListNoDispose has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Consumer/Convert.hs",+ "source_sha256": "9bf267580d3ee008308585ee061e9364a1dbc6556090d78b5e5df0ef767b9115"+ },+ "Kafka.Consumer.Convert:144:LocalBox [\"toNativeTopicPartitionListNoDispose\",\"tnS\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Consumer/Convert.hs:138-150: private toNativeTopicPartitionListNoDispose has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Consumer/Convert.hs",+ "source_sha256": "9bf267580d3ee008308585ee061e9364a1dbc6556090d78b5e5df0ef767b9115"+ },+ "Kafka.Consumer.Convert:145:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Consumer/Convert.hs:138-150: private toNativeTopicPartitionListNoDispose has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Consumer/Convert.hs",+ "source_sha256": "9bf267580d3ee008308585ee061e9364a1dbc6556090d78b5e5df0ef767b9115"+ },+ "Kafka.Consumer.Convert:146:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Consumer/Convert.hs:138-150: private toNativeTopicPartitionListNoDispose has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Consumer/Convert.hs",+ "source_sha256": "9bf267580d3ee008308585ee061e9364a1dbc6556090d78b5e5df0ef767b9115"+ },+ "Kafka.Consumer.Convert:140:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Consumer/Convert.hs:138-150: private toNativeTopicPartitionListNoDispose has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Consumer/Convert.hs",+ "source_sha256": "9bf267580d3ee008308585ee061e9364a1dbc6556090d78b5e5df0ef767b9115"+ },+ "Kafka.Consumer.Convert:148:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Consumer/Convert.hs:138-150: private toNativeTopicPartitionListNoDispose has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Consumer/Convert.hs",+ "source_sha256": "9bf267580d3ee008308585ee061e9364a1dbc6556090d78b5e5df0ef767b9115"+ },+ "Kafka.Consumer.Convert:139:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Consumer/Convert.hs:138-150: private toNativeTopicPartitionListNoDispose has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Consumer/Convert.hs",+ "source_sha256": "9bf267580d3ee008308585ee061e9364a1dbc6556090d78b5e5df0ef767b9115"+ },+ "Kafka.Consumer.Convert:149:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Consumer/Convert.hs:138-150: private toNativeTopicPartitionListNoDispose has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Consumer/Convert.hs",+ "source_sha256": "9bf267580d3ee008308585ee061e9364a1dbc6556090d78b5e5df0ef767b9115"+ },+ "Kafka.Consumer.Convert:137:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Consumer/Convert.hs:138-150: private toNativeTopicPartitionListNoDispose has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Consumer/Convert.hs",+ "source_sha256": "9bf267580d3ee008308585ee061e9364a1dbc6556090d78b5e5df0ef767b9115"+ },+ "Kafka.Consumer.Convert:137:TopLevelBox [\"toNativeTopicPartitionListNoDispose\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Consumer/Convert.hs:138-150: private toNativeTopicPartitionListNoDispose has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Consumer/Convert.hs",+ "source_sha256": "9bf267580d3ee008308585ee061e9364a1dbc6556090d78b5e5df0ef767b9115"+ },+ "Kafka.Internal.Shared:73:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Internal/Shared.hs:64-68: private throwOnError has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Internal/Shared.hs",+ "source_sha256": "fb9eb7755af2a3da0db73b665a0e09a7c6ee3b1381aaac9e658a78f1ebd7e100"+ },+ "Kafka.Internal.Shared:74:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Internal/Shared.hs:64-68: private throwOnError has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Internal/Shared.hs",+ "source_sha256": "fb9eb7755af2a3da0db73b665a0e09a7c6ee3b1381aaac9e658a78f1ebd7e100"+ },+ "Kafka.Internal.Shared:75:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Internal/Shared.hs:64-68: private throwOnError has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Internal/Shared.hs",+ "source_sha256": "fb9eb7755af2a3da0db73b665a0e09a7c6ee3b1381aaac9e658a78f1ebd7e100"+ },+ "Kafka.Internal.Shared:75:ExpBox True": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Internal/Shared.hs:64-68: private throwOnError has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Internal/Shared.hs",+ "source_sha256": "fb9eb7755af2a3da0db73b665a0e09a7c6ee3b1381aaac9e658a78f1ebd7e100"+ },+ "Kafka.Internal.Shared:76:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Internal/Shared.hs:64-68: private throwOnError has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Internal/Shared.hs",+ "source_sha256": "fb9eb7755af2a3da0db73b665a0e09a7c6ee3b1381aaac9e658a78f1ebd7e100"+ },+ "Kafka.Internal.Shared:76:ExpBox True": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Internal/Shared.hs:64-68: private throwOnError has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Internal/Shared.hs",+ "source_sha256": "fb9eb7755af2a3da0db73b665a0e09a7c6ee3b1381aaac9e658a78f1ebd7e100"+ },+ "Kafka.Internal.Shared:72:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Internal/Shared.hs:64-68: private throwOnError has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Internal/Shared.hs",+ "source_sha256": "fb9eb7755af2a3da0db73b665a0e09a7c6ee3b1381aaac9e658a78f1ebd7e100"+ },+ "Kafka.Internal.Shared:72:TopLevelBox [\"throwOnError\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Internal/Shared.hs:64-68: private throwOnError has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Internal/Shared.hs",+ "source_sha256": "fb9eb7755af2a3da0db73b665a0e09a7c6ee3b1381aaac9e658a78f1ebd7e100"+ },+ "Kafka.Internal.Shared:79:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Internal/Shared.hs:71-73: private hasError has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Internal/Shared.hs",+ "source_sha256": "fb9eb7755af2a3da0db73b665a0e09a7c6ee3b1381aaac9e658a78f1ebd7e100"+ },+ "Kafka.Internal.Shared:80:ExpBox True": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Internal/Shared.hs:71-73: private hasError has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Internal/Shared.hs",+ "source_sha256": "fb9eb7755af2a3da0db73b665a0e09a7c6ee3b1381aaac9e658a78f1ebd7e100"+ },+ "Kafka.Internal.Shared:81:ExpBox True": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Internal/Shared.hs:71-73: private hasError has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Internal/Shared.hs",+ "source_sha256": "fb9eb7755af2a3da0db73b665a0e09a7c6ee3b1381aaac9e658a78f1ebd7e100"+ },+ "Kafka.Internal.Shared:79:TopLevelBox [\"hasError\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Internal/Shared.hs:71-73: private hasError has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Internal/Shared.hs",+ "source_sha256": "fb9eb7755af2a3da0db73b665a0e09a7c6ee3b1381aaac9e658a78f1ebd7e100"+ },+ "Kafka.Internal.Shared:91:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Internal/Shared.hs:83-85: private kafkaErrorToEither has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Internal/Shared.hs",+ "source_sha256": "fb9eb7755af2a3da0db73b665a0e09a7c6ee3b1381aaac9e658a78f1ebd7e100"+ },+ "Kafka.Internal.Shared:92:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Internal/Shared.hs:83-85: private kafkaErrorToEither has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Internal/Shared.hs",+ "source_sha256": "fb9eb7755af2a3da0db73b665a0e09a7c6ee3b1381aaac9e658a78f1ebd7e100"+ },+ "Kafka.Internal.Shared:92:ExpBox True": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Internal/Shared.hs:83-85: private kafkaErrorToEither has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Internal/Shared.hs",+ "source_sha256": "fb9eb7755af2a3da0db73b665a0e09a7c6ee3b1381aaac9e658a78f1ebd7e100"+ },+ "Kafka.Internal.Shared:93:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Internal/Shared.hs:83-85: private kafkaErrorToEither has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Internal/Shared.hs",+ "source_sha256": "fb9eb7755af2a3da0db73b665a0e09a7c6ee3b1381aaac9e658a78f1ebd7e100"+ },+ "Kafka.Internal.Shared:93:ExpBox True": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Internal/Shared.hs:83-85: private kafkaErrorToEither has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Internal/Shared.hs",+ "source_sha256": "fb9eb7755af2a3da0db73b665a0e09a7c6ee3b1381aaac9e658a78f1ebd7e100"+ },+ "Kafka.Internal.Shared:91:TopLevelBox [\"kafkaErrorToEither\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Internal/Shared.hs:83-85: private kafkaErrorToEither has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Internal/Shared.hs",+ "source_sha256": "fb9eb7755af2a3da0db73b665a0e09a7c6ee3b1381aaac9e658a78f1ebd7e100"+ },+ "Kafka.Producer.Convert:32:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Producer/Convert.hs:32-34: private handleProduceErr has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Producer/Convert.hs",+ "source_sha256": "9ba868c4ea7d938ab857f2e92f1a033a633b8f7b834da58502d6fb9831f99483"+ },+ "Kafka.Producer.Convert:32:ExpBox True": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Producer/Convert.hs:32-34: private handleProduceErr has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Producer/Convert.hs",+ "source_sha256": "9ba868c4ea7d938ab857f2e92f1a033a633b8f7b834da58502d6fb9831f99483"+ },+ "Kafka.Producer.Convert:33:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Producer/Convert.hs:32-34: private handleProduceErr has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Producer/Convert.hs",+ "source_sha256": "9ba868c4ea7d938ab857f2e92f1a033a633b8f7b834da58502d6fb9831f99483"+ },+ "Kafka.Producer.Convert:33:ExpBox True": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Producer/Convert.hs:32-34: private handleProduceErr has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Producer/Convert.hs",+ "source_sha256": "9ba868c4ea7d938ab857f2e92f1a033a633b8f7b834da58502d6fb9831f99483"+ },+ "Kafka.Producer.Convert:34:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Producer/Convert.hs:32-34: private handleProduceErr has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Producer/Convert.hs",+ "source_sha256": "9ba868c4ea7d938ab857f2e92f1a033a633b8f7b834da58502d6fb9831f99483"+ },+ "Kafka.Producer.Convert:34:ExpBox True": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Producer/Convert.hs:32-34: private handleProduceErr has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Producer/Convert.hs",+ "source_sha256": "9ba868c4ea7d938ab857f2e92f1a033a633b8f7b834da58502d6fb9831f99483"+ },+ "Kafka.Producer.Convert:32:TopLevelBox [\"handleProduceErr\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Producer/Convert.hs:32-34: private handleProduceErr has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Producer/Convert.hs",+ "source_sha256": "9ba868c4ea7d938ab857f2e92f1a033a633b8f7b834da58502d6fb9831f99483"+ },+ "Kafka.Producer.Convert:43:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Producer/Convert.hs:43-45: private handleProduceErr' has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Producer/Convert.hs",+ "source_sha256": "9ba868c4ea7d938ab857f2e92f1a033a633b8f7b834da58502d6fb9831f99483"+ },+ "Kafka.Producer.Convert:43:ExpBox True": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Producer/Convert.hs:43-45: private handleProduceErr' has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Producer/Convert.hs",+ "source_sha256": "9ba868c4ea7d938ab857f2e92f1a033a633b8f7b834da58502d6fb9831f99483"+ },+ "Kafka.Producer.Convert:44:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Producer/Convert.hs:43-45: private handleProduceErr' has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Producer/Convert.hs",+ "source_sha256": "9ba868c4ea7d938ab857f2e92f1a033a633b8f7b834da58502d6fb9831f99483"+ },+ "Kafka.Producer.Convert:44:ExpBox True": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Producer/Convert.hs:43-45: private handleProduceErr' has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Producer/Convert.hs",+ "source_sha256": "9ba868c4ea7d938ab857f2e92f1a033a633b8f7b834da58502d6fb9831f99483"+ },+ "Kafka.Producer.Convert:45:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Producer/Convert.hs:43-45: private handleProduceErr' has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Producer/Convert.hs",+ "source_sha256": "9ba868c4ea7d938ab857f2e92f1a033a633b8f7b834da58502d6fb9831f99483"+ },+ "Kafka.Producer.Convert:45:ExpBox True": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Producer/Convert.hs:43-45: private handleProduceErr' has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Producer/Convert.hs",+ "source_sha256": "9ba868c4ea7d938ab857f2e92f1a033a633b8f7b834da58502d6fb9831f99483"+ },+ "Kafka.Producer.Convert:43:TopLevelBox [\"handleProduceErr'\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Producer/Convert.hs:43-45: private handleProduceErr' has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Producer/Convert.hs",+ "source_sha256": "9ba868c4ea7d938ab857f2e92f1a033a633b8f7b834da58502d6fb9831f99483"+ },+ "Kafka.Internal.RdKafka:110:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Internal/RdKafka.chs:110-110: private peekCAText has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:110:TopLevelBox [\"peekCAText\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Internal/RdKafka.chs:110-110: private peekCAText has no src callers; exact-name searches find only its definition, signature, export/INLINE entries. The module is hidden under Cabal other-modules, and this function is not re-exported. No supported public path invokes this body. Reachable replacement helpers and native error paths remain measured.",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Consumer.Types:206:TopLevelBox [\"bifold\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Consumer/Types.hs:206: this coordinate is the instance header. The handwritten method is bifoldMap, whose separate body remains measured. The named missing method is a GHC-generated forwarding/default method from the class dictionary; no handwritten implementation of it occurs at this header. Generic class defaults are not package-specific branches.",+ "source": "src/Kafka/Consumer/Types.hs",+ "source_sha256": "e815e1744538de8e2bea589d138a887b2e4e254be89d0f0103dd7cdcc75ae7a9"+ },+ "Kafka.Consumer.Types:206:TopLevelBox [\"bifoldr\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Consumer/Types.hs:206: this coordinate is the instance header. The handwritten method is bifoldMap, whose separate body remains measured. The named missing method is a GHC-generated forwarding/default method from the class dictionary; no handwritten implementation of it occurs at this header. Generic class defaults are not package-specific branches.",+ "source": "src/Kafka/Consumer/Types.hs",+ "source_sha256": "e815e1744538de8e2bea589d138a887b2e4e254be89d0f0103dd7cdcc75ae7a9"+ },+ "Kafka.Consumer.Types:206:TopLevelBox [\"bifoldl\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Consumer/Types.hs:206: this coordinate is the instance header. The handwritten method is bifoldMap, whose separate body remains measured. The named missing method is a GHC-generated forwarding/default method from the class dictionary; no handwritten implementation of it occurs at this header. Generic class defaults are not package-specific branches.",+ "source": "src/Kafka/Consumer/Types.hs",+ "source_sha256": "e815e1744538de8e2bea589d138a887b2e4e254be89d0f0103dd7cdcc75ae7a9"+ },+ "Kafka.Consumer.Types:202:TopLevelBox [\"mapM\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Consumer/Types.hs:202: this coordinate is the instance header. The handwritten method is traverse, whose separate body remains measured. The named missing method is a GHC-generated forwarding/default method from the class dictionary; no handwritten implementation of it occurs at this header. Generic class defaults are not package-specific branches.",+ "source": "src/Kafka/Consumer/Types.hs",+ "source_sha256": "e815e1744538de8e2bea589d138a887b2e4e254be89d0f0103dd7cdcc75ae7a9"+ },+ "Kafka.Consumer.Types:198:TopLevelBox [\"fold\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Consumer/Types.hs:198: this coordinate is the instance header. The handwritten method is foldMap, whose separate body remains measured. The named missing method is a GHC-generated forwarding/default method from the class dictionary; no handwritten implementation of it occurs at this header. Generic class defaults are not package-specific branches.",+ "source": "src/Kafka/Consumer/Types.hs",+ "source_sha256": "e815e1744538de8e2bea589d138a887b2e4e254be89d0f0103dd7cdcc75ae7a9"+ },+ "Kafka.Consumer.Types:198:TopLevelBox [\"foldMap'\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Consumer/Types.hs:198: this coordinate is the instance header. The handwritten method is foldMap, whose separate body remains measured. The named missing method is a GHC-generated forwarding/default method from the class dictionary; no handwritten implementation of it occurs at this header. Generic class defaults are not package-specific branches.",+ "source": "src/Kafka/Consumer/Types.hs",+ "source_sha256": "e815e1744538de8e2bea589d138a887b2e4e254be89d0f0103dd7cdcc75ae7a9"+ },+ "Kafka.Consumer.Types:198:TopLevelBox [\"foldr\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Consumer/Types.hs:198: this coordinate is the instance header. The handwritten method is foldMap, whose separate body remains measured. The named missing method is a GHC-generated forwarding/default method from the class dictionary; no handwritten implementation of it occurs at this header. Generic class defaults are not package-specific branches.",+ "source": "src/Kafka/Consumer/Types.hs",+ "source_sha256": "e815e1744538de8e2bea589d138a887b2e4e254be89d0f0103dd7cdcc75ae7a9"+ },+ "Kafka.Consumer.Types:198:TopLevelBox [\"foldr'\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Consumer/Types.hs:198: this coordinate is the instance header. The handwritten method is foldMap, whose separate body remains measured. The named missing method is a GHC-generated forwarding/default method from the class dictionary; no handwritten implementation of it occurs at this header. Generic class defaults are not package-specific branches.",+ "source": "src/Kafka/Consumer/Types.hs",+ "source_sha256": "e815e1744538de8e2bea589d138a887b2e4e254be89d0f0103dd7cdcc75ae7a9"+ },+ "Kafka.Consumer.Types:198:TopLevelBox [\"foldl\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Consumer/Types.hs:198: this coordinate is the instance header. The handwritten method is foldMap, whose separate body remains measured. The named missing method is a GHC-generated forwarding/default method from the class dictionary; no handwritten implementation of it occurs at this header. Generic class defaults are not package-specific branches.",+ "source": "src/Kafka/Consumer/Types.hs",+ "source_sha256": "e815e1744538de8e2bea589d138a887b2e4e254be89d0f0103dd7cdcc75ae7a9"+ },+ "Kafka.Consumer.Types:198:TopLevelBox [\"foldl'\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Consumer/Types.hs:198: this coordinate is the instance header. The handwritten method is foldMap, whose separate body remains measured. The named missing method is a GHC-generated forwarding/default method from the class dictionary; no handwritten implementation of it occurs at this header. Generic class defaults are not package-specific branches.",+ "source": "src/Kafka/Consumer/Types.hs",+ "source_sha256": "e815e1744538de8e2bea589d138a887b2e4e254be89d0f0103dd7cdcc75ae7a9"+ },+ "Kafka.Consumer.Types:198:TopLevelBox [\"foldr1\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Consumer/Types.hs:198: this coordinate is the instance header. The handwritten method is foldMap, whose separate body remains measured. The named missing method is a GHC-generated forwarding/default method from the class dictionary; no handwritten implementation of it occurs at this header. Generic class defaults are not package-specific branches.",+ "source": "src/Kafka/Consumer/Types.hs",+ "source_sha256": "e815e1744538de8e2bea589d138a887b2e4e254be89d0f0103dd7cdcc75ae7a9"+ },+ "Kafka.Consumer.Types:198:TopLevelBox [\"foldl1\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Consumer/Types.hs:198: this coordinate is the instance header. The handwritten method is foldMap, whose separate body remains measured. The named missing method is a GHC-generated forwarding/default method from the class dictionary; no handwritten implementation of it occurs at this header. Generic class defaults are not package-specific branches.",+ "source": "src/Kafka/Consumer/Types.hs",+ "source_sha256": "e815e1744538de8e2bea589d138a887b2e4e254be89d0f0103dd7cdcc75ae7a9"+ },+ "Kafka.Consumer.Types:198:TopLevelBox [\"toList\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Consumer/Types.hs:198: this coordinate is the instance header. The handwritten method is foldMap, whose separate body remains measured. The named missing method is a GHC-generated forwarding/default method from the class dictionary; no handwritten implementation of it occurs at this header. Generic class defaults are not package-specific branches.",+ "source": "src/Kafka/Consumer/Types.hs",+ "source_sha256": "e815e1744538de8e2bea589d138a887b2e4e254be89d0f0103dd7cdcc75ae7a9"+ },+ "Kafka.Consumer.Types:198:TopLevelBox [\"null\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Consumer/Types.hs:198: this coordinate is the instance header. The handwritten method is foldMap, whose separate body remains measured. The named missing method is a GHC-generated forwarding/default method from the class dictionary; no handwritten implementation of it occurs at this header. Generic class defaults are not package-specific branches.",+ "source": "src/Kafka/Consumer/Types.hs",+ "source_sha256": "e815e1744538de8e2bea589d138a887b2e4e254be89d0f0103dd7cdcc75ae7a9"+ },+ "Kafka.Consumer.Types:198:TopLevelBox [\"length\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Consumer/Types.hs:198: this coordinate is the instance header. The handwritten method is foldMap, whose separate body remains measured. The named missing method is a GHC-generated forwarding/default method from the class dictionary; no handwritten implementation of it occurs at this header. Generic class defaults are not package-specific branches.",+ "source": "src/Kafka/Consumer/Types.hs",+ "source_sha256": "e815e1744538de8e2bea589d138a887b2e4e254be89d0f0103dd7cdcc75ae7a9"+ },+ "Kafka.Consumer.Types:198:TopLevelBox [\"elem\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Consumer/Types.hs:198: this coordinate is the instance header. The handwritten method is foldMap, whose separate body remains measured. The named missing method is a GHC-generated forwarding/default method from the class dictionary; no handwritten implementation of it occurs at this header. Generic class defaults are not package-specific branches.",+ "source": "src/Kafka/Consumer/Types.hs",+ "source_sha256": "e815e1744538de8e2bea589d138a887b2e4e254be89d0f0103dd7cdcc75ae7a9"+ },+ "Kafka.Consumer.Types:198:TopLevelBox [\"maximum\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Consumer/Types.hs:198: this coordinate is the instance header. The handwritten method is foldMap, whose separate body remains measured. The named missing method is a GHC-generated forwarding/default method from the class dictionary; no handwritten implementation of it occurs at this header. Generic class defaults are not package-specific branches.",+ "source": "src/Kafka/Consumer/Types.hs",+ "source_sha256": "e815e1744538de8e2bea589d138a887b2e4e254be89d0f0103dd7cdcc75ae7a9"+ },+ "Kafka.Consumer.Types:198:TopLevelBox [\"minimum\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Consumer/Types.hs:198: this coordinate is the instance header. The handwritten method is foldMap, whose separate body remains measured. The named missing method is a GHC-generated forwarding/default method from the class dictionary; no handwritten implementation of it occurs at this header. Generic class defaults are not package-specific branches.",+ "source": "src/Kafka/Consumer/Types.hs",+ "source_sha256": "e815e1744538de8e2bea589d138a887b2e4e254be89d0f0103dd7cdcc75ae7a9"+ },+ "Kafka.Consumer.Types:198:TopLevelBox [\"sum\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Consumer/Types.hs:198: this coordinate is the instance header. The handwritten method is foldMap, whose separate body remains measured. The named missing method is a GHC-generated forwarding/default method from the class dictionary; no handwritten implementation of it occurs at this header. Generic class defaults are not package-specific branches.",+ "source": "src/Kafka/Consumer/Types.hs",+ "source_sha256": "e815e1744538de8e2bea589d138a887b2e4e254be89d0f0103dd7cdcc75ae7a9"+ },+ "Kafka.Consumer.Types:198:TopLevelBox [\"product\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Consumer/Types.hs:198: this coordinate is the instance header. The handwritten method is foldMap, whose separate body remains measured. The named missing method is a GHC-generated forwarding/default method from the class dictionary; no handwritten implementation of it occurs at this header. Generic class defaults are not package-specific branches.",+ "source": "src/Kafka/Consumer/Types.hs",+ "source_sha256": "e815e1744538de8e2bea589d138a887b2e4e254be89d0f0103dd7cdcc75ae7a9"+ },+ "Kafka.Consumer.Types:194:TopLevelBox [\"<$\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Consumer/Types.hs:194: this coordinate is the instance header. The handwritten method is fmap, whose separate body remains measured. The named missing method is a GHC-generated forwarding/default method from the class dictionary; no handwritten implementation of it occurs at this header. Generic class defaults are not package-specific branches.",+ "source": "src/Kafka/Consumer/Types.hs",+ "source_sha256": "e815e1744538de8e2bea589d138a887b2e4e254be89d0f0103dd7cdcc75ae7a9"+ },+ "Kafka.Internal.RdKafka:779:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Internal/RdKafka.chs:779: { broker'RdKafkaGroupInfoT :: RdKafkaMetadataBrokerTPtr is a data-record field declaration. GHC generates the broker'RdKafkaGroupInfoT selector body; there is no handwritten control flow at this coordinate. Public representation and native decoding obligations remain covered independently, rather than treating this compiler projection as an untested native branch.",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:779:TopLevelBox [\"broker'RdKafkaGroupInfoT\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Internal/RdKafka.chs:779: { broker'RdKafkaGroupInfoT :: RdKafkaMetadataBrokerTPtr is a data-record field declaration. GHC generates the broker'RdKafkaGroupInfoT selector body; there is no handwritten control flow at this coordinate. Public representation and native decoding obligations remain covered independently, rather than treating this compiler projection as an untested native branch.",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:165:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Internal/RdKafka.chs:165: , size'RdKafkaTopicPartitionListT :: Int is a data-record field declaration. GHC generates the size'RdKafkaTopicPartitionListT selector body; there is no handwritten control flow at this coordinate. Public representation and native decoding obligations remain covered independently, rather than treating this compiler projection as an untested native branch.",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:165:TopLevelBox [\"size'RdKafkaTopicPartitionListT\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Internal/RdKafka.chs:165: , size'RdKafkaTopicPartitionListT :: Int is a data-record field declaration. GHC generates the size'RdKafkaTopicPartitionListT selector body; there is no handwritten control flow at this coordinate. Public representation and native decoding obligations remain covered independently, rather than treating this compiler projection as an untested native branch.",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:134:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Internal/RdKafka.chs:134: , metadata'RdKafkaTopicPartitionT :: Word8Ptr is a data-record field declaration. GHC generates the metadata'RdKafkaTopicPartitionT selector body; there is no handwritten control flow at this coordinate. Public representation and native decoding obligations remain covered independently, rather than treating this compiler projection as an untested native branch.",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:134:TopLevelBox [\"metadata'RdKafkaTopicPartitionT\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Internal/RdKafka.chs:134: , metadata'RdKafkaTopicPartitionT :: Word8Ptr is a data-record field declaration. GHC generates the metadata'RdKafkaTopicPartitionT selector body; there is no handwritten control flow at this coordinate. Public representation and native decoding obligations remain covered independently, rather than treating this compiler projection as an untested native branch.",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:135:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Internal/RdKafka.chs:135: , metadataSize'RdKafkaTopicPartitionT :: Int is a data-record field declaration. GHC generates the metadataSize'RdKafkaTopicPartitionT selector body; there is no handwritten control flow at this coordinate. Public representation and native decoding obligations remain covered independently, rather than treating this compiler projection as an untested native branch.",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:135:TopLevelBox [\"metadataSize'RdKafkaTopicPartitionT\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Internal/RdKafka.chs:135: , metadataSize'RdKafkaTopicPartitionT :: Int is a data-record field declaration. GHC generates the metadataSize'RdKafkaTopicPartitionT selector body; there is no handwritten control flow at this coordinate. Public representation and native decoding obligations remain covered independently, rather than treating this compiler projection as an untested native branch.",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:136:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Internal/RdKafka.chs:136: , opaque'RdKafkaTopicPartitionT :: Word8Ptr is a data-record field declaration. GHC generates the opaque'RdKafkaTopicPartitionT selector body; there is no handwritten control flow at this coordinate. Public representation and native decoding obligations remain covered independently, rather than treating this compiler projection as an untested native branch.",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:136:TopLevelBox [\"opaque'RdKafkaTopicPartitionT\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Internal/RdKafka.chs:136: , opaque'RdKafkaTopicPartitionT :: Word8Ptr is a data-record field declaration. GHC generates the opaque'RdKafkaTopicPartitionT selector body; there is no handwritten control flow at this coordinate. Public representation and native decoding obligations remain covered independently, rather than treating this compiler projection as an untested native branch.",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.Setup:90:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Internal/Setup.hs:90: kcfgKafkaConfPtr :: RdKafkaConfTPtr, is a data-record field declaration. GHC generates the kcfgKafkaConfPtr selector body; there is no handwritten control flow at this coordinate. Public representation and native decoding obligations remain covered independently, rather than treating this compiler projection as an untested native branch.",+ "source": "src/Kafka/Internal/Setup.hs",+ "source_sha256": "69ef4227adf311f7dee3ec283825d42c1e3a2561df6f66bab29d2abb8b446188"+ },+ "Kafka.Internal.Setup:90:TopLevelBox [\"kcfgKafkaConfPtr\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Internal/Setup.hs:90: kcfgKafkaConfPtr :: RdKafkaConfTPtr, is a data-record field declaration. GHC generates the kcfgKafkaConfPtr selector body; there is no handwritten control flow at this coordinate. Public representation and native decoding obligations remain covered independently, rather than treating this compiler projection as an untested native branch.",+ "source": "src/Kafka/Internal/Setup.hs",+ "source_sha256": "69ef4227adf311f7dee3ec283825d42c1e3a2561df6f66bab29d2abb8b446188"+ },+ "Kafka.Internal.Setup:92:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Internal/Setup.hs:92: kcfgMessagesQueue :: IORef (Maybe RdKafkaQueueTPtr), is a data-record field declaration. GHC generates the kcfgMessagesQueue selector body; there is no handwritten control flow at this coordinate. Public representation and native decoding obligations remain covered independently, rather than treating this compiler projection as an untested native branch.",+ "source": "src/Kafka/Internal/Setup.hs",+ "source_sha256": "69ef4227adf311f7dee3ec283825d42c1e3a2561df6f66bab29d2abb8b446188"+ },+ "Kafka.Internal.Setup:92:TopLevelBox [\"kcfgMessagesQueue\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Internal/Setup.hs:92: kcfgMessagesQueue :: IORef (Maybe RdKafkaQueueTPtr), is a data-record field declaration. GHC generates the kcfgMessagesQueue selector body; there is no handwritten control flow at this coordinate. Public representation and native decoding obligations remain covered independently, rather than treating this compiler projection as an untested native branch.",+ "source": "src/Kafka/Internal/Setup.hs",+ "source_sha256": "69ef4227adf311f7dee3ec283825d42c1e3a2561df6f66bab29d2abb8b446188"+ },+ "Kafka.Internal.Setup:97:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Internal/Setup.hs:97: kcfgLifecycle :: MVar ClientLifecycle, is a data-record field declaration. GHC generates the kcfgLifecycle selector body; there is no handwritten control flow at this coordinate. Public representation and native decoding obligations remain covered independently, rather than treating this compiler projection as an untested native branch.",+ "source": "src/Kafka/Internal/Setup.hs",+ "source_sha256": "69ef4227adf311f7dee3ec283825d42c1e3a2561df6f66bab29d2abb8b446188"+ },+ "Kafka.Internal.Setup:97:TopLevelBox [\"kcfgLifecycle\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Internal/Setup.hs:97: kcfgLifecycle :: MVar ClientLifecycle, is a data-record field declaration. GHC generates the kcfgLifecycle selector body; there is no handwritten control flow at this coordinate. Public representation and native decoding obligations remain covered independently, rather than treating this compiler projection as an untested native branch.",+ "source": "src/Kafka/Internal/Setup.hs",+ "source_sha256": "69ef4227adf311f7dee3ec283825d42c1e3a2561df6f66bab29d2abb8b446188"+ },+ "Kafka.Metadata:85:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Metadata.hs:85: { woTopicName :: !TopicName, is a data-record field declaration. GHC generates the woTopicName selector body; there is no handwritten control flow at this coordinate. Public representation and native decoding obligations remain covered independently, rather than treating this compiler projection as an untested native branch.",+ "source": "src/Kafka/Metadata.hs",+ "source_sha256": "abcfd0962c104901916c4b4a456b4e99b9905ffd430b74b4e2244e5a2744512f"+ },+ "Kafka.Metadata:85:TopLevelBox [\"woTopicName\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Metadata.hs:85: { woTopicName :: !TopicName, is a data-record field declaration. GHC generates the woTopicName selector body; there is no handwritten control flow at this coordinate. Public representation and native decoding obligations remain covered independently, rather than treating this compiler projection as an untested native branch.",+ "source": "src/Kafka/Metadata.hs",+ "source_sha256": "abcfd0962c104901916c4b4a456b4e99b9905ffd430b74b4e2244e5a2744512f"+ },+ "Kafka.Metadata:86:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Metadata.hs:86: woPartitionId :: !PartitionId, is a data-record field declaration. GHC generates the woPartitionId selector body; there is no handwritten control flow at this coordinate. Public representation and native decoding obligations remain covered independently, rather than treating this compiler projection as an untested native branch.",+ "source": "src/Kafka/Metadata.hs",+ "source_sha256": "abcfd0962c104901916c4b4a456b4e99b9905ffd430b74b4e2244e5a2744512f"+ },+ "Kafka.Metadata:86:TopLevelBox [\"woPartitionId\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Metadata.hs:86: woPartitionId :: !PartitionId, is a data-record field declaration. GHC generates the woPartitionId selector body; there is no handwritten control flow at this coordinate. Public representation and native decoding obligations remain covered independently, rather than treating this compiler projection as an untested native branch.",+ "source": "src/Kafka/Metadata.hs",+ "source_sha256": "abcfd0962c104901916c4b4a456b4e99b9905ffd430b74b4e2244e5a2744512f"+ },+ "Kafka.Metadata:87:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Metadata.hs:87: woLowWatermark :: !Offset, is a data-record field declaration. GHC generates the woLowWatermark selector body; there is no handwritten control flow at this coordinate. Public representation and native decoding obligations remain covered independently, rather than treating this compiler projection as an untested native branch.",+ "source": "src/Kafka/Metadata.hs",+ "source_sha256": "abcfd0962c104901916c4b4a456b4e99b9905ffd430b74b4e2244e5a2744512f"+ },+ "Kafka.Metadata:87:TopLevelBox [\"woLowWatermark\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Metadata.hs:87: woLowWatermark :: !Offset, is a data-record field declaration. GHC generates the woLowWatermark selector body; there is no handwritten control flow at this coordinate. Public representation and native decoding obligations remain covered independently, rather than treating this compiler projection as an untested native branch.",+ "source": "src/Kafka/Metadata.hs",+ "source_sha256": "abcfd0962c104901916c4b4a456b4e99b9905ffd430b74b4e2244e5a2744512f"+ },+ "Kafka.Version:22:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Version.hs:22: { versionMajor :: Int, is a data-record field declaration. GHC generates the versionMajor selector body; there is no handwritten control flow at this coordinate. Public representation and native decoding obligations remain covered independently, rather than treating this compiler projection as an untested native branch.",+ "source": "src/Kafka/Version.hs",+ "source_sha256": "1731e25b9b2afade15f0018291d033d7b4527c6538b4153a337736d3ef3b07e5"+ },+ "Kafka.Version:22:TopLevelBox [\"versionMajor\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Version.hs:22: { versionMajor :: Int, is a data-record field declaration. GHC generates the versionMajor selector body; there is no handwritten control flow at this coordinate. Public representation and native decoding obligations remain covered independently, rather than treating this compiler projection as an untested native branch.",+ "source": "src/Kafka/Version.hs",+ "source_sha256": "1731e25b9b2afade15f0018291d033d7b4527c6538b4153a337736d3ef3b07e5"+ },+ "Kafka.Version:23:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Version.hs:23: versionMinor :: Int, is a data-record field declaration. GHC generates the versionMinor selector body; there is no handwritten control flow at this coordinate. Public representation and native decoding obligations remain covered independently, rather than treating this compiler projection as an untested native branch.",+ "source": "src/Kafka/Version.hs",+ "source_sha256": "1731e25b9b2afade15f0018291d033d7b4527c6538b4153a337736d3ef3b07e5"+ },+ "Kafka.Version:23:TopLevelBox [\"versionMinor\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Version.hs:23: versionMinor :: Int, is a data-record field declaration. GHC generates the versionMinor selector body; there is no handwritten control flow at this coordinate. Public representation and native decoding obligations remain covered independently, rather than treating this compiler projection as an untested native branch.",+ "source": "src/Kafka/Version.hs",+ "source_sha256": "1731e25b9b2afade15f0018291d033d7b4527c6538b4153a337736d3ef3b07e5"+ },+ "Kafka.Version:24:ExpBox False": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Version.hs:24: versionRevision :: Int is a data-record field declaration. GHC generates the versionRevision selector body; there is no handwritten control flow at this coordinate. Public representation and native decoding obligations remain covered independently, rather than treating this compiler projection as an untested native branch.",+ "source": "src/Kafka/Version.hs",+ "source_sha256": "1731e25b9b2afade15f0018291d033d7b4527c6538b4153a337736d3ef3b07e5"+ },+ "Kafka.Version:24:TopLevelBox [\"versionRevision\"]": {+ "status": "inapplicable",+ "rationale": "src/Kafka/Version.hs:24: versionRevision :: Int is a data-record field declaration. GHC generates the versionRevision selector body; there is no handwritten control flow at this coordinate. Public representation and native decoding obligations remain covered independently, rather than treating this compiler projection as an untested native branch.",+ "source": "src/Kafka/Version.hs",+ "source_sha256": "1731e25b9b2afade15f0018291d033d7b4527c6538b4153a337736d3ef3b07e5"+ },+ "Kafka.Consumer:868:ExpBox False": {+ "status": "inapplicable",+ "rationale": "Only the lazy unit literal returned by pure () is unforced. Sequencing this IO action does not demand its discarded result. No predicate, native call, release action or error conversion on this line is exempted; those effects retain their behavioral and ownership tests.",+ "source": "src/Kafka/Consumer.hs",+ "source_sha256": "170ea8259f8b0279db807c48799f323a268e7636efcbc929ade003cd4e4bb70a",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Consumer:872:ExpBox False": {+ "status": "inapplicable",+ "rationale": "Only the lazy unit literal returned by pure () is unforced. Sequencing this IO action does not demand its discarded result. No predicate, native call, release action or error conversion on this line is exempted; those effects retain their behavioral and ownership tests.",+ "source": "src/Kafka/Consumer.hs",+ "source_sha256": "170ea8259f8b0279db807c48799f323a268e7636efcbc929ade003cd4e4bb70a",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Consumer:829:ExpBox False": {+ "status": "inapplicable",+ "rationale": "Only the lazy unit literal returned by pure () is unforced. Sequencing this IO action does not demand its discarded result. No predicate, native call, release action or error conversion on this line is exempted; those effects retain their behavioral and ownership tests.",+ "source": "src/Kafka/Consumer.hs",+ "source_sha256": "170ea8259f8b0279db807c48799f323a268e7636efcbc929ade003cd4e4bb70a",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Consumer:881:ExpBox False": {+ "status": "inapplicable",+ "rationale": "Only the lazy unit literal returned by pure () is unforced. Sequencing this IO action does not demand its discarded result. No predicate, native call, release action or error conversion on this line is exempted; those effects retain their behavioral and ownership tests.",+ "source": "src/Kafka/Consumer.hs",+ "source_sha256": "170ea8259f8b0279db807c48799f323a268e7636efcbc929ade003cd4e4bb70a",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Consumer:885:ExpBox False": {+ "status": "inapplicable",+ "rationale": "Only the lazy unit literal returned by pure () is unforced. Sequencing this IO action does not demand its discarded result. No predicate, native call, release action or error conversion on this line is exempted; those effects retain their behavioral and ownership tests.",+ "source": "src/Kafka/Consumer.hs",+ "source_sha256": "170ea8259f8b0279db807c48799f323a268e7636efcbc929ade003cd4e4bb70a",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Consumer:526:ExpBox False": {+ "status": "inapplicable",+ "rationale": "Only the lazy unit literal returned by pure () is unforced. Sequencing this IO action does not demand its discarded result. No predicate, native call, release action or error conversion on this line is exempted; those effects retain their behavioral and ownership tests.",+ "source": "src/Kafka/Consumer.hs",+ "source_sha256": "170ea8259f8b0279db807c48799f323a268e7636efcbc929ade003cd4e4bb70a",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Consumer:395:ExpBox False": {+ "status": "inapplicable",+ "rationale": "Only the lazy unit literal returned by pure () is unforced. Sequencing this IO action does not demand its discarded result. No predicate, native call, release action or error conversion on this line is exempted; those effects retain their behavioral and ownership tests.",+ "source": "src/Kafka/Consumer.hs",+ "source_sha256": "170ea8259f8b0279db807c48799f323a268e7636efcbc929ade003cd4e4bb70a",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Consumer:329:ExpBox False": {+ "status": "inapplicable",+ "rationale": "Only the lazy unit literal returned by pure () is unforced. Sequencing this IO action does not demand its discarded result. No predicate, native call, release action or error conversion on this line is exempted; those effects retain their behavioral and ownership tests.",+ "source": "src/Kafka/Consumer.hs",+ "source_sha256": "170ea8259f8b0279db807c48799f323a268e7636efcbc929ade003cd4e4bb70a",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Consumer:322:BinBox GuardBinBox False": {+ "status": "unreachable",+ "rationale": "The final guard is Prelude.otherwise, the constant True. Its false outcome is impossible; preceding guards and this guarded body remain measured independently.",+ "source": "src/Kafka/Consumer.hs",+ "source_sha256": "170ea8259f8b0279db807c48799f323a268e7636efcbc929ade003cd4e4bb70a",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Consumer:163:BinBox GuardBinBox False": {+ "status": "unreachable",+ "rationale": "The final guard is Prelude.otherwise, the constant True. Its false outcome is impossible; preceding guards and this guarded body remain measured independently.",+ "source": "src/Kafka/Consumer.hs",+ "source_sha256": "170ea8259f8b0279db807c48799f323a268e7636efcbc929ade003cd4e4bb70a",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Consumer.Callbacks:100:ExpBox False": {+ "status": "inapplicable",+ "rationale": "Only the lazy unit literal returned by pure () is unforced. Sequencing this IO action does not demand its discarded result. No predicate, native call, release action or error conversion on this line is exempted; those effects retain their behavioral and ownership tests.",+ "source": "src/Kafka/Consumer/Callbacks.hs",+ "source_sha256": "7e993c821435554f7d705ad0369ce4dab3c561216c1966baf29cf967e310e362",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Internal.RdKafka:792:ExpBox False": {+ "status": "inapplicable",+ "rationale": "The lazy mapped conversion of private Storable field broker'RdKafkaGroupInfoT is never selected by any src consumer. Its only other references are the private record declaration and unused poke implementation. The native read still executes; no allocation, owner transfer, error or release is omitted. Cabal hides this binding module; public metadata decoders copy their separately tested fields.",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Internal.RdKafka:177:ExpBox False": {+ "status": "inapplicable",+ "rationale": "The lazy mapped conversion of private Storable field size'RdKafkaTopicPartitionListT is never selected by any src consumer. Its only other references are the private record declaration and unused poke implementation. The native read still executes; no allocation, owner transfer, error or release is omitted. Cabal hides this binding module; public metadata decoders copy their separately tested fields.",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Internal.RdKafka:148:ExpBox False": {+ "status": "inapplicable",+ "rationale": "The lazy mapped conversion of private Storable field metadata'RdKafkaTopicPartitionT is never selected by any src consumer. Its only other references are the private record declaration and unused poke implementation. The native read still executes; no allocation, owner transfer, error or release is omitted. Cabal hides this binding module; public metadata decoders copy their separately tested fields.",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Internal.RdKafka:149:ExpBox False": {+ "status": "inapplicable",+ "rationale": "The lazy mapped conversion of private Storable field metadataSize'RdKafkaTopicPartitionT is never selected by any src consumer. Its only other references are the private record declaration and unused poke implementation. The native read still executes; no allocation, owner transfer, error or release is omitted. Cabal hides this binding module; public metadata decoders copy their separately tested fields.",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Internal.RdKafka:150:ExpBox False": {+ "status": "inapplicable",+ "rationale": "The lazy mapped conversion of private Storable field opaque'RdKafkaTopicPartitionT is never selected by any src consumer. Its only other references are the private record declaration and unused poke implementation. The native read still executes; no allocation, owner transfer, error or release is omitted. Cabal hides this binding module; public metadata decoders copy their separately tested fields.",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Producer:234:ExpBox False": {+ "status": "inapplicable",+ "rationale": "Only the lazy unit literal returned by pure () is unforced. Sequencing this IO action does not demand its discarded result. No predicate, native call, release action or error conversion on this line is exempted; those effects retain their behavioral and ownership tests.",+ "source": "src/Kafka/Producer.hs",+ "source_sha256": "cce48116f5c80ea4c7d3c2af3bc3723e3e19dfd14c3c4a362a166c18201f93fc",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Producer:114:ExpBox False": {+ "status": "inapplicable",+ "rationale": "Only the lazy unit literal returned by pure () is unforced. Sequencing this IO action does not demand its discarded result. No predicate, native call, release action or error conversion on this line is exempted; those effects retain their behavioral and ownership tests.",+ "source": "src/Kafka/Producer.hs",+ "source_sha256": "cce48116f5c80ea4c7d3c2af3bc3723e3e19dfd14c3c4a362a166c18201f93fc",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Topic:147:ExpBox False": {+ "status": "inapplicable",+ "rationale": "Only the lazy unit literal returned by pure () is unforced. Sequencing this IO action does not demand its discarded result. No predicate, native call, release action or error conversion on this line is exempted; those effects retain their behavioral and ownership tests.",+ "source": "src/Kafka/Topic.hs",+ "source_sha256": "932bbd96cc0b28baf18843e4679acc0ea7f09fdefb74a3e4a3a28c9940b6a53c",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Topic:75:BinBox GuardBinBox False": {+ "status": "unreachable",+ "rationale": "The final guard is Prelude.otherwise, the constant True. Its false outcome is impossible; preceding guards and this guarded body remain measured independently.",+ "source": "src/Kafka/Topic.hs",+ "source_sha256": "932bbd96cc0b28baf18843e4679acc0ea7f09fdefb74a3e4a3a28c9940b6a53c",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Topic:86:BinBox GuardBinBox False": {+ "status": "unreachable",+ "rationale": "The final guard is Prelude.otherwise, the constant True. Its false outcome is impossible; preceding guards and this guarded body remain measured independently.",+ "source": "src/Kafka/Topic.hs",+ "source_sha256": "932bbd96cc0b28baf18843e4679acc0ea7f09fdefb74a3e4a3a28c9940b6a53c",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Topic:61:BinBox GuardBinBox False": {+ "status": "unreachable",+ "rationale": "The final guard is Prelude.otherwise, the constant True. Its false outcome is impossible; preceding guards and this guarded body remain measured independently.",+ "source": "src/Kafka/Topic.hs",+ "source_sha256": "932bbd96cc0b28baf18843e4679acc0ea7f09fdefb74a3e4a3a28c9940b6a53c",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Topic:38:BinBox GuardBinBox False": {+ "status": "unreachable",+ "rationale": "The final guard is Prelude.otherwise, the constant True. Its false outcome is impossible; preceding guards and this guarded body remain measured independently.",+ "source": "src/Kafka/Topic.hs",+ "source_sha256": "932bbd96cc0b28baf18843e4679acc0ea7f09fdefb74a3e4a3a28c9940b6a53c",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Consumer:767:BinBox GuardBinBox False": {+ "status": "unreachable",+ "rationale": "Only the false result of the final Prelude.otherwise guard is classified. otherwise is the constant True; other predicates and the guarded expression remain measured independently.",+ "source": "src/Kafka/Consumer.hs",+ "source_sha256": "170ea8259f8b0279db807c48799f323a268e7636efcbc929ade003cd4e4bb70a",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Consumer:139:ExpBox False": {+ "status": "inapplicable",+ "rationale": "These ticks construct the private clConsumer cleanup result, discarded by bracket. runConsumer observes runHandler separately, and its failure/cleanup tests cover both outcomes and native destruction. The IO close action still executes; only its mapped Either result and the cleanup-only error payload are unforced.",+ "source": "src/Kafka/Consumer.hs",+ "source_sha256": "170ea8259f8b0279db807c48799f323a268e7636efcbc929ade003cd4e4bb70a",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Consumer:140:ExpBox False": {+ "status": "inapplicable",+ "rationale": "These ticks construct the private clConsumer cleanup result, discarded by bracket. runConsumer observes runHandler separately, and its failure/cleanup tests cover both outcomes and native destruction. The IO close action still executes; only its mapped Either result and the cleanup-only error payload are unforced.",+ "source": "src/Kafka/Consumer.hs",+ "source_sha256": "170ea8259f8b0279db807c48799f323a268e7636efcbc929ade003cd4e4bb70a",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Consumer.Convert:84:BinBox GuardBinBox False": {+ "status": "unreachable",+ "rationale": "Only the false result of the final Prelude.otherwise guard is classified. otherwise is the constant True; other predicates and the guarded expression remain measured independently.",+ "source": "src/Kafka/Consumer/Convert.hs",+ "source_sha256": "9bf267580d3ee008308585ee061e9364a1dbc6556090d78b5e5df0ef767b9115",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Internal.Setup:228:BinBox GuardBinBox False": {+ "status": "unreachable",+ "rationale": "Only the false result of the final Prelude.otherwise guard is classified. otherwise is the constant True; other predicates and the guarded expression remain measured independently.",+ "source": "src/Kafka/Internal/Setup.hs",+ "source_sha256": "69ef4227adf311f7dee3ec283825d42c1e3a2561df6f66bab29d2abb8b446188",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Internal.Setup:194:ExpBox False": {+ "status": "inapplicable",+ "rationale": "The unforced tick is only the unit literal returned for RdKafkaConfOk. mapM_ sequences configuration effects and discards this result. Configuration success, native constructor settings and setter failure behavior remain tested.",+ "source": "src/Kafka/Internal/Setup.hs",+ "source_sha256": "69ef4227adf311f7dee3ec283825d42c1e3a2561df6f66bab29d2abb8b446188",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Internal.Shared:162:BinBox GuardBinBox False": {+ "status": "unreachable",+ "rationale": "Only the false result of the final Prelude.otherwise guard is classified. otherwise is the constant True; other predicates and the guarded expression remain measured independently.",+ "source": "src/Kafka/Internal/Shared.hs",+ "source_sha256": "fb9eb7755af2a3da0db73b665a0e09a7c6ee3b1381aaac9e658a78f1ebd7e100",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Internal.Shared:174:BinBox GuardBinBox False": {+ "status": "unreachable",+ "rationale": "Only the false result of the final Prelude.otherwise guard is classified. otherwise is the constant True; other predicates and the guarded expression remain measured independently.",+ "source": "src/Kafka/Internal/Shared.hs",+ "source_sha256": "fb9eb7755af2a3da0db73b665a0e09a7c6ee3b1381aaac9e658a78f1ebd7e100",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Producer:292:BinBox GuardBinBox False": {+ "status": "unreachable",+ "rationale": "Only the false result of the final Prelude.otherwise guard is classified. otherwise is the constant True; other predicates and the guarded expression remain measured independently.",+ "source": "src/Kafka/Producer.hs",+ "source_sha256": "cce48116f5c80ea4c7d3c2af3bc3723e3e19dfd14c3c4a362a166c18201f93fc",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Producer:158:ExpBox False": {+ "status": "inapplicable",+ "rationale": "The tick is the mempty unit returned by produceMessage's private no-op per-message callback. Its result is discarded by the delivery thread. Native enqueue, delivery, callback-root release and errors retain exact public and ownership tests.",+ "source": "src/Kafka/Producer.hs",+ "source_sha256": "cce48116f5c80ea4c7d3c2af3bc3723e3e19dfd14c3c4a362a166c18201f93fc",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Consumer.Convert:170:ExpBox True": {+ "status": "unreachable",+ "rationale": "topicPartitionFromMessage always constructs PartitionOffset from crOffset; topicPartitionFromMessageForCommit immediately matches that value. No public or private call can construct a logical offset between those expressions, so the other constructor branch cannot be selected.",+ "evidence": "docs/testing/deferred-source-audit.json",+ "source": "src/Kafka/Consumer/Convert.hs",+ "source_sha256": "9bf267580d3ee008308585ee061e9364a1dbc6556090d78b5e5df0ef767b9115"+ },+ "Kafka.Dump:82:ExpBox False": {+ "status": "unreachable",+ "rationale": "Private listToTuple receives only the native configuration dump array. In native 2.15.0 and 2.16.0 rd_kafka_anyconf_dump appends a property name and value together and returns the resulting even count. The odd-list error branch cannot occur for this native result; configuration dump acquisition/free effects still require their counted tests.",+ "evidence": "docs/testing/deferred-source-audit.json",+ "source": "src/Kafka/Dump.hs",+ "source_sha256": "434594525064002a7988b63de9e9b5315ca07422c30a8a0e94590987e30b01c1"+ },+ "Kafka.Dump:82:ExpBox True": {+ "status": "unreachable",+ "rationale": "Private listToTuple receives only the native configuration dump array. In native 2.15.0 and 2.16.0 rd_kafka_anyconf_dump appends a property name and value together and returns the resulting even count. The odd-list error branch cannot occur for this native result; configuration dump acquisition/free effects still require their counted tests.",+ "evidence": "docs/testing/deferred-source-audit.json",+ "source": "src/Kafka/Dump.hs",+ "source_sha256": "434594525064002a7988b63de9e9b5315ca07422c30a8a0e94590987e30b01c1"+ },+ "Kafka.Internal.RdKafka:323:ExpBox False": {+ "status": "inapplicable",+ "rationale": "The missed span is precisely the unit literal in managePartitionList (pure ()). Finalization executes the IO action but ignores its unit result. No native acquisition, callback retention, list destruction or parent-touch effect is excluded.",+ "evidence": "docs/testing/deferred-source-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:382:ExpBox False": {+ "status": "inapplicable",+ "rationale": "The mapped missed span is exactly the callback native-client argument k. The installed public delivery/error/log/stats adapter ignores that native argument; its pointer-value thunk is not demanded. Callback invocation, decoding, exception containment and bridge release remain measured and covered by counted callback tests.",+ "evidence": "docs/testing/deferred-source-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:427:ExpBox False": {+ "status": "inapplicable",+ "rationale": "The mapped missed span is exactly the callback native-client argument k. The installed public delivery/error/log/stats adapter ignores that native argument; its pointer-value thunk is not demanded. Callback invocation, decoding, exception containment and bridge release remain measured and covered by counted callback tests.",+ "evidence": "docs/testing/deferred-source-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:459:ExpBox False": {+ "status": "inapplicable",+ "rationale": "The mapped missed span is exactly the callback native-client argument k. The installed public delivery/error/log/stats adapter ignores that native argument; its pointer-value thunk is not demanded. Callback invocation, decoding, exception containment and bridge release remain measured and covered by counted callback tests.",+ "evidence": "docs/testing/deferred-source-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:474:ExpBox False": {+ "status": "inapplicable",+ "rationale": "The mapped missed span is exactly the callback native-client argument k. The installed public delivery/error/log/stats adapter ignores that native argument; its pointer-value thunk is not demanded. Callback invocation, decoding, exception containment and bridge release remain measured and covered by counted callback tests.",+ "evidence": "docs/testing/deferred-source-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1127:ExpBox False": {+ "status": "inapplicable",+ "rationale": "The mapped span is the optional rdKafkaTopicConfDup function argument. Both public reachability paths (legacy seek through newRdKafkaTopicT and metadata through newUnmanagedRdKafkaTopicT) pass Nothing for topicConfPtr, so no caller selects that unused duplication alternative. Native topic construction and destruction are not exempted.",+ "evidence": "docs/testing/deferred-source-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1444:BinBox CondBinBox True": {+ "status": "unreachable",+ "rationale": "For the supported native 2.15.0 and 2.16.0 implementations, rd_kafka_DeleteTopic_new performs one rd_malloc allocation and unconditionally returns it; rd_malloc asserts allocation success. Public withCString supplies a non-NULL topic. It has no recoverable NULL return, so this defensive NULL/error branch cannot occur. Actual broker deletion errors and request/event cleanup remain tested.",+ "evidence": "docs/testing/deferred-source-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1445:ExpBox False": {+ "status": "unreachable",+ "rationale": "For the supported native 2.15.0 and 2.16.0 implementations, rd_kafka_DeleteTopic_new performs one rd_malloc allocation and unconditionally returns it; rd_malloc asserts allocation success. Public withCString supplies a non-NULL topic. It has no recoverable NULL return, so this defensive NULL/error branch cannot occur. Actual broker deletion errors and request/event cleanup remain tested.",+ "evidence": "docs/testing/deferred-source-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Internal.RdKafka:1445:ExpBox True": {+ "status": "unreachable",+ "rationale": "For the supported native 2.15.0 and 2.16.0 implementations, rd_kafka_DeleteTopic_new performs one rd_malloc allocation and unconditionally returns it; rd_malloc asserts allocation success. Public withCString supplies a non-NULL topic. It has no recoverable NULL return, so this defensive NULL/error branch cannot occur. Actual broker deletion errors and request/event cleanup remain tested.",+ "evidence": "docs/testing/deferred-source-audit.json",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf"+ },+ "Kafka.Topic:65:ExpBox True": {+ "status": "unreachable",+ "rationale": "This private Left propagation is reachable only from newRdKafkaDeleteTopic returning Left on a NULL DeleteTopic_new pointer. Native 2.15.0 and 2.16.0 allocate/assert and unconditionally return a non-NULL request for the public non-NULL C string. This does not exempt broker response errors or resource cleanup.",+ "evidence": "docs/testing/deferred-source-audit.json",+ "source": "src/Kafka/Topic.hs",+ "source_sha256": "932bbd96cc0b28baf18843e4679acc0ea7f09fdefb74a3e4a3a28c9940b6a53c"+ },+ "Kafka.Topic:66:ExpBox False": {+ "status": "unreachable",+ "rationale": "This private Left propagation is reachable only from newRdKafkaDeleteTopic returning Left on a NULL DeleteTopic_new pointer. Native 2.15.0 and 2.16.0 allocate/assert and unconditionally return a non-NULL request for the public non-NULL C string. This does not exempt broker response errors or resource cleanup.",+ "evidence": "docs/testing/deferred-source-audit.json",+ "source": "src/Kafka/Topic.hs",+ "source_sha256": "932bbd96cc0b28baf18843e4679acc0ea7f09fdefb74a3e4a3a28c9940b6a53c"+ },+ "Kafka.Topic:107:ExpBox False": {+ "status": "unreachable",+ "rationale": "This private Left propagation is reachable only from newRdKafkaDeleteTopic returning Left on a NULL DeleteTopic_new pointer. Native 2.15.0 and 2.16.0 allocate/assert and unconditionally return a non-NULL request for the public non-NULL C string. This does not exempt broker response errors or resource cleanup.",+ "evidence": "docs/testing/deferred-source-audit.json",+ "source": "src/Kafka/Topic.hs",+ "source_sha256": "932bbd96cc0b28baf18843e4679acc0ea7f09fdefb74a3e4a3a28c9940b6a53c"+ },+ "Kafka.Topic:107:ExpBox True": {+ "status": "unreachable",+ "rationale": "This private Left propagation is reachable only from newRdKafkaDeleteTopic returning Left on a NULL DeleteTopic_new pointer. Native 2.15.0 and 2.16.0 allocate/assert and unconditionally return a non-NULL request for the public non-NULL C string. This does not exempt broker response errors or resource cleanup.",+ "evidence": "docs/testing/deferred-source-audit.json",+ "source": "src/Kafka/Topic.hs",+ "source_sha256": "932bbd96cc0b28baf18843e4679acc0ea7f09fdefb74a3e4a3a28c9940b6a53c"+ },+ "Kafka.Topic:114:ExpBox False": {+ "status": "unreachable",+ "rationale": "This private Left propagation is reachable only from newRdKafkaDeleteTopic returning Left on a NULL DeleteTopic_new pointer. Native 2.15.0 and 2.16.0 allocate/assert and unconditionally return a non-NULL request for the public non-NULL C string. This does not exempt broker response errors or resource cleanup.",+ "evidence": "docs/testing/deferred-source-audit.json",+ "source": "src/Kafka/Topic.hs",+ "source_sha256": "932bbd96cc0b28baf18843e4679acc0ea7f09fdefb74a3e4a3a28c9940b6a53c"+ },+ "Kafka.Topic:114:ExpBox True": {+ "status": "unreachable",+ "rationale": "This private Left propagation is reachable only from newRdKafkaDeleteTopic returning Left on a NULL DeleteTopic_new pointer. Native 2.15.0 and 2.16.0 allocate/assert and unconditionally return a non-NULL request for the public non-NULL C string. This does not exempt broker response errors or resource cleanup.",+ "evidence": "docs/testing/deferred-source-audit.json",+ "source": "src/Kafka/Topic.hs",+ "source_sha256": "932bbd96cc0b28baf18843e4679acc0ea7f09fdefb74a3e4a3a28c9940b6a53c"+ },+ "Kafka.Topic:196:ExpBox False": {+ "status": "inapplicable",+ "rationale": "The missed span is exactly [] in singletonList x = x :| []. All private callers propagate these temporary NonEmpty errors to public create/deleteTopic, which selects NEL.head; no caller demands the empty tail. The head error value and all native error acquisition/destruction still require execution.",+ "evidence": "docs/testing/deferred-source-audit.json",+ "source": "src/Kafka/Topic.hs",+ "source_sha256": "932bbd96cc0b28baf18843e4679acc0ea7f09fdefb74a3e4a3a28c9940b6a53c"+ },+ "Kafka.Internal.Shared:103:ExpBox False": {+ "status": "inapplicable",+ "rationale": "The only caller maps maybeToLeft over closeConsumer in runConsumer's bracket release action. bracket executes closeConsumer but discards the mapped cleanup result without forcing its Either constructor, so the pure mapper and its constructor arguments remain unevaluated. Native close/destroy behavior is not exempted.",+ "evidence": "docs/testing/deferred-source-audit.json",+ "source": "src/Kafka/Internal/Shared.hs",+ "source_sha256": "fb9eb7755af2a3da0db73b665a0e09a7c6ee3b1381aaac9e658a78f1ebd7e100"+ },+ "Kafka.Internal.Shared:103:TopLevelBox [\"maybeToLeft\"]": {+ "status": "inapplicable",+ "rationale": "The only caller maps maybeToLeft over closeConsumer in runConsumer's bracket release action. bracket executes closeConsumer but discards the mapped cleanup result without forcing its Either constructor, so the pure mapper and its constructor arguments remain unevaluated. Native close/destroy behavior is not exempted.",+ "evidence": "docs/testing/deferred-source-audit.json",+ "source": "src/Kafka/Internal/Shared.hs",+ "source_sha256": "fb9eb7755af2a3da0db73b665a0e09a7c6ee3b1381aaac9e658a78f1ebd7e100"+ },+ "Kafka.Internal.Shared:148:ExpBox False": {+ "status": "unreachable",+ "rationale": "Private header iteration reaches this error alternative only if rd_kafka_header_get_all returns neither NO_ERROR nor NOENT. Both native 2.15.0 and 2.16.0 implementations have exactly those two returns for an existing parsed header list. Message-header acquisition/parse errors are handled earlier and remain covered by polled-message failure tests.",+ "evidence": "docs/testing/deferred-source-audit.json",+ "source": "src/Kafka/Internal/Shared.hs",+ "source_sha256": "fb9eb7755af2a3da0db73b665a0e09a7c6ee3b1381aaac9e658a78f1ebd7e100"+ },+ "Kafka.Internal.Shared:148:ExpBox True": {+ "status": "unreachable",+ "rationale": "Private header iteration reaches this error alternative only if rd_kafka_header_get_all returns neither NO_ERROR nor NOENT. Both native 2.15.0 and 2.16.0 implementations have exactly those two returns for an existing parsed header list. Message-header acquisition/parse errors are handled earlier and remain covered by polled-message failure tests.",+ "evidence": "docs/testing/deferred-source-audit.json",+ "source": "src/Kafka/Internal/Shared.hs",+ "source_sha256": "fb9eb7755af2a3da0db73b665a0e09a7c6ee3b1381aaac9e658a78f1ebd7e100"+ },+ "Kafka.Consumer:547:ExpBox False": {+ "status": "inapplicable",+ "rationale": "The private subscription decoder fallback expects partition-specific subscriptions. Public Subscription contains only a Set TopicName, and Consumer.subscribe constructs exactly one partition -1 entry per unique topic. Released native subscribe copies this list; subscription returns the saved topic list. Empty subscriptions yield no entry and every nonempty public entry takes SubscribedPartitionsAll. Manual assignments use a distinct API and do not change subscription. Specific partition decoding is therefore unavailable through this public subscription path; native queries and their errors are still exercised.",+ "source": "src/Kafka/Consumer.hs",+ "source_sha256": "170ea8259f8b0279db807c48799f323a268e7636efcbc929ade003cd4e4bb70a",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Consumer:547:ExpBox True": {+ "status": "inapplicable",+ "rationale": "The entire private SubscribedPartitions fallback has the same source-proven domain restriction as its ps argument: all public subscription entries are unique topic/-1 pairs. Both multiple-topic and regex subscriptions observe the exact All representation; this is not a general exclusion of subscription IO or decoding.",+ "source": "src/Kafka/Consumer.hs",+ "source_sha256": "170ea8259f8b0279db807c48799f323a268e7636efcbc929ade003cd4e4bb70a",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Consumer:319:ExpBox False": {+ "status": "inapplicable",+ "rationale": "Only the nullPtr argument at columns 50-68 is unforced. GHC 9.12.4 Storable (Ptr a) expands STORABLE with sizeOf _ = SIZEOF_HSPTR. Pointer size, negative/overflow bounds and the native allocation boundary are exercised; the ignored pointer value cannot acquire a hit.",+ "source": "src/Kafka/Consumer.hs",+ "source_sha256": "170ea8259f8b0279db807c48799f323a268e7636efcbc929ade003cd4e4bb70a",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Consumer.Callbacks:75:ExpBox False": {+ "status": "inapplicable",+ "rationale": "Only the unit literal at columns 23-24 in return () is ignored. The Nothing queue branch executes in synchronous callback mode; IO sequencing does not demand the unit value. No queue acquisition, forwarding or release action is excluded.",+ "source": "src/Kafka/Consumer/Callbacks.hs",+ "source_sha256": "7e993c821435554f7d705ad0369ce4dab3c561216c1966baf29cf967e310e362",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Internal.RdKafka:1492:ExpBox False": {+ "status": "inapplicable",+ "rationale": "Only the unit value in Right () is lazy and discarded by current private callers, which distinguish Left from Right but never force the successful payload. Native codes and success/error branches execute; the value-level tick is not a missing error conversion.",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Internal.RdKafka:1416:ExpBox False": {+ "status": "inapplicable",+ "rationale": "Only the errMsg tuple field is unforced. Topic.runRequest pattern-matches Left (name, err, _) and propagates the native error code; no public result exposes that private String. The native error-string read, tuple construction, response-name validation and owned-event cleanup are not exempted.",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Internal.Setup:228:ExpBox False": {+ "status": "inapplicable",+ "rationale": "Only the success unit in pure () at columns 22-23 is unforced; validation and both NUL failure predicates run. Sequencing this IO action ignores its result.",+ "source": "src/Kafka/Internal/Setup.hs",+ "source_sha256": "69ef4227adf311f7dee3ec283825d42c1e3a2561df6f66bab29d2abb8b446188",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Internal.Shared:59:ExpBox False": {+ "status": "inapplicable",+ "rationale": "The private pollEvents helper has exactly one production caller, Producer.produceMessage', which supplies Just (Timeout 0). It is hidden by Cabal and is not re-exported by the producer API. Only the Nothing default literal 0 is unavailable to public calls; actual native poll and timeout extraction execute.",+ "source": "src/Kafka/Internal/Shared.hs",+ "source_sha256": "fb9eb7755af2a3da0db73b665a0e09a7c6ee3b1381aaac9e658a78f1ebd7e100",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Internal.Shared:52:BinBox GuardBinBox False": {+ "status": "inapplicable",+ "rationale": "This is the impossible False branch of Prelude.otherwise after both SASL string validations. The otherwise body and both invalid credential guards execute. The constant guard cannot evaluate False.",+ "source": "src/Kafka/Internal/Shared.hs",+ "source_sha256": "fb9eb7755af2a3da0db73b665a0e09a7c6ee3b1381aaac9e658a78f1ebd7e100",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Metadata:255:ExpBox False": {+ "status": "inapplicable",+ "rationale": "Only the ignored unit at columns 40-41 in the Left acquisition cleanup is unforced. A failed acquisition has no owned ForeignPtr; its error is propagated. Successful native results still finalize explicitly and are covered by counted/cancelled native acquisitions.",+ "source": "src/Kafka/Metadata.hs",+ "source_sha256": "abcfd0962c104901916c4b4a456b4e99b9905ffd430b74b4e2244e5a2744512f",+ "evidence": "docs/testing/deferred-source-audit.json"+ },+ "Kafka.Metadata:149:ExpBox False": {+ "status": "inapplicable",+ "rationale": "The two ticks are the lazy unit literal and const () thunk in a failed topic-handle acquisition cleanup. bracket sequences return (const () err) without demanding its value. The failed acquire/error propagation and the successful native-topic destroy remain real tested effects.",+ "source": "src/Kafka/Metadata.hs",+ "source_sha256": "abcfd0962c104901916c4b4a456b4e99b9905ffd430b74b4e2244e5a2744512f",+ "evidence": "docs/testing/deferred-source-audit.json"+ }+ }+}
+ docs/testing/coverage.md view
@@ -0,0 +1,141 @@+# Coverage evidence++The user-selected primary release scope is recorded in [ADR-27](../adr/release-validation-has-explicit-primary-and-expanded-scopes.md). MasterPlan 2 retains all implemented tests and requires current complete primary normal/mapped execution, repair controls and package replay. [MasterPlan 3](../masterplans/3-complete-deferred-coverage-and-compatibility-validation.md) owns exhaustive public/source-path closure and broader compatibility/security qualification. [The deferred ledger](deferred-validation.md) preserves every outstanding obligation and reusable asset. `coverage-matrix.json` records the obligations and responsible child plans. Its initial open rows are deliberate gaps, not passing tests. A compiler-derived export snapshot includes re-exports, types, exported constructors and record fields. Each `symbol` row covers all its `members`; cases must exercise the applicable constructors, selectors and laws before the row can close.++Run commands from the repository root inside `nix develop`:++```bash+just test-it+cabal test rdkafka-hs-test --test-show-details=direct+just coverage+cabal build lib:rdkafka-hs+python3 scripts/check-coverage.py --allow-open+just coverage-check+```++The explicit `--allow-open` check validates exports, registered tests, ownership, artifacts and source freshness while preserving deferred rows; it is also the user-approved primary release inventory check. The strict final comprehensive check rejects those rows and belongs to MasterPlan 3. No test count or percentage closes a contract. To close one, record the exact fully qualified Tasty test names, the measured input `fingerprint`, and `status: tested` only after all of that row's behavior/inputs/expected results pass. Split a row when some cases have different owners or incomplete evidence. Environment rows stay open until actual execution under EP-17, EP-18 and EP-19. A non-applicable row requires a specific source-backed precondition; inaccessible environments and inconvenient failure injection remain open.++`just coverage` collects both suites into `dist-coverage/`, clears only that build directory's previous TIX data, and forces instrumentation recompilation. It fails if a suite fails, its TIX data is missing, the candidate changes during the run, source mapping is absent, or the measured modules omit library source. The evidence manifest records the revision, source/test/build/tooling content digest (including untracked additions), compiler/native versions, exact command, broker endpoint, complete test names, aggregate pass count, and artifact checksums. Test logs retain failure seeds and diagnostics. Large reports stay ignored. Documentation-only inventory/evidence edits do not change the measured digest; scripts and build recipes do.++The report directory contains each suite's library report, the combined TIX and text/XML metrics, every tick's count/span/label, source-attributed misses, unexercised hand-written functions, and separate hand-written/generated tick metrics labelled with HPC's exact box kinds. HPC measures Haskell expressions, alternatives, conditions and declarations. Native allocation balance, races and callback safety require separate controls; HPC cannot establish them. Normal optimized execution remains mandatory.++GHC 9.12 excludes HPC spans redirected to a different source file by a `LINE` pragma. Ordinary c2hs output therefore reports zero ticks for `Kafka.Internal.RdKafka`, including its hand-written wrappers. The coverage-only GHC `-F` adapter replaces c2hs `LINE` directives with blank lines, preserves physical generated coordinates, and emits a sidecar mapping back to `.chs` lines. It also restores the original filename for ordinary `.hs` input so GHC does not attribute its spans to a temporary preprocessor file. Production compilation is unchanged. Mapping segments that originate in c2hs directives are classified as generated; ordinary wrapper segments remain hand-written. Zero measured hand-written wrapper ticks fail collection. Cabal's HTML uses generated `.hs` coordinates; `reports/misses.json` maps those coordinates back to `.chs` for review.++Every uncovered hand-written tick is visible with an owning row. Before the final gate, exercise it or add an exact `module:line:label` entry under `miss_classifications`, with `status: unreachable` or `inapplicable` and a concrete source-backed `rationale`. Critical error/ownership paths require execution and native diagnostics; they cannot be excused by a broad percentage or a successful neighboring case. Generated marshalling misses remain visible separately.++After changing source, tests, build inputs or coverage tooling, rerun both normal and instrumented checks. Missing or modified artifacts, stale fingerprints, removed test names and new exports fail validation. This infrastructure does not run the compatibility matrix; EP-17/18/19 produce that evidence and EP-20 integrates it. Historical EP-15 references in the retained manifests describe their original ownership; the ledger records each transferred `previous_owner`.+++Topic-admin verification inspects the private container with `container exec rdkafka-hs-rp-0 rpk topic describe <run-prefixed-topic> -c`. Isolated external tuples supply `RDKAFKA_TEST_RPK`, configured for their own broker, and `RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY=ignore` or `reject`. Primary Redpanda v26.2.1 accepts unknown topic properties; Apache Kafka's rejection policy must be tested under its own declared fixture. The test checks exact native setter arguments and effective known settings in either policy. The evidence manifest records these non-secret fixture inputs.++The integration executable's `cbits/admin_ownership.c` counts application-owned native requests, options, queue references and events, and provides controlled native failure/response stages. It dispatches ordinary calls to librdkafka and filters calls made internally by that library. A positive control reproduces the old allocation-then-error acquisition pattern and observes its retained request before releasing it. These counters prove wrapper ownership boundaries; Linux leak/invalid-access diagnostics remain required by EP-15.++Run `just test-mutations topic` inside the development shell to build an isolated source archive, pass its unchanged control, and prove that removing configuration application or ownership/error checks fails the intended focused test after successful compilation. Current logs and source-bound evidence stay under ignored `dist-mutations/`; earlier Python-runner archives retain their original paths.++Producer verification uses `Kafka.Integration.ProducerRegressionTest` and the test executable's `cbits/producer_ownership.c`. The shim observes configuration on the actual native client passed to `produceva`, and its barriers pause immediately before controlled rejection or after real native acceptance. Cancellation tests observe the killer blocked in `throwTo`; a thread launch or delay does not define the ownership window. Ordinary calls still dispatch to librdkafka. Header names/values are borrowed Haskell buffers through the call, while native header objects are allocated and released inside librdkafka; EP-15's native diagnostics remain mandatory.++The native mock protocol fixture delays Produce responses and records received Produce requests, proving a message reached the broker before in-flight purge assertions. It runs on owned ephemeral loopback listeners and is destroyed with its callback-free native anchor client. It does not replace actual Redpanda codec/configuration round trips or EP-15's broker/authentication matrix.++Throwing delivery callbacks run in isolated child processes so foreign-boundary failures and uncaught-exception handlers cannot corrupt the parent suite. Coverage collection gives each child a unique TIX path, requires successful global and per-message probe coverage, and merges those ticks into the integration report. Normal runs retain optional child artifacts under ignored `dist-callback-probes/`.++Run `just test-mutations producer` to compile an isolated archive, pass its complete producer control, and reject semantic mutations of settings, callback release/transfer, masking, exception handling, empty-byte representation, input validation and headers. A premature-free safety mutation may abort GHC; it counts only when a native marker proves enqueue succeeded before the isolated process aborted. Source-bound logs and archive checksums stay under ignored `dist-mutations/`.++Generated properties use the released adapter [mori://UnkindPartition/tasty/packages/tasty-quickcheck](mori://UnkindPartition/tasty/packages/tasty-quickcheck), selected at `^>=0.11.1` after checking Hackage and its upstream release tag. Shared generators live in `test-support/Kafka/PropertySupport.hs`, which is included in candidate fingerprints. Pure producer laws use an independent last-write model; callback composition is observed through actual delivery reports. Both suites print replay tokens and retain the adapter's case-count and replay options.++Run a seeded thousand-case check with:++```bash+cabal test rdkafka-hs-test --test-show-details=direct \+ --test-options='--quickcheck-tests=1000 --quickcheck-replay=20261024'+cabal test rdkafka-hs-integration -f integration --test-show-details=direct \+ --test-options='-p /producer-properties/ --quickcheck-tests=1000 --quickcheck-replay=20261024'+```++For an exact failure replay, pass the entire printed `--quickcheck-replay` value as one argument to the binary from `cabal list-bin`. A token includes both generator state and size. `just test-mutations property` builds a disposable archive, catches reversed global/topic/log-level/callback precedence, preserves minimized counterexamples, and reruns each printed token. Its archive, controls, failure and replay logs stay under ignored `dist-mutations/`. The property evidence manifest records resolved test dependency versions as well as source identity; replay uses the recorded toolchain and dependencies.++The single Haskell runner replaces four Python mutation scripts. [The parity record](mutation-runner-parity.json) verifies all 32 original mutations and five controls with identical selected test counts, plus all four minimized property replays. It also records five callback ownership mutations and two controls, available through `just test-mutations callback`. Ordinary tests remain in the Cabal suites.++Seek/rewind regressions run in the `seek-partitions` group in both callback modes. They check native member codes, exact payload/offset replay, partial success, timeout initiation versus completion, duplicate native entries, and committed next offsets. A test-only committed-lookup barrier allows an actual unassignment before rewind's seek. A run-owned prefix trim verifies behavior below the retained log range; external tuples provide their broker-configured `RDKAFKA_TEST_RPK` executable. `nix develop -c just test-mutations seek` compiles an isolated source archive and requires seven semantic mutations to fail their intended tests, plus an unchanged control. The native seam is linked only into the integration executable and ordinary calls forward to the real library.++Transaction ownership uses the `transaction-errors` group and `cbits/transaction_ownership.c`. Returned native errors are counted separately from background allocations. The explicit control repeats the inherited three-call decode-without-destroy sequence on one nontransactional producer and verifies three outstanding objects before fixture cleanup; the repaired loop balances all 300 calls. Native flag fixtures allocate native objects and call the library's diagnostic setters without copying its opaque layout. Real broker cases cover fencing, abort-required delivery rejection and source/output atomicity in both modes.++Run `just test-mutations transaction` to require a passing 51-case control and ten compiled mutations covering error disposal, flag classification, group metadata and the source next-offset convention. [Acceptance evidence](transaction-evidence.json) and [native diagnostics](transaction-native-diagnostics.json) record the candidate, actual native library and commands. Run normal tests after the coverage command's preliminary default-directory build has finished; two concurrent Cabal builds must use distinct build directories.++Remaining public data laws live in `Kafka.PublicPropertiesSpec` and `Kafka.Integration.ConsumerPropertyTest`. The consumer registration property uses real constructor log callbacks, and a native observer checks generated source next-offset fields across the representable signed 64-bit domain. Subscription maps now prefer later values by the user's explicit choice, while topic sets still accumulate; both consumer modes verify the resulting native reset policy. `just test-mutations public` catches eight generated semantic faults and replays their minimized tokens. [The focused M1 record](public-properties-evidence.json) distinguishes these property/HPC checks from the final full-candidate coverage gate.++Polled-message ownership tests are in `public-contract.messages`. The test-only native observer records actual returned message objects and pauses at native-return or decoder boundaries; cancellation is injected only after the boundary and a blocked exception sender are observed. A retained-last-object control verifies the counter. `just test-mutations messages` catches omitted batch cleanup, unmasked single acquisition and suppressed header/acquisition errors. [The checkpoint evidence](message-ownership-evidence.json) records normal, Haskell-instrumented and native-instrumented results; remaining EP-14 API work and final global coverage are separate.++### Actual runtime variants++EP-14 checks async construction, synchronous record delivery and deprecated+runner cleanup in actual threaded and nonthreaded executables:++```bash+nix develop -c cabal test rdkafka-hs-integration -f integration --test-show-details=direct --test-options='-p /runtime-contract/'+nix develop -c cabal test rdkafka-hs-integration -f integration --builddir=dist-nonthreaded --ghc-options='-single-threaded -with-rtsopts=-T' --test-show-details=direct --test-options='-p /runtime-contract/'+nix develop -c just test-mutations runtime+```++The nonthreaded command overrides the integration executable's usual threaded+link and default `-N` options. Its observed RTS way is `rts_v`. The mutation+runner applies the same flags to the runtime family and omits `-N2`; other+families retain their original threaded invocation. See+[runtime evidence](runtime-evidence.json). Focused instrumented results do not+replace final full-candidate mapped coverage.++The accepted primary checkpoint passes 786 registered cases normally and mapped, plus four actual nonthreaded cases and 24 tooling controls. [Primary evidence](primary-validation-evidence.json) records clean package replay and the bounded actual example. The remaining 35 historical open rows and 192 unclassified handwritten ticks are preserved in [the source-bound deferred snapshot](deferred-validation-snapshot.json); the strict checker continues to reject comprehensive incompleteness.+++EP-16's [current checkpoint](deferred-public-contract-evidence.json) passes+808 registered cases normally and mapped, plus four actual nonthreaded cases+and 27 tooling controls. Reconciliation closes 19 historical contract rows;+16 remain open with concrete owners and missing behaviors. This does not alter+the accepted earlier primary candidate or close comprehensive qualification.++Every handwritten applicability classification now carries its exact `source`+and whole-file `source_sha256`. The checker rejects a missing or changed binding+even with `--allow-open`; new measured evidence cannot silently renew an old+source proof. Fallback miss ownership comes from the ledger, and transferred rows+retain their historical `previous_owner`.++`just test-mutations source-edges` passes seven unchanged controls and catches+eight compiled faults covering absent error attribution, logical offsets, native+subscription errors, partial topic acquisition, constructor cleanup, complete+batch order and live producer log level. The log-level assertion reads the actual+native client at enqueue. `dumpKafkaConf` reads the retained construction+configuration, so its `log_level` can differ from a subsequent native setter.++Expanded qualification uses explicit executable modes. With a released Apache+distribution, Java and OpenSSL available, run:++```bash+export RDKAFKA_TEST_KAFKA_HOME=/path/to/apache-kafka+cabal run rdkafka-hs-integration -f integration -- --broker-qualification+cabal run rdkafka-hs-integration -f integration -- --authentication-qualification+```++These modes create and destroy their own broker processes and ephemeral ports;+missing prerequisites fail. Ordinary primary tests still use their private+Redpanda. The shared fixture owns processes; the security extension owns+ephemeral CA/keys, identities, TLS settings and ACLs. No credentials belong in+logs or evidence. [Authentication evidence](authentication-evidence.json) records+its incremental behavioral checkpoint and remaining clean/interruption gates.++`--native-lifetime` wraps any selected executable mode with bounded Haskell GC+and native client-destruction drain. Child probes inherit that mode through+`RDKAFKA_TEST_NATIVE_LIFETIME`. A timeout fails; nothing is silently suppressed.+The transaction flag controls additionally need a diagnostic native build that+exports `rd_kafka_error_set_fatal`, `rd_kafka_error_set_retriable` and+`rd_kafka_error_set_txn_requires_abort`. Standard Linux symbol maps hide them.+The fixture checks their availability before allocating control clients and+fails explicitly if absent. [Linux evidence](linux-tuple-evidence.json) retains+the exact linker-map diff; only these three exports change, not native object+layout or function bodies. Normal public/native compatibility paths need no+private symbol.++`just test-mutations credentials` passes the seven focused setter controls and+rejects four compiled faults: NUL username/password truncation, unmasked native+error acquisition, and omitted error destruction. Pending cancellation is+observed at native acquisition and decoder boundaries, with one real native+allocation and one destruction. These ownership checks complement actual+authentication and replacement-only ACL observations after reconnect.
+ docs/testing/deferred-public-contract-evidence.json view
@@ -0,0 +1,150 @@+{+ "status": "Accepted current public-contract and source-audit checkpoint; EP-16 remains open",+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "normal": {+ "unit": 78,+ "integration": 753,+ "seconds": [+ 1.12,+ 349.49+ ]+ },+ "mapped": {+ "unit": 78,+ "integration": 753,+ "external_behavior_cases": 26,+ "registered_behavior_cases": 857,+ "nonthreaded": 4,+ "tooling_controls": 28,+ "native_wrapper_ticks": 2752+ },+ "inventory": {+ "rows": 181,+ "tested": 180,+ "open": 1,+ "newly_reconciled": 34+ },+ "unclassified_handwritten_ticks": 2,+ "source_classifications": 401,+ "new_source_audit": "docs/testing/deferred-source-audit.json",+ "mutations": {+ "manifest": "dist-mutations/20261025T001512Z-source-edges-91215-0/results.json",+ "controls": 7,+ "compiled_faults": 8+ },+ "artifacts": {+ "normal": {+ "path": "dist-compatibility/expanded-source9/primary-normal9.log",+ "sha256": "0cc78933babadbb7d223879eb76ddd60513010cfab5cd282a0e4ee974a52faeb"+ },+ "mapped": {+ "path": "dist-compatibility/expanded-source9/primary-mapped9.log",+ "sha256": "563e4fcf86cd2047cea629df6837a502e4795dca676f96671655b9758eacf6c8"+ },+ "allow_open": {+ "path": "dist-compatibility/expanded-source9/coverage-allow-open.log",+ "sha256": "6aaeb4a62ef5152f0f1adf20bb654b54b8fe12f057b757150972ebe61992fb7a"+ },+ "strict": {+ "path": "dist-compatibility/expanded-source9/coverage-strict.log",+ "sha256": "542cc685cf514e26aec1535c91dba78ce90b78baacf3eebe98e98afc47a43222"+ },+ "tooling": {+ "path": "dist-compatibility/expanded-source9/coverage-tools9.log",+ "sha256": "32be708ddfdb2bfe9039dfb8c4ace081e2635be74e0618dab745c03e8c2620b1"+ },+ "measured": {+ "path": "dist-compatibility/expanded-source9/primary-measured9-with-contexts.json",+ "sha256": "9a98d410cbeb3ef8ce0e3d99f39d989dbf145ee434db9aedf7aa771c52922ffe"+ },+ "required_checks": {+ "path": "dist-compatibility/expanded-source9/required-check9.log",+ "sha256": "938e9221c460f2b6aba3decc91039024bd71b0ec0204c8a8fad6b254573b97dc"+ }+ },+ "limits": [+ "Historical seek requirement accepted through causal native-identity reconstruction and an isolated 182-case scoped-lifetime differential; the untraced original event itself remains unobservable retrospectively.",+ "Two unexplained producer pre-enqueue exception-cleanup ticks remain. No out-of-memory behavior is claimed tested or exempted.",+ "External context imports add exact registered behavior names only; no HPC counts or ticks are imported. Strict coverage rejects both open rows and both unexplained ticks."+ ],+ "previous_checkpoint": {+ "status": "accepted EP-16 M1 and partial M2 checkpoint; comprehensive qualification remains open",+ "fingerprint": "abbf4e69f7806356c083acb0bb163c3e24f1fc7b4b1b5d78d1f469b0653a8993",+ "normal": {+ "unit": 78,+ "integration": 735,+ "seconds": [+ 1.0,+ 332.5+ ]+ },+ "mapped": {+ "unit": 78,+ "integration": 735,+ "nonthreaded": 4,+ "tooling_controls": 27,+ "native_wrapper_ticks": 2752+ },+ "inventory": {+ "rows": 181,+ "tested": 165,+ "open": 16,+ "newly_reconciled": 19+ },+ "unclassified_handwritten_ticks": 70,+ "source_classifications": 390,+ "new_source_audit": "docs/testing/deferred-source-audit.json",+ "mutations": {+ "manifest": "dist-mutations/20261025T001512Z-source-edges-91215-0/results.json",+ "controls": 7,+ "compiled_faults": 8+ },+ "artifacts": {+ "normal": {+ "path": "dist-compatibility/owned-fixture-checkpoint/primary-phase5-normal.log",+ "sha256": "f88e7453eb9fe561d9b08db2ee062c101c0eaa10ee23309c0e17607332297173"+ },+ "mapped": {+ "path": "dist-compatibility/owned-fixture-checkpoint/primary-phase5-mapped.log",+ "sha256": "00365edde70161aa36232659be4181b60db999709bba2432559fc86eca59bb11"+ },+ "allow_open": {+ "path": "dist-compatibility/owned-fixture-checkpoint/primary-phase5-allow_open.log",+ "sha256": "e942254489b57cbfb27bccae0805b9a1a46bc36847777c9596433a9f0d7d9aa7"+ },+ "strict": {+ "path": "dist-compatibility/owned-fixture-checkpoint/primary-phase5-strict.log",+ "sha256": "beea750daca56559d29ad310e526e7f758df8028462ac78605d17e5388e6d96d"+ },+ "measured": {+ "path": "dist-compatibility/owned-fixture-checkpoint/primary-phase5-measured.json",+ "sha256": "4a3fc998e574923920befbf4f82b09cae9dd4bf8be563aff8d7b33fe7696fbaa"+ }+ },+ "limits": [+ "Historical seek trigger remains unknown and its scope question is pending.",+ "Reachable handwritten paths remain open; strict coverage must continue to fail.",+ "Linux/broker/native/security results are owned by their separate children and are not inferred from this checkpoint."+ ],+ "post_measurement_note": "The commit formatter subsequently sorted the new Cabal module registrations. This measured fingerprint remains the exact pre-format checkpoint; fresh current-candidate evidence is required and is not inferred from formatting equivalence."+ },+ "post_measurement_note": "Current functional source exactly matches measured evidence. The clean Linux archive differs only by ten documented omitted development inputs; cabal.project contains only packages: . and its implicit replacement selects the same package set. Documentation edits do not alter the functional fingerprint.",+ "qualification_contexts": [+ {+ "path": "docs/testing/broker-qualification-context.json",+ "sha256": "d080bb062d1afed7d5a5b71ab37ed9b70b83fbe114d44650253af3999cc56c36"+ },+ {+ "path": "docs/testing/authentication-qualification-context.json",+ "sha256": "bbd1b7edc15934382e7b7f4e516ecce5688f257c0ee9eb19277e3b42ef26c730"+ }+ ],+ "rebalance_mutations": {+ "path": "dist-mutations/20261025T014120Z-rebalance-76179-0/results.json",+ "sha256": "ecc0364f6a0552605aaa48af5954a17474608166805ed5692ffdc809b3bd4785"+ },+ "historical_seek": {+ "path": "docs/testing/legacy-seek-evidence.json",+ "sha256": "4b68dbbd2afcec8d95be8b20e965decbd00b0d09d435ae2b471b1195ddb943a6"+ }+}
+ docs/testing/deferred-source-audit.json view
@@ -0,0 +1,241 @@+{+ "status": "partial source audit; reachable branches and historical seek remain open",+ "baseline_fingerprint": "060dade4e8a9c764dabee54df3030fa6d857be3ea1404a2bc680a45ddadd5e4e",+ "proof_boundary": "Exact module/line/label keys only. Original audited production bytes match checkpoint e29e2f7; later exact-line/source-hash renewals are recorded in coverage-classification-remap.json. Unforced private field conversions and discarded unit literals do not exempt native IO reads, allocation, cleanup or error paths.",+ "keys": [+ "Kafka.Consumer:866:ExpBox False",+ "Kafka.Consumer:870:ExpBox False",+ "Kafka.Consumer:827:ExpBox False",+ "Kafka.Consumer:879:ExpBox False",+ "Kafka.Consumer:883:ExpBox False",+ "Kafka.Consumer:524:ExpBox False",+ "Kafka.Consumer:395:ExpBox False",+ "Kafka.Consumer:329:ExpBox False",+ "Kafka.Consumer:322:BinBox GuardBinBox False",+ "Kafka.Consumer:163:BinBox GuardBinBox False",+ "Kafka.Consumer.Callbacks:100:ExpBox False",+ "Kafka.Internal.RdKafka:792:ExpBox False",+ "Kafka.Internal.RdKafka:177:ExpBox False",+ "Kafka.Internal.RdKafka:148:ExpBox False",+ "Kafka.Internal.RdKafka:149:ExpBox False",+ "Kafka.Internal.RdKafka:150:ExpBox False",+ "Kafka.Producer:234:ExpBox False",+ "Kafka.Producer:114:ExpBox False",+ "Kafka.Topic:147:ExpBox False",+ "Kafka.Topic:75:BinBox GuardBinBox False",+ "Kafka.Topic:86:BinBox GuardBinBox False",+ "Kafka.Topic:61:BinBox GuardBinBox False",+ "Kafka.Topic:38:BinBox GuardBinBox False",+ "Kafka.Consumer:765:BinBox GuardBinBox False",+ "Kafka.Consumer:139:ExpBox False",+ "Kafka.Consumer:140:ExpBox False",+ "Kafka.Consumer.Convert:84:BinBox GuardBinBox False",+ "Kafka.Internal.Setup:228:BinBox GuardBinBox False",+ "Kafka.Internal.Setup:194:ExpBox False",+ "Kafka.Internal.Shared:159:BinBox GuardBinBox False",+ "Kafka.Internal.Shared:171:BinBox GuardBinBox False",+ "Kafka.Producer:290:BinBox GuardBinBox False",+ "Kafka.Producer:158:ExpBox False"+ ],+ "continuations": [+ {+ "status": "precise source-backed applicability additions; full coverage still required",+ "keys": [+ "Kafka.Consumer.Convert:170:ExpBox True",+ "Kafka.Dump:82:ExpBox False",+ "Kafka.Dump:82:ExpBox True",+ "Kafka.Internal.RdKafka:323:ExpBox False",+ "Kafka.Internal.RdKafka:382:ExpBox False",+ "Kafka.Internal.RdKafka:427:ExpBox False",+ "Kafka.Internal.RdKafka:459:ExpBox False",+ "Kafka.Internal.RdKafka:474:ExpBox False",+ "Kafka.Internal.RdKafka:1127:ExpBox False",+ "Kafka.Internal.RdKafka:1444:BinBox CondBinBox True",+ "Kafka.Internal.RdKafka:1445:ExpBox False",+ "Kafka.Internal.RdKafka:1445:ExpBox True",+ "Kafka.Topic:65:ExpBox True",+ "Kafka.Topic:66:ExpBox False",+ "Kafka.Topic:107:ExpBox False",+ "Kafka.Topic:107:ExpBox True",+ "Kafka.Topic:114:ExpBox False",+ "Kafka.Topic:114:ExpBox True",+ "Kafka.Topic:196:ExpBox False",+ "Kafka.Internal.Shared:103:ExpBox False",+ "Kafka.Internal.Shared:103:TopLevelBox [\"maybeToLeft\"]",+ "Kafka.Internal.Shared:148:ExpBox False",+ "Kafka.Internal.Shared:148:ExpBox True"+ ],+ "native_sources": {+ "v215-admin.c": {+ "project": "mori://confluentinc/librdkafka",+ "version": "2.15.0",+ "project_relative_path": "src/rdkafka_admin.c",+ "artifact_uri": "source-artifact URI pending",+ "path": "dist-compatibility/owned-fixture-checkpoint/v215-admin.c",+ "sha256": "8ed0e410007040262668e3b7b83dacf69241a8184ba174e7d32ab1d9dd4b1179"+ },+ "v215-conf.c": {+ "project": "mori://confluentinc/librdkafka",+ "version": "2.15.0",+ "project_relative_path": "src/rdkafka_conf.c",+ "artifact_uri": "source-artifact URI pending",+ "path": "dist-compatibility/owned-fixture-checkpoint/v215-conf.c",+ "sha256": "7464c3e6fa9a95fb9618d9b7b3117693cf08b972042a880dd23eb25c9d8f1fba"+ },+ "v215-header.c": {+ "project": "mori://confluentinc/librdkafka",+ "version": "2.15.0",+ "project_relative_path": "src/rdkafka_header.c",+ "artifact_uri": "source-artifact URI pending",+ "path": "dist-compatibility/owned-fixture-checkpoint/v215-header.c",+ "sha256": "c82403e08653d0d19b39b5740a9477a838575361eab3c83451effaa809bf2175"+ },+ "v216-admin.c": {+ "project": "mori://confluentinc/librdkafka",+ "version": "2.16.0",+ "project_relative_path": "src/rdkafka_admin.c",+ "artifact_uri": "source-artifact URI pending",+ "path": "dist-compatibility/owned-fixture-checkpoint/v216-admin.c",+ "sha256": "266e0ecabac608c165ec51cb97efe23ccf821cb34adcbfbd42bf61a5c9517fc8"+ },+ "v216-conf.c": {+ "project": "mori://confluentinc/librdkafka",+ "version": "2.16.0",+ "project_relative_path": "src/rdkafka_conf.c",+ "artifact_uri": "source-artifact URI pending",+ "path": "dist-compatibility/owned-fixture-checkpoint/v216-conf.c",+ "sha256": "7464c3e6fa9a95fb9618d9b7b3117693cf08b972042a880dd23eb25c9d8f1fba"+ },+ "v216-header.c": {+ "project": "mori://confluentinc/librdkafka",+ "version": "2.16.0",+ "project_relative_path": "src/rdkafka_header.c",+ "artifact_uri": "source-artifact URI pending",+ "path": "dist-compatibility/owned-fixture-checkpoint/v216-header.c",+ "sha256": "c82403e08653d0d19b39b5740a9477a838575361eab3c83451effaa809bf2175"+ }+ },+ "method": "Inspect exact missed HPC spans and all repository callers; verify native constructor/dump/header guarantees independently against released 2.15.0 and 2.16.0 source. Arbitrary rebalance errors remain open because the native header explicitly permits them."+ },+ {+ "status": "Eleven exact source-backed keys; producer marshalling exception continuation remains open",+ "baseline_fingerprint": "4a4d041b2c440f9ee9e53ae0291b07835afa4cbb4677ed722447d57e6d906606",+ "keys": [+ "Kafka.Consumer:547:ExpBox False",+ "Kafka.Consumer:547:ExpBox True",+ "Kafka.Consumer:319:ExpBox False",+ "Kafka.Consumer.Callbacks:75:ExpBox False",+ "Kafka.Internal.RdKafka:1492:ExpBox False",+ "Kafka.Internal.RdKafka:1416:ExpBox False",+ "Kafka.Internal.Setup:228:ExpBox False",+ "Kafka.Internal.Shared:59:ExpBox False",+ "Kafka.Internal.Shared:52:BinBox GuardBinBox False",+ "Kafka.Metadata:255:ExpBox False",+ "Kafka.Metadata:149:ExpBox False"+ ],+ "proofs": [+ {+ "key": "Kafka.Consumer:547:ExpBox False",+ "source": "src/Kafka/Consumer.hs",+ "source_sha256": "170ea8259f8b0279db807c48799f323a268e7636efcbc929ade003cd4e4bb70a",+ "rationale": "The private subscription decoder fallback expects partition-specific subscriptions. Public Subscription contains only a Set TopicName, and Consumer.subscribe constructs exactly one partition -1 entry per unique topic. Released native subscribe copies this list; subscription returns the saved topic list. Empty subscriptions yield no entry and every nonempty public entry takes SubscribedPartitionsAll. Manual assignments use a distinct API and do not change subscription. Specific partition decoding is therefore unavailable through this public subscription path; native queries and their errors are still exercised."+ },+ {+ "key": "Kafka.Consumer:547:ExpBox True",+ "source": "src/Kafka/Consumer.hs",+ "source_sha256": "170ea8259f8b0279db807c48799f323a268e7636efcbc929ade003cd4e4bb70a",+ "rationale": "The entire private SubscribedPartitions fallback has the same source-proven domain restriction as its ps argument: all public subscription entries are unique topic/-1 pairs. Both multiple-topic and regex subscriptions observe the exact All representation; this is not a general exclusion of subscription IO or decoding."+ },+ {+ "key": "Kafka.Consumer:319:ExpBox False",+ "source": "src/Kafka/Consumer.hs",+ "source_sha256": "170ea8259f8b0279db807c48799f323a268e7636efcbc929ade003cd4e4bb70a",+ "rationale": "Only the nullPtr argument at columns 50-68 is unforced. GHC 9.12.4 Storable (Ptr a) expands STORABLE with sizeOf _ = SIZEOF_HSPTR. Pointer size, negative/overflow bounds and the native allocation boundary are exercised; the ignored pointer value cannot acquire a hit."+ },+ {+ "key": "Kafka.Consumer.Callbacks:75:ExpBox False",+ "source": "src/Kafka/Consumer/Callbacks.hs",+ "source_sha256": "7e993c821435554f7d705ad0369ce4dab3c561216c1966baf29cf967e310e362",+ "rationale": "Only the unit literal at columns 23-24 in return () is ignored. The Nothing queue branch executes in synchronous callback mode; IO sequencing does not demand the unit value. No queue acquisition, forwarding or release action is excluded."+ },+ {+ "key": "Kafka.Internal.RdKafka:1492:ExpBox False",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf",+ "rationale": "Only the unit value in Right () is lazy and discarded by current private callers, which distinguish Left from Right but never force the successful payload. Native codes and success/error branches execute; the value-level tick is not a missing error conversion."+ },+ {+ "key": "Kafka.Internal.RdKafka:1416:ExpBox False",+ "source": "src/Kafka/Internal/RdKafka.chs",+ "source_sha256": "869947169916ead0bf7254a9ecceeecbe9ec8600be80d29e724c2dc1e53c1fcf",+ "rationale": "Only the errMsg tuple field is unforced. Topic.runRequest pattern-matches Left (name, err, _) and propagates the native error code; no public result exposes that private String. The native error-string read, tuple construction, response-name validation and owned-event cleanup are not exempted."+ },+ {+ "key": "Kafka.Internal.Setup:228:ExpBox False",+ "source": "src/Kafka/Internal/Setup.hs",+ "source_sha256": "69ef4227adf311f7dee3ec283825d42c1e3a2561df6f66bab29d2abb8b446188",+ "rationale": "Only the success unit in pure () at columns 22-23 is unforced; validation and both NUL failure predicates run. Sequencing this IO action ignores its result."+ },+ {+ "key": "Kafka.Internal.Shared:59:ExpBox False",+ "source": "src/Kafka/Internal/Shared.hs",+ "source_sha256": "fb9eb7755af2a3da0db73b665a0e09a7c6ee3b1381aaac9e658a78f1ebd7e100",+ "rationale": "The private pollEvents helper has exactly one production caller, Producer.produceMessage', which supplies Just (Timeout 0). It is hidden by Cabal and is not re-exported by the producer API. Only the Nothing default literal 0 is unavailable to public calls; actual native poll and timeout extraction execute."+ },+ {+ "key": "Kafka.Internal.Shared:52:BinBox GuardBinBox False",+ "source": "src/Kafka/Internal/Shared.hs",+ "source_sha256": "fb9eb7755af2a3da0db73b665a0e09a7c6ee3b1381aaac9e658a78f1ebd7e100",+ "rationale": "This is the impossible False branch of Prelude.otherwise after both SASL string validations. The otherwise body and both invalid credential guards execute. The constant guard cannot evaluate False."+ },+ {+ "key": "Kafka.Metadata:255:ExpBox False",+ "source": "src/Kafka/Metadata.hs",+ "source_sha256": "abcfd0962c104901916c4b4a456b4e99b9905ffd430b74b4e2244e5a2744512f",+ "rationale": "Only the ignored unit at columns 40-41 in the Left acquisition cleanup is unforced. A failed acquisition has no owned ForeignPtr; its error is propagated. Successful native results still finalize explicitly and are covered by counted/cancelled native acquisitions."+ },+ {+ "key": "Kafka.Metadata:149:ExpBox False",+ "source": "src/Kafka/Metadata.hs",+ "source_sha256": "abcfd0962c104901916c4b4a456b4e99b9905ffd430b74b4e2244e5a2744512f",+ "rationale": "The two ticks are the lazy unit literal and const () thunk in a failed topic-handle acquisition cleanup. bracket sequences return (const () err) without demanding its value. The failed acquire/error propagation and the successful native-topic destroy remain real tested effects."+ }+ ],+ "source_artifacts": {+ "ghc9124-Marshal-Array.hs": {+ "project": "mori://ghc/ghc",+ "version": "9.12.4",+ "artifact_uri": "source-artifact URI pending",+ "project_relative_path": "libraries/ghc-internal/src/GHC/Internal/Foreign/Marshal/Array.hs",+ "path": "dist-compatibility/expanded-source9/ghc9124-Marshal-Array.hs",+ "sha256": "0a0cb7e36925c5332e5fb4dda03ad11f10b1ffa0e96d71e56de657d32f52216d"+ },+ "ghc9124-Storable.hs": {+ "project": "mori://ghc/ghc",+ "version": "9.12.4",+ "artifact_uri": "source-artifact URI pending",+ "project_relative_path": "libraries/ghc-internal/src/GHC/Internal/Foreign/Storable.hs",+ "path": "dist-compatibility/expanded-source9/ghc9124-Storable.hs",+ "sha256": "dda27f3c55cda6fbce4d44c127b6b26f5f18aa1e8b7ade6510e51cd4eec9e9cd"+ },+ "v215-subscription.c": {+ "project": "mori://confluentinc/librdkafka",+ "version": "2.15.0",+ "artifact_uri": "source-artifact URI pending",+ "project_relative_path": "src/rdkafka_subscription.c",+ "path": "dist-compatibility/expanded-source9/v215-subscription.c",+ "sha256": "8a9134c343f9d7bf40eaaf00d19caa6ca505afa98bdf739763a4f7ba2b4c7f68"+ },+ "v216-subscription.c": {+ "project": "mori://confluentinc/librdkafka",+ "version": "2.16.0",+ "artifact_uri": "source-artifact URI pending",+ "project_relative_path": "src/rdkafka_subscription.c",+ "path": "dist-compatibility/expanded-source9/v216-subscription.c",+ "sha256": "8a9134c343f9d7bf40eaaf00d19caa6ca505afa98bdf739763a4f7ba2b4c7f68"+ }+ },+ "remaining": "Current mapped evidence covers the cooperative originless-error branch. Two Producer.hs:204 exception-continuation ticks remain open. Tagged GHC newAlignedPinnedByteArray# raises HeapOverflow synchronously when allocatePinned returns NULL, so this cannot be dismissed as masked asynchronous allocation-counter exhaustion. A meaningful pinned-allocation failure control remains work; no exemption or simulated coverage is accepted."+ }+ ]+}
+ docs/testing/deferred-validation-snapshot.json view
@@ -0,0 +1,686 @@+{+ "scope": "Deferred comprehensive qualification; primary release scope is ADR-27",+ "source_revision": "b740b725126bce2fbf8bf71c2e4da1cc1861e403",+ "fingerprint": "060dade4e8a9c764dabee54df3030fa6d857be3ea1404a2bc680a45ddadd5e4e",+ "registered_passed": 786,+ "nonthreaded_passed": 4,+ "handwritten_native_wrapper_ticks": 2750,+ "tested_rows": 146,+ "open_rows": [+ {+ "id": "API-Kafka-Consumer-assign",+ "symbols": [+ "Kafka.Consumer.assign"+ ],+ "owner": 14,+ "behavior": "Subscription/manual assignment replaces the exact partition set and preserves records",+ "inputs": "empty, one/multiple partitions, invalid partition, repeated/reassignment",+ "expected": "Exact assignment and no record loss/duplication",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [],+ "status": "unimplemented",+ "follow_up_owner": 16,+ "handoff": "Reconcile existing current-source tests first; this historical open status is not a statement that no test exists."+ },+ {+ "id": "API-Kafka-Consumer-assignmentLost",+ "symbols": [+ "Kafka.Consumer.assignmentLost"+ ],+ "owner": 15,+ "behavior": "Report group ownership loss",+ "inputs": "healthy assignment plus actual group eviction/loss; observe the True value in RebalanceBeforeRevoke before native unassignment clears it",+ "expected": "False when valid; True on lost assignment",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [],+ "status": "unimplemented",+ "rationale": "EP-14 verifies healthy False results. The accepted MasterPlan and EP-15 M1 own actual group eviction/handoff behavior; static-member fatal fencing alone does not guarantee an assignment-loss callback. The True case remains open under EP-15.",+ "follow_up_owner": 18,+ "handoff": "Reconcile existing current-source tests first; this historical open status is not a statement that no test exists."+ },+ {+ "id": "API-Kafka-Consumer-commitAllOffsets",+ "symbols": [+ "Kafka.Consumer.commitAllOffsets"+ ],+ "owner": 14,+ "behavior": "Commit consumed/stored offsets according to mode",+ "inputs": "no offsets, multiple records/partitions, sync/async, broker failure",+ "expected": "Exact committed offsets and reported errors",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [],+ "status": "unimplemented",+ "follow_up_owner": 16,+ "handoff": "Reconcile existing current-source tests first; this historical open status is not a statement that no test exists."+ },+ {+ "id": "API-Kafka-Consumer-commitOffsetMessage",+ "symbols": [+ "Kafka.Consumer.commitOffsetMessage"+ ],+ "owner": 14,+ "behavior": "Commit one record at its next offset",+ "inputs": "multiple partitions and sync/async",+ "expected": "Only requested record partition advances to offset + 1",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [],+ "status": "unimplemented",+ "follow_up_owner": 16,+ "handoff": "Reconcile existing current-source tests first; this historical open status is not a statement that no test exists."+ },+ {+ "id": "API-Kafka-Consumer-pollMessage",+ "symbols": [+ "Kafka.Consumer.pollMessage"+ ],+ "owner": 14,+ "behavior": "Return complete records and distinguish idle/error outcomes",+ "inputs": "null key/value, headers, timestamp, offset, EOF, timeout, fatal and broker failure",+ "expected": "Exact topic/partition/offset/key/value/header/time; errors preserved",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [],+ "status": "unimplemented",+ "follow_up_owner": 16,+ "handoff": "Reconcile existing current-source tests first; this historical open status is not a statement that no test exists."+ },+ {+ "id": "API-Kafka-Consumer-pollMessageAttributed",+ "symbols": [+ "Kafka.Consumer.pollMessageAttributed"+ ],+ "owner": 14,+ "behavior": "Return record or error with native attribution",+ "inputs": "ordinary record; timeout; partition EOF; fatal/partition error",+ "expected": "Attribution fields preserved where provided and absent otherwise",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [],+ "status": "unimplemented",+ "follow_up_owner": 16,+ "handoff": "Reconcile existing current-source tests first; this historical open status is not a statement that no test exists."+ },+ {+ "id": "API-Kafka-Consumer-pollMessageBatch",+ "symbols": [+ "Kafka.Consumer.pollMessageBatch"+ ],+ "owner": 14,+ "behavior": "Return at most requested complete records",+ "inputs": "zero/one/large batch, empty topic, partial batch, partition/error events",+ "expected": "Exact count, identity, order and per-element errors",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [],+ "status": "unimplemented",+ "follow_up_owner": 16,+ "handoff": "Reconcile existing current-source tests first; this historical open status is not a statement that no test exists."+ },+ {+ "id": "API-Kafka-Consumer-position",+ "symbols": [+ "Kafka.Consumer.position"+ ],+ "owner": 14,+ "behavior": "Fetch next consume position",+ "inputs": "before/after poll, explicit seek, missing partition",+ "expected": "Exact next offsets and error conventions",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [],+ "status": "unimplemented",+ "follow_up_owner": 16,+ "handoff": "Reconcile existing current-source tests first; this historical open status is not a statement that no test exists."+ },+ {+ "id": "API-Kafka-Consumer-setConsumerQueueIOEvent",+ "symbols": [+ "Kafka.Consumer.setConsumerQueueIOEvent"+ ],+ "owner": 14,+ "behavior": "Notify readable queue transitions and disable safely",+ "inputs": "pending-before-enable, empty-to-nonempty, rearm, disable, close and destroy",+ "expected": "Descriptor receives expected wakeup; queued records preserved; no notification after disable",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [],+ "status": "unimplemented",+ "follow_up_owner": 16,+ "handoff": "Reconcile existing current-source tests first; this historical open status is not a statement that no test exists."+ },+ {+ "id": "API-Kafka-Consumer-setSaslCredentials",+ "symbols": [+ "Kafka.Consumer.setSaslCredentials"+ ],+ "owner": 15,+ "behavior": "Replace credentials used by live authentication",+ "inputs": "valid, invalid and replacement credentials against isolated SASL broker",+ "expected": "Authenticated broker access succeeds/fails for actual credentials",+ "modes": "producer and consumer with actual SASL authentication/authorization",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [],+ "status": "unimplemented",+ "follow_up_owner": 19,+ "handoff": "Reconcile existing current-source tests first; this historical open status is not a statement that no test exists."+ },+ {+ "id": "API-Kafka-Consumer-storeOffsetMessage",+ "symbols": [+ "Kafka.Consumer.storeOffsetMessage"+ ],+ "owner": 14,+ "behavior": "Store next offset for one record",+ "inputs": "noAutoOffsetStore; multiple records/partitions; failed commit",+ "expected": "Exact stored-then-committed offset + 1; no unrelated advancement",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [],+ "status": "unimplemented",+ "follow_up_owner": 16,+ "handoff": "Reconcile existing current-source tests first; this historical open status is not a statement that no test exists."+ },+ {+ "id": "API-Kafka-Consumer-storeOffsets",+ "symbols": [+ "Kafka.Consumer.storeOffsets"+ ],+ "owner": 14,+ "behavior": "Store explicit per-partition offsets",+ "inputs": "empty, valid, invalid and mixed partitions",+ "expected": "Exact later committed offsets; surfaced per-partition errors",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [],+ "status": "unimplemented",+ "follow_up_owner": 16,+ "handoff": "Reconcile existing current-source tests first; this historical open status is not a statement that no test exists."+ },+ {+ "id": "API-Kafka-Consumer-subscription",+ "symbols": [+ "Kafka.Consumer.subscription"+ ],+ "owner": 14,+ "behavior": "Return current subscribed topic set",+ "inputs": "empty, one/multiple topics and patterns",+ "expected": "Exact requested set and matching topic behavior",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [],+ "status": "unimplemented",+ "follow_up_owner": 16,+ "handoff": "Reconcile existing current-source tests first; this historical open status is not a statement that no test exists."+ },+ {+ "id": "API-Kafka-Metadata-allConsumerGroupsInfo",+ "symbols": [+ "Kafka.Metadata.allConsumerGroupsInfo"+ ],+ "owner": 14,+ "behavior": "allConsumerGroupsInfo preserves metadata identity and native per-entity errors",+ "inputs": "empty, existing, missing and invalid topics/groups/partitions; time bounds; unavailable broker; deprecated aliases where present",+ "expected": "Exact broker/topic/partition/group identities, offsets and error details; no success-only or length-only assertion",+ "modes": "all supported modes",+ "ownership": "Temporary topic/metadata/group-list/partition-list handles released after decoding on success and error",+ "tests": [],+ "status": "unimplemented",+ "follow_up_owner": 16,+ "handoff": "Reconcile existing current-source tests first; this historical open status is not a statement that no test exists."+ },+ {+ "id": "API-Kafka-Metadata-allTopicsMetadata",+ "symbols": [+ "Kafka.Metadata.allTopicsMetadata"+ ],+ "owner": 14,+ "behavior": "allTopicsMetadata preserves metadata identity and native per-entity errors",+ "inputs": "empty, existing, missing and invalid topics/groups/partitions; time bounds; unavailable broker; deprecated aliases where present",+ "expected": "Exact broker/topic/partition/group identities, offsets and error details; no success-only or length-only assertion",+ "modes": "all supported modes",+ "ownership": "Temporary topic/metadata/group-list/partition-list handles released after decoding on success and error",+ "tests": [],+ "status": "unimplemented",+ "follow_up_owner": 16,+ "handoff": "Reconcile existing current-source tests first; this historical open status is not a statement that no test exists."+ },+ {+ "id": "API-Kafka-Metadata-consumerGroupInfo",+ "symbols": [+ "Kafka.Metadata.consumerGroupInfo"+ ],+ "owner": 14,+ "behavior": "consumerGroupInfo preserves metadata identity and native per-entity errors",+ "inputs": "empty, existing, missing and invalid topics/groups/partitions; time bounds; unavailable broker; deprecated aliases where present",+ "expected": "Exact broker/topic/partition/group identities, offsets and error details; no success-only or length-only assertion",+ "modes": "all supported modes",+ "ownership": "Temporary topic/metadata/group-list/partition-list handles released after decoding on success and error",+ "tests": [],+ "status": "unimplemented",+ "follow_up_owner": 16,+ "handoff": "Reconcile existing current-source tests first; this historical open status is not a statement that no test exists."+ },+ {+ "id": "API-Kafka-Metadata-offsetsForTime",+ "symbols": [+ "Kafka.Metadata.offsetsForTime"+ ],+ "owner": 14,+ "behavior": "offsetsForTime preserves metadata identity and native per-entity errors",+ "inputs": "empty, existing, missing and invalid topics/groups/partitions; time bounds; unavailable broker; deprecated aliases where present",+ "expected": "Exact broker/topic/partition/group identities, offsets and error details; no success-only or length-only assertion",+ "modes": "all supported modes",+ "ownership": "Temporary topic/metadata/group-list/partition-list handles released after decoding on success and error",+ "tests": [],+ "status": "unimplemented",+ "follow_up_owner": 16,+ "handoff": "Reconcile existing current-source tests first; this historical open status is not a statement that no test exists."+ },+ {+ "id": "API-Kafka-Metadata-offsetsForTime-prime",+ "symbols": [+ "Kafka.Metadata.offsetsForTime'"+ ],+ "owner": 14,+ "behavior": "offsetsForTime' preserves metadata identity and native per-entity errors",+ "inputs": "empty, existing, missing and invalid topics/groups/partitions; time bounds; unavailable broker; deprecated aliases where present",+ "expected": "Exact broker/topic/partition/group identities, offsets and error details; no success-only or length-only assertion",+ "modes": "all supported modes",+ "ownership": "Temporary topic/metadata/group-list/partition-list handles released after decoding on success and error",+ "tests": [],+ "status": "unimplemented",+ "follow_up_owner": 16,+ "handoff": "Reconcile existing current-source tests first; this historical open status is not a statement that no test exists."+ },+ {+ "id": "API-Kafka-Metadata-partitionWatermarkOffsets",+ "symbols": [+ "Kafka.Metadata.partitionWatermarkOffsets"+ ],+ "owner": 14,+ "behavior": "partitionWatermarkOffsets preserves metadata identity and native per-entity errors",+ "inputs": "empty, existing, missing and invalid topics/groups/partitions; time bounds; unavailable broker; deprecated aliases where present",+ "expected": "Exact broker/topic/partition/group identities, offsets and error details; no success-only or length-only assertion",+ "modes": "all supported modes",+ "ownership": "Temporary topic/metadata/group-list/partition-list handles released after decoding on success and error",+ "tests": [],+ "status": "unimplemented",+ "follow_up_owner": 16,+ "handoff": "Reconcile existing current-source tests first; this historical open status is not a statement that no test exists."+ },+ {+ "id": "API-Kafka-Metadata-topicMetadata",+ "symbols": [+ "Kafka.Metadata.topicMetadata"+ ],+ "owner": 14,+ "behavior": "topicMetadata preserves metadata identity and native per-entity errors",+ "inputs": "empty, existing, missing and invalid topics/groups/partitions; time bounds; unavailable broker; deprecated aliases where present",+ "expected": "Exact broker/topic/partition/group identities, offsets and error details; no success-only or length-only assertion",+ "modes": "all supported modes",+ "ownership": "Temporary topic/metadata/group-list/partition-list handles released after decoding on success and error",+ "tests": [],+ "status": "unimplemented",+ "follow_up_owner": 16,+ "handoff": "Reconcile existing current-source tests first; this historical open status is not a statement that no test exists."+ },+ {+ "id": "API-Kafka-Metadata-topicOffsetsForTime",+ "symbols": [+ "Kafka.Metadata.topicOffsetsForTime"+ ],+ "owner": 14,+ "behavior": "topicOffsetsForTime preserves metadata identity and native per-entity errors",+ "inputs": "empty, existing, missing and invalid topics/groups/partitions; time bounds; unavailable broker; deprecated aliases where present",+ "expected": "Exact broker/topic/partition/group identities, offsets and error details; no success-only or length-only assertion",+ "modes": "all supported modes",+ "ownership": "Temporary topic/metadata/group-list/partition-list handles released after decoding on success and error",+ "tests": [],+ "status": "unimplemented",+ "follow_up_owner": 16,+ "handoff": "Reconcile existing current-source tests first; this historical open status is not a statement that no test exists."+ },+ {+ "id": "API-Kafka-Metadata-watermarkOffsets",+ "symbols": [+ "Kafka.Metadata.watermarkOffsets"+ ],+ "owner": 14,+ "behavior": "watermarkOffsets preserves metadata identity and native per-entity errors",+ "inputs": "empty, existing, missing and invalid topics/groups/partitions; time bounds; unavailable broker; deprecated aliases where present",+ "expected": "Exact broker/topic/partition/group identities, offsets and error details; no success-only or length-only assertion",+ "modes": "all supported modes",+ "ownership": "Temporary topic/metadata/group-list/partition-list handles released after decoding on success and error",+ "tests": [],+ "status": "unimplemented",+ "follow_up_owner": 16,+ "handoff": "Reconcile existing current-source tests first; this historical open status is not a statement that no test exists."+ },+ {+ "id": "API-Kafka-Metadata-watermarkOffsets-prime",+ "symbols": [+ "Kafka.Metadata.watermarkOffsets'"+ ],+ "owner": 14,+ "behavior": "watermarkOffsets' preserves metadata identity and native per-entity errors",+ "inputs": "empty, existing, missing and invalid topics/groups/partitions; time bounds; unavailable broker; deprecated aliases where present",+ "expected": "Exact broker/topic/partition/group identities, offsets and error details; no success-only or length-only assertion",+ "modes": "all supported modes",+ "ownership": "Temporary topic/metadata/group-list/partition-list handles released after decoding on success and error",+ "tests": [],+ "status": "unimplemented",+ "follow_up_owner": 16,+ "handoff": "Reconcile existing current-source tests first; this historical open status is not a statement that no test exists."+ },+ {+ "id": "API-Kafka-Producer-Types-ImmediateError",+ "symbols": [+ "Kafka.Producer.Types.ImmediateError"+ ],+ "owner": 14,+ "behavior": "ImmediateError exposes its documented constructors, record selectors and typeclass laws",+ "inputs": "Every exported constructor/member in the compiler export inventory; generated boundary and ordinary field values",+ "expected": "Construction/selection round trips; declared equality/order/show/enum/functor/traversal instances obey their documented laws",+ "modes": "all supported modes",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [],+ "status": "unimplemented",+ "follow_up_owner": 16,+ "handoff": "Reconcile existing current-source tests first; this historical open status is not a statement that no test exists."+ },+ {+ "id": "API-Kafka-Producer-setSaslCredentials",+ "symbols": [+ "Kafka.Producer.setSaslCredentials"+ ],+ "owner": 15,+ "behavior": "Replace credentials used by live authentication",+ "inputs": "valid, invalid and replacement credentials against isolated SASL broker",+ "expected": "Authenticated broker access succeeds/fails for actual credentials",+ "modes": "producer and consumer with actual SASL authentication/authorization",+ "ownership": "Haskell values retain their public constructors, fields and instances; native inputs are borrowed for the call",+ "tests": [],+ "status": "unimplemented",+ "follow_up_owner": 19,+ "handoff": "Reconcile existing current-source tests first; this historical open status is not a statement that no test exists."+ },+ {+ "id": "OWN-partition-list",+ "symbols": [],+ "owner": 14,+ "behavior": "Partition list conversion and native error decoding",+ "inputs": "success, injected failure, interruption, repeated calls and boundaries",+ "expected": "Exact behavior or allocation balance with effective negative controls",+ "modes": "all supported modes",+ "ownership": "Every temporary list freed; per-element errors never silently erased",+ "tests": [],+ "status": "unimplemented",+ "follow_up_owner": 16,+ "handoff": "Reconcile existing current-source tests first; this historical open status is not a statement that no test exists."+ },+ {+ "id": "ENV-primary",+ "symbols": [],+ "owner": 15,+ "behavior": "Primary Darwin/Redpanda behavior and native diagnostics",+ "inputs": "success, injected failure, interruption, repeated calls and boundaries",+ "expected": "Exact behavior or allocation balance with effective negative controls",+ "modes": "all supported modes",+ "ownership": "Exact compiler/native/broker tuple, source fingerprint and native allocation positive controls",+ "tests": [],+ "status": "unimplemented",+ "follow_up_owner": 20,+ "handoff": "Reconcile existing current-source tests first; this historical open status is not a statement that no test exists."+ },+ {+ "id": "ENV-linux",+ "symbols": [],+ "owner": 15,+ "behavior": "Linux build, representative broker behavior and native diagnostics",+ "inputs": "success, injected failure, interruption, repeated calls and boundaries",+ "expected": "Exact behavior or allocation balance with effective negative controls",+ "modes": "all supported modes",+ "ownership": "Actual Linux execution including leak/invalid-access positive controls",+ "tests": [],+ "status": "unimplemented",+ "follow_up_owner": 17,+ "handoff": "Reconcile existing current-source tests first; this historical open status is not a statement that no test exists."+ },+ {+ "id": "ENV-kafka",+ "symbols": [],+ "owner": 15,+ "behavior": "Apache Kafka security, transactions, leader failover and broker outages",+ "inputs": "success, injected failure, interruption, repeated calls and boundaries",+ "expected": "Exact behavior or allocation balance with effective negative controls",+ "modes": "all supported modes",+ "ownership": "Run-owned multi-broker/security fixtures restored after interruption; exact recovered record and group state",+ "tests": [],+ "status": "unimplemented",+ "follow_up_owner": 18,+ "handoff": "Reconcile existing current-source tests first; this historical open status is not a statement that no test exists."+ },+ {+ "id": "ENV-newer",+ "symbols": [],+ "owner": 15,+ "behavior": "Newer compatible released compiler/native version",+ "inputs": "success, injected failure, interruption, repeated calls and boundaries",+ "expected": "Exact behavior or allocation balance with effective negative controls",+ "modes": "all supported modes",+ "ownership": "Registry/tag-verified concrete compatible tuple; actual build and representative execution",+ "tests": [],+ "status": "unimplemented",+ "follow_up_owner": 17,+ "handoff": "Reconcile existing current-source tests first; this historical open status is not a statement that no test exists."+ },+ {+ "id": "OWN-source-coverage",+ "symbols": [],+ "owner": 14,+ "behavior": "Every unexercised hand-written Haskell tick/function has a contract-specific test or a source-backed unreachable/inapplicable explanation",+ "inputs": "all source-attributed misses in the combined HPC report",+ "expected": "No unexplained miss and all critical error/ownership branches exercised",+ "modes": "normal optimized and instrumented builds",+ "ownership": "Coverage does not prove C allocation balance; dedicated ownership controls remain required",+ "tests": [],+ "status": "unimplemented",+ "follow_up_owner": 16,+ "handoff": "Reconcile existing current-source tests first; this historical open status is not a statement that no test exists."+ },+ {+ "id": "OWN-binding-coverage",+ "symbols": [],+ "owner": 14,+ "behavior": "Hand-written c2hs wrapper coverage is source-mapped separately from generated marshalling; every missing hand-written tick/function is classified",+ "inputs": "all source-attributed misses in the combined HPC report",+ "expected": "No unexplained miss and all critical error/ownership branches exercised",+ "modes": "normal optimized and instrumented builds",+ "ownership": "Coverage does not prove C allocation balance; dedicated ownership controls remain required",+ "tests": [],+ "status": "unimplemented",+ "follow_up_owner": 16,+ "handoff": "Reconcile existing current-source tests first; this historical open status is not a statement that no test exists."+ },+ {+ "id": "ENV-topic-configuration-policy",+ "symbols": [],+ "owner": 15,+ "behavior": "Unrecognized topic configuration follows each actual broker fixture policy",+ "inputs": "primary Redpanda ignore policy and Apache Kafka reject policy, declared explicitly for each compatibility tuple",+ "expected": "The same named native-argument/effective-property test passes under both actual declared broker policies",+ "modes": "required broker compatibility tuples",+ "ownership": "Configuration forwarding and native error resources retain EP-8 scopes",+ "tests": [],+ "status": "unimplemented",+ "follow_up_owner": 18,+ "handoff": "Reconcile existing current-source tests first; this historical open status is not a statement that no test exists."+ },+ {+ "id": "ENV-producer-native-headers",+ "symbols": [],+ "owner": 15,+ "behavior": "Native internal header allocations survive the required lifetime and are released on every message path",+ "inputs": "success, immediate queue-full/oversize rejection, observed cancellation and queued/in-flight purge under native heap diagnostics",+ "expected": "Leak/invalid-access diagnostic detects an intentional native cleanup mutation and finds no unexplained candidate allocation or access defects",+ "modes": "required native diagnostic compatibility tuple",+ "ownership": "librdkafka owns header objects created inside produceva; Haskell supplies scoped borrowed name/value buffers",+ "tests": [],+ "status": "unimplemented",+ "follow_up_owner": 17,+ "handoff": "Reconcile existing current-source tests first; this historical open status is not a statement that no test exists."+ },+ {+ "id": "API-Kafka-Consumer-seek",+ "symbols": [+ "Kafka.Consumer.seek"+ ],+ "owner": 14,+ "behavior": "Deprecated seek retains its documented replay and error behavior",+ "inputs": "valid/invalid partitions and offset sentinels; synchronous/asynchronous callback modes; investigate saved intermittent synchronous State failure",+ "expected": "Exact next-record offsets after successful seeks and exact native errors for unsupported state; saved failure must be explained rather than erased by successful reruns",+ "modes": "async and sync callback modes",+ "ownership": "Temporary managed topic handles and their native client remain alive through native seeking; callback-capable finalization belongs to EP-11",+ "tests": [],+ "status": "unimplemented",+ "follow_up_owner": 16,+ "handoff": "Reconcile existing current-source tests first; this historical open status is not a statement that no test exists."+ }+ ],+ "unclassified_handwritten_ticks": 192,+ "unclassified_handwritten_keys": {+ "Kafka.Consumer:900:ExpBox False": 1,+ "Kafka.Consumer:866:ExpBox False": 1,+ "Kafka.Consumer:870:ExpBox False": 1,+ "Kafka.Consumer:827:ExpBox False": 1,+ "Kafka.Consumer:776:ExpBox False": 3,+ "Kafka.Consumer:879:ExpBox False": 1,+ "Kafka.Consumer:883:ExpBox False": 1,+ "Kafka.Consumer:621:ExpBox False": 3,+ "Kafka.Consumer:621:BinBox QualBinBox False": 1,+ "Kafka.Consumer:602:ExpBox False": 2,+ "Kafka.Consumer:585:ExpBox False": 2,+ "Kafka.Consumer:585:ExpBox True": 1,+ "Kafka.Consumer:545:ExpBox False": 1,+ "Kafka.Consumer:545:ExpBox True": 1,+ "Kafka.Consumer:539:ExpBox False": 1,+ "Kafka.Consumer:765:BinBox GuardBinBox False": 1,+ "Kafka.Consumer:524:ExpBox False": 1,+ "Kafka.Consumer:395:ExpBox False": 1,+ "Kafka.Consumer:329:ExpBox False": 1,+ "Kafka.Consumer:317:ExpBox False": 1,+ "Kafka.Consumer:319:ExpBox False": 1,+ "Kafka.Consumer:320:ExpBox False": 1,+ "Kafka.Consumer:322:BinBox GuardBinBox False": 1,+ "Kafka.Consumer:163:BinBox GuardBinBox False": 1,+ "Kafka.Consumer:182:ExpBox False": 2,+ "Kafka.Consumer:209:ExpBox False": 5,+ "Kafka.Consumer:210:ExpBox False": 3,+ "Kafka.Consumer:208:ExpBox True": 1,+ "Kafka.Consumer:139:ExpBox False": 2,+ "Kafka.Consumer:140:ExpBox False": 1,+ "Kafka.Consumer.Callbacks:75:ExpBox False": 1,+ "Kafka.Consumer.Callbacks:75:ExpBox True": 1,+ "Kafka.Consumer.Callbacks:91:ExpBox False": 1,+ "Kafka.Consumer.Callbacks:95:ExpBox False": 2,+ "Kafka.Consumer.Callbacks:100:ExpBox False": 1,+ "Kafka.Consumer.Callbacks:110:ExpBox False": 1,+ "Kafka.Consumer.Callbacks:112:ExpBox False": 1,+ "Kafka.Consumer.Callbacks:116:ExpBox False": 2,+ "Kafka.Consumer.Callbacks:118:ExpBox False": 1,+ "Kafka.Consumer.Callbacks:119:ExpBox False": 5,+ "Kafka.Consumer.Callbacks:119:ExpBox True": 1,+ "Kafka.Consumer.Callbacks:53:ExpBox False": 4,+ "Kafka.Consumer.Callbacks:48:ExpBox False": 1,+ "Kafka.Consumer.Convert:216:BinBox CondBinBox False": 1,+ "Kafka.Consumer.Convert:216:ExpBox True": 1,+ "Kafka.Consumer.Convert:173:ExpBox False": 1,+ "Kafka.Consumer.Convert:170:ExpBox True": 1,+ "Kafka.Consumer.Convert:80:BinBox GuardBinBox True": 1,+ "Kafka.Consumer.Convert:80:ExpBox True": 1,+ "Kafka.Consumer.Convert:82:BinBox GuardBinBox True": 1,+ "Kafka.Consumer.Convert:82:ExpBox True": 1,+ "Kafka.Consumer.Convert:84:BinBox GuardBinBox False": 1,+ "Kafka.Dump:82:ExpBox False": 1,+ "Kafka.Dump:82:ExpBox True": 1,+ "Kafka.Internal.RdKafka:1527:ExpBox False": 1,+ "Kafka.Internal.RdKafka:1523:ExpBox False": 1,+ "Kafka.Internal.RdKafka:1492:ExpBox False": 1,+ "Kafka.Internal.RdKafka:1444:BinBox CondBinBox True": 1,+ "Kafka.Internal.RdKafka:1445:ExpBox False": 6,+ "Kafka.Internal.RdKafka:1445:ExpBox True": 1,+ "Kafka.Internal.RdKafka:1416:ExpBox False": 1,+ "Kafka.Internal.RdKafka:1166:BinBox CondBinBox False": 1,+ "Kafka.Internal.RdKafka:1168:ExpBox False": 4,+ "Kafka.Internal.RdKafka:1168:ExpBox True": 1,+ "Kafka.Internal.RdKafka:644:BinBox CondBinBox True": 1,+ "Kafka.Internal.RdKafka:644:ExpBox False": 1,+ "Kafka.Internal.RdKafka:644:ExpBox True": 1,+ "Kafka.Internal.RdKafka:474:ExpBox False": 1,+ "Kafka.Internal.RdKafka:459:ExpBox False": 1,+ "Kafka.Internal.RdKafka:427:ExpBox False": 1,+ "Kafka.Internal.RdKafka:382:ExpBox False": 1,+ "Kafka.Internal.RdKafka:684:ExpBox False": 2,+ "Kafka.Internal.RdKafka:684:ExpBox True": 1,+ "Kafka.Internal.RdKafka:323:ExpBox False": 1,+ "Kafka.Internal.RdKafka:1127:ExpBox False": 1,+ "Kafka.Internal.RdKafka:792:ExpBox False": 1,+ "Kafka.Internal.RdKafka:177:ExpBox False": 1,+ "Kafka.Internal.RdKafka:148:ExpBox False": 1,+ "Kafka.Internal.RdKafka:149:ExpBox False": 1,+ "Kafka.Internal.RdKafka:150:ExpBox False": 1,+ "Kafka.Internal.Setup:228:BinBox GuardBinBox False": 1,+ "Kafka.Internal.Setup:228:ExpBox False": 1,+ "Kafka.Internal.Setup:194:ExpBox False": 1,+ "Kafka.Internal.Setup:129:ExpBox False": 1,+ "Kafka.Internal.Setup:134:ExpBox False": 14,+ "Kafka.Internal.Shared:159:BinBox GuardBinBox False": 1,+ "Kafka.Internal.Shared:171:BinBox GuardBinBox False": 1,+ "Kafka.Internal.Shared:100:ExpBox False": 4,+ "Kafka.Internal.Shared:100:TopLevelBox [\"maybeToLeft\"]": 1,+ "Kafka.Internal.Shared:145:ExpBox False": 1,+ "Kafka.Internal.Shared:145:ExpBox True": 1,+ "Kafka.Internal.Shared:56:ExpBox False": 1,+ "Kafka.Metadata:255:ExpBox False": 1,+ "Kafka.Metadata:149:ExpBox False": 2,+ "Kafka.Producer:290:BinBox GuardBinBox False": 1,+ "Kafka.Producer:233:ExpBox True": 1,+ "Kafka.Producer:234:ExpBox False": 1,+ "Kafka.Producer:204:ExpBox False": 2,+ "Kafka.Producer:158:ExpBox False": 1,+ "Kafka.Producer:146:ExpBox False": 4,+ "Kafka.Producer:114:ExpBox False": 1,+ "Kafka.Producer.Callbacks:86:ExpBox False": 1,+ "Kafka.Producer.Callbacks:43:BinBox CondBinBox True": 1,+ "Kafka.Producer.Callbacks:44:ExpBox False": 8,+ "Kafka.Producer.Callbacks:44:ExpBox True": 1,+ "Kafka.Producer.Callbacks:60:BinBox CondBinBox True": 1,+ "Kafka.Producer.Callbacks:61:ExpBox False": 1,+ "Kafka.Producer.Callbacks:61:ExpBox True": 1,+ "Kafka.Topic:196:ExpBox False": 1,+ "Kafka.Topic:190:BinBox GuardBinBox False": 1,+ "Kafka.Topic:147:ExpBox False": 1,+ "Kafka.Topic:114:ExpBox False": 6,+ "Kafka.Topic:114:ExpBox True": 1,+ "Kafka.Topic:107:ExpBox False": 3,+ "Kafka.Topic:107:ExpBox True": 1,+ "Kafka.Topic:75:BinBox GuardBinBox False": 1,+ "Kafka.Topic:86:BinBox GuardBinBox False": 1,+ "Kafka.Topic:61:BinBox GuardBinBox False": 1,+ "Kafka.Topic:66:ExpBox False": 5,+ "Kafka.Topic:65:ExpBox True": 1,+ "Kafka.Topic:38:BinBox GuardBinBox False": 1+ },+ "coverage_evidence": "docs/testing/coverage-evidence.json",+ "coverage_evidence_sha256": "7ff3c3290cdb33e82f7a5a716194ceb14c54deac71c471a577b002a7fe55e8fd",+ "remap_proof": "docs/testing/coverage-classification-remap.json",+ "retained_latest_checkpoints": [+ "4daa8a6",+ "2137727",+ "b740b72"+ ]+}
+ docs/testing/deferred-validation.md view
@@ -0,0 +1,89 @@+# Deferred validation and preserved work++On 2026-10-24 the user explicitly narrowed the immediate release to the demonstrated primary environment and requested a comprehensive follow-up without losing started work. [ADR-27](../adr/release-validation-has-explicit-primary-and-expanded-scopes.md) records the boundary. [MasterPlan 3](../masterplans/3-complete-deferred-coverage-and-compatibility-validation.md) and its five children own the work below. Plan creation does not begin that implementation or claim it passed.++The frozen checkpoint `060dade4e8a9c764dabee54df3030fa6d857be3ea1404a2bc680a45ddadd5e4e` passes 78 unit and 708 integration cases normally and mapped, plus four actual nonthreaded runtime cases. The full report measures 2,750 handwritten native-wrapper ticks. Its remaining 192 unclassified handwritten ticks are preserved by exact keys/counts in [the snapshot](deferred-validation-snapshot.json), with all raw misses and artifact hashes in [coverage evidence](coverage-evidence.json). The inventory retains 146 tested and 35 open historical rows. Many open rows already have new passing cases and need reconciliation, not duplicate implementations.++## Current implementation checkpoint++The historical snapshot above remains unchanged. The current functional source+`2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c`+passes 78 unit and 753 integration cases normally and mapped, plus four separate+nonthreaded cases. Nine actual distributed-broker and seventeen actual security+cases contribute source-validated behavior registrations, without contributing+HPC ticks: 857 aggregate registered cases. The inventory now has 180 tested and+one open row; 401 exact source classifications leave two unexplained handwritten+producer exception-cleanup ticks. See [current public evidence](deferred-public-contract-evidence.json).++EP-17, EP-18 and EP-19 are Complete for the named source-bound scenarios in the+[compatibility matrix](compatibility-matrix.json). EP-16 still requires the two source ticks. The user-required historical seek+investigation is accepted through a causal late-topic-finalizer reconstruction+and an isolated 182-case differential with the already implemented scoped lifetime fix.+EP-20 remains Not Started because its whole-child EP-16 prerequisite is unmet.+The tables below preserve the original handoff, not the current row statuses.++## Release boundary++The current release retains all fixes and tests, complete primary normal/mapped runs, generated seeds, native diagnostic controls and semantic mutations. Primary inventory validation uses the explicit `--allow-open` mode; strict `just coverage-check` still rejects comprehensive gaps. New code changes must not be excused as deferred if they leave a known failing regression. Broader execution and exhaustive closure are not claimed by broad bounds, source inspection or this deferral.++## Deferred scope++| Owner | Work still required | Existing work to reuse |+|---|---|---|+| [EP-16](../plans/16-close-deferred-public-contract-and-source-coverage-gaps.md) | Reconcile every remaining public contract, close reachable source/binding gaps, audit exact-span applicability, and investigate the historical inactive-fetcher transition | All 786 registered tests, four nonthreaded checks, compiler export/miss tooling, four partial source audits, coordinate remap and legacy-seek evidence |+| [EP-17](../plans/17-validate-linux-and-released-toolchain-native-lifetimes.md) | Actual Linux and newer released compiler/native tuples; effective leak/invalid-access proof for client/bridge/header/message/metadata/partition lifetimes; complementary Darwin allocation evidence | Existing native counters, barriers, weak references, sanitizer control and focused instrumented runs; current Darwin ASan leak detection is disabled |+| [EP-18](../plans/18-verify-distributed-broker-failure-and-group-recovery.md) | Real Apache multi-broker leader changes/outages/reconnect, commit/poll recovery, eager/cooperative handoffs, assignmentLost True, transactional recovery/fencing/read-committed effects and unknown-topic config reject policy | Current local fencing/cooperative/commit/transaction cases and controlled native errors; these do not already prove distributed failure |+| [EP-19](../plans/19-verify-authenticated-kafka-and-credential-recovery.md) | Actual SASL authentication, TLS validation, ACL allow/deny, and producer/consumer credential replacement on observed future authentication after reconnect | Current setter/error-object ownership cases; these plaintext checks are retained without being mislabeled authenticated proof |+| [EP-20](../plans/20-enforce-the-complete-compatibility-evidence-gate.md) | Strict full inventory/coverage and all-tuple gate, stale/missing evidence controls, complete clean package replay and accurate tested claims | Existing strict checker, source-distribution/example/wrapper mechanics and exact fingerprints; preserve the separate primary release record |++## Exact historical open-row handoff++These rows retain their original status/owner in `coverage-matrix.json` for provenance. The follow-up owner below is the responsible child in MasterPlan 3. The snapshot includes every original behavior/input/expected/ownership field; none was removed to make the primary release green.++| Original row | Follow-up owner |+|---|---|+| `API-Kafka-Consumer-assign` | EP-16 |+| `API-Kafka-Consumer-assignmentLost` | EP-18 |+| `API-Kafka-Consumer-commitAllOffsets` | EP-16 |+| `API-Kafka-Consumer-commitOffsetMessage` | EP-16 |+| `API-Kafka-Consumer-pollMessage` | EP-16 |+| `API-Kafka-Consumer-pollMessageAttributed` | EP-16 |+| `API-Kafka-Consumer-pollMessageBatch` | EP-16 |+| `API-Kafka-Consumer-position` | EP-16 |+| `API-Kafka-Consumer-setConsumerQueueIOEvent` | EP-16 |+| `API-Kafka-Consumer-setSaslCredentials` | EP-19 |+| `API-Kafka-Consumer-storeOffsetMessage` | EP-16 |+| `API-Kafka-Consumer-storeOffsets` | EP-16 |+| `API-Kafka-Consumer-subscription` | EP-16 |+| `API-Kafka-Metadata-allConsumerGroupsInfo` | EP-16 |+| `API-Kafka-Metadata-allTopicsMetadata` | EP-16 |+| `API-Kafka-Metadata-consumerGroupInfo` | EP-16 |+| `API-Kafka-Metadata-offsetsForTime` | EP-16 |+| `API-Kafka-Metadata-offsetsForTime-prime` | EP-16 |+| `API-Kafka-Metadata-partitionWatermarkOffsets` | EP-16 |+| `API-Kafka-Metadata-topicMetadata` | EP-16 |+| `API-Kafka-Metadata-topicOffsetsForTime` | EP-16 |+| `API-Kafka-Metadata-watermarkOffsets` | EP-16 |+| `API-Kafka-Metadata-watermarkOffsets-prime` | EP-16 |+| `API-Kafka-Producer-Types-ImmediateError` | EP-16 |+| `API-Kafka-Producer-setSaslCredentials` | EP-19 |+| `OWN-partition-list` | EP-16 |+| `ENV-primary` | EP-20 |+| `ENV-linux` | EP-17 |+| `ENV-kafka` | EP-18 |+| `ENV-newer` | EP-17 |+| `OWN-source-coverage` | EP-16 |+| `OWN-binding-coverage` | EP-16 |+| `ENV-topic-configuration-policy` | EP-18 |+| `ENV-producer-native-headers` | EP-17 |+| `API-Kafka-Consumer-seek` | EP-16 |++## Preservation and resumption++All source/test/C fixtures and Haskell mutation families remain registered. Recent retained commits are `4daa8a6` (queue payload/constructor boundaries), `2137727` (partial partition-list cleanup) and `b740b72` (fresh inherited seek fixtures). Do not reset them, delete existing cases, recreate the four replaced Python mutation runners, or overwrite historical rejected-run notes.++Keep `legacy-seek-evidence.json` and its hash of `dist-coverage/failures/ep8-sync-seek-state.log`. The log proves State after an older assignment observation but does not identify its native transition; the max-poll hypothesis did not reproduce State. Existing tests preserve exact native State and recovery, and all ten positive scenarios now observe real delivery immediately before seeking. Further forensics belongs to EP-16, not an invented release explanation.++Source audit reuse is conditional on the exact source. `coverage-classification-remap.json` preserved all 334 classifications and moved 33 coordinates only through identical source lines. A new change needs another source-coordinate review. `callback-native-diagnostics.json` retains a failing invalid-access control; `partition-list-evidence.json` retains the four failing pre-fix encoding cases and 19 passing scoped ownership cases. These are started/completed assets, not backlog to repeat blindly.++Ignored build directories and temporary logs can disappear. The checked-in manifests, exact source/mutation descriptions, case names, seeds, version identities and hashes survive; regenerate missing raw artifacts from the matching candidate. Never invent results for an absent log. Use Mori to discover dependency sources, verify released versions before selecting tuples, and keep all broker/security actions on run-owned resources. No publication is authorized by the follow-up plan.
+ docs/testing/deprecated-runner-evidence.json view
@@ -0,0 +1,39 @@+{+ "status": "accepted deprecated-runner checkpoint; EP-14 incomplete",+ "fingerprint": "073aaaf7bb77bebb5b504869d60ce69058795934774f4b63a72e04445f4692ad",+ "runs": {+ "normal": {+ "log": "/tmp/rdkafka-ep14-runners-normal-final.log",+ "sha256": "62fa8a3677dc531f0a47e48b089ab8c8cdf7e9ce1c215d032522d4e8d3adab95",+ "passed": 15+ },+ "instrumented-haskell": {+ "log": "/tmp/rdkafka-ep14-runners-hpc.log",+ "sha256": "fff393482c3c1a0f5aef38d1c4a196ff42acd110015dcb0fb0d13e0bbdb1bef6",+ "passed": 15+ },+ "instrumented-native": {+ "log": "/tmp/rdkafka-ep14-runners-asan.log",+ "sha256": "b790dc47c1352c781989c28b36fb5e5ae9a6654cbc15897805bf7df33b0aa792",+ "passed": 15+ }+ },+ "mutations": "dist-mutations/20261024T210335Z-runners-32700-0/results.json",+ "compiled_mutations_caught": 4,+ "controls": 1,+ "scope": [+ "Producer flushes delivery callbacks after normal return, Left and thrown handler",+ "Consumers close after all three handler outcomes in both callback modes",+ "Native construction failures remain Left; configuration exceptions retain their types; handlers stay uncalled",+ "Exported handle constructors and fields reconstruct working producer/consumer aliases"+ ],+ "native_library": "mori://confluentinc/librdkafka",+ "native_version": "2.15.0",+ "native_diagnostic_control": "docs/testing/callback-native-diagnostics.json",+ "leak_instrumentation": false,+ "remaining": "Examples, input boundaries, saved deprecated-seek diagnosis, whole-candidate inventory and remaining handwritten misses; EP-15 environments remain open.",+ "required_checks": {+ "log": "/tmp/rdkafka-ep14-runners-check.log",+ "sha256": "bb09034a5c1baf4a7efcbe0bbf0fe8c623672476a374ee1a97a5eb966d588c51"+ }+}
+ docs/testing/diagnostic-evidence.json view
@@ -0,0 +1,42 @@+{+ "status": "accepted M2 diagnostics checkpoint; EP-14 incomplete",+ "fingerprint": "16d04c1a0afc4f53ca7c488ddef0c4200e3a4c22066d3e1f97793d8b5773a47f",+ "runs": {+ "normal": {+ "log": "/tmp/rdkafka-ep14-diagnostic-normal.log",+ "sha256": "1d7b9bac8e0a2793cd32638fb179d3f737864f1f731c0666a2078c3d9553035a",+ "passed": 9,+ "seconds": 0.03+ },+ "instrumented-haskell": {+ "log": "/tmp/rdkafka-ep14-diagnostic-hpc.log",+ "sha256": "d33d6b90a8e499b2fdb8e21bcbc2e48c68788c704a72a5d64c5dd50df905d224",+ "passed": 9,+ "seconds": 0.03+ },+ "instrumented-native": {+ "log": "/tmp/rdkafka-ep14-diagnostic-asan.log",+ "sha256": "183b1ebd58c1c54180bead9576d222ed5602d6419bced346c1d8e0c306019322",+ "passed": 9,+ "seconds": 0.04+ }+ },+ "mutations": "dist-mutations/20261024T162611Z-diagnostics-46539-0/results.json",+ "compiled_mutations_caught": 3,+ "controls": 1,+ "baseline": {+ "revision": "e76cbc8",+ "log": "/tmp/rdkafka-ep14-diagnostic-ownership-baseline.log",+ "failed": 4,+ "total": 7,+ "observed": "Both print functions consume the caller handle; cancellation at global/topic native dump return leaves one native array outstanding."+ },+ "native_ownership": "Count actual native arrays, fdopen streams and fclose calls; verify 200 arrays are freed after repeated exact map assertions. A deliberately retained native array validates the counter and is freed after assertion. Observe pending ThreadKilled before releasing each acquisition barrier.",+ "native_stream_failures": "Inject fdopen EMFILE and fclose EIO after the real close. Verify exceptions, duplicate descriptor closure through fcntl, and continued caller-handle usability.",+ "native_library": "mori://confluentinc/librdkafka",+ "native_version": "2.15.0",+ "native_diagnostic_control": "docs/testing/callback-native-diagnostics.json",+ "leak_instrumentation": false,+ "required_checks": "/tmp/rdkafka-ep14-diagnostic-check.log",+ "remaining": "Further consumer/metadata/runtime contracts, saved deprecated-seek failure, global mapped coverage/inventory reconciliation and EP-15 environments remain open."+}
+ docs/testing/example-evidence.json view
@@ -0,0 +1,48 @@+{+ "status": "accepted example checkpoint; EP-14 incomplete",+ "sources": {+ "example/Main.hs": "87c8bc1080e3364366309052c5596d50c07321394334f2e1bd519797e296fcd5",+ "example/ConsumerExample.hs": "0e52d363aa18a148ec5fff4b6a1b363b10e8c19721406c80bc51bf4a57dcff4c",+ "example/ProducerExample.hs": "68d963f2139720fcb46e04aee9760c1c8f8bbca89502f11887216584a7724be1"+ },+ "verification_source": "dist-mutations/example-verification/Probe.hs",+ "verification_source_sha256": "0fc5a2d0b12ddb886d89a98f76d632c764a2d6b8677446efb11ed3aebae6d1c3",+ "scope": [+ "Actual kafka-client-example executable receives three stdin lines against a run-owned topic/group at 127.0.0.1:39092",+ "Four independently read records have exact keys, values, ordered offsets 0 through 3 and fourth-record fancy header",+ "Independent consumer query confirms committed next offset 4",+ "Program completes within a thirty-second outer deadline; temporary process helper uses the existing Haskell fixture"+ ],+ "runs": {+ "normal": {+ "log": "/tmp/rdkafka-ep14-example-normal.log",+ "sha256": "a1122f0082ab550984c587708a4558392d99de38839304fad035ee339fb24e7c",+ "exact_records": 4,+ "committed_offset": 4+ },+ "instrumented-haskell": {+ "log": "/tmp/rdkafka-ep14-example-hpc.log",+ "sha256": "401871eac55232a2e19c2bb1c41a5ed3b25c309828bbd8bf01636a308f0d52b4",+ "exact_records": 4,+ "committed_offset": 4+ },+ "instrumented-native": {+ "log": "/tmp/rdkafka-ep14-example-asan.log",+ "sha256": "9822f823ee7abe69fc69811fa4eaec9af968972bac2806f9e24d6b5ec02fdada",+ "exact_records": 4,+ "committed_offset": 4+ }+ },+ "native_library": "mori://confluentinc/librdkafka",+ "native_version": "2.15.0",+ "leak_instrumentation": false,+ "notes": [+ "No-argument entry points retain existing defaults",+ "The example prints expected idle timeouts and subsequent NoOffset commits; verification separately requires exact successful effects",+ "Temporary verifier compilation required a uniquely renamed System.Process module because the shell exposed two process versions; failed compilation attempts are not test evidence"+ ],+ "required_checks": {+ "log": "/tmp/rdkafka-ep14-example-check.log",+ "sha256": "725c8e6056d13d77d3f8cf8d67b298d74ebd834f7f614d5684099813a4168253"+ }+}
+ docs/testing/final-boundaries-evidence.json view
@@ -0,0 +1,54 @@+{+ "status": "focused checkpoint accepted; whole-candidate reconciliation remains open",+ "fingerprint": "2477c5e49a3f1d43743e330c51e287cfc619ce545d2957ce56b66a2e0b24f0ed",+ "runs": {+ "normal": {+ "log": "/tmp/rdkafka-ep14-final-boundaries-normal.log",+ "sha256": "1fe6ce35d2e2122896cbafafff0c149a97d8e5b791ceec0b948d2255ef3a2ecd",+ "passed": 17+ },+ "instrumented-haskell": {+ "log": "/tmp/rdkafka-ep14-final-boundaries-hpc-corrected.log",+ "sha256": "da292798c9be2442c808f65960f222a2cf416588c7c0137d77d9870555bfab3d",+ "passed": 17+ },+ "instrumented-native": {+ "log": "/tmp/rdkafka-ep14-final-boundaries-asan.log",+ "sha256": "3b9a0bed00ce8988795cc6d30ac24749abdb81939e4dedcd4272223db61af6ca",+ "passed": 17+ },+ "unit-normal": {+ "log": "/tmp/rdkafka-ep14-final-boundaries-unit.log",+ "sha256": "aecbd5292a0e4fcbb45dc1ff350b19e0d61c536351290e1639833cc81249b934",+ "passed": 78+ },+ "unit-haskell": {+ "log": "/tmp/rdkafka-ep14-final-boundaries-unit-hpc.log",+ "sha256": "9d2322d9c26555bf7486c5d17ebceae2fca824e9a1b03cbd776d77efd821e6df",+ "passed": 78+ }+ },+ "mutations": "dist-mutations/20261024T225516Z-boundaries-44042-0/results.json",+ "compiled_mutations_caught": 10,+ "controls": 3,+ "scope": [+ "All six inherited queue cases retained, now fifteen queue cases; refreshed scalar observation checks actual queued records on every loop",+ "Binary notification bytes and empty payload record preservation in both callback modes",+ "Native poll redirection failure returns UnknownGroup and releases callbacks, client and async message queue before GC in both modes",+ "ImmediateError equality uses distinct wrapped errors, Show delegates to the error, unwrap preserves identity; generated cases use seed 20261024 and 1000 trials",+ "Fixture run prefix is printed to stderr for exact crash resource ownership"+ ],+ "excluded_runs": [+ {+ "log": "/tmp/rdkafka-ep14-final-boundaries-hpc.log",+ "reason": "Two new empty-payload assertions exposed an unused observer refresh argument; helper corrected and all focused runs repeated."+ },+ {+ "results": "dist-mutations/20261024T223440Z-boundaries-19287-0",+ "reason": "Redirect tests failed correctly, but mutation runner expected label omitted the async prefix. Correct full labels used in accepted rerun."+ }+ ],+ "native_version": "2.15.0",+ "leak_instrumentation": false,+ "required_checks": "/tmp/rdkafka-ep14-final-boundaries-check.log"+}
+ docs/testing/generated-mapping-evidence.json view
@@ -0,0 +1,37 @@+{+ "status": "accepted coverage-mapper correction; full candidate remeasurement pending",+ "faults": [+ "An internal blank in a generated enum prematurely advanced the origin into handwritten source",+ "Hooks written with whitespace after # were not recognized as generated"+ ],+ "controls": {+ "all_passed": 24,+ "new_controls": 2,+ "old_mapper_failed_both": true,+ "current": {+ "log": "/tmp/rdkafka-ep14-generated-map-controls.log",+ "sha256": "38dc1482d68d976778a138400d0b52a8a5c01f84115d1b12db3a95771ee83e66"+ },+ "baseline": {+ "log": "/tmp/rdkafka-ep14-generated-map-old-controls.log",+ "sha256": "05a93d91ac0357c72bca07daa29041351d87bc9c20f0c90d14c3481392380dd5"+ }+ },+ "real_generated_module": {+ "result": {+ "log": "/tmp/rdkafka-ep14-generated-map-real.log",+ "sha256": "381931d45917a2bb5a75e4ceb0e54994182f96c0dcbde2f885a9f266cbad75d3"+ },+ "emitted_haskell_identical": true,+ "haskell_sha256": "1bcb02aef8033efc572c817ce2261aba46d35fbc7c41a843223777beb20ae859",+ "mapping_entries_changed": 743,+ "manual_to_generated": 86,+ "generated_to_manual": 0,+ "all_handwritten_signatures_verified": true+ },+ "required_checks": {+ "log": "/tmp/rdkafka-ep14-generated-map-check.log",+ "sha256": "b56cd9255eaed8d0e07be255bf589db7a76d331129467b4fb5ce400652ac881c"+ },+ "scope": "Classification/source-map metadata only; emitted instrumented Haskell code is byte identical. All existing controls are retained. The next full mapped run must regenerate metrics and reconcile classification keys."+}
+ docs/testing/input-identity-evidence.json view
@@ -0,0 +1,58 @@+{+ "status": "accepted input-identity checkpoint; EP-14 incomplete",+ "fingerprint": "77945edc43e5baeec2756b998f802bd8b6420bb872299d3b65bdae1ebb33784e",+ "baseline": {+ "log": "/tmp/rdkafka-ep14-input-baseline-compiled.log",+ "failed": 78,+ "total": 78,+ "seconds": 25.64+ },+ "runs": {+ "normal": {+ "log": "/tmp/rdkafka-ep14-input-normal.log",+ "sha256": "581977cb6c03cbf6dd9799c95f2dcb93b0d682f48cd26a13c5b2560944227fbf",+ "passed": 80+ },+ "instrumented-haskell": {+ "log": "/tmp/rdkafka-ep14-input-hpc.log",+ "sha256": "f78ac7b99132af397c14ae149992e7efc1d552fc527304ac2894c62b47cf4ddc",+ "passed": 80+ },+ "instrumented-native": {+ "log": "/tmp/rdkafka-ep14-input-asan.log",+ "sha256": "7268544aaec5f4c26ff676cad9aa7c2a1c1735cdb602b293331491b637a2b491",+ "passed": 80+ }+ },+ "regression_runs": {+ "normal": {+ "log": "/tmp/rdkafka-ep14-input-regression-normal.log",+ "sha256": "f6b417195acd17a5ebbeaf3fe7b29defdffbd6e20e6c2b60067dfd1ba7c205ee",+ "passed": 30+ },+ "instrumented-haskell": {+ "log": "/tmp/rdkafka-ep14-input-regression-hpc.log",+ "sha256": "d7a11ae5ab4864206b67baacc10ce35a597ed4b4e2b77651a3d68b2128630973",+ "passed": 30+ }+ },+ "mutations": "dist-mutations/20261024T212523Z-inputs-67341-0/results.json",+ "compiled_mutations_caught": 5,+ "controls": 1,+ "scope": [+ "Thirteen consumer and metadata operations reject NUL topics and upper/lower partition overflow in both callback modes",+ "All rejected operations preserve prior assignment and the exact next record",+ "Metadata convenience/group queries and subscription construction reject NUL",+ "Mixed malformed assignment is rejected before native effects; a representable maximum C int retains native query behavior"+ ],+ "native_library": "mori://confluentinc/librdkafka",+ "native_version": "2.15.0",+ "native_diagnostic_control": "docs/testing/callback-native-diagnostics.json",+ "leak_instrumentation": false,+ "excluded": "The first baseline attempt failed to compile due to an ambiguous Tasty Timeout import; only the corrected 78-case compiled run counts as defect evidence.",+ "remaining": "Whole-candidate collection/inventory remains at the preceding 662-case checkpoint. Remaining API cases, saved seek diagnosis, reachable ownership/error coverage and EP-15 environments remain open. Coverage exception coordinates must be reconciled after these source-line shifts.",+ "required_checks": {+ "log": "/tmp/rdkafka-ep14-input-check.log",+ "sha256": "2211cecb0715f4fddd0007b416ebfb20964e2d03f1fd5bfa5f9b650224bed9a7"+ }+}
+ docs/testing/legacy-seek-evidence.json view
@@ -0,0 +1,215 @@+{+ "status": "Accepted causal historical reproduction and isolated scoped-lifetime differential; original failure retained",+ "fingerprint": "060dade4e8a9c764dabee54df3030fa6d857be3ea1404a2bc680a45ddadd5e4e",+ "runs": {+ "normal": {+ "log": "/tmp/rdkafka-ep14-legacy-fixtures-normal.log",+ "sha256": "1488d6d69c6e2f897b3ff2577846eaf1ab6a0d1d947a5fa75f2798fcc0375575",+ "passed": 54+ },+ "instrumented-haskell": {+ "log": "/tmp/rdkafka-ep14-legacy-fixtures-hpc.log",+ "sha256": "d5b7cb13f31913f5820f2905e79e9d0bcc8699552222b8eaec3a82c2d0defb91",+ "passed": 54+ },+ "instrumented-native": {+ "log": "/tmp/rdkafka-ep14-legacy-fixtures-asan.log",+ "sha256": "2e4ea314d564e9484263e06f21fd22c19dc3c688ef23088cf43170227dc43fd8",+ "passed": 54+ }+ },+ "mutations": "dist-mutations/20261024T230850Z-legacy-seek-88557-0/results.json",+ "compiled_mutations_caught": 2,+ "controls": 1,+ "inherited_positive_cases_retained": 10,+ "historical_failure": {+ "log": "dist-coverage/failures/ep8-sync-seek-state.log",+ "sha256": "2c45980cc04be4e3579487dd66c991d48769255ac109ae257ff61581abf0cc2b",+ "observed": "Sync consumer previously read fourteen records and reported assignment partition zero. Several blocking metadata/group/time calls intervened before seek returned State. The other four seek cases were skipped by the group dependency.",+ "native_diagnosis": "At native release 2.15.0 rd_kafka_seek waits for the fetcher result. rd_kafka_toppar_seek returns State for a fetch state below OFFSET_QUERY, excluding STOPPING, which returns PrevInProgress. Thus the assignment snapshot did not establish the later active-fetcher precondition.",+ "limit": "The saved log alone does not identify the native transition. The new native-only reproduction shows duplicate topic/partition identity; parent lifetime and late finalizer ordering are under investigation. No max-poll or broker event is asserted as the cause."+ },+ "fixture_change": "All five inherited positive offset scenarios run in both modes on fresh run-owned topics and unique grouped consumers. Each confirms exact record zero immediately before seeking, then verifies exact next identity/offset/value or documented EOF/timeout. Unassignment/State/reassignment and repeated replay remain separate tests. State is not suppressed or retried into success.",+ "native_source": {+ "project": "mori://confluentinc/librdkafka",+ "release": "2.15.0",+ "commit": "9a94e11452cdeb0a844db44ee5dd01ccbe17d3ab",+ "paths": [+ "src/rdkafka.c:4727",+ "src/rdkafka_partition.c:1950",+ "src/rdkafka_partition.h:301"+ ],+ "source_artifact_uri_pending": true+ },+ "rejected_hypothesis": {+ "log": "/tmp/rdkafka-ep14-stale-assignment.log",+ "sha256": "1f400cce426bb905b24efc6fbb5dc71258bab1e474e9d1dad5affc01dd0626a2",+ "description": "A deliberately short max-poll interval produced MAXPOLL and a stale assignment query, but seek still succeeded. This does not reproduce or explain the historical trigger."+ },+ "required_checks": "/tmp/rdkafka-ep14-legacy-fixtures-check.log",+ "adr_checks": "/tmp/rdkafka-ep14-legacy-fixtures-adr.log",+ "leak_instrumentation": false,+ "scope_decision": {+ "at": "2026-10-25",+ "user_choice": "Keep the historical investigation required",+ "completion_requirement": "Identify a reproducible supported transition that accounts for the saved condition, with concrete native/operation evidence; passing reruns and an unknown-cause limitation do not close this requirement."+ },+ "continued_forensics": {+ "historical_checkout": "fc5892d",+ "checkout_receipt": "dist-compatibility/seek-historical-fc5892d/forensic-receipt.json",+ "archive_crosscheck": "Historical mutation archive retains byte-identical ConsumerTest.hs, TestEnv.hs, Consumer.hs and ConsumerProperties.hs relative to fc5892d. The native/admin source hashes also match the preserved subject manifest. The whole failed-run fingerprint differs, so no exact whole-candidate reconstruction is claimed.",+ "traced_replay": {+ "tests": 182,+ "seconds": 100.61,+ "result": "pass; sync fetcher remains active through metadata/group/time queries and first seek is served in active state"+ },+ "forced_gc_replay": {+ "tests": 182,+ "seconds": 100.79,+ "options": [+ "-G1",+ "-A32k"+ ],+ "result": "pass with explicit performGC before every inherited consumer operation; not a reconstruction"+ },+ "broker_log": "Read-only retained primary broker logs establish the exact historical topic was created at 2026-10-24 07:33:31.078 UTC and deleted at 07:34:47.721 UTC after the suite teardown. No intervening deletion of that exact topic occurs. Default INFO logs contain no matching group/fetch-state transition, so they cannot identify the inactive-fetcher cause.",+ "accepted_cause": "A managed legacy-seek topic may outlive its native client. Its late C finalizer accesses the freed parent; when that address is reused by the next consumer, TAILQ_REMOVE writes through the old topic link into the new client topic-list head. Metadata/name lookup then constructs a second topic/partition in fetch state none while the real assigned partition remains active. Legacy seek resolves that second partition and returns State.",+ "artifacts": {+ "rdkafka-mp3-historical-trace7.log": {+ "path": "dist-compatibility/expanded-recovery-checkpoint/rdkafka-mp3-historical-trace7.log",+ "sha256": "445c86226e5c49b469933b1be9fbd18a3958d350bbaff3f976991054893c5c12"+ },+ "rdkafka-mp3-historical-gc7.log": {+ "path": "dist-compatibility/expanded-recovery-checkpoint/rdkafka-mp3-historical-gc7.log",+ "sha256": "9c0521941eae17709a7b4f504344facdf99da7c3842fb7b7c990c84dcfdc20b6"+ },+ "rdkafka-mp3-historical-broker7.log": {+ "path": "dist-compatibility/expanded-recovery-checkpoint/rdkafka-mp3-historical-broker7.log",+ "sha256": "f20d9eda2095d6564ca1dafa6640ed07d4dde43417efd3f531d22e7ab5d78634"+ }+ }+ },+ "native_trace_reproduction": {+ "status": "Native State reproduced; exact object divergence under investigation",+ "tests_failed": 5,+ "real_failure_count": 1,+ "dependency_skips": 4,+ "seconds": 99.16,+ "native_project": "mori://confluentinc/librdkafka",+ "native_revision": "9a94e11452cdeb0a844db44ee5dd01ccbe17d3ab",+ "native_change": "C-only fetch-state transitions and seek-entry trace, with stop-state backtraces; no behavior/layout change. ConsumerTest restored to original with no Haskell debug or forced GC.",+ "observed": "Consumer 73 delivers records on an active partition; first seek later enters with state none. No active-to-none transition is logged; the original active partition reaches stopping/stopped only during final teardown. Distinguish object identity before attributing the result to lost assignment or a stopped fetcher.",+ "artifacts": {+ "rdkafka-mp3-historical-native-trace9.log": {+ "path": "dist-compatibility/expanded-source9/rdkafka-mp3-historical-native-trace9.log",+ "sha256": "5c787df34cea6516047d39e72a4a327864bf83ec560fef3f8f829b0c51a08979"+ }+ },+ "identity_probe": {+ "observed": "The reproduced failing sync consumer delivers on rkt 0xba7a2c500 / partition 0xba7328500. During all-topics metadata a second rkt 0xba7a2ca00 / partition 0xba7328f00 is created for the same topic. Seek uses the second partition in state none. The original remains active until teardown. A separate native lifetime trace aborts when the preceding async consumer topic finalizer accesses its already destroyed parent mutex; parent-address reuse is under investigation.",+ "artifacts": {+ "historical-identities-pass.log": {+ "path": "dist-compatibility/expanded-source9/historical-identities-pass.log",+ "sha256": "7db8174078eac3b4efc9e1018186f2632c8e495cf9e4dc847da22054d433b798"+ },+ "historical-identities-state.log": {+ "path": "dist-compatibility/expanded-source9/historical-identities-state.log",+ "sha256": "e1717a0b11937edd5dacd526a0008ddeae4db60d3bb323db72d0e286d6b55ebb"+ },+ "historical-late-topic-finalizer-abort.log": {+ "path": "dist-compatibility/expanded-source9/historical-late-topic-finalizer-abort.log",+ "sha256": "bd5a9d023a1be7917028f3b0ba55a995932d81203837fba8dd818bad306a2f69"+ }+ },+ "limit": "Do not yet assert that the precise old saved event was a late finalizer. The observed duplicate object and separate invalid-parent destructor motivate a direct address/order probe."+ }+ },+ "causal_acceptance": {+ "historical_subject": "fc5892d core Consumer/Metadata/native API sources with original ConsumerTest and GHC coverage; no Haskell debug/forced GC in the reproducing run. Core source bytes match the original preserved mutation archive; whole failed-candidate fingerprint was not reconstructable.",+ "native_trace": "Tagged librdkafka 2.15.0 with C-only pointer/state/finalizer logging; no native behavior or opaque layout change.",+ "timeline": [+ "Async consumer 72 uses parent 0xbff0b8000, topic 0xbfee2de00 and active partition 0xbfee2e800.",+ "Sync consumer 73 reuses native parent address 0xbff0b8000 and delivers fourteen records using a different topic 0xbfee2e800 and partition 0xbfee2d900.",+ "During watermark lookup two delayed application-reference releases finalize old topic 0xbfee2de00. Its parent now reports consumer-73; the stack is runSomeFinalizers -> rd_kafka_topic_destroy_final.",+ "Native by-name lookup now reports topic count zero, while the original assigned partition has not stopped.",+ "Metadata/topic lookup constructs topic 0xbfee2de00 again with a new never-started partition 0xbfee2ca00. Seek enters that partition in state none and returns State; four dependent cases skip.",+ "A separate explicit client-lifetime trace, with no address reuse, records destruction/free of parent consumer 72 before its topic finalizer and aborts on the destroyed parent mutex. This corroborates the invalid lifetime independently of topic-list corruption."+ ],+ "mechanism_source": {+ "project": "mori://confluentinc/librdkafka",+ "version": "2.15.0",+ "commit": "9a94e11452cdeb0a844db44ee5dd01ccbe17d3ab",+ "project_relative_paths": [+ "src/rdkafka_topic.c:rd_kafka_topic_destroy_final (TAILQ_REMOVE)",+ "src/rdkafka_topic.c:rd_kafka_topic_find_fl",+ "src/rdkafka.c:rd_kafka_seek",+ "src/rdkafka_partition.c:rd_kafka_toppar_seek"+ ],+ "artifact_uri_pending": true+ },+ "minimal_differential": {+ "change": "Only legacy seek in the historical checkout is changed to retain its parent with withForeignPtr and bracket/finalize every acquired topic before returning, mirroring the already implemented current lifetime fix. No offsets, errors, waits, topic fixtures or callback mode is changed.",+ "passed": 182,+ "seconds": 99.41,+ "finalizer_order": "Both historical consumer topics finalize while their original parent is still alive; no State and no duplicate topic object."+ },+ "current_repair": {+ "commit": "2d8be3574b395cbd995b23fff09e06da03c95ae8",+ "source": "src/Kafka/Consumer.hs",+ "source_sha256": "170ea8259f8b0279db807c48799f323a268e7636efcbc929ade003cd4e4bb70a",+ "behavior": "Legacy seek retains the native client and explicitly finalizes scoped topics; current native-child Haskell finalizers also retain the parent. Existing ten fresh positive scenarios, native State propagation/recovery tests, full primary normal/mapped runs and current native diagnostic cohorts remain accepted."+ },+ "scope_limit": "This is a causal reproduction of the saved failure condition with the preserved historical core, not a claim that the untraced original process event can be observed retrospectively. The stopped-fetcher and max-poll explanations are not asserted.",+ "artifacts": {+ "historical-causal-identity.log": {+ "path": "dist-compatibility/expanded-source9/historical-causal-identity.log",+ "sha256": "7d71250fd32bf8b5773099504fe6e5a8c57ca3aa18fb435ec8c0e091964a3314"+ },+ "historical-trace-v4.dylib": {+ "path": "dist-compatibility/expanded-source9/historical-trace-v4.dylib",+ "sha256": "d43912f91b6100e52da2985ed25f812e6c4f313e6325784222c43010402c75d5"+ },+ "historical-scoped-binary": {+ "path": "dist-compatibility/expanded-source9/historical-scoped-binary",+ "sha256": "159997f6bd528ebcf7a61790ed0e3b9b0a548edfacc9250d9096de08c985eed8"+ },+ "historical-scoped-replay.log": {+ "path": "dist-compatibility/expanded-source9/historical-scoped-replay.log",+ "sha256": "d467c5510499003864488f66fb7272f327b85c5713caabf698dfdae6ed601f33"+ },+ "historical-Consumer-original.hs": {+ "path": "dist-compatibility/expanded-source9/historical-Consumer-original.hs",+ "sha256": "302dc7b476e90ec031a6a28f4dd96a0307028fa8b67889724f276ff7a77d734a"+ },+ "historical-Consumer-scoped.hs": {+ "path": "dist-compatibility/expanded-source9/historical-Consumer-scoped.hs",+ "sha256": "7c61dc0a193e3ca6250312176c6964ed21663bef609fe4b7b1eb821fbbefeb42"+ },+ "historical-client-destruction-order.log": {+ "path": "dist-compatibility/expanded-source9/historical-client-destruction-order.log",+ "sha256": "949173d4205d89c5831e0015cfe616b16656d2061f9a38e90ebaf4a2b75ec2ab"+ },+ "historical-trace-v5.dylib": {+ "path": "dist-compatibility/expanded-source9/historical-trace-v5.dylib",+ "sha256": "b1819973bc434e9a8ccb6af66697a3a53446d9d256e4ac2f1e2af87d62b8b673"+ },+ "historical-trace-v5-rdkafka.c": {+ "path": "dist-compatibility/expanded-source9/historical-trace-v5-rdkafka.c",+ "sha256": "3bbb03d7743debdcc065a173056523c221ffaedd15b38f989927568467c69a48"+ },+ "historical-trace-v5-rdkafka_topic.c": {+ "path": "dist-compatibility/expanded-source9/historical-trace-v5-rdkafka_topic.c",+ "sha256": "7bad08c3ec3c35ff819b27c0e73e0849d72999f3865a176939242443d69b27dd"+ },+ "historical-trace-v5-rdkafka_partition.c": {+ "path": "dist-compatibility/expanded-source9/historical-trace-v5-rdkafka_partition.c",+ "sha256": "c3a522c87cfc323f93ef5531f48988e738bec4dc50ded6aea4e382b98329b264"+ },+ "historical-native-trace-v5.diff": {+ "path": "dist-compatibility/expanded-source9/historical-native-trace-v5.diff",+ "sha256": "59a800395bd40922e7796458e37a08b94d65f37ac94e344fec19e693c322e101"+ }+ },+ "native_v5_sha256": "b1819973bc434e9a8ccb6af66697a3a53446d9d256e4ac2f1e2af87d62b8b673"+ }+}
+ docs/testing/linux-tuple-evidence.json view
@@ -0,0 +1,1413 @@+{+ "status": "Accepted Linux/newer released tuple and effective named ownership diagnostics; comprehensive EP-20 qualification remains gated by EP-16",+ "source": {+ "project": "mori://shinzui/rdkafka-hs",+ "candidate_fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "execution_fingerprint": "74c7156e6fee8653bcec844001fd8f95d703bcf4d8e978a857a9f8f3560b6b0a",+ "revision": "bfa4f2e plus captured source",+ "archive": {+ "path": "dist-compatibility/expanded-source9/candidate.tar.gz",+ "sha256": "a70e4839d24c5e5179ff9a8be48643951e185d604cd8ba3401587730279f3b22"+ },+ "root_file_inventory": {+ "path": "dist-compatibility/expanded-source9/root-functional-files.json",+ "sha256": "69506c90cfc124f3a175a664873f5d8b49aff62a7426265c56c3dd64fcc84c21"+ },+ "archive_file_inventory": {+ "path": "dist-compatibility/expanded-source9/phase9-functional-files.json",+ "sha256": "d0e5d59aa49833ecd1305410c839cbebdbbb418679cecc6de0c2548b142dca4b"+ },+ "archive_comparison": {+ "changed_files": [],+ "added_files": [],+ "omitted_development_files": [+ ".envrc",+ "cabal.project",+ "flake.lock",+ "flake.module.nix",+ "flake.nix",+ "justfile",+ "nix/haskell.nix",+ "nix/pre-commit.nix",+ "nix/redpanda.nix",+ "nix/treefmt.nix"+ ],+ "omitted_project_configuration": {+ "path": "cabal.project",+ "content": "packages: .\n",+ "replacement": "Cabal implicit single package in clean extraction; same package set, no solver/compiler constraints in omitted file"+ },+ "execution_fingerprint": "74c7156e6fee8653bcec844001fd8f95d703bcf4d8e978a857a9f8f3560b6b0a",+ "root_fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c"+ },+ "configuration_sha256": "c6c0771e7da58c35d40170db3ec18cdd2439997e223ef4c088ac3f4e793707f9"+ },+ "environment": {+ "os": "PRETTY_NAME=\"Ubuntu 24.04.5 LTS\"\nNAME=\"Ubuntu\"\nVERSION_ID=\"24.04\"\nVERSION=\"24.04.5 LTS (Noble Numbat)\"\nVERSION_CODENAME=noble\nID=ubuntu\nID_LIKE=debian\nHOME_URL=\"https://www.ubuntu.com/\"\nSUPPORT_URL=\"https://help.ubuntu.com/\"\nBUG_REPORT_URL=\"https://bugs.launchpad.net/ubuntu/\"\nPRIVACY_POLICY_URL=\"https://www.ubuntu.com/legal/terms-and-policies/privacy-policy\"\nUBUNTU_CODENAME=noble\nLOGO=ubuntu-logo",+ "kernel": "Linux 6.18.15",+ "architecture": "aarch64",+ "ghc": "9.14.1",+ "cabal": "3.16.1.0",+ "java": "openjdk 21.0.12.1 2026-08-18\nOpenJDK Runtime Environment (build 21.0.12.1+1-1-24.04.4-Ubuntu)\nOpenJDK 64-Bit Server VM (build 21.0.12.1+1-1-24.04.4-Ubuntu, mixed mode, sharing)",+ "native_version": "2.16.0",+ "broker_version": "Apache Kafka 4.4.0",+ "loaded_native_identity": {+ "observed": "(\"2.16.0\",34603263)",+ "path": "/opt/librdkafka-2.16.0/lib/librdkafka.so.1",+ "sha256": "e4ebf0b82581b51a86a0d861a90c07004b0b1fec67ab71e409b572594846154f"+ }+ },+ "release_sources": {+ "ghc": {+ "registry": "https://downloads.haskell.org/ghc/9.14.1/",+ "tag": "ghc-9.14.1-release",+ "tag_object": "961b2ffcc02ea6c93df649fc8367458378fa7aa5"+ },+ "native": {+ "project": "mori://confluentinc/librdkafka",+ "tag": "v2.16.0",+ "commit": "c6c9973cf1b25394c58e0cade13a36f386856f77",+ "release": "https://github.com/confluentinc/librdkafka/releases/tag/v2.16.0"+ },+ "broker": {+ "registry": "https://downloads.apache.org/kafka/4.4.0/",+ "tag": "4.4.0",+ "tag_object": "9661b1ef7a0120e476399250b31d530792506787",+ "sha512_verified": true+ }+ },+ "results": {+ "components_built": [+ "library",+ "examples",+ "unit suite",+ "integration suite"+ ],+ "unit_tests": 78,+ "native_lifetime_tests": 279,+ "native_seconds": 232.63,+ "native_tests": [+ "rdkafka-hs-integration.callback-lifetime.async throwing error callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing log callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing stats callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing rebalance callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async throwing commit callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing error callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing log callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing stats callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing rebalance callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.sync throwing commit callback preserves native lifecycle",+ "rdkafka-hs-integration.callback-lifetime.async error callback releases after destroy with retained wrapper",+ "rdkafka-hs-integration.callback-lifetime.sync error callback releases after destroy with retained wrapper",+ "rdkafka-hs-integration.callback-lifetime.producer delivery callback releases after native finalization",+ "rdkafka-hs-integration.callback-lifetime.noncaptured control is collectible",+ "rdkafka-hs-integration.callback-lifetime.async log callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.async stats callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.sync log callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.sync stats callback is live then releases",+ "rdkafka-hs-integration.callback-lifetime.async construction failure releases callbacks: topic",+ "rdkafka-hs-integration.callback-lifetime.async construction failure releases callbacks: native",+ "rdkafka-hs-integration.callback-lifetime.async construction failure releases callbacks: redirect",+ "rdkafka-hs-integration.callback-lifetime.async construction failure releases callbacks: subscribe",+ "rdkafka-hs-integration.callback-lifetime.sync construction failure releases callbacks: topic",+ "rdkafka-hs-integration.callback-lifetime.sync construction failure releases callbacks: native",+ "rdkafka-hs-integration.callback-lifetime.sync construction failure releases callbacks: redirect",+ "rdkafka-hs-integration.callback-lifetime.sync construction failure releases callbacks: subscribe",+ "rdkafka-hs-integration.callback-lifetime.producer native construction failure releases callbacks",+ "rdkafka-hs-integration.callback-lifetime.async constructor exception at callback-install releases partial native ownership",+ "rdkafka-hs-integration.callback-lifetime.async constructor exception at post-native-loglevel releases partial native ownership",+ "rdkafka-hs-integration.callback-lifetime.sync constructor exception at callback-install releases partial native ownership",+ "rdkafka-hs-integration.callback-lifetime.sync constructor exception at post-native-loglevel releases partial native ownership",+ "rdkafka-hs-integration.callback-lifetime.async rebalance callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.async commit callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.sync rebalance callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.sync commit callback releases captured borrowed configuration",+ "rdkafka-hs-integration.callback-lifetime.replaced producer delivery callbacks both release",+ "rdkafka-hs-integration.callback-lifetime.async concurrent destruction joins at native entry",+ "rdkafka-hs-integration.callback-lifetime.async concurrent destruction joins at native completion",+ "rdkafka-hs-integration.callback-lifetime.async concurrent destruction joins at native shutdown callback",+ "rdkafka-hs-integration.callback-lifetime.sync concurrent destruction joins at native entry",+ "rdkafka-hs-integration.callback-lifetime.sync concurrent destruction joins at native completion",+ "rdkafka-hs-integration.callback-lifetime.sync concurrent destruction joins at native shutdown callback",+ "rdkafka-hs-integration.callback-lifetime.async cancellation at native entry preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.async cancellation at native completion preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.async cancellation at native shutdown callback preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation at native entry preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation at native completion preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation at native shutdown callback preserves exactly-once teardown",+ "rdkafka-hs-integration.callback-lifetime.async cancellation after poll stop and queue detachment preserves teardown",+ "rdkafka-hs-integration.callback-lifetime.producer constructor cancellation at partial registration releases its owner",+ "rdkafka-hs-integration.callback-lifetime.producer constructor cancellation at native acceptance releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-async constructor cancellation at partial registration releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-async constructor cancellation at native acceptance releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-sync constructor cancellation at partial registration releases its owner",+ "rdkafka-hs-integration.callback-lifetime.consumer-sync constructor cancellation at native acceptance releases its owner",+ "rdkafka-hs-integration.callback-lifetime.async cancellation while waiting for active callback permits retry",+ "rdkafka-hs-integration.callback-lifetime.sync cancellation while waiting for active callback permits retry",+ "rdkafka-hs-integration.callback-lifetime.async closed consumer GC releases its registrations once",+ "rdkafka-hs-integration.callback-lifetime.sync closed consumer GC releases its registrations once",+ "rdkafka-hs-integration.callback-lifetime.producer error callback remains live through close and releases on GC",+ "rdkafka-hs-integration.callback-lifetime.producer log callback remains live through close and releases on GC",+ "rdkafka-hs-integration.callback-lifetime.producer stats callback remains live through close and releases on GC",+ "rdkafka-hs-integration.callback-lifetime.failed native construction releases the caller-owned duplicate config",+ "rdkafka-hs-integration.transaction-errors.transaction-error-leak-probe releases 300 immediate native errors",+ "rdkafka-hs-integration.transaction-errors.native allocation control detects the inherited three-error leak",+ "rdkafka-hs-integration.transaction-errors.initialization timeout destroys its native error on each retry",+ "rdkafka-hs-integration.transaction-errors.zero-timeout initialization resumes successfully against the broker",+ "rdkafka-hs-integration.transaction-errors.transaction state errors preserve empty commit and abort recovery",+ "rdkafka-hs-integration.transaction-errors.duplicate transactional IDs report a real fatal fencing error",+ "rdkafka-hs-integration.transaction-errors.broker-rejected delivery requires abort and permits a successful new transaction",+ "rdkafka-hs-integration.transaction-errors.init without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.begin without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.abort without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.commit without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.offset without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.init NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.begin NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.abort NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.commit NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.offset NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.init invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.begin invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.abort invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.commit invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.offset invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 0 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 1 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 2 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 3 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 4 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 5 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 6 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 7 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 0 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 1 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 2 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 3 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 4 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 5 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 6 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 7 before destruction",+ "rdkafka-hs-integration.transaction-errors.init cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.begin cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.abort cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 21 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 22 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 23 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 21 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 22 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 23 releases once",+ "rdkafka-hs-integration.transaction-errors.async commit publishes output and source next offset atomically; abort publishes neither",+ "rdkafka-hs-integration.transaction-errors.sync commit publishes output and source next offset atomically; abort publishes neither",+ "rdkafka-hs-integration.lifecycle.flushProducerTimeout times out, purgeProducer empties the queue",+ "rdkafka-hs-integration.lifecycle.consumerClosed is False until closeConsumer",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials replaces credentials on a consumer",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials replaces credentials on a producer",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials rejects NUL in username without changing producer or consumer identity",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials rejects NUL in password without changing producer or consumer identity",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials releases each actual native error after decoding its exact code",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials cancellation at error decoding releases the owned error",+ "rdkafka-hs-integration.lifecycle.setSaslCredentials cancellation at error acquisition releases the owned error",+ "rdkafka-hs-integration.producer-regressions.explicit topic timeout expires an accepted message",+ "rdkafka-hs-integration.producer-regressions.global timeout still expires an accepted message",+ "rdkafka-hs-integration.producer-regressions.queue-full rejection releases callback capture without invoking it",+ "rdkafka-hs-integration.producer-regressions.accepted callback retains its capture until a purged report completes",+ "rdkafka-hs-integration.producer-regressions.throwing global callback preserves per-message delivery and releases capture",+ "rdkafka-hs-integration.producer-regressions.throwing per-message callback reports exception and releases capture",+ "rdkafka-hs-integration.producer-regressions.repeated queue-full rejections release every callback capture",+ "rdkafka-hs-integration.producer-regressions.cancellation at a rejected enqueue releases capture before unmasking",+ "rdkafka-hs-integration.producer-regressions.cancellation after native acceptance retains callback until its report",+ "rdkafka-hs-integration.producer-regressions.another poller can deliver before successful enqueue returns",+ "rdkafka-hs-integration.producer-regressions.running callback keeps its capture after the native root is released",+ "rdkafka-hs-integration.producer-regressions.native error decoding failure releases rejected callback capture",+ "rdkafka-hs-integration.producer-regressions.non-null native success-code error rejects and releases capture",+ "rdkafka-hs-integration.producer-regressions.unknown native error code is preserved instead of reading errno",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: defaults",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: global only",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: topic only",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: disjoint maps",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: explicit topic wins duplicate",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: last topic property wins",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: empty topic map preserves global",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: zero topic timeout is infinite",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: maximum native topic timeout",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: explicit topic wins native timeout alias",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: topic codec overrides global codec",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: global codec survives unrelated topic keys",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with NoCompression",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Gzip",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Snappy",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Lz4",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Zstd",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: none",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: inflight",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue+inflight",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue+nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: inflight+nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: all",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: none",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: inflight",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue+inflight",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue+nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: inflight+nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: all",+ "rdkafka-hs-integration.producer-regressions.bounded flush timeout recovers when the delayed response arrives",+ "rdkafka-hs-integration.producer-regressions.close retries a timed-out flush until the delayed delivery completes",+ "rdkafka-hs-integration.producer-regressions.oversized rejection releases capture without a delivery report",+ "rdkafka-hs-integration.producer-regressions.known invalid partition rejection releases capture",+ "rdkafka-hs-integration.producer-regressions.empty queue supports repeated flush and close",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: NUL topic name",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: NUL header name",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: maximum unrepresentable partition",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: minimum unrepresentable partition",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: unknown global key",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: unknown topic key",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: invalid topic timeout",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: excessive topic timeout",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: global-only key in topic map",+ "rdkafka-hs-integration.producer-regressions.later delivery callback replaces the earlier callback",+ "rdkafka-hs-integration.producer-regressions.null native delivery frame reports the generic errno fallback without dereferencing a message",+ "rdkafka-hs-integration.producer-regressions.native delivery without an opaque Haskell callback preserves the complete record",+ "rdkafka-hs-integration.producer-regressions.delivery header acquisition failure preserves the outcome with empty headers",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.counter detects a retained native list before explicit release",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.pair conversion failure releases the partial list before GC",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.offset conversion failure releases the partial list before GC",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.ordinary input lists release after exact native results",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.native logical offsets decode independently without losing partition identity",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.missing native partition queue preserves assignment and later forwarding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.assignment outputs release after exact decoding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.subscription outputs release after exact decoding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.subscription acquisition failure preserves the native error without a list",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.assignment decoder failure releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.subscription decoder failure releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.cancellation at input allocation releases the owned list",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.cancellation at assignment return releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.pair conversion failure releases the partial list before GC",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.offset conversion failure releases the partial list before GC",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.ordinary input lists release after exact native results",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.native logical offsets decode independently without losing partition identity",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.missing native partition queue preserves assignment and later forwarding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.assignment outputs release after exact decoding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.subscription outputs release after exact decoding",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.subscription acquisition failure preserves the native error without a list",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.assignment decoder failure releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.subscription decoder failure releases the owned output",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.cancellation at input allocation releases the owned list",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.cancellation at assignment return releases the owned output",+ "rdkafka-hs-integration.public-contract.messages.batch conversion releases every returned native message",+ "rdkafka-hs-integration.public-contract.messages.native message counter detects a retained final object",+ "rdkafka-hs-integration.public-contract.messages.batch decoder exception releases unprocessed messages",+ "rdkafka-hs-integration.public-contract.messages.batch native header errors remain errors while later records are released",+ "rdkafka-hs-integration.public-contract.messages.batch cancellation at native return releases every acquired message",+ "rdkafka-hs-integration.public-contract.messages.batch cancellation at middle conversion releases every acquired message",+ "rdkafka-hs-integration.public-contract.messages.async single cancellation at native return releases its native message",+ "rdkafka-hs-integration.public-contract.messages.async single cancellation at inside conversion releases its native message",+ "rdkafka-hs-integration.public-contract.messages.sync single cancellation at native return releases its native message",+ "rdkafka-hs-integration.public-contract.messages.sync single cancellation at inside conversion releases its native message",+ "rdkafka-hs-integration.public-contract.messages.async header failure preserves the polled record origin",+ "rdkafka-hs-integration.public-contract.messages.sync header failure preserves the polled record origin",+ "rdkafka-hs-integration.public-contract.messages.async plain polling surfaces native header failure",+ "rdkafka-hs-integration.public-contract.messages.sync plain polling surfaces native header failure",+ "rdkafka-hs-integration.public-contract.messages.async attributed error preserves independently absent partition-and-offset",+ "rdkafka-hs-integration.public-contract.messages.async attributed error preserves independently absent offset",+ "rdkafka-hs-integration.public-contract.messages.async attributed error preserves independently absent partition",+ "rdkafka-hs-integration.public-contract.messages.sync attributed error preserves independently absent partition-and-offset",+ "rdkafka-hs-integration.public-contract.messages.sync attributed error preserves independently absent offset",+ "rdkafka-hs-integration.public-contract.messages.sync attributed error preserves independently absent partition",+ "rdkafka-hs-integration.public-contract.messages.callback-event polling cancellation releases a returned message",+ "rdkafka-hs-integration.public-contract.messages.callback buffer preserves attributed header failure",+ "rdkafka-hs-integration.public-contract.messages.callback buffer preserves plain header failure",+ "rdkafka-hs-integration.public-contract.messages.originless callback error survives seek filtering and a paused partition",+ "rdkafka-hs-integration.public-contract.messages.callback-event polling releases and discards a returned fatal frame",+ "rdkafka-hs-integration.public-contract.messages.zero batch size leaves the queued records available",+ "rdkafka-hs-integration.public-contract.messages.unsupported sync batch does not discard a record",+ "rdkafka-hs-integration.public-contract.messages.signed native batch failure preserves its error and queued data",+ "rdkafka-hs-integration.public-contract.messages.infinite batch timeout returns available records",+ "rdkafka-hs-integration.public-contract.messages.batch capacity 1 preserves complete ordered records across partial batches",+ "rdkafka-hs-integration.public-contract.messages.batch capacity 2 preserves complete ordered records across partial batches",+ "rdkafka-hs-integration.public-contract.messages.batch capacity 5 preserves complete ordered records across partial batches",+ "rdkafka-hs-integration.public-contract.messages.invalid batch array size is rejected before native acquisition: -1",+ "rdkafka-hs-integration.public-contract.messages.invalid batch array size is rejected before native acquisition: -9223372036854775808",+ "rdkafka-hs-integration.public-contract.messages.invalid batch array size is rejected before native acquisition: 9223372036854775807",+ "rdkafka-hs-integration.public-contract.messages.batch preserves complete records followed by exact partition EOF and idle timeout",+ "rdkafka-hs-integration.public-contract.messages.empty batch respects timeout 0",+ "rdkafka-hs-integration.public-contract.messages.empty batch respects timeout 100",+ "rdkafka-hs-integration.public-contract.diagnostics.supported-property print flushes and preserves the caller handle",+ "rdkafka-hs-integration.public-contract.diagnostics.client print flushes and preserves the caller handle",+ "rdkafka-hs-integration.public-contract.diagnostics.failed fdopen releases the duplicate and preserves the original",+ "rdkafka-hs-integration.public-contract.diagnostics.failed native flush is reported after closing the duplicate",+ "rdkafka-hs-integration.public-contract.diagnostics.producer configuration dumps retain exact explicit and global settings",+ "rdkafka-hs-integration.public-contract.diagnostics.producer constructor log level overrides the global property on the native client",+ "rdkafka-hs-integration.public-contract.diagnostics.consumer configuration dump preserves global settings after subscription merge",+ "rdkafka-hs-integration.public-contract.diagnostics.native dump counter detects an unreleased array",+ "rdkafka-hs-integration.public-contract.diagnostics.global cancellation at native acquisition releases its array",+ "rdkafka-hs-integration.public-contract.diagnostics.topic cancellation at native acquisition releases its array",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata counter detects an unreleased result",+ "rdkafka-hs-integration.public-contract.metadata-contract.native topic-constructor failure survives metadata convenience queries",+ "rdkafka-hs-integration.public-contract.metadata-contract.empty native metadata remains empty and releases every result",+ "rdkafka-hs-integration.public-contract.metadata-contract.timestamp lookup preserves native overall errors",+ "rdkafka-hs-integration.public-contract.metadata-contract.watermark queries preserve unknown partition errors and empty provided metadata",+ "rdkafka-hs-integration.public-contract.metadata-contract.topic identity replica sets and exact watermarks",+ "rdkafka-hs-integration.public-contract.metadata-contract.distinct native metadata fields retain exact identities and errors",+ "rdkafka-hs-integration.public-contract.metadata-contract.provided metadata preserves partition failures in convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.native metadata partition failures survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.group query timeout preserves initial metadata wait failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.missing topic errors survive convenience helpers",+ "rdkafka-hs-integration.public-contract.metadata-contract.timestamp lookup distinguishes before at and after actual record times",+ "rdkafka-hs-integration.public-contract.metadata-contract.mixed timestamp request preserves native partition failure",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata timeouts preserve the native error",+ "rdkafka-hs-integration.public-contract.metadata-contract.metadata native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.groups native acquisition cancellation releases its result",+ "rdkafka-hs-integration.public-contract.metadata-contract.async group identity lifecycle and supported native states",+ "rdkafka-hs-integration.public-contract.metadata-contract.sync group identity lifecycle and supported native states"+ ],+ "actual_nonthreaded_tests": 4,+ "apache_policy_case": {+ "tests": 1,+ "declared": "reject",+ "observed": "InvalidConfig; no topic created"+ },+ "memory": {+ "tool": "Valgrind 3.22.0",+ "parent_and_child_reports": 15,+ "invalid_access_errors": 0,+ "definite_bytes_lost": 0,+ "indirect_bytes_lost": 0,+ "retained_native_header_stacks": 0,+ "retained_test_seam_allocation_stacks": 0,+ "intentional_process_global_sasl_stacks": 225,+ "possible_RTS_worker_TLS": [+ {+ "path": "dist-compatibility/expanded-source9/native-phase9.134783.valgrind",+ "sha256": "f5985fed7d3760f65ed02e685feaf667e55c702e68eb66fd28ac49f1088dc89e"+ },+ {+ "path": "dist-compatibility/expanded-source9/native-phase9.134810.valgrind",+ "sha256": "50aabcae28231c2458a37b48e81951720c97f2d6482824790cfc6612ba02ae5b"+ }+ ],+ "RTS_explanation": "Only detached GHC worker-thread TLS stacks remain possibly lost (304 bytes per affected child); exact GHC 9.14.1 Task.c and posix/OSThreads.c are retained. The pure forkOn baseline did not reproduce this timing-dependent TLS observation. No project/native per-client stack is suppressed.",+ "global_SASL_explanation": "All retained stacks containing librdkafka allocation frames lead exclusively through rd_kafka_sasl_cyrus_global_init into Cyrus SASL process-global initialization. Tagged 2.16.0 source intentionally omits sasl_done because another application may share SASL. These are not per-message/client owners.",+ "suppression": "Only the independently reproduced 20-byte CapIOManager startup baseline is suppressed by exact RTS frames.",+ "controls": {+ "invalid_access_exit": 99,+ "stock_header_exit": 0,+ "mutant_header_exit": 99,+ "header_oracle": "Inspect all leak kinds and native allocation stacks, including still-reachable blocks. Stock has no rd_kafka_headers_new retention; deliberate cleanup omission has retained native headers. Earlier mutation replay exit 0 is preserved as evidence that a summary-only oracle can miss conservative GHC roots."+ }+ }+ },+ "discarded_attempts": [+ "Initial include path pointed one directory too deep for <librdkafka/rdkafka.h>; corrected without changing package bounds.",+ "Cabal retained the failed preprocessing timestamp; touching the unchanged .chs forced regeneration, after which the library built.",+ "Printing Text directly in a GHC expression lacked its Show instance scope; explicitly unpacking Text recorded the actual loaded version.",+ "The initial diagnostic smoke exited with native threads still reachable; it is superseded by the bounded GC/native-wait prototype with zero possible leaks."+ ],+ "artifacts": {+ "LeaderProbe.hs": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/LeaderProbe.hs",+ "sha256": "932cf2bec75d2ed20ed8193a8dd7a0ddc76a0240a79c6b002edd865b298388e9"+ },+ "Main.before-quiescence.hs": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/Main.before-quiescence.hs",+ "sha256": "747ae37d4feef1d5c312a2eaf3cbd4277ee3302cbf3429ee8f719d7863ec2044"+ },+ "Main.quiescence-prototype.hs": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/Main.quiescence-prototype.hs",+ "sha256": "ac4a5eaa3919656bb8b5972ee7c4946a70df2d279728b416e378e4f7f2d3c3f3"+ },+ "cabal-release-index.html": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/cabal-release-index.html",+ "sha256": "69a99efb30e065bef728e361988b0d214e8103eed10046c683b6ea451ecceb47"+ },+ "candidate.tar.gz": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/candidate.tar.gz",+ "sha256": "b02206dc4621d86226f15f6b8b88768e8e9e494b51cb13ec6746805ae1d367ba"+ },+ "configs-help.txt": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/configs-help.txt",+ "sha256": "f1a166d8d72e498d9e9452652708396f20a2b1036018f93b0e17d6f2ff56164e"+ },+ "counted-callback-tests.txt": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/counted-callback-tests.txt",+ "sha256": "cf065db5b874ead76036eb6b0e789170abb29840c6479f5d94adde2553b8841e"+ },+ "counted-callback.log": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/counted-callback.log",+ "sha256": "7e40ba7a1852908f5f2bc028698d9ac3a2b1da3c5a588a1f6da1e878d17e87ed"+ },+ "env.sh": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/env.sh",+ "sha256": "9cef400b820313b0f4551bc55f7e0c953086c7119f503a08e3b545b08de7fe38"+ },+ "fixture-default-policy.log": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/fixture-default-policy.log",+ "sha256": "a59f5deb54f0117897bc08637af9a82ee9b04577953061225471e2e827c0fdc6"+ },+ "ghc-release-index.html": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/ghc-release-index.html",+ "sha256": "f1f5b13b839e94ae7433ee7724742897a9ceed77c58f33df0a604c541a0da317"+ },+ "header-candidate.stdout": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/header-candidate.stdout",+ "sha256": "af9f07d6f4f9a76ed6084d55a6736ee70eca2196cecd1781ae7686de2c9150f0"+ },+ "header-control-tests.txt": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/header-control-tests.txt",+ "sha256": "d394d838c4cd0e475b98e59fd7b28b995de44536408cc72df32ca94b55519214"+ },+ "header-controls.sh": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/header-controls.sh",+ "sha256": "5fb43885558d317e7c182f32fe0f39ede2b729ef72ec75f6b459a1c62ce5fdc7"+ },+ "header-leak-build.log": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/header-leak-build.log",+ "sha256": "134cb8262034f9e8b6855f4b89f7ba6118489cd752341b502ac8a6369c50d1db"+ },+ "header-leak-mutation.py": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/header-leak-mutation.py",+ "sha256": "9153671bb14b4410dec0162f1382570c6469133576f918e01f504c8204dfa7d9"+ },+ "header-mutation.exit": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/header-mutation.exit",+ "sha256": "7e332bcee418f7d700927c946d36341f0651d6d90997b58d3d5441dec96b2e74"+ },+ "header-mutation.stdout": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/header-mutation.stdout",+ "sha256": "86f6903fea2d4d347698f5dc063f3fe055131c511679bfd7b5b181e0e6af6220"+ },+ "java-setup.log": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/java-setup.log",+ "sha256": "b5436b0410bc38a0d920cb84a2f23d6b5a84ea3505f001d7f5d9ef39a79268fe"+ },+ "kafka-release-index.html": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/kafka-release-index.html",+ "sha256": "4366ff9c9ca7dfb12e8094132a928b5cea8059ebfd8e57eb582fbc99b5ad5400"+ },+ "kafka-start.log": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/kafka-start.log",+ "sha256": "e04defe1b1b98ad409439177368842c1c2c2767a44aebe68c77066fa6e4ad02d"+ },+ "kafka.sha512": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/kafka.sha512",+ "sha256": "2536dc9204ce287a1816def8d68bfe049e860f780e7e65ea1c535c4e660dacee"+ },+ "kernel.txt": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/kernel.txt",+ "sha256": "0986a7c568207573585d452318a4b0b53fbefb2f6a2d689b2770da26e9a9b195"+ },+ "leader-build.log": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/leader-build.log",+ "sha256": "e76e214025478ec384c464ceb3edb651bedd5f56d97836ecc6de6bd833117ed2"+ },+ "leader-probe.log": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/leader-probe.log",+ "sha256": "8f82f2c0f05e3d73b2c5040b3de68b060d25c8d18abdfc29d8b52677183c4cf7"+ },+ "library-fresh.log": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/library-fresh.log",+ "sha256": "9ef91e90f838e94cebf1638a262aabe11be13f18dd9ecb9e3e329902a534065c"+ },+ "library-verbose.log": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/library-verbose.log",+ "sha256": "73773ee15e14d99cbee421df3872e6ac1f68a3d30c79929552705de65e494b59"+ },+ "linux-smoke-tests.json": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/linux-smoke-tests.json",+ "sha256": "50a4991e3ba780d80bb10559cb6c2bdd713f7d081da43513b379da4c798501d5"+ },+ "linux-smoke.log": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/linux-smoke.log",+ "sha256": "424fd29085e2e6e17a8ee6f090c5c4f748b41ba3014ae05e04c63f49de4f0468"+ },+ "loaded-libraries.log": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/loaded-libraries.log",+ "sha256": "1eadb3fce16b3a55fd4cc4a9a27eccefc277fd3e664fd3b76c75acccfa846e3a"+ },+ "loaded-native.log": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/loaded-native.log",+ "sha256": "6ec9b644a82e1dd0a2ec1c57250b4e2d3043deb9a608d8384f7ec30026876a93"+ },+ "native-build-hashes.txt": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/native-build-hashes.txt",+ "sha256": "05f329f3ba7a3d32827958ae606cdd6ba94c85305b4a5568e16679090ae37f7c"+ },+ "native-candidate.so.1": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/native-candidate.so.1",+ "sha256": "e4ebf0b82581b51a86a0d861a90c07004b0b1fec67ab71e409b572594846154f"+ },+ "native-header-mutation.so.1": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/native-header-mutation.so.1",+ "sha256": "be9e3a93250d151b24a578851fed6d784bdaa6e3b1813cb417f27d23ed90fe52"+ },+ "native-release.html": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/native-release.html",+ "sha256": "37a9dcbf689e646f66a2f0b2aaedb1ebe1e25e510777f68c16c13cb8cd88fcb6"+ },+ "nonthreaded-build.log": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/nonthreaded-build.log",+ "sha256": "8ce719e1acd9c5a7bca7d2b0be4994a4357d7dc3a4ebfdb2cfd4f34111e9d46b"+ },+ "nonthreaded-rts.txt": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/nonthreaded-rts.txt",+ "sha256": "4624cb69ac272748f36b86dca2969623bb2ce1a54d2f66dbbf5226ff74f36e3d"+ },+ "nonthreaded-runtime.log": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/nonthreaded-runtime.log",+ "sha256": "672324aa3d9a4099f5e114a1ffde606ab45dd044dc0663663545e41f81280352"+ },+ "nonthreaded-tests.txt": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/nonthreaded-tests.txt",+ "sha256": "24b751e0a51502cb8f7e98cd3b05c4980ea3dc578fa6421d9edbb76d6c321831"+ },+ "os-release.txt": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/os-release.txt",+ "sha256": "87458b3b1f1ca0e5c693ade771de7007c3783bdc692fa6b39eb6414bf2af2763"+ },+ "package-build.log": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/package-build.log",+ "sha256": "4c5d02022f2ac5a1c017ed0263f2117a2680978399f8faa656cf0ef7fa687e64"+ },+ "package-build.sh": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/package-build.sh",+ "sha256": "40ac7fbb04507c8b42826c474d5b164e3b5c9332dfc6944da91c0057045a533d"+ },+ "package-recovered.log": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/package-recovered.log",+ "sha256": "0370c2efbbce7adcf45841fe85014934c1998508f04670c8f362099b9e823a46"+ },+ "package-retry.log": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/package-retry.log",+ "sha256": "e51a5218486958c0d0397df09049d6380e8cb881804b5a9874b9a25def468665"+ },+ "package-retry.sh": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/package-retry.sh",+ "sha256": "d42bc4f364dc9922b4a44226e6eb96863c5370c043cee9d42444a2fb077670e6"+ },+ "prototype-quiescence.py": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/prototype-quiescence.py",+ "sha256": "b9931fd223546318197d354f1bf90a8f26f0c85bbaa69293bc45e9dd1ab5ff30"+ },+ "quiescence-build.log": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/quiescence-build.log",+ "sha256": "4038528f33baf64c514340de07d0f9707e8e08277c30a198fb34c9da2acb9be9"+ },+ "rdkafka_header.original.c": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/rdkafka_header.original.c",+ "sha256": "c82403e08653d0d19b39b5740a9477a838575361eab3c83451effaa809bf2175"+ },+ "restart-one.py": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/restart-one.py",+ "sha256": "88b578b3e71233c580474dfd890ebafc48a4ed412d76707faea03009a112db55"+ },+ "runtime.sh": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/runtime.sh",+ "sha256": "e5a4abd1fca16fd413e1184cba02799733591a389a2b3e9f30b958c661258eb6"+ },+ "setup.log": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/setup.log",+ "sha256": "3b10f0a5123241a5c401ac93e6c86e67c7a5538cfa52e3577ef9e169f01b11a7"+ },+ "setup.sh": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/setup.sh",+ "sha256": "0c4bcda82ae0b7620ce52b550b0ec869307eca971623103928eb4847ead66386"+ },+ "smoke.py": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/smoke.py",+ "sha256": "ccd36be50cf25e6d2403da5406fee357c24d8e4e8a5e79eaf83ab02a0c933269"+ },+ "smoke.sh": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/smoke.sh",+ "sha256": "e4fcfcead2f99175cc9608f03d941618dac18d2fd97143ead3f9d9094362d115"+ },+ "start-kafka.py": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/start-kafka.py",+ "sha256": "4e3bb507b55624513a7fdd72d10912e754c88620fc9a15e2011a58cb93fb69e8"+ },+ "storage-help.txt": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/storage-help.txt",+ "sha256": "59c2c0ba1636c777feab6b8b859dc8bb5f796e22ea3a059f7afc234a13bac928"+ },+ "valgrind-header-candidate.log": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/valgrind-header-candidate.log",+ "sha256": "062efe16a1df849980cfd3f82806da8d026ed2acaa23861bd92db746158200eb"+ },+ "valgrind-header-mutation.log": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/valgrind-header-mutation.log",+ "sha256": "6ab5dcbcd73374bb3942826ac98f73044132429d1b1a1d36af8bc2a655be165a"+ },+ "valgrind-invalid-control.log": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/valgrind-invalid-control.log",+ "sha256": "1a7d713b91061fbc2bc686b5ca4d269787a23b236e5f1cdca113223dc69ebc65"+ },+ "valgrind-invalid-control.stdout": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/valgrind-invalid-control.stdout",+ "sha256": "223d146ce867f09c836471f5067d7957c50c4426e4f941f340b46f41189839ab"+ },+ "valgrind-quiescent.log": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/valgrind-quiescent.log",+ "sha256": "4d6cd303990505b856bc398eb52973715023762983f70b7072e10a66803703c6"+ },+ "valgrind-quiescent.stdout": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/valgrind-quiescent.stdout",+ "sha256": "37ba41e918b7ea0f7f4c1f866348c9a9e5997a1c4225e4f0acd6513c0022d886"+ },+ "valgrind-smoke.log": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/valgrind-smoke.log",+ "sha256": "3c79a6948abdc7b64be9fc4ab973d02ae1dc011fbe9716d62b307d254628ef95"+ },+ "valgrind-smoke.stdout": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/valgrind-smoke.stdout",+ "sha256": "eee1b4e4cb52fb11a371d421fa8db3c5096243e673683ab5904af4a701902aa2"+ }+ },+ "continued_diagnostic_work": {+ "status": "partial cohorts not accepted; final replay required",+ "private_native_symbols": "Stock Linux exports hide three private error-flag setters required by inherited controls; diagnostic-only linker map exports exactly those three without copying opaque objects. Haskell preflight now fails explicitly if they are absent.",+ "metadata_fixture": "Distinct-field control now selects one broker from a real multi-node frame instead of aborting on broker_cnt > 1. Full native allocation retains its actual owner.",+ "runtime_baseline": "GHC 9.14.1 minimal main=pure() reproduces the same 20 definite bytes in five CapIOManager allocations. Exact upstream IOManager.c and a ten-frame suppression match only the RTS initialization stack; no project allocation or positive control is suppressed.",+ "interrupted_run": "The owned VM became unresponsive during concurrent Valgrind and Java cohorts; only that VM restarted. Neither partial cohort is accepted. Remaining cohorts run sequentially.",+ "artifacts": {+ "RtsBaseline.hs": {+ "path": "dist-compatibility/owned-fixture-checkpoint/RtsBaseline.hs",+ "sha256": "667b93357c3b851e3b4944dc2d8400540580440be59d5b75e9e6a12eb546e585"+ },+ "rts-baseline.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/rts-baseline.log",+ "sha256": "b853dc070bcd72d34eba8d220959b39b619086318aed79a6f890fdbb870326b9"+ },+ "rts-baseline-suppressed.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/rts-baseline-suppressed.log",+ "sha256": "7a20a2b619bce7ac929f70b7db4225cc3013298d3a0651511ba6397552cbf4a5"+ },+ "ghc914-IOManager.c": {+ "path": "dist-compatibility/owned-fixture-checkpoint/ghc914-IOManager.c",+ "sha256": "75b19a43809b3155ba6265c6c4bc73fab86ddfed4d17312ce5422fe4227714dc"+ },+ "ghc914-rts.supp": {+ "path": "dist-compatibility/owned-fixture-checkpoint/ghc914-rts.supp",+ "sha256": "c9b04b1b79da557d62a4183c4108a636646feadb4f025ff4439ae026121e48f4"+ },+ "native-diagnostic-exports.diff": {+ "path": "dist-compatibility/owned-fixture-checkpoint/native-diagnostic-exports.diff",+ "sha256": "ff6312086bba73e0e6891060f48f02540b38174dbcbc26c080b12b8655bceafb"+ },+ "diagnostic-export-symbols.txt": {+ "path": "dist-compatibility/owned-fixture-checkpoint/diagnostic-export-symbols.txt",+ "sha256": "b959a9d7f9aab8245708a13d9d605c7e32b01930ecc91372f5d848094830f873"+ },+ "native-full.stdout": {+ "path": "dist-compatibility/owned-fixture-checkpoint/native-full.stdout",+ "sha256": "d9a93a21c5b34100767a43ea4eb4074330d3f80f9c9215a9731631d57cb2828d"+ },+ "native-phase4.stdout": {+ "path": "dist-compatibility/owned-fixture-checkpoint/native-phase4.stdout",+ "sha256": "03686ed592108efc49b895798d98c38183bda1ad68f4662396ff9a04cbb465d9"+ }+ },+ "clean_archive_cohort": {+ "selected": 268,+ "test_failures": 2,+ "status": "failed, not accepted",+ "findings": [+ "A pending cancellation at final transaction decoder stage was observed after the worker had already stored a result; fixture handshake must define an explicit interrupt point.",+ "Apache abort-recovery path returns PURGE_QUEUE then abort-required OUT_OF_ORDER_SEQUENCE_NUMBER on its first small recovery record. Independent C API probe reproduces it without Haskell or test interposers.",+ "31 retained environment bytes are RDKAFKA_TEST_NATIVE_LIFETIME=1, created by Haskell setEnv/putenv; next heap cohort provides the flag externally instead of suppressing an allocation."+ ],+ "artifacts": {+ "native-phase5.54289.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/native-phase5.54289.log",+ "sha256": "1ff9de6272d75f19f03a24bd72eb3610a73b294203c21adbc3cffe4eb0f2f71b"+ },+ "native-phase5.54470.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/native-phase5.54470.log",+ "sha256": "09dd094ec398ef23b14816d2aabdfa44bac520fd3e4acd7a966325883917d14f"+ },+ "native-phase5.54302.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/native-phase5.54302.log",+ "sha256": "19d63b73e78c2979e3982ccf0aa7993aaec579cda05cec3c0338fbda2ae06e46"+ },+ "native-phase5.55633.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/native-phase5.55633.log",+ "sha256": "889e3d084e244c52b90a5cfe9972f29edb1b2f9c4ed5a85a4dcd2d000e6686fc"+ },+ "native-phase5.56955.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/native-phase5.56955.log",+ "sha256": "50c086a03468e58b5e9a1b5feb70b28157745661345dffd626fee200b8e734d4"+ },+ "native-phase5.54402.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/native-phase5.54402.log",+ "sha256": "bae84b013bb96aa386406ed1fca149fef407fa5ee64450499605c08e08efddde"+ },+ "native-phase5.54374.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/native-phase5.54374.log",+ "sha256": "eaf812713e5b4080747ca471c10e23ed0f617ab1282b3b90ecc66408d375b82a"+ },+ "native-phase5.54558.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/native-phase5.54558.log",+ "sha256": "0d7d311e98837dadf039c301a3e3555012ca6cc7ae5aed1c417dc433db359a64"+ },+ "native-phase5.54346.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/native-phase5.54346.log",+ "sha256": "c7b0dfd11351870cdede662c26049d2eb8423cb505007d0c288020baa1e61d0f"+ },+ "native-phase5.56977.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/native-phase5.56977.log",+ "sha256": "0a6ae6a8ac87ced7b93d0c0138f60df9a1c27a577370c8f5c7a974b0772791ae"+ },+ "native-phase5.54431.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/native-phase5.54431.log",+ "sha256": "15ced8329395c7b33cf620ffa9504a6ea55f6c341289b25ed30355f819b8c5b6"+ },+ "native-phase5.54326.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/native-phase5.54326.log",+ "sha256": "bf04c98c0d8286f413068be0ec423d267553ad119406dd1e8dcfc2fa6b69e982"+ },+ "native-phase5.54450.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/native-phase5.54450.log",+ "sha256": "b274f53115c62fbcca424718a34f0c565bac54651697b1b3ed19a96e7096f632"+ },+ "native-phase5.55610.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/native-phase5.55610.log",+ "sha256": "ea71d6504459718e55e5a8fe4d50c00f0fc5fd2ade54d50bc9ea45f8bd9a8364"+ },+ "native-phase5.54490.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/native-phase5.54490.log",+ "sha256": "eaace94dd5eba3bd1e1f1090c3aeb335d07e81c32afa7438bc51dbbc991c8a30"+ },+ "isolate-lifecycle.59405.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/isolate-lifecycle.59405.log",+ "sha256": "8295567961f0deb9d4a777dac10da4091fd0902f15c160cd009b0f68c92f22d5"+ },+ "isolate-lifecycle.59363.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/isolate-lifecycle.59363.log",+ "sha256": "7721c4ec46fbdd594702fd5117fb62147466888b036adc417382e8669ed9e894"+ },+ "isolate-lifecycle.60694.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/isolate-lifecycle.60694.log",+ "sha256": "93e9e48cea94ec805c624f8f6125a68536fa48f4b12e53073389d3b28dc7dc64"+ },+ "isolate-lifecycle.59348.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/isolate-lifecycle.59348.log",+ "sha256": "280ba3cac72a7ee78589383ff788afbcce7958af1e36df0385246f2826a41417"+ },+ "isolate-messages.58561.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/isolate-messages.58561.log",+ "sha256": "343d35a8a013cea36c874648d00d06f05fdfe489ffa490d04002b9761fc7f50c"+ },+ "isolate-lifecycle.60241.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/isolate-lifecycle.60241.log",+ "sha256": "5bf87ffa48f287ce56a54bef0d636e87d7ec9f9115f21f031e043074b24a41a0"+ },+ "isolate-lists.59019.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/isolate-lists.59019.log",+ "sha256": "d21ea314cfb41a7b915aa52ed819649c9dd54c51430166a5f7e1866dce032817"+ },+ "isolate-lifecycle.60281.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/isolate-lifecycle.60281.log",+ "sha256": "014a87d2f379ecea749f5b69b7dfef9e532d40149f1c46885e55fe668d8daac6"+ },+ "isolate-metadata.58456.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/isolate-metadata.58456.log",+ "sha256": "72b2fd39e174769390708b5a6f10655b6cdbd061c84ada04367e3097216c137a"+ },+ "isolate-external-transactions.62344.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/isolate-external-transactions.62344.log",+ "sha256": "bbe825949243755b215aee777979aec9d3af17c06a4181c777fe65330076a5c5"+ },+ "isolate-diagnostics.58502.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/isolate-diagnostics.58502.log",+ "sha256": "9f7f761c2f4e31b5a4e29e69ea497679d2305e45de1fd8b82a0878189e31e1a2"+ },+ "isolate-transactions.57081.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/isolate-transactions.57081.log",+ "sha256": "73cb0ba634b1f15fe30de275bb78dcd3a527e27e12d49d22df96a831d700ccbf"+ },+ "isolate-producer.57837.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/isolate-producer.57837.log",+ "sha256": "9198f653f10e5778af5e1d36d1c9a8462c2897d9cfce83179e117b836b403215"+ },+ "isolate-producer.57765.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/isolate-producer.57765.log",+ "sha256": "250f65a3ec6d0ad66f7b2c0e69118ef41b2cd209b69d2d2b365de3dbc5ccdba9"+ },+ "isolate-lifecycle.60221.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/isolate-lifecycle.60221.log",+ "sha256": "a34b72f4779a76b55e0aedb6ed39204ddfbb7c022f73b1988872ca7bd23f77c0"+ },+ "isolate-metadata.58389.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/isolate-metadata.58389.log",+ "sha256": "b218b7841a36d20130f0182920c26401e6a43f7b8118950e149101f5223c40f8"+ },+ "isolate-lifecycle.59453.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/isolate-lifecycle.59453.log",+ "sha256": "136a0f762453d550061bb5f6d945b947377a09afbe7d9fbfca24c81e0de3e0a9"+ },+ "isolate-producer.57815.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/isolate-producer.57815.log",+ "sha256": "8d09079cd2986c7db8aa568c096af9e31c58868c7f63d7c6bba34f598002accf"+ },+ "isolate-metadata.58275.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/isolate-metadata.58275.log",+ "sha256": "d8b50d15af85fdbdb36c984a1976ed5de56a4ec6e4ed8a0d17226abb77110928"+ },+ "isolate-lifecycle.59426.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/isolate-lifecycle.59426.log",+ "sha256": "abc5311a0135013f494a6e14a08c139f99b03b6afd85896251e14d255a158ffe"+ },+ "isolate-lifecycle.60261.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/isolate-lifecycle.60261.log",+ "sha256": "168a701aa1cc75720e08bdb3330ca8b6016ccedfb6ee96a892c5f215c17173a2"+ },+ "isolate-lifecycle.59385.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/isolate-lifecycle.59385.log",+ "sha256": "d5fa6f375e3036e7e3754e73b5eb13a48ea06c36879abe30e45eb8f71a0885bc"+ },+ "native-phase5.stdout": {+ "path": "dist-compatibility/owned-fixture-checkpoint/native-phase5.stdout",+ "sha256": "ddf3389e4d786c804fd3420d917ed87ef859cc57f91404cc544226f9a7d067cd"+ },+ "native-phase5-command.json": {+ "path": "dist-compatibility/owned-fixture-checkpoint/native-phase5-command.json",+ "sha256": "4a3afd041d6ed5eb0b5d03e6334783aff35a14c4bd8e8d68d4c32b0528278b04"+ },+ "native-phase5-tests.json": {+ "path": "dist-compatibility/owned-fixture-checkpoint/native-phase5-tests.json",+ "sha256": "bfc155dd99daabf5a6cd53f56cc771bcafee3a7ec1505806bb54ef68a47ba438"+ },+ "native-isolate-progress.log": {+ "path": "dist-compatibility/owned-fixture-checkpoint/native-isolate-progress.log",+ "sha256": "caddaa7b6230dd3446bf4b0f55b1805131343a00739ee0894b63a26b7a28af46"+ },+ "native-isolate-results.json": {+ "path": "dist-compatibility/owned-fixture-checkpoint/native-isolate-results.json",+ "sha256": "b33cc0a95a64bc42c66c0b8241f1396e9e6463964a7a5d9fe955454e4f6339ea"+ },+ "trace31.c": {+ "path": "dist-compatibility/owned-fixture-checkpoint/trace31.c",+ "sha256": "4a69e06daf876ee4ede244dfc459aeee62d8ab65fd9bc8c82587c9c5b5bd188e"+ },+ "trace31.stdout": {+ "path": "dist-compatibility/owned-fixture-checkpoint/trace31.stdout",+ "sha256": "5e30339161d4d0669c82c6627aa1c8f7a8a97be3611fd925f30e8cae6b7d3582"+ },+ "ghc914-Environment.hs": {+ "path": "dist-compatibility/owned-fixture-checkpoint/ghc914-Environment.hs",+ "sha256": "7d815aa6f55e3b93e057506ebdf45824a331369b3c6630575d6de85a76c72863"+ },+ "TxProbe.c": {+ "path": "dist-compatibility/owned-fixture-checkpoint/TxProbe.c",+ "sha256": "ece677f4d542ff4bf6b242b30a79976ec7048d7bfdb342bedd0fae3b6afabb8e"+ },+ "tx-c-probe-recovery.stdout": {+ "path": "dist-compatibility/owned-fixture-checkpoint/tx-c-probe-recovery.stdout",+ "sha256": "69e00b25f7c6e95bbc7630378453d05ce8abf6af0deb07c2167a0ba33f5e01ab"+ },+ "kafka440-features.txt": {+ "path": "dist-compatibility/owned-fixture-checkpoint/kafka440-features.txt",+ "sha256": "ae488e65d55150668e17b768cca3ee4bbda5fb44a77a534b201d5c177b15e3a9"+ }+ }+ }+ },+ "later_attempts": [+ {+ "label": "phase7",+ "accepted": false,+ "behavioral_tests_passed": 279,+ "seconds": 229.68,+ "finding": "Valgrind retains two native topics (2176 direct +427 indirect bytes) because new public-message fault modes 24/25 temporarily clear rkt but did not restore it before real native message destruction. Fixture cleanup now restores original rkt and err as well as partition/offset; fresh source replay is required.",+ "artifacts": {+ "native-phase7.stdout": {+ "path": "dist-compatibility/expanded-recovery-checkpoint/native-phase7.stdout",+ "sha256": "4cde75846e7960a3f6c3c9588ba1703df9eb87532b92d1386d4c8f8b5c1ea38f"+ },+ "native-phase7.95421.log": {+ "path": "dist-compatibility/expanded-recovery-checkpoint/native-phase7.95421.log",+ "sha256": "a1f09a800754c2d9f30951023f341f03a18b46c8f12ad615361677ffaac66e8c"+ },+ "native-phase7-command.json": {+ "path": "dist-compatibility/expanded-recovery-checkpoint/native-phase7-command.json",+ "sha256": "1495a5f70635b2631041c49628ec26a090d31f6577fdefbaf73722e2d01894e5"+ },+ "native-phase7-tests.json": {+ "path": "dist-compatibility/expanded-recovery-checkpoint/native-phase7-tests.json",+ "sha256": "5c0ad609423f4578b70c8ff6e10a8a875b14f4613cdc7d8fc1a49ca710a620c6"+ },+ "candidate-phase7-receipt.json": {+ "path": "dist-compatibility/expanded-recovery-checkpoint/candidate-phase7-receipt.json",+ "sha256": "14af1e7c85bd26c7377c18cefb1c4d72441fb82144a9ff5a4972ee8ce3983fa0"+ }+ }+ }+ ],+ "initial_checkpoint": {+ "source": {+ "project": "mori://shinzui/rdkafka-hs",+ "candidate_fingerprint": "eb6352fe62c75ec289a0a5f543ed0692106d24f3370ddb46ef31f0188410b14a",+ "archive": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/candidate.tar.gz",+ "sha256": "b02206dc4621d86226f15f6b8b88768e8e9e494b51cb13ec6746805ae1d367ba"+ },+ "qualification_prototype": "The native-lifetime mode is an explicitly recorded modification of test-integration/Main.hs. Its before/after bytes and transformation are retained; native diagnostic outcomes are prototype evidence, not final candidate qualification."+ },+ "environment": {+ "os": "PRETTY_NAME=\"Ubuntu 24.04.5 LTS\"\nNAME=\"Ubuntu\"\nVERSION_ID=\"24.04\"\nVERSION=\"24.04.5 LTS (Noble Numbat)\"\nVERSION_CODENAME=noble\nID=ubuntu\nID_LIKE=debian\nHOME_URL=\"https://www.ubuntu.com/\"\nSUPPORT_URL=\"https://help.ubuntu.com/\"\nBUG_REPORT_URL=\"https://bugs.launchpad.net/ubuntu/\"\nPRIVACY_POLICY_URL=\"https://www.ubuntu.com/legal/terms-and-policies/privacy-policy\"\nUBUNTU_CODENAME=noble\nLOGO=ubuntu-logo\n",+ "kernel": "Linux 6.18.15 aarch64",+ "architecture": "aarch64",+ "ghc": "9.14.1",+ "cabal": "3.16.1.0",+ "loaded_libraries": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/loaded-libraries.log",+ "sha256": "1eadb3fce16b3a55fd4cc4a9a27eccefc277fd3e664fd3b76c75acccfa846e3a"+ },+ "native_binary": {+ "path": "dist-compatibility/linux-arm64-ghc9141-native2160-apache440/native-candidate.so.1",+ "sha256": "e4ebf0b82581b51a86a0d861a90c07004b0b1fec67ab71e409b572594846154f"+ },+ "native_version": "2.16.0",+ "loaded_native_identity": {+ "version": "2.16.0",+ "number": 34603263,+ "path": "/opt/librdkafka-2.16.0/lib/librdkafka.so.1",+ "sha256": "e4ebf0b82581b51a86a0d861a90c07004b0b1fec67ab71e409b572594846154f",+ "observed": "(\"2.16.0\",34603263)"+ },+ "broker_version": "Apache Kafka 4.4.0",+ "broker_topology": "Three owned combined broker/controllers, IDs 1/2/3 on loopback 41092/42092/43092; broker default min ISR 1 for single-replica inherited fixtures; failover topic replication 3 and min ISR 2"+ },+ "results": {+ "components_built": [+ "library",+ "examples",+ "unit suite",+ "integration suite"+ ],+ "unit": 78,+ "broker_smoke": 14,+ "counted_callback_teardown": 2,+ "nonthreaded": 4,+ "normal_smoke_tests": [+ "rdkafka-hs-integration.callback-lifetime.async error callback releases after destroy with retained wrapper",+ "rdkafka-hs-integration.callback-lifetime.sync error callback releases after destroy with retained wrapper",+ "rdkafka-hs-integration.transaction-errors.transaction-error-leak-probe releases 300 immediate native errors",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.async.native logical offsets decode independently without losing partition identity",+ "rdkafka-hs-integration.public-contract.partition-list-ownership.sync.native logical offsets decode independently without losing partition identity",+ "rdkafka-hs-integration.public-contract.messages.batch capacity 1 preserves complete ordered records across partial batches",+ "rdkafka-hs-integration.public-contract.messages.batch capacity 2 preserves complete ordered records across partial batches",+ "rdkafka-hs-integration.public-contract.messages.batch capacity 5 preserves complete ordered records across partial batches",+ "rdkafka-hs-integration.public-contract.runtime-contract.RTS capability is observed by async construction",+ "rdkafka-hs-integration.public-contract.runtime-contract.explicit async construction checks the runtime",+ "rdkafka-hs-integration.public-contract.runtime-contract.sync subscription delivers an exact record",+ "rdkafka-hs-integration.public-contract.runtime-contract.deprecated sync runner closes after an exact record",+ "rdkafka-hs-integration.seek-partitions.async.single seek replays exact record",+ "rdkafka-hs-integration.seek-partitions.sync.single seek replays exact record"+ ],+ "valgrind": {+ "version": "3.22.0",+ "invalid_access_control": "Two freed-configuration reads in native rd_kafka_conf_get and the Haskell/C bridge were detected.",+ "quiescent_smoke": "Eight cases passed; zero errors and zero definite, indirect or possible leaks; no suppressions.",+ "header_candidate": "Exact NoCompression header roundtrip passes with zero errors and no definite/indirect/possible leaks.",+ "header_mutation": "Omitting native rd_kafka_headers_destroy cleanup is detected under actual produceva: 48 bytes definitely and 210 bytes indirectly lost; exit 99.",+ "limit": "Reachable RTS/library allocations are retained separately. Complete ownership scenarios, final quiescent runner and current candidate replay remain required."+ }+ }+ },+ "previous_native_checkpoint": {+ "fingerprint": "4a4d041b2c440f9ee9e53ae0291b07835afa4cbb4677ed722447d57e6d906606",+ "tests": 279,+ "seconds": 234.81,+ "valgrind_exit": 0,+ "invalid_accesses": 0,+ "definite_and_indirect_leaks": 0,+ "limitations": "Two child logs retain 304-byte possible TLS allocations exclusively in GHC createAttachedOSThread/createOSThread/startWorkerTask stacks. Tagged GHC Task.c and posix/OSThreads.c show these are detached RTS workers. No project stack is suppressed. Full allocation-stack inspection remains in progress: conservative stale words in GHC heap can make deliberate native header leaks appear still reachable, so a zero-error summary alone is not sufficient.",+ "control_replay": "Actual invalid-access control exits 99; stock header path has no retained rd_kafka_headers_new stack. The same mutant library initially exits 0, then detailed all-leak-kind replay exposes header retention and exits 99. Preserve both outcomes; use allocation stacks as the oracle.",+ "artifact_directory": "dist-compatibility/expanded-source8"+ },+ "accepted_final_artifacts": {+ "native-phase9.134763.valgrind": {+ "path": "dist-compatibility/expanded-source9/native-phase9.134763.valgrind",+ "sha256": "bf5f0a40255d062fd2f9e59e66d1267748bdbcaea39cf26b3298e97ab9fdcca3"+ },+ "phase9-package-check.log": {+ "path": "dist-compatibility/expanded-source9/phase9-package-check.log",+ "sha256": "a19b4064f1acadadad1e1f24beae3785b778a6c5baabde7f333e4dacb7191d30"+ },+ "v216-sasl-cyrus.c": {+ "path": "dist-compatibility/expanded-source9/v216-sasl-cyrus.c",+ "sha256": "0a1781f34535d192b404464afaa9466a39d2246b93e3593fc2161c5d166b6153"+ },+ "native-phase9-binary": {+ "path": "dist-compatibility/expanded-source9/native-phase9-binary",+ "sha256": "4da060580b375bfe31242b6b1e421801d54ddda9b7ffd332cc867e785ae7bb97"+ },+ "native-header-mutant9.log": {+ "path": "dist-compatibility/expanded-source9/native-header-mutant9.log",+ "sha256": "f32c3efd2f92b7c1c06ff6f33e9afb5c82be7b27d39e01d3fabbfbe76503e9c3"+ },+ "current-source.json": {+ "path": "dist-compatibility/expanded-source9/current-source.json",+ "sha256": "c4bf1202261f924377da4e1d6f259b3966aaef85949c6fb648ff58133188c72d"+ },+ "native-phase9.134628.valgrind": {+ "path": "dist-compatibility/expanded-source9/native-phase9.134628.valgrind",+ "sha256": "58c94ed0ad90cf7d3cd7630ca457ca299a973124a16f0e3869a86ef3742748b4"+ },+ "nonthreaded-build9.log": {+ "path": "dist-compatibility/expanded-source9/nonthreaded-build9.log",+ "sha256": "367db75d4bd65ea9f4e08a4836567f2f60183e3fa7c14595da5c79e212b3a16f"+ },+ "authentication-final9-tests.txt": {+ "path": "dist-compatibility/expanded-source9/authentication-final9-tests.txt",+ "sha256": "e011f6a1ed4544904bc4117ebdd30e85339b33c096b3d0619bbff506f5e2e893"+ },+ "ghc9124-Marshal-Array.hs": {+ "path": "dist-compatibility/expanded-source9/ghc9124-Marshal-Array.hs",+ "sha256": "0a0cb7e36925c5332e5fb4dda03ad11f10b1ffa0e96d71e56de657d32f52216d"+ },+ "qualification9-progress.log": {+ "path": "dist-compatibility/expanded-source9/qualification9-progress.log",+ "sha256": "725e4e551f9a122dd698b2817f5594c4b5e4fcf7846f0f1e7ae1366710356b84"+ },+ "native-phase9.135889.valgrind": {+ "path": "dist-compatibility/expanded-source9/native-phase9.135889.valgrind",+ "sha256": "daf316120d8eb7905496bed39920d6110e920435b3cc69999b8b6e76d1c48af5"+ },+ "darwin-asan-version.log": {+ "path": "dist-compatibility/expanded-source9/darwin-asan-version.log",+ "sha256": "250f23c2a7b1b6ea32218ce5efdac3d157db099342c29485f788af715e16c473"+ },+ "native-phase9.134698.valgrind": {+ "path": "dist-compatibility/expanded-source9/native-phase9.134698.valgrind",+ "sha256": "4376d4163b9981a461f8ca04a022c15b675546f63e4a0dc9b7ca840885dd52b8"+ },+ "v215-subscription.c": {+ "path": "dist-compatibility/expanded-source9/v215-subscription.c",+ "sha256": "8a9134c343f9d7bf40eaaf00d19caa6ca505afa98bdf739763a4f7ba2b4c7f68"+ },+ "darwin-native-receipt.json": {+ "path": "dist-compatibility/expanded-source9/darwin-native-receipt.json",+ "sha256": "ab74ca68a62aa0a601d7d8f6782807c46fe5437bc102430b85ea79360bbb0b83"+ },+ "ghc914-IOManager.c": {+ "path": "dist-compatibility/expanded-source9/ghc914-IOManager.c",+ "sha256": "75b19a43809b3155ba6265c6c4bc73fab86ddfed4d17312ce5422fe4227714dc"+ },+ "darwin-asan-candidate.log": {+ "path": "dist-compatibility/expanded-source9/darwin-asan-candidate.log",+ "sha256": "bed5ff95177992d5ec812468fa79432c938c50d61928bb88344f2a951a4b8d36"+ },+ "native-phase9.134648.valgrind": {+ "path": "dist-compatibility/expanded-source9/native-phase9.134648.valgrind",+ "sha256": "b9ce9b6934221126ec8ea00174f960fe2b061b22a0c9519b46ac6217eafe001d"+ },+ "root-functional-files.json": {+ "path": "dist-compatibility/expanded-source9/root-functional-files.json",+ "sha256": "69506c90cfc124f3a175a664873f5d8b49aff62a7426265c56c3dd64fcc84c21"+ },+ "native-phase9.134587.valgrind": {+ "path": "dist-compatibility/expanded-source9/native-phase9.134587.valgrind",+ "sha256": "77e4a2a6e9d04ee4f22f8649cf8c47ae328027669411eb277e1c3b697efca613"+ },+ "phase9-version.log": {+ "path": "dist-compatibility/expanded-source9/phase9-version.log",+ "sha256": "6ec9b644a82e1dd0a2ec1c57250b4e2d3043deb9a608d8384f7ec30026876a93"+ },+ "ghc914-rts.supp": {+ "path": "dist-compatibility/expanded-source9/ghc914-rts.supp",+ "sha256": "c9b04b1b79da557d62a4183c4108a636646feadb4f025ff4439ae026121e48f4"+ },+ "coverage-strict.log": {+ "path": "dist-compatibility/expanded-source9/coverage-strict.log",+ "sha256": "542cc685cf514e26aec1535c91dba78ce90b78baacf3eebe98e98afc47a43222"+ },+ "phase9-unit.log": {+ "path": "dist-compatibility/expanded-source9/phase9-unit.log",+ "sha256": "1e9125e7cda4a5a18944f368fde934dc8a4b1900d981189931e1fa0632fe7f09"+ },+ "native-phase9-tests.txt": {+ "path": "dist-compatibility/expanded-source9/native-phase9-tests.txt",+ "sha256": "b831efa655febe0285f836ab1723191edd5adf33c462cd4974a0244c2ef75648"+ },+ "ghc9124-Storable.hs": {+ "path": "dist-compatibility/expanded-source9/ghc9124-Storable.hs",+ "sha256": "dda27f3c55cda6fbce4d44c127b6b26f5f18aa1e8b7ade6510e51cd4eec9e9cd"+ },+ "native-phase9.134670.valgrind": {+ "path": "dist-compatibility/expanded-source9/native-phase9.134670.valgrind",+ "sha256": "d3257f8515d736c3d4c2946db63b91c82a1c7a32cb3e58dc820c84c4609d325e"+ },+ "tuple9-environment.json": {+ "path": "dist-compatibility/expanded-source9/tuple9-environment.json",+ "sha256": "bbcb28035890918e115956be97a6cca328d0d6584f751b18c79bd9890d894065"+ },+ "ghc914-Task.c": {+ "path": "dist-compatibility/expanded-source9/ghc914-Task.c",+ "sha256": "f911aeccd0076d6091567a1842e9dbe3733f5a9e134b107c8f4e1c833745b907"+ },+ "coverage-allow-open.log": {+ "path": "dist-compatibility/expanded-source9/coverage-allow-open.log",+ "sha256": "6aaeb4a62ef5152f0f1adf20bb654b54b8fe12f057b757150972ebe61992fb7a"+ },+ "nonthreaded-runtime9.log": {+ "path": "dist-compatibility/expanded-source9/nonthreaded-runtime9.log",+ "sha256": "64f2de222b1848528141d2f18cf942adeedf21ade725229e19805a236d33f516"+ },+ "darwin-native-candidate": {+ "path": "dist-compatibility/expanded-source9/darwin-native-candidate",+ "sha256": "b927f6f6ccda06a50269df2156f524108c7d735995aad643e1cc61d9f3ae7d5f"+ },+ "v216-subscription.c": {+ "path": "dist-compatibility/expanded-source9/v216-subscription.c",+ "sha256": "8a9134c343f9d7bf40eaaf00d19caa6ca505afa98bdf739763a4f7ba2b4c7f68"+ },+ "native-phase9.135909.valgrind": {+ "path": "dist-compatibility/expanded-source9/native-phase9.135909.valgrind",+ "sha256": "7553908191c3cae5343f631ddef08d0d4f679c5a536e6815711cf3a5513b067e"+ },+ "native-header-stock9.log": {+ "path": "dist-compatibility/expanded-source9/native-header-stock9.log",+ "sha256": "64006cdb72c4dbb7654549faedba32d9e4291dc888218bcae308b537339aa2a5"+ },+ "primary-measured9-with-contexts.json": {+ "path": "dist-compatibility/expanded-source9/primary-measured9-with-contexts.json",+ "sha256": "9a98d410cbeb3ef8ce0e3d99f39d989dbf145ee434db9aedf7aa771c52922ffe"+ },+ "phase9-build.log": {+ "path": "dist-compatibility/expanded-source9/phase9-build.log",+ "sha256": "15848881c353039514fedb23424160586241f4cc00332ac11283b414d901675d"+ },+ "darwin-version-candidate": {+ "path": "dist-compatibility/expanded-source9/darwin-version-candidate",+ "sha256": "b3285ab47834bea5f592ba3bcf973b6433d5294c9d6a259c4e31370ead063f8f"+ },+ "native-phase9.134810.valgrind": {+ "path": "dist-compatibility/expanded-source9/native-phase9.134810.valgrind",+ "sha256": "50aabcae28231c2458a37b48e81951720c97f2d6482824790cfc6612ba02ae5b"+ },+ "native-phase9.134743.valgrind": {+ "path": "dist-compatibility/expanded-source9/native-phase9.134743.valgrind",+ "sha256": "d564ffaa8319d5e295bc1b583d08b8b615bee9e02682b16199df8d344279ca92"+ },+ "phase9-diagnostic-identity.log": {+ "path": "dist-compatibility/expanded-source9/phase9-diagnostic-identity.log",+ "sha256": "b5e947e38cfa999d968be7abd53685be88beb01ac33c6191db9c34ec24554a6d"+ },+ "native-header-stock9.valgrind": {+ "path": "dist-compatibility/expanded-source9/native-header-stock9.valgrind",+ "sha256": "b30e9245641fa29f53468b1b491ad4c62436ce4502a9ad9a6579ab54b78208c6"+ },+ "phase9-loaded.log": {+ "path": "dist-compatibility/expanded-source9/phase9-loaded.log",+ "sha256": "0ea352a045eddd425369467d19eef2c60d2ca235538e1335b9557897a003d120"+ },+ "primary-mapped9.log": {+ "path": "dist-compatibility/expanded-source9/primary-mapped9.log",+ "sha256": "563e4fcf86cd2047cea629df6837a502e4795dca676f96671655b9758eacf6c8"+ },+ "native-phase9.log": {+ "path": "dist-compatibility/expanded-source9/native-phase9.log",+ "sha256": "951b4b7b5d1b30800ea4699fe604aaf4a9e04a5a290570ff02afc1283569faf3"+ },+ "primary-measured9.json": {+ "path": "dist-compatibility/expanded-source9/primary-measured9.json",+ "sha256": "34c5f6a7adfebf78d56084fd34bc8ea50cc4ceb5dbba82e067574ab10f7d58e3"+ },+ "qualification9-results.json": {+ "path": "dist-compatibility/expanded-source9/qualification9-results.json",+ "sha256": "e0915ee5d4e748697d3ddab61599eea0ff74ea3db67aa1ae5c4e2b747491a7d1"+ },+ "configuration.json": {+ "path": "dist-compatibility/expanded-source9/configuration.json",+ "sha256": "c6c0771e7da58c35d40170db3ec18cdd2439997e223ef4c088ac3f4e793707f9"+ },+ "native-phase9.137396.valgrind": {+ "path": "dist-compatibility/expanded-source9/native-phase9.137396.valgrind",+ "sha256": "e527e901e42638741bd6fda76dc782ef6bf1a7678b08659248721418293d64fa"+ },+ "native-header-mutant9.valgrind": {+ "path": "dist-compatibility/expanded-source9/native-header-mutant9.valgrind",+ "sha256": "8501cc160b066a23f74d0c79ac66f7c3a61407b5db4c61fa62dbb85bc5098337"+ },+ "apache-policy9.log": {+ "path": "dist-compatibility/expanded-source9/apache-policy9.log",+ "sha256": "619f1dacc2a5c8f5e4fa510ce8d50ef9490183a6e2a9078da8c6a023eaecec7c"+ },+ "primary-normal9.log": {+ "path": "dist-compatibility/expanded-source9/primary-normal9.log",+ "sha256": "0cc78933babadbb7d223879eb76ddd60513010cfab5cd282a0e4ee974a52faeb"+ },+ "candidate.tar.gz": {+ "path": "dist-compatibility/expanded-source9/candidate.tar.gz",+ "sha256": "a70e4839d24c5e5179ff9a8be48643951e185d604cd8ba3401587730279f3b22"+ },+ "ghc914-OSThreads.c": {+ "path": "dist-compatibility/expanded-source9/ghc914-OSThreads.c",+ "sha256": "762b8e71d1e99327338a4614efa1d2a0283ae6bf9dcdeecb96a9d81cae9986a3"+ },+ "phase9-functional-files.json": {+ "path": "dist-compatibility/expanded-source9/phase9-functional-files.json",+ "sha256": "d0e5d59aa49833ecd1305410c839cbebdbbb418679cecc6de0c2548b142dca4b"+ },+ "broker-final9.log": {+ "path": "dist-compatibility/expanded-source9/broker-final9.log",+ "sha256": "f9236628ae671ffa549c4c9ce17ba8ba1acaf5f69e066acfe4ebfe94bd303681"+ },+ "rdkafka-mp3-historical-native-trace9.log": {+ "path": "dist-compatibility/expanded-source9/rdkafka-mp3-historical-native-trace9.log",+ "sha256": "5c787df34cea6516047d39e72a4a327864bf83ec560fef3f8f829b0c51a08979"+ },+ "context-registration.log": {+ "path": "dist-compatibility/expanded-source9/context-registration.log",+ "sha256": "49b53b3006255e8436a31adb5efbbd3eaa2a41e15fbe9cd6cb382bfe896767dd"+ },+ "native-phase9.134725.valgrind": {+ "path": "dist-compatibility/expanded-source9/native-phase9.134725.valgrind",+ "sha256": "29662c22c1f41b856536061098d484b3b5a8b3328d06229ec2844c998fdca278"+ },+ "fixture-cleanup.json": {+ "path": "dist-compatibility/expanded-source9/fixture-cleanup.json",+ "sha256": "22a1434a32c0b23c77e8cb0f788c46ca45dc4129ff55add57033437db77be5aa"+ },+ "native-diagnostic-exports.diff": {+ "path": "dist-compatibility/expanded-source9/native-diagnostic-exports.diff",+ "sha256": "ff6312086bba73e0e6891060f48f02540b38174dbcbc26c080b12b8655bceafb"+ },+ "authentication-final9.log": {+ "path": "dist-compatibility/expanded-source9/authentication-final9.log",+ "sha256": "a9cc23df591ca6608c613090bf42ae57ece89c1dc3e3ede7bbc0dee1cbcd2457"+ },+ "native-phase9.137374.valgrind": {+ "path": "dist-compatibility/expanded-source9/native-phase9.137374.valgrind",+ "sha256": "2914657723d38601197d8565fe5e9464898efad60b82b004bf8a8afb18ccca05"+ },+ "current-environment.json": {+ "path": "dist-compatibility/expanded-source9/current-environment.json",+ "sha256": "bef1715288957bc95f9acbfdb84ba444209ecbb886070a71a980129741ceda29"+ },+ "native-phase9.134783.valgrind": {+ "path": "dist-compatibility/expanded-source9/native-phase9.134783.valgrind",+ "sha256": "f5985fed7d3760f65ed02e685feaf667e55c702e68eb66fd28ac49f1088dc89e"+ },+ "native-invalid9.valgrind": {+ "path": "dist-compatibility/expanded-source9/native-invalid9.valgrind",+ "sha256": "c5897519cc5a1b81b9bb0abd329746f2d1e80dd3d844b43da2344def8f8f10cb"+ },+ "source-comparison.json": {+ "path": "dist-compatibility/expanded-source9/source-comparison.json",+ "sha256": "635403f708e286d4461d40a3d86842d4c670ac70862a9688e2b5fbd72801ace5"+ },+ "diagnostic-export-symbols.txt": {+ "path": "dist-compatibility/expanded-source9/diagnostic-export-symbols.txt",+ "sha256": "b959a9d7f9aab8245708a13d9d605c7e32b01930ecc91372f5d848094830f873"+ },+ "nonthreaded-info9.log": {+ "path": "dist-compatibility/expanded-source9/nonthreaded-info9.log",+ "sha256": "4624cb69ac272748f36b86dca2969623bb2ce1a54d2f66dbbf5226ff74f36e3d"+ },+ "native-diagnostic9.so.1": {+ "path": "dist-compatibility/expanded-source9/native-diagnostic9.so.1",+ "sha256": "c6fdc93c4cdefaeeafd8f3fc9bb0ce49cc63746d57cddbaab2839a04c23b309c"+ },+ "native-phase9.134604.valgrind": {+ "path": "dist-compatibility/expanded-source9/native-phase9.134604.valgrind",+ "sha256": "a334a37b296703dc8e61dd86ef80614a453180df72433da2ef3e4ab96cf65795"+ },+ "broker-final9-tests.txt": {+ "path": "dist-compatibility/expanded-source9/broker-final9-tests.txt",+ "sha256": "1b2270f302280d667a9a755787ee368fce03adc8f849ef070c54f02d99919b84"+ },+ "rdkafka-mp3-historical-mapped9.log": {+ "path": "dist-compatibility/expanded-source9/rdkafka-mp3-historical-mapped9.log",+ "sha256": "401b8f756dc647a81b00f74b182ea83b9be6eeb526efcff7557caa8cd3fa73cf"+ },+ "native-invalid9.log": {+ "path": "dist-compatibility/expanded-source9/native-invalid9.log",+ "sha256": "223d146ce867f09c836471f5067d7957c50c4426e4f941f340b46f41189839ab"+ },+ "darwin-asan-control.log": {+ "path": "dist-compatibility/expanded-source9/darwin-asan-control.log",+ "sha256": "7d3f29e4f75b0cb43aff9c863c81300e2851c4f2b8c958b4bf8c9113b8fb00ee"+ },+ "candidate-receipt.json": {+ "path": "dist-compatibility/expanded-source9/candidate-receipt.json",+ "sha256": "5b490ca3e42d563fec2e7b0ea8735fc40e8a2c8754964a449532e3344402bd1f"+ },+ "darwin-asan-results.json": {+ "path": "dist-compatibility/expanded-source9/darwin-asan-results.json",+ "sha256": "b68f72dc78eefb93b70287c25d05ce35c974cc1044a7fe9cab9701c726394098"+ }+ },+ "accepted_diagnostic_native": {+ "path": "/opt/librdkafka-diagnostics/lib/librdkafka.so.1",+ "sha256": "c6fdc93c4cdefaeeafd8f3fc9bb0ce49cc63746d57cddbaab2839a04c23b309c",+ "source": "Same tagged 2.16.0 C bodies, linker-map change exposes exactly three private error-flag fixture setters; no opaque native layout is copied",+ "exports_diff": {+ "path": "dist-compatibility/expanded-source9/native-diagnostic-exports.diff",+ "sha256": "ff6312086bba73e0e6891060f48f02540b38174dbcbc26c080b12b8655bceafb"+ },+ "loaded_identity": {+ "path": "dist-compatibility/expanded-source9/phase9-diagnostic-identity.log",+ "sha256": "b5e947e38cfa999d968be7abd53685be88beb01ac33c6191db9c34ec24554a6d"+ }+ },+ "darwin_complement": {+ "fingerprint": "2ec6cfbb3416926925e68ad8e96da1322be55ec292821543a8279040762cd98c",+ "tests": 279,+ "seconds": 90.38,+ "native_version": "2.15.0",+ "native_revision": "9a94e11452cdeb0a844db44ee5dd01ccbe17d3ab",+ "native_binary_sha256": "2fa8b4e5d5e623550305022c6dc881674ccf0c0fb43183e532c27d9faaa6e51f",+ "scope": "Matched Apple clang AddressSanitizer native runtime; deliberate invalid access aborts and candidate has no findings. Leak detection disabled: no Darwin leak-freedom claim.",+ "results": [+ {+ "label": "version",+ "command": [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-compatibility/expanded-source9/darwin-version-candidate",+ "--native-version"+ ],+ "exit": 0+ },+ {+ "label": "control",+ "command": [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-compatibility/expanded-source9/darwin-native-candidate",+ "--callback-lifetime-native-control"+ ],+ "exit": -6+ },+ {+ "label": "candidate",+ "command": [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-compatibility/expanded-source9/darwin-native-candidate",+ "-p",+ "/producer-regressions/ || /callback-lifetime/ || (/public-contract/ && (/messages/ || /partition-list-ownership/ || /metadata-contract/ || /diagnostics/)) || /transaction-errors/ || /lifecycle/",+ "+RTS",+ "-N2",+ "-RTS"+ ],+ "exit": 0+ }+ ],+ "artifacts": {+ "darwin-asan-control.log": {+ "path": "dist-compatibility/expanded-source9/darwin-asan-control.log",+ "sha256": "7d3f29e4f75b0cb43aff9c863c81300e2851c4f2b8c958b4bf8c9113b8fb00ee"+ },+ "darwin-asan-candidate.log": {+ "path": "dist-compatibility/expanded-source9/darwin-asan-candidate.log",+ "sha256": "bed5ff95177992d5ec812468fa79432c938c50d61928bb88344f2a951a4b8d36"+ },+ "darwin-native-receipt.json": {+ "path": "dist-compatibility/expanded-source9/darwin-native-receipt.json",+ "sha256": "ab74ca68a62aa0a601d7d8f6782807c46fe5437bc102430b85ea79360bbb0b83"+ }+ }+ }+}
+ docs/testing/message-ownership-evidence.json view
@@ -0,0 +1,54 @@+{+ "status": "accepted M2 message-ownership checkpoint; EP-14 incomplete",+ "fingerprint": "098b3d4bfa91b77f9d9e43b50688a4bd682cb11dea3688f18572b2bb2c405bf2",+ "runs": {+ "normal": {+ "log": "/tmp/rdkafka-ep14-message-final-normal.log",+ "sha256": "8a9af745f3449e61678f7ab5fab9c546a0da0fa6dbef9310c4dfd2cd87c5dcd0",+ "passed": 24,+ "seconds": 16.53+ },+ "instrumented-haskell": {+ "log": "/tmp/rdkafka-ep14-message-final-hpc.log",+ "sha256": "811a826acba3d1dce7d9be9eb51400a034da991fdfa80325b64d523da8f5fbc5",+ "passed": 24,+ "seconds": 16.52+ },+ "instrumented-native": {+ "log": "/tmp/rdkafka-ep14-message-asan.log",+ "sha256": "314a839c5d9702f5895f7170e7b28f331a4d528f010a14e4f668c770bdade582",+ "passed": 24,+ "seconds": 16.4+ }+ },+ "mutations": "dist-mutations/20261024T153417Z-messages-73150-0/results.json",+ "compiled_mutations_caught": 4,+ "controls": 1,+ "baseline": {+ "revision": "8334ad0",+ "log": "/tmp/rdkafka-ep14-message-baseline-headers.log",+ "failed": 10,+ "total": 14,+ "retained_native_messages": {+ "batch_decoder_exception": 1,+ "batch_native_return_cancellation": 3,+ "batch_middle_cancellation": 1,+ "async_single_native_return_cancellation": 1,+ "sync_single_native_return_cancellation": 1+ },+ "other_failures": "Five native header error cases returned records with empty headers instead of the native error.",+ "invalid_initial_fixture_log": "/tmp/rdkafka-ep14-message-baseline.log",+ "fixture_note": "Initial human-readable labels contained spaces invalid in topic names. Corrected run-owned labels before accepting the baseline."+ },+ "native_counter_control": "The final message is deliberately retained: three acquired, two actually destroyed before fixture cleanup; duplicate destruction is counted separately and rejected.",+ "native_library": "mori://confluentinc/librdkafka",+ "native_version": "2.15.0",+ "diagnostic_environment": {+ "DYLD_LIBRARY_PATH": "/tmp/rdkafka-hs-ep11-asan-install/lib",+ "DYLD_INSERT_LIBRARIES": "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/21/lib/darwin/libclang_rt.asan_osx_dynamic.dylib",+ "ASAN_OPTIONS": "detect_leaks=0:abort_on_error=1:symbolize=1"+ },+ "native_diagnostic_control": "docs/testing/callback-native-diagnostics.json",+ "required_checks": "/tmp/rdkafka-ep14-message-check.log",+ "remaining": "Other public APIs, cooperative rebalance errors, saved deprecated-seek failure, final full-candidate coverage/inventory and EP-15 environments remain open."+}
+ docs/testing/metadata-evidence.json view
@@ -0,0 +1,58 @@+{+ "status": "accepted M2 metadata checkpoint; EP-14 incomplete",+ "fingerprint": "45f359cd7b2b9c20d8a0c81ffe8f139dd405a2b6805b1b2151dd3eba60bc5862",+ "runs": {+ "normal": {+ "log": "/tmp/rdkafka-ep14-metadata-normal.log",+ "sha256": "f0889937e841788a06596e0bcf1a59e57375aabaf7edb73839de9a5d913d65a4",+ "passed": 10,+ "seconds": 11.01+ },+ "instrumented-haskell": {+ "log": "/tmp/rdkafka-ep14-metadata-hpc-final.log",+ "sha256": "22a8bc77266712e109f07ad22ad7eff7f404e03c6bf2d17349f8792a3b18eaed",+ "passed": 10,+ "seconds": 11.11+ },+ "instrumented-native": {+ "log": "/tmp/rdkafka-ep14-metadata-asan.log",+ "sha256": "9d57cbc7c145f5dca84dbb081b65a3aebc76a2984be021070729574cd0784917",+ "passed": 10,+ "seconds": 11.14+ }+ },+ "mutations": "dist-mutations/20261024T164556Z-metadata-78004-0/results.json",+ "compiled_mutations_caught": 5,+ "controls": 1,+ "baseline": {+ "revision": "9b76605",+ "log": "/tmp/rdkafka-ep14-metadata-baseline.log",+ "observed": [+ "metadata and group acquisition cancellation each retain one native result",+ "normal result destruction waits for garbage collection",+ "missing topic convenience query returns an empty success list",+ "mixed timestamp query discards member failure"+ ],+ "fixture_correction": "The initial unreachable-broker assertion expected TimedOut; source and observation show Transport before a broker connection exists. This expectation failure is excluded from defect evidence."+ },+ "discarded_builds": {+ "mutation": "dist-mutations/20261024T164500Z-metadata-75772-0",+ "haskell_coverage": "/tmp/rdkafka-ep14-metadata-hpc.log",+ "reason": "A test indentation error failed compilation; fixed before the accepted builds. No build failure counts as a caught mutation."+ },+ "scope": [+ "exact topic/partition identity, leaders, replicas and watermarks",+ "before/at/after timestamp queries and duplicate/empty partition requests",+ "missing-topic and timestamp-query member errors",+ "real stable and empty groups, exact client identity and all/specific group consistency",+ "native-owned controlled group strings including CompletingRebalance and FutureState",+ "isolated native-return cancellation and native retained-result counter control"+ ],+ "native_ownership": "Explicitly finalize native metadata and group results after copying while retaining the client. Cancellation children avoid competing with managed ForeignPtr finalizers; baseline pre-owner failures terminate with the detected outstanding allocation. Native-only retained control frees its own result after assertion.",+ "native_library": "mori://confluentinc/librdkafka",+ "native_version": "2.15.0",+ "native_diagnostic_control": "docs/testing/callback-native-diagnostics.json",+ "leak_instrumentation": false,+ "required_checks": "/tmp/rdkafka-ep14-metadata-check.log",+ "remaining": "Remaining public contracts and input boundaries, saved deprecated-seek diagnosis, full mapped coverage reconciliation and EP-15 environments remain open."+}
+ docs/testing/metadata-field-evidence.json view
@@ -0,0 +1,47 @@+{+ "status": "accepted metadata-field sensitivity checkpoint; EP-14 incomplete",+ "fingerprint": "2a9a48c90e661d890c111fcccd8a86b4b6baa20d8449749bdd5f2aa089e5285d",+ "runs": {+ "normal": {+ "log": "/tmp/rdkafka-ep14-metadata-fields-normal-focused.log",+ "sha256": "3119d02db770aba99e05149784687208b7a0aafec6994e96babf4c3950be6d3e",+ "passed": 14+ },+ "instrumented-haskell": {+ "log": "/tmp/rdkafka-ep14-metadata-fields-hpc.log",+ "sha256": "a419b8fee6aa16d7d1549b518d77cce02257bb2f1641bb24914cff5883ce9dab",+ "passed": 14+ },+ "instrumented-native": {+ "log": "/tmp/rdkafka-ep14-metadata-fields-asan.log",+ "sha256": "50ede3672dd87fe7cd648d0de463628b4f79735bd271fb98093bfce9f88bead9",+ "passed": 14+ },+ "generated-unit": {+ "log": "/tmp/rdkafka-ep14-metadata-fields-normal.log",+ "passed": 1,+ "cases": 1000,+ "seed": 20261024,+ "additional_integration_with_dependencies": 55+ }+ },+ "mutations": "dist-mutations/20261024T202539Z-metadata-fields-95023-0/results.json",+ "compiled_mutations_caught": 3,+ "controls": 1,+ "scope": [+ "Independent broker id/port/Unicode host/origin fields",+ "Distinct leader/replica/ISR/partition fields and topic/partition errors",+ "Explicit range assignor and exact group protocol",+ "Generated broker port varies independently from broker id"+ ],+ "native_frame": "Modify scalars, array elements and a bounded shorter host string in an actual native-owned metadata result. The existing native destructor releases the result exactly once; no test-side ownership substitution. The controlled frame verifies decoding, not real broker topology.",+ "native_library": "mori://confluentinc/librdkafka",+ "native_version": "2.15.0",+ "native_diagnostic_control": "docs/testing/callback-native-diagnostics.json",+ "leak_instrumentation": false,+ "required_checks": {+ "log": "/tmp/rdkafka-ep14-metadata-fields-check.log",+ "sha256": "7d786b08192df44348ac2c6644ce6f1fceaaf8db4a9108ea9be0f2901264edca"+ },+ "remaining": "Whole-candidate inventory refresh and remaining EP-14 contracts/coverage, historical deprecated-seek diagnosis and EP-15 environments remain open."+}
+ docs/testing/metadata-partition-evidence.json view
@@ -0,0 +1,53 @@+{+ "status": "accepted independent metadata-partition checkpoint; EP-14 incomplete",+ "fingerprint": "a8017f2849c2051e0f642ddfc1635f511c1a944e9f6169926fc4fae00a91ed42",+ "workspace": "/tmp/rdkafka-hs-ep14-metadata-partitions",+ "base_revision": "c857191",+ "runs": {+ "normal": {+ "log": "/tmp/rdkafka-ep14-metadata-partitions-isolated-normal.log",+ "sha256": "fd3eef20a0ee029f1a2dd1fddf08e49ffd00b6c8300d1eceae03461cf744d858",+ "passed": 13+ },+ "instrumented-haskell": {+ "log": "/tmp/rdkafka-ep14-metadata-partitions-isolated-hpc.log",+ "sha256": "13bec8cfb0ed57bd4a51e59bcb8d73c78b6dc00f96e370c84de6dfbc817dd889",+ "passed": 13+ },+ "instrumented-native": {+ "log": "/tmp/rdkafka-ep14-metadata-partitions-asan.log",+ "sha256": "75272e8b3fdbf092dd5b6126457bd9c55bc02f9dcdda54902b20d88d63ba8bb9",+ "passed": 13+ }+ },+ "mutations": "/tmp/rdkafka-hs-ep14-metadata-partitions/dist-mutations/20261024T192521Z-metadata-partitions-9975-0/results.json",+ "compiled_mutations_caught": 5,+ "controls": 1,+ "baseline": {+ "log": "/tmp/rdkafka-ep14-metadata-partitions-baseline.log",+ "failed": 2,+ "total": 13,+ "scope": "Inherited metadata convenience implementation with new provided/native partition-error cases; the unrelated sync callback buffer experiment was present. Accepted isolated runs exclude that experiment."+ },+ "scope": [+ "Per-partition watermark failures preserve healthy partition results",+ "Timestamp convenience helpers preserve supplied and queried partition errors",+ "Native group-level entity errors retain their GroupInfo field",+ "Unavailable group queries preserve the initial metadata-wait TimedOut error"+ ],+ "native_library": "mori://confluentinc/librdkafka",+ "native_version": "2.15.0",+ "native_diagnostic_control": "docs/testing/callback-native-diagnostics.json",+ "leak_instrumentation": false,+ "required_checks": {+ "log": "/tmp/rdkafka-ep14-metadata-partitions-check.log",+ "sha256": "e74c81c03c759f6b8ea75ec23b7d88480f056c6299b03de2eb4432c2dc7cb934"+ },+ "discarded_runs": [+ {+ "log": "/tmp/rdkafka-ep14-metadata-partitions-mutations-final.log",+ "reason": "A duplicate was started after misreading a concurrent shell-hook Git config lock warning as failure. The original run remained active and passed; the duplicate was terminated and is excluded."+ }+ ],+ "remaining": "Whole-candidate inventory refresh, complete manual sync callback polling, other consumer contracts, saved deprecated-seek failure, handwritten misses and EP-15 environments remain open."+}
+ docs/testing/metadata-unicode-evidence.json view
@@ -0,0 +1,73 @@+{+ "status": "accepted Unicode metadata checkpoint; EP-14 M2/M3 incomplete",+ "fingerprint": "d640380b9a73fdbd8dabbaa2dc7139e11f2d982a946cf35d4c6614b3f28b51e9",+ "runs": {+ "normal": {+ "log": "/tmp/rdkafka-ep14-metadata-utf8-normal.log",+ "sha256": "d3b04ce5d99e750be579aae1299d5c2c46d1994909e119fedda47dfdc6dc8f78",+ "passed": 10+ },+ "instrumented-native": {+ "log": "/tmp/rdkafka-ep14-metadata-utf8-asan.log",+ "sha256": "f40225758a6dd9b6e61ea1009b2385f85b560f87a3f9b03e1a7dc5335cca1d14",+ "passed": 10+ },+ "instrumented-haskell": {+ "manifest": "docs/testing/coverage-evidence.json",+ "scoped_cases": 10,+ "part_of_integration_cases": 533+ }+ },+ "baseline": {+ "query": {+ "log": "/tmp/rdkafka-ep14-metadata-utf8-baseline.log",+ "sha256": "c497c01361ac368f2ffd2a729237470345a2d0b9a5977318e0f52c027ca47782"+ },+ "decoder": {+ "log": "/tmp/rdkafka-ep14-metadata-utf8-decoder-baseline.log",+ "sha256": "3c3020c6413fffa1a389bdf4159ba47ace2c50309730576ad5e6b598db34de9c"+ },+ "failed_cases_each": 2,+ "observed": [+ "Existing Unicode groups return an empty query result with the ASCII query encoder",+ "Correcting only query encoding returns groups with changed identities through the ASCII decoder"+ ]+ },+ "mutations": "dist-mutations/20261024T185243Z-metadata-utf8-47170-0/results.json",+ "compiled_mutations_caught": 3,+ "controls": 1,+ "scope": [+ "Actual Unicode group/client IDs in async and sync modes",+ "Distinct native-owned Unicode member/client/host fields",+ "Independent binary metadata and assignment fields",+ "Existing group lifecycle and controlled state/error behavior retained"+ ],+ "native_library": "mori://confluentinc/librdkafka",+ "native_version": "2.15.0",+ "native_diagnostic_control": "docs/testing/callback-native-diagnostics.json",+ "leak_instrumentation": false,+ "required_checks": {+ "log": "/tmp/rdkafka-ep14-metadata-utf8-check.log",+ "sha256": "5fc98e306b543a98978650b1ca806de5dc2137233f06075b9595aeb9bcb81850"+ },+ "build_all_with_examples": {+ "log": "/tmp/rdkafka-ep14-config-metadata-build-all.log",+ "sha256": "ba73e57456fad258353dc371119be992a4c8d194659279249a60efdc8519a8e5"+ },+ "remaining": "Provided-metadata partition errors, consumer gaps, deprecated wrapper/example runtime checks, saved deprecated-seek failure, remaining handwritten coverage misses and EP-15 environments remain open.",+ "full_mapped": {+ "manifest": "docs/testing/coverage-evidence.json",+ "fingerprint": "d640380b9a73fdbd8dabbaa2dc7139e11f2d982a946cf35d4c6614b3f28b51e9",+ "registered": 611,+ "unit": 78,+ "integration": 533,+ "integration_seconds": 243.47,+ "nonthreaded_supplement": 4,+ "handwritten_native_wrapper_ticks": 2902,+ "tooling_controls": 22+ },+ "inventory": {+ "tested": 125,+ "open": 56+ }+}
+ docs/testing/mutation-runner-parity.json view
@@ -0,0 +1,351 @@+{+ "status": "parity verified",+ "runner": "scripts/test-mutations.hs",+ "command": "just test-mutations FAMILY",+ "canonical_fingerprint_after_metadata_fix": "957b73f96a1425f194da48f7c8494ebfbf19bc1cc1b782f6390fd0d53feeb0d3",+ "subject_sha256": "6832af5c393f891b55e7b61fbfdd26bc76e72c0efcba22bd4e2f02346c70849f",+ "subject_scope": "All files under src, test, test-integration and test-support, plus rdkafka-hs.cabal. Byte-identical to all five replacement archives. The runner supplies an isolated cabal.project with packages: .",+ "fingerprint_note": "Historical replacement reports retain their original whole-path lexicographic fingerprint. The runner now uses path-component ordering, matching coverage_common.py. Only the runner metadata ordering changed after these runs; compiled subjects and selected tests are byte-identical. Historical reports were not rewritten.",+ "original_mutations": 32,+ "original_controls": 5,+ "families": [+ {+ "family": "topic",+ "before": "dist-topic-mutations/20261024T083604Z-my8qigbc/results.json",+ "after": "dist-mutations/20261024T132141Z-topic-55379-0/results.json",+ "archive_sha256": "49d3997d9713d7028bddb02db1cb4392f3d36329076b3c2c2dbbf2dbba770d33",+ "reported_fingerprint": "546598429e120bed081ebb4a58f1ae49dff3fded278119dc1d08deaecc77e9d5",+ "results": [+ {+ "mutation": "unchanged-control",+ "selected_tests_before": 53,+ "selected_tests_after": 53,+ "exit_after": 0,+ "replay_token": null,+ "test_log": "dist-mutations/20261024T132141Z-topic-55379-0/unchanged-control.test.log"+ },+ {+ "mutation": "configuration-removed",+ "selected_tests_before": 1,+ "selected_tests_after": 1,+ "exit_after": 1,+ "replay_token": null,+ "test_log": "dist-mutations/20261024T132141Z-topic-55379-0/configuration-removed.test.log"+ },+ {+ "mutation": "old-acquisition-lifetime",+ "selected_tests_before": 1,+ "selected_tests_after": 1,+ "exit_after": 1,+ "replay_token": null,+ "test_log": "dist-mutations/20261024T132141Z-topic-55379-0/old-acquisition-lifetime.test.log"+ },+ {+ "mutation": "queue-finalization-removed",+ "selected_tests_before": 1,+ "selected_tests_after": 1,+ "exit_after": 1,+ "replay_token": null,+ "test_log": "dist-mutations/20261024T132141Z-topic-55379-0/queue-finalization-removed.test.log"+ },+ {+ "mutation": "options-finalization-removed",+ "selected_tests_before": 1,+ "selected_tests_after": 1,+ "exit_after": 1,+ "replay_token": null,+ "test_log": "dist-mutations/20261024T132141Z-topic-55379-0/options-finalization-removed.test.log"+ },+ {+ "mutation": "delete-request-finalization-removed",+ "selected_tests_before": 1,+ "selected_tests_after": 1,+ "exit_after": 1,+ "replay_token": null,+ "test_log": "dist-mutations/20261024T132141Z-topic-55379-0/delete-request-finalization-removed.test.log"+ },+ {+ "mutation": "event-finalization-removed",+ "selected_tests_before": 1,+ "selected_tests_after": 1,+ "exit_after": 1,+ "replay_token": null,+ "test_log": "dist-mutations/20261024T132141Z-topic-55379-0/event-finalization-removed.test.log"+ },+ {+ "mutation": "native-request-error-ignored",+ "selected_tests_before": 1,+ "selected_tests_after": 1,+ "exit_after": 1,+ "replay_token": null,+ "test_log": "dist-mutations/20261024T132141Z-topic-55379-0/native-request-error-ignored.test.log"+ },+ {+ "mutation": "topic-identity-ignored",+ "selected_tests_before": 1,+ "selected_tests_after": 1,+ "exit_after": 1,+ "replay_token": null,+ "test_log": "dist-mutations/20261024T132141Z-topic-55379-0/topic-identity-ignored.test.log"+ }+ ]+ },+ {+ "family": "producer",+ "before": "dist-producer-mutations/20261024T103255Z-mjr6tn_0/results.json",+ "after": "dist-mutations/20261024T131819Z-producer-48964-0/results.json",+ "archive_sha256": "49d3997d9713d7028bddb02db1cb4392f3d36329076b3c2c2dbbf2dbba770d33",+ "reported_fingerprint": "546598429e120bed081ebb4a58f1ae49dff3fded278119dc1d08deaecc77e9d5",+ "results": [+ {+ "mutation": "unchanged-control",+ "selected_tests_before": 61,+ "selected_tests_after": 61,+ "exit_after": 0,+ "replay_token": null,+ "test_log": "dist-mutations/20261024T131819Z-producer-48964-0/unchanged-control.test.log"+ },+ {+ "mutation": "topic-settings-dropped",+ "selected_tests_before": 1,+ "selected_tests_after": 1,+ "exit_after": 1,+ "replay_token": null,+ "test_log": "dist-mutations/20261024T131819Z-producer-48964-0/topic-settings-dropped.test.log"+ },+ {+ "mutation": "rejection-root-retained",+ "selected_tests_before": 1,+ "selected_tests_after": 1,+ "exit_after": 1,+ "replay_token": null,+ "test_log": "dist-mutations/20261024T131819Z-producer-48964-0/rejection-root-retained.test.log"+ },+ {+ "mutation": "accepted-root-freed",+ "selected_tests_before": null,+ "selected_tests_after": null,+ "exit_after": -6,+ "replay_token": null,+ "test_log": "dist-mutations/20261024T131819Z-producer-48964-0/accepted-root-freed.test.log"+ },+ {+ "mutation": "enqueue-mask-removed",+ "selected_tests_before": null,+ "selected_tests_after": null,+ "exit_after": -6,+ "replay_token": null,+ "test_log": "dist-mutations/20261024T131819Z-producer-48964-0/enqueue-mask-removed.test.log"+ },+ {+ "mutation": "global-exception-skips-message",+ "selected_tests_before": 1,+ "selected_tests_after": 1,+ "exit_after": 1,+ "replay_token": null,+ "test_log": "dist-mutations/20261024T131819Z-producer-48964-0/global-exception-skips-message.test.log"+ },+ {+ "mutation": "delivery-root-retained",+ "selected_tests_before": 1,+ "selected_tests_after": 1,+ "exit_after": 1,+ "replay_token": null,+ "test_log": "dist-mutations/20261024T131819Z-producer-48964-0/delivery-root-retained.test.log"+ },+ {+ "mutation": "empty-bytes-become-absent",+ "selected_tests_before": 1,+ "selected_tests_after": 1,+ "exit_after": 1,+ "replay_token": null,+ "test_log": "dist-mutations/20261024T131819Z-producer-48964-0/empty-bytes-become-absent.test.log"+ },+ {+ "mutation": "input-validation-dropped",+ "selected_tests_before": 1,+ "selected_tests_after": 1,+ "exit_after": 1,+ "replay_token": null,+ "test_log": "dist-mutations/20261024T131819Z-producer-48964-0/input-validation-dropped.test.log"+ },+ {+ "mutation": "global-overrides-topic",+ "selected_tests_before": 1,+ "selected_tests_after": 1,+ "exit_after": 1,+ "replay_token": null,+ "test_log": "dist-mutations/20261024T131819Z-producer-48964-0/global-overrides-topic.test.log"+ },+ {+ "mutation": "headers-dropped",+ "selected_tests_before": 1,+ "selected_tests_after": 1,+ "exit_after": 1,+ "replay_token": null,+ "test_log": "dist-mutations/20261024T131819Z-producer-48964-0/headers-dropped.test.log"+ },+ {+ "mutation": "rejection-release-after-decoding",+ "selected_tests_before": 1,+ "selected_tests_after": 1,+ "exit_after": 1,+ "replay_token": null,+ "test_log": "dist-mutations/20261024T131819Z-producer-48964-0/rejection-release-after-decoding.test.log"+ },+ {+ "mutation": "nonnull-success-code-accepted",+ "selected_tests_before": 1,+ "selected_tests_after": 1,+ "exit_after": 1,+ "replay_token": null,+ "test_log": "dist-mutations/20261024T131819Z-producer-48964-0/nonnull-success-code-accepted.test.log"+ },+ {+ "mutation": "unknown-error-replaced-by-errno",+ "selected_tests_before": 1,+ "selected_tests_after": 1,+ "exit_after": 1,+ "replay_token": null,+ "test_log": "dist-mutations/20261024T131819Z-producer-48964-0/unknown-error-replaced-by-errno.test.log"+ }+ ]+ },+ {+ "family": "property",+ "before": "dist-property-mutations/20261024T103255Z-t4e5jvw8/results.json",+ "after": "dist-mutations/20261024T131346Z-property-39846-0/results.json",+ "archive_sha256": "49d3997d9713d7028bddb02db1cb4392f3d36329076b3c2c2dbbf2dbba770d33",+ "reported_fingerprint": "546598429e120bed081ebb4a58f1ae49dff3fded278119dc1d08deaecc77e9d5",+ "results": [+ {+ "mutation": "pure-control",+ "selected_tests_before": 7,+ "selected_tests_after": 7,+ "exit_after": 0,+ "replay_token": null,+ "test_log": "dist-mutations/20261024T131346Z-property-39846-0/pure-control.test.log"+ },+ {+ "mutation": "callback-control",+ "selected_tests_before": 1,+ "selected_tests_after": 1,+ "exit_after": 0,+ "replay_token": null,+ "test_log": "dist-mutations/20261024T131346Z-property-39846-0/callback-control.test.log"+ },+ {+ "mutation": "global-bias-reversed",+ "selected_tests_before": 1,+ "selected_tests_after": 1,+ "exit_after": 1,+ "replay_token": "(SMGen 7603286587113926598 6750786074473487893,17)",+ "test_log": "dist-mutations/20261024T131346Z-property-39846-0/global-bias-reversed.test.log"+ },+ {+ "mutation": "topic-bias-reversed",+ "selected_tests_before": 1,+ "selected_tests_after": 1,+ "exit_after": 1,+ "replay_token": "(SMGen 16220535950959846018 13032396016077086513,13)",+ "test_log": "dist-mutations/20261024T131346Z-property-39846-0/topic-bias-reversed.test.log"+ },+ {+ "mutation": "log-level-bias-reversed",+ "selected_tests_before": 1,+ "selected_tests_after": 1,+ "exit_after": 1,+ "replay_token": "(SMGen 876416796774277236 1544764139296909573,5)",+ "test_log": "dist-mutations/20261024T131346Z-property-39846-0/log-level-bias-reversed.test.log"+ },+ {+ "mutation": "callback-order-reversed",+ "selected_tests_before": 1,+ "selected_tests_after": 1,+ "exit_after": 1,+ "replay_token": "(SMGen 13262595567567848789 8761751867160652105,2)",+ "test_log": "dist-mutations/20261024T131346Z-property-39846-0/callback-order-reversed.test.log"+ }+ ]+ },+ {+ "family": "seek",+ "before": "dist-seek-mutations/20261024T105811Z-z8yr14j7/results.json",+ "after": "dist-mutations/20261024T131515Z-seek-41713-0/results.json",+ "archive_sha256": "49d3997d9713d7028bddb02db1cb4392f3d36329076b3c2c2dbbf2dbba770d33",+ "reported_fingerprint": "546598429e120bed081ebb4a58f1ae49dff3fded278119dc1d08deaecc77e9d5",+ "results": [+ {+ "mutation": "unchanged-control",+ "selected_tests_before": 76,+ "selected_tests_after": 76,+ "exit_after": 0,+ "replay_token": null,+ "test_log": "dist-mutations/20261024T131515Z-seek-41713-0/unchanged-control.test.log"+ },+ {+ "mutation": "member-errors-dropped",+ "selected_tests_before": 2,+ "selected_tests_after": 2,+ "exit_after": 1,+ "replay_token": null,+ "test_log": "dist-mutations/20261024T131515Z-seek-41713-0/member-errors-dropped.test.log"+ },+ {+ "mutation": "error-order-reversed",+ "selected_tests_before": 2,+ "selected_tests_after": 2,+ "exit_after": 1,+ "replay_token": null,+ "test_log": "dist-mutations/20261024T131515Z-seek-41713-0/error-order-reversed.test.log"+ },+ {+ "mutation": "pending-always-normalized",+ "selected_tests_before": 2,+ "selected_tests_after": 2,+ "exit_after": 1,+ "replay_token": null,+ "test_log": "dist-mutations/20261024T131515Z-seek-41713-0/pending-always-normalized.test.log"+ },+ {+ "mutation": "pending-never-normalized",+ "selected_tests_before": 2,+ "selected_tests_after": 2,+ "exit_after": 1,+ "replay_token": null,+ "test_log": "dist-mutations/20261024T131515Z-seek-41713-0/pending-never-normalized.test.log"+ },+ {+ "mutation": "message-commit-forgets-next-offset",+ "selected_tests_before": 2,+ "selected_tests_after": 2,+ "exit_after": 1,+ "replay_token": null,+ "test_log": "dist-mutations/20261024T131515Z-seek-41713-0/message-commit-forgets-next-offset.test.log"+ },+ {+ "mutation": "rewind-decrements-committed-offset",+ "selected_tests_before": 2,+ "selected_tests_after": 2,+ "exit_after": 1,+ "replay_token": null,+ "test_log": "dist-mutations/20261024T131515Z-seek-41713-0/rewind-decrements-committed-offset.test.log"+ },+ {+ "mutation": "rewind-discards-seek-error",+ "selected_tests_before": 2,+ "selected_tests_after": 2,+ "exit_after": 1,+ "replay_token": null,+ "test_log": "dist-mutations/20261024T131515Z-seek-41713-0/rewind-discards-seek-error.test.log"+ }+ ]+ }+ ],+ "new_callback_coverage": {+ "mutations": 5,+ "controls": 2,+ "report": "dist-mutations/20261024T131006Z-callback-29820-0/results.json",+ "archive_sha256": "49d3997d9713d7028bddb02db1cb4392f3d36329076b3c2c2dbbf2dbba770d33"+ }+}
+ docs/testing/native-storable-coverage-audit.json view
@@ -0,0 +1,59 @@+{+ "status": "source-backed partial M3 audit; public contract and remaining coverage gaps remain open",+ "binding_source_sha256": "95633699b8e19f1140bdb6154a2521ab6e27902b4fda4fc1f4a60dfa89b9a991",+ "baseline_evidence": "docs/testing/coverage-evidence.json",+ "classified_missing_ticks": 484,+ "classification_keys": 120,+ "audit": [+ "rdkafka-hs.cabal does not expose Kafka.Internal.RdKafka",+ "All handwritten poke/pokeArray/pokeElemOff/pokeByteOff and withArray references under src were reviewed",+ "Returned native structures are read only; native partition setters mutate list contents",+ "Among the audited private native structures, only outbound RdKafkaVuT uses aggregate Haskell writes through withArrayLen. Pointer arrays and primitive output buffers use separate Storable instances and are not classified.",+ "Compiler-generated Storable default forwarding wrappers are identified by exact tick labels at instance declarations"+ ],+ "excluded": "No classification applies to reachable public operations, native error paths, private methods actually used by array conversion, or outbound union constructors.",+ "baseline_fingerprint": "d640380b9a73fdbd8dabbaa2dc7139e11f2d982a946cf35d4c6614b3f28b51e9",+ "audited_source_hashes": {+ "src/Kafka/Internal/RdKafka.chs": "95633699b8e19f1140bdb6154a2521ab6e27902b4fda4fc1f4a60dfa89b9a991",+ "src/Kafka/Consumer/Convert.hs": "61ce0505eaa2aead929700fc60b31dcf27125c095a944f92874146c1a15091e1",+ "src/Kafka/Metadata.hs": "fd84532b5f4c5588a07298f9f0bc3a0d9be3bfab3bb2664687b192a927e2bb00",+ "src/Kafka/Producer.hs": "b433ed35ead2ec4504d3c392eb8f8958e23c4ceb83b9411682a71b3a30c9beb0",+ "rdkafka-hs.cabal": "a0035cc2e49c8b9e807d30d99c71077255d7d6f89d529da97f4de1e1f5ab4e7e"+ },+ "baseline_revision": "542b0d7",+ "verified_on_candidate": "acc3974e02bc5dfc6d23b9291a865133b52f8019dcae4783219e8763029a82de",+ "candidate_classified_ticks": 484,+ "outbound_union_audit": {+ "baseline_revision": "c8317f0",+ "classified_ticks": 203,+ "classification_keys": 42,+ "ranges": [+ {+ "start": 1205,+ "end": 1226,+ "rationale": "RdKafkaVuT is only an outbound argument union. Public producers construct values that withArrayLen writes for rd_kafka_produceva; no src call reads this private union with peek. Native test observers inspect C arguments directly and do not use this Haskell reader."+ },+ {+ "start": 1227,+ "end": 1228,+ "rationale": "The outbound argument array supplies an explicit count, so public producers do not construct an End terminator."+ },+ {+ "start": 1232,+ "end": 1234,+ "rationale": "ProducerRecord has no per-record timestamp input. No src call constructs the private Timestamp union variant."+ },+ {+ "start": 1241,+ "end": 1243,+ "rationale": "Public Headers are ordered byte pairs converted to individual Header union entries; no src call supplies a prebuilt native header-list pointer."+ },+ {+ "start": 1244,+ "end": 1246,+ "rationale": "Public ProducerRecord selects a TopicName, not a native topic handle. No src call constructs this private union variant."+ }+ ],+ "excluded": "All public outbound variants and their actual writer/size/alignment paths remain measured; no blanket union-instance exclusion."+ }+}
+ docs/testing/partition-list-evidence.json view
@@ -0,0 +1,63 @@+{+ "status": "focused partition-list ownership checkpoint accepted; whole-candidate reconciliation remains open",+ "fingerprint": "84013dc8aa34c81743fab5033ec37d5a6f132b4343a7d5fb9aa2bed5832a55d1",+ "baseline": {+ "log": "/tmp/rdkafka-ep14-partition-lists-baseline.log",+ "passed": 15,+ "failed": 4,+ "expected_before_gc": [+ 1,+ 1,+ 0+ ],+ "actual_before_gc": [+ 1,+ 0,+ 1+ ],+ "probe_log": "/tmp/rdkafka-partition-ownership-baseline.log",+ "scope": "Both managed converters leave a partially encoded list to GC after a real encoding IOException; the probe confirms later GC destroys it. This is deferred cleanup, not evidence of a permanent leak."+ },+ "runs": {+ "normal": {+ "log": "/tmp/rdkafka-ep14-partition-lists-normal.log",+ "sha256": "c0b34cb446f31c2aee446abfbfca5e57695367902e309ac2af0326f18229c730",+ "passed": 19+ },+ "instrumented-haskell": {+ "log": "/tmp/rdkafka-ep14-partition-lists-hpc.log",+ "sha256": "1f2b54ea8738680ce247cb2fd9d71dae2bf839d1debc182f1c6a0771836d1f8c",+ "passed": 19+ },+ "instrumented-native": {+ "log": "/tmp/rdkafka-ep14-partition-lists-asan.log",+ "sha256": "bcd9e12609682c63cd35ec8095916ce7779b920454ef1454569921efcab46ea2",+ "passed": 19+ }+ },+ "mutations": "dist-mutations/20261024T230323Z-partition-lists-66957-0/results.json",+ "compiled_mutations_caught": 4,+ "controls": 1,+ "scope": [+ "Input and native-returned output ownership counted separately from native internal copies",+ "Real latin1 encoding failure after an ASCII member preserves the IOException and releases the partial list before GC",+ "Assignment/subscription success, repeated decoding and invalid UTF-8 decoder errors release owned outputs",+ "Cancellation is pending at held input allocation and assignment return; native objects release once before returning ThreadKilled",+ "Explicit retained-list control proves the observer detects allocation without release",+ "No native pointer is retained after destruction; the observer unlocks before callback-capable native release"+ ],+ "native_version": "2.15.0",+ "native_library": "mori://confluentinc/librdkafka",+ "native_release_commit": "9a94e11452cdeb0a844db44ee5dd01ccbe17d3ab",+ "dependency_api_check": {+ "project": "mori://ghc/ghc",+ "release_tag": "ghc-9.12.4-release",+ "source_path": "libraries/base/src/GHC/IO/Encoding.hs",+ "source_artifact_uri_pending": true,+ "lookup": "Mori has no base package entry; upstream release source verifies get/set foreign encoding, latin1 and utf8 exports."+ },+ "required_checks": "/tmp/rdkafka-ep14-partition-lists-check.log",+ "adr_checks": "/tmp/rdkafka-ep14-partition-lists-adr.log",+ "leak_instrumentation": false,+ "classification_reconciliation": "coverage-classification-remap.json"+}
+ docs/testing/post-wrapper-evidence.json view
@@ -0,0 +1,48 @@+{+ "status": "accepted full post-wrapper checkpoint; EP-14 remains incomplete",+ "fingerprint": "073aaaf7bb77bebb5b504869d60ce69058795934774f4b63a72e04445f4692ad",+ "counts": {+ "tested": 146,+ "unimplemented": 35+ },+ "normal": {+ "unit": 78,+ "integration": 584,+ "log": "/tmp/rdkafka-ep14-post-runners-full-normal.log"+ },+ "mapped": {+ "unit": 78,+ "integration": 584,+ "manifest": "docs/testing/coverage-evidence.json"+ },+ "actual_nonthreaded": 4,+ "tooling_controls": 24,+ "measured_native_wrapper_ticks": 2750,+ "unexplained_handwritten_missing_ticks": 255,+ "newly_reconciled_rows": [+ "API-Kafka-Consumer-Types-KafkaConsumer",+ "API-Kafka-Consumer-commitPartitionsOffsets",+ "API-Kafka-Consumer-committed",+ "API-Kafka-Consumer-consumerFatalError",+ "API-Kafka-Consumer-runConsumer",+ "API-Kafka-Metadata-BrokerMetadata",+ "API-Kafka-Metadata-GroupInfo",+ "API-Kafka-Metadata-GroupProtocol",+ "API-Kafka-Metadata-KafkaMetadata",+ "API-Kafka-Metadata-PartitionMetadata",+ "API-Kafka-Metadata-TopicMetadata",+ "API-Kafka-Metadata-WatermarkOffsets",+ "API-Kafka-Producer-Types-KafkaProducer",+ "API-Kafka-Producer-runProducer"+ ],+ "partial_audits": [+ "docs/testing/private-haskell-coverage-audit.json",+ "docs/testing/compiler-forwarding-coverage-audit.json"+ ],+ "open_discoveries": [+ "Embedded NUL topic inputs truncate in consumer assignment",+ "Partition values outside C int wrap and can select partition zero",+ "Saved historical deprecated-seek state failure remains unexplained"+ ],+ "remaining": "Consumer/API boundaries, reachable ownership/error misses, remaining exact contracts and all EP-15 requirements"+}
+ docs/testing/primary-validation-evidence.json view
@@ -0,0 +1,149 @@+{+ "status": "passed primary release-preparation scope; publication is separate",+ "scope_decision": "docs/adr/release-validation-has-explicit-primary-and-expanded-scopes.md",+ "source_revision": "b740b725126bce2fbf8bf71c2e4da1cc1861e403",+ "scope_plan_commit": "f9640d4",+ "fingerprint": "060dade4e8a9c764dabee54df3030fa6d857be3ea1404a2bc680a45ddadd5e4e",+ "environment": {+ "os": "macOS 26.7",+ "kernel": "Darwin 25.6.0",+ "architecture": "arm64",+ "ghc": "9.12.4",+ "cabal": "3.16.1.0",+ "native": "2.15.0",+ "loaded_native": "(\"2.15.0\",34537727)",+ "broker_versions": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "broker": "127.0.0.1:39092"+ },+ "normal": {+ "unit": 78,+ "integration": 708,+ "seconds": [+ 1.12,+ 330.23+ ]+ },+ "mapped": {+ "unit": 78,+ "integration": 708,+ "seconds": [+ 1.56,+ 324.56+ ],+ "evidence": "docs/testing/coverage-evidence.json",+ "handwritten_native_wrapper_ticks": 2750+ },+ "actual_nonthreaded_passed": 4,+ "tooling_controls_passed": 24,+ "inventory": {+ "valid": true,+ "allow_open": true,+ "rows": 181,+ "tested": 146,+ "deferred": 35+ },+ "source_distribution": {+ "archive": "dist-primary-release/rdkafka-hs-1.0.0.1.tar.gz",+ "archive_sha256": "51b5463ea79925d677999c8b113989003c41de26291f746409da3284c1c12524",+ "extraction": "dist-primary-release/replay-9jlwx8sb/rdkafka-hs-1.0.0.1",+ "compared_source_test_example_script_files": 103,+ "all_bytes_match": true,+ "project_config": "packages: .",+ "unit_passed": 78,+ "integration_ownership_runtime_passed": 23,+ "integration_six_repair_passed": 8,+ "loaded_native": "(\"2.15.0\",34537727)",+ "example": "Four exact key/value/header/offset records and broker committed next offset 4 independently verified under a 30-second bound"+ },+ "selection_correction": "The first combined package command selected zero unit tests and only the 23 ownership/runtime integration cases. Its unit result is excluded. The accepted separate unfiltered unit command passes all 78, and the direct binary named repair selection passes all eight expected cases. No zero-test result is counted.",+ "native_controls": {+ "scope": "Retain accepted focused native runs and effective controls documented by repair/ownership manifests. Later documentation and seek fixture edits do not change their native ownership source scopes.",+ "evidence": [+ "docs/testing/callback-native-diagnostics.json",+ "docs/testing/partition-list-evidence.json",+ "docs/testing/final-boundaries-evidence.json",+ "docs/testing/legacy-seek-evidence.json"+ ],+ "leak_detection": false,+ "limit": "Darwin AddressSanitizer invalid-access, weak-reference and native-counter evidence is not comprehensive leak freedom."+ },+ "deferred_work": "docs/masterplans/3-complete-deferred-coverage-and-compatibility-validation.md",+ "deferred_snapshot": "docs/testing/deferred-validation-snapshot.json",+ "unclassified_handwritten_ticks_deferred": 192,+ "artifacts": {+ "normal-full": {+ "log": "dist-primary-release/evidence/normal-full.log",+ "sha256": "4430092b7158fa78459adb0bd96bac93198ac24cd9a553e096b936894dda54ae"+ },+ "mapped-full": {+ "log": "dist-primary-release/evidence/mapped-full.log",+ "sha256": "ddafabb793b3220670f9d9d2741cbd6e2001dd04851dae70eb8f7054549aa378"+ },+ "coverage-collection": {+ "log": "dist-primary-release/evidence/coverage-collection.log",+ "sha256": "ca37d689a706d9717506fbe43b41bb47ca8ecb9943a5e2a96b49ff82d47219d3"+ },+ "coverage-tools": {+ "log": "dist-primary-release/evidence/coverage-tools.log",+ "sha256": "6b0281b1ee7a1b66cf3cb95bf1dd118dac65c970c2dff8aa1e4ff3ec18bcf337"+ },+ "inventory": {+ "log": "dist-primary-release/evidence/inventory.log",+ "sha256": "6aaeb4a62ef5152f0f1adf20bb654b54b8fe12f057b757150972ebe61992fb7a"+ },+ "package-build": {+ "log": "dist-primary-release/evidence/package-build.log",+ "sha256": "17be004d39f5127ae9a26bda0247ac0456faf16d3ad4a247a8642a8a81f44749"+ },+ "package-unit": {+ "log": "dist-primary-release/evidence/package-unit.log",+ "sha256": "7422a52c5b41a017d2e831f2ab8dc8850faf83d6e3107f0b0e67a84b07b5b46b"+ },+ "package-ownership-runtime": {+ "log": "dist-primary-release/evidence/package-ownership-runtime.log",+ "sha256": "6f505b82f99181f0d1f3e60ef7a2df41b9560ae310807f2837f2698de92cce65"+ },+ "package-repairs": {+ "log": "dist-primary-release/evidence/package-repairs.log",+ "sha256": "fef5f3e584b01b07d7d9739287502b4e6b23368aceb29b681459bc3687b92a1c"+ },+ "package-example": {+ "log": "dist-primary-release/evidence/package-example.log",+ "sha256": "0ad5aead3404305296f7b6675214afe5c22f9fecfba30f1a5afc0ec8535f8830"+ },+ "cabal-check": {+ "log": "dist-primary-release/evidence/cabal-check.log",+ "sha256": "c6eb9fc26e6b12b67ab0b600e39a34f1e847f6a8f7e2fe07a3e2d4ab07591021"+ },+ "package-binding-nix-checks": {+ "log": "dist-primary-release/evidence/package-binding-nix-checks.log",+ "sha256": "37d6b9dbde43d9202abf141d7b8626e1001a4b034c7d394b2838cf8ab65aef28"+ },+ "plan-docs-check": {+ "log": "dist-primary-release/evidence/plan-docs-check.log",+ "sha256": "62644b6a564a5ae4e08acf494818d103474d0da76074f1a6abb2aaaca2cc020d"+ },+ "adr-check": {+ "log": "dist-primary-release/evidence/adr-check.log",+ "sha256": "4241ee2e8e9a28a010236e444eef70c3234656ac5f7cc1bf1f49d42f631dc119"+ },+ "final-documentation": {+ "log": "dist-primary-release/evidence/final-documentation.log",+ "sha256": "62644b6a564a5ae4e08acf494818d103474d0da76074f1a6abb2aaaca2cc020d"+ },+ "final-inventory": {+ "log": "dist-primary-release/evidence/final-inventory.log",+ "sha256": "986a981183b5e0669e31a34eb6f50f0df62b06f8499d4c6b33fe0aa7c4736909"+ },+ "final-format": {+ "log": "dist-primary-release/evidence/final-format.log",+ "sha256": "b1e28e55fcd53798aaf473dd1f86eef1641cd312466a0371ad7aa93732f96c61"+ }+ },+ "publication_performed": false+}
+ docs/testing/private-binding-coverage-audit.json view
@@ -0,0 +1,62 @@+{+ "status": "partial source-backed M3 audit; no public contract is waived",+ "baseline_revision": "c8317f0",+ "baseline_manifest": "docs/testing/coverage-evidence.json",+ "baseline_fingerprint": "acc3974e02bc5dfc6d23b9291a865133b52f8019dcae4783219e8763029a82de",+ "private_module": "src/Kafka/Internal/RdKafka.chs",+ "classified_ticks": 211,+ "classification_keys": 58,+ "declarations": [+ {+ "name": "rdKafkaMsgFlagFree",+ "start": 84,+ "end": 85+ },+ {+ "name": "copyRdKafkaTopicPartitionList",+ "start": 343,+ "end": 346+ },+ {+ "name": "rdKafkaConfSetConsumeCb",+ "start": 394,+ "end": 397+ },+ {+ "name": "rdKafkaConfSetThrottleCb",+ "start": 439,+ "end": 442+ },+ {+ "name": "rdKafkaConfSetSocketCb",+ "start": 486,+ "end": 489+ },+ {+ "name": "rdKafkaTopicConfSetPartitionerCb",+ "start": 516,+ "end": 520+ },+ {+ "name": "pollRdKafkaConsumer",+ "start": 689,+ "end": 695+ },+ {+ "name": "rdKafkaConsumeStart",+ "start": 1022,+ "end": 1027+ },+ {+ "name": "rdKafkaConsumeStop",+ "start": 1041,+ "end": 1046+ },+ {+ "name": "newRdKafkaNewTopic",+ "start": 1369,+ "end": 1376+ }+ ],+ "proof": "rg of the exact names across all src Haskell/c2hs files finds only their declarations, definitions and same-helper internal setter calls. Cabal lists the module under other-modules. Only these declaration bodies are classified; shared utilities with reachable native failure paths remain open."+}
+ docs/testing/private-haskell-coverage-audit.json view
@@ -0,0 +1,142 @@+{+ "status": "partial M3 source audit; whole-candidate refresh and reachable branches remain open",+ "baseline_fingerprint": "acc3974e02bc5dfc6d23b9291a865133b52f8019dcae4783219e8763029a82de",+ "proof": "Exact-name scans across every src .hs/.chs file find only each listed function definition, signature, export and INLINE entries. Cabal other-modules hides all four owning modules; exposed module exports do not re-export these helpers.",+ "declarations": [+ {+ "file": "src/Kafka/Consumer/Convert.hs",+ "name": "offsetSyncToInt",+ "start": 62,+ "end": 66,+ "source_sha256": "61ce0505eaa2aead929700fc60b31dcf27125c095a944f92874146c1a15091e1",+ "baseline_missing_ticks": 7,+ "keys": [+ "Kafka.Consumer.Convert:62:TopLevelBox [\"offsetSyncToInt\"]",+ "Kafka.Consumer.Convert:63:ExpBox False",+ "Kafka.Consumer.Convert:64:ExpBox False",+ "Kafka.Consumer.Convert:64:ExpBox True",+ "Kafka.Consumer.Convert:65:ExpBox True",+ "Kafka.Consumer.Convert:66:ExpBox True"+ ]+ },+ {+ "file": "src/Kafka/Consumer/Convert.hs",+ "name": "toNativeTopicPartitionListNoDispose",+ "start": 138,+ "end": 150,+ "source_sha256": "61ce0505eaa2aead929700fc60b31dcf27125c095a944f92874146c1a15091e1",+ "baseline_missing_ticks": 32,+ "keys": [+ "Kafka.Consumer.Convert:138:ExpBox False",+ "Kafka.Consumer.Convert:138:TopLevelBox [\"toNativeTopicPartitionListNoDispose\"]",+ "Kafka.Consumer.Convert:139:ExpBox False",+ "Kafka.Consumer.Convert:140:ExpBox False",+ "Kafka.Consumer.Convert:141:ExpBox False",+ "Kafka.Consumer.Convert:142:ExpBox False",+ "Kafka.Consumer.Convert:143:ExpBox False",+ "Kafka.Consumer.Convert:144:ExpBox False",+ "Kafka.Consumer.Convert:144:LocalBox [\"toNativeTopicPartitionListNoDispose\",\"to\"]",+ "Kafka.Consumer.Convert:145:ExpBox False",+ "Kafka.Consumer.Convert:145:LocalBox [\"toNativeTopicPartitionListNoDispose\",\"tnS\"]",+ "Kafka.Consumer.Convert:146:ExpBox False",+ "Kafka.Consumer.Convert:147:ExpBox False",+ "Kafka.Consumer.Convert:149:ExpBox False",+ "Kafka.Consumer.Convert:150:ExpBox False"+ ]+ },+ {+ "file": "src/Kafka/Internal/Shared.hs",+ "name": "throwOnError",+ "start": 64,+ "end": 68,+ "source_sha256": "da37bdff0d9cf6bd60109b63e563e4eec0d6a2c74b251df1d2e8244756c176a7",+ "baseline_missing_ticks": 11,+ "keys": [+ "Kafka.Internal.Shared:64:ExpBox False",+ "Kafka.Internal.Shared:64:TopLevelBox [\"throwOnError\"]",+ "Kafka.Internal.Shared:65:ExpBox False",+ "Kafka.Internal.Shared:66:ExpBox False",+ "Kafka.Internal.Shared:67:ExpBox False",+ "Kafka.Internal.Shared:67:ExpBox True",+ "Kafka.Internal.Shared:68:ExpBox False",+ "Kafka.Internal.Shared:68:ExpBox True"+ ]+ },+ {+ "file": "src/Kafka/Internal/Shared.hs",+ "name": "hasError",+ "start": 71,+ "end": 73,+ "source_sha256": "da37bdff0d9cf6bd60109b63e563e4eec0d6a2c74b251df1d2e8244756c176a7",+ "baseline_missing_ticks": 5,+ "keys": [+ "Kafka.Internal.Shared:71:ExpBox False",+ "Kafka.Internal.Shared:71:TopLevelBox [\"hasError\"]",+ "Kafka.Internal.Shared:72:ExpBox True",+ "Kafka.Internal.Shared:73:ExpBox True"+ ]+ },+ {+ "file": "src/Kafka/Internal/Shared.hs",+ "name": "kafkaErrorToEither",+ "start": 83,+ "end": 85,+ "source_sha256": "da37bdff0d9cf6bd60109b63e563e4eec0d6a2c74b251df1d2e8244756c176a7",+ "baseline_missing_ticks": 7,+ "keys": [+ "Kafka.Internal.Shared:83:ExpBox False",+ "Kafka.Internal.Shared:83:TopLevelBox [\"kafkaErrorToEither\"]",+ "Kafka.Internal.Shared:84:ExpBox False",+ "Kafka.Internal.Shared:84:ExpBox True",+ "Kafka.Internal.Shared:85:ExpBox False",+ "Kafka.Internal.Shared:85:ExpBox True"+ ]+ },+ {+ "file": "src/Kafka/Producer/Convert.hs",+ "name": "handleProduceErr",+ "start": 32,+ "end": 34,+ "source_sha256": "9ba868c4ea7d938ab857f2e92f1a033a633b8f7b834da58502d6fb9831f99483",+ "baseline_missing_ticks": 12,+ "keys": [+ "Kafka.Producer.Convert:32:ExpBox False",+ "Kafka.Producer.Convert:32:ExpBox True",+ "Kafka.Producer.Convert:32:TopLevelBox [\"handleProduceErr\"]",+ "Kafka.Producer.Convert:33:ExpBox False",+ "Kafka.Producer.Convert:33:ExpBox True",+ "Kafka.Producer.Convert:34:ExpBox False",+ "Kafka.Producer.Convert:34:ExpBox True"+ ]+ },+ {+ "file": "src/Kafka/Producer/Convert.hs",+ "name": "handleProduceErr'",+ "start": 43,+ "end": 45,+ "source_sha256": "9ba868c4ea7d938ab857f2e92f1a033a633b8f7b834da58502d6fb9831f99483",+ "baseline_missing_ticks": 13,+ "keys": [+ "Kafka.Producer.Convert:43:ExpBox False",+ "Kafka.Producer.Convert:43:ExpBox True",+ "Kafka.Producer.Convert:43:TopLevelBox [\"handleProduceErr'\"]",+ "Kafka.Producer.Convert:44:ExpBox False",+ "Kafka.Producer.Convert:44:ExpBox True",+ "Kafka.Producer.Convert:45:ExpBox False",+ "Kafka.Producer.Convert:45:ExpBox True"+ ]+ },+ {+ "file": "src/Kafka/Internal/RdKafka.chs",+ "name": "peekCAText",+ "start": 110,+ "end": 110,+ "source_sha256": "95633699b8e19f1140bdb6154a2521ab6e27902b4fda4fc1f4a60dfa89b9a991",+ "baseline_missing_ticks": 5,+ "keys": [+ "Kafka.Internal.RdKafka:110:ExpBox False",+ "Kafka.Internal.RdKafka:110:TopLevelBox [\"peekCAText\"]"+ ]+ }+ ]+}
+ docs/testing/producer-evidence.json view
@@ -0,0 +1,380 @@+{+ "revision": "8396f7b60ae762068970eb7d802e1bb1f514c07e",+ "fingerprint": "603e828f9aca4c20cfe867950e50ed5c106ff74de7db07124e960db07890cd9a",+ "configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ },+ "normal": {+ "unit_tests": 21,+ "integration_tests": 244,+ "integration_seconds": 108.03+ },+ "instrumented": {+ "unit_tests": 21,+ "integration_tests": 244,+ "integration_seconds": 105.84+ },+ "focused_tests": [+ "rdkafka-hs-integration.producer-regressions.explicit topic timeout expires an accepted message",+ "rdkafka-hs-integration.producer-regressions.global timeout still expires an accepted message",+ "rdkafka-hs-integration.producer-regressions.queue-full rejection releases callback capture without invoking it",+ "rdkafka-hs-integration.producer-regressions.accepted callback retains its capture until a purged report completes",+ "rdkafka-hs-integration.producer-regressions.throwing global callback preserves per-message delivery and releases capture",+ "rdkafka-hs-integration.producer-regressions.throwing per-message callback reports exception and releases capture",+ "rdkafka-hs-integration.producer-regressions.repeated queue-full rejections release every callback capture",+ "rdkafka-hs-integration.producer-regressions.cancellation at a rejected enqueue releases capture before unmasking",+ "rdkafka-hs-integration.producer-regressions.cancellation after native acceptance retains callback until its report",+ "rdkafka-hs-integration.producer-regressions.another poller can deliver before successful enqueue returns",+ "rdkafka-hs-integration.producer-regressions.running callback keeps its capture after the native root is released",+ "rdkafka-hs-integration.producer-regressions.native error decoding failure releases rejected callback capture",+ "rdkafka-hs-integration.producer-regressions.non-null native success-code error rejects and releases capture",+ "rdkafka-hs-integration.producer-regressions.unknown native error code is preserved instead of reading errno",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: defaults",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: global only",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: topic only",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: disjoint maps",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: explicit topic wins duplicate",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: last topic property wins",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: empty topic map preserves global",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: zero topic timeout is infinite",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: maximum native topic timeout",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: explicit topic wins native timeout alias",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: topic codec overrides global codec",+ "rdkafka-hs-integration.producer-regressions.actual client configuration: global codec survives unrelated topic keys",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with NoCompression",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Gzip",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Snappy",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Lz4",+ "rdkafka-hs-integration.producer-regressions.byte-exact round trip with Zstd",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: none",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: inflight",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue+inflight",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: queue+nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: inflight+nonblocking",+ "rdkafka-hs-integration.producer-regressions.queued purge flags: all",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: none",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: inflight",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue+inflight",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: queue+nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: inflight+nonblocking",+ "rdkafka-hs-integration.producer-regressions.in-flight purge flags: all",+ "rdkafka-hs-integration.producer-regressions.bounded flush timeout recovers when the delayed response arrives",+ "rdkafka-hs-integration.producer-regressions.oversized rejection releases capture without a delivery report",+ "rdkafka-hs-integration.producer-regressions.known invalid partition rejection releases capture",+ "rdkafka-hs-integration.producer-regressions.empty queue supports repeated flush and close",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: NUL topic name",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: NUL header name",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: maximum unrepresentable partition",+ "rdkafka-hs-integration.producer-regressions.rejects before native enqueue: minimum unrepresentable partition",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: unknown global key",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: unknown topic key",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: invalid topic timeout",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: excessive topic timeout",+ "rdkafka-hs-integration.producer-regressions.configuration rejection: global-only key in topic map",+ "rdkafka-hs-integration.producer-regressions.later delivery callback replaces the earlier callback"+ ],+ "generated_property_tests": [+ "rdkafka-hs.Producer properties generated.program follows last-write semantics",+ "rdkafka-hs.Producer properties generated.configuration has left and right identity",+ "rdkafka-hs.Producer properties generated.configuration composition is associative",+ "rdkafka-hs.Producer properties generated.composition appends writes in order",+ "rdkafka-hs.Producer properties generated.unrelated keys survive a conflicting write",+ "rdkafka-hs.Producer properties generated.last explicit log level wins",+ "rdkafka-hs.Producer properties generated.fixed empty duplicate and binary text values",+ "rdkafka-hs-integration.producer-properties.callback composition preserves order and identity"+ ],+ "property_evidence": "docs/testing/producer-properties-evidence.json",+ "tooling_controls": 18,+ "mutation_evidence": "dist-producer-mutations/20261024T103255Z-mjr6tn_0/results.json",+ "mutation_archive_sha256": "d8ca382bf9f07a2f7fb7259035b82a901c627665dd0392720c13049897e9f166",+ "mutations": [+ {+ "mutation": "unchanged-control",+ "compiled": true,+ "exit": 0,+ "test": null,+ "safety_probe": false,+ "command": [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-producer-mutations/20261024T103255Z-mjr6tn_0/source/rdkafka-hs-1.0.0.1/dist-newstyle/build/aarch64-osx/ghc-9.12.4/rdkafka-hs-1.0.0.1/t/rdkafka-hs-integration/build/rdkafka-hs-integration/rdkafka-hs-integration",+ "-p",+ "/producer-regressions/",+ "+RTS",+ "-N2",+ "-RTS"+ ],+ "build_log": "dist-producer-mutations/20261024T103255Z-mjr6tn_0/unchanged-control.build.log",+ "test_log": "dist-producer-mutations/20261024T103255Z-mjr6tn_0/unchanged-control.test.log"+ },+ {+ "mutation": "topic-settings-dropped",+ "compiled": true,+ "exit": 1,+ "test": "explicit topic timeout expires an accepted message",+ "safety_probe": false,+ "command": [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-producer-mutations/20261024T103255Z-mjr6tn_0/source/rdkafka-hs-1.0.0.1/dist-newstyle/build/aarch64-osx/ghc-9.12.4/rdkafka-hs-1.0.0.1/t/rdkafka-hs-integration/build/rdkafka-hs-integration/rdkafka-hs-integration",+ "-p",+ "/producer-regressions/&&/explicit topic timeout expires an accepted message/",+ "+RTS",+ "-N2",+ "-RTS"+ ],+ "build_log": "dist-producer-mutations/20261024T103255Z-mjr6tn_0/topic-settings-dropped.build.log",+ "test_log": "dist-producer-mutations/20261024T103255Z-mjr6tn_0/topic-settings-dropped.test.log"+ },+ {+ "mutation": "rejection-root-retained",+ "compiled": true,+ "exit": 1,+ "test": "queue-full rejection releases callback capture without invoking it",+ "safety_probe": false,+ "command": [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-producer-mutations/20261024T103255Z-mjr6tn_0/source/rdkafka-hs-1.0.0.1/dist-newstyle/build/aarch64-osx/ghc-9.12.4/rdkafka-hs-1.0.0.1/t/rdkafka-hs-integration/build/rdkafka-hs-integration/rdkafka-hs-integration",+ "-p",+ "/producer-regressions/&&/queue-full rejection releases callback capture without invoking it/",+ "+RTS",+ "-N2",+ "-RTS"+ ],+ "build_log": "dist-producer-mutations/20261024T103255Z-mjr6tn_0/rejection-root-retained.build.log",+ "test_log": "dist-producer-mutations/20261024T103255Z-mjr6tn_0/rejection-root-retained.test.log"+ },+ {+ "mutation": "accepted-root-freed",+ "compiled": true,+ "exit": -6,+ "test": "accepted callback retains its capture until a purged report completes",+ "safety_probe": true,+ "command": [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-producer-mutations/20261024T103255Z-mjr6tn_0/source/rdkafka-hs-1.0.0.1/dist-newstyle/build/aarch64-osx/ghc-9.12.4/rdkafka-hs-1.0.0.1/t/rdkafka-hs-integration/build/rdkafka-hs-integration/rdkafka-hs-integration",+ "-p",+ "/producer-regressions/&&/accepted callback retains its capture until a purged report completes/",+ "+RTS",+ "-N2",+ "-RTS"+ ],+ "build_log": "dist-producer-mutations/20261024T103255Z-mjr6tn_0/accepted-root-freed.build.log",+ "test_log": "dist-producer-mutations/20261024T103255Z-mjr6tn_0/accepted-root-freed.test.log"+ },+ {+ "mutation": "enqueue-mask-removed",+ "compiled": true,+ "exit": -6,+ "test": "cancellation after native acceptance retains callback until its report",+ "safety_probe": true,+ "command": [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-producer-mutations/20261024T103255Z-mjr6tn_0/source/rdkafka-hs-1.0.0.1/dist-newstyle/build/aarch64-osx/ghc-9.12.4/rdkafka-hs-1.0.0.1/t/rdkafka-hs-integration/build/rdkafka-hs-integration/rdkafka-hs-integration",+ "-p",+ "/producer-regressions/&&/cancellation after native acceptance retains callback until its report/",+ "+RTS",+ "-N2",+ "-RTS"+ ],+ "build_log": "dist-producer-mutations/20261024T103255Z-mjr6tn_0/enqueue-mask-removed.build.log",+ "test_log": "dist-producer-mutations/20261024T103255Z-mjr6tn_0/enqueue-mask-removed.test.log"+ },+ {+ "mutation": "global-exception-skips-message",+ "compiled": true,+ "exit": 1,+ "test": "throwing global callback preserves per-message delivery and releases capture",+ "safety_probe": false,+ "command": [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-producer-mutations/20261024T103255Z-mjr6tn_0/source/rdkafka-hs-1.0.0.1/dist-newstyle/build/aarch64-osx/ghc-9.12.4/rdkafka-hs-1.0.0.1/t/rdkafka-hs-integration/build/rdkafka-hs-integration/rdkafka-hs-integration",+ "-p",+ "/producer-regressions/&&/throwing global callback preserves per-message delivery and releases capture/",+ "+RTS",+ "-N2",+ "-RTS"+ ],+ "build_log": "dist-producer-mutations/20261024T103255Z-mjr6tn_0/global-exception-skips-message.build.log",+ "test_log": "dist-producer-mutations/20261024T103255Z-mjr6tn_0/global-exception-skips-message.test.log"+ },+ {+ "mutation": "delivery-root-retained",+ "compiled": true,+ "exit": 1,+ "test": "accepted callback retains its capture until a purged report completes",+ "safety_probe": false,+ "command": [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-producer-mutations/20261024T103255Z-mjr6tn_0/source/rdkafka-hs-1.0.0.1/dist-newstyle/build/aarch64-osx/ghc-9.12.4/rdkafka-hs-1.0.0.1/t/rdkafka-hs-integration/build/rdkafka-hs-integration/rdkafka-hs-integration",+ "-p",+ "/producer-regressions/&&/accepted callback retains its capture until a purged report completes/",+ "+RTS",+ "-N2",+ "-RTS"+ ],+ "build_log": "dist-producer-mutations/20261024T103255Z-mjr6tn_0/delivery-root-retained.build.log",+ "test_log": "dist-producer-mutations/20261024T103255Z-mjr6tn_0/delivery-root-retained.test.log"+ },+ {+ "mutation": "empty-bytes-become-absent",+ "compiled": true,+ "exit": 1,+ "test": "byte-exact round trip with NoCompression",+ "safety_probe": false,+ "command": [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-producer-mutations/20261024T103255Z-mjr6tn_0/source/rdkafka-hs-1.0.0.1/dist-newstyle/build/aarch64-osx/ghc-9.12.4/rdkafka-hs-1.0.0.1/t/rdkafka-hs-integration/build/rdkafka-hs-integration/rdkafka-hs-integration",+ "-p",+ "/producer-regressions/&&/byte-exact round trip with NoCompression/",+ "+RTS",+ "-N2",+ "-RTS"+ ],+ "build_log": "dist-producer-mutations/20261024T103255Z-mjr6tn_0/empty-bytes-become-absent.build.log",+ "test_log": "dist-producer-mutations/20261024T103255Z-mjr6tn_0/empty-bytes-become-absent.test.log"+ },+ {+ "mutation": "input-validation-dropped",+ "compiled": true,+ "exit": 1,+ "test": "rejects before native enqueue: NUL topic name",+ "safety_probe": false,+ "command": [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-producer-mutations/20261024T103255Z-mjr6tn_0/source/rdkafka-hs-1.0.0.1/dist-newstyle/build/aarch64-osx/ghc-9.12.4/rdkafka-hs-1.0.0.1/t/rdkafka-hs-integration/build/rdkafka-hs-integration/rdkafka-hs-integration",+ "-p",+ "/producer-regressions/&&/rejects before native enqueue: NUL topic name/",+ "+RTS",+ "-N2",+ "-RTS"+ ],+ "build_log": "dist-producer-mutations/20261024T103255Z-mjr6tn_0/input-validation-dropped.build.log",+ "test_log": "dist-producer-mutations/20261024T103255Z-mjr6tn_0/input-validation-dropped.test.log"+ },+ {+ "mutation": "global-overrides-topic",+ "compiled": true,+ "exit": 1,+ "test": "actual client configuration: explicit topic wins duplicate",+ "safety_probe": false,+ "command": [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-producer-mutations/20261024T103255Z-mjr6tn_0/source/rdkafka-hs-1.0.0.1/dist-newstyle/build/aarch64-osx/ghc-9.12.4/rdkafka-hs-1.0.0.1/t/rdkafka-hs-integration/build/rdkafka-hs-integration/rdkafka-hs-integration",+ "-p",+ "/producer-regressions/&&/actual client configuration: explicit topic wins duplicate/",+ "+RTS",+ "-N2",+ "-RTS"+ ],+ "build_log": "dist-producer-mutations/20261024T103255Z-mjr6tn_0/global-overrides-topic.build.log",+ "test_log": "dist-producer-mutations/20261024T103255Z-mjr6tn_0/global-overrides-topic.test.log"+ },+ {+ "mutation": "headers-dropped",+ "compiled": true,+ "exit": 1,+ "test": "byte-exact round trip with NoCompression",+ "safety_probe": false,+ "command": [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-producer-mutations/20261024T103255Z-mjr6tn_0/source/rdkafka-hs-1.0.0.1/dist-newstyle/build/aarch64-osx/ghc-9.12.4/rdkafka-hs-1.0.0.1/t/rdkafka-hs-integration/build/rdkafka-hs-integration/rdkafka-hs-integration",+ "-p",+ "/producer-regressions/&&/byte-exact round trip with NoCompression/",+ "+RTS",+ "-N2",+ "-RTS"+ ],+ "build_log": "dist-producer-mutations/20261024T103255Z-mjr6tn_0/headers-dropped.build.log",+ "test_log": "dist-producer-mutations/20261024T103255Z-mjr6tn_0/headers-dropped.test.log"+ },+ {+ "mutation": "rejection-release-after-decoding",+ "compiled": true,+ "exit": 1,+ "test": "native error decoding failure releases rejected callback capture",+ "safety_probe": false,+ "command": [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-producer-mutations/20261024T103255Z-mjr6tn_0/source/rdkafka-hs-1.0.0.1/dist-newstyle/build/aarch64-osx/ghc-9.12.4/rdkafka-hs-1.0.0.1/t/rdkafka-hs-integration/build/rdkafka-hs-integration/rdkafka-hs-integration",+ "-p",+ "/producer-regressions/&&/native error decoding failure releases rejected callback capture/",+ "+RTS",+ "-N2",+ "-RTS"+ ],+ "build_log": "dist-producer-mutations/20261024T103255Z-mjr6tn_0/rejection-release-after-decoding.build.log",+ "test_log": "dist-producer-mutations/20261024T103255Z-mjr6tn_0/rejection-release-after-decoding.test.log"+ },+ {+ "mutation": "nonnull-success-code-accepted",+ "compiled": true,+ "exit": 1,+ "test": "non-null native success-code error rejects and releases capture",+ "safety_probe": false,+ "command": [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-producer-mutations/20261024T103255Z-mjr6tn_0/source/rdkafka-hs-1.0.0.1/dist-newstyle/build/aarch64-osx/ghc-9.12.4/rdkafka-hs-1.0.0.1/t/rdkafka-hs-integration/build/rdkafka-hs-integration/rdkafka-hs-integration",+ "-p",+ "/producer-regressions/&&/non-null native success-code error rejects and releases capture/",+ "+RTS",+ "-N2",+ "-RTS"+ ],+ "build_log": "dist-producer-mutations/20261024T103255Z-mjr6tn_0/nonnull-success-code-accepted.build.log",+ "test_log": "dist-producer-mutations/20261024T103255Z-mjr6tn_0/nonnull-success-code-accepted.test.log"+ },+ {+ "mutation": "unknown-error-replaced-by-errno",+ "compiled": true,+ "exit": 1,+ "test": "unknown native error code is preserved instead of reading errno",+ "safety_probe": false,+ "command": [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-producer-mutations/20261024T103255Z-mjr6tn_0/source/rdkafka-hs-1.0.0.1/dist-newstyle/build/aarch64-osx/ghc-9.12.4/rdkafka-hs-1.0.0.1/t/rdkafka-hs-integration/build/rdkafka-hs-integration/rdkafka-hs-integration",+ "-p",+ "/producer-regressions/&&/unknown native error code is preserved instead of reading errno/",+ "+RTS",+ "-N2",+ "-RTS"+ ],+ "build_log": "dist-producer-mutations/20261024T103255Z-mjr6tn_0/unknown-error-replaced-by-errno.build.log",+ "test_log": "dist-producer-mutations/20261024T103255Z-mjr6tn_0/unknown-error-replaced-by-errno.test.log"+ }+ ],+ "mutation_artifacts": {+ "dist-producer-mutations/20261024T103255Z-mjr6tn_0/results.json": "0a431c0c93842c2d95c1ceb7269a7d62304b489b43c81bd768871b0ebbdbcc5f",+ "dist-producer-mutations/20261024T103255Z-mjr6tn_0/unchanged-control.build.log": "d2973eeb662ac26aa20bbbb902ed4c737920dc09ae00ab25773d4ea88be9643d",+ "dist-producer-mutations/20261024T103255Z-mjr6tn_0/unchanged-control.test.log": "3ff41537bfc665fecfac2444bd220e881b76298eb38aa07d8f94f707868d1f04",+ "dist-producer-mutations/20261024T103255Z-mjr6tn_0/topic-settings-dropped.build.log": "405ff90869b82c886d3bd1caeabb91f353f8828193556983a8d89e7fd3194ccc",+ "dist-producer-mutations/20261024T103255Z-mjr6tn_0/topic-settings-dropped.test.log": "e3af567fe6335eaa44c3e8b9070a6b5d78e645446227f35fdfa522092975a4d7",+ "dist-producer-mutations/20261024T103255Z-mjr6tn_0/rejection-root-retained.build.log": "b2500ecbf1364d341d4c493b67dc22f839c20f9bbfda99ed8a87de2c0df8a710",+ "dist-producer-mutations/20261024T103255Z-mjr6tn_0/rejection-root-retained.test.log": "6efa8e78ad8c1de4ee280d374eb0ea40ca7ff9a925b39d761407c96a633291c3",+ "dist-producer-mutations/20261024T103255Z-mjr6tn_0/accepted-root-freed.build.log": "84aa7d09c478a8c1c5ea258b37531914e8357e99a92f1277d92703faae41ef61",+ "dist-producer-mutations/20261024T103255Z-mjr6tn_0/accepted-root-freed.test.log": "066d0f450565a1655e07fdc48c26e9707ab3044f1e0c8607b7424c7218bfe727",+ "dist-producer-mutations/20261024T103255Z-mjr6tn_0/enqueue-mask-removed.build.log": "fdfae13bfac48f02591613f79ff761fda3acf7f44bc12b87b19b6b47ddc95c42",+ "dist-producer-mutations/20261024T103255Z-mjr6tn_0/enqueue-mask-removed.test.log": "e66c2d39ceb089576886636431705d3def9df6d07269919c9ab184903c928731",+ "dist-producer-mutations/20261024T103255Z-mjr6tn_0/global-exception-skips-message.build.log": "e08251e8ac188bc0a1a352e46a24c9875822479e238accc7fc3e484c03f3437a",+ "dist-producer-mutations/20261024T103255Z-mjr6tn_0/global-exception-skips-message.test.log": "ae058feded655f93d9b85fa5cb8028a2ea4148b35353f90b348136d86a2ccbe6",+ "dist-producer-mutations/20261024T103255Z-mjr6tn_0/delivery-root-retained.build.log": "849872d6c5b2d36f4ec3d7777f4aeb5c8cda5c95d88e171c7c4190fb11d3e64c",+ "dist-producer-mutations/20261024T103255Z-mjr6tn_0/delivery-root-retained.test.log": "9fa6d635351780db9238d2d245729da1f308b16c0b61b6951f73c31ba3fca557",+ "dist-producer-mutations/20261024T103255Z-mjr6tn_0/empty-bytes-become-absent.build.log": "f228b32d788df5cfe4b625398a6ab5b656fd01d0ef2870d9a771713305da9b4e",+ "dist-producer-mutations/20261024T103255Z-mjr6tn_0/empty-bytes-become-absent.test.log": "cf0b16c9c83c3c0b1a3651b6ab6ed54f35806f4f9f84b06e7ae7697a620928a5",+ "dist-producer-mutations/20261024T103255Z-mjr6tn_0/input-validation-dropped.build.log": "34184df9aa5ccbb4b784ead2ac86cf7b16bed612f8a43bca88e1fcd19e0f7111",+ "dist-producer-mutations/20261024T103255Z-mjr6tn_0/input-validation-dropped.test.log": "dfdad91b2e71df71024838b3e98337ba1b04f0b36e787e5e3a64a6669dfae613",+ "dist-producer-mutations/20261024T103255Z-mjr6tn_0/global-overrides-topic.build.log": "b2500ecbf1364d341d4c493b67dc22f839c20f9bbfda99ed8a87de2c0df8a710",+ "dist-producer-mutations/20261024T103255Z-mjr6tn_0/global-overrides-topic.test.log": "a5f68aee4564f283f51ec6e1a6ac8dca54c31ed233201db11462528e42b88625",+ "dist-producer-mutations/20261024T103255Z-mjr6tn_0/headers-dropped.build.log": "6cc4d5fc3a5797cf1a4ae14e98ee8b5e77115ac5714426f692357e90fbbfa30b",+ "dist-producer-mutations/20261024T103255Z-mjr6tn_0/headers-dropped.test.log": "cf0b16c9c83c3c0b1a3651b6ab6ed54f35806f4f9f84b06e7ae7697a620928a5",+ "dist-producer-mutations/20261024T103255Z-mjr6tn_0/rejection-release-after-decoding.build.log": "b7e5f593dd634e4b591e98798483a1e1a6970b36bf33be7eb3e5ddce2a14bc3a",+ "dist-producer-mutations/20261024T103255Z-mjr6tn_0/rejection-release-after-decoding.test.log": "af0f3b6901463b5aa6520bd10a829c77a6bec927d58d2b47cb022be7b6330bf5",+ "dist-producer-mutations/20261024T103255Z-mjr6tn_0/nonnull-success-code-accepted.build.log": "84aa7d09c478a8c1c5ea258b37531914e8357e99a92f1277d92703faae41ef61",+ "dist-producer-mutations/20261024T103255Z-mjr6tn_0/nonnull-success-code-accepted.test.log": "8f1dbd6b50e4f542172124e84d6ea8568b970f8a563e6cad7c7e77d5e3b9b99c",+ "dist-producer-mutations/20261024T103255Z-mjr6tn_0/unknown-error-replaced-by-errno.build.log": "cb30ca7d422941981951f52959a3b5887dd780de24a8dedd9b470cc932a46d04",+ "dist-producer-mutations/20261024T103255Z-mjr6tn_0/unknown-error-replaced-by-errno.test.log": "491a11e989f93794d08b5011d859f5e3366934080e2c673bfd725a022f821f9d"+ },+ "native_diagnostics": "Callback weak controls and application ownership boundaries pass; EP-15 native heap/invalid-access diagnostics and compatibility remain open.",+ "status": "EP-9 complete; MasterPlan remaining children and gates remain open"+}
+ docs/testing/producer-properties-evidence.json view
@@ -0,0 +1,232 @@+{+ "revision": "8396f7b60ae762068970eb7d802e1bb1f514c07e",+ "fingerprint": "603e828f9aca4c20cfe867950e50ed5c106ff74de7db07124e960db07890cd9a",+ "configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ },+ "resolved_test_dependencies": {+ "QuickCheck": "2.19.0.0",+ "tasty": "1.5.5",+ "tasty-quickcheck": "0.11.1"+ },+ "selected_adapter": {+ "package": "mori://UnkindPartition/tasty/packages/tasty-quickcheck",+ "bounds": "^>=0.11.1",+ "hackage_revision": 7,+ "upstream_tag": "quickcheck-0.11.1",+ "upstream_commit": "f838314360d1c8f20f2919b376a5d2672aedc893"+ },+ "tests": [+ "rdkafka-hs.Producer properties generated.program follows last-write semantics",+ "rdkafka-hs.Producer properties generated.configuration has left and right identity",+ "rdkafka-hs.Producer properties generated.configuration composition is associative",+ "rdkafka-hs.Producer properties generated.composition appends writes in order",+ "rdkafka-hs.Producer properties generated.unrelated keys survive a conflicting write",+ "rdkafka-hs.Producer properties generated.last explicit log level wins",+ "rdkafka-hs.Producer properties generated.fixed empty duplicate and binary text values",+ "rdkafka-hs-integration.producer-properties.callback composition preserves order and identity"+ ],+ "normal": {+ "unit_tests": 21,+ "integration_tests": 244,+ "integration_seconds": 108.03+ },+ "instrumented": {+ "unit_tests": 21,+ "integration_tests": 244,+ "integration_seconds": 105.84+ },+ "stress": {+ "seed": 20261024,+ "pure_properties": 6,+ "cases_per_pure_property": 1000,+ "native_callback_cases": 1000+ },+ "mutation_evidence": "dist-property-mutations/20261024T103255Z-t4e5jvw8/results.json",+ "mutation_archive_sha256": "d8ca382bf9f07a2f7fb7259035b82a901c627665dd0392720c13049897e9f166",+ "mutations": [+ {+ "mutation": "pure-control",+ "compiled": true,+ "exit": 0,+ "command": [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-property-mutations/20261024T103255Z-t4e5jvw8/source/rdkafka-hs-1.0.0.1/dist-newstyle/build/aarch64-osx/ghc-9.12.4/rdkafka-hs-1.0.0.1/t/rdkafka-hs-test/build/rdkafka-hs-test/rdkafka-hs-test",+ "-p",+ "/Producer properties generated/",+ "--quickcheck-replay=20261024",+ "--quickcheck-tests=1000",+ "+RTS",+ "-N2",+ "-RTS"+ ],+ "build_log": "dist-property-mutations/20261024T103255Z-t4e5jvw8/pure-control.build.log",+ "test_log": "dist-property-mutations/20261024T103255Z-t4e5jvw8/pure-control.test.log",+ "replay_token": null,+ "replay_command": null+ },+ {+ "mutation": "callback-control",+ "compiled": true,+ "exit": 0,+ "command": [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-property-mutations/20261024T103255Z-t4e5jvw8/source/rdkafka-hs-1.0.0.1/dist-newstyle/build/aarch64-osx/ghc-9.12.4/rdkafka-hs-1.0.0.1/t/rdkafka-hs-integration/build/rdkafka-hs-integration/rdkafka-hs-integration",+ "-p",+ "/producer-properties/",+ "--quickcheck-replay=20261024",+ "--quickcheck-tests=1000",+ "+RTS",+ "-N2",+ "-RTS"+ ],+ "build_log": "dist-property-mutations/20261024T103255Z-t4e5jvw8/callback-control.build.log",+ "test_log": "dist-property-mutations/20261024T103255Z-t4e5jvw8/callback-control.test.log",+ "replay_token": null,+ "replay_command": null+ },+ {+ "mutation": "global-bias-reversed",+ "compiled": true,+ "exit": 1,+ "command": [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-property-mutations/20261024T103255Z-t4e5jvw8/source/rdkafka-hs-1.0.0.1/dist-newstyle/build/aarch64-osx/ghc-9.12.4/rdkafka-hs-1.0.0.1/t/rdkafka-hs-test/build/rdkafka-hs-test/rdkafka-hs-test",+ "-p",+ "/program follows last-write semantics/",+ "--quickcheck-replay=20261024",+ "--quickcheck-tests=1000",+ "+RTS",+ "-N2",+ "-RTS"+ ],+ "build_log": "dist-property-mutations/20261024T103255Z-t4e5jvw8/global-bias-reversed.build.log",+ "test_log": "dist-property-mutations/20261024T103255Z-t4e5jvw8/global-bias-reversed.test.log",+ "replay_token": "(SMGen 7603286587113926598 6750786074473487893,17)",+ "replay_command": [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-property-mutations/20261024T103255Z-t4e5jvw8/source/rdkafka-hs-1.0.0.1/dist-newstyle/build/aarch64-osx/ghc-9.12.4/rdkafka-hs-1.0.0.1/t/rdkafka-hs-test/build/rdkafka-hs-test/rdkafka-hs-test",+ "-p",+ "/program follows last-write semantics/",+ "--quickcheck-replay=(SMGen 7603286587113926598 6750786074473487893,17)",+ "--quickcheck-tests=1000",+ "+RTS",+ "-N2",+ "-RTS"+ ]+ },+ {+ "mutation": "topic-bias-reversed",+ "compiled": true,+ "exit": 1,+ "command": [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-property-mutations/20261024T103255Z-t4e5jvw8/source/rdkafka-hs-1.0.0.1/dist-newstyle/build/aarch64-osx/ghc-9.12.4/rdkafka-hs-1.0.0.1/t/rdkafka-hs-test/build/rdkafka-hs-test/rdkafka-hs-test",+ "-p",+ "/program follows last-write semantics/",+ "--quickcheck-replay=20261024",+ "--quickcheck-tests=1000",+ "+RTS",+ "-N2",+ "-RTS"+ ],+ "build_log": "dist-property-mutations/20261024T103255Z-t4e5jvw8/topic-bias-reversed.build.log",+ "test_log": "dist-property-mutations/20261024T103255Z-t4e5jvw8/topic-bias-reversed.test.log",+ "replay_token": "(SMGen 16220535950959846018 13032396016077086513,13)",+ "replay_command": [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-property-mutations/20261024T103255Z-t4e5jvw8/source/rdkafka-hs-1.0.0.1/dist-newstyle/build/aarch64-osx/ghc-9.12.4/rdkafka-hs-1.0.0.1/t/rdkafka-hs-test/build/rdkafka-hs-test/rdkafka-hs-test",+ "-p",+ "/program follows last-write semantics/",+ "--quickcheck-replay=(SMGen 16220535950959846018 13032396016077086513,13)",+ "--quickcheck-tests=1000",+ "+RTS",+ "-N2",+ "-RTS"+ ]+ },+ {+ "mutation": "log-level-bias-reversed",+ "compiled": true,+ "exit": 1,+ "command": [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-property-mutations/20261024T103255Z-t4e5jvw8/source/rdkafka-hs-1.0.0.1/dist-newstyle/build/aarch64-osx/ghc-9.12.4/rdkafka-hs-1.0.0.1/t/rdkafka-hs-test/build/rdkafka-hs-test/rdkafka-hs-test",+ "-p",+ "/program follows last-write semantics/",+ "--quickcheck-replay=20261024",+ "--quickcheck-tests=1000",+ "+RTS",+ "-N2",+ "-RTS"+ ],+ "build_log": "dist-property-mutations/20261024T103255Z-t4e5jvw8/log-level-bias-reversed.build.log",+ "test_log": "dist-property-mutations/20261024T103255Z-t4e5jvw8/log-level-bias-reversed.test.log",+ "replay_token": "(SMGen 876416796774277236 1544764139296909573,5)",+ "replay_command": [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-property-mutations/20261024T103255Z-t4e5jvw8/source/rdkafka-hs-1.0.0.1/dist-newstyle/build/aarch64-osx/ghc-9.12.4/rdkafka-hs-1.0.0.1/t/rdkafka-hs-test/build/rdkafka-hs-test/rdkafka-hs-test",+ "-p",+ "/program follows last-write semantics/",+ "--quickcheck-replay=(SMGen 876416796774277236 1544764139296909573,5)",+ "--quickcheck-tests=1000",+ "+RTS",+ "-N2",+ "-RTS"+ ]+ },+ {+ "mutation": "callback-order-reversed",+ "compiled": true,+ "exit": 1,+ "command": [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-property-mutations/20261024T103255Z-t4e5jvw8/source/rdkafka-hs-1.0.0.1/dist-newstyle/build/aarch64-osx/ghc-9.12.4/rdkafka-hs-1.0.0.1/t/rdkafka-hs-integration/build/rdkafka-hs-integration/rdkafka-hs-integration",+ "-p",+ "/producer-properties/",+ "--quickcheck-replay=20261024",+ "--quickcheck-tests=1000",+ "+RTS",+ "-N2",+ "-RTS"+ ],+ "build_log": "dist-property-mutations/20261024T103255Z-t4e5jvw8/callback-order-reversed.build.log",+ "test_log": "dist-property-mutations/20261024T103255Z-t4e5jvw8/callback-order-reversed.test.log",+ "replay_token": "(SMGen 13262595567567848789 8761751867160652105,2)",+ "replay_command": [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-property-mutations/20261024T103255Z-t4e5jvw8/source/rdkafka-hs-1.0.0.1/dist-newstyle/build/aarch64-osx/ghc-9.12.4/rdkafka-hs-1.0.0.1/t/rdkafka-hs-integration/build/rdkafka-hs-integration/rdkafka-hs-integration",+ "-p",+ "/producer-properties/",+ "--quickcheck-replay=(SMGen 13262595567567848789 8761751867160652105,2)",+ "--quickcheck-tests=1000",+ "+RTS",+ "-N2",+ "-RTS"+ ]+ }+ ],+ "mutation_artifacts": {+ "dist-property-mutations/20261024T103255Z-t4e5jvw8/results.json": "8f50a3050edee8a85ac219742ca21fa84b0d1dd4cc18dc7b8358815daa3d31e1",+ "dist-property-mutations/20261024T103255Z-t4e5jvw8/pure-control.build.log": "63cabfbc3f5b462c98b2d07c1ab3ddde0e8d85a1154967011ba72e73f5f67729",+ "dist-property-mutations/20261024T103255Z-t4e5jvw8/pure-control.test.log": "b4fa898f5eb0e246df167d311ecbd59688659b9b31f4d5ecd1271ad4eb8514d0",+ "dist-property-mutations/20261024T103255Z-t4e5jvw8/callback-control.build.log": "5b44994c521b2096e4e747679f8e98af18e4050d843f22f4a1616b6edabe612f",+ "dist-property-mutations/20261024T103255Z-t4e5jvw8/callback-control.test.log": "6af1832ce30c9d62eab494769793612a572378c489146dc822a3cee00ce57e3f",+ "dist-property-mutations/20261024T103255Z-t4e5jvw8/global-bias-reversed.build.log": "d88685c2906f8edfed803ac8e4483968e9c32b9149331f09924665f2ec661c0e",+ "dist-property-mutations/20261024T103255Z-t4e5jvw8/global-bias-reversed.test.log": "cf780ec944d019230f9ef866cedaa6fc182186aac75217f4353c8f2def9f9f05",+ "dist-property-mutations/20261024T103255Z-t4e5jvw8/global-bias-reversed.replay.log": "02634a23fc2b0034c2c229004c6e46aff8455b526f7ec6655153336b593cd05f",+ "dist-property-mutations/20261024T103255Z-t4e5jvw8/topic-bias-reversed.build.log": "d88685c2906f8edfed803ac8e4483968e9c32b9149331f09924665f2ec661c0e",+ "dist-property-mutations/20261024T103255Z-t4e5jvw8/topic-bias-reversed.test.log": "8a467a77136751225f2505198b6e5d24676cb4280fc903c6b2eccc616fcaffa6",+ "dist-property-mutations/20261024T103255Z-t4e5jvw8/topic-bias-reversed.replay.log": "72f81d6044bfbff465a331ae7b7ec0c364f241237e778b0391a68a8a18028b69",+ "dist-property-mutations/20261024T103255Z-t4e5jvw8/log-level-bias-reversed.build.log": "d88685c2906f8edfed803ac8e4483968e9c32b9149331f09924665f2ec661c0e",+ "dist-property-mutations/20261024T103255Z-t4e5jvw8/log-level-bias-reversed.test.log": "92970c4d15fdddbdd47f65ea062b0e378585b34f394c31f21471ef1c4103c867",+ "dist-property-mutations/20261024T103255Z-t4e5jvw8/log-level-bias-reversed.replay.log": "63216342d6e19387a84cfbe9fe34fdbbb9165a65977439b2f2169f5b9d890be7",+ "dist-property-mutations/20261024T103255Z-t4e5jvw8/callback-order-reversed.build.log": "2eef00e7196ac2ca384b4797882201dfe9b8b3e24be4eba8be116f8bc5894202",+ "dist-property-mutations/20261024T103255Z-t4e5jvw8/callback-order-reversed.test.log": "1c8f19964beb3e3575da40b77e2d251881f6a19bcefe986ab49fe435e742e522",+ "dist-property-mutations/20261024T103255Z-t4e5jvw8/callback-order-reversed.replay.log": "c0a83178ddafb780168ee388bec29b831c659a5544c2b236340ff1cc830beb38"+ },+ "status": "producer-composition integration milestone accepted; EP-14 remaining laws and public API coverage stay open"+}
+ docs/testing/public-data-evidence.json view
@@ -0,0 +1,56 @@+{+ "status": "accepted data-law and mapped coverage checkpoint; EP-14 incomplete",+ "fingerprint": "19b70f13af39a6184d9fc6299551348e74c2a937c32a81773b97a70ba6764914",+ "full_mapped": {+ "manifest": "docs/testing/coverage-evidence.json",+ "registered": 596,+ "unit": 78,+ "integration": 518,+ "property_cases": 1000,+ "seed": 20261024,+ "nonthreaded_supplement": 4,+ "merged_nonthreaded_modules": [+ "Kafka.Consumer"+ ],+ "handwritten_native_wrapper_ticks": 2902,+ "log": "/tmp/rdkafka-ep14-data-full-coverage-final.log",+ "sha256": "7bad3dbfe025b6ad1618be2374d99e8e41de6b5b85bc047ee794de7ab727b729"+ },+ "normal_unit": {+ "passed": 78,+ "log": "/tmp/rdkafka-ep14-data-unit-final2.log",+ "sha256": "a975e7a850017af3665f5a68554289f8c286a78e74c60accb075d8a35515571c"+ },+ "native_instrumented_data": {+ "passed": 13,+ "log": "/tmp/rdkafka-ep14-data-asan.log",+ "sha256": "1856a625993491588bd63719ba376aca21dc5b9137c46d584e861197abfb701c",+ "scope": "Before the final distinct metadata-member byte generator strengthening; final full mapped run covers that strengthening. AddressSanitizer, not LeakSanitizer."+ },+ "mutations": "dist-mutations/20261024T171848Z-data-19904-0/results.json",+ "compiled_mutations_caught": 3,+ "controls": 2,+ "mutation_scope": [+ "wrong consumer property key",+ "reversed producer debug context order",+ "native metadata/assignment byte field substitution"+ ],+ "tooling_controls": 22,+ "required_checks": {+ "log": "/tmp/rdkafka-ep14-data-check.log",+ "sha256": "14a33c039a398fe5c26b56fe5f70e5b85736e658deae4d70cfc4bedff3c68545"+ },+ "corrections": [+ "Native error descriptor boundary sentinels have NULL descriptions. The test C shim now filters both name and description; 188 described errors and three numeric sentinels are checked. The initial shim crash is excluded from library defect evidence.",+ "Physical deriving declarations are compiler-generated coverage. Handwritten instances and mixed declaration/code lines are not exempt.",+ "Independent runtime builds have different generated RdKafka MIX hashes. Only the identical Kafka.Consumer module is merged; no tick or hash rewriting."+ ],+ "inventory": {+ "newly_reconciled": 57,+ "statuses": {+ "tested": 86,+ "unimplemented": 95+ }+ },+ "remaining": "Builder/native-validation reconciliation, metadata Unicode boundaries, ordinary consumer API gaps, saved deprecated-seek failure, remaining handwritten misses and EP-15 environments remain open."+}
+ docs/testing/public-properties-evidence.json view
@@ -0,0 +1,87 @@+{+ "status": "M1 accepted; EP-14 remains in progress",+ "fingerprint": "a7a1729efeadb0f9262ae5248898367d977708db484ccd9e1a0d2f9bc1cd9a7d",+ "pure_generated_properties_added": 31,+ "pure_fixed_cases_added": 5,+ "native_generated_properties_added": 2,+ "native_fixed_cases_added": 2,+ "cases_per_generated_property": 1000,+ "seed": 20261024,+ "runs": {+ "unit": {+ "log": "/tmp/rdkafka-ep14-m1-unit.log",+ "test_count": 65,+ "sha256": "c330de31bd8e5a056b52aa24e2c510dfb1ac2bc9b6fe97801c4e5d336766f1fe"+ },+ "native": {+ "log": "/tmp/rdkafka-ep14-m1-native.log",+ "test_count": 4,+ "sha256": "8afe2d981440d9adfe7a85b3181476879ff7352a70e74003c3ed0e0bd25c0c6c"+ },+ "instrumented-unit": {+ "log": "/tmp/rdkafka-ep14-m1-instrumented-unit.log",+ "test_count": 65,+ "sha256": "1dfe166bb35da18bcadf5332bc05d1c69836e13dc3faad4ab57645ac7826338b"+ },+ "instrumented-native": {+ "log": "/tmp/rdkafka-ep14-m1-instrumented-native.log",+ "test_count": 4,+ "sha256": "962738c7754efdd5d608ce96303c9e578552d06208c41b2b728bb271101bcddd"+ }+ },+ "mutation_report": "dist-mutations/20261024T144754Z-public-1339-0/results.json",+ "compiled_mutations_caught": 8,+ "controls": 2,+ "shrunk_and_replayed": [+ {+ "mutation": "consumer-bias-reversed",+ "token": "(SMGen 7603286587113926598 6750786074473487893,17)",+ "log": "dist-mutations/20261024T144754Z-public-1339-0/consumer-bias-reversed.replay.log"+ },+ {+ "mutation": "consumer-poll-mode-bias-reversed",+ "token": "(SMGen 1259825427043897998 10285425458784129881,10)",+ "log": "dist-mutations/20261024T144754Z-public-1339-0/consumer-poll-mode-bias-reversed.replay.log"+ },+ {+ "mutation": "subscription-bias-reversed",+ "token": "(SMGen 1259825427043897998 10285425458784129881,10)",+ "log": "dist-mutations/20261024T144754Z-public-1339-0/subscription-bias-reversed.replay.log"+ },+ {+ "mutation": "header-order-reversed",+ "token": "(SMGen 1898965826930799901 8987761867696480937,3)",+ "log": "dist-mutations/20261024T144754Z-public-1339-0/header-order-reversed.replay.log"+ },+ {+ "mutation": "record-map-loses-headers",+ "token": "(SMGen 13262595567567848789 8761751867160652105,2)",+ "log": "dist-mutations/20261024T144754Z-public-1339-0/record-map-loses-headers.replay.log"+ },+ {+ "mutation": "version-minor-shifted",+ "token": "(SMGen 13262595567567848789 8761751867160652105,2)",+ "log": "dist-mutations/20261024T144754Z-public-1339-0/version-minor-shifted.replay.log"+ },+ {+ "mutation": "consumer-callback-order-reversed",+ "token": "(SMGen 396203672453433329 7631371620466699889,1)",+ "log": "dist-mutations/20261024T144754Z-public-1339-0/consumer-callback-order-reversed.replay.log"+ },+ {+ "mutation": "generated-source-offset-not-advanced",+ "token": "(SMGen 16269197159708892605 15933398308838956321,0)",+ "log": "dist-mutations/20261024T144754Z-public-1339-0/generated-source-offset-not-advanced.replay.log"+ }+ ],+ "inherited_subscription_failure": {+ "log": "/tmp/rdkafka-ep14-subscription-before.log",+ "minimal_counterexample": "[Reset Earliest, Reset Latest]",+ "replay": "(SMGen 1259825427043897998 10285425458784129881,10)",+ "resolution": "User explicitly chose later values; corrected map union and both native consumer modes read preexisting data with the final earliest policy."+ },+ "native_offset_domain": "Nonnegative consumed offsets whose next position fits signed 64-bit storage, including maxBound - 1; the native observer checks the actual partition-list field, native error release and group-metadata release.",+ "callback_fixture": "Real constructor log callbacks avoid a connection-failure delay per generated program; the earlier stress timeout remains /tmp/rdkafka-ep14-consumer-properties.log.",+ "required_checks": "/tmp/rdkafka-ep14-m1-check.log",+ "remaining": "M2 public API/diagnostic/state coverage and the known batch/cooperative-rebalance/deprecated-seek defects; M3 global coverage/inventory reconciliation. These focused HPC runs do not replace final full-candidate coverage collection."+}
+ docs/testing/queue-notification-evidence.json view
@@ -0,0 +1,71 @@+{+ "status": "earlier checkpoint; refreshed queue observations accepted in final-boundaries-evidence.json",+ "fingerprint": "e60269df1b56e383003809e16cd6e9ec074ae17a069f8e1d992cb3aed12330bb",+ "runs": {+ "normal": {+ "log": "/tmp/rdkafka-ep14-queue-normal-corrected.log",+ "sha256": "16e2e27091505240299910908952b9d33b8c3faa75c2652c22574bb0b636a76d",+ "passed": 13+ },+ "instrumented-haskell": {+ "log": "/tmp/rdkafka-ep14-queue-hpc-corrected.log",+ "sha256": "95bfa35c4144bd70448312210108ed8934c790bab4566247a4af56fccda5f2a6",+ "passed": 13+ },+ "instrumented-native": {+ "log": "/tmp/rdkafka-ep14-queue-asan.log",+ "sha256": "84b41bc36de02cdeebb33720567e332f55646503e2ed56d5923365021ffd359f",+ "passed": 13+ }+ },+ "mutations": "dist-mutations/20261024T220955Z-queue-1667-0/results.json",+ "compiled_mutations_caught": 5,+ "controls": 1,+ "original_cases_retained": 6,+ "registered_cases": 13,+ "scope": [+ "All original notification, preloaded-record and rearm cases are retained in both modes",+ "Native queue length is observed within the wrapper borrowing call; no native queue pointer is retained",+ "Producer delivery reports and complete record identity/offsets are checked; unexpected record/descriptor errors remain failures",+ "Close/destroy preserve caller descriptor ownership, and disabled/closed operations do not register notifications",+ "Pipes outlive consumer destruction even when a test action fails",+ "Queue cases move to the independent public-contract group without removing any original case"+ ],+ "native_library": "mori://confluentinc/librdkafka",+ "native_version": "2.15.0",+ "leak_instrumentation": false,+ "fixture_correction": {+ "logs": [+ "/tmp/rdkafka-ep14-queue-normal.log",+ "/tmp/rdkafka-ep14-queue-hpc.log"+ ],+ "reason": "The first observer retained a borrowed sync queue wrapper beyond release. Those runs aborted and are excluded. The corrected observer stores only scalar values observed within the borrowing call.",+ "cleanup_log": "/tmp/rdkafka-ep14-queue-crash-cleanup.log",+ "owned_topics_removed": [+ "fdpcykbjns-queue-event-sync-preloaded",+ "savlqyosei-queue-event-sync-preloaded"+ ],+ "ownership_check": "Both exact new fixture names contained only the expected early record at partition zero/offset zero with timestamps matching these two aborted runs. No other topics were removed."+ },+ "dependency_api_check": {+ "project": "mori://ghc/ghc",+ "release_tag": "ghc-9.12.4-release",+ "base_version": "4.21.2.0",+ "source_paths": [+ "libraries/base/src/GHC/IO/Exception.hs",+ "libraries/ghc-internal/src/GHC/Internal/IO/Exception.hs"+ ],+ "source_artifact_uri_pending": true,+ "lookup": "Mori has no base package entry; the upstream release-tag sources verify exported IOException errno fields."+ },+ "remaining": "Whole-candidate reconciliation, other boundary/ownership/source-miss cases, saved legacy-seek diagnosis and EP-15 remain open.",+ "required_checks": {+ "log": "/tmp/rdkafka-ep14-queue-check.log",+ "sha256": "9209fffbf1a9256b2f0982806deb034bc2baedcc4e2ffe62c7c2aaf960176ff7"+ },+ "prefetch_followup": {+ "reason": "The scalar observer refresh argument was unused. Existing notification/error/teardown results remain recorded, but the earlier preload check could read a stale count. A new empty-payload case exposed the issue; the helper now calls refresh on every observation.",+ "failure_log": "/tmp/rdkafka-ep14-final-boundaries-hpc.log",+ "replacement_checks": "Accepted: final-boundaries-evidence.json; all five original queue mutations rerun plus stale-observer and binary-size regressions."+ }+}
+ docs/testing/rebalance-error-evidence.json view
@@ -0,0 +1,43 @@+{+ "status": "accepted M2 rebalance-error checkpoint; EP-14 incomplete",+ "fingerprint": "35b563bf08998d3045496fe0c1354e195a83d99b4113322471d1890d8f45ca16",+ "runs": {+ "normal": {+ "log": "/tmp/rdkafka-ep14-rebalance-normal.log",+ "sha256": "593582cfd66b6d83394e433a4e675ba56e429048b477353033628506dc0d6a2f",+ "passed": 39,+ "seconds": 18.96+ },+ "instrumented-haskell": {+ "log": "/tmp/rdkafka-ep14-rebalance-hpc.log",+ "sha256": "4efa442e309264cfaee08d0954545f89822fcdf54121bad051d23b69f3452527",+ "passed": 15,+ "seconds": 2.14+ },+ "instrumented-native": {+ "log": "/tmp/rdkafka-ep14-rebalance-asan.log",+ "sha256": "054d094cd7a91fcd0bbce886e94accaa734c0745ce29ba9bf14ce97ba32117a4",+ "passed": 15,+ "seconds": 2.86+ }+ },+ "mutations": "dist-mutations/20261024T160849Z-rebalance-15738-0/results.json",+ "compiled_mutations_caught": 4,+ "controls": 1,+ "baseline": {+ "revision": "825be68",+ "log": "/tmp/rdkafka-ep14-rebalance-baseline.log",+ "failed": 12,+ "total": 13,+ "failures": "Cooperative error objects retained; eager and cooperative failures suppressed; after-events incorrectly reported success."+ },+ "controlled_native_scope": "Twelve isolated children invoke the installed callback with native partition lists and actually allocated cooperative error objects. Tests distinguish protocol, assign/revoke, async/sync and cooperative decoder failure; this does not simulate a real group handoff.",+ "real_broker_scope": "Two cooperative-sticky consumers independently verify exact record delivery and assignment/revocation event order, one per callback poll mode.",+ "native_counter_control": "An actual native error is intentionally retained until after the counter assertion and released by fixture cleanup.",+ "native_library": "mori://confluentinc/librdkafka",+ "native_version": "2.15.0",+ "native_diagnostic_control": "docs/testing/callback-native-diagnostics.json",+ "leak_instrumentation": false,+ "required_checks": "/tmp/rdkafka-ep14-rebalance-check.log",+ "remaining": "Consumer state, metadata and diagnostics contracts, deprecated seek, final coverage reconciliation and EP-15 environments remain open."+}
+ docs/testing/runtime-evidence.json view
@@ -0,0 +1,41 @@+{+ "status": "accepted M2 runtime checkpoint; EP-14 incomplete",+ "fingerprint": "617dcc03cd792c1c6d67b8333b8a1b5b6991389253d635572d006662324ef22c",+ "runs": {+ "threaded": {+ "log": "/tmp/rdkafka-ep14-runtime-threaded.log",+ "sha256": "2a423c824c66822ed967b03ea1f562131029449440a454c80d32c566477a0a96",+ "passed": 4,+ "seconds": 0.8+ },+ "nonthreaded": {+ "log": "/tmp/rdkafka-ep14-runtime-nonthreaded.log",+ "sha256": "8c4fd155a17285f51b1b681026f6c83b27f4b85aa861a3150aa82885d99ef4f6",+ "passed": 4,+ "seconds": 0.8+ },+ "hpc": {+ "log": "/tmp/rdkafka-ep14-runtime-hpc.log",+ "sha256": "3efc5de756f69eb1d1a5cf2738a3293a3c18b2d2292e14c27986d9c2b0d5ee28",+ "passed": 4,+ "seconds": 0.82+ }+ },+ "mutations": "dist-mutations/20261024T163256Z-runtime-57734-0/results.json",+ "compiled_mutations_caught": 1,+ "controls": 1,+ "mutation_runtime": "Actual nonthreaded executable built with -single-threaded -with-rtsopts=-T; no -N runtime argument. Other mutation families retain their threaded build and runtime arguments.",+ "baseline": {+ "revision": "cc83145",+ "async_log": "/tmp/rdkafka-ep14-nonthreaded-async.log",+ "async_failed": 1,+ "async_seconds": 10.25,+ "sync_log": "/tmp/rdkafka-ep14-nonthreaded-sync.log",+ "note": "The broad sync substring also selected async: async failed and sync alone passed (0.18s). Accepted fixed runs use the exact runtime-contract group."+ },+ "nonthreaded_rts_info": "/tmp/rdkafka-ep14-runtime-rts-info.log",+ "rts_way": "rts_v",+ "scope": "Default and explicit async guards; actual sync subscription record and deprecated runner close, in both runtimes.",+ "required_checks": "/tmp/rdkafka-ep14-runtime-check.log",+ "remaining": "Metadata and remaining public contracts, saved deprecated-seek failure, final mapped coverage/inventory reconciliation and EP-15 environments remain open."+}
+ docs/testing/seek-evidence.json view
@@ -0,0 +1,165 @@+{+ "schema_version": 1,+ "owner": 10,+ "status": "complete",+ "revision": "4c2a519c7c1ea72f05e9f97a6ac77a0abd28054a",+ "fingerprint": "e0efdb19089bfda33df08ddbc34c1a98a57c7a16430ce167addf2a2ff3c3fa14",+ "at": "2026-10-24T11:02:42.589841+00:00",+ "focused_tests": 76,+ "unit_tests": 21,+ "integration_tests": 320,+ "normal_seconds": 156.82,+ "instrumented_seconds": 149.39,+ "tooling_controls": 18,+ "native": "(\"2.15.0\",34537727)",+ "broker_versions": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "tests": [+ "rdkafka-hs-integration.seek-partitions.async.unassigned member reports native error",+ "rdkafka-hs-integration.seek-partitions.async.empty list preserves top-level invalid argument",+ "rdkafka-hs-integration.seek-partitions.async.zero-timeout unassigned failure is immediate",+ "rdkafka-hs-integration.seek-partitions.async.empty zero-timeout preserves top-level error",+ "rdkafka-hs-integration.seek-partitions.async.rewind without assignment does not seek",+ "rdkafka-hs-integration.seek-partitions.async.top-level error precedes member error and is destroyed",+ "rdkafka-hs-integration.seek-partitions.async.first substantive error follows input order",+ "rdkafka-hs-integration.seek-partitions.async.reversed input selects the other substantive error",+ "rdkafka-hs-integration.seek-partitions.async.zero-timeout skips pending but reports later failure",+ "rdkafka-hs-integration.seek-partitions.async.nonzero-timeout preserves residual pending",+ "rdkafka-hs-integration.seek-partitions.async.zero-timeout all pending promises initiation only",+ "rdkafka-hs-integration.seek-partitions.async.nonzero-timeout all pending is not success",+ "rdkafka-hs-integration.seek-partitions.async.top-level decoder exception still destroys error object",+ "rdkafka-hs-integration.seek-partitions.async.rewind assignment failure prevents seek",+ "rdkafka-hs-integration.seek-partitions.async.single seek replays exact record",+ "rdkafka-hs-integration.seek-partitions.async.multiple successful seeks replay both partitions",+ "rdkafka-hs-integration.seek-partitions.async.mixed seek reports failure without rolling back success",+ "rdkafka-hs-integration.seek-partitions.async.mixed errors follow actual request order",+ "rdkafka-hs-integration.seek-partitions.async.zero-timeout valid seek is followed by synchronous replay",+ "rdkafka-hs-integration.seek-partitions.async.zero-timeout mixed request keeps immediate unknown error",+ "rdkafka-hs-integration.seek-partitions.async.zero-timeout logical offsets promise initiation only",+ "rdkafka-hs-integration.seek-partitions.async.infinite native timeout completes a valid seek",+ "rdkafka-hs-integration.seek-partitions.async.duplicate entries preserve residual native pending error",+ "rdkafka-hs-integration.seek-partitions.async.unassigned existing partition returns state error",+ "rdkafka-hs-integration.seek-partitions.async.unknown topic reports member error",+ "rdkafka-hs-integration.seek-partitions.async.stored sentinel is rejected without altering position",+ "rdkafka-hs-integration.seek-partitions.async.end and exact high watermark produce no record",+ "rdkafka-hs-integration.seek-partitions.async.seek before retained log range resets to actual low watermark",+ "rdkafka-hs-integration.seek-partitions.async.rewind without committed offset starts at beginning",+ "rdkafka-hs-integration.seek-partitions.async.rewind uses committed next offset exactly",+ "rdkafka-hs-integration.seek-partitions.async.rewind message commit resumes after committed message",+ "rdkafka-hs-integration.seek-partitions.async.rewind lookup failure prevents seek",+ "rdkafka-hs-integration.seek-partitions.async.rewind propagates assignment change after committed lookup",+ "rdkafka-hs-integration.seek-partitions.async.beginning sentinel replays offset zero",+ "rdkafka-hs-integration.seek-partitions.async.absolute low watermark replays offset zero",+ "rdkafka-hs-integration.seek-partitions.async.invalid sentinel uses configured earliest reset",+ "rdkafka-hs-integration.seek-partitions.async.above high watermark uses configured earliest reset",+ "rdkafka-hs-integration.seek-partitions.async.native tail sentinel replays final two records",+ "rdkafka-hs-integration.seek-partitions.sync.unassigned member reports native error",+ "rdkafka-hs-integration.seek-partitions.sync.empty list preserves top-level invalid argument",+ "rdkafka-hs-integration.seek-partitions.sync.zero-timeout unassigned failure is immediate",+ "rdkafka-hs-integration.seek-partitions.sync.empty zero-timeout preserves top-level error",+ "rdkafka-hs-integration.seek-partitions.sync.rewind without assignment does not seek",+ "rdkafka-hs-integration.seek-partitions.sync.top-level error precedes member error and is destroyed",+ "rdkafka-hs-integration.seek-partitions.sync.first substantive error follows input order",+ "rdkafka-hs-integration.seek-partitions.sync.reversed input selects the other substantive error",+ "rdkafka-hs-integration.seek-partitions.sync.zero-timeout skips pending but reports later failure",+ "rdkafka-hs-integration.seek-partitions.sync.nonzero-timeout preserves residual pending",+ "rdkafka-hs-integration.seek-partitions.sync.zero-timeout all pending promises initiation only",+ "rdkafka-hs-integration.seek-partitions.sync.nonzero-timeout all pending is not success",+ "rdkafka-hs-integration.seek-partitions.sync.top-level decoder exception still destroys error object",+ "rdkafka-hs-integration.seek-partitions.sync.rewind assignment failure prevents seek",+ "rdkafka-hs-integration.seek-partitions.sync.single seek replays exact record",+ "rdkafka-hs-integration.seek-partitions.sync.multiple successful seeks replay both partitions",+ "rdkafka-hs-integration.seek-partitions.sync.mixed seek reports failure without rolling back success",+ "rdkafka-hs-integration.seek-partitions.sync.mixed errors follow actual request order",+ "rdkafka-hs-integration.seek-partitions.sync.zero-timeout valid seek is followed by synchronous replay",+ "rdkafka-hs-integration.seek-partitions.sync.zero-timeout mixed request keeps immediate unknown error",+ "rdkafka-hs-integration.seek-partitions.sync.zero-timeout logical offsets promise initiation only",+ "rdkafka-hs-integration.seek-partitions.sync.infinite native timeout completes a valid seek",+ "rdkafka-hs-integration.seek-partitions.sync.duplicate entries preserve residual native pending error",+ "rdkafka-hs-integration.seek-partitions.sync.unassigned existing partition returns state error",+ "rdkafka-hs-integration.seek-partitions.sync.unknown topic reports member error",+ "rdkafka-hs-integration.seek-partitions.sync.stored sentinel is rejected without altering position",+ "rdkafka-hs-integration.seek-partitions.sync.end and exact high watermark produce no record",+ "rdkafka-hs-integration.seek-partitions.sync.seek before retained log range resets to actual low watermark",+ "rdkafka-hs-integration.seek-partitions.sync.rewind without committed offset starts at beginning",+ "rdkafka-hs-integration.seek-partitions.sync.rewind uses committed next offset exactly",+ "rdkafka-hs-integration.seek-partitions.sync.rewind message commit resumes after committed message",+ "rdkafka-hs-integration.seek-partitions.sync.rewind lookup failure prevents seek",+ "rdkafka-hs-integration.seek-partitions.sync.rewind propagates assignment change after committed lookup",+ "rdkafka-hs-integration.seek-partitions.sync.beginning sentinel replays offset zero",+ "rdkafka-hs-integration.seek-partitions.sync.absolute low watermark replays offset zero",+ "rdkafka-hs-integration.seek-partitions.sync.invalid sentinel uses configured earliest reset",+ "rdkafka-hs-integration.seek-partitions.sync.above high watermark uses configured earliest reset",+ "rdkafka-hs-integration.seek-partitions.sync.native tail sentinel replays final two records"+ ],+ "mutation_evidence": "dist-seek-mutations/20261024T105811Z-z8yr14j7/results.json",+ "mutations": 7,+ "unchanged_control": true,+ "source_reference": {+ "project": "mori://confluentinc/librdkafka",+ "project_relative_paths": [+ "librdkafka/src/rdkafka.h",+ "librdkafka/src/rdkafka.c",+ "librdkafka/src/rdkafka_partition.c"+ ],+ "artifact_uri_status": "pending",+ "local_revision": "122fc0c98562d086c3618bf376862632ae0808e1",+ "release_tag": "v2.15.0",+ "release_revision": "9a94e11452cdeb0a844db44ee5dd01ccbe17d3ab",+ "release_function_sha256": {+ "rd_kafka_seek_partitions": "2f37a035e8427eafda6d7a35d3c423c5dbbf1fe97b25e09535123564894b54eb",+ "rd_kafka_toppar_seek": "649914c932a65375d7043ae6c1941ac62d42ec1f98587b27b44390991b933f46",+ "rd_kafka_topic_partition_list_set_offset": "9536878a019edaffd90edc02a218bcc64314b71d5e020fdc198465bf153c5e29"+ },+ "local_functions_identical_to_release": true+ },+ "commands": {+ "focused": "nix develop -c just test-it '--test-options=-p /seek-partitions/'",+ "normal": "nix develop -c cabal test rdkafka-hs-test rdkafka-hs-integration -f integration --test-show-details=direct",+ "instrumented": "nix develop -c just coverage",+ "mutations": "nix develop -c python3 scripts/test-seek-mutations.py",+ "checks": [+ "nix develop -c just check",+ "nix develop -c cabal check",+ "okf validate docs/adr --strict --profile docs/adr/profile.dhall --profile-enforce --log-enforce"+ ]+ },+ "artifacts": {+ "/tmp/rdkafka-ep10-before.log": "f1a047d79f732e979da2dd34749c3599e23385f8713577a7d562ffbec5a5243e",+ "/tmp/rdkafka-ep10-matrix.log": "06ac8c7254a563534ad5e0565043689a7ff778aa01639ce35fc4db844f621924",+ "/tmp/rdkafka-ep10-matrix3.log": "2f1d7fe426444e23508d7b8d1db4d11fc23dcb428edd1e9f1953cc6ef659b291",+ "/tmp/rdkafka-ep10-normal.log": "4afdd6c417f6a4900034372090865bd63b4eb1445b368605313d9ba7673595ad",+ "/tmp/rdkafka-ep10-check.log": "d057de772c82e3e611b346c9a0c1e8cea400369f5b3e041849eaeb847a01a9e4",+ "/tmp/rdkafka-ep10-cabal-check.log": "e56e09e5ab9d1068ef55f6cfff9c20c9defa3f40af0c5abb1ff43d69d5ce931e",+ "/tmp/rdkafka-ep10-coverage.log": "8a0bb043d7f99ba5b1aaf1bbab3b45d696cd1f0e7082833fc89b6329063676d7",+ "dist-seek-mutations/20261024T105811Z-z8yr14j7/results.json": "3a593ea4fb338a71dee2a78491eff1343de879a5ff8405ac480cdf91faa2fb3d",+ "dist-seek-mutations/20261024T105811Z-z8yr14j7/unchanged-control.build.log": "d2f08ca40b87a60371f36b0be3f5822c636bde13bbe516eb97fa68170e17a2db",+ "dist-seek-mutations/20261024T105811Z-z8yr14j7/unchanged-control.test.log": "1ae9bf8c004dda8ed5ce07bd7a0fc75ddd37080fc429011dbe220c276bf0fd64",+ "dist-seek-mutations/20261024T105811Z-z8yr14j7/member-errors-dropped.build.log": "d4e1748b9a8a0221535f86fc1799e3c96edd4ea858030d32929de8b8596f1267",+ "dist-seek-mutations/20261024T105811Z-z8yr14j7/member-errors-dropped.test.log": "0931bc2cdea3d1a675f3be43ac4e58e419ff06665a8eeeb434415d7eb5c95401",+ "dist-seek-mutations/20261024T105811Z-z8yr14j7/error-order-reversed.build.log": "a987a77cfb0f3da8c4e120d84c73cc748b6be14347a917dc6d3d8d49534a73de",+ "dist-seek-mutations/20261024T105811Z-z8yr14j7/error-order-reversed.test.log": "e3a44dc4a043806bb91d318f9ec10b80d58206b0b8254b594fa832775d43ca04",+ "dist-seek-mutations/20261024T105811Z-z8yr14j7/pending-always-normalized.build.log": "a987a77cfb0f3da8c4e120d84c73cc748b6be14347a917dc6d3d8d49534a73de",+ "dist-seek-mutations/20261024T105811Z-z8yr14j7/pending-always-normalized.test.log": "b74f1c229ef02ee0a459057716c944321a446c98af5c38e7c83b50741ec29842",+ "dist-seek-mutations/20261024T105811Z-z8yr14j7/pending-never-normalized.build.log": "c47185e3f01580faa721695b917dfd8b9757bab191190b0ac15abf17ac189b55",+ "dist-seek-mutations/20261024T105811Z-z8yr14j7/pending-never-normalized.test.log": "4370a1f48eadbb51b2adf0dd64838f4c870252962ab16c74e77aad883fccbf04",+ "dist-seek-mutations/20261024T105811Z-z8yr14j7/message-commit-forgets-next-offset.build.log": "12f40c3a3ea7edc79a0cee00cfaaa8cb1ae60d98a13d3193ad63b1b25445db77",+ "dist-seek-mutations/20261024T105811Z-z8yr14j7/message-commit-forgets-next-offset.test.log": "d56732a3b894a8154ae131d024db6523a3059ecae31e15bc2237268e823c4864",+ "dist-seek-mutations/20261024T105811Z-z8yr14j7/rewind-decrements-committed-offset.build.log": "12f40c3a3ea7edc79a0cee00cfaaa8cb1ae60d98a13d3193ad63b1b25445db77",+ "dist-seek-mutations/20261024T105811Z-z8yr14j7/rewind-decrements-committed-offset.test.log": "4883b661b9edf946e312c760c55d4eb56a0466722efd59c64fe9890a97d100c0",+ "dist-seek-mutations/20261024T105811Z-z8yr14j7/rewind-discards-seek-error.build.log": "a987a77cfb0f3da8c4e120d84c73cc748b6be14347a917dc6d3d8d49534a73de",+ "dist-seek-mutations/20261024T105811Z-z8yr14j7/rewind-discards-seek-error.test.log": "e037412c061ae8a34ee1f0e4e0b004f1a4cc5a0eca7326271c79ee05045a45d1"+ },+ "owned_source_sha256": {+ "src/Kafka/Consumer.hs": "dea0ff7193ca4c10962fcf281a8985e654862de0f2e31a260bdd8d25d6152002",+ "src/Kafka/Consumer/Convert.hs": "d9e821da80314908c093f021a43c1603331db7538a324111f3da1c1f132a1a4c",+ "test-integration/Kafka/Integration/SeekPartitionsTest.hs": "681ac36e6934a0ccc84bbc2f956926e89e32b8a183dada2028002b3237a7cdea",+ "test-integration/Kafka/SeekTestSupport.hs": "5c19e85be0f3ec19a750c8d7ac1e87b955dca8948d8f216cab036175f34b89f8",+ "test-integration/cbits/seek_faults.c": "9aad50936a4bd1dcfb24b0a7b7b01eb50ce0d137ae79485db1ca599a6ffc9f4a",+ "scripts/test-seek-mutations.py": "5a08ea029b3ac4ba0175b3446377f0e49cf586538a6ad6245ad5203b35322ea7"+ }+}
+ docs/testing/topic-admin-evidence.json view
@@ -0,0 +1,295 @@+{+ "revision": "8396f7b60ae762068970eb7d802e1bb1f514c07e",+ "fingerprint": "603e828f9aca4c20cfe867950e50ed5c106ff74de7db07124e960db07890cd9a",+ "configuration": {+ "ghc": "9.12.4",+ "native": "(\"2.15.0\",34537727)",+ "broker": [+ {+ "node_id": 0,+ "version": "v26.2.1 - 8cd781be99c737c7d147d9dc239a0bbdd591a4d8"+ }+ ],+ "fixture": {+ "RDKAFKA_TEST_BROKER": "127.0.0.1:39092",+ "RDKAFKA_TEST_ADMIN": null,+ "RDKAFKA_TEST_RPK": null,+ "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY": null+ }+ },+ "normal": {+ "unit_tests": 21,+ "integration_tests": 244,+ "integration_seconds": 108.03+ },+ "instrumented": {+ "unit_tests": 21,+ "integration_tests": 244,+ "integration_seconds": 105.84+ },+ "focused_tests": [+ "rdkafka-hs-integration.topic-configuration.singleton configuration reaches the broker",+ "rdkafka-hs-integration.topic-configuration.native allocation control detects a retained request",+ "rdkafka-hs-integration.topic-configuration.setter rejection releases allocated request before submission",+ "rdkafka-hs-integration.topic-configuration.interruption after allocation releases request before submission",+ "rdkafka-hs-integration.topic-configuration.multiple configuration entries reach the broker",+ "rdkafka-hs-integration.topic-configuration.broker-rejected values release requests and response events repeatedly",+ "rdkafka-hs-integration.topic-configuration.unrepresentable partition count never wraps to broker defaults",+ "rdkafka-hs-integration.topic-configuration.NUL in a topic name never creates a truncated topic",+ "rdkafka-hs-integration.topic-configuration.unresponsive broker preserves the native timeout error",+ "rdkafka-hs-integration.topic-configuration.empty configuration creates a usable topic",+ "rdkafka-hs-integration.topic-configuration.later setter rejection releases partially configured request",+ "rdkafka-hs-integration.topic-configuration.duplicate creation preserves the existing topic",+ "rdkafka-hs-integration.topic-configuration.deletion removes exactly the existing topic",+ "rdkafka-hs-integration.topic-configuration.missing topic deletion preserves its error and releases the request",+ "rdkafka-hs-integration.topic-configuration.NUL deletion cannot remove a truncated victim name",+ "rdkafka-hs-integration.topic-configuration.broker default partition and replication counts remain supported",+ "rdkafka-hs-integration.topic-configuration.replication above the available broker count is rejected",+ "rdkafka-hs-integration.topic-configuration.unsupported configuration follows the declared broker policy",+ "rdkafka-hs-integration.topic-configuration.minimum unrepresentable partition count is rejected",+ "rdkafka-hs-integration.topic-configuration.maximum unrepresentable replication count is rejected",+ "rdkafka-hs-integration.topic-configuration.minimum unrepresentable replication count is rejected",+ "rdkafka-hs-integration.topic-configuration.NUL configuration key is rejected before native allocation",+ "rdkafka-hs-integration.topic-configuration.NUL configuration value is rejected before native allocation",+ "rdkafka-hs-integration.topic-configuration.negative invalid partition count retains native validation",+ "rdkafka-hs-integration.topic-configuration.maximum C partition count retains native validation",+ "rdkafka-hs-integration.topic-configuration.negative invalid replication count retains native validation",+ "rdkafka-hs-integration.topic-configuration.maximum C replication count retains native validation",+ "rdkafka-hs-integration.topic-configuration.empty topic name is rejected by the broker",+ "rdkafka-hs-integration.topic-configuration.space in a topic name is rejected by the broker",+ "rdkafka-hs-integration.topic-configuration.overlong topic name is rejected by the broker",+ "rdkafka-hs-integration.topic-configuration.zero partition count is rejected by the broker",+ "rdkafka-hs-integration.topic-configuration.zero replication count is rejected by the broker",+ "rdkafka-hs-integration.topic-configuration.wrong event type fails and releases its event",+ "rdkafka-hs-integration.topic-configuration.empty response fails and releases its event",+ "rdkafka-hs-integration.topic-configuration.wrong topic response cannot report success",+ "rdkafka-hs-integration.topic-configuration.missing polled event reports a timeout",+ "rdkafka-hs-integration.topic-configuration.delayed response succeeds with balanced ownership",+ "rdkafka-hs-integration.topic-configuration.consumer administration applies settings in async mode",+ "rdkafka-hs-integration.topic-configuration.consumer administration applies settings in sync mode",+ "rdkafka-hs-integration.topic-configuration.consumer administration applies settings in async-closed mode",+ "rdkafka-hs-integration.topic-configuration.consumer administration applies settings in sync-closed mode",+ "rdkafka-hs-integration.topic-configuration.concurrent requests keep their own queues and responses",+ "rdkafka-hs-integration.topic-configuration.unresponsive deletion preserves the native timeout error",+ "rdkafka-hs-integration.topic-configuration.deletion rejects a wrong event type and releases it",+ "rdkafka-hs-integration.topic-configuration.deletion rejects an empty result and releases its event",+ "rdkafka-hs-integration.topic-configuration.deletion rejects a mismatched topic result",+ "rdkafka-hs-integration.topic-configuration.deletion reports a missing response as a timeout",+ "rdkafka-hs-integration.topic-configuration.missing native timeout configuration returns an error",+ "rdkafka-hs-integration.topic-configuration.malformed native timeout configuration returns an error",+ "rdkafka-hs-integration.topic-configuration.zero native timeout configuration returns an error",+ "rdkafka-hs-integration.topic-configuration.negative native timeout configuration returns an error",+ "rdkafka-hs-integration.topic-configuration.overflowing native timeout configuration returns an error",+ "rdkafka-hs-integration.topic-configuration.oversized native timeout configuration never reads a truncated buffer"+ ],+ "tooling_controls": 18,+ "mutation_evidence": "dist-topic-mutations/20261024T083604Z-my8qigbc/results.json",+ "mutation_fingerprint": "3d85bfdffc9e562df964f231c47daf7e20f45f1939c0a4b36a0d40a5eab774ca",+ "mutation_archive_sha256": "29836531a3df40a8db9ba70f2d0ed699242a9cc2b563b7e1ec59dc08f725d6f0",+ "mutations": [+ {+ "mutation": "unchanged-control",+ "compiled": true,+ "exit": 0,+ "pattern": "/topic-configuration/",+ "expected_failure": null,+ "command": [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-topic-mutations/20261024T083604Z-my8qigbc/source/rdkafka-hs-1.0.0.1/dist-newstyle/build/aarch64-osx/ghc-9.12.4/rdkafka-hs-1.0.0.1/t/rdkafka-hs-integration/build/rdkafka-hs-integration/rdkafka-hs-integration",+ "-p",+ "/topic-configuration/",+ "+RTS",+ "-N2",+ "-A256m",+ "-RTS"+ ],+ "build_log": "dist-topic-mutations/20261024T083604Z-my8qigbc/unchanged-control.build.log",+ "test_log": "dist-topic-mutations/20261024T083604Z-my8qigbc/unchanged-control.test.log"+ },+ {+ "mutation": "configuration-removed",+ "compiled": true,+ "exit": 1,+ "pattern": "/singleton/",+ "expected_failure": "singleton configuration reaches the broker",+ "command": [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-topic-mutations/20261024T083604Z-my8qigbc/source/rdkafka-hs-1.0.0.1/dist-newstyle/build/aarch64-osx/ghc-9.12.4/rdkafka-hs-1.0.0.1/t/rdkafka-hs-integration/build/rdkafka-hs-integration/rdkafka-hs-integration",+ "-p",+ "/singleton/",+ "+RTS",+ "-N2",+ "-A256m",+ "-RTS"+ ],+ "build_log": "dist-topic-mutations/20261024T083604Z-my8qigbc/configuration-removed.build.log",+ "test_log": "dist-topic-mutations/20261024T083604Z-my8qigbc/configuration-removed.test.log"+ },+ {+ "mutation": "old-acquisition-lifetime",+ "compiled": true,+ "exit": 1,+ "pattern": "/setter rejection releases allocated/",+ "expected_failure": "setter rejection releases allocated request before submission",+ "command": [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-topic-mutations/20261024T083604Z-my8qigbc/source/rdkafka-hs-1.0.0.1/dist-newstyle/build/aarch64-osx/ghc-9.12.4/rdkafka-hs-1.0.0.1/t/rdkafka-hs-integration/build/rdkafka-hs-integration/rdkafka-hs-integration",+ "-p",+ "/setter rejection releases allocated/",+ "+RTS",+ "-N2",+ "-A256m",+ "-RTS"+ ],+ "build_log": "dist-topic-mutations/20261024T083604Z-my8qigbc/old-acquisition-lifetime.build.log",+ "test_log": "dist-topic-mutations/20261024T083604Z-my8qigbc/old-acquisition-lifetime.test.log"+ },+ {+ "mutation": "queue-finalization-removed",+ "compiled": true,+ "exit": 1,+ "pattern": "/setter rejection releases allocated/",+ "expected_failure": "setter rejection releases allocated request before submission",+ "command": [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-topic-mutations/20261024T083604Z-my8qigbc/source/rdkafka-hs-1.0.0.1/dist-newstyle/build/aarch64-osx/ghc-9.12.4/rdkafka-hs-1.0.0.1/t/rdkafka-hs-integration/build/rdkafka-hs-integration/rdkafka-hs-integration",+ "-p",+ "/setter rejection releases allocated/",+ "+RTS",+ "-N2",+ "-A256m",+ "-RTS"+ ],+ "build_log": "dist-topic-mutations/20261024T083604Z-my8qigbc/queue-finalization-removed.build.log",+ "test_log": "dist-topic-mutations/20261024T083604Z-my8qigbc/queue-finalization-removed.test.log"+ },+ {+ "mutation": "options-finalization-removed",+ "compiled": true,+ "exit": 1,+ "pattern": "/setter rejection releases allocated/",+ "expected_failure": "setter rejection releases allocated request before submission",+ "command": [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-topic-mutations/20261024T083604Z-my8qigbc/source/rdkafka-hs-1.0.0.1/dist-newstyle/build/aarch64-osx/ghc-9.12.4/rdkafka-hs-1.0.0.1/t/rdkafka-hs-integration/build/rdkafka-hs-integration/rdkafka-hs-integration",+ "-p",+ "/setter rejection releases allocated/",+ "+RTS",+ "-N2",+ "-A256m",+ "-RTS"+ ],+ "build_log": "dist-topic-mutations/20261024T083604Z-my8qigbc/options-finalization-removed.build.log",+ "test_log": "dist-topic-mutations/20261024T083604Z-my8qigbc/options-finalization-removed.test.log"+ },+ {+ "mutation": "delete-request-finalization-removed",+ "compiled": true,+ "exit": 1,+ "pattern": "/missing topic deletion/",+ "expected_failure": "missing topic deletion preserves its error and releases the request",+ "command": [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-topic-mutations/20261024T083604Z-my8qigbc/source/rdkafka-hs-1.0.0.1/dist-newstyle/build/aarch64-osx/ghc-9.12.4/rdkafka-hs-1.0.0.1/t/rdkafka-hs-integration/build/rdkafka-hs-integration/rdkafka-hs-integration",+ "-p",+ "/missing topic deletion/",+ "+RTS",+ "-N2",+ "-A256m",+ "-RTS"+ ],+ "build_log": "dist-topic-mutations/20261024T083604Z-my8qigbc/delete-request-finalization-removed.build.log",+ "test_log": "dist-topic-mutations/20261024T083604Z-my8qigbc/delete-request-finalization-removed.test.log"+ },+ {+ "mutation": "event-finalization-removed",+ "compiled": true,+ "exit": 1,+ "pattern": "/broker-rejected values/",+ "expected_failure": "broker-rejected values release requests and response events repeatedly",+ "command": [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-topic-mutations/20261024T083604Z-my8qigbc/source/rdkafka-hs-1.0.0.1/dist-newstyle/build/aarch64-osx/ghc-9.12.4/rdkafka-hs-1.0.0.1/t/rdkafka-hs-integration/build/rdkafka-hs-integration/rdkafka-hs-integration",+ "-p",+ "/broker-rejected values/",+ "+RTS",+ "-N2",+ "-A256m",+ "-RTS"+ ],+ "build_log": "dist-topic-mutations/20261024T083604Z-my8qigbc/event-finalization-removed.build.log",+ "test_log": "dist-topic-mutations/20261024T083604Z-my8qigbc/event-finalization-removed.test.log"+ },+ {+ "mutation": "native-request-error-ignored",+ "compiled": true,+ "exit": 1,+ "pattern": "/unresponsive broker preserves/",+ "expected_failure": "unresponsive broker preserves the native timeout error",+ "command": [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-topic-mutations/20261024T083604Z-my8qigbc/source/rdkafka-hs-1.0.0.1/dist-newstyle/build/aarch64-osx/ghc-9.12.4/rdkafka-hs-1.0.0.1/t/rdkafka-hs-integration/build/rdkafka-hs-integration/rdkafka-hs-integration",+ "-p",+ "/unresponsive broker preserves/",+ "+RTS",+ "-N2",+ "-A256m",+ "-RTS"+ ],+ "build_log": "dist-topic-mutations/20261024T083604Z-my8qigbc/native-request-error-ignored.build.log",+ "test_log": "dist-topic-mutations/20261024T083604Z-my8qigbc/native-request-error-ignored.test.log"+ },+ {+ "mutation": "topic-identity-ignored",+ "compiled": true,+ "exit": 1,+ "pattern": "/wrong topic response/",+ "expected_failure": "wrong topic response cannot report success",+ "command": [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-topic-mutations/20261024T083604Z-my8qigbc/source/rdkafka-hs-1.0.0.1/dist-newstyle/build/aarch64-osx/ghc-9.12.4/rdkafka-hs-1.0.0.1/t/rdkafka-hs-integration/build/rdkafka-hs-integration/rdkafka-hs-integration",+ "-p",+ "/wrong topic response/",+ "+RTS",+ "-N2",+ "-A256m",+ "-RTS"+ ],+ "build_log": "dist-topic-mutations/20261024T083604Z-my8qigbc/topic-identity-ignored.build.log",+ "test_log": "dist-topic-mutations/20261024T083604Z-my8qigbc/topic-identity-ignored.test.log"+ }+ ],+ "mutation_artifacts": {+ "dist-topic-mutations/20261024T083604Z-my8qigbc/results.json": "035a3732b8c898571e0294d9c2dc08f41f670ceadfb3f7bedd0ecab4c82e964c",+ "dist-topic-mutations/20261024T083604Z-my8qigbc/unchanged-control.build.log": "c40fb5a392b98b375cabd8d5e392ed91091bd0f9716f38dc094015cd57e8b270",+ "dist-topic-mutations/20261024T083604Z-my8qigbc/unchanged-control.test.log": "f0716eb56e0f752050a20d873798b0c58be55c5b24f6ac950c69190f0d248caa",+ "dist-topic-mutations/20261024T083604Z-my8qigbc/configuration-removed.build.log": "33e519297f326f6ac96768a5bf0cbf86e1ae6f570c8627349c115ad4a4548fdc",+ "dist-topic-mutations/20261024T083604Z-my8qigbc/configuration-removed.test.log": "f978708a010965bfde8c8ae37f2f6d05657b15700aa842619bb378474bb24e56",+ "dist-topic-mutations/20261024T083604Z-my8qigbc/old-acquisition-lifetime.build.log": "1baf94972fa975a5aafac81b15475eab29e789b5db13e864859a97f645a2644a",+ "dist-topic-mutations/20261024T083604Z-my8qigbc/old-acquisition-lifetime.test.log": "ed3c40a8468fc0c9b67c6763c0300babac80514e1cb4b422ce44a61df136f36f",+ "dist-topic-mutations/20261024T083604Z-my8qigbc/queue-finalization-removed.build.log": "07e278cb121802346b7a6989b27a489a1567c654e14a1a4243a4d711776352fb",+ "dist-topic-mutations/20261024T083604Z-my8qigbc/queue-finalization-removed.test.log": "f3273d52027f03ba00dadc90b47ae072ce47237f2e9645add235e7713e457c7f",+ "dist-topic-mutations/20261024T083604Z-my8qigbc/options-finalization-removed.build.log": "07e278cb121802346b7a6989b27a489a1567c654e14a1a4243a4d711776352fb",+ "dist-topic-mutations/20261024T083604Z-my8qigbc/options-finalization-removed.test.log": "5eb8150fa4fcf8a1ad4192c5d82f53192a6d9c3bb9369709a8e084a63d1ddd04",+ "dist-topic-mutations/20261024T083604Z-my8qigbc/delete-request-finalization-removed.build.log": "07e278cb121802346b7a6989b27a489a1567c654e14a1a4243a4d711776352fb",+ "dist-topic-mutations/20261024T083604Z-my8qigbc/delete-request-finalization-removed.test.log": "6ce08cdc4a03c6441964b8aecd09ff522150cf5125faccb189f136b3b502f3e3",+ "dist-topic-mutations/20261024T083604Z-my8qigbc/event-finalization-removed.build.log": "07e278cb121802346b7a6989b27a489a1567c654e14a1a4243a4d711776352fb",+ "dist-topic-mutations/20261024T083604Z-my8qigbc/event-finalization-removed.test.log": "3be341610e2b7dc7ba99bad65e760515951e360811da5f28f249170fe449acd5",+ "dist-topic-mutations/20261024T083604Z-my8qigbc/native-request-error-ignored.build.log": "07e278cb121802346b7a6989b27a489a1567c654e14a1a4243a4d711776352fb",+ "dist-topic-mutations/20261024T083604Z-my8qigbc/native-request-error-ignored.test.log": "80d069b6b2d46855549267578383f7010ed75c7aa4778963c9b8842c1c4c931a",+ "dist-topic-mutations/20261024T083604Z-my8qigbc/topic-identity-ignored.build.log": "07e278cb121802346b7a6989b27a489a1567c654e14a1a4243a4d711776352fb",+ "dist-topic-mutations/20261024T083604Z-my8qigbc/topic-identity-ignored.test.log": "e894adfac7f4a8ff0926d26c743959503a90c4c02c2f8444b99c3468c27c5937"+ },+ "known_cross_plan_failures": [+ {+ "fingerprint": "470be3ccad19c06c1822393486da4d3420681f99914cea3938b7f11d15b734a5",+ "accepted": false,+ "log": "dist-coverage/failures/ep8-sync-seek-state.log",+ "sha256": "2c45980cc04be4e3579487dd66c991d48769255ac109ae257ff61581abf0cc2b",+ "result": "Synchronous deprecated seek returned RdKafkaRespErrState; four dependent cases skipped. All 53 admin cases passed. Investigation remains open.",+ "owner": 14,+ "resolution": "Unresolved deprecated-seek failure remains open in API-Kafka-Consumer-seek; subsequent passing runs do not explain it."+ }+ ],+ "status": "EP-8 local admin behavior and scoped ownership accepted; broader native diagnostics and compatibility remain open under EP-15",+ "unchanged_mutation_subject_sources": {+ "src/Kafka/Topic.hs": "932bbd96cc0b28baf18843e4679acc0ea7f09fdefb74a3e4a3a28c9940b6a53c",+ "src/Kafka/Internal/RdKafka.chs": "a60896eedd0943c73d3962c5337a4223b8ab4c431e4a22e4a9cd59fbfa0afad0",+ "test-integration/Kafka/AdminTestSupport.hs": "446cceaf01c8684ef19ce8afa062ca9f4c71d9100e64f846bc63b9987ffc15fe",+ "test-integration/Kafka/Integration/TopicConfigurationTest.hs": "cb5d3b4b660bb813a69ce073e225879a008eb51e37a59b892af6c5d84c28c5ab",+ "test-integration/Kafka/FaultTestSupport.hs": "a30011b3c337602b0ee1b9f5a32b12369e26988fb25b6953ea83c2f3f20137b0",+ "test-integration/cbits/admin_ownership.c": "f515c199ba09cecca282da2dd5a4177864c788114c91be3d96551a57bd4987f5"+ },+ "mutation_scope": "The accepted topic mutation archive retains identical admin implementation and fault/counter sources; current full suites rerun its 53 admin cases after independent producer/property changes."+}
+ docs/testing/transaction-evidence.json view
@@ -0,0 +1,93 @@+{+ "status": "accepted",+ "fingerprint": "b578bd424b68a7f6dda5b028cc9b8c2574cc4367dde558fe70e1c675e0330ead",+ "revision": "5a80c66d7dcccc74062e14f146d18d32b33587ff",+ "normal": {+ "log": "/tmp/rdkafka-ep12-normal-final.log",+ "unit": 29,+ "integration": 426,+ "integration_seconds": 162.15+ },+ "instrumented": {+ "manifest": "docs/testing/coverage-evidence.json",+ "unit": 29,+ "integration": 426,+ "integration_seconds": 165.96+ },+ "focused": {+ "cases": 51,+ "log": "/tmp/rdkafka-ep12-focused2.log",+ "seconds": 12.08+ },+ "native_errors": {+ "repeated_immediate_calls": 300,+ "created": 300,+ "destroyed": 300,+ "control_sequence": "One repaired begin establishes the live producer, then the C control repeats the inherited init/begin/abort decode-without-destroy sequence on that producer.",+ "control_created": 4,+ "control_destroyed_before_cleanup": 1,+ "control_outstanding": 3,+ "control_cleanup": "The fixture destroys retained native objects after the assertions."+ },+ "mutations": "dist-mutations/20261024T141053Z-transaction-39758-0/results.json",+ "mutations_caught": 10,+ "unchanged_controls": 1,+ "native_diagnostics": "docs/testing/transaction-native-diagnostics.json",+ "required_checks": "/tmp/rdkafka-ep12-check.log",+ "package_check": "/tmp/rdkafka-ep12-cabalcheck.log",+ "tooling_controls": 19,+ "tests": [+ "rdkafka-hs-integration.transaction-errors.transaction-error-leak-probe releases 300 immediate native errors",+ "rdkafka-hs-integration.transaction-errors.native allocation control detects the inherited three-error leak",+ "rdkafka-hs-integration.transaction-errors.initialization timeout destroys its native error on each retry",+ "rdkafka-hs-integration.transaction-errors.zero-timeout initialization resumes successfully against the broker",+ "rdkafka-hs-integration.transaction-errors.transaction state errors preserve empty commit and abort recovery",+ "rdkafka-hs-integration.transaction-errors.duplicate transactional IDs report a real fatal fencing error",+ "rdkafka-hs-integration.transaction-errors.broker-rejected delivery requires abort and permits a successful new transaction",+ "rdkafka-hs-integration.transaction-errors.init without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.begin without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.abort without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.commit without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.offset without transactional ID preserves native code and destroys error",+ "rdkafka-hs-integration.transaction-errors.init NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.begin NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.abort NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.commit NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.offset NULL return remains success",+ "rdkafka-hs-integration.transaction-errors.init invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.begin invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.abort invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.commit invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.offset invalid native code still destroys acquired error",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 0 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 1 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 2 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 3 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 4 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 5 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 6 before destruction",+ "rdkafka-hs-integration.transaction-errors.commit copies native flag combination 7 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 0 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 1 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 2 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 3 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 4 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 5 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 6 before destruction",+ "rdkafka-hs-integration.transaction-errors.offset copies native flag combination 7 before destruction",+ "rdkafka-hs-integration.transaction-errors.init cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.begin cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.abort cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 21 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 22 releases once",+ "rdkafka-hs-integration.transaction-errors.commit cancellation at decoder stage 23 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 20 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 21 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 22 releases once",+ "rdkafka-hs-integration.transaction-errors.offset cancellation at decoder stage 23 releases once",+ "rdkafka-hs-integration.transaction-errors.async commit publishes output and source next offset atomically; abort publishes neither",+ "rdkafka-hs-integration.transaction-errors.sync commit publishes output and source next offset atomically; abort publishes neither"+ ],+ "remaining": "EP-15 owns compatibility tuples and wider network/auth/native heap evidence. No EP-12 contract row remains open."+}
+ docs/testing/transaction-native-diagnostics.json view
@@ -0,0 +1,27 @@+{+ "status": "accepted",+ "fingerprint": "b578bd424b68a7f6dda5b028cc9b8c2574cc4367dde558fe70e1c675e0330ead",+ "source_project": "mori://confluentinc/librdkafka",+ "native": "v2.15.0",+ "compiler_runtime_and_negative_control": "docs/testing/callback-native-diagnostics.json",+ "scope": "51 transaction cases; the actual native allocation/destruction counter detects the three-error leaking control and balances 300 repeated immediate errors. Native invalid-access instrumentation complements those counters; leak instrumentation and other tuples remain EP-15.",+ "command": [+ "/Users/shinzui/Keikaku/bokuno/rdkafka-hs/dist-newstyle/build/aarch64-osx/ghc-9.12.4/rdkafka-hs-1.0.0.1/t/rdkafka-hs-integration/build/rdkafka-hs-integration/rdkafka-hs-integration",+ "-p",+ "/transaction-errors/",+ "+RTS",+ "-N2",+ "-RTS"+ ],+ "environment": {+ "DYLD_LIBRARY_PATH": "/tmp/rdkafka-hs-ep11-asan-install/lib",+ "DYLD_INSERT_LIBRARIES": "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/21/lib/darwin/libclang_rt.asan_osx_dynamic.dylib",+ "ASAN_OPTIONS": "detect_leaks=0:abort_on_error=1:symbolize=1",+ "DYLD_PRINT_LIBRARIES": "1"+ },+ "exit": 0,+ "log": "/tmp/rdkafka-ep12-asan.log",+ "log_sha256": "e51ec1a6df39793170ff144696df6866b124121d4d9c667605e75041be259647",+ "native_library_sha256": "2fa8b4e5d5e623550305022c6dc881674ccf0c0fb43183e532c27d9faaa6e51f",+ "binary_sha256": "3e2d518a9046eebe98bf63c412f9406beded3cd12a986551dfaa929df74216f1"+}
+ example/ConsumerExample.hs view
@@ -0,0 +1,79 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}++module ConsumerExample+ ( consumerProps,+ consumerSub,+ runConsumerExample,+ runConsumerExampleWith,+ processMessages,+ printingRebalanceCallback,+ printingOffsetCallback,+ )+where++import Control.Arrow ((&&&))+import Control.Exception (bracket)+import Kafka.Consumer++-- Global consumer properties+consumerProps :: ConsumerProperties+consumerProps =+ brokersList ["localhost:9092"]+ <> groupId "consumer_example_group"+ <> noAutoCommit+ <> setCallback (rebalanceCallback printingRebalanceCallback)+ <> setCallback (offsetCommitCallback printingOffsetCallback)+ <> logLevel KafkaLogInfo++-- Subscription to topics+consumerSub :: Subscription+consumerSub =+ topics ["kafka-client-example-topic"]+ <> offsetReset Earliest++-- Running an example+runConsumerExample :: IO ()+runConsumerExample = runConsumerExampleWith consumerProps consumerSub++-- | Override configuration for a run-owned broker, topic and group.+runConsumerExampleWith :: ConsumerProperties -> Subscription -> IO ()+runConsumerExampleWith props subscription = do+ print $ cpLogLevel props+ res <- bracket mkConsumer clConsumer runHandler+ print res+ where+ mkConsumer = newConsumer props subscription+ clConsumer (Left err) = return (Left err)+ clConsumer (Right kc) = maybe (Right ()) Left <$> closeConsumer kc+ runHandler (Left err) = return (Left err)+ runHandler (Right kc) = processMessages kc++-------------------------------------------------------------------+processMessages :: KafkaConsumer -> IO (Either KafkaError ())+processMessages kafka = do+ mapM_+ ( \_ -> do+ msg1 <- pollMessage kafka (Timeout 1000)+ putStrLn $ "Message: " <> show msg1+ err <- commitAllOffsets OffsetCommit kafka+ putStrLn $ "Offsets: " <> maybe "Committed." show err+ )+ [0 :: Integer .. 10]+ return $ Right ()++printingRebalanceCallback :: KafkaConsumer -> RebalanceEvent -> IO ()+printingRebalanceCallback _ e = case e of+ RebalanceBeforeAssign ps ->+ putStrLn $ "[Rebalance] About to assign partitions: " <> show ps+ RebalanceAssign ps ->+ putStrLn $ "[Rebalance] Assign partitions: " <> show ps+ RebalanceBeforeRevoke ps ->+ putStrLn $ "[Rebalance] About to revoke partitions: " <> show ps+ RebalanceRevoke ps ->+ putStrLn $ "[Rebalance] Revoke partitions: " <> show ps++printingOffsetCallback :: KafkaConsumer -> KafkaError -> [TopicPartition] -> IO ()+printingOffsetCallback _ e ps = do+ print ("Offsets callback:" ++ show e)+ mapM_ (print . (tpTopicName &&& tpPartition &&& tpOffset)) ps
+ example/Main.hs view
@@ -0,0 +1,28 @@+module Main (main) where++import ConsumerExample+import Data.Text qualified as Text+import Kafka.Consumer qualified as C+import Kafka.Producer qualified as P+import ProducerExample+import System.Environment (getArgs)+import System.Exit (die)++main :: IO ()+main = do+ args <- getArgs+ case args of+ [] -> run runProducerExample runConsumerExample+ [broker, topic, group] ->+ run+ (runProducerExampleWith (producerProps <> P.brokersList [P.BrokerAddress (Text.pack broker)]) (P.TopicName (Text.pack topic)))+ (runConsumerExampleWith (consumerProps <> C.brokersList [C.BrokerAddress (Text.pack broker)] <> C.groupId (C.ConsumerGroupId (Text.pack group))) (C.topics [C.TopicName (Text.pack topic)] <> C.offsetReset C.Earliest))+ _ -> die "Usage: kafka-client-example [BROKER TOPIC GROUP]"+ where+ run :: IO () -> IO () -> IO ()+ run producer consumer = do+ putStrLn "Running producer example..."+ producer+ putStrLn "Running consumer example..."+ consumer+ putStrLn "Ok."
+ example/ProducerExample.hs view
@@ -0,0 +1,119 @@+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}++module ProducerExample+ ( producerProps,+ targetTopic,+ mkMessage,+ runProducerExample,+ runProducerExampleWith,+ sendMessages,+ sendMessageSync,+ )+where++import Control.Concurrent.MVar (newEmptyMVar, putMVar, takeMVar)+import Control.Exception (bracket)+import Control.Monad (forM_)+import Control.Monad.IO.Class (MonadIO (..))+import Data.ByteString (ByteString)+import Data.ByteString.Char8 (pack)+import Kafka.Consumer (Offset)+import Kafka.Producer++-- Global producer properties+producerProps :: ProducerProperties+producerProps =+ brokersList ["localhost:9092"]+ <> sendTimeout (Timeout 10000)+ <> setCallback (deliveryCallback print)+ <> logLevel KafkaLogDebug++-- Topic to send messages to+targetTopic :: TopicName+targetTopic = "kafka-client-example-topic"++mkMessage :: Maybe ByteString -> Maybe ByteString -> ProducerRecord+mkMessage k v =+ ProducerRecord+ { prTopic = targetTopic,+ prPartition = UnassignedPartition,+ prKey = k,+ prValue = v,+ prHeaders = mempty+ }++-- Run an example+runProducerExample :: IO ()+runProducerExample = runProducerExampleWith producerProps targetTopic++-- | Use an isolated broker/topic while retaining the interactive example.+runProducerExampleWith :: ProducerProperties -> TopicName -> IO ()+runProducerExampleWith props topic =+ bracket mkProducer clProducer runHandler >>= print+ where+ mkProducer = newProducer props+ clProducer (Left _) = return ()+ clProducer (Right prod) = closeProducer prod+ runHandler (Left err) = return $ Left err+ runHandler (Right prod) = sendMessagesTo topic prod++sendMessages :: KafkaProducer -> IO (Either KafkaError ())+sendMessages = sendMessagesTo targetTopic++sendMessagesTo :: TopicName -> KafkaProducer -> IO (Either KafkaError ())+sendMessagesTo topic prod = do+ putStrLn "Producer is ready, send your messages!"+ msg1 <- getLine++ err1 <- produceMessage prod (mkMessageFor (Just "zero") (Just $ pack msg1))+ forM_ err1 print++ putStrLn "One more time!"+ msg2 <- getLine++ err2 <- produceMessage prod (mkMessageFor (Just "key") (Just $ pack msg2))+ forM_ err2 print++ putStrLn "And the last one..."+ msg3 <- getLine+ err3 <- produceMessage prod (mkMessageFor (Just "key3") (Just $ pack msg3))+ forM_ err3 print++ err4 <- produceMessage prod ((mkMessageFor (Just "key4") (Just $ pack msg3)) {prHeaders = headersFromList [("fancy", "header")]})+ forM_ err4 print++ putStrLn "Thank you."+ return $ Right ()+ where+ mkMessageFor k v = (mkMessage k v) {prTopic = topic}++-- | An example for sending messages synchronously using the 'produceMessage''+-- function+sendMessageSync ::+ (MonadIO m) =>+ KafkaProducer ->+ ProducerRecord ->+ m (Either KafkaError Offset)+sendMessageSync producer record = liftIO $ do+ -- Create an empty MVar:+ var <- newEmptyMVar++ -- Produce the message and use the callback to put the delivery report in the+ -- MVar:+ res <- produceMessage' producer record (putMVar var)++ case res of+ Left (ImmediateError err) ->+ pure (Left err)+ Right () -> do+ -- Flush producer queue to make sure you don't get stuck waiting for the+ -- message to send:+ flushProducer producer++ -- Wait for the message's delivery report and map accordingly:+ takeMVar var+ >>= return . \case+ DeliverySuccess _ offset -> Right offset+ DeliveryFailure _ err -> Left err+ NoMessageError err -> Left err
+ rdkafka-hs.cabal view
@@ -0,0 +1,268 @@+cabal-version: 3.0+name: rdkafka-hs+version: 1.1.0.0+synopsis: Kafka bindings for Haskell backed by librdkafka+description:+ Apache Kafka bindings backed by the librdkafka C library.++ rdkafka-hs is the maintained successor of hw-kafka-client and keeps+ its Kafka.* module namespace.++ Features include:++ * Consumer groups: auto-rebalancing consumers++ * Keyed and keyless messages producing/consuming++ * Batch producing messages++category: Database+homepage: https://github.com/shinzui/rdkafka-hs+bug-reports: https://github.com/shinzui/rdkafka-hs/issues+author: Alexey Raga <alexey.raga@gmail.com>+maintainer: Nadeem Bitar <nadeem@gmail.com>+license: MIT+license-file: LICENSE+tested-with: ghc ==9.12.4+build-type: Simple+extra-doc-files:+ CHANGELOG.md+ README.md++extra-source-files:+ docs/testing/*.json+ docs/testing/*.md+ scripts/*.hs+ scripts/*.py+ scripts/*.sh++source-repository head+ type: git+ location: https://github.com/shinzui/rdkafka-hs.git++flag examples+ description: Also compile examples+ manual: True+ default: False++flag integration+ description: Build the integration tests (they need a Kafka broker)+ manual: True+ default: False++common common-options+ ghc-options:+ -Wall+ -Wcompat+ -Widentities+ -Wincomplete-uni-patterns+ -Wincomplete-record-updates+ -Wredundant-constraints+ -fhide-source-paths+ -Wmissing-export-lists+ -Wpartial-fields+ -Wmissing-deriving-strategies++ default-language: GHC2024+ default-extensions:+ DeriveAnyClass+ DuplicateRecordFields+ OverloadedLabels+ OverloadedStrings++library+ import: common-options+ hs-source-dirs: src+ extra-libraries: rdkafka+ build-depends:+ base >=4.21 && <5,+ bifunctors >=5.6 && <5.7,+ bytestring >=0.12 && <0.13,+ containers >=0.7 && <0.9,+ text >=2.1 && <2.2,+ transformers >=0.6 && <0.7,+ unix >=2.8 && <2.9,++ build-tool-depends: c2hs:c2hs+ exposed-modules:+ Kafka.Consumer+ Kafka.Consumer.ConsumerProperties+ Kafka.Consumer.Subscription+ Kafka.Consumer.Types+ Kafka.Dump+ Kafka.Metadata+ Kafka.Producer+ Kafka.Producer.ProducerProperties+ Kafka.Producer.Types+ Kafka.Topic+ Kafka.Topic.Types+ Kafka.Transaction+ Kafka.Types+ Kafka.Version++ other-modules:+ Kafka.Callbacks+ Kafka.Consumer.Callbacks+ Kafka.Consumer.Convert+ Kafka.Internal.CallbackOwner+ Kafka.Internal.RdKafka+ Kafka.Internal.Setup+ Kafka.Internal.Shared+ Kafka.Producer.Callbacks+ Kafka.Producer.Convert++executable kafka-client-example+ import: common-options+ main-is: Main.hs+ hs-source-dirs: example+ ghc-options:+ -threaded+ -rtsopts++ build-depends:+ base >=4.21 && <5,+ bytestring,+ rdkafka-hs,+ text,++ if !flag(examples)+ buildable: False+ other-modules:+ ConsumerExample+ ProducerExample++test-suite rdkafka-hs-integration+ import: common-options+ type: exitcode-stdio-1.0+ main-is: Main.hs+ hs-source-dirs:+ test-integration+ test-support++ c-sources:+ test-integration/cbits/admin_ownership.c+ test-integration/cbits/callback_lifetime.c+ test-integration/cbits/consumer_state.c+ test-integration/cbits/diagnostics.c+ test-integration/cbits/message_ownership.c+ test-integration/cbits/metadata.c+ test-integration/cbits/partition_lists.c+ test-integration/cbits/producer_ownership.c+ test-integration/cbits/seek_faults.c+ test-integration/cbits/transaction_ownership.c++ if os(linux)+ extra-libraries: dl+ ghc-options:+ -threaded+ -rtsopts+ -with-rtsopts=-N++ build-depends:+ base >=4.21 && <5,+ bytestring,+ containers,+ directory,+ network,+ process,+ random,+ rdkafka-hs,+ tasty ^>=1.5,+ tasty-hunit ^>=0.10,+ tasty-quickcheck ^>=0.11.1,+ text,+ unix,++ if !flag(integration)+ buildable: False+ other-modules:+ Kafka.AdminTestSupport+ Kafka.CallbackLifetimeSupport+ Kafka.CallbackTestSupport+ Kafka.Compatibility.KafkaFixture+ Kafka.Compatibility.SecurityFixture+ Kafka.ConsumerStateSupport+ Kafka.DiagnosticTestSupport+ Kafka.FaultTestSupport+ Kafka.FixtureSupport+ Kafka.FixtureSupportTest+ Kafka.Integration.AssignOnlyTest+ Kafka.Integration.AttributedErrorTest+ Kafka.Integration.AuthenticationTest+ Kafka.Integration.BatchTest+ Kafka.Integration.BrokerFailureTest+ Kafka.Integration.CallbackLifetimeTest+ Kafka.Integration.ConfigStringContractTest+ Kafka.Integration.ConfigurationTest+ Kafka.Integration.ConsumerCommitContractTest+ Kafka.Integration.ConsumerPropertyTest+ Kafka.Integration.ConsumerStateContractTest+ Kafka.Integration.ConsumerTest+ Kafka.Integration.DeprecatedRunnerContractTest+ Kafka.Integration.DestroyTest+ Kafka.Integration.DiagnosticContractTest+ Kafka.Integration.FatalErrorTest+ Kafka.Integration.HeadersTest+ Kafka.Integration.InputBoundaryContractTest+ Kafka.Integration.LifecycleTest+ Kafka.Integration.MetadataContractTest+ Kafka.Integration.ObserverTest+ Kafka.Integration.PartitionListContractTest+ Kafka.Integration.PerMessageCommitTest+ Kafka.Integration.ProducerPropertyTest+ Kafka.Integration.ProducerRegressionTest+ Kafka.Integration.PublicConsumerContractTest+ Kafka.Integration.QueueEventTest+ Kafka.Integration.ReadCommittedTest+ Kafka.Integration.RuntimeContractTest+ Kafka.Integration.SeekPartitionsTest+ Kafka.Integration.StoreOffsetsTest+ Kafka.Integration.TopicConfigurationTest+ Kafka.Integration.TopicTest+ Kafka.Integration.TransactionErrorTest+ Kafka.MessageTestSupport+ Kafka.MetadataTestSupport+ Kafka.ProducerTestSupport+ Kafka.PropertySupport+ Kafka.SeekTestSupport+ Kafka.TestEnv+ Kafka.TransactionTestSupport++test-suite rdkafka-hs-test+ import: common-options+ c-sources: test/cbits/error_constants.c+ default-extensions: PackageImports+ type: exitcode-stdio-1.0+ main-is: Main.hs+ hs-source-dirs:+ test+ test-support+ src++ ghc-options:+ -threaded+ -rtsopts+ -with-rtsopts=-N++ build-depends:+ base >=4.21 && <5,+ bifunctors,+ bytestring,+ containers,+ rdkafka-hs,+ tasty ^>=1.5,+ tasty-hunit ^>=0.10,+ tasty-quickcheck ^>=0.11.1,+ text,++ other-modules:+ Kafka.Consumer.ConsumerPropertiesSpec+ Kafka.Consumer.ConsumerRecordMapSpec+ Kafka.Consumer.ConsumerRecordTraverseSpec+ Kafka.Internal.CallbackOwner+ Kafka.Internal.CallbackOwnerSpec+ Kafka.Producer.ProducerPropertiesSpec+ Kafka.PropertySupport+ Kafka.PublicDataContractSpec+ Kafka.PublicPropertiesSpec+ Kafka.VersionTest
+ scripts/binding-inventory.sh view
@@ -0,0 +1,226 @@+#!/bin/sh+# Regenerate docs/bindings.md: every function librdkafka's public header+# exports, grouped by the header's own @name sections, marked bound or unbound+# by src/Kafka/Internal/RdKafka.chs.+#+# Usage: scripts/binding-inventory.sh [OUTPUT] (default: docs/bindings.md)+#+# RDKAFKA_SOURCE_HEADER must name src/rdkafka.h in a librdkafka release+# checkout outside /nix/store whose version matches the library pkg-config+# finds; `just librdkafka-source` prepares one. The script exits non-zero when+# the module binds a function the header does not export.+set -eu++out=${1:-docs/bindings.md}+module=src/Kafka/Internal/RdKafka.chs++die() {+ echo "binding-inventory: $*" >&2+ exit 1+}++[ -n "${RDKAFKA_SOURCE_HEADER:-}" ] ||+ die "set RDKAFKA_SOURCE_HEADER to src/rdkafka.h of a librdkafka release checkout (see 'just librdkafka-source')"+header=$(realpath "$RDKAFKA_SOURCE_HEADER") || die "cannot resolve $RDKAFKA_SOURCE_HEADER"+case "$header" in+ /nix/store/*) die "refusing to read a header in /nix/store; use a release checkout" ;;+esac+[ -f "$header" ] || die "$header is not a file"+[ -f "$module" ] || die "run from the repository root ($module not found)"++linked=$(pkg-config --modversion rdkafka) || die "pkg-config cannot find rdkafka"+hexversion=$(awk '$1 == "#define" && $2 == "RD_KAFKA_VERSION" { print $3; exit }' "$header")+[ -n "$hexversion" ] || die "$header does not define RD_KAFKA_VERSION"+headerversion=$(printf '%d.%d.%d' \+ $((hexversion >> 24 & 255)) $((hexversion >> 16 & 255)) $((hexversion >> 8 & 255)))+[ "$headerversion" = "$linked" ] ||+ die "header is librdkafka $headerversion but pkg-config finds $linked"++if command -v sha256sum >/dev/null 2>&1; then+ digest=$(sha256sum "$header" | cut -d ' ' -f 1)+else+ digest=$(shasum -a 256 "$header" | cut -d ' ' -f 1)+fi++tmp=$(mktemp -d)+trap 'rm -rf "$tmp"' EXIT++# Exported functions as "group<TAB>name", in header order. Group headings are+# read from comments before comments are stripped; declarations are joined+# across lines up to their first parenthesis.+awk '+ BEGIN { group = "Before the first group"; incomment = 0; collecting = 0 }+ {+ line = $0+ if (match(line, /@name[ \t]+/)) {+ heading = substr(line, RSTART + RLENGTH)+ sub(/[ \t]*(\*\/)?[ \t]*$/, "", heading)+ group = heading+ }+ code = ""+ while (length(line) > 0) {+ if (incomment) {+ i = index(line, "*/")+ if (i == 0) line = ""+ else { line = substr(line, i + 2); incomment = 0 }+ } else {+ i = index(line, "/*"); j = index(line, "//")+ if (j > 0 && (i == 0 || j < i)) { code = code substr(line, 1, j - 1); line = "" }+ else if (i == 0) { code = code line; line = "" }+ else { code = code substr(line, 1, i - 1); line = substr(line, i + 2); incomment = 1 }+ }+ }+ if (code ~ /^[ \t]*#/) next+ if (!collecting && code ~ /(^|[^A-Za-z0-9_])RD_EXPORT([^A-Za-z0-9_]|$)/) {+ collecting = 1; decl = ""; declgroup = group+ }+ if (collecting) {+ decl = decl " " code+ p = index(decl, "(")+ if (p > 0) {+ before = substr(decl, 1, p - 1)+ if (match(before, /[A-Za-z_][A-Za-z0-9_]*[ \t]*$/)) {+ name = substr(before, RSTART, RLENGTH)+ gsub(/[ \t]/, "", name)+ if (name ~ /^rd_kafka_/ && !(name in seen)) {+ seen[name] = 1+ print declgroup "\t" name+ }+ }+ collecting = 0+ } else if (index(decl, ";") > 0) {+ collecting = 0+ }+ }+ }+' "$header" >"$tmp/exports"++# Bindings as "name<TAB>haskell name<TAB>kind".+awk '+ function camel(s, n, parts, i, r) {+ n = split(s, parts, "_")+ r = parts[1]+ for (i = 2; i <= n; i++)+ r = r toupper(substr(parts[i], 1, 1)) substr(parts[i], 2)+ return r+ }+ pending != "" && NF > 0 {+ hs = $1+ sub(/::.*/, "", hs)+ print pending "\t" hs "\t" pendingkind+ pending = ""+ }+ {+ line = $0+ while (match(line, /\{#[ \t]*fun[ \t]+((pure|unsafe|safe)[ \t]+)*rd_kafka_[A-Za-z0-9_]+([ \t]+as[ \t]+[^ \t{]+)?/)) {+ d = substr(line, RSTART, RLENGTH)+ line = substr(line, RSTART + RLENGTH)+ match(d, /rd_kafka_[A-Za-z0-9_]+/)+ name = substr(d, RSTART, RLENGTH)+ hs = name+ if (match(d, /[ \t]as[ \t]+[^ \t{]+$/)) {+ hs = substr(d, RSTART, RLENGTH)+ sub(/^[ \t]as[ \t]+/, "", hs)+ if (hs == "^") hs = camel(name)+ }+ print name "\t" hs "\tc2hs fun"+ }+ line = $0+ while (match(line, /\{#[ \t]*call[ \t]+((pure|unsafe|safe)[ \t]+)*rd_kafka_[A-Za-z0-9_]+/)) {+ d = substr(line, RSTART, RLENGTH)+ line = substr(line, RSTART + RLENGTH)+ match(d, /rd_kafka_[A-Za-z0-9_]+/)+ print substr(d, RSTART, RLENGTH) "\t\tc2hs call"+ }+ if ($0 ~ /^[ \t]*foreign[ \t]+import[ \t]/ && match($0, /"[^"]*rd_kafka_[A-Za-z0-9_]+"/)) {+ s = substr($0, RSTART, RLENGTH)+ kind = (s ~ /&rd_kafka_/) ? "finalizer pointer" : "foreign import"+ match(s, /rd_kafka_[A-Za-z0-9_]+/)+ pending = substr(s, RSTART, RLENGTH)+ pendingkind = kind+ rest = $0+ sub(/^.*"[ \t]*/, "", rest)+ if (rest ~ /::/) {+ sub(/[ \t]*::.*/, "", rest)+ print pending "\t" rest "\t" pendingkind+ pending = ""+ }+ }+ }+' "$module" >"$tmp/bound"++awk -F '\t' -v version="$linked" -v digest="$digest" -v module="$module" '+ FNR == NR {+ label = ($2 == "") ? "inline `{#call}`" : "`" $2 "`"+ if ($3 == "finalizer pointer") label = label " (finalizer pointer)"+ else if ($3 == "foreign import") label = label " (foreign import)"+ if (!(($1, label) in boundpair)) {+ boundpair[$1, label] = 1+ bound[$1] = ($1 in bound) ? bound[$1] ", " label : label+ }+ next+ }+ {+ if (!($1 in groupseen)) { groupseen[$1] = 1; groups[++ngroups] = $1 }+ members[$1] = members[$1] "\n" $2+ exported[$2] = 1+ total+++ if ($2 in bound) nbound+++ }+ END {+ print "# librdkafka binding inventory"+ print ""+ print "Generated by `scripts/binding-inventory.sh` from librdkafka'"'"'s public header and"+ print "`" module "`. Do not edit by hand: run `just bindings-inventory` after"+ print "changing the binding module, and `just bindings-check` to verify."+ print ""+ print "- librdkafka: " version+ print "- Header: `src/rdkafka.h`, sha256 `" digest "`"+ print "- Exported functions: " total+ print "- Bound: " nbound + 0+ print "- Unbound: " total - nbound+ for (g = 1; g <= ngroups; g++) {+ name = groups[g]+ n = split(substr(members[name], 2), fns, "\n")+ nb = 0+ for (i = 1; i <= n; i++) if (fns[i] in bound) nb+++ print ""+ print "## " name+ print ""+ print nb " of " n " bound."+ if (nb > 0) {+ print ""+ print "| C function | Haskell binding |"+ print "| --- | --- |"+ for (i = 1; i <= n; i++)+ if (fns[i] in bound) print "| `" fns[i] "` | " bound[fns[i]] " |"+ }+ if (nb < n) {+ print ""+ print "<details><summary>Unbound (" n - nb ")</summary>"+ print ""+ for (i = 1; i <= n; i++)+ if (!(fns[i] in bound)) print "- `" fns[i] "`"+ print ""+ print "</details>"+ }+ }+ nstale = 0+ for (f in bound) if (!(f in exported)) stale[++nstale] = f+ if (nstale > 0) {+ print ""+ print "## Bound but not exported by the header"+ print ""+ for (i = 1; i <= nstale; i++) print "- `" stale[i] "`: " bound[stale[i]]+ exit 3+ }+ }+' "$tmp/bound" "$tmp/exports" >"$tmp/out" || status=$?++mkdir -p "$(dirname "$out")"+cp "$tmp/out" "$out"+if [ "${status:-0}" -eq 3 ]; then+ die "the binding module binds functions the header does not export; see $out"+elif [ "${status:-0}" -ne 0 ]; then+ die "inventory generation failed"+fi
+ scripts/check-coverage.py view
@@ -0,0 +1,149 @@+#!/usr/bin/env python3+"""Fail closed on unassigned exports, missing tests and stale evidence."""++import argparse+import hashlib+import json+import sys+from pathlib import Path+from coverage_common import ROOT, compiler_exports, fingerprint, qualification_context_errors++# Original repair owners remain valid; the expanded qualification plans own+# transferred obligations. EP-20 consumes evidence rather than producing it.+OWNERS = frozenset(range(8, 20))+++def validate(matrix, exports, evidence, allow_open):+ errors = []+ if matrix.get("schema_version") != 1:+ errors.append("unsupported matrix schema")+ if matrix.get("exports") != exports:+ errors.append("public exports changed: reconcile compiler-derived exports and contract rows")+ symbols = {e["symbol"] for entries in exports.values() for e in entries}+ assigned = set()+ ids = set()+ registered = set() if evidence is None else set(evidence["tests"])+ for row in matrix.get("contracts", []):+ rid = row.get("id", "<missing ID>")+ if rid in ids:+ errors.append(f"duplicate row {rid}")+ ids.add(rid)+ for key in ("symbols", "behavior", "inputs", "expected", "modes", "ownership", "owner", "tests", "status"):+ if key not in row or (key not in ("symbols", "tests") and not row[key]):+ errors.append(f"{rid}: missing {key}")+ if row.get("owner") not in OWNERS:+ errors.append(f"{rid}: invalid child owner")+ if "previous_owner" in row and (row["previous_owner"] not in range(8, 16) or row.get("owner") not in range(16, 20)):+ errors.append(f"{rid}: invalid ownership transfer")+ for symbol in row.get("symbols", []):+ if symbol not in symbols:+ errors.append(f"{rid}: unknown symbol {symbol}")+ assigned.add(symbol)+ status = row.get("status")+ if status not in ("unimplemented", "tested", "not-applicable"):+ errors.append(f"{rid}: invalid status")+ if status == "unimplemented" and not allow_open:+ errors.append(f"{rid}: open (EP-{row.get('owner')})")+ if status == "not-applicable" and not row.get("rationale"):+ errors.append(f"{rid}: missing source-backed non-applicability rationale")+ tests = row.get("tests", [])+ if status == "tested":+ if not tests or not evidence:+ errors.append(f"{rid}: no test evidence")+ if row.get("fingerprint") != fingerprint():+ errors.append(f"{rid}: stale source evidence")+ for test in tests:+ if test not in registered:+ errors.append(f"{rid}: unregistered test {test}")+ for symbol in sorted(symbols - assigned):+ errors.append(f"unassigned public symbol {symbol}")+ for required in ("F1", "F2", "F3", "F4", "F5", "F6"):+ if required not in ids:+ errors.append(f"missing defect row {required}")+ if evidence is None:+ errors.append("missing measured evidence: run just coverage")+ else:+ if evidence.get("fingerprint") != fingerprint():+ errors.append("measured evidence is stale: run just coverage")+ if set(evidence.get("suites", [])) != {"rdkafka-hs-test", "rdkafka-hs-integration"}:+ errors.append("coverage requires both suites")+ artifacts = evidence.get("artifacts", {})+ if not isinstance(artifacts, dict) or not artifacts:+ errors.append("missing artifact checksums")+ artifacts = {}+ for artifact, checksum in artifacts.items():+ path = ROOT / artifact+ if not path.is_file():+ errors.append(f"missing coverage artifact {artifact}")+ elif hashlib.sha256(path.read_bytes()).hexdigest() != checksum:+ errors.append(f"modified coverage artifact {artifact}")+ if evidence.get("measured_native_wrapper_ticks", 0) <= 0:+ errors.append("missing hand-written .chs coverage")+ if not evidence.get("tests"):+ errors.append("empty registered-test evidence")+ runtime_tests = {name for name in registered if ".runtime-contract." in name}+ runtime = [run for run in evidence.get("supplemental_runs", []) if run.get("kind") == "nonthreaded-runtime"]+ if len(runtime) != 1 or not runtime_tests:+ errors.append("missing nonthreaded runtime coverage")+ else:+ supplement = runtime[0]+ way = supplement.get("rts_way")+ if not isinstance(way, str) or "thr" in way:+ errors.append("runtime supplement is not nonthreaded")+ if set(supplement.get("tests", [])) != runtime_tests or supplement.get("passed") != len(runtime_tests):+ errors.append("runtime supplement does not cover every registered runtime contract")+ if supplement.get("tix") not in artifacts:+ errors.append("missing runtime coverage artifact")+ contexts = evidence.get("qualification_contexts", [])+ modes = set()+ for context in contexts:+ errors.extend(qualification_context_errors(context, fingerprint()))+ if context.get("mode") in modes:+ errors.append("duplicate qualification context")+ modes.add(context.get("mode"))+ if not set(context.get("tests", [])) <= registered:+ errors.append("qualification context tests are not registered in evidence")+ if any(artifacts.get(name) != checksum for name, checksum in context.get("artifacts", {}).items()):+ errors.append("qualification artifacts are absent from aggregate evidence")+ exceptions = matrix.get("miss_classifications", {})+ for miss in evidence.get("misses", []):+ if miss.get("owner") not in OWNERS:+ errors.append(f"unclassified coverage miss: {miss}")+ if miss.get("contract") not in ids:+ errors.append(f"coverage miss has no contract row: {miss}")+ if not miss.get("generated"):+ key = f"{miss['module']}:{miss['line']}:{miss['label']}"+ classification = exceptions.get(key, {})+ if classification:+ source = ROOT / miss.get("source", "")+ if (classification.get("source") != miss.get("source") or not source.is_file()+ or classification.get("source_sha256") != hashlib.sha256(source.read_bytes()).hexdigest()):+ errors.append(f"stale source classification: {key}")+ if not allow_open and (classification.get("status") not in ("unreachable", "inapplicable") or not classification.get("rationale")):+ errors.append(f"unexplained hand-written coverage miss: {key} (EP-{miss.get('owner')})")+ return errors+++def main():+ parser = argparse.ArgumentParser(description=__doc__)+ parser.add_argument("--allow-open", action="store_true")+ parser.add_argument("--builddir", default="dist-newstyle")+ parser.add_argument("--evidence", default="dist-coverage/evidence.json")+ args = parser.parse_args()+ try:+ matrix = json.loads((ROOT / "docs/testing/coverage-matrix.json").read_text())+ evidence_path = ROOT / args.evidence+ evidence = json.loads(evidence_path.read_text()) if evidence_path.exists() else None+ errors = validate(matrix, compiler_exports(args.builddir), evidence, args.allow_open)+ except (ValueError, KeyError, OSError) as err:+ errors = [str(err)]+ for error in errors:+ print(error, file=sys.stderr)+ if errors:+ return 1+ print(f"Coverage inventory valid ({len(matrix['contracts'])} rows, allow_open={args.allow_open})")+ return 0+++if __name__ == "__main__":+ sys.exit(main())
+ scripts/collect-coverage.py view
@@ -0,0 +1,274 @@+#!/usr/bin/env python3+"""Run both suites on one instrumented candidate and retain source maps."""++import argparse+import hashlib+import json+import os+import re+import subprocess+import sys+import urllib.request+from datetime import datetime, timezone+from pathlib import Path+from coverage_common import compiler_generated_declaration, library_hpc_includes, ROOT, components, fingerprint, qualification_context_errors, run++SUITES = ("rdkafka-hs-test", "rdkafka-hs-integration")+BUILD = "dist-coverage"+OUTPUT = ROOT / BUILD / "reports"+++def digest(path):+ return hashlib.sha256(path.read_bytes()).hexdigest()+++def runtime_coverage():+ build = BUILD + "-nonthreaded"+ build_log = OUTPUT / "nonthreaded-build.log"+ command = ["cabal", "build", "rdkafka-hs-integration", "-f", "integration", "--enable-coverage", "--builddir=" + build,+ "--ghc-options=-fforce-recomp -F -pgmF scripts/coverage-preprocess.py -single-threaded -with-rtsopts=-T"]+ with build_log.open("w") as stream:+ subprocess.run(command, cwd=ROOT, stdout=stream, stderr=subprocess.STDOUT, check=True)+ component = components(build)["test:rdkafka-hs-integration"]+ binary = component / "build/rdkafka-hs-integration/rdkafka-hs-integration"+ info = subprocess.check_output([str(binary), "+RTS", "--info"], cwd=ROOT, text=True)+ way = re.search(r'\("RTS way", "([^"]+)"\)', info)+ if way is None or "thr" in way[1]:+ raise ValueError("runtime supplement did not link a nonthreaded executable")+ info_log = OUTPUT / "nonthreaded-rts.txt"+ info_log.write_text(info)+ tix = OUTPUT / "nonthreaded-runtime.tix"+ tix.unlink(missing_ok=True)+ environment = dict(os.environ, HPCTIXFILE=str(tix))+ options = ["-p", "/runtime-contract/", "+RTS", "--read-tix-file=no", "-RTS"]+ names = subprocess.check_output([str(binary), "--list-tests", *options], cwd=ROOT, text=True,+ env=dict(environment, HPCTIXFILE=str(OUTPUT / "nonthreaded-list.tix"))).splitlines()+ log = OUTPUT / "nonthreaded-runtime.log"+ with log.open("w") as stream:+ subprocess.run([str(binary), *options], cwd=ROOT, stdout=stream, stderr=subprocess.STDOUT, check=True, env=environment)+ counts = re.findall(r"All (\d+) tests passed", log.read_text())+ if not names or counts != [str(len(names))] or not tix.is_file():+ raise ValueError("missing complete nonthreaded runtime test coverage")+ # The alternative RTS branch is in Consumer.hs. Generated c2hs output has+ # different MIX hashes between these builds, so never combine its indices+ # across builds. Retain the full raw artifact, and let hpc verify that the+ # ordinary Consumer module is identical when it is merged below.+ consumer_tix = OUTPUT / "nonthreaded-consumer.tix"+ mixfiles = (components(BUILD)["lib"] / "build").rglob("Kafka.Consumer.mix")+ includes = library_hpc_includes([path for path in mixfiles if "vanilla" in path.parts])+ if len(includes) != 1:+ raise ValueError("missing unambiguous Consumer library MIX")+ run("hpc", "sum", "--union", *includes, "--output=" + str(consumer_tix), str(tix))+ evidence = dict(kind="nonthreaded-runtime", rts_way=way[1], tests=names, passed=len(names),+ command=[str(binary), *options], build_command=command, merged_modules=["Kafka.Consumer"],+ raw_tix=str(tix.relative_to(ROOT)), tix=str(consumer_tix.relative_to(ROOT)))+ return evidence, [build_log, info_log, log, tix, consumer_tix]+++def collect(context_paths=()):+ OUTPUT.mkdir(parents=True, exist_ok=True)+ before = fingerprint()+ command = ["cabal", "test", *SUITES, "-f", "integration", "--enable-coverage", "--builddir=" + BUILD,+ "--ghc-options=-fforce-recomp -F -pgmF scripts/coverage-preprocess.py", "--test-show-details=direct",+ "--test-options=--quickcheck-tests=1000 --quickcheck-replay=20261024"]+ # A previous run must never contribute ticks. Only this build directory is+ # touched; retain the old logs while replacing its machine evidence.+ for tix in (ROOT / BUILD).rglob("*.tix"):+ tix.unlink()+ child_directory = ROOT / BUILD / "children"+ child_directory.mkdir(exist_ok=True)+ log = OUTPUT / "test.log"+ with log.open("w") as stream:+ subprocess.run(command, cwd=ROOT, stdout=stream, stderr=subprocess.STDOUT, check=True,+ env=dict(os.environ, RDKAFKA_TEST_CHILD_HPC_DIR=str(child_directory)))+ runtime, runtime_artifacts = runtime_coverage()+ if fingerprint() != before:+ raise ValueError("candidate changed during coverage execution; discard this run")+ cs = components(BUILD)+ library = cs["lib"] / "build"+ mixfiles = sorted(p for p in library.rglob("*.mix") if "vanilla" in p.parts)+ mixdirs = sorted({p.parent.parent for p in mixfiles})+ if not mixdirs:+ raise ValueError("missing library MIX data")+ modules = sorted({p.stem for directory in mixdirs for p in directory.rglob("*.mix")})+ expected_modules = sorted(str(p.relative_to(ROOT / "src")).rsplit(".", 1)[0].replace("/", ".")+ for p in (ROOT / "src").rglob("*") if p.suffix in (".hs", ".chs"))+ if modules != expected_modules:+ raise ValueError("library MIX module set does not match hand-written sources")+ # Unit tests compile the internal owner in isolation. Select the library+ # package explicitly so its test-local copy cannot inflate library coverage.+ include = library_hpc_includes(mixfiles)+ mixargs = ["--hpcdir=" + str(d) for d in mixdirs]+ zeros = OUTPUT / "unlinked-zero.tix"+ zero_args = [arg for p in mixfiles for arg in (p.parent.name + "/" + p.stem, str(p))]+ run("runghc", "-package=hpc", "scripts/coverage-zero.hs", str(zeros), *zero_args)+ tixfiles = []+ tests = []+ artifacts = [log, zeros, *runtime_artifacts]+ children = sorted(child_directory.glob("*.tix"))+ for mode in ("global", "message"):+ if len(list(child_directory.glob("producer-" + mode + "-*.tix"))) != 1:+ raise ValueError("missing or ambiguous successful producer callback child coverage: " + mode)+ for kind in ("error", "log", "stats", "rebalance", "commit"):+ for mode in ("async", "sync"):+ if len(list(child_directory.glob("lifetime-" + kind + "-" + mode + "-*.tix"))) != 1:+ raise ValueError("missing or ambiguous callback lifetime child coverage: " + kind + "/" + mode)+ artifacts.extend(children)+ for kind in ("metadata", "groups"):+ if len(list(child_directory.glob("metadata-" + kind + "-*.tix"))) != 1:+ raise ValueError("missing or ambiguous metadata cancellation child coverage: " + kind)+ for protocol in ("cooperative", "eager"):+ for operation in ("assign", "revoke"):+ for mode in ("async", "sync"):+ for failure in (("native", "decode") if protocol == "cooperative" else ("native",)):+ prefix = "rebalance-" + protocol + "-" + operation + "-" + mode + "-" + failure+ if len(list(child_directory.glob(prefix + "-*.tix"))) != 1:+ raise ValueError("missing or ambiguous rebalance error child coverage: " + prefix)+ for suite in SUITES:+ matches = list(cs["test:" + suite].rglob(suite + ".tix"))+ if len(matches) != 1 or not matches[0].stat().st_size:+ raise ValueError(f"missing or ambiguous TIX data for {suite}")+ expanded = OUTPUT / (suite + ".tix")+ child_tix = [*map(str, children), runtime["tix"]] if suite == "rdkafka-hs-integration" else []+ run("hpc", "sum", "--union", *include, "--output=" + str(expanded), str(matches[0]), str(zeros), *child_tix)+ tixfiles.append(expanded)+ artifacts.append(expanded)+ binary = cs["test:" + suite] / "build" / suite / suite+ probe_env = dict(os.environ, HPCTIXFILE=str(OUTPUT / (suite + "-probe.tix")))+ names = subprocess.check_output([str(binary), "--list-tests", "+RTS", "--read-tix-file=no", "-RTS"], cwd=ROOT, env=probe_env, text=True).splitlines()+ root = "rdkafka-hs" if suite == "rdkafka-hs-test" else suite+ if not names or any(not n.startswith(root + ".") for n in names):+ raise ValueError(f"unexpected test list for {suite}")+ tests.extend(names)+ report = OUTPUT / (suite + ".txt")+ report.write_text(run("hpc", "report", *mixargs, *include, "--per-module", "--decl-list", str(expanded)))+ artifacts.extend([matches[0], report])+ counts = [int(n) for n in re.findall(r"All (\d+) tests passed", log.read_text())]+ if len(counts) != 2 or sum(counts) != len(tests):+ raise ValueError("suite pass counts do not match the complete registered test list")+ if set(runtime["tests"]) != {name for name in tests if ".runtime-contract." in name}:+ raise ValueError("nonthreaded runtime coverage does not match the registered runtime contracts")+ combined = OUTPUT / "combined.tix"+ run("hpc", "sum", "--union", *include, "--output=" + str(combined), *map(str, tixfiles))+ artifacts.append(combined)+ for name, options in (("combined.txt", ["--per-module", "--decl-list"]), ("combined.xml", ["--xml-output", "--per-module"])):+ path = OUTPUT / name+ path.write_text(run("hpc", "report", *mixargs, *options, str(combined)))+ artifacts.append(path)+ ticks = run("hpc", "show", *mixargs, str(combined))+ (OUTPUT / "ticks.txt").write_text(ticks)+ artifacts.append(OUTPUT / "ticks.txt")+ mapping_path = library / "Kafka/Internal/RdKafka.hs.coverage-map.json"+ mapping = json.loads(mapping_path.read_text())+ artifacts.append(mapping_path)+ matrix = json.loads((ROOT / "docs/testing/coverage-matrix.json").read_text())+ symbol_rows = {s: r for r in matrix["contracts"] for s in r["symbols"]}+ misses = []+ native_ticks = 0+ module_ticks = {module: 0 for module in modules}+ classified_metrics = {"handwritten": {}, "generated": {}}+ unused_functions = []+ source_lines = {}+ for line in ticks.splitlines():+ match = re.fullmatch(r'\s*(\d+)\s+(\d+)\s+[^ ]+/(Kafka[\w.]+)\s+(\d+):([\d:-]+)\s+(.+)', line)+ if not match:+ raise ValueError("unrecognised HPC tick/source format: " + line)+ index, hits, module, source_line, _, label = match.groups()+ module_ticks[module] += 1+ source_line = int(source_line)+ source = "src/" + module.replace(".", "/") + ".hs"+ generated = False+ if module == "Kafka.Internal.RdKafka":+ if source_line < 1 or source_line > len(mapping) or mapping[source_line - 1] is None:+ raise ValueError("unmapped native binding tick")+ origin = mapping[source_line - 1]+ generated = origin["generated"]+ source, source_line = origin["file"], origin["line"]+ if not source or not (ROOT / source).is_file():+ raise ValueError("missing source for HPC tick")+ if not generated:+ if source not in source_lines:+ source_lines[source] = (ROOT / source).read_text().splitlines()+ lines = source_lines[source]+ if not 1 <= source_line <= len(lines):+ raise ValueError("coverage tick has no source line")+ generated = compiler_generated_declaration(lines[source_line - 1])+ if module == "Kafka.Internal.RdKafka" and not generated:+ native_ticks += 1+ kind = label.split(" [", 1)[0]+ category = "generated" if generated else "handwritten"+ metric = classified_metrics[category].setdefault(kind, {"ticks": 0, "hit": 0})+ metric["ticks"] += 1+ metric["hit"] += int(int(hits) > 0)+ if int(hits) == 0 and label.startswith("TopLevelBox") and not generated:+ unused_functions.append(dict(module=module, source=source, line=source_line, label=label))+ if int(hits) == 0:+ declaration = re.search(r'TopLevelBox \["([^"]+)"', label)+ symbol = module + "." + declaration[1] if declaration else None+ row = symbol_rows.get(symbol)+ if row is None and module == "Kafka.Internal.CallbackOwner":+ row = next(r for r in matrix["contracts"] if r["id"] == "F5")+ fallback = "OWN-binding-coverage" if module == "Kafka.Internal.RdKafka" else "OWN-source-coverage"+ if row is None:+ row = next(r for r in matrix["contracts"] if r["id"] == fallback)+ misses.append(dict(module=module, source=source, line=source_line, tick=int(index), label=label,+ generated=generated, contract=row["id"], owner=row["owner"]))+ if native_ticks == 0:+ raise ValueError("HPC did not measure hand-written .chs wrappers; refuse inflated report")+ for module in modules:+ path = ROOT / "src" / (module.replace(".", "/") + ".hs")+ if path.exists() and re.search(r"^[a-z][\w']*\s*::", path.read_text(), re.M) and module_ticks[module] == 0:+ raise ValueError("HPC omitted hand-written functions in " + module)+ for name, data in (("classified-metrics.json", classified_metrics), ("unexercised-functions.json", unused_functions)):+ path = OUTPUT / name+ path.write_text(json.dumps(data, indent=2) + "\n")+ artifacts.append(path)+ misses_path = OUTPUT / "misses.json"+ misses_path.write_text(json.dumps(misses, indent=2) + "\n")+ artifacts.append(misses_path)+ native_binary = cs["test:rdkafka-hs-test"] / "build/rdkafka-hs-test/rdkafka-hs-test"+ loaded_native = subprocess.check_output([str(native_binary), "--native-version", "+RTS", "--read-tix-file=no", "-RTS"], cwd=ROOT,+ env=dict(os.environ, HPCTIXFILE=str(OUTPUT / "native-probe.tix")), text=True).strip()+ admin = os.getenv("RDKAFKA_TEST_ADMIN", "http://127.0.0.1:39644")+ with urllib.request.urlopen(admin + "/v1/brokers", timeout=5) as response:+ broker_versions = [{"node_id": b["node_id"], "version": b["version"]} for b in json.load(response)]+ if not broker_versions:+ raise ValueError("missing actual broker version")+ contexts = []+ primary_tests = list(tests)+ binary = cs["test:rdkafka-hs-integration"] / "build/rdkafka-hs-integration/rdkafka-hs-integration"+ for context_path in context_paths:+ context_path = context_path.resolve()+ context = json.loads(context_path.read_text())+ mode = context.get("mode")+ if mode not in ("--broker-qualification", "--authentication-qualification"):+ raise ValueError("unsupported qualification mode")+ names = subprocess.check_output([str(binary), mode, "--list-tests", "+RTS", "--read-tix-file=no", "-RTS"],+ cwd=ROOT, text=True, env=dict(os.environ, HPCTIXFILE=str(OUTPUT / "context-list.tix"))).splitlines()+ errors = qualification_context_errors(context, before, names)+ if errors or any(c["mode"] == mode for c in contexts) or set(names) & set(tests):+ raise ValueError("invalid qualification supplement: " + "; ".join(errors or ["duplicate context/test registration"]))+ contexts.append(context)+ tests.extend(names)+ artifacts.extend([context_path, *(ROOT / name for name in context["artifacts"])])+ evidence = dict(test_configuration={key: os.getenv(key) for key in ("RDKAFKA_TEST_BROKER", "RDKAFKA_TEST_ADMIN", "RDKAFKA_TEST_RPK", "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY")}, schema_version=1, revision=run("git", "rev-parse", "HEAD").strip(), fingerprint=before,+ at=datetime.now(timezone.utc).isoformat(), command=command, suites=list(SUITES), tests=tests,+ passed_test_count=sum(counts) + sum(c["passed"] for c in contexts), primary_passed_test_count=sum(counts), primary_tests=primary_tests, qualification_contexts=contexts, supplemental_runs=[runtime], toolchain=run("ghc", "--numeric-version").strip(), cabal=run("cabal", "--numeric-version").strip(),+ loaded_native=loaded_native, broker_versions=broker_versions, native=run("pkg-config", "--modversion", "rdkafka").strip(),+ broker=os.getenv("RDKAFKA_TEST_BROKER", "127.0.0.1:39092"),+ misses=misses, module_tick_counts=module_ticks, measured_native_wrapper_ticks=native_ticks,+ artifacts={str(p.relative_to(ROOT)): digest(p) for p in artifacts})+ if fingerprint() != before:+ raise ValueError("candidate changed during report generation")+ (ROOT / BUILD / "evidence.json").write_text(json.dumps(evidence, indent=2) + "\n")+ print(f"Coverage evidence: {BUILD}/evidence.json; {len(tests)} registered tests; {native_ticks} native-wrapper ticks")+++if __name__ == "__main__":+ try:+ parser = argparse.ArgumentParser(description=__doc__)+ parser.add_argument("--context", action="append", type=Path, default=[], help="source-bound external broker/security behavioral evidence; adds no HPC ticks")+ collect(parser.parse_args().context)+ except (ValueError, OSError, subprocess.CalledProcessError) as error:+ print(f"Coverage collection failed: {error}; see {OUTPUT}/test.log", file=sys.stderr)+ sys.exit(1)
+ scripts/coverage-preprocess.py view
@@ -0,0 +1,78 @@+#!/usr/bin/env python3+"""GHC -F adapter: retain c2hs code but make its spans measurable by HPC.++GHC 9.12 ignores ticks whose LINE filename differs from the module's .hs+filename. Replace only c2hs LINE pragmas with blank lines, retaining physical+coordinates and a sidecar mapping back to the .chs source. Ordinary .hs inputs+retain their original source filename and contents. The adapter never changes production build inputs.+"""++import json+import re+import sys+from pathlib import Path+++def transform(original, text):+ if '"src/Kafka/Internal/RdKafka.chs"' not in text:+ return '{-# LINE 1 ' + json.dumps(original) + ' #-}\n' + text, None+ source = Path("src/Kafka/Internal/RdKafka.chs").read_text().splitlines()+ generated = set()+ directive = False+ for number, line in enumerate(source, 1):+ if re.match(r"^\s*\{#\s*(?:fun|enum|pointer|typedef)\b", line):+ directive = True+ if directive:+ generated.add(number)+ if "#}" in line:+ directive = False+ result = []+ mapping = []+ origin = None+ line_number = 0+ just_reset = False+ for physical, line in enumerate(text.splitlines(keepends=True), 1):+ match = re.fullmatch(r'{-# LINE (\d+) "([^"]+)" #-}\s*', line)+ if match:+ line_number = int(match[1])+ origin = match[2]+ just_reset = True+ result.append("\n")+ mapping.append(None)+ else:+ result.append(line)+ is_generated = origin != "src/Kafka/Internal/RdKafka.chs" or line_number in generated+ mapping.append({"file": origin, "line": line_number, "generated": is_generated})+ if not is_generated:+ line_number += 1+ elif just_reset and 1 <= line_number <= len(source) and "#}" in source[line_number - 1] and not line.strip():+ # c2hs resets to the closing hook line, emitting its suffix+ # (usually blank) before continuing verbatim hand-written code.+ line_number += 1+ just_reset = False+ # Every explicitly typed hand-written declaration must map back to its+ # exact declaration line. This catches mapping drift around inline hooks.+ signatures = {match[1]: i for i, line in enumerate(source, 1)+ if (match := re.match(r"^([a-zA-Z_][\w']*)\s*::", line))}+ for physical, line in enumerate(text.splitlines(), 1):+ match = re.match(r"^([a-zA-Z_][\w']*)\s*::", line)+ if match and match[1] in signatures:+ entry = mapping[physical - 1]+ if entry is None or entry["generated"] or entry["line"] != signatures[match[1]]:+ raise ValueError("unmapped hand-written declaration: " + match[1])+ # GHC supplies the original source location before invoking -F. State it+ # explicitly because c2hs's first LINE is removed from the input.+ prefix = '{-# LINE 1 ' + json.dumps(original) + ' #-}\n'+ return prefix + "".join(result), mapping+++def main():+ original, input_name, output_name = sys.argv[-3:]+ text, mapping = transform(original, Path(input_name).read_text())+ Path(output_name).write_text(text)+ if mapping is not None:+ Path(original + ".coverage-map.json").write_text(json.dumps(mapping))+++if __name__ == "__main__":+ main()
+ scripts/coverage-zero.hs view
@@ -0,0 +1,22 @@+-- Include unlinked library modules as explicit zero-count coverage. The MIX+-- file supplies the exact instrumentation hash and tick count; never invent+-- counts or mark an unlinked module as inapplicable.+module Main (main) where++import System.Environment (getArgs)+import Trace.Hpc.Mix (Mix (..))+import Trace.Hpc.Tix (Tix (..), TixModule (..), writeTix)++main :: IO ()+main = do+ args <- getArgs+ case args of+ output : inputs -> mapM zero (pairs inputs) >>= writeTix output . Tix+ _ -> fail "usage: coverage-zero.hs OUTPUT NAME MIX [NAME MIX ...]"+ where+ pairs [] = []+ pairs (name : path : rest) = (name, path) : pairs rest+ pairs _ = error "coverage-zero: unmatched name/path"+ zero (name, path) = do+ Mix _ _ hash _ entries <- read <$> readFile path+ pure (TixModule name hash (length entries) (replicate (length entries) 0))
+ scripts/coverage_common.py view
@@ -0,0 +1,124 @@+"""Candidate identity and compiler-derived public exports for coverage tools."""++import hashlib+import json+import re+import subprocess+from pathlib import Path++ROOT = Path(__file__).resolve().parent.parent+++def run(*args):+ return subprocess.check_output(args, cwd=ROOT, text=True)+++def library_hpc_includes(mixfiles):+ return ["--include=" + p.parent.name + ":" + p.stem for p in mixfiles]+++def compiler_generated_declaration(line):+ """Ticks on deriving declarations come from GHC, not handwritten methods."""+ if not re.match(r"^\s*deriving\b", line):+ return False+ if ";" in line:+ raise ValueError("mixed deriving/code line requires explicit coverage classification")+ return True+++def fingerprint():+ # Evidence-only documentation is deliberately excluded. Include untracked+ # test/source additions; git diff alone cannot identify a dirty candidate.+ files = set()+ for directory in ("src", "test", "test-integration", "test-support", "scripts", "nix"):+ files.update(p for p in (ROOT / directory).rglob("*") if p.is_file() and "__pycache__" not in p.parts)+ files.update(ROOT / name for name in ("rdkafka-hs.cabal", "cabal.project", "cabal.project.local", "cabal.project.freeze", ".envrc", ".envrc.local", "flake.nix", "flake.lock", "flake.module.nix", "justfile"))+ digest = hashlib.sha256()+ for path in sorted(files):+ if path.exists():+ digest.update(str(path.relative_to(ROOT)).encode() + b"\0" + path.read_bytes() + b"\0")+ return digest.hexdigest()+++def exposed_modules():+ cabal = (ROOT / "rdkafka-hs.cabal").read_text()+ # Scope deliberately limited to this package's flat exposed-modules stanza.+ # Reject unrecognised syntax instead of silently losing conditional exports.+ sections = re.findall(r"^ exposed-modules:\s*\n((?: [^\n]+\n)+)", cabal, re.M)+ if len(sections) != 1:+ raise ValueError("expected exactly one flat exposed-modules stanza")+ modules = sections[0].split()+ if not all(re.fullmatch(r"[A-Z][\w]*(?:\.[A-Z][\w]*)*", m) for m in modules):+ raise ValueError("unsupported exposed-modules syntax")+ return modules+++def components(builddir):+ plan = json.loads((ROOT / builddir / "cache/plan.json").read_text())+ return {c["component-name"]: Path(c["dist-dir"]) for c in plan["install-plan"] if c.get("pkg-name") == "rdkafka-hs"}+++def compiler_exports(builddir):+ library = components(builddir)["lib"] / "build"+ result = {}+ for module in exposed_modules():+ interface = library / (module.replace(".", "/") + ".hi")+ # GHC resolves multiline exports, module re-exports, constructors,+ # record selectors and opaque types. This parser consumes its explicit+ # export section, never a source-code approximation of Haskell exports.+ output = run("ghc", "--show-iface", str(interface))+ match = re.search(r"^exports:\n((?: [^\n]+\n)+)", output, re.M)+ if not match:+ raise ValueError(f"missing compiler exports: {module}")+ entries = []+ for line in match[1].splitlines():+ names = re.findall(r"[A-Za-z_][A-Za-z_0-9'.]*", line)+ if not names:+ raise ValueError(f"unsupported export syntax: {line}")+ names = [name if "." in name else module + "." + name for name in names]+ entries.append({"symbol": names[0], "members": sorted(set(names[1:]))})+ result[module] = sorted(entries, key=lambda x: x["symbol"])+ return result+++QUALIFICATION_MODES = frozenset(("--broker-qualification", "--authentication-qualification"))+++def qualification_context_errors(context, candidate, registered=None):+ """Supplement behavioral registration only; never manufacture HPC ticks."""+ errors = []+ if context.get("kind") != "qualification-context" or context.get("mode") not in QUALIFICATION_MODES:+ errors.append("unsupported qualification context")+ if context.get("fingerprint") != candidate:+ errors.append("stale qualification context")+ names = context.get("tests", [])+ if not isinstance(names, list) or not names or len(names) != len(set(names)):+ errors.append("empty or duplicate qualification tests")+ elif registered is not None and set(names) != set(registered):+ errors.append("qualification context differs from current registered tests")+ if context.get("passed") != len(names):+ errors.append("incomplete qualification context")+ if not context.get("environment") or not context.get("source") or context.get("mode") not in context.get("command", []):+ errors.append("missing qualification source/environment/command")+ artifacts = context.get("artifacts", {})+ if not isinstance(artifacts, dict) or not artifacts:+ errors.append("missing qualification artifacts")+ artifacts = {}+ for name, checksum in artifacts.items():+ path = ROOT / name+ if not path.is_file() or hashlib.sha256(path.read_bytes()).hexdigest() != checksum:+ errors.append("missing or modified qualification artifact: " + name)+ for field in ("listing", "log"):+ name = context.get(field)+ if name not in artifacts:+ errors.append("missing qualification " + field)+ continue+ path = ROOT / name+ if not path.is_file():+ continue+ content = path.read_text()+ if field == "listing" and content.splitlines() != names:+ errors.append("qualification listing differs from recorded tests")+ if field == "log" and (re.findall(r"All (\d+) tests passed", content) != [str(len(names))] or re.search(r": FAIL(?:\s|$)", content)):+ errors.append("qualification log does not prove every test passed")+ return errors
+ scripts/test-coverage-tools.py view
@@ -0,0 +1,282 @@+import copy+import hashlib+import re+import importlib.util+import json+import sys+import subprocess+import tempfile+import unittest+from pathlib import Path+from unittest.mock import patch++ROOT = Path(__file__).resolve().parent+# Install into scripts/test-coverage-tools.py before use.+sys.path.insert(0, str(ROOT))+import coverage_common as common+++def load(name, file):+ spec = importlib.util.spec_from_file_location(name, ROOT / file)+ module = importlib.util.module_from_spec(spec)+ spec.loader.exec_module(module)+ return module+++checker = load("checker", "check-coverage.py")+preprocessor = load("preprocessor", "coverage-preprocess.py")+++class GateControls(unittest.TestCase):+ def test_only_compiler_deriving_declarations_are_generated(self):+ for line in (" deriving stock (Eq, Show)", "deriving newtype (Num)", "deriving stock instance Eq Native"):+ self.assertTrue(common.compiler_generated_declaration(line))+ for line in ("instance Show Native where", "show native = nativeName native", " nativeField :: Int", "-- deriving is mentioned in this comment"):+ self.assertFalse(common.compiler_generated_declaration(line))+ with self.assertRaisesRegex(ValueError, "mixed deriving/code"):+ common.compiler_generated_declaration("deriving stock Eq; manual = undefined")++ def test_shared_property_source_changes_candidate_identity(self):+ with tempfile.TemporaryDirectory(prefix="rdkafka-shared-source-control-") as directory:+ root = Path(directory)+ support = root / "test-support" / "Kafka"+ support.mkdir(parents=True)+ source = support / "PropertySupport.hs"+ source.write_text("module Kafka.PropertySupport where\nvalue = 1\n")+ with patch.object(common, "ROOT", root):+ first = common.fingerprint()+ source.write_text("module Kafka.PropertySupport where\nvalue = 2\n")+ self.assertNotEqual(common.fingerprint(), first)++ def test_test_local_module_cannot_inflate_library_ticks(self):+ with tempfile.TemporaryDirectory(prefix="rdkafka-package-coverage-control-") as directory:+ root = Path(directory)+ source, output = root / "source.tix", root / "library.tix"+ source.write_text('Tix [TixModule "library/Kafka.Sample" 1 1 [0],TixModule "main/Kafka.Sample" 2 1 [99]]\n')+ includes = common.library_hpc_includes([root / "library" / "Kafka.Sample.mix"])+ subprocess.run(["hpc", "sum", "--union", *includes, "--output=" + str(output), str(source)], check=True)+ measured = output.read_text()+ self.assertIn('"library/Kafka.Sample"', measured)+ self.assertIn('[0]', measured)+ self.assertNotIn('"main/Kafka.Sample"', measured)+ self.assertNotIn('[99]', measured)++ def setUp(self):+ self.matrix = json.loads((checker.ROOT / "docs/testing/coverage-matrix.json").read_text())+ self.exports = self.matrix["exports"]+ # These are schema/gate controls, independent of live candidate rows.+ # A real accepted row may legitimately be stale during implementation.+ for row in self.matrix["contracts"]:+ row["status"] = "unimplemented"+ row["tests"] = []+ row.pop("fingerprint", None)+ self.evidence = dict(fingerprint="candidate", tests=["suite.case", "suite.runtime-contract.case"], suites=["rdkafka-hs-test", "rdkafka-hs-integration"],+ artifacts={"README.md": hashlib.sha256((checker.ROOT / "README.md").read_bytes()).hexdigest()},+ supplemental_runs=[dict(kind="nonthreaded-runtime", rts_way="rts_v", tests=["suite.runtime-contract.case"], passed=1, tix="README.md")],+ measured_native_wrapper_ticks=1, misses=[])+ self.identity = patch.object(checker, "fingerprint", return_value="candidate")+ self.identity.start()+ self.addCleanup(self.identity.stop)++ def errors(self, allow=True):+ return checker.validate(self.matrix, self.exports, self.evidence, allow)++ def test_qualification_context_requires_exact_current_registration_and_complete_artifacts(self):+ with tempfile.TemporaryDirectory(prefix="rdkafka-context-control-") as directory:+ root = Path(directory)+ listing, log = root / "listing.txt", root / "run.log"+ listing.write_text("broker.case\n")+ log.write_text("All 1 tests passed (0.1s)\n")+ context = dict(kind="qualification-context", mode="--broker-qualification", fingerprint="candidate", tests=["broker.case"], passed=1,+ command=["binary", "--broker-qualification"], environment={"broker": "isolated"}, source={"archive": "controlled"},+ listing=str(listing), log=str(log), artifacts={str(p): hashlib.sha256(p.read_bytes()).hexdigest() for p in (listing, log)})+ self.assertEqual(common.qualification_context_errors(context, "candidate", ["broker.case"]), [])+ self.assertIn("stale qualification context", common.qualification_context_errors(context, "new-candidate"))+ self.assertIn("qualification context differs from current registered tests", common.qualification_context_errors(context, "candidate", ["broker.case", "missing.case"]))+ for broken in ("All 0 tests passed\n", "broker.case: FAIL\nAll 1 tests passed\n", "interrupted\n"):+ log.write_text(broken)+ context["artifacts"][str(log)] = hashlib.sha256(log.read_bytes()).hexdigest()+ self.assertIn("qualification log does not prove every test passed", common.qualification_context_errors(context, "candidate"))+ log.write_text("All 1 tests passed\n")+ self.assertTrue(any("modified qualification artifact" in e for e in common.qualification_context_errors(context, "candidate")))++ def test_owned_open_inventory_is_valid_for_development(self):+ self.assertEqual(self.errors(), [])++ def test_transferred_rows_keep_the_original_owner(self):+ row = self.matrix["contracts"][0]+ row.update(owner=16, previous_owner=14)+ self.assertEqual(self.errors(), [])+ self.assertTrue(any(row["id"] + ": open (EP-16)" == error for error in self.errors(False)))+ row["previous_owner"] = 99+ self.assertIn(row["id"] + ": invalid ownership transfer", self.errors())++ def test_unknown_owner_is_rejected_for_rows_and_misses(self):+ row = self.matrix["contracts"][0]+ row["owner"] = 99+ self.evidence["misses"] = [dict(module="Kafka.Version", line=1, label="ExpBox False", generated=False, contract="OWN-source-coverage", owner=99)]+ errors = self.errors()+ self.assertIn(row["id"] + ": invalid child owner", errors)+ self.assertTrue(any("unclassified coverage miss" in error for error in errors))++ def test_runtime_supplement_is_required(self):+ self.evidence.pop("supplemental_runs")+ self.assertIn("missing nonthreaded runtime coverage", self.errors())++ def test_threaded_run_cannot_substitute_for_nonthreaded_coverage(self):+ self.evidence["supplemental_runs"][0]["rts_way"] = "rts_thr"+ self.assertIn("runtime supplement is not nonthreaded", self.errors())++ def test_final_gate_rejects_open_rows(self):+ self.assertTrue(any("open (EP-" in e for e in self.errors(False)))++ def test_temporary_unassigned_export_is_rejected(self):+ self.exports = copy.deepcopy(self.exports)+ self.exports["Kafka.Version"].append(dict(symbol="Kafka.Version.untestedExport", members=[]))+ errors = self.errors()+ self.assertTrue(any("public exports changed" in e for e in errors))+ self.assertTrue(any("unassigned public symbol Kafka.Version.untestedExport" in e for e in errors))++ def test_new_constructor_cannot_hide_inside_existing_type(self):+ self.exports = copy.deepcopy(self.exports)+ self.exports["Kafka.Version"][0]["members"].append("Kafka.Version.NewConstructor")+ self.assertTrue(any("public exports changed" in e for e in self.errors()))++ def test_current_tested_row_is_accepted(self):+ row = self.matrix["contracts"][0]+ row.update(status="tested", tests=["suite.case"], fingerprint="candidate")+ self.assertEqual(self.errors(), [])++ def test_stale_tested_row_is_rejected_with_current_measurements(self):+ row = self.matrix["contracts"][0]+ row.update(status="tested", tests=["suite.case"], fingerprint="previous candidate")+ self.assertTrue(any(row["id"] + ": stale source evidence" in error for error in self.errors()))++ def test_missing_test_is_rejected(self):+ self.matrix["contracts"][0]["tests"] = ["removed.test"]+ self.assertTrue(any("unregistered test removed.test" in e for e in self.errors()))++ def test_stale_source_is_rejected(self):+ self.evidence["fingerprint"] = "previous candidate"+ self.assertIn("measured evidence is stale: run just coverage", self.errors())++ def test_missing_tix_artifact_is_rejected(self):+ self.evidence["artifacts"] = {"dist-coverage/missing-control.tix": "missing"}+ self.assertTrue(any("missing coverage artifact" in e for e in self.errors()))++ def test_modified_artifact_is_rejected(self):+ self.evidence["artifacts"]["README.md"] = "wrong"+ self.assertTrue(any("modified coverage artifact" in e for e in self.errors()))++ def test_zero_native_wrapper_coverage_is_rejected(self):+ self.evidence["measured_native_wrapper_ticks"] = 0+ self.assertIn("missing hand-written .chs coverage", self.errors())++ def test_missing_suite_is_rejected(self):+ self.evidence["suites"] = ["rdkafka-hs-test"]+ self.assertIn("coverage requires both suites", self.errors())++ def test_unexplained_source_miss_is_rejected(self):+ self.evidence["misses"] = [dict(module="Kafka.Version", line=1, label="ExpBox False", generated=False, contract="OWN-source-coverage", owner=14)]+ self.assertTrue(any("unexplained hand-written coverage miss" in e for e in self.errors(False)))++ def test_source_classification_requires_matching_file_bytes(self):+ key = "Kafka.Version:1:ExpBox False"+ self.evidence["misses"] = [dict(module="Kafka.Version", line=1, label="ExpBox False", generated=False,+ source="src/Kafka/Version.hs", contract="OWN-source-coverage", owner=16)]+ classification = dict(status="inapplicable", rationale="Synthetic control", source="src/Kafka/Version.hs",+ source_sha256=hashlib.sha256((checker.ROOT / "src/Kafka/Version.hs").read_bytes()).hexdigest())+ self.matrix["miss_classifications"][key] = classification+ self.assertEqual(self.errors(), [])+ classification["source_sha256"] = "previous source"+ self.assertIn("stale source classification: " + key, self.errors())+ classification.pop("source_sha256")+ self.assertIn("stale source classification: " + key, self.errors())++ def test_normal_haskell_is_unchanged(self):+ source = "module Example where\nexample = 1\n"+ actual, mapping = preprocessor.transform("Example.hs", source)+ self.assertEqual(actual, '{-# LINE 1 "Example.hs" #-}\n' + source)+ self.assertIsNone(mapping)++ def test_c2hs_spans_map_both_generated_and_handwritten_code(self):+ source = (checker.ROOT / "src/Kafka/Internal/RdKafka.chs").read_text().splitlines()+ generated = next(i for i, s in enumerate(source, 1) if s.startswith("{#"))+ handwritten = next(i for i, s in enumerate(source, 1) if s.startswith("newRdKafkaConfT ::"))+ text = f'{{-# LINE {generated} "src/Kafka/Internal/RdKafka.chs" #-}}\ngenerated = 1\n{{-# LINE {handwritten} "src/Kafka/Internal/RdKafka.chs" #-}}\nwrapper = 2\n'+ actual, mapping = preprocessor.transform("Generated.hs", text)+ self.assertTrue(mapping[1]["generated"])+ self.assertFalse(mapping[3]["generated"])+ self.assertEqual(mapping[3]["line"], handwritten)+ self.assertNotIn('"src/Kafka/Internal/RdKafka.chs"', actual)+ self.assertIn('{-# LINE 1 "Generated.hs" #-}', actual)++ def test_generated_enum_internal_blank_does_not_advance_into_manual_source(self):+ source = (checker.ROOT / "src/Kafka/Internal/RdKafka.chs").read_text().splitlines()+ hook = next(i for i, line in enumerate(source, 1) if line.startswith("{#enum rd_kafka_conf_res_t"))+ text = f'{{-# LINE {hook} "src/Kafka/Internal/RdKafka.chs" #-}}\ndata Generated = A\ninstance Enum Generated where\n fromEnum A = 0\n\n toEnum 0 = A\n{{-# LINE {hook} "src/Kafka/Internal/RdKafka.chs" #-}}\n\nmanual = 1\n'+ _, mapping = preprocessor.transform("Generated.hs", text)+ self.assertTrue(all(mapping[index]["generated"] for index in range(1, 6)))+ self.assertFalse(mapping[8]["generated"])+ self.assertEqual(mapping[8]["line"], hook + 1)++ def test_spaced_c2hs_hook_is_generated(self):+ source = (checker.ROOT / "src/Kafka/Internal/RdKafka.chs").read_text().splitlines()+ hook = next(i for i, line in enumerate(source, 1) if line.startswith("{# fun"))+ end = next(i for i in range(hook, len(source) + 1) if "#}" in source[i - 1])+ text = f'{{-# LINE {hook} "src/Kafka/Internal/RdKafka.chs" #-}}\ngenerated = 1\n\ngeneratedMore = 2\n{{-# LINE {end} "src/Kafka/Internal/RdKafka.chs" #-}}\n\nmanual = 3\n'+ _, mapping = preprocessor.transform("Generated.hs", text)+ self.assertTrue(all(mapping[index]["generated"] for index in range(1, 4)))+ self.assertFalse(mapping[6]["generated"])+ self.assertEqual(mapping[6]["line"], end + 1)++ def test_compiler_derived_temporary_export_is_rejected(self):+ with tempfile.TemporaryDirectory(prefix="rdkafka-export-control-") as directory:+ root = Path(directory)+ source = root / "Version.hs"+ source.write_text("module Kafka.Version (untestedExport) where\nuntestedExport :: Int\nuntestedExport = 1\n")+ subprocess.run(["ghc", "-c", str(source), "-odir", str(root / "build"), "-hidir", str(root / "build")], check=True, capture_output=True)+ with patch.object(common, "exposed_modules", return_value=["Kafka.Version"]), patch.object(common, "components", return_value={"lib": root}):+ exports = common.compiler_exports("unused")+ self.exports = copy.deepcopy(self.exports)+ self.exports["Kafka.Version"] = exports["Kafka.Version"]+ self.assertIn("unassigned public symbol Kafka.Version.untestedExport", self.errors())++ def test_semantic_fixture_mutations_fail_after_successful_compilation(self):+ prepared = subprocess.run(["cabal", "build", "rdkafka-hs-integration", "-f", "integration"], cwd=checker.ROOT, capture_output=True, text=True)+ self.assertEqual(prepared.returncode, 0, prepared.stdout + prepared.stderr)+ plan = json.loads((checker.ROOT / "dist-newstyle/cache/plan.json").read_text())+ component = next(c for c in plan["install-plan"] if c.get("pkg-name") == "rdkafka-hs" and c.get("component-name") == "test:rdkafka-hs-integration")+ # Expose the exact selected component dependencies. Broad -package NAME+ # flags can expose several installed variants; cabal exec's default+ # library environment omits test-only packages such as network.+ packages = [arg for unit in component["depends"] for arg in ("-package-id", unit)]+ with tempfile.TemporaryDirectory(prefix="rdkafka-fixture-controls-") as directory:+ root = Path(directory)+ for name in ("FixtureSupport", "FixtureSupportTest", "CallbackTestSupport", "FaultTestSupport"):+ target = root / "Kafka" / (name + ".hs")+ target.parent.mkdir(exist_ok=True)+ target.write_text((checker.ROOT / "test-integration/Kafka" / (name + ".hs")).read_text())+ (root / "Main.hs").write_text("module Main (main) where\nimport Kafka.FixtureSupportTest (tests)\nimport Test.Tasty (defaultMain)\nmain :: IO ()\nmain = defaultMain tests\n")+ source_path = root / "Kafka/FixtureSupport.hs"+ source = source_path.read_text()+ variants = [+ ("control", source, 0, None),+ ("fabricated enqueue success", source.replace("Left (ImmediateError err) -> pure (Left err)", "Left (ImmediateError _) -> pure (Right ())"), 1, "immediate enqueue rejection propagates"),+ ("swallowed poll error", source.replace("| otherwise -> pure (Left err)", "| otherwise -> go acc"), 1, "unexpected poll error propagates")]+ for name, text, expected_exit, failed_case in variants:+ with self.subTest(mutation=name):+ if failed_case:+ self.assertNotEqual(source, text)+ source_path.write_text(text)+ command = ["cabal", "exec", "--", "ghc", "--make", "-O1", "-threaded", "-XGHC2024", "-XOverloadedStrings", "-i" + str(root), "-hide-all-packages", *packages, str(root / "Main.hs"), "-o", str(root / "controls")]+ compiled = subprocess.run(command, cwd=checker.ROOT, capture_output=True, text=True)+ self.assertEqual(compiled.returncode, 0, compiled.stdout + compiled.stderr)+ result = subprocess.run([str(root / "controls")], capture_output=True, text=True)+ self.assertEqual(result.returncode, expected_exit, result.stdout + result.stderr)+ if failed_case:+ self.assertRegex(result.stdout, re.escape(failed_case) + r":\s+FAIL")+++if __name__ == "__main__":+ unittest.main()
+ scripts/test-coverage.sh view
@@ -0,0 +1,7 @@+#!/usr/bin/env bash+set -euo pipefail+cd "$(dirname "$0")/.."+cabal build lib:rdkafka-hs rdkafka-hs-integration -f integration+python3 scripts/test-coverage-tools.py+redpanda-local-up+python3 scripts/collect-coverage.py
+ scripts/test-mutations.hs view
@@ -0,0 +1,621 @@+#!/usr/bin/env cabal+{-# LANGUAGE GHC2024 #-}+{- cabal:+build-depends: base >=4.21 && <5, aeson, bytestring, directory, filepath, process, text, time+default-language: GHC2024+ghc-options: -Wall+-}+{-# LANGUAGE OverloadedStrings #-}++-- One runner for the repair plans' isolated, compiled semantic mutations.+-- Ordinary tests remain Cabal test suites; this tool only proves their sensitivity.+import Control.Exception (evaluate)+import Control.Monad (forM, forM_, unless, when)+import Data.Aeson (encode, object, (.=))+import Data.ByteString qualified as B+import Data.ByteString.Char8 qualified as BC+import Data.ByteString.Lazy qualified as BL+import Data.Char (isSpace)+import Data.List (findIndex, isInfixOf, isPrefixOf, isSuffixOf, nub, sortOn, stripPrefix, tails)+import Data.Text qualified as T+import Data.Text.Encoding qualified as TE+import Data.Time (defaultTimeLocale, formatTime, getCurrentTime)+import System.Directory (createDirectory, createDirectoryIfMissing, doesDirectoryExist, doesFileExist, getCurrentDirectory, listDirectory, removeFile)+import System.Environment (getArgs, getEnvironment)+import System.Exit (ExitCode (..), die)+import System.FilePath (makeRelative, (</>))+import System.IO (IOMode (WriteMode), hClose, hFlush, openTempFile, stdout, withFile)+import System.Process (CreateProcess (..), StdStream (..), proc, readCreateProcessWithExitCode, waitForProcess, withCreateProcess)+import System.Timeout (timeout)++data Mutation = Mutation+ { name :: String,+ suite :: String,+ patternText :: String,+ expected :: Maybe String,+ edits :: [(FilePath, String -> String)],+ replay :: Bool,+ safety :: Maybe String+ }++integration, unit, producer, callbacks, conversion, consumer, consumerConversion, topic, properties :: String+integration = "rdkafka-hs-integration"+unit = "rdkafka-hs-test"+producer = "src/Kafka/Producer.hs"+callbacks = "src/Kafka/Producer/Callbacks.hs"+conversion = "src/Kafka/Producer/Convert.hs"+consumer = "src/Kafka/Consumer.hs"+consumerConversion = "src/Kafka/Consumer/Convert.hs"+topic = "src/Kafka/Topic.hs"+properties = "src/Kafka/Producer/ProducerProperties.hs"++control :: String -> String -> String -> Mutation+control label component group = Mutation label component ("/" <> group <> "/") Nothing [] False Nothing++mutation :: String -> String -> FilePath -> (String -> String) -> String -> Mutation+mutation group label file change test = Mutation label integration ("/" <> group <> "/&&/" <> test <> "/") (Just test) [(file, change)] False Nothing++families :: String -> [Mutation]+families "producer" =+ control "unchanged-control" integration "producer-regressions"+ : [ p "topic-settings-dropped" producer (replace setting "") "explicit topic timeout expires an accepted message",+ p "rejection-root-retained" producer (replace release "") "queue-full rejection releases callback capture without invoking it",+ unsafe $ p "accepted-root-freed" producer (replace "then pure (Right ())" "then freeStablePtr callbackPtr >> pure (Right ())") "accepted callback retains its capture until a purged report completes",+ unsafe $ p "enqueue-mask-removed" producer (replace "\\topicName -> mask_ $ do" "\\topicName -> do") "cancellation after native acceptance retains callback until its report",+ p "global-exception-skips-message" callbacks (replace "outcome <- try @SomeException (restore (callback rep))" "outcome <- (Right <$> restore (callback rep)) :: IO (Either SomeException ())") "throwing global callback preserves per-message delivery and releases capture",+ p "delivery-root-retained" callbacks (replace "bracket (pure $ castPtrToStablePtr cbPtr) freeStablePtr" "bracket (pure $ castPtrToStablePtr cbPtr) (const (pure ()))") "accepted callback retains its capture until a purged report completes",+ p "empty-bytes-become-absent" producer (replace "withBS (Just bs) f | BS.null bs = allocaBytes 1 $ \\p -> f p 0\n" "") "byte-exact round trip with NoCompression",+ p "input-validation-dropped" producer (replace "case recordError msg of" "case Nothing of") "rejects before native enqueue: NUL topic name",+ p "global-overrides-topic" producer (replace setting (setting <> "\n setAllKafkaConfValues kc (KafkaProps (ppKafkaProps pps))")) "actual client configuration: explicit topic wins duplicate",+ p "headers-dropped" producer (replace "rdKafkaMessageProduceVa k (hdrs ++ opts)" "rdKafkaMessageProduceVa k opts") "byte-exact round trip with NoCompression",+ p "rejection-release-after-decoding" producer (replace " res <- handleProduceErrT code\n" (" res <- handleProduceErrT code\n" <> release) . replace release "") "native error decoding failure releases rejected callback capture",+ p "nonnull-success-code-accepted" producer (replace "pure $ Left (ImmediateError (maybe KafkaInvalidReturnValue id res))" "pure $ maybe (Right ()) (Left . ImmediateError) res") "non-null native success-code error rejects and releases capture",+ p "unknown-error-replaced-by-errno" conversion (replace "handleProduceErrT RdKafkaRespErrNoError" "handleProduceErrT RdKafkaRespErrUnknown = Just . kafkaRespErr <$> getErrno\nhandleProduceErrT RdKafkaRespErrNoError") "unknown native error code is preserved instead of reading errno"+ ]+ where+ p = mutation "producer-regressions"+ setting = " setAllKafkaConfValues kc (KafkaProps (ppTopicProps pps))"+ release = " freeStablePtr callbackPtr\n"+ unsafe m = m {safety = Just ("producer safety probe: native enqueue accepted (" <> name m <> ")")}+families "seek" =+ control "unchanged-control" integration "seek-partitions"+ : [ s "member-errors-dropped" consumer (replace selection "pure Nothing") "unassigned member reports native error",+ s "error-order-reversed" consumer (replace selection "pure $ KafkaResponseError <$> find substantive (reverse errors)") "mixed errors follow actual request order",+ s "pending-always-normalized" consumer (replace pending "code /= RdKafkaRespErrInProgress") "nonzero-timeout preserves residual pending",+ s "pending-never-normalized" consumer (replace pending "True") "zero-timeout all pending promises initiation only",+ s "message-commit-forgets-next-offset" consumerConversion (replace "PartitionOffset $ moff + 1" "PartitionOffset moff") "rewind message commit resumes after committed message",+ s "rewind-decrements-committed-offset" consumer (replace "let ps' = map checkOffsets ps" "let ps' = map (\\p -> case tpOffset p of { PartitionOffset n -> p {tpOffset = PartitionOffset (n - 1)}; _ -> p }) (map checkOffsets ps)") "rewind uses committed next offset exactly",+ s "rewind-discards-seek-error" consumer (replace " seekPartitions c ps' to" " seekPartitions c ps' to >> pure Nothing") "rewind propagates assignment change after committed lookup"+ ]+ where+ s = mutation "seek-partitions"+ selection = "pure $ KafkaResponseError <$> find substantive errors"+ pending = "(timeout /= 0 || code /= RdKafkaRespErrInProgress)"+families "property" =+ map+ stress+ [ control "pure-control" unit "Producer properties generated",+ control "callback-control" integration "producer-properties",+ pureLaw "global-bias-reversed" "M.union k2 k1" "M.union k1 k2",+ pureLaw "topic-bias-reversed" "M.union t2 t1" "M.union t1 t2",+ pureLaw "log-level-bias-reversed" "ll2 `mplus` ll1" "ll1 `mplus` ll2",+ mutation "producer-properties" "callback-order-reversed" properties (replace "cb1 `mplus` cb2" "cb2 `mplus` cb1") "callback composition preserves order and identity"+ ]+ where+ stress m = m {replay = True}+ pureLaw label old new = (mutation "Producer properties generated" label properties (replace old new) "program follows last-write semantics") {suite = unit}+families "topic" =+ control "unchanged-control" integration "topic-configuration"+ : [ t "configuration-removed" (section "withNewTopic t action =" "withOldTopic ::" (section "configured <-" "\n case configured of" (const "configured <- pure (Right ())"))) "singleton configuration reaches the broker",+ t "old-acquisition-lifetime" oldAcquisition "setter rejection releases allocated request before submission",+ t "queue-finalization-removed" (replace "bracket (newRdKafkaQueue kafka) finalizeForeignPtr" "bracket (newRdKafkaQueue kafka) (const (pure ()))") "setter rejection releases allocated request before submission",+ t "options-finalization-removed" (replace "bracket (newRdKAdminOptions kafka RdKafkaAdminOpAny) finalizeForeignPtr" "bracket (newRdKAdminOptions kafka RdKafkaAdminOpAny) (const (pure ()))") "setter rejection releases allocated request before submission",+ t "delete-request-finalization-removed" (section "withOldTopic tName transform =" "oldTopicPtr ::" (replace "(mapM_ finalizeForeignPtr)" "(const (pure ()))")) "missing topic deletion preserves its error and releases the request",+ t "event-finalization-removed" (section "waitForResponse topic fromEvent" "singletonList ::" (replace "(mapM_ finalizeForeignPtr)" "(const (pure ()))")) "broker-rejected values release requests and response events repeatedly",+ t "native-request-error-ignored" (replace "requestError <- rdKafkaEventError event" "requestError <- pure RdKafkaRespErrNoError") "unresponsive broker preserves the native timeout error",+ t "topic-identity-ignored" (replace "[Right name] | TopicName (T.pack name) == topic -> Right topic" "[Right _] -> Right topic") "wrong topic response cannot report success"+ ]+ where+ t label change = mutation "topic-configuration" label topic change+ oldAcquisition =+ section "mkNewTopicUnsafe topic =" "-- Keep the client alive" (const oldSetup)+ . section "withNewTopic t action =" "withOldTopic ::" (const "withNewTopic t = withUnsafeOne t mkNewTopicUnsafe rdKafkaNewTopicDestroy\n\n")+ oldSetup =+ unlines+ [ "mkNewTopicUnsafe topic = do",+ " allocated <- newRdKafkaNewTopicUnsafe (T.unpack $ unTopicName $ topicName topic) (unPartitionCount $ topicPartitionCount topic) (unReplicationFactor $ topicReplicationFactor topic)",+ " case first (KafkaError . T.pack) allocated of",+ " Left err -> pure (Left err)",+ " Right native -> do",+ " configured <- whileRight (uncurry $ rdKafkaNewTopicSetConfig native) (M.toList $ topicConfig topic)",+ " pure $ case configured of",+ " Left err -> Left (KafkaResponseError err)",+ " Right () -> Right native",+ ""+ ]+families "callback" =+ [ control "integration-control" integration "callback-lifetime",+ control "registry-control" unit "Callback owner",+ c "registrations-never-freed" owner (replace "newCallbackOwner = newCallbackOwnerWith freeHaskellFunPtr" "newCallbackOwner = newCallbackOwnerWith (const (pure ()))") "async error callback releases after destroy with retained wrapper",+ early {safety = Just ("callback safety probe: native destructor entered (" <> name early <> ")")},+ c "native-handoff-mask-removed" native (replace "newRdKafkaT owner kafkaType confPtr = mask_ $" "newRdKafkaT owner kafkaType confPtr =") "producer constructor cancellation at native acceptance releases its owner",+ c "lifecycle-published-before-teardown" consumer (replace " finalizeForeignPtr k" " void $ forkIO (finalizeForeignPtr k)") "async concurrent destruction joins at native entry",+ (mutation "Callback owner" "registration-allocation-unmasked" owner (replace "allocate install = mask_ $ do" "allocate install = do") "bridge allocation executes masked before ownership is recorded") {suite = unit}+ ]+ where+ owner = "src/Kafka/Internal/CallbackOwner.hs"+ native = "src/Kafka/Internal/RdKafka.chs"+ c = mutation "callback-lifetime"+ finalizer = section "Concurrent.addForeignPtrFinalizer ret $" "\n{#fun rd_kafka_brokers_add"+ early =+ c+ "registrations-freed-before-native-shutdown"+ native+ (finalizer (replace " {# call rd_kafka_destroy_flags #} realPtr 0x8" " releaseCallbackOwner owner\n {# call rd_kafka_destroy_flags #} realPtr 0x8" . replace " releaseCallbackOwner owner\n" ""))+ "async concurrent destruction joins at native entry"+families "transaction" =+ control "unchanged-control" integration "transaction-errors"+ : [ t "init-error-retained" transaction (omit "initTransactions p" "\n-- | Begins") (immediate "init"),+ t "begin-error-retained" transaction (omit "beginTransaction p" "\n-- | Commits") (immediate "begin"),+ t "abort-error-retained" transaction (omit "abortTransaction p" "\n-- | Commits the message") (immediate "abort"),+ t "commit-error-retained" transaction (omit "commitTransaction p" "\n-- | Aborts") (immediate "commit"),+ t "offset-error-retained" transaction (omit "commitOffsetMessageTransaction p" "\n-- -- | Commit offsets") (immediate "offset"),+ t "fatal-flag-inverted" transaction (replace "txErrorFatal = fatal" "txErrorFatal = not fatal") (flags "commit"),+ t "retry-flag-inverted" transaction (replace "txErrorRetriable = retriable" "txErrorRetriable = not retriable") (flags "commit"),+ t "abort-flag-inverted" transaction (replace "txErrorTxnReqAbort = reqAbort" "txErrorTxnReqAbort = not reqAbort") (flags "offset"),+ t "group-metadata-retained" native (replace "rdKafkaConsumerGroupMetadataDestroy $" "(const (pure ())) $") (immediate "offset"),+ t "wrong-source-offset" consumerConversion (replace "moff + 1" "moff") "async commit publishes output and source next offset atomically; abort publishes neither"+ ]+ where+ transaction = "src/Kafka/Transaction.hs"+ native = "src/Kafka/Internal/RdKafka.chs"+ t = mutation "transaction-errors"+ omit start end = section start end (replace "rdKafkaErrorDestroy" "(const (pure ()))")+ immediate operation = operation <> " without transactional ID preserves native code and destroys error"+ flags operation = operation <> " copies native flag combination 7 before destruction"+families "public" =+ [ control "unit-control" unit "Public properties",+ (control "native-control" integration "consumer-properties") {replay = True},+ p "consumer-bias-reversed" "src/Kafka/Consumer/ConsumerProperties.hs" (replace "M.union m2 m1" "M.union m1 m2") "consumer program follows independent last-write model",+ p "consumer-poll-mode-bias-reversed" "src/Kafka/Consumer/ConsumerProperties.hs" (replace "(cup2 `mplus` cup1)" "(cup1 `mplus` cup2)") "consumer program follows independent last-write model",+ p "subscription-bias-reversed" "src/Kafka/Consumer/Subscription.hs" (replace "M.union m2 m1" "M.union m1 m2") "subscription follows last-write properties and topic union",+ p "header-order-reversed" "src/Kafka/Types.hs" (replace "headersToList = unHeaders" "headersToList = reverse . unHeaders") "header list round-trip preserves duplicates and binary bytes",+ p "record-map-loses-headers" "src/Kafka/Consumer/Types.hs" (replace " fmap = second" " fmap f = (\\r -> r {crHeaders = mempty}) . second f") "record functor identity",+ p "version-minor-shifted" "src/Kafka/Version.hs" (replace "versionMinor = (n `shiftR` 16)" "versionMinor = (n `shiftR` 8)") "version bytes decode independently of prerelease byte",+ (mutation "consumer-properties" "consumer-callback-order-reversed" "src/Kafka/Consumer/ConsumerProperties.hs" (replace "(cb1 `mplus` cb2)" "(cb2 `mplus` cb1)") "consumer callback composition preserves registration order and identity") {replay = True},+ (mutation "consumer-properties" "generated-source-offset-not-advanced" consumerConversion (replace "moff + 1" "moff") "generated source offsets reach native code as the representable next position") {replay = True}+ ]+ where+ p label path change test = (mutation "Public properties" label path change test) {suite = unit, replay = True}+families "messages" =+ [ control "unchanged-control" integration "public-contract/&&/messages",+ m "batch-release-removed" consumer (replace "releaseBatch (Right messages) = mapM_ (\\message -> withForeignPtr message rdKafkaMessageDestroy) messages" "releaseBatch (Right _) = pure ()") "batch decoder exception releases unprocessed messages",+ m+ "single-acquisition-unmasked"+ consumerConversion+ ( replace "withPolledMessage acquire = bracket acquire releaseMessage" "withPolledMessage acquire action = do\n pointer <- acquire\n action pointer `finally` releaseMessage pointer"+ . replace "import Control.Exception (bracket)" "import Control.Exception (bracket, finally)"+ )+ "async single cancellation at native return releases its native message",+ m "header-error-suppressed" consumerConversion (replace "readHeaders rptr >>= \\case" "(either (const (Right mempty)) Right <$> readHeaders rptr) >>= \\case") "batch native header errors remain errors while later records are released",+ m "native-batch-failure-suppressed" consumer (replace "Left code -> pure [Left (KafkaResponseError code)]" "Left _ -> pure []") "signed native batch failure preserves its error and queued data"+ ]+ where+ m = mutation "public-contract"+families "rebalance" =+ [ control "unchanged-control" integration "rebalance-errors",+ r "owned-rebalance-error-retained" (replace "bracket acquire rdKafkaErrorDestroy" "bracket acquire (const (pure ()))") "cooperative assign async native reports failure without a success event",+ r "cooperative-assign-error-ignored" (replace "then checkRebalanceError (rdKafkaIncrementalAssign kptr pls)" "then void $ rdKafkaIncrementalAssign kptr pls") "cooperative assign async native reports failure without a success event",+ r "cooperative-revoke-error-ignored" (replace "then checkRebalanceError (rdKafkaIncrementalUnassign kptr pls)" "then void $ rdKafkaIncrementalUnassign kptr pls") "cooperative revoke sync native reports failure without a success event",+ r "rebalance-error-code-ignored" (replace "checkRebalanceCode action = action >>= either throwIO pure . rdKafkaErrorToEither" "checkRebalanceCode action = void action") "eager revoke sync native reports failure without a success event",+ r "unexpected-rebalance-reset-omitted" (section " x -> mask_ $ do" "-- The outer native callback boundary" (replace "checkRebalanceCode (newForeignPtr_ nullPtr >>= rdKafkaAssign kptr)" "pure ()")) "sync unexpected rebalance error clears assignment and pending records",+ r "unexpected-rebalance-reset-error-ignored" (section " x -> mask_ $ do" "-- The outer native callback boundary" (replace "checkRebalanceCode (newForeignPtr_ nullPtr >>= rdKafkaAssign kptr)" "void (newForeignPtr_ nullPtr >>= rdKafkaAssign kptr)")) "async unexpected rebalance error preserves state when native reset fails"+ ]+ where+ r label change test = mutation "public-contract" label "src/Kafka/Consumer/Callbacks.hs" change test+families "credentials" =+ [ control "unchanged-credentials-control" integration "setSaslCredentials",+ mutation "lifecycle" "nul-username-truncated" "src/Kafka/Internal/Shared.hs" (replace "validateCStringInput \"SASL username\" username" "Nothing") "setSaslCredentials rejects NUL in username without changing producer or consumer identity",+ mutation "lifecycle" "nul-password-truncated" "src/Kafka/Internal/Shared.hs" (replace "validateCStringInput \"SASL password\" password" "Nothing") "setSaslCredentials rejects NUL in password without changing producer or consumer identity",+ mutation "lifecycle" "credential-acquisition-unmasked" "src/Kafka/Internal/RdKafka.chs" (replace "rdKafkaSaslSetCredentials k username password = mask_ $ do" "rdKafkaSaslSetCredentials k username password = do") "setSaslCredentials cancellation at error acquisition releases the owned error",+ mutation "lifecycle" "credential-error-retained" "src/Kafka/Internal/RdKafka.chs" (replace "else rdKafkaErrorCode err `finally` rdKafkaErrorDestroy err" "else rdKafkaErrorCode err") "setSaslCredentials releases each actual native error after decoding its exact code"+ ]+families "source-edges" =+ [ control "unchanged-message-control" integration "independently absent",+ control "unchanged-offset-control" integration "native logical offsets decode independently",+ control "unchanged-constructor-control" integration "construction failure releases callbacks: subscribe",+ control "unchanged-batch-control" integration "batch capacity",+ control "unchanged-log-level-control" integration "producer constructor log level",+ control "unchanged-subscription-error-control" integration "subscription acquisition failure",+ control "unchanged-legacy-constructor-control" integration "legacy-seek-constructor-failure",+ edge "negative-partition-fabricates-origin" (replace "cmePartition = if partition >= 0 then Just (PartitionId partition) else Nothing" "cmePartition = Just (PartitionId partition)") "async attributed error preserves independently absent partition-and-offset",+ edge "negative-offset-fabricates-origin" (replace "cmeOffset = if offset >= 0 then Just (Offset offset) else Nothing" "cmeOffset = Just (Offset offset)") "sync attributed error preserves independently absent offset",+ edge "beginning-offset-decoded-as-stored" (replace "o == -2 = PartitionOffsetBeginning" "o == -2 = PartitionOffsetStored") "native logical offsets decode independently without losing partition identity",+ mutation+ "callback-lifetime"+ "subscription-failure-client-retained"+ consumer+ (section "case subscribeError of" "-- | Create a consumer" (replace "_ <- closeConsumer kafka `finally` destroyConsumer kafka" "_ <- pure Nothing"))+ "async construction failure releases callbacks: subscribe",+ mutation+ "public-contract"+ "batch-record-order-reversed"+ consumer+ (replace "traverse copyMessagePtr messages" "traverse copyMessagePtr (reverse messages)")+ "batch capacity 2 preserves complete ordered records across partial batches",+ mutation+ "public-contract"+ "producer-constructor-log-level-omitted"+ "src/Kafka/Producer.hs"+ (replace "forM_ (ppLogLevel pps) (rdKafkaSetLogLevel kafka . fromEnum)" "pure ()")+ "producer constructor log level overrides the global property on the native client",+ mutation+ "public-contract"+ "subscription-native-error-replaced"+ "src/Kafka/Internal/RdKafka.chs"+ (section "rdKafkaSubscription ::" "{#fun rd_kafka_consumer_poll" (replace "e -> return (Left e)" "_ -> return (Left RdKafkaRespErrTimedOut)"))+ "subscription acquisition failure preserves the native error without a list",+ mutation+ "public-contract"+ "legacy-topic-acquisition-error-suppressed"+ consumer+ (section "withTopics (tp : rest) action" "seekAll pairs" (replace "Left err -> pure (Left err)" "Left _ -> pure (Right ())"))+ "legacy-seek-constructor-failure-does-not-execute-an-earlier-valid-seek"+ ]+ where+ edge label change test = mutation "public-contract" label consumerConversion change test+families "state" =+ [ control "unchanged-control" integration "consumer-state",+ c "pause-omitted" (replace "changePause consumer ps True rdKafkaPausePartitions" "changePause consumer ps True (\\_ _ -> pure RdKafkaRespErrNoError)") "pause-resume-preserves-records",+ c "member-errors-suppressed" (replace "Right () -> fmap KafkaResponseError . find (/= RdKafkaRespErrNoError) <$> nativeTopicPartitionErrors partitions" "Right () -> pure Nothing") "pause-mixed-member-error",+ c "store-member-errors-suppressed" (replace "partitionListError pl =<< rdKafkaOffsetsStore k pl" "kafkaErrorToMaybe . KafkaResponseError <$> rdKafkaOffsetsStore k pl") "store-mixed-member-error",+ c "global-consumer-topic-setting-discarded" (replace "setAllKafkaConfValues kc (KafkaProps tp)" "setAllKafkaConfValues kc (KafkaProps (M.insert \"auto.offset.reset\" \"latest\" tp))") "global-topic-setting-survives-empty-subscription-properties"+ ]+ where+ c label change test = mutation "consumer-state" label consumer change test+families "diagnostics" =+ [ control "unchanged-control" integration "diagnostics",+ d "dump-array-release-removed" "src/Kafka/Dump.hs" (replace "(uncurry rdKafkaConfDumpFree)" "(const (pure ()))") "global cancellation at native acquisition releases its array",+ d "native-stream-close-removed" "src/Kafka/Internal/RdKafka.chs" (replace "(throwErrnoIfMinus1_ \"fclose\" . fclose)" "(const (pure ()))") "supported-property print flushes and preserves the caller handle",+ d "caller-handle-consumed" "src/Kafka/Internal/RdKafka.chs" (replace "(hDuplicate handle)" "(pure handle)") "client print flushes and preserves the caller handle"+ ]+ where+ d = mutation "diagnostics"+families "runtime" =+ [ control "nonthreaded-control" integration "runtime-contract",+ mutation "runtime-contract" "async-runtime-guard-removed" consumer (replace "&& not rtsSupportsBoundThreads" "&& False") "RTS capability is observed by async construction"+ ]+families "metadata" =+ [ control "unchanged-control" integration "metadata-contract",+ d+ "metadata-acquisition-unmasked"+ ( replace+ "bracket acquire (either (const (pure ())) finalizeForeignPtr) $\n either (pure . Left . KafkaResponseError) decode"+ "do\n result <- acquire\n either (pure . Left . KafkaResponseError) decode result `finally` either (const (pure ())) finalizeForeignPtr result"+ . replace "import Control.Exception (bracket)" "import Control.Exception (bracket, finally)"+ )+ "metadata native acquisition cancellation releases its result",+ d "metadata-topic-error-suppressed" (replace "watermarkOffsets' k timeout tm = case tmError tm of" "watermarkOffsets' k timeout tm = case Nothing of") "missing topic errors survive convenience helpers",+ d "timestamp-member-error-suppressed" (replace "case find (/= RdKafkaRespErrNoError) errors of" "case Nothing of") "mixed timestamp request preserves native partition failure",+ d "future-group-state-throws" (replace "_ -> Left (KafkaError (\"Unsupported Kafka consumer group state: \" <> s))" "_ -> error (\"Unsupported Kafka consumer group state: \" <> Text.unpack s)") "sync group identity lifecycle and supported native states",+ d "completing-rebalance-state-wrong" (replace "\"CompletingRebalance\" -> Right GroupAwaitingSync" "\"CompletingRebalance\" -> Right GroupStable") "sync group identity lifecycle and supported native states"+ ]+ where+ d label change test = mutation "metadata-contract" label "src/Kafka/Metadata.hs" change test+families "buffer" =+ [ control "unchanged-control" integration "public-contract",+ b "callback-record-not-retained" (replace "bufferedMessages buffer |> packPendingMessage copied" "bufferedMessages buffer") "callback-event-poll-preserves-application-records",+ b "callback-buffer-reversed" (replace "bufferedMessages buffer |> packPendingMessage copied" "packPendingMessage copied Seq.<| bufferedMessages buffer") "sync-buffer-fields-create-time",+ b "callback-origin-offset-lost" (replace "(Offset <$> offset)" "(const (Offset 0) <$> offset)") "sync-buffer-fields-create-time",+ b "callback-append-time-changed" (replace "packTimestamp (LogAppendTime time) = PendingLogAppendTime time" "packTimestamp (LogAppendTime time) = PendingCreateTime time") "sync-buffer-fields-append-time",+ b "callback-buffer-kept-after-assignment" (replace "when (err == RdKafkaRespErrNoError) (resetPendingMessages conf)" "pure ()") "callback-buffer-reassignment-replaces-pending-records",+ b "callback-buffer-kept-after-seek" (replace "discardPendingMessages (getKafkaConf consumer) initiated" "pure ()") "callback-buffer-seek-replaces-pending-records",+ b "callback-buffer-pause-ignored" (replace "let ready = maybe True (`Set.notMember` pendingPausedPartitions buffer) . pendingMessagePartition" "let ready _ = True") "callback-buffer-pause-defers-pending-records",+ b "callback-buffer-kept-after-legacy-seek" (replace "when (result == RdKafkaRespErrNoError) (discardPendingMessages (getKafkaConf consumer) (Set.singleton (topic, partition)))" "pure ()") "callback-buffer-legacy-partial-seek-keeps-success"+ ]+ where+ b label change test = mutation "public-contract" label consumer change test+families "legacy-seek" =+ [ control "unchanged-control" integration "deprecated-seek",+ mutation "consumer-state" "legacy-native-state-suppressed" consumer (section " rdSeek kt topic" " topicPair tp" (replace "pure (rdKafkaErrorToEither result)" "pure (Right ())")) "deprecated-seek-reports-unassigned-state-and-recovers-after-assignment",+ mutation "consumer-state" "legacy-offset-incremented" consumer (section " rdSeek kt topic" " topicPair tp" (replace "(offsetToInt64 o)" "(offsetToInt64 o + 1)")) "deprecated-seek-exact-repeated-replay"+ ]+families "partition-lists" =+ control "unchanged-control" integration "partition-list-ownership"+ : [ mutation "partition-list-ownership" "pair-conversion-cleanup-deferred" consumerConversion (section "toNativeTopicPartitionList' tps =" "topicPartitionFromMessage ::" (replace "finalizeForeignPtr" "(const (pure ()))")) "pair conversion failure releases the partial list before GC",+ mutation "partition-list-ownership" "offset-conversion-cleanup-deferred" consumerConversion (section "toNativeTopicPartitionList ps =" "toNativeTopicPartitionListNoDispose ::" (replace "finalizeForeignPtr" "(const (pure ()))")) "offset conversion failure releases the partial list before GC",+ mutation "partition-list-ownership" "assignment-output-cleanup-deferred" consumer (section "assignment (KafkaConsumer" "-- | Returns current consumer's subscription" (replace "(mapM_ finalizeForeignPtr)" "(const (pure ()))")) "assignment outputs release after exact decoding",+ mutation "partition-list-ownership" "subscription-output-cleanup-deferred" consumer (section "subscription (KafkaConsumer" "-- | Pauses specified partitions" (replace "(mapM_ finalizeForeignPtr)" "(const (pure ()))")) "subscription outputs release after exact decoding"+ ]+families "boundaries" =+ families "queue"+ <> [ control "unchanged-unit-control" unit "Public data contracts",+ control "unchanged-redirect-control" integration "construction failure releases callbacks: redirect",+ mutation "public-contract.queue" "notification-binary-payload-truncated" consumer (section "setConsumerQueueIOEvent ::" "setSaslCredentials ::" (replace "rdKafkaQueueIoEventEnable q (fromIntegral fd) (castPtr bytes) (fromIntegral size)" "rdKafkaQueueIoEventEnable q (fromIntegral fd) (castPtr bytes) 1")) "binary payloads retain every byte and empty payloads preserve records",+ mutation "public-contract.queue" "fixture-prefetch-observer-is-stale" "test-integration/Kafka/ConsumerStateSupport.hs" (replace " refresh\n" " pure ()\n") "binary payloads retain every byte and empty payloads preserve records",+ mutation "construction failure releases callbacks: redirect" "redirect-construction-error-suppressed" consumer (replace "kafkaErrorToMaybe . KafkaResponseError <$> rdKafkaPollSetConsumer k" "pure Nothing") "async construction failure releases callbacks: redirect",+ mutation "construction failure releases callbacks: redirect" "redirect-client-cleanup-deferred-to-gc" consumer (section "redErr <- redirectCallbacksPoll kafka" "Nothing -> do" (replace "closeConsumer kafka `finally` destroyConsumer kafka" "closeConsumer kafka")) "async construction failure releases callbacks: redirect",+ (mutation "Public data contracts" "immediate-error-show-adds-constructor" "src/Kafka/Producer/Types.hs" (replace "newtype ImmediateError = ImmediateError KafkaError\n deriving newtype (Eq, Show)" "newtype ImmediateError = ImmediateError KafkaError\n deriving stock (Eq, Show)") "producer records delivery variants and topic requests retain exact fields") {suite = unit, replay = True}+ ]+families "queue" =+ [ control "unchanged-control" integration "public-contract.queue",+ q "notification-watches-the-wrong-queue" (replace "readIORef qr" "pure Nothing") "wakes an idle consumer and stays quiet once disabled",+ q "notification-payload-is-empty" (replace "rdKafkaQueueIoEventEnable q (fromIntegral fd) (castPtr bytes) (fromIntegral size)" "rdKafkaQueueIoEventEnable q (fromIntegral fd) (castPtr bytes) 0") "wakes an idle consumer and stays quiet once disabled",+ q "notification-disable-is-ignored" (replace "Nothing -> rdKafkaQueueIoEventEnable q (-1) nullPtr 0" "Nothing -> pure ()") "wakes an idle consumer and stays quiet once disabled",+ fixture "fixture-descriptor-errors-swallowed" (section "fdRead ::" "drainPipe ::" (replace "Left err -> throwIO err" "Left _ -> pure BS.empty")) "empty pipes are idle but invalid descriptor errors are preserved",+ fixture "fixture-record-errors-swallowed" (section "drainQueue ::" "fdRead ::" (replace "Left err -> throwIO err" "Left _ -> go (n - 1)")) "native record errors are never treated as idle"+ ]+ where+ q label change test = mutation "public-contract.queue" label consumer (section "setConsumerQueueIOEvent ::" "setSaslCredentials ::" change) test+ fixture label change test = mutation "public-contract.queue" label "test-integration/Kafka/Integration/QueueEventTest.hs" change test+families "consumer-edges" =+ [ control "unchanged-metadata-control" integration "metadata-contract",+ control "unchanged-commit-control" integration "consumer-commit",+ control "unchanged-fencing-control" integration "public-contract.fatal",+ d "metadata-constructor-error-lost" (section "watermarkOffsets ::" "watermarkOffsets' ::" (replace "Left err -> return [Left err]" "Left _ -> return []")) "native topic-constructor failure survives metadata convenience queries",+ d "empty-metadata-manufactures-error" (section "watermarkOffsets ::" "watermarkOffsets' ::" (replace "[] -> return []" "[] -> return [Left (KafkaBadSpecification \"empty metadata\")]")) "empty native metadata remains empty and releases every result",+ d "timestamp-overall-error-ignored" (section "offsetsForTime ::" "allConsumerGroupsInfo ::" (replace "case res of" "case RdKafkaRespErrNoError of")) "timestamp lookup preserves native overall errors",+ d "watermark-native-error-ignored" (replace "return $ bimap KafkaResponseError toWatermark offs" "return $ Right (toWatermark (0, 0))") "watermark queries preserve unknown partition errors and empty provided metadata",+ c "message-commit-targets-partition-zero" (section "commitOffsetMessage ::" "storeOffsetMessage ::" (replace "[topicPartitionFromMessageForCommit m]" "[(topicPartitionFromMessageForCommit m) {tpPartition = PartitionId 0}]")),+ c "message-store-targets-partition-zero" (section "storeOffsetMessage ::" "storeOffsets ::" (replace "[topicPartitionFromMessageForCommit m]" "[(topicPartitionFromMessageForCommit m) {tpPartition = PartitionId 0}]"))+ ]+ where+ d label change test = mutation "metadata-contract" label "src/Kafka/Metadata.hs" change test+ c label change = mutation "consumer-commit" label consumer change "async message and stored commits preserve unrelated partition offsets"+families "inputs" =+ [ control "unchanged-control" integration "input-boundaries",+ i "input-topic-nul-guard-removed" (replace "Text.any (== '\\0') value" "False") "async assign rejects nul-topic",+ i "input-partition-upper-bound-removed" (replace "toInteger partition > toInteger (maxBound :: CInt)" "False") "async assign rejects overflow-partition",+ i "input-partition-lower-bound-removed" (replace "toInteger partition < toInteger (minBound :: CInt)" "False") "sync assign rejects underflow-partition",+ i "input-list-tail-not-validated" (replace "validateTopicPartitions = listToMaybe . mapMaybe invalid" "validateTopicPartitions = listToMaybe . mapMaybe invalid . take 1") "async string queries and subscription reject NUL before native effects",+ mutation "input-boundaries" "subscription-topic-guard-removed" consumer (section "newConsumer ::" "newAssignedConsumer ::" (replace "validateTopicPartitions [(topic, PartitionId 0) | topic <- Set.toList ts]" "Nothing")) "sync string queries and subscription reject NUL before native effects"+ ]+ where+ i label change test = mutation "input-boundaries" label "src/Kafka/Internal/Shared.hs" change test+families "runners" =+ [ control "unchanged-control" integration "deprecated-runners",+ mutation "deprecated-runners" "producer-wrapper-skips-flush" producer (replace "clProducer (Right prod) = closeProducer prod" "clProducer (Right _) = pure ()") "producer flushes after Thrown",+ mutation "deprecated-runners" "consumer-wrapper-skips-close" consumer (replace "clConsumer (Right kc) = maybeToLeft <$> closeConsumer kc" "clConsumer (Right _) = pure (Right ())") "sync consumer closes after Thrown",+ mutation "deprecated-runners" "consumer-wrapper-throws-construction-error" consumer (section "runConsumer ::" "newConsumer ::" (replace "runHandler (Left err) = return (Left err)" "runHandler (Left err) = throwIO err") . replace "import Control.Exception (bracket," "import Control.Exception (bracket, throwIO,") "sync consumer preserves native construction failure",+ mutation "deprecated-runners" "producer-wrapper-throws-handler-left" producer (section "runProducer ::" "newProducer ::" (replace "runHandler (Right prod) = f prod" "runHandler (Right prod) = f prod >>= either throwIO (pure . Right)") . replace "import Control.Exception (bracket," "import Control.Exception (bracket, throwIO,") "producer flushes after Refused"+ ]+families "consumer-commit" =+ [ control "unchanged-control" integration "consumer-commit",+ mutation "consumer-commit" "async-commit-submitted-synchronously" consumerConversion (replace "offsetCommitToBool OffsetCommitAsync = True" "offsetCommitToBool OffsetCommitAsync = False") "async commit modes preserve native flags callback offsets and broker state",+ mutation "consumer-commit" "message-commit-next-offset-lost" consumerConversion (replace "PartitionOffset $ moff + 1" "PartitionOffset moff") "async commit modes preserve native flags callback offsets and broker state",+ mutation "consumer-commit" "commit-callback-error-suppressed" "src/Kafka/Consumer/Callbacks.hs" (section "offsetCommitCallback ::" "-------------------------------------------------------------------------------" (replace "callback (KafkaConsumer (Kafka k') kc) (KafkaResponseError err) pls" "callback (KafkaConsumer (Kafka k') kc) (KafkaResponseError RdKafkaRespErrNoError) pls")) "sync empty commit requests preserve no-offset callbacks",+ mutation "consumer-commit" "commit-all-submits-empty-list" consumer (replace "newForeignPtr_ nullPtr >>= commitOffsets o k" "withPartitionList k (toNativeTopicPartitionList []) (commitOffsets o k)") "async commit modes preserve native flags callback offsets and broker state"+ ]+families "metadata-fields" =+ [ control "unchanged-control" integration "metadata-contract",+ d "broker-port-decoded-as-id" (replace "bmBrokerPort = port'RdKafkaMetadataBrokerT bm" "bmBrokerPort = id'RdKafkaMetadataBrokerT bm") "distinct native metadata fields retain exact identities and errors",+ d "replicas-decoded-as-isr" (replace "pmReplicas = BrokerId . fromIntegral <$> reps" "pmReplicas = BrokerId . fromIntegral <$> isrs") "distinct native metadata fields retain exact identities and errors",+ d "protocol-decoded-as-type" (replace "pr <- peekCText $ protocol'RdKafkaGroupInfoT gi" "pr <- peekCText $ protocolType'RdKafkaGroupInfoT gi") "async group identity lifecycle and supported native states"+ ]+ where+ d label change test = mutation "metadata-contract" label "src/Kafka/Metadata.hs" change test+families "metadata-partitions" =+ [ control "unchanged-control" integration "metadata-contract",+ d "watermark-partition-error-ignored" (replace "case pmError partition of" "case Nothing of") "provided metadata preserves partition failures in convenience helpers",+ d "provided-timestamp-partition-error-ignored" (replace "case listToMaybe (mapMaybe pmError (tmPartitions t)) of" "case Nothing of") "provided metadata preserves partition failures in convenience helpers",+ d "queried-timestamp-partition-error-ignored" (replace "mapMaybe tmError (kmTopics meta') <> concatMap (mapMaybe pmError . tmPartitions) (kmTopics meta')" "mapMaybe tmError (kmTopics meta')") "native metadata partition failures survive convenience helpers",+ d "group-entity-error-suppressed" (replace "giError = kafkaErrorToMaybe $ KafkaResponseError (err'RdKafkaGroupInfoT gi)" "giError = Nothing") "async group identity lifecycle and supported native states",+ mutation "metadata-contract" "group-wait-error-replaced" "src/Kafka/Internal/RdKafka.chs" (section "rdKafkaListGroups ::" "-------------------------------------------------------------------------------------------------" (replace "e -> return $ Left e" "e -> return $ Left RdKafkaRespErrTransport")) "group query timeout preserves initial metadata wait failure"+ ]+ where+ d label change test = mutation "metadata-contract" label "src/Kafka/Metadata.hs" change test+families "metadata-utf8" =+ [ control "unchanged-control" integration "metadata-contract",+ mutation "metadata-contract" "group-query-ascii-encoded" "src/Kafka/Internal/RdKafka.chs" (replace "Just strGrp -> withCString strGrp listGroups" "Just strGrp -> withCAString strGrp listGroups") "async group identity lifecycle and supported native states",+ d "group-identity-ascii-decoded" (replace "cid <- peekCText $ group'RdKafkaGroupInfoT gi" "cid <- peekCAText $ group'RdKafkaGroupInfoT gi"),+ d "member-client-ascii-decoded" (replace "cid <- peekCText $ clientId'RdKafkaGroupMemberInfoT mi" "cid <- peekCAText $ clientId'RdKafkaGroupMemberInfoT mi")+ ]+ where+ d label change = mutation "metadata-contract" label "src/Kafka/Metadata.hs" (change . replace "peekCText," "peekCText, peekCAText,") "async group identity lifecycle and supported native states"+families "data" =+ [ control "unchanged-unit-control" unit "Public data contracts",+ control "unchanged-native-control" integration "metadata-contract",+ (mutation "Public data contracts" "consumer-builder-key-wrong" "src/Kafka/Consumer/ConsumerProperties.hs" (replace "extraProp \"queued.max.messages.kbytes\"" "extraProp \"queued.max.messages.bytes\"") "consumer builders preserve exact settings and leave other fields unset") {suite = unit},+ (mutation "Public data contracts" "producer-debug-order-reversed" "src/Kafka/Producer/ProducerProperties.hs" (replace "kafkaDebugToText <$> d" "kafkaDebugToText <$> reverse d") "debug contexts preserve order duplicates and the empty-list identity") {suite = unit},+ mutation "metadata-contract" "group-member-byte-fields-swapped" "src/Kafka/Metadata.hs" (replace "gmiMetadata = pack mtd" "gmiMetadata = pack ass") "async group identity lifecycle and supported native states"+ ]+families "config" =+ [ control "unchanged-control" integration "config-strings",+ mutation "config-strings" "c-string-key-guard-removed" "src/Kafka/Internal/Setup.hs" (replace "Text.any (== '\\0') key" "False") "producer topic rejects NUL key",+ mutation "config-strings" "c-string-value-guard-removed" "src/Kafka/Internal/Setup.hs" (replace "Text.any (== '\\0') value" "False") "producer global rejects NUL value"+ ]+families other = error ("Unknown family: " <> other <> "; choose topic, producer, property, seek, callback, transaction, public, messages, rebalance, state, diagnostics, runtime, metadata, metadata-utf8, metadata-partitions, metadata-fields, consumer-commit, runners, inputs, consumer-edges, queue, boundaries, buffer, data or config")++replace :: String -> String -> String -> String+replace old new source = case [i | (i, rest) <- zip [0 ..] (tails source), old `isPrefixOf` rest] of+ [i] -> take i source <> new <> drop (i + length old) source+ _ -> error ("Mutation target must occur exactly once: " <> old)++section :: String -> String -> (String -> String) -> String -> String+section start end change source = case findIndex (isPrefixOf start) (tails source) of+ Nothing -> error ("Missing section: " <> start)+ Just first -> case findIndex (isPrefixOf end) (tails (drop first source)) of+ Nothing -> error ("Missing section end: " <> end)+ Just size -> take first source <> change (take size (drop first source)) <> drop (first + size) source++main :: IO ()+main =+ getArgs >>= \case+ ["--fingerprint"] -> getCurrentDirectory >>= fingerprint >>= putStrLn+ ["--check", family] -> do+ root <- getCurrentDirectory+ forM_ (families family) $ \m -> forM_ (edits m) $ \(path, change) -> do+ old <- readUtf8 (root </> path)+ let new = change old+ _ <- evaluate (length new)+ when (old == new) (die ("Mutation is unchanged: " <> name m))+ putStrLn "All mutation targets found."+ [family] -> runFamily family+ _ -> die "Usage: cabal run scripts/test-mutations.hs -- FAMILY | --check FAMILY | --fingerprint"++runFamily :: String -> IO ()+runFamily family = do+ root <- getCurrentDirectory+ before <- fingerprint root+ revision <- command root "git" ["rev-parse", "HEAD"]+ now <- getCurrentTime+ let base = root </> "dist-mutations"+ createDirectoryIfMissing True base+ (output, handle) <- openTempFile base (formatTime defaultTimeLocale "%Y%m%dT%H%M%SZ-" now <> family <> "-")+ hClose handle+ removeFile output+ createDirectory output+ _ <- command root "cabal" ["sdist", "--output-directory=" <> output]+ archives <- filter (isSuffixOf ".tar.gz") <$> listDirectory output+ archive <- case archives of [file] -> pure (output </> file); _ -> die "Expected one source archive"+ let package = output </> "source"+ createDirectory package+ _ <- command root "tar" ["-xzf", archive, "--strip-components=1", "-C", package]+ writeFile (package </> "cabal.project") "packages: .\n"+ let nonthreaded = family == "runtime"+ variants = families family+ originals <- forM (nub [path | m <- variants, (path, _) <- edits m]) $ \path -> (path,) <$> readUtf8 (package </> path)+ results <- forM variants $ \m -> do+ forM_ originals $ \(path, source) -> writeUtf8 (package </> path) source+ forM_ (edits m) $ \(path, change) -> case lookup path originals of+ Nothing -> die ("Missing original: " <> path)+ Just source -> do+ let changed = change source+ when (source == changed) (die ("Unchanged mutation: " <> name m))+ writeUtf8 (package </> path) changed+ let buildLog = output </> name m <> ".build.log"+ testLog = output </> name m <> ".test.log"+ withFile buildLog WriteMode $ \logHandle ->+ withCreateProcess+ (proc "cabal" (["build", suite m, "-f", "integration"] <> ["--ghc-options=-single-threaded -with-rtsopts=-T" | nonthreaded]))+ { cwd = Just package,+ std_out = UseHandle logHandle,+ std_err = UseHandle logHandle+ }+ $ \_ _ _ child ->+ waitForProcess child >>= \code -> unless (code == ExitSuccess) (die ("Build failed: " <> buildLog))+ binary <- command package "cabal" ["list-bin", suite m, "-f", "integration", "-v0"]+ environment <- getEnvironment+ let options = ["-p", patternText m] <> ["--quickcheck-replay=20261024" | replay m] <> ["--quickcheck-tests=1000" | replay m] <> ["+RTS"] <> ["-N2" | not nonthreaded] <> ["-RTS"]+ key = if maybe False (isPrefixOf "callback safety probe") (safety m) then "RDKAFKA_TEST_CALLBACK_SAFETY_PROBE" else "RDKAFKA_TEST_PRODUCER_SAFETY_PROBE"+ extra = [(key, name m) | safety m /= Nothing]+ process args = (proc binary args) {cwd = Just package, env = Just (extra <> environment)}+ (code, out, err) <- bounded (readCreateProcessWithExitCode (process options) "")+ writeFile testLog (out <> err)+ let intended = maybe False (`namedFailure` out) (expected m)+ invalidAccess = case (code, safety m) of (ExitFailure n, Just marker) -> n < 0 && marker `isInfixOf` err; _ -> False+ case expected m of+ Nothing -> unless (code == ExitSuccess && not ("All 0 tests" `isInfixOf` out)) (die ("Control failed: " <> testLog))+ Just _ -> unless ((code == ExitFailure 1 && intended) || invalidAccess) (die ("Intended regression did not fail: " <> testLog))+ token <-+ if replay m && expected m /= Nothing+ then do+ unless ("Falsified" `isInfixOf` out) (die ("Missing generated counterexample: " <> testLog))+ let marker = "Use --quickcheck-replay=\""+ value <- case findIndex (isPrefixOf marker) (tails out) of+ Nothing -> die ("Missing replay token: " <> testLog)+ Just i -> pure (takeWhile (/= '"') (drop (i + length marker) out))+ let replayOptions = [if "--quickcheck-replay=" `isPrefixOf` arg then "--quickcheck-replay=" <> value else arg | arg <- options]+ (again, replayOut, replayErr) <- bounded (readCreateProcessWithExitCode (process replayOptions) "")+ writeFile (output </> name m <> ".replay.log") (replayOut <> replayErr)+ unless (again == ExitFailure 1 && maybe False (`namedFailure` replayOut) (expected m) && "Falsified" `isInfixOf` replayOut) (die "Counterexample did not replay")+ pure (Just value)+ else pure Nothing+ putStrLn (name m <> ": " <> if expected m == Nothing then "control passed" else "intended regression failed")+ hFlush stdout+ pure $+ object+ [ "mutation" .= name m,+ "compiled" .= True,+ "exit" .= exitNumber code,+ "test" .= expected m,+ "command" .= (binary : options),+ "build_log" .= makeRelative root buildLog,+ "test_log" .= makeRelative root testLog,+ "replay_token" .= token+ ]+ forM_ originals $ \(path, source) -> writeUtf8 (package </> path) source+ after <- fingerprint root+ unless (before == after) (die "Candidate changed during mutations")+ archiveHash <- B.readFile archive >>= digest+ native <- command root "pkg-config" ["--modversion", "rdkafka"]+ BL.writeFile+ (output </> "results.json")+ ( encode+ ( object+ [ "revision" .= revision,+ "fingerprint" .= before,+ "family" .= family,+ "native" .= native,+ "archive_sha256" .= archiveHash,+ "results" .= results+ ]+ )+ )+ putStrLn ("Mutation evidence: " <> output </> "results.json")++namedFailure :: String -> String -> Bool+namedFailure label output = any check (lines output)+ where+ check line = maybe False (isPrefixOf "FAIL" . dropWhile isSpace) (stripPrefix (label <> ":") (dropWhile isSpace line))++exitNumber :: ExitCode -> Int+exitNumber ExitSuccess = 0+exitNumber (ExitFailure n) = n++bounded :: IO a -> IO a+bounded action = timeout 120000000 action >>= maybe (die "Mutation process exceeded 120 seconds") pure++command :: FilePath -> FilePath -> [String] -> IO String+command directory executable arguments = do+ (code, output, errors) <- readCreateProcessWithExitCode (proc executable arguments) {cwd = Just directory} ""+ unless (code == ExitSuccess) (die (unwords (executable : arguments) <> " failed: " <> errors <> output))+ pure (reverse (dropWhile isSpace (reverse output)))++readUtf8 :: FilePath -> IO String+readUtf8 path = T.unpack . TE.decodeUtf8 <$> B.readFile path++writeUtf8 :: FilePath -> String -> IO ()+writeUtf8 path = B.writeFile path . TE.encodeUtf8 . T.pack++fingerprint :: FilePath -> IO String+fingerprint root = do+ files <- concat <$> mapM (walk root) ["src", "test", "test-integration", "test-support", "scripts", "nix"]+ let optional = ["rdkafka-hs.cabal", "cabal.project", "cabal.project.local", "cabal.project.freeze", ".envrc", ".envrc.local", "flake.nix", "flake.lock", "flake.module.nix", "justfile"]+ present <- filterMFile root optional+ -- Match coverage_common.py's pathlib ordering, which compares path components.+ content <- forM (sortOn (T.splitOn "/" . T.pack) (nub (files <> present))) $ \path -> do+ bytes <- B.readFile (root </> path)+ pure (TE.encodeUtf8 (T.pack path) <> B.singleton 0 <> bytes <> B.singleton 0)+ digest (B.concat content)++walk :: FilePath -> FilePath -> IO [FilePath]+walk root relative = do+ exists <- doesDirectoryExist (root </> relative)+ if not exists+ then pure []+ else do+ entries <- filter (/= "__pycache__") <$> listDirectory (root </> relative)+ concat+ <$> forM+ entries+ ( \entry -> do+ let path = relative </> entry+ directory <- doesDirectoryExist (root </> path)+ if directory then walk root path else filterMFile root [path]+ )++filterMFile :: FilePath -> [FilePath] -> IO [FilePath]+filterMFile root files = concat <$> forM files (\file -> doesFileExist (root </> file) >>= \exists -> pure [file | exists])++digest :: B.ByteString -> IO String+digest bytes = withCreateProcess (proc "sha256sum" []) {std_in = CreatePipe, std_out = CreatePipe} $ \input output _ child ->+ case (input, output) of+ (Just writer, Just reader) -> do+ B.hPut writer bytes+ hClose writer+ result <- B.hGetContents reader+ code <- waitForProcess child+ unless (code == ExitSuccess) (die "sha256sum failed")+ pure (take 64 (BC.unpack result))+ _ -> die "Missing hash pipes"
+ src/Kafka/Callbacks.hs view
@@ -0,0 +1,57 @@+module Kafka.Callbacks+ ( errorCallback,+ logCallback,+ statsCallback,+ Callback,+ )+where++import Data.ByteString (ByteString)+import Kafka.Internal.RdKafka (rdKafkaConfSetErrorCb, rdKafkaConfSetLogCb, rdKafkaConfSetStatsCb)+import Kafka.Internal.Setup (Callback (..), KafkaConf (kcfgCallbackOwner), getRdKafkaConf)+import Kafka.Types (KafkaError (..), KafkaLogLevel (..))++-- | Add a callback for errors.+--+-- ==== __Examples__+--+-- Basic usage:+--+-- > 'setCallback' ('errorCallback' myErrorCallback)+-- >+-- > myErrorCallback :: 'KafkaError' -> String -> IO ()+-- > myErrorCallback kafkaError message = print $ show kafkaError <> "|" <> message+errorCallback :: (KafkaError -> String -> IO ()) -> Callback+errorCallback callback =+ let realCb _ err = callback (KafkaResponseError err)+ in Callback $ \k -> rdKafkaConfSetErrorCb (kcfgCallbackOwner k) (getRdKafkaConf k) realCb++-- | Add a callback for logs.+--+-- ==== __Examples__+--+-- Basic usage:+--+-- > 'setCallback' ('logCallback' myLogCallback)+-- >+-- > myLogCallback :: 'KafkaLogLevel' -> String -> String -> IO ()+-- > myLogCallback level facility message = print $ show level <> "|" <> facility <> "|" <> message+logCallback :: (KafkaLogLevel -> String -> String -> IO ()) -> Callback+logCallback callback =+ let realCb _ = callback . toEnum+ in Callback $ \k -> rdKafkaConfSetLogCb (kcfgCallbackOwner k) (getRdKafkaConf k) realCb++-- | Add a callback for stats. The passed ByteString contains an UTF-8 encoded JSON document and can e.g. be parsed using Data.Aeson.decodeStrict. For more information about the content of the JSON document see <https://github.com/edenhill/librdkafka/blob/master/STATISTICS.md>.+--+-- ==== __Examples__+--+-- Basic usage:+--+-- > 'setCallback' ('statsCallback' myStatsCallback)+-- >+-- > myStatsCallback :: String -> IO ()+-- > myStatsCallback stats = print $ show stats+statsCallback :: (ByteString -> IO ()) -> Callback+statsCallback callback =+ let realCb _ = callback+ in Callback $ \k -> rdKafkaConfSetStatsCb (kcfgCallbackOwner k) (getRdKafkaConf k) realCb
+ src/Kafka/Consumer.hs view
@@ -0,0 +1,929 @@+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TupleSections #-}++-----------------------------------------------------------------------------++-----------------------------------------------------------------------------++-- |+-- Module to consume messages from Kafka topics.+--+-- Here's an example of code to consume messages from a topic:+--+-- @+-- import Control.Exception (bracket)+-- import Control.Monad (replicateM_)+-- import Kafka.Consumer+--+-- -- Global consumer properties+-- consumerProps :: 'ConsumerProperties'+-- consumerProps = 'brokersList' ["localhost:9092"]+-- <> 'groupId' ('ConsumerGroupId' "consumer_example_group")+-- <> 'noAutoCommit'+-- <> 'logLevel' 'KafkaLogInfo'+--+-- -- Subscription to topics+-- consumerSub :: 'Subscription'+-- consumerSub = 'topics' ['TopicName' "kafka-client-example-topic"]+-- <> 'offsetReset' 'Earliest'+--+-- -- Running an example+-- runConsumerExample :: IO ()+-- runConsumerExample = do+-- res <- bracket mkConsumer clConsumer runHandler+-- print res+-- where+-- mkConsumer = 'newConsumer' consumerProps consumerSub+-- clConsumer (Left err) = pure (Left err)+-- clConsumer (Right kc) = (maybe (Right ()) Left) \<$\> 'closeConsumer' kc+-- runHandler (Left err) = pure (Left err)+-- runHandler (Right kc) = processMessages kc+--+-- -- Example polling 10 times before stopping+-- processMessages :: 'KafkaConsumer' -> IO (Either 'KafkaError' ())+-- processMessages kafka = do+-- replicateM_ 10 $ do+-- msg <- 'pollMessage' kafka ('Timeout' 1000)+-- putStrLn $ "Message: " <> show msg+-- err <- 'commitAllOffsets' 'OffsetCommit' kafka+-- putStrLn $ "Offsets: " <> maybe "Committed." show err+-- pure $ Right ()+-- @+module Kafka.Consumer+ ( KafkaConsumer,+ module X,+ runConsumer,+ newConsumer,+ newAssignedConsumer,+ assign,+ assignment,+ subscription,+ pausePartitions,+ resumePartitions,+ committed,+ position,+ seek,+ seekPartitions,+ pollMessage,+ pollMessageAttributed,+ pollConsumerEvents,+ pollMessageBatch,+ consumerFatalError,+ assignmentLost,+ consumerClosed,+ setConsumerQueueIOEvent,+ setSaslCredentials,+ commitOffsetMessage,+ commitAllOffsets,+ commitPartitionsOffsets,+ storeOffsets,+ storeOffsetMessage,+ rewindConsumer,+ closeConsumer,+ destroyConsumer,+ -- ReExport Types+ RdKafkaRespErrT (..),+ )+where++import Kafka.Internal.CallbackOwner (releaseUnattachedCallbacks)++import Control.Arrow (left, (&&&))+import Control.Concurrent (forkIO, modifyMVar, modifyMVarMasked_, rtsSupportsBoundThreads, withMVar)+import Control.Exception (bracket, finally, mask, mask_, onException)+import Control.Monad (forM_, unless, void, when)+import Control.Monad.IO.Class (MonadIO (liftIO))+import Control.Monad.Trans.Except (ExceptT (ExceptT), runExceptT)+import Data.Bifunctor (bimap, first)+import Data.ByteString qualified as BS+import Data.ByteString.Unsafe (unsafeUseAsCStringLen)+import Data.IORef (IORef, atomicModifyIORef', readIORef, writeIORef)+import Data.List (find)+import Data.Map qualified as M hiding (foldr, map)+import Data.Maybe (fromMaybe, isJust)+import Data.Sequence (ViewL (..), (|>))+import Data.Sequence qualified as Seq+import Data.Set (Set)+import Data.Set qualified as Set+import Data.Text (Text)+import Data.Text qualified as Text+import Foreign hiding (void)+import Kafka.Consumer.Callbacks (forwardPartitionsToMessageQueue)+import Kafka.Consumer.Convert (copyMessagePtr, copyMessagePtrAttributed, fromMessagePtr, fromMessagePtrAttributed, fromNativeTopicPartitionList'', nativeTopicPartitionErrors, offsetCommitToBool, offsetToInt64, toMap, toNativeTopicPartitionList, toNativeTopicPartitionList', topicPartitionFromMessageForCommit, withPolledMessage)+import Kafka.Consumer.Types (KafkaConsumer (..))+import Kafka.Internal.RdKafka (RdKafkaQueueTPtr, RdKafkaRespErrT (..), RdKafkaTPtr, RdKafkaTopicPartitionListTPtr, RdKafkaTypeT (..), newRdKafkaT, newRdKafkaTopicPartitionListT, newRdKafkaTopicT, rdKafkaAssign, rdKafkaAssignment, rdKafkaAssignmentLost, rdKafkaCommit, rdKafkaCommitted, rdKafkaConsumeBatchQueue, rdKafkaConsumeQueue, rdKafkaConsumerClose, rdKafkaConsumerClosed, rdKafkaConsumerPoll, rdKafkaErrorCode, rdKafkaErrorDestroy, rdKafkaFatalError, rdKafkaMessageDestroy, rdKafkaOffsetsStore, rdKafkaPausePartitions, rdKafkaPollSetConsumer, rdKafkaPosition, rdKafkaQueueDestroy, rdKafkaQueueGetConsumer, rdKafkaQueueIoEventEnable, rdKafkaQueueNew, rdKafkaResumePartitions, rdKafkaSeek, rdKafkaSeekPartitions, rdKafkaSetLogLevel, rdKafkaSubscribe, rdKafkaSubscription, rdKafkaTopicPartitionListAdd)+import Kafka.Internal.Setup (Callback (..), CallbackPollStatus (..), ClientLifecycle (..), Kafka (..), KafkaConf (..), KafkaProps (..), PendingMessage (..), PendingMessages (..), PendingTimestamp (..), TopicProps (..), discardPendingMessages, emptyPendingMessages, getKafkaConf, getRdKafka, getRdMsgQueue, kafkaConf, pendingMessagePartition, resetPendingMessages, setAllKafkaConfValues, topicConf)+import Kafka.Internal.Shared (kafkaErrorToMaybe, maybeToLeft, rdKafkaErrorToEither, setSaslCredentials', validateTopicPartitions)+import System.Posix.Types (Fd (..))++import Kafka.Consumer.ConsumerProperties as X+import Kafka.Consumer.Subscription as X+import Kafka.Consumer.Types as X hiding (KafkaConsumer)+import Kafka.Types as X++-- | Runs high-level kafka consumer.+-- A callback provided is expected to call 'pollMessage' when convenient.+{-# DEPRECATED runConsumer "Use 'newConsumer'/'closeConsumer' instead" #-}+runConsumer ::+ ConsumerProperties ->+ Subscription ->+ -- | A callback function to poll and handle messages+ (KafkaConsumer -> IO (Either KafkaError a)) ->+ IO (Either KafkaError a)+runConsumer cp sub f =+ bracket mkConsumer clConsumer runHandler+ where+ mkConsumer = newConsumer cp sub++ clConsumer (Left err) = return (Left err)+ clConsumer (Right kc) = maybeToLeft <$> closeConsumer kc++ runHandler (Left err) = return (Left err)+ runHandler (Right kc) = f kc++-- | Create a `KafkaConsumer`. This consumer must be correctly released using 'closeConsumer'.+--+-- With an empty subscription (@mempty@) the consumer never calls+-- @rd_kafka_subscribe@ and so never joins its consumer group; it reads only the+-- partitions given to 'assign'. 'newAssignedConsumer' names that case.+--+-- Async callback polling (the default) requires an executable linked with+-- @-threaded@. Without that runtime, choose 'CallbackPollModeSync'; requesting+-- async polling returns 'KafkaBadSpecification' before allocating a client.+newConsumer ::+ (MonadIO m) =>+ ConsumerProperties ->+ Subscription ->+ m (Either KafkaError KafkaConsumer)+newConsumer props (Subscription ts tp)+ | effectiveCallbackPollMode props == CallbackPollModeAsync && not rtsSupportsBoundThreads =+ pure (Left (KafkaBadSpecification "Async callback polling requires -threaded; select CallbackPollModeSync for a nonthreaded runtime."))+ | Just failure <- validateTopicPartitions [(topic, PartitionId 0) | topic <- Set.toList ts] = pure (Left failure)+ | otherwise = liftIO $ mask $ \restore -> do+ -- Both modes track rebalance invalidation. A later user callback replaces+ -- the no-op handler while retaining the same checked state transitions.+ let cp = setCallback (rebalanceCallback (\_ _ -> return ())) <> props+ kc@(KafkaConf kc' qref _ _ _ _) <- newConsumerConf cp+ flip onException (releaseUnattachedCallbacks (kcfgCallbackOwner kc)) $ restore $ do+ -- Validate subscription values as topic properties, then merge only their+ -- explicit keys so globally supplied topic settings remain effective.+ _ <- topicConf (TopicProps tp)+ setAllKafkaConfValues kc (KafkaProps tp)+ rdk <- newRdKafkaT (kcfgCallbackOwner kc) RdKafkaConsumer kc'+ case rdk of+ Left err ->+ return $+ Left (KafkaError err)+ Right rdk' -> do+ let kafka =+ KafkaConsumer (Kafka rdk') kc++ flip onException (destroyConsumer kafka) $ do+ when (effectiveCallbackPollMode props == CallbackPollModeAsync) $ mask_ $ do+ messageQueue <- rdKafkaQueueNew rdk'+ writeIORef qref (Just messageQueue)++ redErr <- redirectCallbacksPoll kafka+ case redErr of+ Just err -> do+ _ <- closeConsumer kafka `finally` destroyConsumer kafka+ return (Left err)+ Nothing -> do+ forM_ (cpLogLevel cp) $+ setConsumerLogLevel kafka++ subscribeError <-+ if Set.null ts+ then+ pure Nothing+ else+ subscribe kafka ts++ case subscribeError of+ Nothing -> do+ when (effectiveCallbackPollMode props == CallbackPollModeAsync) $+ runConsumerLoop kafka (Just $ Timeout 100)+ return (Right kafka)+ Just err -> do+ _ <- closeConsumer kafka `finally` destroyConsumer kafka+ return (Left err)++-- | Create a consumer that never subscribes and therefore never joins a group:+-- it reads only the partitions given to 'assign', from the offsets given there.+--+-- librdkafka still requires a @group.id@. With 'noAutoCommit', and without+-- committing offsets explicitly, the consumer sends neither JoinGroup nor+-- OffsetCommit, so the broker never records the group. Release the consumer with+-- 'closeConsumer' or 'destroyConsumer'.+newAssignedConsumer :: (MonadIO m) => ConsumerProperties -> m (Either KafkaError KafkaConsumer)+newAssignedConsumer props = newConsumer props mempty++-- | Polls a single message+--+-- If a /fatal/ error has been raised on this client, this returns+-- @Left ('KafkaResponseError' 'RdKafkaRespErrFatal')@ immediately, without+-- polling, and keeps doing so on every subsequent call. A fatal error is+-- permanent — librdkafka halts all consumer group activity for the client and+-- the only remedy is to close the consumer — so it is reported until the+-- consumer is closed rather than delivered once and forgotten.+--+-- This matters most in 'CallbackPollModeAsync'. There the application drains a+-- side queue, while consumer errors — including the fatal one — are delivered+-- only on librdkafka's consumer queue, which the background callback-poll loop+-- drains. Before this check existed, a fatal error was therefore unobservable+-- in async mode: the application simply polled an empty side queue forever. It+-- could not be observed through @error_cb@ either, because librdkafka returns+-- consumer errors to the application as messages and never routes them to the+-- error callback.+--+-- Use 'consumerFatalError' to recover the underlying cause of the fatal error+-- and its human readable description.+pollMessage ::+ (MonadIO m) =>+ KafkaConsumer ->+ -- | the timeout, in milliseconds+ Timeout ->+ -- | Left on error or timeout, right for success+ m (Either KafkaError (ConsumerRecord (Maybe BS.ByteString) (Maybe BS.ByteString)))+pollMessage c@(KafkaConsumer _ (KafkaConf _ qr _ _ _ _)) (Timeout ms) =+ liftIO $ withForeignPtr (getRdKafka c) $ \_ ->+ pollFatalError c >>= \case+ Just err -> pure (Left err)+ Nothing -> do+ servePendingCallbacks c+ nextPendingMessage c >>= \case+ Just message -> pure (first cmeError message)+ Nothing -> do+ mbq <- readIORef qr+ case mbq of+ Nothing -> fromMessagePtr (rdKafkaConsumerPoll (getRdKafka c) ms)+ Just q -> fromMessagePtr (rdKafkaConsumeQueue q ms)++-- | Like 'pollMessage', but an error comes with the topic, partition and offset+-- librdkafka attached to the errored message, so an application can tell, for+-- example, which partition a 'RdKafkaRespErrPartitionEof' belongs to.+--+-- A raised fatal error is reported first, as by 'pollMessage', as+-- @'ConsumerMessageError' ('KafkaResponseError' 'RdKafkaRespErrFatal')@ with+-- no origin; so is a poll timeout, as 'RdKafkaRespErrTimedOut'.+pollMessageAttributed ::+ (MonadIO m) =>+ KafkaConsumer ->+ -- | the timeout, in milliseconds+ Timeout ->+ m (Either ConsumerMessageError (ConsumerRecord (Maybe BS.ByteString) (Maybe BS.ByteString)))+pollMessageAttributed c@(KafkaConsumer _ (KafkaConf _ qr _ _ _ _)) (Timeout ms) =+ liftIO $ withForeignPtr (getRdKafka c) $ \_ ->+ pollFatalError c >>= \case+ Just err -> pure (Left (ConsumerMessageError err Nothing Nothing Nothing))+ Nothing -> do+ servePendingCallbacks c+ nextPendingMessage c >>= \case+ Just message -> pure message+ Nothing -> do+ mbq <- readIORef qr+ case mbq of+ Nothing -> fromMessagePtrAttributed (rdKafkaConsumerPoll (getRdKafka c) ms)+ Just q -> fromMessagePtrAttributed (rdKafkaConsumeQueue q ms)++-- | Polls up to 'BatchSize' messages.+-- A normal timeout returns an empty batch; native acquisition failures and+-- per-record decoding failures remain errors. Zero size+-- returns an empty batch; negative or unrepresentable sizes return a bad+-- specification. Native acquisition and message decoding errors remain errors.+--+-- This API is not available when 'CallbackPollMode' is set to 'CallbackPollModeSync'.+--+-- As with 'pollMessage', if a fatal error has been raised on this client this+-- returns a single-element batch+-- @['Left' ('KafkaResponseError' 'RdKafkaRespErrFatal')]@ immediately and keeps+-- doing so on every subsequent call. This fatal path is distinct from an+-- ordinary empty batch, which means "no messages+-- available", but a fatal error means the consumer is permanently dead.+pollMessageBatch ::+ (MonadIO m) =>+ KafkaConsumer ->+ Timeout ->+ BatchSize ->+ m [Either KafkaError (ConsumerRecord (Maybe BS.ByteString) (Maybe BS.ByteString))]+pollMessageBatch c@(KafkaConsumer _ (KafkaConf _ qr _ _ _ _)) (Timeout ms) (BatchSize b) =+ liftIO $ withForeignPtr (getRdKafka c) $ \_ ->+ pollFatalError c >>= \case+ Just err -> pure [Left err]+ Nothing -> do+ mbq <- readIORef qr+ case mbq of+ Nothing -> return [Left $ KafkaBadSpecification "Calling pollMessageBatch while CallbackPollMode is set to CallbackPollModeSync."]+ Just q+ | b < 0 || b > maxBound `div` sizeOf (nullPtr :: Ptr ()) ->+ pure [Left (KafkaBadSpecification "Batch size must be nonnegative and fit a native pointer array.")]+ | b == 0 -> pure []+ | otherwise -> do+ pollConsumerEvents c Nothing+ whileNoCallbackRunning c $+ bracket (rdKafkaConsumeBatchQueue q ms b) releaseBatch $ \case+ Left code -> pure [Left (KafkaResponseError code)]+ Right messages -> traverse copyMessagePtr messages+ where+ releaseBatch (Left _) = pure ()+ releaseBatch (Right messages) = mapM_ (\message -> withForeignPtr message rdKafkaMessageDestroy) messages++-- | Whether the current assignment was lost involuntarily+-- (@rd_kafka_assignment_lost@): the consumer was evicted from the group, for+-- example after its session timed out, rather than revoked by a normal+-- rebalance. Meaningful inside a rebalance callback handling a revocation, where+-- offsets for a lost assignment must not be committed.+assignmentLost :: (MonadIO m) => KafkaConsumer -> m Bool+assignmentLost c = liftIO $ rdKafkaAssignmentLost (getRdKafka c)++-- | Whether 'closeConsumer' has been called on this consumer+-- (@rd_kafka_consumer_closed@).+consumerClosed :: (MonadIO m) => KafkaConsumer -> m Bool+consumerClosed c = liftIO $ rdKafkaConsumerClosed (getRdKafka c)++-- | Asks librdkafka to write a payload to a file descriptor when records or+-- events become available on the queue 'pollMessage' and 'pollMessageBatch'+-- read from, so an application can wait with+-- 'Control.Concurrent.threadWaitRead' instead of polling on a timer+-- (@rd_kafka_queue_io_event_enable@). 'Nothing' disables the notification.+--+-- The queue is the consumer's message queue in 'CallbackPollModeAsync' and+-- librdkafka's consumer queue in 'CallbackPollModeSync'; in both cases it is+-- the final destination of the partition queues, which is where librdkafka+-- requires the event to be enabled. Enabling again replaces the previous+-- descriptor and payload. After 'closeConsumer' this does nothing.+--+-- librdkafka's rules:+--+-- * The descriptor must be non-blocking (for a pipe's write end, set+-- 'System.Posix.IO.NonBlockingRead', which sets @O_NONBLOCK@): librdkafka writes from+-- an internal thread and ignores write errors.+-- * IO-event and callback-event notification are mutually exclusive on one queue.+-- * librdkafka copies the payload before this function returns. The descriptor+-- stays owned by the caller: disable the notification (or destroy the+-- consumer) before closing it, or librdkafka may write to a reused descriptor.+--+-- The notification is edge-triggered. librdkafka writes when an op lands in the+-- empty queue, at most once until the queue is next polled, so a wake-up can+-- stand for several records and is not repeated while records remain. It can+-- also stand for something other than a record: a callback-serving event, an+-- error, or a wake-up with an empty queue. Wait like this:+--+-- 1. Enable the notification.+-- 2. Read and discard the pending payload bytes from the descriptor, then poll+-- until the queue is empty (records may have arrived before the notification+-- was enabled, or since the last wake-up).+-- 3. Wait, with a timeout, for the descriptor to become readable, and go back to+-- step 2.+--+-- Discard the bytes before polling, not after: a record that arrives after the+-- last poll writes a fresh wake-up, and discarding it afterwards would leave+-- the application waiting while that record sits in the queue.+--+-- A wake-up is not a promise of a record, and a fatal error need not produce+-- one: in 'CallbackPollModeAsync' a raised fatal error is delivered on+-- librdkafka's consumer queue, not on the message queue this watches. Bound+-- every wait with a timeout and poll (or call 'consumerFatalError') when it+-- expires, so a fatal consumer is noticed; never wait indefinitely.+--+-- Serialize this with 'closeConsumer' and assignment changes: do not call it+-- concurrently with them, nor from a librdkafka callback.+setConsumerQueueIOEvent :: (MonadIO m) => KafkaConsumer -> Maybe (Fd, BS.ByteString) -> m ()+setConsumerQueueIOEvent c@(KafkaConsumer _ (KafkaConf _ qr statusVar _ _ _)) event =+ liftIO $ withMVar statusVar $ \case+ CallbackPollDisabled -> pure ()+ CallbackPollEnabled ->+ readIORef qr >>= \case+ Just messageQueue -> enable messageQueue+ Nothing ->+ bracket (rdKafkaQueueGetConsumer (getRdKafka c)) releaseQueue $ \consumerQueue ->+ withForeignPtr consumerQueue $ \p -> unless (p == nullPtr) (enable consumerQueue)+ where+ enable q = case event of+ Nothing -> rdKafkaQueueIoEventEnable q (-1) nullPtr 0+ Just (Fd fd, payload) ->+ unsafeUseAsCStringLen payload $ \(bytes, size) ->+ rdKafkaQueueIoEventEnable q (fromIntegral fd) (castPtr bytes) (fromIntegral size)+ releaseQueue q = withForeignPtr q $ \p -> unless (p == nullPtr) (rdKafkaQueueDestroy q)++-- | Replaces the SASL username and password the consumer uses for future+-- authentications (@rd_kafka_sasl_set_credentials@); existing connections+-- are not re-authenticated. librdkafka stores the credentials whether or not+-- SASL is configured.+-- Embedded NUL in either credential returns 'KafkaBadSpecification' before+-- changing the native credentials.+setSaslCredentials ::+ (MonadIO m) =>+ KafkaConsumer ->+ -- | username+ Text ->+ -- | password+ Text ->+ m (Maybe KafkaError)+setSaslCredentials c username password = liftIO $ setSaslCredentials' c username password++-- | Returns the underlying cause of the fatal error raised on this client,+-- together with librdkafka's human readable description of it, or 'Nothing'+-- when no fatal error has been raised.+--+-- Fatal errors are permanent. They are raised for conditions from which the+-- client cannot recover — the canonical consumer example is a /fenced/ static+-- group member, where a second consumer joined with the same+-- @group.instance.id@ and the broker fenced this one. Once a fatal error is+-- raised librdkafka halts all consumer group activity: rejoins return+-- immediately and subscribes are treated as unsubscribes. The only remedy is to+-- close this consumer and create a new one.+--+-- 'pollMessage' and 'pollMessageBatch' report the /generic/ code+-- 'RdKafkaRespErrFatal' in-band, identically in both callback poll modes; this+-- function is how the specific cause — for example+-- @RdKafkaRespErrFencedInstanceId@ — is recovered for logging or alerting.+consumerFatalError :: (MonadIO m) => KafkaConsumer -> m (Maybe (KafkaError, Text))+consumerFatalError c = liftIO $ do+ (cause, description) <- rdKafkaFatalError (getRdKafka c)+ pure $ case cause of+ RdKafkaRespErrNoError -> Nothing+ _ -> Just (KafkaResponseError cause, description)++-- | Commit message's offset on broker for the message's partition.+commitOffsetMessage ::+ (MonadIO m) =>+ OffsetCommit ->+ KafkaConsumer ->+ ConsumerRecord k v ->+ m (Maybe KafkaError)+commitOffsetMessage _ _ record | Just failure <- validateTopicPartitions [(crTopic record, crPartition record)] = pure (Just failure)+commitOffsetMessage o k m =+ liftIO $ withPartitionList k (toNativeTopicPartitionList [topicPartitionFromMessageForCommit m]) (commitOffsets o k)++-- | Stores message's offset locally for the message's partition.+storeOffsetMessage ::+ (MonadIO m) =>+ KafkaConsumer ->+ ConsumerRecord k v ->+ m (Maybe KafkaError)+storeOffsetMessage _ record | Just failure <- validateTopicPartitions [(crTopic record, crPartition record)] = pure (Just failure)+storeOffsetMessage k m =+ liftIO $ withPartitionList k (toNativeTopicPartitionList [topicPartitionFromMessageForCommit m]) (commitOffsetsStore k)++-- | Stores offsets locally+storeOffsets ::+ (MonadIO m) =>+ KafkaConsumer ->+ [TopicPartition] ->+ m (Maybe KafkaError)+storeOffsets _ ps | Just failure <- validateTopicPartitions [(tpTopicName p, tpPartition p) | p <- ps] = pure (Just failure)+storeOffsets k ps =+ liftIO $ withPartitionList k (toNativeTopicPartitionList ps) (commitOffsetsStore k)++-- | Commit offsets for all currently assigned partitions.+commitAllOffsets ::+ (MonadIO m) =>+ OffsetCommit ->+ KafkaConsumer ->+ m (Maybe KafkaError)+commitAllOffsets o k =+ liftIO $ newForeignPtr_ nullPtr >>= commitOffsets o k++-- | Commit offsets for all currently assigned partitions.+commitPartitionsOffsets ::+ (MonadIO m) =>+ OffsetCommit ->+ KafkaConsumer ->+ [TopicPartition] ->+ m (Maybe KafkaError)+commitPartitionsOffsets _ _ ps | Just failure <- validateTopicPartitions [(tpTopicName p, tpPartition p) | p <- ps] = pure (Just failure)+commitPartitionsOffsets o k ps =+ liftIO $ withPartitionList k (toNativeTopicPartitionList ps) (commitOffsets o k)++-- | Assigns the consumer to consume from the given topics, partitions,+-- and offsets.+--+-- The new assignment replaces the previous one; an empty list unassigns every+-- partition. In 'CallbackPollModeAsync' each partition's queue is forwarded to+-- the queue 'pollMessage' reads before it is assigned, so no record is fetched+-- onto librdkafka's consumer queue, where the background loop would discard it.+-- Use this on a consumer from 'newAssignedConsumer'; on a subscribed consumer the+-- rebalance callback assigns partitions.+assign :: (MonadIO m) => KafkaConsumer -> [TopicPartition] -> m (Maybe KafkaError)+assign _ ps | Just failure <- validateTopicPartitions [(tpTopicName p, tpPartition p) | p <- ps] = pure (Just failure)+assign c@(KafkaConsumer (Kafka k) conf) ps = liftIO $ withForeignPtr k $ \_ -> mask_ $ bracket (toNativeTopicPartitionList ps) finalizeForeignPtr $ \tps -> do+ let partitions = (tpTopicName &&& tpPartition) <$> ps+ forwardPartitionsToMessageQueue c partitions+ err <- rdKafkaAssign k tps+ when (err == RdKafkaRespErrNoError) (resetPendingMessages conf)+ -- Reassigning a partition stops its fetcher, and librdkafka clears the+ -- partition queue's forwarding when that stop is processed, after+ -- rd_kafka_assign has returned. The stop requests and rd_kafka_assignment's+ -- request are served in order by librdkafka's main thread, so once+ -- rd_kafka_assignment returns the stops are done and the forwarding can be+ -- restored. Records fetched in between wait on the partition queue itself+ -- (librdkafka does not re-forward an application-forwarded queue) and move+ -- with the forward.+ isAsync <- isJust <$> getRdMsgQueue conf+ when (err == RdKafkaRespErrNoError && isAsync) $ do+ bracket (rdKafkaAssignment k) (mapM_ finalizeForeignPtr) (const (pure ()))+ forwardPartitionsToMessageQueue c partitions+ pure (kafkaErrorToMaybe (KafkaResponseError err))++-- | Returns current consumer's assignment+assignment :: (MonadIO m) => KafkaConsumer -> m (Either KafkaError (M.Map TopicName [PartitionId]))+assignment (KafkaConsumer (Kafka k) _) = liftIO $ withForeignPtr k $ \_ -> bracket (rdKafkaAssignment k) (mapM_ finalizeForeignPtr) $ \tpl -> do+ tps <- traverse fromNativeTopicPartitionList'' (left KafkaResponseError tpl)+ return $ tpMap <$> tps+ where+ tpMap ts = toMap $ (tpTopicName &&& tpPartition) <$> ts++-- | Returns current consumer's subscription+subscription :: (MonadIO m) => KafkaConsumer -> m (Either KafkaError [(TopicName, SubscribedPartitions)])+subscription (KafkaConsumer (Kafka k) _) = liftIO $ withForeignPtr k $ \_ -> bracket (rdKafkaSubscription k) (mapM_ finalizeForeignPtr) $ \tpl -> do+ tps <- traverse fromNativeTopicPartitionList'' (left KafkaResponseError tpl)+ return $ toSub <$> tps+ where+ toSub ts = M.toList $ subParts <$> tpMap ts+ tpMap ts = toMap $ (tpTopicName &&& tpPartition) <$> ts+ subParts [PartitionId (-1)] = SubscribedPartitionsAll+ subParts ps = SubscribedPartitions ps++-- | Pauses specified partitions on the current consumer. Reports the overall+-- native error or the first member error; successful members remain paused.+pausePartitions :: (MonadIO m) => KafkaConsumer -> [(TopicName, PartitionId)] -> m KafkaError+pausePartitions consumer ps = changePause consumer ps True rdKafkaPausePartitions++-- | Resumes specified partitions on the current consumer. Successful members+-- resume even when another member reports an error.+resumePartitions :: (MonadIO m) => KafkaConsumer -> [(TopicName, PartitionId)] -> m KafkaError+resumePartitions consumer ps = changePause consumer ps False rdKafkaResumePartitions++changePause :: (MonadIO m) => KafkaConsumer -> [(TopicName, PartitionId)] -> Bool -> (RdKafkaTPtr -> RdKafkaTopicPartitionListTPtr -> IO RdKafkaRespErrT) -> m KafkaError+changePause _ ps _ _ | Just failure <- validateTopicPartitions ps = pure failure+changePause consumer ps paused action = liftIO $ withForeignPtr (getRdKafka consumer) $ \_ -> mask_ $+ bracket (newRdKafkaTopicPartitionListT (length ps)) finalizeForeignPtr $ \list -> do+ mapM_ (\(TopicName topic, PartitionId partition) -> rdKafkaTopicPartitionListAdd list (Text.unpack topic) partition) ps+ code <- action (getRdKafka consumer) list+ when (code == RdKafkaRespErrNoError) $ do+ errors <- nativeTopicPartitionErrors list+ let successful = Set.fromList [partition | (partition, result) <- zip ps errors, result == RdKafkaRespErrNoError]+ atomicModifyIORef' (kcfgPendingMessages (getKafkaConf consumer)) $ \buffer ->+ let states = pendingPausedPartitions buffer+ updated = if paused then Set.union states successful else states `Set.difference` successful+ in (buffer {pendingPausedPartitions = updated}, ())+ fromMaybe (KafkaResponseError RdKafkaRespErrNoError) <$> partitionListError list code++-- | Seek a particular offset for each provided 'TopicPartition'+{-# DEPRECATED seek "Use seekPartitions instead" #-}+seek :: (MonadIO m) => KafkaConsumer -> Timeout -> [TopicPartition] -> m (Maybe KafkaError)+seek _ _ ps | Just failure <- validateTopicPartitions [(tpTopicName p, tpPartition p) | p <- ps] = pure (Just failure)+seek consumer@(KafkaConsumer (Kafka k) _) (Timeout timeout) tps =+ liftIO $ withForeignPtr k $ \_ ->+ either Just (const Nothing) <$> withTopics tps seekAll+ where+ -- Acquire all topics before seeking, preserving the deprecated wrapper's+ -- error order, and release every topic before returning to its caller.+ withTopics [] action = action []+ withTopics (tp : rest) action =+ topicPair tp >>= \case+ Left err -> pure (Left err)+ Right owned ->+ bracket (pure owned) (\(ptr, _, _, _) -> finalizeForeignPtr ptr) $ \_ ->+ withTopics rest (\remaining -> action (owned : remaining))++ seekAll pairs =+ runExceptT $+ mapM_ (\(kt, topic, p, o) -> ExceptT (rdSeek kt topic p o)) pairs++ rdSeek kt topic partition@(PartitionId p) o = mask_ $ do+ result <- rdKafkaSeek kt (fromIntegral p) (offsetToInt64 o) timeout+ when (result == RdKafkaRespErrNoError) (discardPendingMessages (getKafkaConf consumer) (Set.singleton (topic, partition)))+ pure (rdKafkaErrorToEither result)++ topicPair tp = do+ let (TopicName tn) = tpTopicName tp+ nt <- newRdKafkaTopicT k (Text.unpack tn) Nothing+ return $ bimap KafkaError (,tpTopicName tp,tpPartition tp,tpOffset tp) (first Text.pack nt)++-- | Seek already assigned partitions to their requested offsets. A nonzero+-- timeout waits for the fetcher update and discards prefetched records from the+-- old position. The overall native error takes precedence; otherwise the first+-- failed partition in input order is returned. Successful members of a mixed+-- request are not rolled back when another member fails.+--+-- A zero timeout initiates the operation without waiting for completion. Pending+-- member markers are ignored only in that case; immediate errors are returned.+-- 'PartitionOffsetStored' is not supported by native seek (use 'rewindConsumer').+seekPartitions :: (MonadIO m) => KafkaConsumer -> [TopicPartition] -> Timeout -> m (Maybe KafkaError)+seekPartitions _ ps _ | Just failure <- validateTopicPartitions [(tpTopicName p, tpPartition p) | p <- ps] = pure (Just failure)+seekPartitions consumer@(KafkaConsumer (Kafka k) _) ps (Timeout timeout) = liftIO $ withForeignPtr k $ \_ -> mask_ $ bracket (toNativeTopicPartitionList ps) finalizeForeignPtr $ \tps -> do+ err <- bracket (rdKafkaSeekPartitions k tps timeout) rdKafkaErrorDestroy rdKafkaErrorCode+ case rdKafkaErrorToEither err of+ Left failure -> pure (Just failure)+ Right () -> do+ errors <- nativeTopicPartitionErrors tps+ let initiated = Set.fromList [(tpTopicName partition, tpPartition partition) | (partition, code) <- zip ps errors, code == RdKafkaRespErrNoError || code == RdKafkaRespErrInProgress]+ discardPendingMessages (getKafkaConf consumer) initiated+ pure $ KafkaResponseError <$> find substantive errors+ where+ substantive code =+ code /= RdKafkaRespErrNoError+ && (timeout /= 0 || code /= RdKafkaRespErrInProgress)++-- | Retrieve committed offsets for topics+partitions.+committed :: (MonadIO m) => KafkaConsumer -> Timeout -> [(TopicName, PartitionId)] -> m (Either KafkaError [TopicPartition])+committed _ _ ps | Just failure <- validateTopicPartitions ps = pure (Left failure)+committed (KafkaConsumer (Kafka k) _) (Timeout timeout) tps = liftIO $ withForeignPtr k $ \_ -> bracket (toNativeTopicPartitionList' tps) finalizeForeignPtr $ \ntps -> do+ failure <- partitionListError ntps =<< rdKafkaCommitted k ntps timeout+ case failure of+ Nothing -> Right <$> fromNativeTopicPartitionList'' ntps+ Just err -> pure (Left err)++-- | Retrieve current positions (last consumed message offset+1) for the current running instance of the consumer.+-- If the current consumer hasn't received any messages for a given partition, 'PartitionOffsetInvalid' is returned.+position :: (MonadIO m) => KafkaConsumer -> [(TopicName, PartitionId)] -> m (Either KafkaError [TopicPartition])+position _ ps | Just failure <- validateTopicPartitions ps = pure (Left failure)+position (KafkaConsumer (Kafka k) _) tps = liftIO $ withForeignPtr k $ \_ -> bracket (toNativeTopicPartitionList' tps) finalizeForeignPtr $ \ntps -> do+ failure <- partitionListError ntps =<< rdKafkaPosition k ntps+ case failure of+ Nothing -> Right <$> fromNativeTopicPartitionList'' ntps+ Just err -> pure (Left err)++-- | Polls the provided kafka consumer for events.+--+-- Events will cause application provided callbacks to be called.+--+-- The 'Timeout' argument specifies the maximum amount of time+-- (in milliseconds) that the call will block waiting for events.+--+-- In async mode a background thread serves callbacks periodically. In sync+-- mode 'pollMessage' serves callbacks during its native poll. Calling this+-- function explicitly in sync mode copies any returned records or attributed+-- errors into a private FIFO for the next application polls; native messages+-- are released before this call returns. Empty polls add nothing to the FIFO.+--+-- In async mode application records use separate partition queues. Any message+-- returned on the callback queue is discarded and destroyed. Fatal errors stay+-- observable through the public polling APIs and 'consumerFatalError'.+pollConsumerEvents :: KafkaConsumer -> Maybe Timeout -> IO ()+pollConsumerEvents k timeout =+ void . withCallbackPollEnabled k $ pollConsumerEvents' k timeout++-- | Closes the consumer gracefully (@rd_kafka_consumer_close@): stops the+-- background callback-poll loop, releases the message queue, and leaves the+-- consumer group, committing offsets if auto-commit is enabled and serving the+-- final rebalance callback. Against an unresponsive broker this can block; use+-- 'destroyConsumer' to tear the client down within a bound.+--+-- Closing does not free the librdkafka client; its finalizer does that when+-- the consumer is garbage collected, or 'destroyConsumer' does it now. Closing+-- again, or after 'destroyConsumer', does nothing and returns 'Nothing'.+--+-- See 'newConsumer'+closeConsumer :: (MonadIO m) => KafkaConsumer -> m (Maybe KafkaError)+closeConsumer (KafkaConsumer (Kafka k) (KafkaConf _ qr statusVar lifecycle _ pending)) = liftIO $+ modifyMVar lifecycle $ \case+ ClientOpen -> do+ -- because closing the consumer will raise callbacks,+ -- prevent the async loop from doing it at the same time+ res <- modifyMVar statusVar $ \_ -> do+ -- librdkafka says:+ -- Prior to destroying the client instance, loose your reference to the+ -- background queue by calling rd_kafka_queue_destroy()+ atomicModifyIORef' pending (const (emptyPendingMessages, ()))+ releaseMessageQueue qr+ res <- kafkaErrorToMaybe . KafkaResponseError <$> rdKafkaConsumerClose k+ pure (CallbackPollDisabled, res)+ pure (ClientClosed, res)+ state -> pure (state, Nothing)++-- | Destroys the consumer's librdkafka client now, synchronously and exactly+-- once: stops the background callback-poll loop (waiting for a poll in+-- progress), releases the message queue, and runs the client's finalizer,+-- @rd_kafka_destroy_flags@ with @RD_KAFKA_DESTROY_F_NO_CONSUMER_CLOSE@. When it+-- returns, librdkafka's threads have stopped and its broker connections are+-- closed, without waiting for a garbage collection.+--+-- It does not leave the consumer group gracefully or commit offsets; call+-- 'closeConsumer' first for that. Destroying again, or closing after+-- destroying, does nothing; concurrent calls wait until the destruction has+-- finished. If a destroy is interrupted by an asynchronous exception, a later+-- call completes it.+--+-- Every other operation on the consumer is invalid once this has been called,+-- including 'consumerClosed'. Serialize normal operations with teardown, and do+-- not call this from a librdkafka callback.+destroyConsumer :: (MonadIO m) => KafkaConsumer -> m ()+destroyConsumer (KafkaConsumer (Kafka k) (KafkaConf _ qr statusVar lifecycle _ pending)) = liftIO $+ modifyMVarMasked_ lifecycle $ \case+ ClientDestroyed -> pure ClientDestroyed+ _ -> do+ -- Each step is safe to repeat, so a destroy interrupted before it+ -- published ClientDestroyed can be completed by the next call.+ modifyMVarMasked_ statusVar (const (pure CallbackPollDisabled))+ atomicModifyIORef' pending (const (emptyPendingMessages, ()))+ releaseMessageQueue qr+ finalizeForeignPtr k+ pure ClientDestroyed++-- | Release the async message queue, if any, exactly once.+releaseMessageQueue :: IORef (Maybe RdKafkaQueueTPtr) -> IO ()+releaseMessageQueue qr = atomicModifyIORef' qr (Nothing,) >>= mapM_ rdKafkaQueueDestroy++-- | Rewind the current assignment to the committed next offsets, or beginning+-- when no offset is committed. Assignment, lookup and seek failures propagate.+-- Lookup and seek are separate operations: callers must serialize assignment+-- changes when a stable assignment is required. Successful seek members are+-- not rolled back if another member fails.+--+-- Follows @mori://confluentinc/librdkafka@, project-relative+-- @librdkafka/examples/transactions.c@ (source artifact URI pending).+rewindConsumer ::+ (MonadIO m) =>+ KafkaConsumer ->+ Timeout ->+ m (Maybe KafkaError)+rewindConsumer c to = liftIO $ do+ ret <- assignment c+ case ret of+ Left err -> pure $ Just err+ Right os -> do+ if M.size os == 0+ -- No current assignment to rewind+ then pure Nothing+ else do+ let tps = foldr (\(t, ps) acc -> map (t,) ps ++ acc) [] $ M.toList os+ ret' <- committed c to tps+ case ret' of+ Left err -> pure $ Just err+ Right ps -> do+ -- Seek to committed offset, or start of partition if no+ -- committed offset is available.+ let ps' = map checkOffsets ps+ seekPartitions c ps' to+ where+ checkOffsets :: TopicPartition -> TopicPartition+ checkOffsets tp+ | isUncommitedOffset $ tpOffset tp =+ tp {tpOffset = PartitionOffsetBeginning}+ | otherwise = tp++ isUncommitedOffset :: PartitionOffset -> Bool+ isUncommitedOffset (PartitionOffset _) = False+ isUncommitedOffset _ = True++-----------------------------------------------------------------------------+newConsumerConf :: ConsumerProperties -> IO KafkaConf+newConsumerConf ConsumerProperties {cpProps = m, cpCallbacks = cbs} = do+ conf <- kafkaConf (KafkaProps m)+ (forM_ cbs (\(Callback setCb) -> setCb conf) >> pure conf)+ `onException` releaseUnattachedCallbacks (kcfgCallbackOwner conf)++-- | Subscribes to a given list of topics.+--+-- Wildcard (regex) topics are supported by the /librdkafka/ assignor:+-- any topic name in the topics list that is prefixed with @^@ will+-- be regex-matched to the full list of topics in the cluster and matching+-- topics will be added to the subscription list.+subscribe :: KafkaConsumer -> Set TopicName -> IO (Maybe KafkaError)+subscribe (KafkaConsumer (Kafka k) _) ts = withForeignPtr k $ \_ -> bracket (newRdKafkaTopicPartitionListT (length ts)) finalizeForeignPtr $ \pl -> do+ mapM_ (\(TopicName t) -> rdKafkaTopicPartitionListAdd pl (Text.unpack t) (-1)) (Set.toList ts)+ res <- KafkaResponseError <$> rdKafkaSubscribe k pl+ return $ kafkaErrorToMaybe res++-- The caller's input list is borrowed by native operations. Release its+-- private native references before the client can be finalized or destroyed.+withPartitionList :: KafkaConsumer -> IO RdKafkaTopicPartitionListTPtr -> (RdKafkaTopicPartitionListTPtr -> IO a) -> IO a+withPartitionList consumer acquire action = withForeignPtr (getRdKafka consumer) $ \_ ->+ bracket acquire finalizeForeignPtr action++commitOffsets :: OffsetCommit -> KafkaConsumer -> RdKafkaTopicPartitionListTPtr -> IO (Maybe KafkaError)+commitOffsets o (KafkaConsumer (Kafka k) _) pl =+ kafkaErrorToMaybe . KafkaResponseError <$> rdKafkaCommit k pl (offsetCommitToBool o)++commitOffsetsStore :: KafkaConsumer -> RdKafkaTopicPartitionListTPtr -> IO (Maybe KafkaError)+commitOffsetsStore (KafkaConsumer (Kafka k) _) pl =+ partitionListError pl =<< rdKafkaOffsetsStore k pl++-- Preserve an overall error first, then the first failing member in input order.+-- Successful members of a mixed native request are not rolled back.+partitionListError :: RdKafkaTopicPartitionListTPtr -> RdKafkaRespErrT -> IO (Maybe KafkaError)+partitionListError partitions overall = case rdKafkaErrorToEither overall of+ Left failure -> pure (Just failure)+ Right () -> fmap KafkaResponseError . find (/= RdKafkaRespErrNoError) <$> nativeTopicPartitionErrors partitions++setConsumerLogLevel :: KafkaConsumer -> KafkaLogLevel -> IO ()+setConsumerLogLevel (KafkaConsumer (Kafka k) _) level =+ liftIO $ rdKafkaSetLogLevel k (fromEnum level)++redirectCallbacksPoll :: KafkaConsumer -> IO (Maybe KafkaError)+redirectCallbacksPoll (KafkaConsumer (Kafka k) _) =+ kafkaErrorToMaybe . KafkaResponseError <$> rdKafkaPollSetConsumer k++runConsumerLoop :: KafkaConsumer -> Maybe Timeout -> IO ()+runConsumerLoop k timeout =+ when rtsSupportsBoundThreads $ void $ forkIO go+ where+ go = do+ st <- withCallbackPollEnabled k (pollConsumerEvents' k timeout)+ case st of+ CallbackPollEnabled -> go+ CallbackPollDisabled -> pure ()++whileNoCallbackRunning :: KafkaConsumer -> IO a -> IO a+whileNoCallbackRunning k f = do+ let statusVar = kcfgCallbackPollStatus (getKafkaConf k)+ withMVar statusVar $ \_ -> f++withCallbackPollEnabled :: KafkaConsumer -> IO () -> IO CallbackPollStatus+withCallbackPollEnabled k f = do+ let statusVar = kcfgCallbackPollStatus (getKafkaConf k)+ withMVar statusVar $ \case+ CallbackPollEnabled -> f >> pure CallbackPollEnabled+ CallbackPollDisabled -> pure CallbackPollDisabled++-- | Polls the consumer queue to let librdkafka serve callback-type events, and+-- releases whatever native message that poll hands back. Sync-mode results+-- are copied into the application FIFO before release.+--+-- Most events on the consumer queue are served as callbacks inside librdkafka+-- during the poll itself and nothing is returned. Two kinds of event are+-- instead /returned/ to the caller as a message: a fetched record that raced a+-- partition-queue redirect, and any consumer error. This function is only+-- interested in the callback side effects, so it discards both — but it must+-- still free them. The returned foreign pointer carries no finalizer, so+-- dropping it without calling 'rdKafkaMessageDestroy' leaks the underlying C+-- message; before this was fixed, every consumer error and every raced record+-- leaked, on a loop that runs every 100 ms.+--+-- Discarding a returned consumer error costs no observability: fatal errors are+-- reported in-band by 'pollMessage' and 'pollMessageBatch', which read+-- librdkafka's fatal state directly rather than relying on this loop having+-- seen the message, and non-fatal consumer errors were never visible from here+-- to begin with (librdkafka does not route them to @error_cb@).+pollConsumerEvents' :: KafkaConsumer -> Maybe Timeout -> IO ()+pollConsumerEvents' k timeout = withForeignPtr (getRdKafka k) $ \_ -> do+ let (Timeout tm) = fromMaybe (Timeout 0) timeout+ queue <- getRdMsgQueue k+ withPolledMessage (rdKafkaConsumerPoll (getRdKafka k) tm) $ \message ->+ case queue of+ Just _ -> pure ()+ Nothing -> withForeignPtr message $ \raw -> when (raw /= nullPtr) $ do+ copied <- copyMessagePtrAttributed message+ case copied of+ Left (ConsumerMessageError (KafkaResponseError RdKafkaRespErrFatal) _ _ _) -> pure ()+ _ -> atomicModifyIORef' (kcfgPendingMessages (getKafkaConf k)) $ \buffer ->+ (buffer {bufferedMessages = bufferedMessages buffer |> packPendingMessage copied}, ())++-- A cached result must not bypass ready rebalance/commit callbacks or stop+-- updating native poll liveness while the application drains copied records.+servePendingCallbacks :: KafkaConsumer -> IO ()+servePendingCallbacks consumer =+ getRdMsgQueue consumer >>= \case+ Just _ -> pure ()+ Nothing -> do+ buffer <- readIORef (kcfgPendingMessages (getKafkaConf consumer))+ case Seq.viewl (bufferedMessages buffer) of+ EmptyL -> pure ()+ _ -> pollConsumerEvents consumer (Just (Timeout 0))++-- Callback polling copies messages before releasing their native owners. The+-- buffer stores no client references, so it cannot form a callback/client cycle.+packPendingMessage :: Either ConsumerMessageError (ConsumerRecord (Maybe BS.ByteString) (Maybe BS.ByteString)) -> PendingMessage+packPendingMessage = \case+ Left (ConsumerMessageError failure topic partition offset) -> PendingMessageError failure topic partition (unOffset <$> offset)+ Right (ConsumerRecord topic partition (Offset offset) timestamp headers key value) ->+ PendingMessageRecord topic partition offset (packTimestamp timestamp) headers key value+ where+ packTimestamp NoTimestamp = PendingNoTimestamp+ packTimestamp (CreateTime time) = PendingCreateTime time+ packTimestamp (LogAppendTime time) = PendingLogAppendTime time++nextPendingMessage :: KafkaConsumer -> IO (Maybe (Either ConsumerMessageError (ConsumerRecord (Maybe BS.ByteString) (Maybe BS.ByteString))))+nextPendingMessage consumer = atomicModifyIORef' (kcfgPendingMessages (getKafkaConf consumer)) $ \buffer ->+ let ready = maybe True (`Set.notMember` pendingPausedPartitions buffer) . pendingMessagePartition+ (held, available) = Seq.breakl ready (bufferedMessages buffer)+ in case Seq.viewl available of+ EmptyL -> (buffer, Nothing)+ value :< rest -> (buffer {bufferedMessages = held Seq.>< rest}, Just (unpack value))+ where+ unpack (PendingMessageError failure topic partition offset) = Left (ConsumerMessageError failure topic partition (Offset <$> offset))+ unpack (PendingMessageRecord topic partition offset timestamp headers key value) =+ Right (ConsumerRecord topic partition (Offset offset) (unpackTimestamp timestamp) headers key value)+ unpackTimestamp PendingNoTimestamp = NoTimestamp+ unpackTimestamp (PendingCreateTime time) = CreateTime time+ unpackTimestamp (PendingLogAppendTime time) = LogAppendTime time++-- | The in-band error a poll must report because a fatal error has been raised+-- on this client, or 'Nothing' when the client is healthy.+--+-- Reports the generic 'RdKafkaRespErrFatal' rather than the underlying cause so+-- that both callback poll modes deliver an identical value: in+-- 'CallbackPollModeSync' librdkafka itself hands exactly this code to the+-- application as a consumer error, and callers should not have to discriminate+-- by poll mode when classifying an error as fatal. 'consumerFatalError' recovers+-- the cause when it is wanted.+pollFatalError :: KafkaConsumer -> IO (Maybe KafkaError)+pollFatalError c = do+ (cause, _description) <- rdKafkaFatalError (getRdKafka c)+ pure $ case cause of+ RdKafkaRespErrNoError -> Nothing+ _ -> Just (KafkaResponseError RdKafkaRespErrFatal)
+ src/Kafka/Consumer/Callbacks.hs view
@@ -0,0 +1,134 @@+{-# LANGUAGE BangPatterns #-}++module Kafka.Consumer.Callbacks+ ( rebalanceCallback,+ offsetCommitCallback,+ forwardPartitionsToMessageQueue,+ module X,+ )+where++import Control.Arrow ((&&&))+import Control.Exception (bracket, mask_, throwIO)+import Control.Monad (forM_, void)+import Foreign.ForeignPtr (finalizeForeignPtr, newForeignPtr_, withForeignPtr)+import Foreign.Ptr (nullPtr)+import Kafka.Callbacks as X+import Kafka.Consumer.Convert (fromNativeTopicPartitionList', fromNativeTopicPartitionList'')+import Kafka.Consumer.Types (KafkaConsumer (..), RebalanceEvent (..), TopicPartition (..))+import Kafka.Internal.CallbackOwner (containCallbackException)+import Kafka.Internal.RdKafka+import Kafka.Internal.Setup (Callback (..), HasKafka (..), HasKafkaConf (..), Kafka (..), KafkaConf (..), forgetPendingPartitions, getRdMsgQueue, resetPendingMessages)+import Kafka.Internal.Shared (rdKafkaErrorToEither)+import Kafka.Types (KafkaError (..), PartitionId (..), TopicName (..))++import Data.Set qualified as Set+import Data.Text qualified as Text++-- | Sets a callback that is called when rebalance is needed.+rebalanceCallback :: (KafkaConsumer -> RebalanceEvent -> IO ()) -> Callback+rebalanceCallback callback =+ Callback $ \kc@(KafkaConf con _ _ _ _ _) -> rdKafkaConfSetRebalanceCb (kcfgCallbackOwner kc) con (realCb kc)+ where+ realCb kc k err pl = do+ k' <- newForeignPtr_ k+ pls <- newForeignPtr_ pl+ setRebalanceCallback callback (KafkaConsumer (Kafka k') kc) (KafkaResponseError err) pls++-- | Sets a callback that is called when rebalance is needed.+--+-- The results of automatic or manual offset commits will be scheduled+-- for this callback and is served by 'Kafka.Consumer.pollMessage'.+--+-- If no partitions had valid offsets to commit this callback will be called+-- with 'KafkaResponseError' 'RdKafkaRespErrNoOffset' which is not to be considered+-- an error.+offsetCommitCallback :: (KafkaConsumer -> KafkaError -> [TopicPartition] -> IO ()) -> Callback+offsetCommitCallback callback =+ Callback $ \kc@(KafkaConf conf _ _ _ _ _) -> rdKafkaConfSetOffsetCommitCb (kcfgCallbackOwner kc) conf (realCb kc)+ where+ realCb kc k err pl = do+ k' <- newForeignPtr_ k+ pls <- fromNativeTopicPartitionList' pl+ callback (KafkaConsumer (Kafka k') kc) (KafkaResponseError err) pls++-------------------------------------------------------------------------------++-- | In 'Kafka.Consumer.ConsumerProperties.CallbackPollModeAsync', forward each+-- partition's queue to the consumer's message queue, which 'Kafka.Consumer.pollMessage'+-- reads; without this, records stay on librdkafka's consumer queue, where the+-- background callback-poll loop discards them. Does nothing in sync mode.+--+-- The forwarding outlives the partition-queue reference, which is released+-- here rather than left to the garbage collector. Forward before assigning a+-- partition, or pause it around forwarding, so no record is fetched onto the+-- consumer queue in between.+forwardPartitionsToMessageQueue :: KafkaConsumer -> [(TopicName, PartitionId)] -> IO ()+forwardPartitionsToMessageQueue k ps = do+ mbq <- getRdMsgQueue (getKafkaConf k)+ forM_ mbq $ \mq -> forM_ ps $ \(t, p) -> redirectPartitionQueue (getKafka k) t p mq++redirectPartitionQueue :: Kafka -> TopicName -> PartitionId -> RdKafkaQueueTPtr -> IO ()+redirectPartitionQueue (Kafka k) (TopicName t) (PartitionId p) q = withForeignPtr k $ \_ -> do+ mpq <- rdKafkaQueueGetPartition k (Text.unpack t) p+ case mpq of+ Nothing -> return ()+ Just pq -> rdKafkaQueueForward pq q >> finalizeForeignPtr pq++setRebalanceCallback ::+ (KafkaConsumer -> RebalanceEvent -> IO ()) ->+ KafkaConsumer ->+ KafkaError ->+ RdKafkaTopicPartitionListTPtr ->+ IO ()+setRebalanceCallback f k e pls = do+ ps <- fromNativeTopicPartitionList'' pls+ let assignment = (tpTopicName &&& tpPartition) <$> ps+ let (Kafka kptr) = getKafka k++ case e of+ KafkaResponseError RdKafkaRespErrAssignPartitions -> do+ containCallbackException $ f k (RebalanceBeforeAssign assignment)+ protocol <- rdKafkaRebalanceProtocol kptr+ mask_ $+ if protocol == "COOPERATIVE"+ then checkRebalanceError (rdKafkaIncrementalAssign kptr pls) >> forgetPendingPartitions (getKafkaConf k) (Set.fromList assignment)+ else checkRebalanceCode (rdKafkaAssign kptr pls) >> resetPendingMessages (getKafkaConf k)++ mbq <- getRdMsgQueue $ getKafkaConf k+ case mbq of+ Nothing -> pure ()+ Just _ -> do+ {- Magnus Edenhill:+ If you redirect after assign() it means some messages may be forwarded to the single consumer queue,+ so either do it before assign() or do: assign(); pause(); redirect; resume()+ -}+ void $ rdKafkaPausePartitions kptr pls+ forwardPartitionsToMessageQueue k assignment+ void $ rdKafkaResumePartitions kptr pls++ containCallbackException $ f k (RebalanceAssign assignment)+ KafkaResponseError RdKafkaRespErrRevokePartitions -> do+ containCallbackException $ f k (RebalanceBeforeRevoke assignment)+ protocol <- rdKafkaRebalanceProtocol kptr+ mask_ $+ if protocol == "COOPERATIVE"+ then checkRebalanceError (rdKafkaIncrementalUnassign kptr pls) >> forgetPendingPartitions (getKafkaConf k) (Set.fromList assignment)+ else checkRebalanceCode (newForeignPtr_ nullPtr >>= rdKafkaAssign kptr) >> resetPendingMessages (getKafkaConf k)+ containCallbackException $ f k (RebalanceRevoke assignment)+ x -> mask_ $ do+ -- Native arbitrary rebalance failures require an explicit unassignment.+ -- Publish no success event and preserve state if the reset itself fails.+ checkRebalanceCode (newForeignPtr_ nullPtr >>= rdKafkaAssign kptr)+ resetPendingMessages (getKafkaConf k)+ throwIO x++-- The outer native callback boundary contains and reports these exceptions.+-- Do not publish an after-assignment/revocation event when the native action+-- failed, and do not let an owned error escape its decoding scope.+checkRebalanceError :: IO RdKafkaErrorTPtr -> IO ()+checkRebalanceError acquire = bracket acquire rdKafkaErrorDestroy $ \pointer ->+ checkRebalanceCode (rdKafkaErrorCode pointer)++checkRebalanceCode :: IO RdKafkaRespErrT -> IO ()+checkRebalanceCode action = action >>= either throwIO pure . rdKafkaErrorToEither
+ src/Kafka/Consumer/ConsumerProperties.hs view
@@ -0,0 +1,200 @@+{-# LANGUAGE OverloadedStrings #-}++-----------------------------------------------------------------------------++-----------------------------------------------------------------------------++-- |+-- Module with consumer properties types and functions.+module Kafka.Consumer.ConsumerProperties+ ( ConsumerProperties (..),+ CallbackPollMode (..),+ brokersList,+ autoCommit,+ noAutoCommit,+ noAutoOffsetStore,+ groupId,+ clientId,+ setCallback,+ logLevel,+ compression,+ suppressDisconnectLogs,+ statisticsInterval,+ extraProps,+ extraProp,+ debugOptions,+ queuedMaxMessagesKBytes,+ callbackPollMode,+ effectiveCallbackPollMode,+ module X,+ )+where++import Control.Monad (MonadPlus (mplus))+import Data.Map (Map)+import Data.Map qualified as M+import Data.Maybe (fromMaybe)+import Data.Semigroup as Sem+import Data.Text (Text)+import Data.Text qualified as Text+import Kafka.Consumer.Types (ConsumerGroupId (..))+import Kafka.Types (BrokerAddress (..), ClientId (..), KafkaCompressionCodec (..), KafkaDebug (..), KafkaLogLevel (..), Millis (..), kafkaCompressionCodecToText, kafkaDebugToText)++import Kafka.Consumer.Callbacks as X hiding (forwardPartitionsToMessageQueue)++-- | Whether the callback polling should be done synchronously or not.+data CallbackPollMode+ = -- | You have to poll the consumer frequently to handle new messages+ -- as well as rebalance and keep alive events.+ -- This enables lowering the footprint and having full control over when polling+ -- happens, at the cost of manually managing those events.+ CallbackPollModeSync+ | -- | Handle polling rebalance and keep alive events for you in a background thread.+ --+ -- Note that @max.poll.interval.ms@ cannot detect a stuck application in+ -- this mode. The background thread polls librdkafka's consumer queue every+ -- 100 ms, and librdkafka counts /any/ poll of that queue as application+ -- progress and resets the @max.poll.interval.ms@ timer — regardless of+ -- whether the application is calling 'Kafka.Consumer.pollMessage' at all.+ -- An application that relies on the broker evicting it when it stops making+ -- progress must use 'CallbackPollModeSync', where the application's own+ -- polls are the only ones that happen.+ CallbackPollModeAsync+ deriving stock (Show, Eq)++-- | Properties to create 'Kafka.Consumer.Types.KafkaConsumer'.+data ConsumerProperties = ConsumerProperties+ { cpProps :: Map Text Text,+ cpLogLevel :: Maybe KafkaLogLevel,+ cpCallbacks :: [Callback],+ -- | 'Nothing' until 'callbackPollMode' sets it; see 'effectiveCallbackPollMode'.+ cpCallbackPollMode :: Maybe CallbackPollMode+ }++instance Sem.Semigroup ConsumerProperties where+ (ConsumerProperties m1 ll1 cb1 cup1) <> (ConsumerProperties m2 ll2 cb2 cup2) =+ ConsumerProperties (M.union m2 m1) (ll2 `mplus` ll1) (cb1 `mplus` cb2) (cup2 `mplus` cup1)+ {-# INLINE (<>) #-}++-- | /Right biased/ so we prefer newer properties over older ones.+instance Monoid ConsumerProperties where+ mempty =+ ConsumerProperties+ { cpProps = M.empty,+ cpLogLevel = Nothing,+ cpCallbacks = [],+ cpCallbackPollMode = Nothing+ }+ {-# INLINE mempty #-}+ mappend = (Sem.<>)+ {-# INLINE mappend #-}++-- | Set the <https://kafka.apache.org/documentation/#bootstrap.servers list of brokers> to contact to connect to the Kafka cluster.+brokersList :: [BrokerAddress] -> ConsumerProperties+brokersList bs =+ let bs' = Text.intercalate "," (unBrokerAddress <$> bs)+ in extraProps $ M.fromList [("bootstrap.servers", bs')]++-- | Set the <https://kafka.apache.org/documentation/#auto.commit.interval.ms auto commit interval> and enables <https://kafka.apache.org/documentation/#enable.auto.commit auto commit>.+autoCommit :: Millis -> ConsumerProperties+autoCommit (Millis ms) =+ extraProps $+ M.fromList+ [ ("enable.auto.commit", "true"),+ ("auto.commit.interval.ms", Text.pack $ show ms)+ ]++-- | Disable <https://kafka.apache.org/documentation/#enable.auto.commit auto commit> for the consumer.+noAutoCommit :: ConsumerProperties+noAutoCommit =+ extraProps $ M.fromList [("enable.auto.commit", "false")]++-- | Disable auto offset store for the consumer.+--+-- See <https://github.com/edenhill/librdkafka/blob/master/CONFIGURATION.md enable.auto.offset.store> for more information.+noAutoOffsetStore :: ConsumerProperties+noAutoOffsetStore =+ extraProps $ M.fromList [("enable.auto.offset.store", "false")]++-- | Set the consumer <https://kafka.apache.org/documentation/#group.id group id>.+groupId :: ConsumerGroupId -> ConsumerProperties+groupId (ConsumerGroupId cid) =+ extraProps $ M.fromList [("group.id", cid)]++-- | Set the <https://kafka.apache.org/documentation/#client.id consumer identifier>.+clientId :: ClientId -> ConsumerProperties+clientId (ClientId cid) =+ extraProps $ M.fromList [("client.id", cid)]++-- | Set the consumer callback.+--+-- For examples of use, see:+--+-- * 'errorCallback'+-- * 'logCallback'+-- * 'statsCallback'+setCallback :: Callback -> ConsumerProperties+setCallback cb = mempty {cpCallbacks = [cb]}++-- | Set the logging level.+-- Usually is used with 'debugOptions' to configure which logs are needed.+logLevel :: KafkaLogLevel -> ConsumerProperties+logLevel ll = mempty {cpLogLevel = Just ll}++-- | Set the <https://github.com/edenhill/librdkafka/blob/master/CONFIGURATION.md compression.codec> for the consumer.+compression :: KafkaCompressionCodec -> ConsumerProperties+compression c =+ extraProps $ M.singleton "compression.codec" (kafkaCompressionCodecToText c)++-- | Suppresses consumer <https://github.com/edenhill/librdkafka/blob/master/CONFIGURATION.md log.connection.close>.+--+-- It might be useful to turn this off when interacting with brokers+-- with an aggressive @connection.max.idle.ms@ value.+suppressDisconnectLogs :: ConsumerProperties+suppressDisconnectLogs =+ extraProps $ M.fromList [("log.connection.close", "false")]++-- | Set the <https://github.com/edenhill/librdkafka/blob/master/CONFIGURATION.md statistics.interval.ms> for the producer.+statisticsInterval :: Millis -> ConsumerProperties+statisticsInterval (Millis t) =+ extraProps $ M.singleton "statistics.interval.ms" (Text.pack $ show t)++-- | Set any configuration options that are supported by /librdkafka/.+-- The full list can be found <https://github.com/edenhill/librdkafka/blob/master/CONFIGURATION.md here>+extraProps :: Map Text Text -> ConsumerProperties+extraProps m = mempty {cpProps = m}+{-# INLINE extraProps #-}++-- | Set any configuration option that is supported by /librdkafka/.+-- The full list can be found <https://github.com/edenhill/librdkafka/blob/master/CONFIGURATION.md here>+extraProp :: Text -> Text -> ConsumerProperties+extraProp k v = mempty {cpProps = M.singleton k v}+{-# INLINE extraProp #-}++-- | Set <https://github.com/edenhill/librdkafka/blob/master/CONFIGURATION.md debug> features for the consumer.+-- Usually is used with 'logLevel'.+debugOptions :: [KafkaDebug] -> ConsumerProperties+debugOptions [] = extraProps M.empty+debugOptions d =+ let points = Text.intercalate "," (kafkaDebugToText <$> d)+ in extraProps $ M.fromList [("debug", points)]++-- | Set <https://github.com/edenhill/librdkafka/blob/master/CONFIGURATION.md queued.max.messages.kbytes>+queuedMaxMessagesKBytes :: Int -> ConsumerProperties+queuedMaxMessagesKBytes kBytes =+ extraProp "queued.max.messages.kbytes" (Text.pack $ show kBytes)+{-# INLINE queuedMaxMessagesKBytes #-}++-- | Set the callback poll mode. Default value is 'CallbackPollModeAsync'.+-- Async polling requires a threaded runtime; 'CallbackPollModeSync' also works+-- in executables linked without @-threaded@.+--+-- Like every property, a later setting overrides an earlier one, and+-- composing properties that do not set the mode leaves it unchanged.+callbackPollMode :: CallbackPollMode -> ConsumerProperties+callbackPollMode mode = mempty {cpCallbackPollMode = Just mode}++-- | The callback poll mode a consumer created with these properties uses:+-- the last one set with 'callbackPollMode', or 'CallbackPollModeAsync'.+effectiveCallbackPollMode :: ConsumerProperties -> CallbackPollMode+effectiveCallbackPollMode = fromMaybe CallbackPollModeAsync . cpCallbackPollMode
+ src/Kafka/Consumer/Convert.hs view
@@ -0,0 +1,241 @@+module Kafka.Consumer.Convert+ ( offsetSyncToInt,+ offsetToInt64,+ int64ToOffset,+ fromNativeTopicPartitionList'',+ nativeTopicPartitionErrors,+ fromNativeTopicPartitionList',+ fromNativeTopicPartitionList,+ toNativeTopicPartitionList,+ toNativeTopicPartitionListNoDispose,+ toNativeTopicPartitionList',+ topicPartitionFromMessage,+ topicPartitionFromMessageForCommit,+ toMap,+ fromMessagePtr,+ fromMessagePtrAttributed,+ copyMessagePtr,+ copyMessagePtrAttributed,+ withPolledMessage,+ offsetCommitToBool,+ )+where++import Control.Exception (bracket, bracketOnError)+import Control.Monad (when, (>=>))+import Data.Bifunctor (first)+import Data.ByteString qualified as BS+import Data.Int (Int64)+import Data.Map.Strict (Map, fromListWith)+import Data.Set qualified as S+import Data.Text qualified as Text+import Foreign.C.Error (getErrno)+import Foreign.ForeignPtr (finalizeForeignPtr, withForeignPtr)+import Foreign.Ptr (Ptr, nullPtr)+import Foreign.Storable (Storable (..))+import Kafka.Consumer.Types (ConsumerMessageError (..), ConsumerRecord (..), Offset (..), OffsetCommit (..), OffsetStoreSync (..), PartitionOffset (..), TopicPartition (..))+import Kafka.Internal.RdKafka+ ( RdKafkaMessageT (..),+ RdKafkaMessageTPtr,+ RdKafkaRespErrT (..),+ RdKafkaTopicPartitionListT (..),+ RdKafkaTopicPartitionListTPtr,+ RdKafkaTopicPartitionT (..),+ newRdKafkaTopicPartitionListT,+ peekCText,+ rdKafkaMessageDestroy,+ rdKafkaTopicPartitionListAdd,+ rdKafkaTopicPartitionListNew,+ rdKafkaTopicPartitionListSetOffset,+ )+import Kafka.Internal.Shared (kafkaRespErr, readHeaders, readKey, readPayload, readTimestamp, readTopic)+import Kafka.Types (KafkaError (..), PartitionId (..), TopicName (..))++-- | Converts offsets sync policy to integer (the way Kafka understands it):+--+-- * @OffsetSyncDisable == -1@+--+-- * @OffsetSyncImmediate == 0@+--+-- * @OffsetSyncInterval ms == ms@+offsetSyncToInt :: OffsetStoreSync -> Int+offsetSyncToInt sync =+ case sync of+ OffsetSyncDisable -> -1+ OffsetSyncImmediate -> 0+ OffsetSyncInterval ms -> ms+{-# INLINE offsetSyncToInt #-}++offsetToInt64 :: PartitionOffset -> Int64+offsetToInt64 o = case o of+ PartitionOffsetBeginning -> -2+ PartitionOffsetEnd -> -1+ PartitionOffset off -> off+ PartitionOffsetStored -> -1000+ PartitionOffsetInvalid -> -1001+{-# INLINE offsetToInt64 #-}++int64ToOffset :: Int64 -> PartitionOffset+int64ToOffset o+ | o == -2 = PartitionOffsetBeginning+ | o == -1 = PartitionOffsetEnd+ | o == -1000 = PartitionOffsetStored+ | o >= 0 = PartitionOffset o+ | otherwise = PartitionOffsetInvalid+{-# INLINE int64ToOffset #-}++fromNativeTopicPartitionList'' :: RdKafkaTopicPartitionListTPtr -> IO [TopicPartition]+fromNativeTopicPartitionList'' ptr =+ withForeignPtr ptr $ \fptr -> fromNativeTopicPartitionList' fptr++fromNativeTopicPartitionList' :: Ptr RdKafkaTopicPartitionListT -> IO [TopicPartition]+fromNativeTopicPartitionList' ppl =+ if ppl == nullPtr+ then return []+ else peek ppl >>= fromNativeTopicPartitionList++fromNativeTopicPartitionList :: RdKafkaTopicPartitionListT -> IO [TopicPartition]+fromNativeTopicPartitionList pl =+ let count = cnt'RdKafkaTopicPartitionListT pl+ elems = elems'RdKafkaTopicPartitionListT pl+ in mapM (peekElemOff elems >=> toPart) [0 .. (count - 1)]+ where+ toPart :: RdKafkaTopicPartitionT -> IO TopicPartition+ toPart p = do+ topic <- peekCText $ topic'RdKafkaTopicPartitionT p+ return+ TopicPartition+ { tpTopicName = TopicName topic,+ tpPartition = PartitionId $ partition'RdKafkaTopicPartitionT p,+ tpOffset = int64ToOffset $ offset'RdKafkaTopicPartitionT p+ }++-- | Read member errors in native/input order while retaining the owning list.+-- This deliberately leaves the generic public TopicPartition conversion alone.+nativeTopicPartitionErrors :: RdKafkaTopicPartitionListTPtr -> IO [RdKafkaRespErrT]+nativeTopicPartitionErrors list = withForeignPtr list $ \ptr -> do+ value <- peek ptr+ mapM+ (fmap err'RdKafkaTopicPartitionT . peekElemOff (elems'RdKafkaTopicPartitionListT value))+ [0 .. cnt'RdKafkaTopicPartitionListT value - 1]++toNativeTopicPartitionList :: [TopicPartition] -> IO RdKafkaTopicPartitionListTPtr+toNativeTopicPartitionList ps = bracketOnError (newRdKafkaTopicPartitionListT (length ps)) finalizeForeignPtr $ \pl -> do+ mapM_+ ( \p -> do+ let TopicName tn = tpTopicName p+ (PartitionId tp) = tpPartition p+ to = offsetToInt64 $ tpOffset p+ tnS = Text.unpack tn+ _ <- rdKafkaTopicPartitionListAdd pl tnS tp+ rdKafkaTopicPartitionListSetOffset pl tnS tp to+ )+ ps+ return pl++toNativeTopicPartitionListNoDispose :: [TopicPartition] -> IO RdKafkaTopicPartitionListTPtr+toNativeTopicPartitionListNoDispose ps = do+ pl <- rdKafkaTopicPartitionListNew (length ps)+ mapM_+ ( \p -> do+ let TopicName tn = tpTopicName p+ (PartitionId tp) = tpPartition p+ to = offsetToInt64 $ tpOffset p+ tnS = Text.unpack tn+ _ <- rdKafkaTopicPartitionListAdd pl tnS tp+ rdKafkaTopicPartitionListSetOffset pl tnS tp to+ )+ ps+ return pl++toNativeTopicPartitionList' :: [(TopicName, PartitionId)] -> IO RdKafkaTopicPartitionListTPtr+toNativeTopicPartitionList' tps =+ let utps = S.toList . S.fromList $ tps+ in bracketOnError (newRdKafkaTopicPartitionListT (length utps)) finalizeForeignPtr $ \pl -> do+ mapM_ (\(TopicName t, PartitionId p) -> rdKafkaTopicPartitionListAdd pl (Text.unpack t) p) utps+ return pl++topicPartitionFromMessage :: ConsumerRecord k v -> TopicPartition+topicPartitionFromMessage m =+ let (Offset moff) = crOffset m+ in TopicPartition (crTopic m) (crPartition m) (PartitionOffset moff)++-- | Creates a topic partition message for use with the offset commit message.+-- We increment the offset by 1 here because when we commit, the offset is the position+-- the consumer reads from to process the next message.+topicPartitionFromMessageForCommit :: ConsumerRecord k v -> TopicPartition+topicPartitionFromMessageForCommit m =+ case topicPartitionFromMessage m of+ (TopicPartition t p (PartitionOffset moff)) -> TopicPartition t p (PartitionOffset $ moff + 1)+ other -> other++toMap :: (Ord k) => [(k, v)] -> Map k [v]+toMap kvs = fromListWith (++) [(k, [v]) | (k, v) <- kvs]++-- | Acquire and copy one message within the same ownership scope. Masking+-- acquisition closes the window between native return and installing cleanup.+fromMessagePtr :: IO RdKafkaMessageTPtr -> IO (Either KafkaError (ConsumerRecord (Maybe BS.ByteString) (Maybe BS.ByteString)))+fromMessagePtr acquire = first cmeError <$> fromMessagePtrAttributed acquire++fromMessagePtrAttributed :: IO RdKafkaMessageTPtr -> IO (Either ConsumerMessageError (ConsumerRecord (Maybe BS.ByteString) (Maybe BS.ByteString)))+fromMessagePtrAttributed acquire = withPolledMessage acquire copyMessagePtrAttributed++withPolledMessage :: IO RdKafkaMessageTPtr -> (RdKafkaMessageTPtr -> IO a) -> IO a+withPolledMessage acquire = bracket acquire releaseMessage+ where+ releaseMessage pointer = withForeignPtr pointer $ \raw ->+ when (raw /= nullPtr) (rdKafkaMessageDestroy raw)++-- | Copy a borrowed batch member. The caller owns and releases the complete+-- batch, including members not reached if a conversion is interrupted.+copyMessagePtr :: RdKafkaMessageTPtr -> IO (Either KafkaError (ConsumerRecord (Maybe BS.ByteString) (Maybe BS.ByteString)))+copyMessagePtr pointer = first cmeError <$> copyMessagePtrAttributed pointer++copyMessagePtrAttributed :: RdKafkaMessageTPtr -> IO (Either ConsumerMessageError (ConsumerRecord (Maybe BS.ByteString) (Maybe BS.ByteString)))+copyMessagePtrAttributed ptr =+ withForeignPtr ptr $ \realPtr ->+ if realPtr == nullPtr+ then (\err -> Left (ConsumerMessageError err Nothing Nothing Nothing)) . kafkaRespErr <$> getErrno+ else do+ message <- peek realPtr+ if err'RdKafkaMessageT message /= RdKafkaRespErrNoError+ then Left <$> attributed (err'RdKafkaMessageT message) message+ else mkRecord message realPtr+ where+ attributed code msg = do+ topic <-+ if topic'RdKafkaMessageT msg == nullPtr+ then pure Nothing+ else Just . TopicName <$> readTopic msg+ let partition = partition'RdKafkaMessageT msg+ offset = offset'RdKafkaMessageT msg+ pure+ ConsumerMessageError+ { cmeError = KafkaResponseError code,+ cmeTopic = topic,+ cmePartition = if partition >= 0 then Just (PartitionId partition) else Nothing,+ cmeOffset = if offset >= 0 then Just (Offset offset) else Nothing+ }+ mkRecord msg rptr = do+ topic <- readTopic msg+ key <- readKey msg+ payload <- readPayload msg+ timestamp <- readTimestamp ptr+ readHeaders rptr >>= \case+ Left code -> Left <$> attributed code msg+ Right headers ->+ pure $+ Right+ ConsumerRecord+ { crTopic = TopicName topic,+ crPartition = PartitionId $ partition'RdKafkaMessageT msg,+ crOffset = Offset $ offset'RdKafkaMessageT msg,+ crTimestamp = timestamp,+ crHeaders = headers,+ crKey = key,+ crValue = payload+ }++offsetCommitToBool :: OffsetCommit -> Bool+offsetCommitToBool OffsetCommit = False+offsetCommitToBool OffsetCommitAsync = True
+ src/Kafka/Consumer/Subscription.hs view
@@ -0,0 +1,69 @@+{-# LANGUAGE OverloadedStrings #-}++-----------------------------------------------------------------------------++-----------------------------------------------------------------------------++-- |+-- Module with subscription types and functions.+module Kafka.Consumer.Subscription+ ( Subscription (..),+ topics,+ offsetReset,+ extraSubscriptionProps,+ )+where++import Data.Map (Map)+import Data.Map qualified as M+import Data.Semigroup as Sem+import Data.Set (Set)+import Data.Set qualified as Set+import Data.Text (Text)+import Kafka.Consumer.Types (OffsetReset (..))+import Kafka.Types (TopicName (..))++-- | A consumer subscription to a topic.+--+-- ==== __Examples__+--+-- Typically you don't call the constructor directly, but combine settings:+--+-- @+-- consumerSub :: 'Subscription'+-- consumerSub = 'topics' ['TopicName' "kafka-client-example-topic"]+-- <> 'offsetReset' 'Earliest'+-- <> 'extraSubscriptionProps' (fromList [("prop1", "value 1"), ("prop2", "value 2")])+-- @+data Subscription = Subscription (Set TopicName) (Map Text Text)++instance Sem.Semigroup Subscription where+ (Subscription ts1 m1) <> (Subscription ts2 m2) =+ let ts' = Set.union ts1 ts2+ ps' = M.union m2 m1+ in Subscription ts' ps'+ {-# INLINE (<>) #-}++-- | Topic names accumulate; later property values override earlier ones,+-- matching consumer and producer property composition.+instance Monoid Subscription where+ mempty = Subscription Set.empty M.empty+ {-# INLINE mempty #-}+ mappend = (Sem.<>)+ {-# INLINE mappend #-}++-- | Build a subscription by giving the list of topic names only+topics :: [TopicName] -> Subscription+topics ts = Subscription (Set.fromList ts) M.empty++-- | Build a subscription by giving the offset reset parameter only+offsetReset :: OffsetReset -> Subscription+offsetReset o =+ let o' = case o of+ Earliest -> "earliest"+ Latest -> "latest"+ in Subscription Set.empty (M.fromList [("auto.offset.reset", o')])++-- | Build a subscription by giving extra properties only+extraSubscriptionProps :: Map Text Text -> Subscription+extraSubscriptionProps = Subscription Set.empty
+ src/Kafka/Consumer/Types.hs view
@@ -0,0 +1,269 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}++-----------------------------------------------------------------------------++-----------------------------------------------------------------------------++-- |+-- Module holding consumer types.+module Kafka.Consumer.Types+ ( KafkaConsumer (..),+ ConsumerGroupId (..),+ Offset (..),+ OffsetReset (..),+ RebalanceEvent (..),+ PartitionOffset (..),+ SubscribedPartitions (..),+ Timestamp (..),+ OffsetCommit (..),+ OffsetStoreSync (..),+ OffsetStoreMethod (..),+ TopicPartition (..),+ ConsumerRecord (..),+ ConsumerMessageError (..),+ crMapKey,+ crMapValue,+ crMapKV,+ -- why are these here?++ -- * Deprecated+ sequenceFirst,+ traverseFirst,+ traverseFirstM,+ traverseM,+ bitraverseM,+ )+where++import Data.Bifoldable (Bifoldable (..))+import Data.Bifunctor (Bifunctor (..))+import Data.Bitraversable (Bitraversable (..), bimapM, bisequence)+import Data.Int (Int64)+import Data.String (IsString)+import Data.Text (Text)+import GHC.Generics (Generic)+import Kafka.Internal.Setup (HasKafka (..), HasKafkaConf (..), Kafka (..), KafkaConf (..))+import Kafka.Types (Headers, KafkaError, Millis (..), PartitionId (..), TopicName (..))++-- | The main type for Kafka consumption, used e.g. to poll and commit messages.+--+-- Use 'Kafka.Consumer.newConsumer' to acquire a managed consumer.+data KafkaConsumer = KafkaConsumer+ { kcKafkaPtr :: !Kafka,+ kcKafkaConf :: !KafkaConf+ }++instance HasKafka KafkaConsumer where+ getKafka = kcKafkaPtr+ {-# INLINE getKafka #-}++instance HasKafkaConf KafkaConsumer where+ getKafkaConf = kcKafkaConf+ {-# INLINE getKafkaConf #-}++-- | Consumer group ID. Different consumers with the same consumer group ID will get assigned different partitions of each subscribed topic.+--+-- See <https://kafka.apache.org/documentation/#group.id Kafka documentation on consumer group>+newtype ConsumerGroupId = ConsumerGroupId+ { unConsumerGroupId :: Text+ }+ deriving stock (Show, Ord, Eq, Generic)+ deriving newtype (IsString)++-- | A message offset in a partition+newtype Offset = Offset {unOffset :: Int64}+ deriving stock (Show, Eq, Ord, Read, Generic)++-- | Where to reset the offset when there is no initial offset in Kafka+--+-- See <https://kafka.apache.org/documentation/#auto.offset.reset Kafka documentation on offset reset>+data OffsetReset = Earliest | Latest+ deriving stock (Show, Eq, Generic)++-- | A set of events which happen during the rebalancing process+data RebalanceEvent+ = -- | Happens before Kafka Client confirms new assignment+ RebalanceBeforeAssign [(TopicName, PartitionId)]+ | -- | Happens after the new assignment is confirmed+ RebalanceAssign [(TopicName, PartitionId)]+ | -- | Happens before Kafka Client confirms partitions rejection+ RebalanceBeforeRevoke [(TopicName, PartitionId)]+ | -- | Happens after the rejection is confirmed+ RebalanceRevoke [(TopicName, PartitionId)]+ deriving stock (Eq, Show, Generic)++-- | The partition offset+data PartitionOffset+ = PartitionOffsetBeginning+ | PartitionOffsetEnd+ | PartitionOffset Int64+ | PartitionOffsetStored+ | PartitionOffsetInvalid+ deriving stock (Eq, Show, Generic)++-- | Partitions subscribed by a consumer+data SubscribedPartitions+ = -- | Subscribe only to those partitions+ SubscribedPartitions [PartitionId]+ | -- | Subscribe to all partitions+ SubscribedPartitionsAll+ deriving stock (Show, Eq, Generic)++-- | Consumer record timestamp+data Timestamp+ = CreateTime !Millis+ | LogAppendTime !Millis+ | NoTimestamp+ deriving stock (Show, Eq, Read, Generic)++-- | Offsets commit mode+data OffsetCommit+ = -- | Forces consumer to block until the broker offsets commit is done+ OffsetCommit+ | -- | Offsets will be committed in a non-blocking way+ OffsetCommitAsync+ deriving stock (Show, Eq, Generic)++-- | Indicates how offsets are to be synced to disk+data OffsetStoreSync+ = -- | Do not sync offsets (in Kafka: -1)+ OffsetSyncDisable+ | -- | Sync immediately after each offset commit (in Kafka: 0)+ OffsetSyncImmediate+ | -- | Sync after specified interval in millis+ OffsetSyncInterval Int+ deriving stock (Show, Eq, Generic)++-- | Indicates the method of storing the offsets+data OffsetStoreMethod+ = -- | Offsets are stored in Kafka broker (preferred)+ OffsetStoreBroker+ | -- | Offsets are stored in a file (and synced to disk according to the sync policy)+ OffsetStoreFile FilePath OffsetStoreSync+ deriving stock (Show, Eq, Generic)++-- | Kafka topic partition structure+data TopicPartition = TopicPartition+ { tpTopicName :: TopicName,+ tpPartition :: PartitionId,+ tpOffset :: PartitionOffset+ }+ deriving stock (Show, Eq, Generic)++-- | Represents a /received/ message from Kafka (i.e. used in a consumer)+-- | A per-message error from 'Kafka.Consumer.pollMessageAttributed', with the+-- topic, partition and offset librdkafka attached to the errored message.+--+-- For @'Kafka.Types.KafkaResponseError' 'Kafka.Consumer.RdKafkaRespErrPartitionEof'@+-- (delivered when @enable.partition.eof@ is @true@) the offset is the+-- partition's end offset. Each origin field is 'Nothing' when librdkafka did+-- not set it, and all three are 'Nothing' for errors that belong to no message:+-- a poll timeout or a raised fatal error.+data ConsumerMessageError = ConsumerMessageError+ { cmeError :: !KafkaError,+ cmeTopic :: !(Maybe TopicName),+ cmePartition :: !(Maybe PartitionId),+ cmeOffset :: !(Maybe Offset)+ }+ deriving stock (Eq, Show, Generic)++data ConsumerRecord k v = ConsumerRecord+ { -- | Kafka topic this message was received from+ crTopic :: !TopicName,+ -- | Kafka partition this message was received from+ crPartition :: !PartitionId,+ -- | Offset within the 'crPartition' Kafka partition+ crOffset :: !Offset,+ -- | Message timestamp+ crTimestamp :: !Timestamp,+ -- | Message headers+ crHeaders :: !Headers,+ -- | Message key+ crKey :: !k,+ -- | Message value+ crValue :: !v+ }+ deriving stock (Eq, Show, Read, Generic)++instance Bifunctor ConsumerRecord where+ bimap f g (ConsumerRecord t p o ts hds k v) = ConsumerRecord t p o ts hds (f k) (g v)+ {-# INLINE bimap #-}++instance Functor (ConsumerRecord k) where+ fmap = second+ {-# INLINE fmap #-}++instance Foldable (ConsumerRecord k) where+ foldMap f r = f (crValue r)+ {-# INLINE foldMap #-}++instance Traversable (ConsumerRecord k) where+ traverse f r = (\v -> crMapValue (const v) r) <$> f (crValue r)+ {-# INLINE traverse #-}++instance Bifoldable ConsumerRecord where+ bifoldMap f g r = f (crKey r) `mappend` g (crValue r)+ {-# INLINE bifoldMap #-}++instance Bitraversable ConsumerRecord where+ bitraverse f g r = (\k v -> bimap (const k) (const v) r) <$> f (crKey r) <*> g (crValue r)+ {-# INLINE bitraverse #-}++{-# DEPRECATED crMapKey "Isn't concern of this library. Use 'first'" #-}+crMapKey :: (k -> k') -> ConsumerRecord k v -> ConsumerRecord k' v+crMapKey = first+{-# INLINE crMapKey #-}++{-# DEPRECATED crMapValue "Isn't concern of this library. Use 'second'" #-}+crMapValue :: (v -> v') -> ConsumerRecord k v -> ConsumerRecord k v'+crMapValue = second+{-# INLINE crMapValue #-}++{-# DEPRECATED crMapKV "Isn't concern of this library. Use 'bimap'" #-}+crMapKV :: (k -> k') -> (v -> v') -> ConsumerRecord k v -> ConsumerRecord k' v'+crMapKV = bimap+{-# INLINE crMapKV #-}++{-# DEPRECATED sequenceFirst "Isn't concern of this library. Use @'bitraverse' 'id' 'pure'@" #-}+sequenceFirst :: (Bitraversable t, Applicative f) => t (f k) v -> f (t k v)+sequenceFirst = bitraverse id pure+{-# INLINE sequenceFirst #-}++{-# DEPRECATED traverseFirst "Isn't concern of this library. Use @'bitraverse' f 'pure'@" #-}+traverseFirst ::+ (Bitraversable t, Applicative f) =>+ (k -> f k') ->+ t k v ->+ f (t k' v)+traverseFirst f = bitraverse f pure+{-# INLINE traverseFirst #-}++{-# DEPRECATED traverseFirstM "Isn't concern of this library. Use @'bitraverse' 'id' 'pure' '<$>' 'bitraverse' f 'pure' r@" #-}+traverseFirstM ::+ (Bitraversable t, Applicative f, Monad m) =>+ (k -> m (f k')) ->+ t k v ->+ m (f (t k' v))+traverseFirstM f r = bitraverse id pure <$> bitraverse f pure r+{-# INLINE traverseFirstM #-}++{-# DEPRECATED traverseM "Isn't concern of this library. Use @'sequenceA' '<$>' 'traverse' f r@" #-}+traverseM ::+ (Traversable t, Applicative f, Monad m) =>+ (v -> m (f v')) ->+ t v ->+ m (f (t v'))+traverseM f r = sequenceA <$> traverse f r+{-# INLINE traverseM #-}++{-# DEPRECATED bitraverseM "Isn't concern of this library. Use @'Data.Bitraversable.bisequenceA' '<$>' 'bimapM' f g r@" #-}+bitraverseM ::+ (Bitraversable t, Applicative f, Monad m) =>+ (k -> m (f k')) ->+ (v -> m (f v')) ->+ t k v ->+ m (f (t k' v'))+bitraverseM f g r = bisequence <$> bimapM f g r+{-# INLINE bitraverseM #-}
+ src/Kafka/Dump.hs view
@@ -0,0 +1,82 @@+-----------------------------------------------------------------------------++-----------------------------------------------------------------------------++-- |+-- Module providing various functions to dump information. These may be useful for+-- debug/investigation but should probably not be used on production applications.+module Kafka.Dump+ ( hPrintSupportedKafkaConf,+ hPrintKafka,+ dumpKafkaConf,+ dumpTopicConf,+ )+where++import Kafka.Internal.RdKafka+ ( CSizePtr,+ peekCText,+ rdKafkaConfDump,+ rdKafkaConfDumpFree,+ rdKafkaConfPropertiesShow,+ rdKafkaDump,+ rdKafkaTopicConfDump,+ withCFile,+ )+import Kafka.Internal.Setup+ ( HasKafka (..),+ HasKafkaConf (..),+ HasTopicConf (..),+ getRdKafka,+ getRdKafkaConf,+ getRdTopicConf,+ )++import Control.Exception (bracket, evaluate)+import Control.Monad ((<=<))+import Control.Monad.IO.Class (MonadIO (liftIO))+import Data.Map.Strict (Map)+import Data.Map.Strict qualified as Map+import Data.Text (Text)+import Foreign (Ptr, Storable (peek, peekElemOff), alloca, withForeignPtr)+import Foreign.C.String (CString)+import System.IO (Handle)++-- | Prints supported Kafka properties, flushing the native output before+-- returning. The handle stays open and owned by the caller. Serialize other+-- access to this handle while printing.+hPrintSupportedKafkaConf :: (MonadIO m) => Handle -> m ()+hPrintSupportedKafkaConf h = liftIO $ withCFile h "w" rdKafkaConfPropertiesShow++-- | Prints native client diagnostics, flushing before returning. The handle+-- stays open and owned by the caller. Serialize other access while printing.+hPrintKafka :: (MonadIO m, HasKafka k) => Handle -> k -> m ()+hPrintKafka h k = liftIO $ withForeignPtr (getRdKafka k) $ \_ ->+ withCFile h "w" (\file -> rdKafkaDump file (getRdKafka k))++-- | Returns a map of the current topic configuration+dumpTopicConf :: (MonadIO m, HasTopicConf t) => t -> m (Map Text Text)+dumpTopicConf t = liftIO $ parseDump (rdKafkaTopicConfDump (getRdTopicConf t))++-- | Returns a map of the current kafka configuration+dumpKafkaConf :: (MonadIO m, HasKafkaConf k) => k -> m (Map Text Text)+dumpKafkaConf k = liftIO $ parseDump (rdKafkaConfDump (getRdKafkaConf k))++parseDump :: (CSizePtr -> IO (Ptr CString)) -> IO (Map Text Text)+parseDump cstr = alloca $ \sizeptr ->+ bracket+ ( do+ pointer <- cstr sizeptr+ size <- peek sizeptr+ pure (pointer, size)+ )+ (uncurry rdKafkaConfDumpFree)+ ( \(pointer, size) -> do+ keysAndValues <- mapM (peekCText <=< peekElemOff pointer) [0 .. (fromIntegral size - 1)]+ evaluate (Map.fromList (listToTuple keysAndValues))+ )++listToTuple :: [Text] -> [(Text, Text)]+listToTuple [] = []+listToTuple (k : v : ts) = (k, v) : listToTuple ts+listToTuple _ = error "list to tuple can only be called on even length lists"
+ src/Kafka/Internal/CallbackOwner.hs view
@@ -0,0 +1,90 @@+-- | A client-independent owner for persistent Haskell callback bridges. This+-- owner must never capture the owning client ForeignPtr. Native configuration+-- copies borrow the same bridges; only client teardown releases them.+module Kafka.Internal.CallbackOwner+ ( CallbackOwner,+ newCallbackOwner,+ newCallbackOwnerWith,+ installCallback,+ checkCallbackOwner,+ attachCallbackOwner,+ releaseCallbackOwner,+ releaseUnattachedCallbacks,+ containCallbackException,+ containCallbackResult,+ )+where++import Control.Concurrent (forkIOWithUnmask)+import Control.Concurrent.MVar (MVar, modifyMVarMasked_, newMVar, withMVar)+import Control.Exception (SomeException, catch, mask_, onException, throwIO)+import Control.Monad (void)+import Data.IORef (IORef, modifyIORef', newIORef, readIORef, writeIORef)+import Foreign.Ptr (FunPtr, castFunPtr, freeHaskellFunPtr)++data Phase = Building | Attached | Released++data CallbackOwner = CallbackOwner (MVar Phase) (IORef [FunPtr ()]) (FunPtr () -> IO ())++newCallbackOwner :: IO CallbackOwner+newCallbackOwner = newCallbackOwnerWith freeHaskellFunPtr++-- | The releaser must either throw before freeing, or return after freeing.+-- This internal seam lets tests count actual allocations and releases without+-- adding instrumentation to normal clients.+newCallbackOwnerWith :: (FunPtr () -> IO ()) -> IO CallbackOwner+newCallbackOwnerWith free = CallbackOwner <$> newMVar Building <*> newIORef [] <*> pure free++installCallback :: CallbackOwner -> IO (FunPtr a) -> (FunPtr a -> IO ()) -> IO ()+installCallback owner@(CallbackOwner phase pointers _) allocate install = mask_ $ do+ checkCallbackOwner owner+ pointer <- allocate+ ( withMVar phase $ \case+ Building -> modifyIORef' pointers (castFunPtr pointer :)+ _ -> ioError (userError "callback configuration is no longer mutable")+ )+ `onException` freeHaskellFunPtr pointer+ install pointer++checkCallbackOwner :: CallbackOwner -> IO ()+checkCallbackOwner (CallbackOwner phase _ _) = withMVar phase $ \case+ Building -> pure ()+ _ -> ioError (userError "callback configuration cannot construct another client")++attachCallbackOwner :: CallbackOwner -> IO ()+attachCallbackOwner (CallbackOwner phase _ _) = modifyMVarMasked_ phase $ \case+ Building -> pure Attached+ _ -> ioError (userError "callback owner already transferred or released")++releaseCallbackOwner :: CallbackOwner -> IO ()+releaseCallbackOwner = releaseWhen (const True)++-- | After transfer the client finalizer is the sole releaser. A constructor+-- exception after native creation must not free live callback addresses.+releaseUnattachedCallbacks :: CallbackOwner -> IO ()+releaseUnattachedCallbacks = releaseWhen $ \case+ Building -> True+ _ -> False++releaseWhen :: (Phase -> Bool) -> CallbackOwner -> IO ()+releaseWhen shouldRelease (CallbackOwner phase pointers free) = modifyMVarMasked_ phase $ \current ->+ if shouldRelease current then drain >> pure Released else pure current+ where+ -- Commit each completed release while masked. A later failing releaser+ -- leaves only the remaining pointers for a retry.+ drain =+ readIORef pointers >>= \case+ [] -> pure ()+ pointer : rest -> free pointer >> writeIORef pointers rest >> drain++-- | Report on a fresh Haskell thread, never through a foreign callback frame.+-- Rebalance installers also use this around each user action so native+-- assignment/revocation still runs after a user callback throws.+containCallbackException :: IO () -> IO ()+containCallbackException = containCallbackResult ()++containCallbackResult :: a -> IO a -> IO a+containCallbackResult fallback action =+ action `catch` \(exception :: SomeException) -> do+ void $ forkIOWithUnmask (\unmask -> unmask (throwIO exception))+ pure fallback
+ src/Kafka/Internal/RdKafka.chs view
@@ -0,0 +1,1550 @@+{-# LANGUAGE ForeignFunctionInterface #-}+{-# LANGUAGE EmptyDataDecls #-}+-- This module re-exports every c2hs-generated binding, so it has no export+-- list, and c2hs marshalling emits fromIntegral calls between identical C+-- integer types and strategy-less `deriving (Enum)` clauses for contiguous+-- enums; neither can be changed from the .chs source. Hand-written deriving+-- below uses explicit strategies.+{-# OPTIONS_GHC -Wno-missing-export-lists -Wno-identities -Wno-missing-deriving-strategies #-}++-- Conventions for this module:+--+-- * New bindings go in the section of their function's @name group in+-- librdkafka's rdkafka.h; new sections follow the header's group order.+-- docs/bindings.md lists every exported function under its group.+-- * Plain calls use a {#fun ... as ^ ...#} directive.+-- * Anything that needs buffers, finalizers or rd_kafka_error_t handling gets a+-- hand-written wrapper directly below its {#fun#}. Bracket every non-null+-- rd_kafka_error_t with rdKafkaErrorDestroy, and treat NULL as success.+-- * Handles the caller must destroy are foreign pointers with the destroy+-- function attached as a finalizer by a newRdKafka... helper.+-- * After any change, run `just bindings-inventory` and commit+-- docs/bindings.md; `just bindings-check` fails when it is stale.++module Kafka.Internal.RdKafka where++import Data.ByteString (ByteString)+import Data.ByteString qualified as BS+import Text.Read (readMaybe)+import Data.Text (Text)+import Data.Text qualified as Text+import Control.Exception (bracket, bracketOnError, finally, mask_)+import Kafka.Internal.CallbackOwner (CallbackOwner, installCallback, checkCallbackOwner, attachCallbackOwner, releaseCallbackOwner, containCallbackException, containCallbackResult)+import Control.Monad (liftM)+import Data.Int (Int32, Int64)+import Data.Word (Word8)+import Foreign.Concurrent qualified as Concurrent+import Foreign.Marshal.Alloc (alloca, allocaBytes)+import Foreign.Marshal.Array (peekArray, allocaArray, withArrayLen)+import Foreign.Storable (Storable(..))+import Foreign.Ptr (Ptr, FunPtr, castFunPtr, castPtr, nullPtr)+import Foreign.ForeignPtr (FinalizerPtr, addForeignPtrFinalizer, newForeignPtr_, withForeignPtr, ForeignPtr, newForeignPtr, touchForeignPtr)+import Foreign.C.Error (Errno(..), getErrno, throwErrnoIfNull, throwErrnoIfMinus1_)+import Foreign.C.String (CString, withCString, withCAString, peekCAString, peekCString)+import Foreign.C.Types (CFile, CInt(..), CSize, CChar, CLong)+import System.IO (Handle, hClose)+import GHC.IO.Handle (hDuplicate)+import System.Posix.IO (handleToFd, closeFd)+import System.Posix.Types (Fd(..))++#include <librdkafka/rdkafka.h>++-- The supported floor, checked against the header at build time. A pkg-config+-- bound would check it at configure time, but `pkg-config --cflags rdkafka`+-- also needs the .pc files of librdkafka's private dependencies, which the+-- shared Nix dev shells do not provide.+#if RD_KAFKA_VERSION < 0x020f0000+#error "rdkafka-hs requires librdkafka 2.15 or newer"+#endif++type CInt64T = {#type int64_t #}+type CInt32T = {#type int32_t #}++{#pointer *FILE as CFilePtr -> CFile #}+{#pointer *size_t as CSizePtr -> CSize #}++type Word8Ptr = Ptr Word8+type CCharBufPointer = Ptr CChar++{#enum rd_kafka_type_t as ^ {underscoreToCase} #}+deriving stock instance Show RdKafkaTypeT+deriving stock instance Eq RdKafkaTypeT+{#enum rd_kafka_conf_res_t as ^ {underscoreToCase} #}+deriving stock instance Show RdKafkaConfResT+deriving stock instance Eq RdKafkaConfResT+{#enum rd_kafka_resp_err_t as ^ {underscoreToCase} #}+deriving stock instance Show RdKafkaRespErrT+deriving stock instance Eq RdKafkaRespErrT+deriving stock instance Bounded RdKafkaRespErrT+{#enum rd_kafka_timestamp_type_t as ^ {underscoreToCase} #}+deriving stock instance Show RdKafkaTimestampTypeT+deriving stock instance Eq RdKafkaTimestampTypeT++type RdKafkaMsgFlag = Int+rdKafkaMsgFlagFree :: RdKafkaMsgFlag+rdKafkaMsgFlagFree = 0x1+rdKafkaMsgFlagCopy :: RdKafkaMsgFlag+rdKafkaMsgFlagCopy = 0x2++-- Number of bytes allocated for an error buffer+nErrorBytes :: Int+nErrorBytes = 1024 * 8++-- Helper functions+{#fun pure rd_kafka_version as ^+ {} -> `Int' #}++{#fun pure rd_kafka_version_str as ^+ {} -> `String' #}++{#fun pure rd_kafka_err2str as ^+ {enumToCInt `RdKafkaRespErrT'} -> `String' #}++{#fun pure rd_kafka_err2name as ^+ {enumToCInt `RdKafkaRespErrT'} -> `String' #}++{#fun pure rd_kafka_errno2err as ^+ {`Int'} -> `RdKafkaRespErrT' cIntToEnum #}++peekCAText :: CString -> IO Text+peekCAText cp = Text.pack <$> peekCAString cp++peekCText :: CString -> IO Text+peekCText cp = Text.pack <$> peekCString cp++kafkaErrnoString :: IO String+kafkaErrnoString = do+ (Errno num) <- getErrno+ return $ rdKafkaErr2str $ rdKafkaErrno2err (fromIntegral num)++-- Kafka Pointer Types+data RdKafkaConfT+{#pointer *rd_kafka_conf_t as RdKafkaConfTPtr foreign -> RdKafkaConfT #}++data RdKafkaTopicConfT+{#pointer *rd_kafka_topic_conf_t as RdKafkaTopicConfTPtr foreign -> RdKafkaTopicConfT #}++data RdKafkaT+{#pointer *rd_kafka_t as RdKafkaTPtr foreign -> RdKafkaT #}++data RdKafkaTopicPartitionT = RdKafkaTopicPartitionT+ { topic'RdKafkaTopicPartitionT :: CString+ , partition'RdKafkaTopicPartitionT :: Int+ , offset'RdKafkaTopicPartitionT :: Int64+ , metadata'RdKafkaTopicPartitionT :: Word8Ptr+ , metadataSize'RdKafkaTopicPartitionT :: Int+ , opaque'RdKafkaTopicPartitionT :: Word8Ptr+ , err'RdKafkaTopicPartitionT :: RdKafkaRespErrT+ }+ deriving stock (Show, Eq)++instance Storable RdKafkaTopicPartitionT where+ alignment _ = {#alignof rd_kafka_topic_partition_t#}+ sizeOf _ = {#sizeof rd_kafka_topic_partition_t#}+ peek p = RdKafkaTopicPartitionT+ <$> liftM id ({#get rd_kafka_topic_partition_t->topic #} p)+ <*> liftM fromIntegral ({#get rd_kafka_topic_partition_t->partition #} p)+ <*> liftM fromIntegral ({#get rd_kafka_topic_partition_t->offset #} p)+ <*> liftM castPtr ({#get rd_kafka_topic_partition_t->metadata #} p)+ <*> liftM fromIntegral ({#get rd_kafka_topic_partition_t->metadata_size #} p)+ <*> liftM castPtr ({#get rd_kafka_topic_partition_t->opaque #} p)+ <*> liftM cIntToEnum ({#get rd_kafka_topic_partition_t->err #} p)+ poke p x = do+ {#set rd_kafka_topic_partition_t.topic#} p (id $ topic'RdKafkaTopicPartitionT x)+ {#set rd_kafka_topic_partition_t.partition#} p (fromIntegral $ partition'RdKafkaTopicPartitionT x)+ {#set rd_kafka_topic_partition_t.offset#} p (fromIntegral $ offset'RdKafkaTopicPartitionT x)+ {#set rd_kafka_topic_partition_t.metadata#} p (castPtr $ metadata'RdKafkaTopicPartitionT x)+ {#set rd_kafka_topic_partition_t.metadata_size#} p (fromIntegral $ metadataSize'RdKafkaTopicPartitionT x)+ {#set rd_kafka_topic_partition_t.opaque#} p (castPtr $ opaque'RdKafkaTopicPartitionT x)+ {#set rd_kafka_topic_partition_t.err#} p (enumToCInt $ err'RdKafkaTopicPartitionT x)++{#pointer *rd_kafka_topic_partition_t as RdKafkaTopicPartitionTPtr foreign -> RdKafkaTopicPartitionT #}++data RdKafkaTopicPartitionListT = RdKafkaTopicPartitionListT+ { cnt'RdKafkaTopicPartitionListT :: Int+ , size'RdKafkaTopicPartitionListT :: Int+ , elems'RdKafkaTopicPartitionListT :: Ptr RdKafkaTopicPartitionT+ }+ deriving stock (Show, Eq)++{#pointer *rd_kafka_topic_partition_list_t as RdKafkaTopicPartitionListTPtr foreign -> RdKafkaTopicPartitionListT #}++instance Storable RdKafkaTopicPartitionListT where+ alignment _ = {#alignof rd_kafka_topic_partition_list_t#}+ sizeOf _ = {#sizeof rd_kafka_topic_partition_list_t #}+ peek p = RdKafkaTopicPartitionListT+ <$> liftM fromIntegral ({#get rd_kafka_topic_partition_list_t->cnt #} p)+ <*> liftM fromIntegral ({#get rd_kafka_topic_partition_list_t->size #} p)+ <*> liftM castPtr ({#get rd_kafka_topic_partition_list_t->elems #} p)+ poke p x = do+ {#set rd_kafka_topic_partition_list_t.cnt#} p (fromIntegral $ cnt'RdKafkaTopicPartitionListT x)+ {#set rd_kafka_topic_partition_list_t.size#} p (fromIntegral $ size'RdKafkaTopicPartitionListT x)+ {#set rd_kafka_topic_partition_list_t.elems#} p (castPtr $ elems'RdKafkaTopicPartitionListT x)++data RdKafkaTopicT+{#pointer *rd_kafka_topic_t as RdKafkaTopicTPtr foreign -> RdKafkaTopicT #}++data RdKafkaMessageT = RdKafkaMessageT+ { err'RdKafkaMessageT :: RdKafkaRespErrT+ , topic'RdKafkaMessageT :: Ptr RdKafkaTopicT+ , partition'RdKafkaMessageT :: Int+ , len'RdKafkaMessageT :: Int+ , keyLen'RdKafkaMessageT :: Int+ , offset'RdKafkaMessageT :: Int64+ , payload'RdKafkaMessageT :: Word8Ptr+ , key'RdKafkaMessageT :: Word8Ptr+ , opaque'RdKafkaMessageT :: Ptr ()+ }+ deriving stock (Show, Eq)++instance Storable RdKafkaMessageT where+ alignment _ = {#alignof rd_kafka_message_t#}+ sizeOf _ = {#sizeof rd_kafka_message_t#}+ peek p = RdKafkaMessageT+ <$> liftM cIntToEnum ({#get rd_kafka_message_t->err #} p)+ <*> liftM castPtr ({#get rd_kafka_message_t->rkt #} p)+ <*> liftM fromIntegral ({#get rd_kafka_message_t->partition #} p)+ <*> liftM fromIntegral ({#get rd_kafka_message_t->len #} p)+ <*> liftM fromIntegral ({#get rd_kafka_message_t->key_len #} p)+ <*> liftM fromIntegral ({#get rd_kafka_message_t->offset #} p)+ <*> liftM castPtr ({#get rd_kafka_message_t->payload #} p)+ <*> liftM castPtr ({#get rd_kafka_message_t->key #} p)+ <*> liftM castPtr ({#get rd_kafka_message_t->_private #} p)+ poke p x = do+ {#set rd_kafka_message_t.err#} p (enumToCInt $ err'RdKafkaMessageT x)+ {#set rd_kafka_message_t.rkt#} p (castPtr $ topic'RdKafkaMessageT x)+ {#set rd_kafka_message_t.partition#} p (fromIntegral $ partition'RdKafkaMessageT x)+ {#set rd_kafka_message_t.len#} p (fromIntegral $ len'RdKafkaMessageT x)+ {#set rd_kafka_message_t.key_len#} p (fromIntegral $ keyLen'RdKafkaMessageT x)+ {#set rd_kafka_message_t.offset#} p (fromIntegral $ offset'RdKafkaMessageT x)+ {#set rd_kafka_message_t.payload#} p (castPtr $ payload'RdKafkaMessageT x)+ {#set rd_kafka_message_t.key#} p (castPtr $ key'RdKafkaMessageT x)+ {#set rd_kafka_message_t._private#} p (castPtr $ opaque'RdKafkaMessageT x)++{#pointer *rd_kafka_message_t as RdKafkaMessageTPtr foreign -> RdKafkaMessageT #}++data RdKafkaMetadataBrokerT = RdKafkaMetadataBrokerT+ { id'RdKafkaMetadataBrokerT :: Int+ , host'RdKafkaMetadataBrokerT :: CString+ , port'RdKafkaMetadataBrokerT :: Int+ }+ deriving stock (Show, Eq)++{#pointer *rd_kafka_metadata_broker_t as RdKafkaMetadataBrokerTPtr -> RdKafkaMetadataBrokerT #}+++instance Storable RdKafkaMetadataBrokerT where+ alignment _ = {#alignof rd_kafka_metadata_broker_t#}+ sizeOf _ = {#sizeof rd_kafka_metadata_broker_t#}+ peek p = RdKafkaMetadataBrokerT+ <$> liftM fromIntegral ({#get rd_kafka_metadata_broker_t->id #} p)+ <*> liftM id ({#get rd_kafka_metadata_broker_t->host #} p)+ <*> liftM fromIntegral ({#get rd_kafka_metadata_broker_t->port #} p)+ poke = undefined++data RdKafkaMetadataPartitionT = RdKafkaMetadataPartitionT+ { id'RdKafkaMetadataPartitionT :: Int+ , err'RdKafkaMetadataPartitionT :: RdKafkaRespErrT+ , leader'RdKafkaMetadataPartitionT :: Int+ , replicaCnt'RdKafkaMetadataPartitionT :: Int+ , replicas'RdKafkaMetadataPartitionT :: Ptr CInt32T+ , isrCnt'RdKafkaMetadataPartitionT :: Int+ , isrs'RdKafkaMetadataPartitionT :: Ptr CInt32T+ }+ deriving stock (Show, Eq)++instance Storable RdKafkaMetadataPartitionT where+ alignment _ = {#alignof rd_kafka_metadata_partition_t#}+ sizeOf _ = {#sizeof rd_kafka_metadata_partition_t#}+ peek p = RdKafkaMetadataPartitionT+ <$> liftM fromIntegral ({#get rd_kafka_metadata_partition_t->id#} p)+ <*> liftM cIntToEnum ({#get rd_kafka_metadata_partition_t->err#} p)+ <*> liftM fromIntegral ({#get rd_kafka_metadata_partition_t->leader#} p)+ <*> liftM fromIntegral ({#get rd_kafka_metadata_partition_t->replica_cnt#} p)+ <*> liftM castPtr ({#get rd_kafka_metadata_partition_t->replicas#} p)+ <*> liftM fromIntegral ({#get rd_kafka_metadata_partition_t->isr_cnt#} p)+ <*> liftM castPtr ({#get rd_kafka_metadata_partition_t->isrs#} p)++ poke = undefined++{#pointer *rd_kafka_metadata_partition_t as RdKafkaMetadataPartitionTPtr -> RdKafkaMetadataPartitionT #}++data RdKafkaMetadataTopicT = RdKafkaMetadataTopicT+ { topic'RdKafkaMetadataTopicT :: CString+ , partitionCnt'RdKafkaMetadataTopicT :: Int+ , partitions'RdKafkaMetadataTopicT :: Ptr RdKafkaMetadataPartitionT+ , err'RdKafkaMetadataTopicT :: RdKafkaRespErrT+ }+ deriving stock (Show, Eq)++instance Storable RdKafkaMetadataTopicT where+ alignment _ = {#alignof rd_kafka_metadata_topic_t#}+ sizeOf _ = {#sizeof rd_kafka_metadata_topic_t #}+ peek p = RdKafkaMetadataTopicT+ <$> liftM id ({#get rd_kafka_metadata_topic_t->topic #} p)+ <*> liftM fromIntegral ({#get rd_kafka_metadata_topic_t->partition_cnt #} p)+ <*> liftM castPtr ({#get rd_kafka_metadata_topic_t->partitions #} p)+ <*> liftM cIntToEnum ({#get rd_kafka_metadata_topic_t->err #} p)+ poke _ _ = undefined++{#pointer *rd_kafka_metadata_topic_t as RdKafkaMetadataTopicTPtr -> RdKafkaMetadataTopicT #}++data RdKafkaMetadataT = RdKafkaMetadataT+ { brokerCnt'RdKafkaMetadataT :: Int+ , brokers'RdKafkaMetadataT :: RdKafkaMetadataBrokerTPtr+ , topicCnt'RdKafkaMetadataT :: Int+ , topics'RdKafkaMetadataT :: RdKafkaMetadataTopicTPtr+ , origBrokerId'RdKafkaMetadataT :: CInt32T+ }+ deriving stock (Show, Eq)++instance Storable RdKafkaMetadataT where+ alignment _ = {#alignof rd_kafka_metadata_t#}+ sizeOf _ = {#sizeof rd_kafka_metadata_t#}+ peek p = RdKafkaMetadataT+ <$> liftM fromIntegral ({#get rd_kafka_metadata_t->broker_cnt #} p)+ <*> liftM castPtr ({#get rd_kafka_metadata_t->brokers #} p)+ <*> liftM fromIntegral ({#get rd_kafka_metadata_t->topic_cnt #} p)+ <*> liftM castPtr ({#get rd_kafka_metadata_t->topics #} p)+ <*> liftM fromIntegral ({#get rd_kafka_metadata_t->orig_broker_id #} p)+ poke _ _ = undefined++{#pointer *rd_kafka_metadata_t as RdKafkaMetadataTPtr foreign -> RdKafkaMetadataT #}++-------------------------------------------------------------------------------------------------+---- Partitions+{#fun rd_kafka_topic_partition_list_new as ^+ {`Int'} -> `RdKafkaTopicPartitionListTPtr' #}+++newRdKafkaTopicPartitionListT :: Int -> IO RdKafkaTopicPartitionListTPtr+newRdKafkaTopicPartitionListT size = mask_ $ do+ ret <- rdKafkaTopicPartitionListNew size+ managePartitionList (pure ()) ret++-- Lists returned by assignment can retain private partition references.+-- Releasing the last reference may log through a Haskell callback.+managePartitionList :: IO () -> RdKafkaTopicPartitionListTPtr -> IO RdKafkaTopicPartitionListTPtr+managePartitionList retainParent pointer = withForeignPtr pointer $ \raw -> do+ Concurrent.addForeignPtrFinalizer pointer $ do+ {# call rd_kafka_topic_partition_list_destroy #} raw+ retainParent+ pure pointer++{# fun rd_kafka_topic_partition_list_add as ^+ {`RdKafkaTopicPartitionListTPtr', `String', `Int'} -> `RdKafkaTopicPartitionTPtr' #}++{# fun rd_kafka_topic_partition_list_add_range as ^+ {`RdKafkaTopicPartitionListTPtr', `String', `Int', `Int'} -> `()' #}++{# fun rd_kafka_topic_partition_list_copy as ^+ {`RdKafkaTopicPartitionListTPtr'} -> `RdKafkaTopicPartitionListTPtr' #}++copyRdKafkaTopicPartitionList :: RdKafkaTopicPartitionListTPtr -> IO RdKafkaTopicPartitionListTPtr+copyRdKafkaTopicPartitionList pl = mask_ $ do+ cp <- rdKafkaTopicPartitionListCopy pl+ managePartitionList (touchForeignPtr pl) cp++{# fun rd_kafka_topic_partition_list_set_offset as ^+ {`RdKafkaTopicPartitionListTPtr', `String', `Int', `Int64'}+ -> `RdKafkaRespErrT' cIntToEnum #}++---- Rebalance Callback+type RdRebalanceCallback' = Ptr RdKafkaT -> CInt -> Ptr RdKafkaTopicPartitionListT -> Ptr Word8 -> IO ()+type RdRebalanceCallback = Ptr RdKafkaT -> RdKafkaRespErrT -> Ptr RdKafkaTopicPartitionListT -> IO ()++foreign import ccall safe "wrapper"+ mkRebalanceCallback :: RdRebalanceCallback' -> IO (FunPtr RdRebalanceCallback')++foreign import ccall safe "rd_kafka.h rd_kafka_conf_set_rebalance_cb"+ rdKafkaConfSetRebalanceCb' ::+ Ptr RdKafkaConfT+ -> FunPtr RdRebalanceCallback'+ -> IO ()++rdKafkaConfSetRebalanceCb :: CallbackOwner -> RdKafkaConfTPtr -> RdRebalanceCallback -> IO ()+rdKafkaConfSetRebalanceCb owner conf cb =+ installCallback owner (mkRebalanceCallback (\k e p _ -> containCallbackException (cb k (cIntToEnum e) p))) $ \cb' ->+ withForeignPtr conf $ \c -> rdKafkaConfSetRebalanceCb' c cb'++---- Delivery Callback+type DeliveryCallback' = Ptr RdKafkaT -> Ptr RdKafkaMessageT -> Word8Ptr -> IO ()+type DeliveryCallback = Ptr RdKafkaT -> Ptr RdKafkaMessageT -> IO ()++foreign import ccall safe "wrapper"+ mkDeliveryCallback :: DeliveryCallback' -> IO (FunPtr DeliveryCallback')++foreign import ccall safe "rd_kafka.h rd_kafka_conf_set_dr_msg_cb"+ rdKafkaConfSetDrMsgCb' :: Ptr RdKafkaConfT -> FunPtr DeliveryCallback' -> IO ()++rdKafkaConfSetDrMsgCb :: CallbackOwner -> RdKafkaConfTPtr -> DeliveryCallback -> IO ()+rdKafkaConfSetDrMsgCb owner conf cb =+ installCallback owner (mkDeliveryCallback (\k m _ -> cb k m)) $ \cb' ->+ withForeignPtr conf $ \c -> rdKafkaConfSetDrMsgCb' c cb'++---- Consume Callback+type ConsumeCallback = Ptr RdKafkaMessageT -> Word8Ptr -> IO ()++foreign import ccall safe "wrapper"+ mkConsumeCallback :: ConsumeCallback -> IO (FunPtr ConsumeCallback)++foreign import ccall safe "rd_kafka.h rd_kafka_conf_set_consume_cb"+ rdKafkaConfSetConsumeCb' :: Ptr RdKafkaConfT -> FunPtr ConsumeCallback -> IO ()++rdKafkaConfSetConsumeCb :: CallbackOwner -> RdKafkaConfTPtr -> ConsumeCallback -> IO ()+rdKafkaConfSetConsumeCb owner conf cb =+ installCallback owner (mkConsumeCallback (\m opaque -> containCallbackException (cb m opaque))) $ \cb' ->+ withForeignPtr conf $ \c -> rdKafkaConfSetConsumeCb' c cb'++---- Offset Commit Callback+type OffsetCommitCallback' = Ptr RdKafkaT -> CInt -> Ptr RdKafkaTopicPartitionListT -> Word8Ptr -> IO ()+type OffsetCommitCallback = Ptr RdKafkaT -> RdKafkaRespErrT -> Ptr RdKafkaTopicPartitionListT -> IO ()++foreign import ccall safe "wrapper"+ mkOffsetCommitCallback :: OffsetCommitCallback' -> IO (FunPtr OffsetCommitCallback')++foreign import ccall safe "rd_kafka.h rd_kafka_conf_set_offset_commit_cb"+ rdKafkaConfSetOffsetCommitCb' :: Ptr RdKafkaConfT -> FunPtr OffsetCommitCallback' -> IO ()++rdKafkaConfSetOffsetCommitCb :: CallbackOwner -> RdKafkaConfTPtr -> OffsetCommitCallback -> IO ()+rdKafkaConfSetOffsetCommitCb owner conf cb =+ installCallback owner (mkOffsetCommitCallback (\k e p _ -> containCallbackException (cb k (cIntToEnum e) p))) $ \cb' ->+ withForeignPtr conf $ \c -> rdKafkaConfSetOffsetCommitCb' c cb'+++----- Error Callback+type ErrorCallback' = Ptr RdKafkaT -> CInt -> CString -> Word8Ptr -> IO ()+type ErrorCallback = Ptr RdKafkaT -> RdKafkaRespErrT -> String -> IO ()++foreign import ccall safe "wrapper"+ mkErrorCallback :: ErrorCallback' -> IO (FunPtr ErrorCallback')++foreign import ccall safe "rd_kafka.h rd_kafka_conf_set_error_cb"+ rdKafkaConfSetErrorCb' :: Ptr RdKafkaConfT -> FunPtr ErrorCallback' -> IO ()++rdKafkaConfSetErrorCb :: CallbackOwner -> RdKafkaConfTPtr -> ErrorCallback -> IO ()+rdKafkaConfSetErrorCb owner conf cb =+ installCallback owner (mkErrorCallback (\k e r _ -> containCallbackException (peekCAString r >>= cb k (cIntToEnum e)))) $ \cb' ->+ withForeignPtr conf $ \c -> rdKafkaConfSetErrorCb' c cb'++---- Throttle Callback+type ThrottleCallback = Ptr RdKafkaT -> CString -> Int -> Int -> Word8Ptr -> IO ()++foreign import ccall safe "wrapper"+ mkThrottleCallback :: ThrottleCallback -> IO (FunPtr ThrottleCallback)++foreign import ccall safe "rd_kafka.h rd_kafka_conf_set_throttle_cb"+ rdKafkaConfSetThrottleCb' :: Ptr RdKafkaConfT -> FunPtr ThrottleCallback -> IO ()++rdKafkaConfSetThrottleCb :: CallbackOwner -> RdKafkaConfTPtr -> ThrottleCallback -> IO ()+rdKafkaConfSetThrottleCb owner conf cb =+ installCallback owner (mkThrottleCallback (\k name ident duration opaque -> containCallbackException (cb k name ident duration opaque))) $ \cb' ->+ withForeignPtr conf $ \c -> rdKafkaConfSetThrottleCb' c cb'++---- Log Callback+type LogCallback' = Ptr RdKafkaT -> CInt -> CString -> CString -> IO ()+type LogCallback = Ptr RdKafkaT -> Int -> String -> String -> IO ()++foreign import ccall safe "wrapper"+ mkLogCallback :: LogCallback' -> IO (FunPtr LogCallback')++foreign import ccall safe "rd_kafka.h rd_kafka_conf_set_log_cb"+ rdKafkaConfSetLogCb' :: Ptr RdKafkaConfT -> FunPtr LogCallback' -> IO ()++rdKafkaConfSetLogCb :: CallbackOwner -> RdKafkaConfTPtr -> LogCallback -> IO ()+rdKafkaConfSetLogCb owner conf cb =+ installCallback owner (mkLogCallback $ \k l f b -> containCallbackException $ do+ f' <- peekCAString f+ b' <- peekCAString b+ cb k (cIntConv l) f' b') $ \cb' ->+ withForeignPtr conf $ \c -> rdKafkaConfSetLogCb' c cb'++---- Stats Callback+type StatsCallback' = Ptr RdKafkaT -> CString -> CSize -> Word8Ptr -> IO CInt+type StatsCallback = Ptr RdKafkaT -> ByteString -> IO ()++foreign import ccall safe "wrapper"+ mkStatsCallback :: StatsCallback' -> IO (FunPtr StatsCallback')++foreign import ccall safe "rd_kafka.h rd_kafka_conf_set_stats_cb"+ rdKafkaConfSetStatsCb' :: Ptr RdKafkaConfT -> FunPtr StatsCallback' -> IO ()++rdKafkaConfSetStatsCb :: CallbackOwner -> RdKafkaConfTPtr -> StatsCallback -> IO ()+rdKafkaConfSetStatsCb owner conf cb =+ installCallback owner (mkStatsCallback $ \k j jl _ -> containCallbackException (BS.packCStringLen (j, cIntConv jl) >>= cb k) >> pure 0) $ \cb' ->+ withForeignPtr conf $ \c -> rdKafkaConfSetStatsCb' c cb'++---- Socket Callback+type SocketCallback = Int -> Int -> Int -> Word8Ptr -> IO CInt++foreign import ccall safe "wrapper"+ mkSocketCallback :: SocketCallback -> IO (FunPtr SocketCallback)++foreign import ccall safe "rd_kafka.h rd_kafka_conf_set_socket_cb"+ rdKafkaConfSetSocketCb' :: Ptr RdKafkaConfT -> FunPtr SocketCallback -> IO ()++rdKafkaConfSetSocketCb :: CallbackOwner -> RdKafkaConfTPtr -> SocketCallback -> IO ()+rdKafkaConfSetSocketCb owner conf cb =+ installCallback owner (mkSocketCallback (\domain typ protocol opaque -> containCallbackResult (-1) (cb domain typ protocol opaque))) $ \cb' ->+ withForeignPtr conf $ \c -> rdKafkaConfSetSocketCb' c cb'++{#fun rd_kafka_conf_set_opaque as ^+ {`RdKafkaConfTPtr', castPtr `Word8Ptr'} -> `()' #}++{#fun rd_kafka_opaque as ^+ {`RdKafkaTPtr'} -> `Word8Ptr' castPtr #}++{#fun rd_kafka_conf_set_default_topic_conf as ^+ {`RdKafkaConfTPtr', `RdKafkaTopicConfTPtr'} -> `()' #}++---- Partitioner Callback+type PartitionerCallback =+ Ptr RdKafkaTopicTPtr+ -> Word8Ptr -- keydata+ -> Int -- keylen+ -> Int -- partition_cnt+ -> Word8Ptr -- topic_opaque+ -> Word8Ptr -- msg_opaque+ -> IO Int++foreign import ccall safe "wrapper"+ mkPartitionerCallback :: PartitionerCallback -> IO (FunPtr PartitionerCallback)++foreign import ccall safe "rd_kafka.h rd_kafka_topic_conf_set_partitioner_cb"+ rdKafkaTopicConfSetPartitionerCb' :: Ptr RdKafkaTopicConfT -> FunPtr PartitionerCallback -> IO ()++rdKafkaTopicConfSetPartitionerCb :: CallbackOwner -> RdKafkaTopicConfTPtr -> PartitionerCallback -> IO ()+rdKafkaTopicConfSetPartitionerCb owner conf cb =+ installCallback owner (mkPartitionerCallback (\topic key keyLength partitionCount topicOpaque messageOpaque ->+ containCallbackResult (-1) (cb topic key keyLength partitionCount topicOpaque messageOpaque))) $ \cb' ->+ withForeignPtr conf $ \c -> rdKafkaTopicConfSetPartitionerCb' c cb'++---- Partition++{#fun rd_kafka_topic_partition_available as ^+ {`RdKafkaTopicTPtr', cIntConv `CInt32T'} -> `Int' #}++{#fun rd_kafka_msg_partitioner_random as ^+ { `RdKafkaTopicTPtr'+ , castPtr `Word8Ptr'+ , cIntConv `CSize'+ , cIntConv `CInt32T'+ , castPtr `Word8Ptr'+ , castPtr `Word8Ptr'}+ -> `CInt32T' cIntConv #}++{#fun rd_kafka_msg_partitioner_consistent as ^+ { `RdKafkaTopicTPtr'+ , castPtr `Word8Ptr'+ , cIntConv `CSize'+ , cIntConv `CInt32T'+ , castPtr `Word8Ptr'+ , castPtr `Word8Ptr'}+ -> `CInt32T' cIntConv #}++{#fun rd_kafka_msg_partitioner_consistent_random as ^+ { `RdKafkaTopicTPtr'+ , castPtr `Word8Ptr'+ , cIntConv `CSize'+ , cIntConv `CInt32T'+ , castPtr `Word8Ptr'+ , castPtr `Word8Ptr'}+ -> `CInt32T' cIntConv #}++---- Poll / Yield++{#fun rd_kafka_yield as ^+ {`RdKafkaTPtr'} -> `()' #}++---- Pause / Resume+{#fun rd_kafka_pause_partitions as ^+ {`RdKafkaTPtr', `RdKafkaTopicPartitionListTPtr'} -> `RdKafkaRespErrT' cIntToEnum #}++{#fun rd_kafka_resume_partitions as ^+ {`RdKafkaTPtr', `RdKafkaTopicPartitionListTPtr'} -> `RdKafkaRespErrT' cIntToEnum #}++---- EVENT++data RdKafkaEventT+{#pointer *rd_kafka_event_t as RdKafkaEventTPtr foreign -> RdKafkaEventT #}++{#fun rd_kafka_event_destroy as ^+ {`RdKafkaEventTPtr'} -> `()'#}++{#fun rd_kafka_event_error as ^+ {`RdKafkaEventTPtr'} -> `RdKafkaRespErrT' cIntToEnum #}++---- QUEUE+data RdKafkaQueueT+{#pointer *rd_kafka_queue_t as RdKafkaQueueTPtr foreign -> RdKafkaQueueT #}++{#fun rd_kafka_queue_new as ^+ {`RdKafkaTPtr'} -> `RdKafkaQueueTPtr' #}++{#fun rd_kafka_queue_destroy as ^+ {`RdKafkaQueueTPtr'} -> `()'#}+++-- | A new reference to the consumer queue; release it with+-- 'rdKafkaQueueDestroy'. NULL when the client has no consumer group.+{#fun rd_kafka_queue_get_consumer as ^+ {`RdKafkaTPtr'} -> `RdKafkaQueueTPtr' #}++-- | Write the payload to the descriptor when an op lands in the empty queue,+-- at most once until the queue is next served; fd -1 disables. librdkafka+-- copies the payload.+{#fun rd_kafka_queue_io_event_enable as ^+ {`RdKafkaQueueTPtr', `Int', castPtr `Ptr Word8', cIntConv `CSize'} -> `()' #}++-- | The callback runs on an internal librdkafka thread and must not call+-- librdkafka for the same handle. Not wrapped by the public API.+type QueueEventCallback = Ptr RdKafkaT -> Ptr () -> IO ()++{#fun rd_kafka_queue_cb_event_enable as ^+ {`RdKafkaQueueTPtr', castFunPtr `FunPtr QueueEventCallback', castPtr `Ptr ()'} -> `()' #}++newRdKafkaQueue :: RdKafkaTPtr -> IO RdKafkaQueueTPtr+newRdKafkaQueue k = mask_ $ do+ q <- rdKafkaQueueNew k+ manageQueue k q++manageQueue :: RdKafkaTPtr -> RdKafkaQueueTPtr -> IO RdKafkaQueueTPtr+manageQueue parent pointer = withForeignPtr pointer $ \raw -> do+ Concurrent.addForeignPtrFinalizer pointer $ do+ {# call rd_kafka_queue_destroy #} raw+ touchForeignPtr parent+ pure pointer++rdKafkaQueuePoll :: RdKafkaQueueTPtr -> Int -> IO (Maybe RdKafkaEventTPtr)+rdKafkaQueuePoll qPtr timeout = mask_ $+ withForeignPtr qPtr $ \qPtr' -> do+ res <- {#call rd_kafka_queue_poll#} qPtr' (fromIntegral timeout)+ if res == nullPtr+ then pure Nothing+ else do+ event <- newForeignPtr_ res+ Concurrent.addForeignPtrFinalizer event $ do+ {# call rd_kafka_event_destroy #} res+ touchForeignPtr qPtr+ pure (Just event)++{#fun rd_kafka_consume_queue as ^+ {`RdKafkaQueueTPtr', `Int'} -> `RdKafkaMessageTPtr' #}++{#fun rd_kafka_queue_forward as ^+ {`RdKafkaQueueTPtr', `RdKafkaQueueTPtr'} -> `()' #}++{#fun rd_kafka_queue_get_partition as rdKafkaQueueGetPartition'+ {`RdKafkaTPtr', `String', `Int'} -> `RdKafkaQueueTPtr' #}++rdKafkaQueueGetPartition :: RdKafkaTPtr -> String -> Int -> IO (Maybe RdKafkaQueueTPtr)+rdKafkaQueueGetPartition k t p = mask_ $ do+ ret <- rdKafkaQueueGetPartition' k t p+ withForeignPtr ret $ \realPtr ->+ if realPtr == nullPtr then return Nothing+ else do+ Just <$> manageQueue k ret++{#fun rd_kafka_consume_batch_queue as rdKafkaConsumeBatchQueue'+ {`RdKafkaQueueTPtr', `Int', castPtr `Ptr (Ptr RdKafkaMessageT)', cIntConv `CSize'}+ -> `Int' cIntConv #}++-- The caller masks acquisition and releases every returned member as one+-- scope. These ForeignPtrs deliberately have no individual finalizers.+rdKafkaConsumeBatchQueue :: RdKafkaQueueTPtr -> Int -> Int -> IO (Either RdKafkaRespErrT [RdKafkaMessageTPtr])+rdKafkaConsumeBatchQueue qptr timeout batchSize = do+ allocaArray batchSize $ \pArr -> do+ rSize <- rdKafkaConsumeBatchQueue' qptr timeout pArr (fromIntegral batchSize)+ if rSize < 0 then do+ (Errno errorNumber) <- getErrno+ pure (Left (rdKafkaErrno2err (fromIntegral errorNumber)))+ else Right <$> (peekArray rSize pArr >>= traverse newForeignPtr_)++-------------------------------------------------------------------------------------------------+---- High-level KafkaConsumer++{#fun rd_kafka_subscribe as ^+ {`RdKafkaTPtr', `RdKafkaTopicPartitionListTPtr'}+ -> `RdKafkaRespErrT' cIntToEnum #}++{#fun rd_kafka_unsubscribe as ^+ {`RdKafkaTPtr'}+ -> `RdKafkaRespErrT' cIntToEnum #}++{#fun rd_kafka_subscription as rdKafkaSubscription'+ {`RdKafkaTPtr', alloca- `Ptr RdKafkaTopicPartitionListT' peekPtr*}+ -> `RdKafkaRespErrT' cIntToEnum #}++rdKafkaSubscription :: RdKafkaTPtr -> IO (Either RdKafkaRespErrT RdKafkaTopicPartitionListTPtr)+rdKafkaSubscription k = mask_ $ do+ (err, sub) <- rdKafkaSubscription' k+ case err of+ RdKafkaRespErrNoError ->+ newForeignPtr_ sub >>= fmap Right . managePartitionList (touchForeignPtr k)+ e -> return (Left e)++{#fun rd_kafka_consumer_poll as ^+ {`RdKafkaTPtr', `Int'} -> `RdKafkaMessageTPtr' #}++pollRdKafkaConsumer :: RdKafkaTPtr -> Int -> IO RdKafkaMessageTPtr+pollRdKafkaConsumer k t = do+ m <- rdKafkaConsumerPoll k t+ withForeignPtr m $ \raw -> Concurrent.addForeignPtrFinalizer m $ do+ {# call rd_kafka_message_destroy #} raw+ touchForeignPtr k+ pure m++{#fun rd_kafka_consumer_close as ^+ {`RdKafkaTPtr'} -> `RdKafkaRespErrT' cIntToEnum #}++{#fun rd_kafka_poll_set_consumer as ^+ {`RdKafkaTPtr'} -> `RdKafkaRespErrT' cIntToEnum #}++{#fun rd_kafka_assignment_lost as ^+ {`RdKafkaTPtr'} -> `Bool' #}++{#fun rd_kafka_consumer_closed as ^+ {`RdKafkaTPtr'} -> `Bool' #}++-- rd_kafka_assign+{#fun rd_kafka_assign as ^+ {`RdKafkaTPtr', `RdKafkaTopicPartitionListTPtr'}+ -> `RdKafkaRespErrT' cIntToEnum #}++{#fun rd_kafka_rebalance_protocol as ^+ {`RdKafkaTPtr'} -> `String' #}++{#fun rd_kafka_assignment as rdKafkaAssignment'+ {`RdKafkaTPtr', alloca- `Ptr RdKafkaTopicPartitionListT' peekPtr* }+ -> `RdKafkaRespErrT' cIntToEnum #}++rdKafkaAssignment :: RdKafkaTPtr -> IO (Either RdKafkaRespErrT RdKafkaTopicPartitionListTPtr)+rdKafkaAssignment k = mask_ $ do+ (err, ass) <- rdKafkaAssignment' k+ case err of+ RdKafkaRespErrNoError ->+ newForeignPtr_ ass >>= fmap Right . managePartitionList (touchForeignPtr k)+ e -> return (Left e)++{#fun rd_kafka_commit as ^+ {`RdKafkaTPtr', `RdKafkaTopicPartitionListTPtr', boolToCInt `Bool'}+ -> `RdKafkaRespErrT' cIntToEnum #}++{#fun rd_kafka_commit_message as ^+ {`RdKafkaTPtr', `RdKafkaMessageTPtr', boolToCInt `Bool'}+ -> `RdKafkaRespErrT' cIntToEnum #}++{#fun rd_kafka_committed as ^+ {`RdKafkaTPtr', `RdKafkaTopicPartitionListTPtr', `Int'}+ -> `RdKafkaRespErrT' cIntToEnum #}++{#fun rd_kafka_position as ^+ {`RdKafkaTPtr', `RdKafkaTopicPartitionListTPtr'}+ -> `RdKafkaRespErrT' cIntToEnum #}++-------------------------------------------------------------------------------------------------+---- Groups+data RdKafkaGroupMemberInfoT = RdKafkaGroupMemberInfoT+ { memberId'RdKafkaGroupMemberInfoT :: CString+ , clientId'RdKafkaGroupMemberInfoT :: CString+ , clientHost'RdKafkaGroupMemberInfoT :: CString+ , memberMetadata'RdKafkaGroupMemberInfoT :: Word8Ptr+ , memberMetadataSize'RdKafkaGroupMemberInfoT :: Int+ , memberAssignment'RdKafkaGroupMemberInfoT :: Word8Ptr+ , memberAssignmentSize'RdKafkaGroupMemberInfoT :: Int }++instance Storable RdKafkaGroupMemberInfoT where+ alignment _ = {#alignof rd_kafka_group_member_info#}+ sizeOf _ = {#sizeof rd_kafka_group_member_info#}+ peek p = RdKafkaGroupMemberInfoT+ <$> liftM id ({#get rd_kafka_group_member_info->member_id #} p)+ <*> liftM id ({#get rd_kafka_group_member_info->client_id #} p)+ <*> liftM id ({#get rd_kafka_group_member_info->client_host #} p)+ <*> liftM castPtr ({#get rd_kafka_group_member_info->member_metadata #} p)+ <*> liftM fromIntegral ({#get rd_kafka_group_member_info->member_metadata_size #} p)+ <*> liftM castPtr ({#get rd_kafka_group_member_info->member_assignment #} p)+ <*> liftM fromIntegral ({#get rd_kafka_group_member_info->member_assignment_size #} p)+ poke p x = do+ {#set rd_kafka_group_member_info.member_id#} p (id $ memberId'RdKafkaGroupMemberInfoT x)+ {#set rd_kafka_group_member_info.client_id#} p (id $ clientId'RdKafkaGroupMemberInfoT x)+ {#set rd_kafka_group_member_info.client_host#} p (id $ clientHost'RdKafkaGroupMemberInfoT x)+ {#set rd_kafka_group_member_info.member_metadata#} p (castPtr $ memberMetadata'RdKafkaGroupMemberInfoT x)+ {#set rd_kafka_group_member_info.member_metadata_size#} p (fromIntegral $ memberMetadataSize'RdKafkaGroupMemberInfoT x)+ {#set rd_kafka_group_member_info.member_assignment#} p (castPtr $ memberAssignment'RdKafkaGroupMemberInfoT x)+ {#set rd_kafka_group_member_info.member_assignment_size#} p (fromIntegral $ memberAssignmentSize'RdKafkaGroupMemberInfoT x)++{#pointer *rd_kafka_group_member_info as RdKafkaGroupMemberInfoTPtr -> RdKafkaGroupMemberInfoT #}++data RdKafkaGroupInfoT = RdKafkaGroupInfoT+ { broker'RdKafkaGroupInfoT :: RdKafkaMetadataBrokerTPtr+ , group'RdKafkaGroupInfoT :: CString+ , err'RdKafkaGroupInfoT :: RdKafkaRespErrT+ , state'RdKafkaGroupInfoT :: CString+ , protocolType'RdKafkaGroupInfoT :: CString+ , protocol'RdKafkaGroupInfoT :: CString+ , members'RdKafkaGroupInfoT :: RdKafkaGroupMemberInfoTPtr+ , memberCnt'RdKafkaGroupInfoT :: Int }++instance Storable RdKafkaGroupInfoT where+ alignment _ = {#alignof rd_kafka_group_info #}+ sizeOf _ = {#sizeof rd_kafka_group_info #}+ peek p = RdKafkaGroupInfoT+ <$> liftM castPtr ({#get rd_kafka_group_info->broker #} p)+ <*> liftM id ({#get rd_kafka_group_info->group #} p)+ <*> liftM cIntToEnum ({#get rd_kafka_group_info->err #} p)+ <*> liftM id ({#get rd_kafka_group_info->state #} p)+ <*> liftM id ({#get rd_kafka_group_info->protocol_type #} p)+ <*> liftM id ({#get rd_kafka_group_info->protocol #} p)+ <*> liftM castPtr ({#get rd_kafka_group_info->members #} p)+ <*> liftM fromIntegral ({#get rd_kafka_group_info->member_cnt #} p)+ poke p x = do+ {#set rd_kafka_group_info.broker#} p (castPtr $ broker'RdKafkaGroupInfoT x)+ {#set rd_kafka_group_info.group#} p (id $ group'RdKafkaGroupInfoT x)+ {#set rd_kafka_group_info.err#} p (enumToCInt $ err'RdKafkaGroupInfoT x)+ {#set rd_kafka_group_info.state#} p (id $ state'RdKafkaGroupInfoT x)+ {#set rd_kafka_group_info.protocol_type#} p (id $ protocolType'RdKafkaGroupInfoT x)+ {#set rd_kafka_group_info.protocol#} p (id $ protocol'RdKafkaGroupInfoT x)+ {#set rd_kafka_group_info.members#} p (castPtr $ members'RdKafkaGroupInfoT x)+ {#set rd_kafka_group_info.member_cnt#} p (fromIntegral $ memberCnt'RdKafkaGroupInfoT x)++{#pointer *rd_kafka_group_info as RdKafkaGroupInfoTPtr foreign -> RdKafkaGroupInfoT #}++data RdKafkaGroupListT = RdKafkaGroupListT+ { groups'RdKafkaGroupListT :: Ptr RdKafkaGroupInfoT+ , groupCnt'RdKafkaGroupListT :: Int }++instance Storable RdKafkaGroupListT where+ alignment _ = {#alignof rd_kafka_group_list #}+ sizeOf _ = {#sizeof rd_kafka_group_list #}+ peek p = RdKafkaGroupListT+ <$> liftM castPtr ({#get rd_kafka_group_list->groups #} p)+ <*> liftM fromIntegral ({#get rd_kafka_group_list->group_cnt #} p)+ poke p x = do+ {#set rd_kafka_group_list.groups#} p (castPtr $ groups'RdKafkaGroupListT x)+ {#set rd_kafka_group_list.group_cnt#} p (fromIntegral $ groupCnt'RdKafkaGroupListT x)++{#pointer *rd_kafka_group_list as RdKafkaGroupListTPtr foreign -> RdKafkaGroupListT #}++{#fun rd_kafka_list_groups as rdKafkaListGroups'+ {`RdKafkaTPtr', `CString', alloca- `Ptr RdKafkaGroupListT' peek*, `Int'}+ -> `RdKafkaRespErrT' cIntToEnum #}++foreign import ccall "rdkafka.h &rd_kafka_group_list_destroy"+ rdKafkaGroupListDestroyF :: FinalizerPtr RdKafkaGroupListT++foreign import ccall "rdkafka.h &rd_kafka_group_list_destroy"+ rdKafkaGroupListDestroy :: FinalizerPtr RdKafkaGroupListT++rdKafkaListGroups :: RdKafkaTPtr -> Maybe String -> Int -> IO (Either RdKafkaRespErrT RdKafkaGroupListTPtr)+rdKafkaListGroups k g t = case g of+ Nothing -> listGroups nullPtr+ Just strGrp -> withCString strGrp listGroups+ where+ listGroups grp = do+ (err, res) <- rdKafkaListGroups' k grp t+ case err of+ RdKafkaRespErrNoError -> Right <$> newForeignPtr rdKafkaGroupListDestroy res+ e -> return $ Left e+-------------------------------------------------------------------------------------------------++-- rd_kafka_message++foreign import ccall unsafe "rdkafka.h rd_kafka_message_destroy"+ rdKafkaMessageDestroy :: Ptr RdKafkaMessageT -> IO ()++{#fun rd_kafka_query_watermark_offsets as rdKafkaQueryWatermarkOffsets'+ {`RdKafkaTPtr', `String', cIntConv `CInt32T',+ alloca- `Int64' peekInt64Conv*, alloca- `Int64' peekInt64Conv*,+ cIntConv `Int'+ } -> `RdKafkaRespErrT' cIntToEnum #}+++rdKafkaQueryWatermarkOffsets :: RdKafkaTPtr -> String -> Int -> Int -> IO (Either RdKafkaRespErrT (Int64, Int64))+rdKafkaQueryWatermarkOffsets kafka topic partition timeout = do+ (err, l, h) <- rdKafkaQueryWatermarkOffsets' kafka topic (cIntConv partition) timeout+ return $ case err of+ RdKafkaRespErrNoError -> Right (cIntConv l, cIntConv h)+ e -> Left e++{#pointer *rd_kafka_timestamp_type_t as RdKafkaTimestampTypeTPtr foreign -> RdKafkaTimestampTypeT #}++instance Storable RdKafkaTimestampTypeT where+ sizeOf _ = {#sizeof rd_kafka_timestamp_type_t#}+ alignment _ = {#alignof rd_kafka_timestamp_type_t#}+ peek p = cIntToEnum <$> peek (castPtr p)+ poke p x = poke (castPtr p) (enumToCInt x)++{#fun rd_kafka_message_timestamp as rdKafkaReadTimestamp'+ {castPtr `Ptr RdKafkaMessageT', `RdKafkaTimestampTypeTPtr'} -> `CInt64T' cIntConv #}++{#fun rd_kafka_message_timestamp as ^+ {`RdKafkaMessageTPtr', `RdKafkaTimestampTypeTPtr'} -> `CInt64T' cIntConv #}++{#fun rd_kafka_offsets_for_times as rdKafkaOffsetsForTimes+ {`RdKafkaTPtr', `RdKafkaTopicPartitionListTPtr', `Int'} -> `RdKafkaRespErrT' cIntToEnum #}++-- rd_kafka_conf+{#fun rd_kafka_conf_new as ^+ {} -> `RdKafkaConfTPtr' #}++foreign import ccall unsafe "rdkafka.h &rd_kafka_conf_destroy"+ rdKafkaConfDestroy :: FinalizerPtr RdKafkaConfT++{#fun rd_kafka_conf_dup as ^+ {`RdKafkaConfTPtr'} -> `RdKafkaConfTPtr' #}++{#fun rd_kafka_conf_set as ^+ {`RdKafkaConfTPtr', `String', `String', id `CCharBufPointer', cIntConv `CSize'}+ -> `RdKafkaConfResT' cIntToEnum #}++-- Borrowed, read-only configuration: the client owns it.+{#fun rd_kafka_conf as ^ {`RdKafkaTPtr'} -> `RdKafkaConfTPtr' #}++{#fun rd_kafka_conf_get as ^+ {`RdKafkaConfTPtr', `String', id `Ptr CChar', castPtr `Ptr CSize'}+ -> `RdKafkaConfResT' cIntToEnum #}++-- | Read the actual native request timeout, including defaults and overrides.+-- No configuration ownership is transferred by rd_kafka_conf().+rdKafkaSocketTimeout :: RdKafkaTPtr -> IO (Either String Int)+rdKafkaSocketTimeout kafka = withForeignPtr kafka $ \_ -> do+ conf <- rdKafkaConf kafka+ allocaBytes 32 $ \buffer -> alloca $ \size -> do+ poke size (32 :: CSize)+ result <- rdKafkaConfGet conf "socket.timeout.ms" buffer size+ required <- peek size+ if result /= RdKafkaConfOk || required > 32+ then pure (Left "could not read socket.timeout.ms from the native client")+ else do+ value <- peekCString buffer+ pure $ case (readMaybe value :: Maybe Integer) of+ Just milliseconds | milliseconds > 0 && milliseconds <= toInteger (maxBound :: CInt) -> Right (fromInteger milliseconds)+ _ -> Left "invalid socket.timeout.ms value from the native client"++newRdKafkaConfT :: IO RdKafkaConfTPtr+newRdKafkaConfT = mask_ $ do+ ret <- rdKafkaConfNew+ addForeignPtrFinalizer rdKafkaConfDestroy ret+ return ret++{#fun rd_kafka_conf_dump as ^+ {`RdKafkaConfTPtr', castPtr `CSizePtr'} -> `Ptr CString' id #}++{#fun rd_kafka_conf_dump_free as ^+ {id `Ptr CString', cIntConv `CSize'} -> `()' #}++{#fun rd_kafka_conf_properties_show as ^+ {`CFilePtr'} -> `()' #}++-- rd_kafka_topic_conf+{#fun rd_kafka_topic_conf_new as ^+ {} -> `RdKafkaTopicConfTPtr' #}++{#fun rd_kafka_topic_conf_dup as ^+ {`RdKafkaTopicConfTPtr'} -> `RdKafkaTopicConfTPtr' #}++foreign import ccall unsafe "rdkafka.h &rd_kafka_topic_conf_destroy"+ rdKafkaTopicConfDestroy :: FinalizerPtr RdKafkaTopicConfT++{#fun rd_kafka_topic_conf_set as ^+ {`RdKafkaTopicConfTPtr', `String', `String', id `CCharBufPointer', cIntConv `CSize'}+ -> `RdKafkaConfResT' cIntToEnum #}++newRdKafkaTopicConfT :: IO RdKafkaTopicConfTPtr+newRdKafkaTopicConfT = mask_ $ do+ ret <- rdKafkaTopicConfNew+ addForeignPtrFinalizer rdKafkaTopicConfDestroy ret+ return ret++{#fun rd_kafka_topic_conf_dump as ^+ {`RdKafkaTopicConfTPtr', castPtr `CSizePtr'} -> `Ptr CString' id #}++-- rd_kafka+{#fun rd_kafka_new as ^+ {enumToCInt `RdKafkaTypeT', `RdKafkaConfTPtr', id `CCharBufPointer', cIntConv `CSize'}+ -> `RdKafkaTPtr' #}++newRdKafkaT :: CallbackOwner -> RdKafkaTypeT -> RdKafkaConfTPtr -> IO (Either Text RdKafkaTPtr)+newRdKafkaT owner kafkaType confPtr = mask_ $+ allocaBytes nErrorBytes $ \charPtr -> do+ checkCallbackOwner owner+ duper <- rdKafkaConfDup confPtr+ ret <- rdKafkaNew kafkaType duper charPtr (fromIntegral nErrorBytes)+ withForeignPtr ret $ \realPtr ->+ if realPtr == nullPtr+ then do+ -- rd_kafka_new consumes its configuration only on success.+ withForeignPtr duper $ \duplicate -> {# call rd_kafka_conf_destroy #} duplicate+ releaseCallbackOwner owner+ Left <$> peekCText charPtr+ else do+ attachCallbackOwner owner+ -- Native shutdown may call Haskell. Keep every registration+ -- alive through its final callback, then release exactly once.+ Concurrent.addForeignPtrFinalizer ret $ mask_ $ do+ {# call rd_kafka_destroy_flags #} realPtr 0x8+ releaseCallbackOwner owner+ pure (Right ret)++{#fun rd_kafka_brokers_add as ^+ {`RdKafkaTPtr', `String'} -> `Int' #}++{#fun rd_kafka_set_log_level as ^+ {`RdKafkaTPtr', `Int'} -> `()' #}++-- | Returns the error code and human readable description of the fatal error+-- that was previously raised on this client, or 'RdKafkaRespErrNoError' (and an+-- empty description) if no fatal error has been raised.+--+-- A fatal error permanently degrades the client and there is no recovery from+-- it other than destroying the instance. For the high-level consumer,+-- librdkafka additionally propagates the fact that a fatal error was raised as+-- a consumer error carrying the generic code @RD_KAFKA_RESP_ERR__FATAL@; this+-- call is how the /original/ cause behind that generic wrapper is recovered.+--+-- Cheap enough to call on every poll: when no fatal error has been raised the C+-- implementation performs a single atomic read and returns, taking no locks and+-- writing nothing to the buffer.+rdKafkaFatalError :: RdKafkaTPtr -> IO (RdKafkaRespErrT, Text)+rdKafkaFatalError k =+ allocaBytes nErrorBytes $ \charPtr -> do+ pokeByteOff charPtr 0 (0 :: CChar)+ code <- withForeignPtr k $ \kPtr ->+ {# call rd_kafka_fatal_error #} kPtr charPtr (fromIntegral nErrorBytes)+ description <- peekCText charPtr+ pure (cIntToEnum code, description)++-- rd_kafka consume++{#fun rd_kafka_consume_start as rdKafkaConsumeStartInternal+ {`RdKafkaTopicTPtr', cIntConv `CInt32T', cIntConv `CInt64T'} -> `Int' #}++rdKafkaConsumeStart :: RdKafkaTopicTPtr -> Int -> Int64 -> IO (Maybe String)+rdKafkaConsumeStart topicPtr partition offset = do+ i <- rdKafkaConsumeStartInternal topicPtr (fromIntegral partition) (fromIntegral offset)+ case i of+ -1 -> kafkaErrnoString >>= return . Just+ _ -> return Nothing+{#fun rd_kafka_consume_stop as rdKafkaConsumeStopInternal+ {`RdKafkaTopicTPtr', cIntConv `CInt32T'} -> `Int' #}++{#fun rd_kafka_seek as rdKafkaSeek+ {`RdKafkaTopicTPtr', `Int32', `Int64', `Int'} -> `RdKafkaRespErrT' cIntToEnum #}++{#fun rd_kafka_consume as ^+ {`RdKafkaTopicTPtr', cIntConv `CInt32T', `Int'} -> `RdKafkaMessageTPtr' #}++{#fun rd_kafka_consume_batch as ^+ {`RdKafkaTopicTPtr', cIntConv `CInt32T', `Int', castPtr `Ptr (Ptr RdKafkaMessageT)', cIntConv `CSize'}+ -> `CSize' cIntConv #}++rdKafkaConsumeStop :: RdKafkaTopicTPtr -> Int -> IO (Maybe String)+rdKafkaConsumeStop topicPtr partition = do+ i <- rdKafkaConsumeStopInternal topicPtr (fromIntegral partition)+ case i of+ -1 -> kafkaErrnoString >>= return . Just+ _ -> return Nothing++{#fun rd_kafka_offset_store as rdKafkaOffsetStore+ {`RdKafkaTopicTPtr', cIntConv `CInt32T', cIntConv `CInt64T'}+ -> `RdKafkaRespErrT' cIntToEnum #}++{#fun rd_kafka_offsets_store as rdKafkaOffsetsStore+ {`RdKafkaTPtr', `RdKafkaTopicPartitionListTPtr'}+ -> `RdKafkaRespErrT' cIntToEnum #}++-- rd_kafka produce++{#fun rd_kafka_produce as ^+ {`RdKafkaTopicTPtr', cIntConv `CInt32T', `Int', castPtr `Word8Ptr',+ cIntConv `CSize', castPtr `Word8Ptr', cIntConv `CSize', castPtr `Ptr ()'}+ -> `Int' #}++{#fun rd_kafka_produce_batch as ^+ {`RdKafkaTopicTPtr', cIntConv `CInt32T', `Int', `RdKafkaMessageTPtr', `Int'} -> `Int' #}++-- Serves delivery callbacks while it waits, so it must be a safe call.+{#fun rd_kafka_flush as ^+ {`RdKafkaTPtr', `Int'} -> `RdKafkaRespErrT' cIntToEnum #}++{#fun rd_kafka_purge as ^+ {`RdKafkaTPtr', `Int'} -> `RdKafkaRespErrT' cIntToEnum #}++rdKafkaPurgeFQueue :: Int+rdKafkaPurgeFQueue = {#const RD_KAFKA_PURGE_F_QUEUE #}++rdKafkaPurgeFInflight :: Int+rdKafkaPurgeFInflight = {#const RD_KAFKA_PURGE_F_INFLIGHT #}++rdKafkaPurgeFNonBlocking :: Int+rdKafkaPurgeFNonBlocking = {#const RD_KAFKA_PURGE_F_NON_BLOCKING #}+++-- rd_kafka_metadata++{#fun rd_kafka_metadata as rdKafkaMetadata'+ {`RdKafkaTPtr', boolToCInt `Bool', `RdKafkaTopicTPtr',+ alloca- `Ptr RdKafkaMetadataT' peekPtr*, `Int'}+ -> `RdKafkaRespErrT' cIntToEnum #}++foreign import ccall unsafe "rdkafka.h &rd_kafka_metadata_destroy"+ rdKafkaMetadataDestroy :: FinalizerPtr RdKafkaMetadataT++rdKafkaMetadata :: RdKafkaTPtr -> Bool -> Maybe RdKafkaTopicTPtr -> Int -> IO (Either RdKafkaRespErrT RdKafkaMetadataTPtr)+rdKafkaMetadata k allTopics mt timeout = do+ tptr <- maybe (newForeignPtr_ nullPtr) pure mt+ (err, res) <- rdKafkaMetadata' k allTopics tptr timeout+ case err of+ RdKafkaRespErrNoError -> Right <$> newForeignPtr rdKafkaMetadataDestroy res+ e -> return (Left e)++{#fun rd_kafka_poll as ^+ {`RdKafkaTPtr', `Int'} -> `Int' #}++{#fun rd_kafka_outq_len as ^+ {`RdKafkaTPtr'} -> `Int' #}++{#fun rd_kafka_dump as ^+ {`CFilePtr', `RdKafkaTPtr'} -> `()' #}++-- rd_kafka_topic+{#fun rd_kafka_topic_name as ^+ {`RdKafkaTopicTPtr'} -> `String' #}++{#fun rd_kafka_topic_new as ^+ {`RdKafkaTPtr', `String', `RdKafkaTopicConfTPtr'} -> `RdKafkaTopicTPtr' #}++{# fun rd_kafka_topic_destroy as ^+ {castPtr `Ptr RdKafkaTopicT'} -> `()' #}++destroyUnmanagedRdKafkaTopic :: RdKafkaTopicTPtr -> IO ()+destroyUnmanagedRdKafkaTopic ptr =+ withForeignPtr ptr rdKafkaTopicDestroy+++newUnmanagedRdKafkaTopicT :: RdKafkaTPtr -> String -> Maybe RdKafkaTopicConfTPtr -> IO (Either String RdKafkaTopicTPtr)+newUnmanagedRdKafkaTopicT kafkaPtr topic topicConfPtr = mask_ $ do+ duper <- maybe (newForeignPtr_ nullPtr) rdKafkaTopicConfDup topicConfPtr+ ret <- rdKafkaTopicNew kafkaPtr topic duper+ withForeignPtr ret $ \realPtr ->+ if realPtr == nullPtr then kafkaErrnoString >>= return . Left+ else return $ Right ret++newRdKafkaTopicT :: RdKafkaTPtr -> String -> Maybe RdKafkaTopicConfTPtr -> IO (Either String RdKafkaTopicTPtr)+newRdKafkaTopicT kafkaPtr topic topicConfPtr = mask_ $ do+ res <- newUnmanagedRdKafkaTopicT kafkaPtr topic topicConfPtr+ _ <- traverse (\topicPtr -> withForeignPtr topicPtr $ \realPtr ->+ Concurrent.addForeignPtrFinalizer topicPtr $ do+ {# call rd_kafka_topic_destroy #} realPtr+ touchForeignPtr kafkaPtr) res+ return res++-------------------------------------------------------------------------------------------------+---- Errors++data RdKafkaErrorT+{#pointer *rd_kafka_error_t as RdKafkaErrorTPtr -> RdKafkaErrorT #}++{#fun rd_kafka_error_code as ^+ {`RdKafkaErrorTPtr'} -> `RdKafkaRespErrT' cIntToEnum #}++{#fun rd_kafka_error_destroy as ^+ {`RdKafkaErrorTPtr'} -> `()' #}++-------------------------------------------------------------------------------------------------+---- Security++{#fun rd_kafka_sasl_set_credentials as rdKafkaSaslSetCredentials'+ {`RdKafkaTPtr', `String', `String'} -> `RdKafkaErrorTPtr' #}++-- | Replace the SASL username and password used for future authentications.+-- A NULL error object means success; a non-NULL one is destroyed after its+-- code is read.+rdKafkaSaslSetCredentials :: RdKafkaTPtr -> String -> String -> IO RdKafkaRespErrT+rdKafkaSaslSetCredentials k username password = mask_ $ do+ err <- rdKafkaSaslSetCredentials' k username password+ if err == nullPtr+ then pure RdKafkaRespErrNoError+ else rdKafkaErrorCode err `finally` rdKafkaErrorDestroy err+-------------------------------------------------------------------------------------------------+---- Headers++data RdKafkaHeadersT+{#pointer *rd_kafka_headers_t as RdKafkaHeadersTPtr -> RdKafkaHeadersT #}++{#fun rd_kafka_header_get_all as ^+ {`RdKafkaHeadersTPtr', cIntConv `CSize', castPtr `Ptr CString', castPtr `Ptr Word8Ptr', castPtr `CSizePtr'} -> `RdKafkaRespErrT' cIntToEnum #}++{#fun rd_kafka_message_headers as ^+ {castPtr `Ptr RdKafkaMessageT', alloca- `RdKafkaHeadersTPtr' peekPtr*} -> `RdKafkaRespErrT' cIntToEnum #}++--- Produceva api++{#enum rd_kafka_vtype_t as ^ {underscoreToCase} #}+deriving stock instance Show RdKafkaVtypeT+deriving stock instance Eq RdKafkaVtypeT++data RdKafkaVuT+ = Topic'RdKafkaVu CString+ | TopicHandle'RdKafkaVu (Ptr RdKafkaTopicT)+ | Partition'RdKafkaVu CInt32T+ | Value'RdKafkaVu Word8Ptr CSize+ | Key'RdKafkaVu Word8Ptr CSize+ | MsgFlags'RdKafkaVu CInt+ | Timestamp'RdKafkaVu CInt64T+ | Opaque'RdKafkaVu (Ptr ())+ | Header'RdKafkaVu CString Word8Ptr CSize+ | Headers'RdKafkaVu (Ptr RdKafkaHeadersT) -- The message object will assume ownership of the headers (unless produceva() fails)+ | End'RdKafkaVu++{#pointer *rd_kafka_vu_t as RdKafkaVuTPtr foreign -> RdKafkaVuT #}++instance Storable RdKafkaVuT where+ alignment _ = {#alignof rd_kafka_vu_t #}+ sizeOf _ = {#sizeof rd_kafka_vu_t #}+ peek p = {#get rd_kafka_vu_t->vtype #} p >>= \a -> case cIntToEnum a of+ RdKafkaVtypeEnd -> return End'RdKafkaVu+ RdKafkaVtypeTopic -> Topic'RdKafkaVu <$> ({#get rd_kafka_vu_t->u.cstr #} p)+ RdKafkaVtypeMsgflags -> MsgFlags'RdKafkaVu <$> ({#get rd_kafka_vu_t->u.i #} p)+ RdKafkaVtypeTimestamp -> Timestamp'RdKafkaVu <$> ({#get rd_kafka_vu_t->u.i64 #} p)+ RdKafkaVtypePartition -> Partition'RdKafkaVu <$> ({#get rd_kafka_vu_t->u.i32 #} p)+ RdKafkaVtypeHeaders -> Headers'RdKafkaVu <$> ({#get rd_kafka_vu_t->u.headers #} p)+ RdKafkaVtypeValue -> do+ nm <- liftM castPtr ({#get rd_kafka_vu_t->u.mem.ptr #} p)+ sz <- ({#get rd_kafka_vu_t->u.mem.size #} p)+ return $ Value'RdKafkaVu nm (cIntConv sz)+ RdKafkaVtypeKey -> do+ nm <- liftM castPtr ({#get rd_kafka_vu_t->u.mem.ptr #} p)+ sz <- ({#get rd_kafka_vu_t->u.mem.size #} p)+ return $ Key'RdKafkaVu nm (cIntConv sz)+ RdKafkaVtypeRkt -> TopicHandle'RdKafkaVu <$> ({#get rd_kafka_vu_t->u.rkt #} p)+ RdKafkaVtypeOpaque -> Opaque'RdKafkaVu <$> ({#get rd_kafka_vu_t->u.ptr #} p)+ RdKafkaVtypeHeader -> do+ nm <- ({#get rd_kafka_vu_t->u.header.name #} p)+ val' <- liftM castPtr ({#get rd_kafka_vu_t->u.header.val #} p)+ sz <- ({#get rd_kafka_vu_t->u.header.size #} p)+ return $ Header'RdKafkaVu nm val' (cIntConv sz)+ poke p End'RdKafkaVu =+ {#set rd_kafka_vu_t.vtype #} p (enumToCInt RdKafkaVtypeEnd)+ poke p (Topic'RdKafkaVu str) = do+ {#set rd_kafka_vu_t.vtype #} p (enumToCInt RdKafkaVtypeTopic)+ {#set rd_kafka_vu_t.u.cstr #} p str+ poke p (Timestamp'RdKafkaVu tms) = do+ {#set rd_kafka_vu_t.vtype #} p (enumToCInt RdKafkaVtypeTimestamp)+ {#set rd_kafka_vu_t.u.i64 #} p tms+ poke p (Partition'RdKafkaVu prt) = do+ {#set rd_kafka_vu_t.vtype #} p (enumToCInt RdKafkaVtypePartition)+ {#set rd_kafka_vu_t.u.i32 #} p prt+ poke p (MsgFlags'RdKafkaVu flags) = do+ {#set rd_kafka_vu_t.vtype #} p (enumToCInt RdKafkaVtypeMsgflags)+ {#set rd_kafka_vu_t.u.i #} p flags+ poke p (Headers'RdKafkaVu headers) = do+ {#set rd_kafka_vu_t.vtype #} p (enumToCInt RdKafkaVtypeHeaders)+ {#set rd_kafka_vu_t.u.headers #} p headers+ poke p (TopicHandle'RdKafkaVu tphandle) = do+ {#set rd_kafka_vu_t.vtype #} p (enumToCInt RdKafkaVtypeRkt)+ {#set rd_kafka_vu_t.u.rkt #} p tphandle+ poke p (Value'RdKafkaVu pl sz) = do+ {#set rd_kafka_vu_t.vtype #} p (enumToCInt RdKafkaVtypeValue)+ {#set rd_kafka_vu_t.u.mem.size #} p (cIntConv sz)+ {#set rd_kafka_vu_t.u.mem.ptr #} p (castPtr pl)+ poke p (Key'RdKafkaVu pl sz) = do+ {#set rd_kafka_vu_t.vtype #} p (enumToCInt RdKafkaVtypeKey)+ {#set rd_kafka_vu_t.u.mem.size #} p (cIntConv sz)+ {#set rd_kafka_vu_t.u.mem.ptr #} p (castPtr pl)+ poke p (Opaque'RdKafkaVu ptr') = do+ {#set rd_kafka_vu_t.vtype #} p (enumToCInt RdKafkaVtypeOpaque)+ {#set rd_kafka_vu_t.u.ptr #} p ptr'+ poke p (Header'RdKafkaVu nm val' sz) = do+ {#set rd_kafka_vu_t.vtype #} p (enumToCInt RdKafkaVtypeHeader)+ {#set rd_kafka_vu_t.u.header.size #} p (cIntConv sz)+ {#set rd_kafka_vu_t.u.header.name #} p nm+ {#set rd_kafka_vu_t.u.header.val #} p (castPtr val')++{#fun rd_kafka_produceva as rdKafkaMessageProduceVa'+ {`RdKafkaTPtr', `RdKafkaVuTPtr', `CLong'} -> `RdKafkaErrorTPtr' #}++rdKafkaMessageProduceVa :: RdKafkaTPtr -> [RdKafkaVuT] -> IO RdKafkaErrorTPtr+rdKafkaMessageProduceVa kafkaPtr vts = withArrayLen vts $ \i arrPtr -> do+ fptr <- newForeignPtr_ arrPtr+ rdKafkaMessageProduceVa' kafkaPtr fptr (cIntConv i)++--- Transactional api++{#fun rd_kafka_init_transactions as rdKafkaInitTransactions+ {`RdKafkaTPtr', `Int'} -> `RdKafkaErrorTPtr' #}++{#fun rd_kafka_begin_transaction as rdKafkaBeginTransaction+ {`RdKafkaTPtr'} -> `RdKafkaErrorTPtr' #}++{#fun rd_kafka_send_offsets_to_transaction as rdKafkaSendOffsetsToTransaction'+ {`RdKafkaTPtr', `RdKafkaTopicPartitionListTPtr', `Ptr ()', `Int' } -> `RdKafkaErrorTPtr' #}++{#fun rd_kafka_commit_transaction as rdKafkaCommitTransaction+ {`RdKafkaTPtr', `Int'} -> `RdKafkaErrorTPtr' #}++{#fun rd_kafka_abort_transaction as rdKafkaAbortTransaction+ {`RdKafkaTPtr', `Int'} -> `RdKafkaErrorTPtr' #}++{#fun rd_kafka_incremental_assign as ^+ {`RdKafkaTPtr', `RdKafkaTopicPartitionListTPtr'} -> `RdKafkaErrorTPtr' #}++{#fun rd_kafka_incremental_unassign as ^+ {`RdKafkaTPtr', `RdKafkaTopicPartitionListTPtr'}+ -> `RdKafkaErrorTPtr' #}++{#fun rd_kafka_consumer_group_metadata as rdKafkaConsumerGroupMetadata+ {`RdKafkaTPtr'} -> `Ptr ()' #}++{#fun rd_kafka_consumer_group_metadata_destroy as rdKafkaConsumerGroupMetadataDestroy+ {`Ptr ()'} -> `()' #}++{#fun rd_kafka_seek_partitions as rdKafkaSeekPartitions+ {`RdKafkaTPtr', `RdKafkaTopicPartitionListTPtr', `Int'} -> `RdKafkaErrorTPtr' #}++rdKafkaSendOffsetsToTransaction :: RdKafkaTPtr -> RdKafkaTPtr -> RdKafkaTopicPartitionListTPtr -> Int -> IO RdKafkaErrorTPtr+rdKafkaSendOffsetsToTransaction p c topicPartition timeOut =+ bracket (rdKafkaConsumerGroupMetadata c) rdKafkaConsumerGroupMetadataDestroy $ \metaData ->+ rdKafkaSendOffsetsToTransaction' p topicPartition metaData timeOut++{#fun rd_kafka_error_is_fatal as rdKafkaErrorIsFatal'+ {`RdKafkaErrorTPtr'} -> `CInt' #}++{#fun rd_kafka_error_is_retriable as rdKafkaErrorIsRetriable'+ {`RdKafkaErrorTPtr'} -> `CInt' #}++{#fun rd_kafka_error_txn_requires_abort as rdKafkaErrorTxnRequiresAbort'+ {`RdKafkaErrorTPtr'} -> `CInt' #}++rdKafkaErrorIsFatal :: RdKafkaErrorTPtr -> IO Bool+rdKafkaErrorIsFatal ptr = boolFromCInt <$> rdKafkaErrorIsFatal' ptr++rdKafkaErrorIsRetriable :: RdKafkaErrorTPtr -> IO Bool+rdKafkaErrorIsRetriable ptr = boolFromCInt <$> rdKafkaErrorIsRetriable' ptr++rdKafkaErrorTxnRequiresAbort :: RdKafkaErrorTPtr -> IO Bool+rdKafkaErrorTxnRequiresAbort ptr = boolFromCInt <$> rdKafkaErrorTxnRequiresAbort' ptr++-- Topics+{#enum rd_kafka_admin_op_t as ^ {underscoreToCase} #}+deriving stock instance Show RdKafkaAdminOpT+deriving stock instance Eq RdKafkaAdminOpT++data RdKafkaTopicResultT+{#pointer *rd_kafka_topic_result_t as RdKafkaTopicResultTPtr foreign -> RdKafkaTopicResultT#}++data RdKafkaAdminOptionsT+{#pointer *rd_kafka_AdminOptions_t as RdKafkaAdminOptionsTPtr foreign -> RdKafkaAdminOptionsT #}++{#fun rd_kafka_AdminOptions_new as ^+ {`RdKafkaTPtr', enumToCInt `RdKafkaAdminOpT'} -> `RdKafkaAdminOptionsTPtr' #}++data RdKafkaNewTopicT+{#pointer *rd_kafka_NewTopic_t as RdKafkaNewTopicTPtr foreign -> RdKafkaNewTopicT #}++{#fun rd_kafka_NewTopic_new as ^ {`String', `Int', `Int', id `Ptr CChar', cIntConv `CSize'} -> `RdKafkaNewTopicTPtr' #}++foreign import ccall unsafe "rdkafka.h &rd_kafka_AdminOptions_destroy" -- prevent memory leak+ finalRdKafkaAdminOptionsDestroy :: FinalizerPtr RdKafkaAdminOptionsT++{#fun rd_kafka_NewTopic_set_config as ^+ {`RdKafkaNewTopicTPtr', `String', `String'} -> `Either RdKafkaRespErrT ()' cIntToRespEither #}++newRdKAdminOptions :: RdKafkaTPtr -> RdKafkaAdminOpT -> IO RdKafkaAdminOptionsTPtr+newRdKAdminOptions kafkaPtr opt = do+ res <- rdKafkaAdminOptionsNew kafkaPtr opt+ addForeignPtrFinalizer finalRdKafkaAdminOptionsDestroy res+ pure res++rdKafkaNewTopicDestroy :: RdKafkaNewTopicTPtr -> IO () -- prevent memory leak+rdKafkaNewTopicDestroy tPtr = do+ withForeignPtr tPtr {#call rd_kafka_NewTopic_destroy#}++foreign import ccall "&rd_kafka_NewTopic_destroy"+ rdKafkaNewTopicDestroyFinalizer :: FinalizerPtr RdKafkaNewTopicT++data RdKafkaCreateTopicsResultT+{#pointer *rd_kafka_CreateTopics_result_t as RdKafkaCreateTopicsResultTPtr foreign -> RdKafkaCreateTopicsResultT #}++newRdKafkaNewTopic :: String -> Int -> Int -> IO (Either String RdKafkaNewTopicTPtr)+newRdKafkaNewTopic topicName topicPartitions topicReplicationFactor = do+ allocaBytes nErrorBytes $ \ptr -> do+ res <- rdKafkaNewTopicNew topicName topicPartitions topicReplicationFactor ptr (fromIntegral nErrorBytes)+ withForeignPtr res $ \realPtr -> do+ if realPtr == nullPtr+ then peekCString ptr >>= pure . Left+ else addForeignPtrFinalizer rdKafkaNewTopicDestroyFinalizer res >> pure (Right res)++newRdKafkaNewTopicUnsafe :: String -> Int -> Int -> IO (Either String RdKafkaNewTopicTPtr)+newRdKafkaNewTopicUnsafe topicName topicPartition topicReplicationFactor = do+ allocaBytes nErrorBytes $ \ptr -> do+ res <- rdKafkaNewTopicNew topicName topicPartition topicReplicationFactor ptr (fromIntegral nErrorBytes)+ withForeignPtr res $ \realPtr -> do+ if realPtr == nullPtr+ then peekCString ptr >>= pure . Left+ else pure (Right res)++rdKafkaEventCreateTopicsResult :: RdKafkaEventTPtr -> IO (Maybe RdKafkaCreateTopicsResultTPtr)+rdKafkaEventCreateTopicsResult evtPtr =+ withForeignPtr evtPtr $ \evtPtr' -> do+ res <- {#call rd_kafka_event_CreateTopics_result#} (castPtr evtPtr')+ if (res == nullPtr)+ then pure Nothing+ else Just <$> newForeignPtr_ (castPtr res)++rdKafkaCreateTopicsResultTopics :: RdKafkaCreateTopicsResultTPtr+ -> IO [Either (String, RdKafkaRespErrT, String) String]+rdKafkaCreateTopicsResultTopics tRes =+ withForeignPtr tRes $ \tRes' ->+ alloca $ \sPtr -> do+ res <- {#call rd_kafka_CreateTopics_result_topics#} (castPtr tRes') sPtr+ size <- peekIntConv sPtr+ arr <- peekArray size res+ traverse unpackRdKafkaTopicResult arr++-- | Unpacks raw result into+-- 'Either (topicName, errorType, errorMsg) topicName'+unpackRdKafkaTopicResult :: Ptr RdKafkaTopicResultT+ -> IO (Either (String, RdKafkaRespErrT, String) String)+unpackRdKafkaTopicResult resPtr = do+ name <- {#call rd_kafka_topic_result_name#} resPtr >>= peekCString+ err <- {#call rd_kafka_topic_result_error#} resPtr+ case cIntToEnum err of+ RdKafkaRespErrNoError -> pure $ Right name+ respErr -> do+ errMsg <- {#call rd_kafka_topic_result_error_string#} resPtr >>= peekCString+ pure $ Left (name, respErr, errMsg)++--- Create topic+rdKafkaCreateTopic :: RdKafkaTPtr+ -> RdKafkaNewTopicTPtr+ -> RdKafkaAdminOptionsTPtr+ -> RdKafkaQueueTPtr+ -> IO ()+rdKafkaCreateTopic kafkaPtr topic opts queue = do+ let topics = [topic]+ withForeignPtrs kafkaPtr opts queue $ \kPtr oPtr qPtr ->+ withForeignPtrsArrayLen topics $ \tLen tPtr -> do+ {#call rd_kafka_CreateTopics#} kPtr tPtr (fromIntegral tLen) oPtr qPtr++--- Delete topic+foreign import ccall unsafe "rdkafka.h &rd_kafka_DeleteTopic_destroy"+ rdKafkaDeleteTopicDestroy :: FinalizerPtr RdKafkaDeleteTopicT++data RdKafkaDeleteTopicT+{#pointer *rd_kafka_DeleteTopic_t as RdKafkaDeleteTopicTPtr foreign -> RdKafkaDeleteTopicT #}++data RdKafkaDeleteTopicsResultT+{#pointer *rd_kafka_DeleteTopics_result_t as RdKafkaDeleteTopicsResultTPtr foreign -> RdKafkaDeleteTopicsResultT #}++newRdKafkaDeleteTopic :: String -> IO (Either String RdKafkaDeleteTopicTPtr)+newRdKafkaDeleteTopic topicNameStr =+ withCString topicNameStr $ \topicNameStrPtr -> do+ res <- {#call rd_kafka_DeleteTopic_new#} topicNameStrPtr+ if (res == nullPtr)+ then return $ Left $ "Something went wrong while deleting topic " ++ topicNameStr+ else Right <$> newForeignPtr rdKafkaDeleteTopicDestroy res++rdKafkaEventDeleteTopicsResult :: RdKafkaEventTPtr -> IO (Maybe RdKafkaDeleteTopicsResultTPtr)+rdKafkaEventDeleteTopicsResult evtPtr =+ withForeignPtr evtPtr $ \evtPtr' -> do+ res <- {#call rd_kafka_event_DeleteTopics_result#} (castPtr evtPtr')+ if (res == nullPtr)+ then pure Nothing+ else Just <$> newForeignPtr_ (castPtr res)++rdKafkaDeleteTopics :: RdKafkaTPtr+ -> [RdKafkaDeleteTopicTPtr]+ -> RdKafkaAdminOptionsTPtr+ -> RdKafkaQueueTPtr+ -> IO ()+rdKafkaDeleteTopics kafkaPtr topics opts queue = do+ withForeignPtrs kafkaPtr opts queue $ \kPtr oPtr qPtr ->+ withForeignPtrsArrayLen topics $ \tLen tPtr -> do+ {#call rd_kafka_DeleteTopics#} kPtr tPtr (fromIntegral tLen) oPtr qPtr++rdKafkaDeleteTopicsResultTopics :: RdKafkaDeleteTopicsResultTPtr+ -> IO [Either (String, RdKafkaRespErrT, String) String]+rdKafkaDeleteTopicsResultTopics tRes =+ withForeignPtr tRes $ \tRes' ->+ alloca $ \sPtr -> do+ res <- {#call rd_kafka_DeleteTopics_result_topics#} (castPtr tRes') sPtr+ size <- peekIntConv sPtr+ arr <- peekArray size res+ traverse unpackRdKafkaTopicResult arr++-- Marshall / Unmarshall+enumToCInt :: Enum a => a -> CInt+enumToCInt = fromIntegral . fromEnum+{-# INLINE enumToCInt #-}++cIntToEnum :: Enum a => CInt -> a+cIntToEnum = toEnum . fromIntegral+{-# INLINE cIntToEnum #-}++cIntConv :: (Integral a, Num b) => a -> b+cIntConv = fromIntegral+{-# INLINE cIntConv #-}++cIntToRespEither :: CInt -> Either RdKafkaRespErrT ()+cIntToRespEither err =+ case cIntToEnum err of+ RdKafkaRespErrNoError -> Right ()+ respErr -> Left respErr+{-# INLINE cIntToRespEither #-}++boolToCInt :: Bool -> CInt+boolToCInt True = CInt 1+boolToCInt False = CInt 0+{-# INLINE boolToCInt #-}++boolFromCInt :: CInt -> Bool+boolFromCInt (CInt 0) = False+boolFromCInt (CInt _) = True+{-# INLINE boolFromCInt #-}++peekIntConv :: (Storable a, Integral a, Integral b) => Ptr a -> IO b+peekIntConv = liftM fromIntegral . peek++peekInt64Conv :: (Storable a, Integral a) => Ptr a -> IO Int64+peekInt64Conv = liftM cIntConv . peek+{-# INLINE peekInt64Conv #-}++peekPtr :: Ptr a -> IO (Ptr b)+peekPtr = peek . castPtr+{-# INLINE peekPtr #-}++-- Borrow the caller's handle through an owned duplicate. fdopen takes the+-- duplicate descriptor only on success; fclose flushes and releases it.+foreign import ccall safe "fdopen" fdopen :: Fd -> CString -> IO (Ptr CFile)+foreign import ccall safe "fclose" fclose :: Ptr CFile -> IO CInt++withCFile :: Handle -> String -> (CFilePtr -> IO a) -> IO a+withCFile handle mode = bracket acquire (throwErrnoIfMinus1_ "fclose" . fclose)+ where+ acquire = bracketOnError (hDuplicate handle) hClose $ \duplicate ->+ bracketOnError (handleToFd duplicate) closeFd $ \fd ->+ withCString mode $ \modeString -> throwErrnoIfNull "fdopen" (fdopen fd modeString)+++withForeignPtrs :: ForeignPtr kafkaPtr+ -> ForeignPtr optPtr+ -> ForeignPtr queuePtr+ -> (Ptr kafkaPtr -> Ptr optPtr -> Ptr queuePtr -> IO x)+ -> IO x+withForeignPtrs kafkaPtr optPtr queuePtr f =+ withForeignPtr kafkaPtr $ \kafkaPtr' ->+ withForeignPtr optPtr $ \optPtr' ->+ withForeignPtr queuePtr $ \queuePtr' -> f kafkaPtr' optPtr' queuePtr'++withForeignPtrsArrayLen :: [ForeignPtr a] + -> (Int -> Ptr (Ptr a) -> IO b)+ -> IO b+withForeignPtrsArrayLen as f =+ let withForeignPtrsList [] g = g []+ withForeignPtrsList (x:xs) g =+ withForeignPtr x $ \x' ->+ withForeignPtrsList xs $ \xs' ->+ g (x' : xs')+ in withForeignPtrsList as $ \ptrs ->+ withArrayLen ptrs $ \llen pptrs -> f llen pptrs
+ src/Kafka/Internal/Setup.hs view
@@ -0,0 +1,228 @@+module Kafka.Internal.Setup+ ( KafkaProps (..),+ TopicProps (..),+ Kafka (..),+ KafkaConf (..),+ PendingMessages (..),+ emptyPendingMessages,+ pendingMessagePartition,+ resetPendingMessages,+ discardPendingMessages,+ forgetPendingPartitions,+ PendingMessage (..),+ PendingTimestamp (..),+ TopicConf (..),+ HasKafka (..),+ HasKafkaConf (..),+ HasTopicConf (..),+ Callback (..),+ CallbackPollStatus (..),+ ClientLifecycle (..),+ getRdKafka,+ getRdKafkaConf,+ getRdMsgQueue,+ getRdTopicConf,+ newTopicConf,+ newKafkaConf,+ kafkaConf,+ topicConf,+ checkConfSetValue,+ setKafkaConfValue,+ setAllKafkaConfValues,+ setTopicConfValue,+ setAllTopicConfValues,+ )+where++import Kafka.Internal.CallbackOwner (CallbackOwner, newCallbackOwner)+import Kafka.Internal.RdKafka (CCharBufPointer, RdKafkaConfResT (..), RdKafkaConfTPtr, RdKafkaQueueTPtr, RdKafkaTPtr, RdKafkaTopicConfTPtr, nErrorBytes, newRdKafkaConfT, newRdKafkaTopicConfT, rdKafkaConfSet, rdKafkaTopicConfSet)+import Kafka.Types (Headers, KafkaError (..), Millis, PartitionId, TopicName)++import Control.Concurrent.MVar (MVar, newMVar)+import Control.Exception (throw, throwIO)+import Data.ByteString (ByteString)+import Data.IORef (IORef, atomicModifyIORef', newIORef, readIORef)+import Data.Int (Int64)+import Data.Map (Map)+import Data.Sequence (Seq)+import Data.Sequence qualified as Seq+import Data.Set (Set)+import Data.Set qualified as Set+import Data.Text (Text)+import Foreign.C.String (peekCString)+import Foreign.Marshal.Alloc (allocaBytes)++import Data.Map qualified as Map+import Data.Text qualified as Text++--+-- Configuration+--+newtype KafkaProps = KafkaProps (Map Text Text)+ deriving stock (Show, Eq)++newtype TopicProps = TopicProps (Map Text Text)+ deriving stock (Show, Eq)++newtype Kafka = Kafka RdKafkaTPtr+ deriving stock (Show)++newtype TopicConf = TopicConf RdKafkaTopicConfTPtr+ deriving stock (Show)++-- | Callbacks allow retrieving various information like error occurences, statistics+-- and log messages.+-- See `Kafka.Consumer.setCallback` (Consumer) and `Kafka.Producer.setCallback` (Producer) for more details.+newtype Callback = Callback (KafkaConf -> IO ())++data CallbackPollStatus = CallbackPollEnabled | CallbackPollDisabled+ deriving stock (Show, Eq)++-- | Where a consumer is in its teardown. 'Kafka.Consumer.closeConsumer' moves+-- an open consumer to 'ClientClosed'; 'Kafka.Consumer.destroyConsumer' moves+-- any consumer to 'ClientDestroyed'. Both hold the 'MVar' for the whole+-- transition, so a concurrent caller waits for it to finish.+data ClientLifecycle = ClientOpen | ClientClosed | ClientDestroyed+ deriving stock (Show, Eq)++data KafkaConf = KafkaConf+ { -- | A pointer to a native Kafka configuration+ kcfgKafkaConfPtr :: RdKafkaConfTPtr,+ -- | A queue for messages+ kcfgMessagesQueue :: IORef (Maybe RdKafkaQueueTPtr),+ -- | A mutex to prevent handling callbacks from multiple threads+ -- which can be dangerous in some cases.+ kcfgCallbackPollStatus :: MVar CallbackPollStatus,+ -- | Serializes consumer close and destroy.+ kcfgLifecycle :: MVar ClientLifecycle,+ -- | Persistent callback bridges, transferred to the native client finalizer.+ kcfgCallbackOwner :: CallbackOwner,+ -- | Copied records/errors returned while serving callbacks. No native owners.+ kcfgPendingMessages :: IORef PendingMessages+ }++-- Kept independent of Consumer.Types, which uses KafkaConf for its client.+data PendingTimestamp = PendingNoTimestamp | PendingCreateTime Millis | PendingLogAppendTime Millis++data PendingMessage+ = PendingMessageError KafkaError (Maybe TopicName) (Maybe PartitionId) (Maybe Int64)+ | PendingMessageRecord TopicName PartitionId Int64 PendingTimestamp Headers (Maybe ByteString) (Maybe ByteString)++data PendingMessages = PendingMessages+ { bufferedMessages :: Seq PendingMessage,+ pendingPausedPartitions :: Set (TopicName, PartitionId)+ }++emptyPendingMessages :: PendingMessages+emptyPendingMessages = PendingMessages Seq.empty Set.empty++pendingMessagePartition :: PendingMessage -> Maybe (TopicName, PartitionId)+pendingMessagePartition (PendingMessageError _ topic partition _) = (,) <$> topic <*> partition+pendingMessagePartition (PendingMessageRecord topic partition _ _ _ _ _) = Just (topic, partition)++resetPendingMessages :: KafkaConf -> IO ()+resetPendingMessages conf = atomicModifyIORef' (kcfgPendingMessages conf) (const (emptyPendingMessages, ()))++-- Successful seeks replace cached records only for affected partitions.+discardPendingMessages :: KafkaConf -> Set (TopicName, PartitionId) -> IO ()+discardPendingMessages conf partitions = atomicModifyIORef' (kcfgPendingMessages conf) $ \buffer ->+ (buffer {bufferedMessages = Seq.filter (maybe True (`Set.notMember` partitions) . pendingMessagePartition) (bufferedMessages buffer)}, ())++-- Revocation also forgets the application's pause state for those partitions.+forgetPendingPartitions :: KafkaConf -> Set (TopicName, PartitionId) -> IO ()+forgetPendingPartitions conf partitions = atomicModifyIORef' (kcfgPendingMessages conf) $ \buffer ->+ (buffer {bufferedMessages = Seq.filter (maybe True (`Set.notMember` partitions) . pendingMessagePartition) (bufferedMessages buffer), pendingPausedPartitions = pendingPausedPartitions buffer `Set.difference` partitions}, ())++class HasKafka a where+ getKafka :: a -> Kafka++class HasKafkaConf a where+ getKafkaConf :: a -> KafkaConf++class HasTopicConf a where+ getTopicConf :: a -> TopicConf++instance HasKafkaConf KafkaConf where+ getKafkaConf = id+ {-# INLINE getKafkaConf #-}++instance HasKafka Kafka where+ getKafka = id+ {-# INLINE getKafka #-}++instance HasTopicConf TopicConf where+ getTopicConf = id+ {-# INLINE getTopicConf #-}++getRdKafka :: (HasKafka k) => k -> RdKafkaTPtr+getRdKafka k = let (Kafka k') = getKafka k in k'+{-# INLINE getRdKafka #-}++getRdKafkaConf :: (HasKafkaConf k) => k -> RdKafkaConfTPtr+getRdKafkaConf k = let (KafkaConf k' _ _ _ _ _) = getKafkaConf k in k'+{-# INLINE getRdKafkaConf #-}++getRdMsgQueue :: (HasKafkaConf k) => k -> IO (Maybe RdKafkaQueueTPtr)+getRdMsgQueue k =+ let (KafkaConf _ rq _ _ _ _) = getKafkaConf k+ in readIORef rq++getRdTopicConf :: (HasTopicConf t) => t -> RdKafkaTopicConfTPtr+getRdTopicConf t = let (TopicConf t') = getTopicConf t in t'+{-# INLINE getRdTopicConf #-}++newTopicConf :: IO TopicConf+newTopicConf = TopicConf <$> newRdKafkaTopicConfT++newKafkaConf :: IO KafkaConf+newKafkaConf = KafkaConf <$> newRdKafkaConfT <*> newIORef Nothing <*> newMVar CallbackPollEnabled <*> newMVar ClientOpen <*> newCallbackOwner <*> newIORef emptyPendingMessages++kafkaConf :: KafkaProps -> IO KafkaConf+kafkaConf overrides = do+ conf <- newKafkaConf+ setAllKafkaConfValues conf overrides+ return conf++topicConf :: TopicProps -> IO TopicConf+topicConf overrides = do+ conf <- newTopicConf+ setAllTopicConfValues conf overrides+ return conf++checkConfSetValue :: RdKafkaConfResT -> CCharBufPointer -> IO ()+checkConfSetValue err charPtr = case err of+ RdKafkaConfOk -> return ()+ RdKafkaConfInvalid -> do+ str <- peekCString charPtr+ throw $ KafkaInvalidConfigurationValue (Text.pack str)+ RdKafkaConfUnknown -> do+ str <- peekCString charPtr+ throw $ KafkaUnknownConfigurationKey (Text.pack str)++setKafkaConfValue :: KafkaConf -> Text -> Text -> IO ()+setKafkaConfValue (KafkaConf confPtr _ _ _ _ _) key value = do+ validateConfigStrings key value+ allocaBytes nErrorBytes $ \charPtr -> do+ err <- rdKafkaConfSet confPtr (Text.unpack key) (Text.unpack value) charPtr (fromIntegral nErrorBytes)+ checkConfSetValue err charPtr++setAllKafkaConfValues :: KafkaConf -> KafkaProps -> IO ()+setAllKafkaConfValues conf (KafkaProps props) = Map.foldMapWithKey (setKafkaConfValue conf) props -- forM_ props $ uncurry (setKafkaConfValue conf)++setTopicConfValue :: TopicConf -> Text -> Text -> IO ()+setTopicConfValue (TopicConf confPtr) key value = do+ validateConfigStrings key value+ allocaBytes nErrorBytes $ \charPtr -> do+ err <- rdKafkaTopicConfSet confPtr (Text.unpack key) (Text.unpack value) charPtr (fromIntegral nErrorBytes)+ checkConfSetValue err charPtr++setAllTopicConfValues :: TopicConf -> TopicProps -> IO ()+setAllTopicConfValues conf (TopicProps props) = Map.foldMapWithKey (setTopicConfValue conf) props -- forM_ props $ uncurry (setTopicConfValue conf)++-- Native setters borrow NUL-terminated strings; accepting embedded NULs would+-- validate and apply only a prefix of the supplied property.+validateConfigStrings :: Text -> Text -> IO ()+validateConfigStrings key value+ | Text.any (== '\0') key = throwIO (KafkaInvalidConfigurationValue "Configuration key contains NUL")+ | Text.any (== '\0') value = throwIO (KafkaInvalidConfigurationValue "Configuration value contains NUL")+ | otherwise = pure ()
@@ -0,0 +1,174 @@+{-# LANGUAGE LambdaCase #-}++module Kafka.Internal.Shared+ ( pollEvents,+ word8PtrToBS,+ kafkaRespErr,+ throwOnError,+ hasError,+ rdKafkaErrorToEither,+ kafkaErrorToEither,+ kafkaErrorToMaybe,+ maybeToLeft,+ readHeaders,+ readPayload,+ readTopic,+ readKey,+ readTimestamp,+ readBS,+ setSaslCredentials',+ validateCStringInput,+ validateTopicNameInput,+ validateTopicPartitions,+ )+where++import Control.Exception (throw)+import Control.Monad (void)+import Data.ByteString qualified as BS+import Data.ByteString.Internal qualified as BSI+import Data.Maybe (listToMaybe, mapMaybe)+import Data.Text (Text)+import Data.Text qualified as Text+import Data.Word (Word8)+import Foreign.C.Error (Errno (..))+import Foreign.C.Types (CInt)+import Foreign.ForeignPtr (newForeignPtr_)+import Foreign.Marshal.Alloc (alloca)+import Foreign.Marshal.Utils (copyBytes)+import Foreign.Ptr (Ptr, nullPtr)+import Foreign.Storable (Storable (peek))+import Kafka.Consumer.Types (Timestamp (..))+import Kafka.Internal.RdKafka (RdKafkaMessageT (..), RdKafkaMessageTPtr, RdKafkaRespErrT (..), RdKafkaTimestampTypeT (..), Word8Ptr, rdKafkaErrno2err, rdKafkaHeaderGetAll, rdKafkaMessageHeaders, rdKafkaMessageTimestamp, rdKafkaPoll, rdKafkaSaslSetCredentials, rdKafkaTopicName)+import Kafka.Internal.Setup (HasKafka (..), Kafka (..))+import Kafka.Types (Headers, KafkaError (..), Millis (..), PartitionId (..), Timeout (..), TopicName (..), headersFromList)++-- | Replace a client's SASL username and password+-- (@rd_kafka_sasl_set_credentials@).+setSaslCredentials' :: (HasKafka a) => a -> Text -> Text -> IO (Maybe KafkaError)+setSaslCredentials' a username password+ | Just err <- validateCStringInput "SASL username" username = pure (Just err)+ | Just err <- validateCStringInput "SASL password" password = pure (Just err)+ | otherwise =+ let Kafka k = getKafka a+ in kafkaErrorToMaybe . KafkaResponseError+ <$> rdKafkaSaslSetCredentials k (Text.unpack username) (Text.unpack password)++pollEvents :: (HasKafka a) => a -> Maybe Timeout -> IO ()+pollEvents a tm =+ let timeout = maybe 0 unTimeout tm+ Kafka k = getKafka a+ in void (rdKafkaPoll k timeout)++word8PtrToBS :: Int -> Word8Ptr -> IO BS.ByteString+word8PtrToBS len ptr = BSI.create len $ \bsptr ->+ copyBytes bsptr ptr len++kafkaRespErr :: Errno -> KafkaError+kafkaRespErr (Errno num) = KafkaResponseError $ rdKafkaErrno2err (fromIntegral num)+{-# INLINE kafkaRespErr #-}++throwOnError :: IO (Maybe Text) -> IO ()+throwOnError action = do+ m <- action+ case m of+ Just e -> throw $ KafkaError e+ Nothing -> return ()++hasError :: KafkaError -> Bool+hasError err = case err of+ KafkaResponseError RdKafkaRespErrNoError -> False+ _ -> True+{-# INLINE hasError #-}++rdKafkaErrorToEither :: RdKafkaRespErrT -> Either KafkaError ()+rdKafkaErrorToEither err = case err of+ RdKafkaRespErrNoError -> Right ()+ _ -> Left (KafkaResponseError err)+{-# INLINE rdKafkaErrorToEither #-}++kafkaErrorToEither :: KafkaError -> Either KafkaError ()+kafkaErrorToEither err = case err of+ KafkaResponseError RdKafkaRespErrNoError -> Right ()+ _ -> Left err+{-# INLINE kafkaErrorToEither #-}++kafkaErrorToMaybe :: KafkaError -> Maybe KafkaError+kafkaErrorToMaybe err = case err of+ KafkaResponseError RdKafkaRespErrNoError -> Nothing+ _ -> Just err+{-# INLINE kafkaErrorToMaybe #-}++maybeToLeft :: Maybe a -> Either a ()+maybeToLeft = maybe (Right ()) Left+{-# INLINE maybeToLeft #-}++readPayload :: RdKafkaMessageT -> IO (Maybe BS.ByteString)+readPayload = readBS len'RdKafkaMessageT payload'RdKafkaMessageT++readTopic :: RdKafkaMessageT -> IO Text+readTopic msg = newForeignPtr_ (topic'RdKafkaMessageT msg) >>= (fmap Text.pack . rdKafkaTopicName)++readKey :: RdKafkaMessageT -> IO (Maybe BSI.ByteString)+readKey = readBS keyLen'RdKafkaMessageT key'RdKafkaMessageT++readTimestamp :: RdKafkaMessageTPtr -> IO Timestamp+readTimestamp msg =+ alloca $ \p -> do+ typeP <- newForeignPtr_ p+ ts <- fromIntegral <$> rdKafkaMessageTimestamp msg typeP+ tsType <- peek p+ return $ case tsType of+ RdKafkaTimestampCreateTime -> CreateTime (Millis ts)+ RdKafkaTimestampLogAppendTime -> LogAppendTime (Millis ts)+ RdKafkaTimestampNotAvailable -> NoTimestamp++readHeaders :: Ptr RdKafkaMessageT -> IO (Either RdKafkaRespErrT Headers)+readHeaders msg = do+ (err, headersPtr) <- rdKafkaMessageHeaders msg+ case err of+ RdKafkaRespErrNoent -> return $ Right mempty+ RdKafkaRespErrNoError -> fmap headersFromList <$> extractHeaders headersPtr+ e -> return . Left $ e+ where+ extractHeaders ptHeaders =+ alloca $ \nptr ->+ alloca $ \vptr ->+ alloca $ \szptr ->+ let go acc idx =+ rdKafkaHeaderGetAll ptHeaders idx nptr vptr szptr >>= \case+ RdKafkaRespErrNoent -> return . Right $ reverse acc+ RdKafkaRespErrNoError -> do+ cstr <- peek nptr+ wptr <- peek vptr+ csize <- peek szptr+ hn <- BS.packCString cstr+ hv <- word8PtrToBS (fromIntegral csize) wptr+ go ((hn, hv) : acc) (idx + 1)+ _ -> error "Unexpected error code while extracting headers"+ in go [] 0++readBS :: (t -> Int) -> (t -> Ptr Word8) -> t -> IO (Maybe BS.ByteString)+readBS flen fdata s =+ if fdata s == nullPtr+ then return Nothing+ else Just <$> word8PtrToBS (flen s) (fdata s)++-- C strings and native partition integers must preserve the caller's identity.+-- Keep all other validation with librdkafka and preserve input error order.+validateCStringInput :: Text -> Text -> Maybe KafkaError+validateCStringInput label value+ | Text.any (== '\0') value = Just (KafkaBadSpecification (label <> " contains NUL"))+ | otherwise = Nothing++validateTopicNameInput :: TopicName -> Maybe KafkaError+validateTopicNameInput (TopicName name) = validateCStringInput "topic name" name++validateTopicPartitions :: [(TopicName, PartitionId)] -> Maybe KafkaError+validateTopicPartitions = listToMaybe . mapMaybe invalid+ where+ invalid (topic, PartitionId partition)+ | Just failure <- validateTopicNameInput topic = Just failure+ | toInteger partition < toInteger (minBound :: CInt) || toInteger partition > toInteger (maxBound :: CInt) =+ Just (KafkaBadSpecification "partition is outside the C int range")+ | otherwise = Nothing
+ src/Kafka/Metadata.hs view
@@ -0,0 +1,362 @@+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE OverloadedStrings #-}++-----------------------------------------------------------------------------++-----------------------------------------------------------------------------++-- |+-- Module with metadata types and functions.+module Kafka.Metadata+ ( KafkaMetadata (..),+ BrokerMetadata (..),+ TopicMetadata (..),+ PartitionMetadata (..),+ WatermarkOffsets (..),+ GroupMemberId (..),+ GroupMemberInfo (..),+ GroupProtocolType (..),+ GroupProtocol (..),+ GroupState (..),+ GroupInfo (..),+ allTopicsMetadata,+ topicMetadata,+ watermarkOffsets,+ watermarkOffsets',+ partitionWatermarkOffsets,+ offsetsForTime,+ offsetsForTime',+ topicOffsetsForTime,+ allConsumerGroupsInfo,+ consumerGroupInfo,+ )+where++import Control.Exception (bracket)+import Control.Monad.IO.Class (MonadIO (liftIO))+import Data.Bifunctor (bimap)+import Data.ByteString (ByteString, pack)+import Data.List (find)+import Data.Maybe (listToMaybe, mapMaybe)+import Data.Text (Text)+import Foreign (ForeignPtr, Storable (peek), finalizeForeignPtr, peekArray, withForeignPtr)+import GHC.Generics (Generic)+import Kafka.Consumer.Convert (fromNativeTopicPartitionList'', nativeTopicPartitionErrors, toNativeTopicPartitionList)+import Kafka.Consumer.Types (ConsumerGroupId (..), Offset (..), PartitionOffset (..), TopicPartition (..))+import Kafka.Internal.RdKafka (RdKafkaGroupInfoT (..), RdKafkaGroupListT (..), RdKafkaGroupListTPtr, RdKafkaGroupMemberInfoT (..), RdKafkaMetadataBrokerT (..), RdKafkaMetadataPartitionT (..), RdKafkaMetadataT (..), RdKafkaMetadataTPtr, RdKafkaMetadataTopicT (..), RdKafkaRespErrT (..), RdKafkaTPtr, destroyUnmanagedRdKafkaTopic, newUnmanagedRdKafkaTopicT, peekCText, rdKafkaListGroups, rdKafkaMetadata, rdKafkaOffsetsForTimes, rdKafkaQueryWatermarkOffsets)+import Kafka.Internal.Setup (HasKafka (..), Kafka (..))+import Kafka.Internal.Shared (kafkaErrorToMaybe, validateCStringInput, validateTopicNameInput, validateTopicPartitions)+import Kafka.Types (BrokerId (..), ClientId (..), KafkaError (..), Millis (..), PartitionId (..), Timeout (..), TopicName (..))++import Data.Set qualified as S+import Data.Text qualified as Text++data KafkaMetadata = KafkaMetadata+ { kmBrokers :: [BrokerMetadata],+ kmTopics :: [TopicMetadata],+ kmOrigBroker :: !BrokerId+ }+ deriving stock (Show, Eq, Generic)++data BrokerMetadata = BrokerMetadata+ { bmBrokerId :: !BrokerId,+ bmBrokerHost :: !Text,+ bmBrokerPort :: !Int+ }+ deriving stock (Show, Eq, Generic)++data PartitionMetadata = PartitionMetadata+ { pmPartitionId :: !PartitionId,+ pmError :: Maybe KafkaError,+ pmLeader :: !BrokerId,+ pmReplicas :: [BrokerId],+ pmInSyncReplicas :: [BrokerId]+ }+ deriving stock (Show, Eq, Generic)++data TopicMetadata = TopicMetadata+ { tmTopicName :: !TopicName,+ tmPartitions :: [PartitionMetadata],+ tmError :: Maybe KafkaError+ }+ deriving stock (Show, Eq, Generic)++data WatermarkOffsets = WatermarkOffsets+ { woTopicName :: !TopicName,+ woPartitionId :: !PartitionId,+ woLowWatermark :: !Offset,+ woHighWatermark :: !Offset+ }+ deriving stock (Show, Eq, Generic)++newtype GroupMemberId = GroupMemberId Text+ deriving stock (Show, Eq, Read, Ord)++data GroupMemberInfo = GroupMemberInfo+ { gmiMemberId :: !GroupMemberId,+ gmiClientId :: !ClientId,+ gmiClientHost :: !Text,+ gmiMetadata :: !ByteString,+ gmiAssignment :: !ByteString+ }+ deriving stock (Show, Eq, Generic)++newtype GroupProtocolType = GroupProtocolType Text+ deriving stock (Show, Eq, Read, Ord, Generic)++newtype GroupProtocol = GroupProtocol Text+ deriving stock (Show, Eq, Read, Ord, Generic)++data GroupState+ = -- | Group is preparing to rebalance+ GroupPreparingRebalance+ | -- | Group has no more members, but lingers until all offsets have expired+ GroupEmpty+ | -- | Group is awaiting state assignment from the leader+ GroupAwaitingSync+ | -- | Group is stable+ GroupStable+ | -- | Group has no more members and its metadata is being removed+ GroupDead+ deriving stock (Show, Eq, Read, Ord, Generic)++data GroupInfo = GroupInfo+ { giGroup :: !ConsumerGroupId,+ giError :: Maybe KafkaError,+ giState :: !GroupState,+ giProtocolType :: !GroupProtocolType,+ giProtocol :: !GroupProtocol,+ giMembers :: [GroupMemberInfo]+ }+ deriving stock (Show, Eq, Generic)++-- | Returns metadata for all topics in the cluster+allTopicsMetadata :: (MonadIO m, HasKafka k) => k -> Timeout -> m (Either KafkaError KafkaMetadata)+allTopicsMetadata k (Timeout timeout) =+ liftIO $+ withNativeResult k (rdKafkaMetadata (getKafkaPtr k) True Nothing timeout) (fmap Right . fromKafkaMetadataPtr)++-- | Returns metadata only for specified topic+topicMetadata :: (MonadIO m, HasKafka k) => k -> Timeout -> TopicName -> m (Either KafkaError KafkaMetadata)+topicMetadata _ _ topic | Just failure <- validateTopicNameInput topic = pure (Left failure)+topicMetadata k (Timeout timeout) (TopicName tn) = liftIO $ withForeignPtr (getKafkaPtr k) $ \_ ->+ bracket mkTopic clTopic $ \mbt -> case mbt of+ Left err -> return (Left $ KafkaError (Text.pack err))+ Right t -> do+ withNativeResult k (rdKafkaMetadata (getKafkaPtr k) False (Just t) timeout) (fmap Right . fromKafkaMetadataPtr)+ where+ mkTopic = newUnmanagedRdKafkaTopicT (getKafkaPtr k) (Text.unpack tn) Nothing+ clTopic = either (return . const ()) destroyUnmanagedRdKafkaTopic++-- | Query broker for low (oldest/beginning) and high (newest/end) offsets for a given topic.+watermarkOffsets :: (MonadIO m, HasKafka k) => k -> Timeout -> TopicName -> m [Either KafkaError WatermarkOffsets]+watermarkOffsets k timeout t = do+ meta <- topicMetadata k timeout t+ case meta of+ Left err -> return [Left err]+ Right tm -> case kmTopics tm of+ [] -> return []+ (t' : _) -> watermarkOffsets' k timeout t'++-- | Query broker for low (oldest/beginning) and high (newest/end) offsets for a given topic.+watermarkOffsets' :: (MonadIO m, HasKafka k) => k -> Timeout -> TopicMetadata -> m [Either KafkaError WatermarkOffsets]+watermarkOffsets' k timeout tm = case tmError tm of+ Just failure -> pure [Left failure]+ Nothing -> liftIO $ traverse query (tmPartitions tm)+ where+ query partition = case pmError partition of+ Just failure -> pure (Left failure)+ Nothing -> partitionWatermarkOffsets k timeout (tmTopicName tm) (pmPartitionId partition)++-- | Query broker for low (oldest/beginning) and high (newest/end) offsets for a specific partition+partitionWatermarkOffsets :: (MonadIO m, HasKafka k) => k -> Timeout -> TopicName -> PartitionId -> m (Either KafkaError WatermarkOffsets)+partitionWatermarkOffsets _ _ topic partition | Just failure <- validateTopicPartitions [(topic, partition)] = pure (Left failure)+partitionWatermarkOffsets k (Timeout timeout) (TopicName t) (PartitionId p) = liftIO $ do+ offs <- rdKafkaQueryWatermarkOffsets (getKafkaPtr k) (Text.unpack t) p timeout+ return $ bimap KafkaResponseError toWatermark offs+ where+ toWatermark (l, h) = WatermarkOffsets (TopicName t) (PartitionId p) (Offset l) (Offset h)++-- | Look up the offsets for the given topic by timestamp.+--+-- The returned offset for each partition is the earliest offset whose+-- timestamp is greater than or equal to the given timestamp in the+-- corresponding partition.+topicOffsetsForTime :: (MonadIO m, HasKafka k) => k -> Timeout -> Millis -> TopicName -> m (Either KafkaError [TopicPartition])+topicOffsetsForTime k timeout timestamp topic = do+ meta <- topicMetadata k timeout topic+ case meta of+ Left err -> return $ Left err+ Right meta' -> case listToMaybe (mapMaybe tmError (kmTopics meta') <> concatMap (mapMaybe pmError . tmPartitions) (kmTopics meta')) of+ Just failure -> pure (Left failure)+ Nothing ->+ let tps = [(tmTopicName t, pmPartitionId p) | t <- kmTopics meta', p <- tmPartitions t]+ in offsetsForTime k timeout timestamp tps++-- | Look up the offsets for the given metadata by timestamp.+--+-- The returned offset for each partition is the earliest offset whose+-- timestamp is greater than or equal to the given timestamp in the+-- corresponding partition.+offsetsForTime' :: (MonadIO m, HasKafka k) => k -> Timeout -> Millis -> TopicMetadata -> m (Either KafkaError [TopicPartition])+offsetsForTime' k timeout timestamp t = case tmError t of+ Just failure -> pure (Left failure)+ Nothing -> case listToMaybe (mapMaybe pmError (tmPartitions t)) of+ Just failure -> pure (Left failure)+ Nothing ->+ let tps = [(tmTopicName t, pmPartitionId p) | p <- tmPartitions t]+ in offsetsForTime k timeout timestamp tps++-- | Look up the offsets for the given partitions by timestamp.+--+-- The returned offset for each partition is the earliest offset whose+-- timestamp is greater than or equal to the given timestamp in the+-- corresponding partition.+offsetsForTime :: (MonadIO m, HasKafka k) => k -> Timeout -> Millis -> [(TopicName, PartitionId)] -> m (Either KafkaError [TopicPartition])+offsetsForTime _ _ _ ps | Just failure <- validateTopicPartitions ps = pure (Left failure)+offsetsForTime k (Timeout timeout) (Millis t) tps = liftIO $ withForeignPtr (getKafkaPtr k) $ \_ -> bracket (toNativeTopicPartitionList (mkTopicPartition <$> uniqueTps)) finalizeForeignPtr $ \ntps -> do+ res <- rdKafkaOffsetsForTimes (getKafkaPtr k) ntps timeout+ case res of+ RdKafkaRespErrNoError -> do+ errors <- nativeTopicPartitionErrors ntps+ case find (/= RdKafkaRespErrNoError) errors of+ Just failure -> pure (Left (KafkaResponseError failure))+ Nothing -> Right <$> fromNativeTopicPartitionList'' ntps+ err -> return $ Left (KafkaResponseError err)+ where+ uniqueTps = S.toList . S.fromList $ tps+ -- rd_kafka_offsets_for_times reuses `offset` to specify timestamp :(+ mkTopicPartition (tn, p) = TopicPartition tn p (PartitionOffset t)++-- | List and describe all consumer groups in cluster. Unsupported native+-- group-state names return a descriptive error.+allConsumerGroupsInfo :: (MonadIO m, HasKafka k) => k -> Timeout -> m (Either KafkaError [GroupInfo])+allConsumerGroupsInfo k (Timeout t) =+ liftIO $+ withNativeResult k (rdKafkaListGroups (getKafkaPtr k) Nothing t) fromGroupInfoListPtr++-- | Describe a given consumer group. Unsupported native group-state names+-- return a descriptive error; a missing group returns an empty list.+consumerGroupInfo :: (MonadIO m, HasKafka k) => k -> Timeout -> ConsumerGroupId -> m (Either KafkaError [GroupInfo])+consumerGroupInfo _ _ (ConsumerGroupId name) | Just failure <- validateCStringInput "consumer group" name = pure (Left failure)+consumerGroupInfo k (Timeout timeout) (ConsumerGroupId gn) =+ liftIO $+ withNativeResult k (rdKafkaListGroups (getKafkaPtr k) (Just (Text.unpack gn)) timeout) fromGroupInfoListPtr++-------------------------------------------------------------------------------+getKafkaPtr :: (HasKafka k) => k -> RdKafkaTPtr+getKafkaPtr k = let (Kafka k') = getKafka k in k'+{-# INLINE getKafkaPtr #-}++-- Retain the client until its complete result has been copied and destroyed.+-- Mask acquisition through ForeignPtr registration, including native return.+withNativeResult :: (HasKafka k) => k -> IO (Either RdKafkaRespErrT (ForeignPtr a)) -> (ForeignPtr a -> IO (Either KafkaError b)) -> IO (Either KafkaError b)+withNativeResult client acquire decode = withForeignPtr (getKafkaPtr client) $ \_ ->+ bracket acquire (either (const (pure ())) finalizeForeignPtr) $+ either (pure . Left . KafkaResponseError) decode++fromGroupInfoListPtr :: RdKafkaGroupListTPtr -> IO (Either KafkaError [GroupInfo])+fromGroupInfoListPtr ptr =+ withForeignPtr ptr $ \realPtr -> do+ gl <- peek realPtr+ pgis <- peekArray (groupCnt'RdKafkaGroupListT gl) (groups'RdKafkaGroupListT gl)+ sequence <$> traverse fromGroupInfoPtr pgis++fromGroupInfoPtr :: RdKafkaGroupInfoT -> IO (Either KafkaError GroupInfo)+fromGroupInfoPtr gi = do+ -- bmd <- peek (broker'RdKafkaGroupInfoT gi) -- >>= fromBrokerMetadataPtr+ -- xxx <- fromBrokerMetadataPtr bmd+ cid <- peekCText $ group'RdKafkaGroupInfoT gi+ stt <- peekCText $ state'RdKafkaGroupInfoT gi+ prt <- peekCText $ protocolType'RdKafkaGroupInfoT gi+ pr <- peekCText $ protocol'RdKafkaGroupInfoT gi+ mbs <- peekArray (memberCnt'RdKafkaGroupInfoT gi) (members'RdKafkaGroupInfoT gi)+ mbl <- mapM fromGroupMemberInfoPtr mbs+ pure $ do+ state <- groupStateFromKafkaString stt+ pure+ GroupInfo+ { -- giBroker = bmd+ giGroup = ConsumerGroupId cid,+ giError = kafkaErrorToMaybe $ KafkaResponseError (err'RdKafkaGroupInfoT gi),+ giState = state,+ giProtocolType = GroupProtocolType prt,+ giProtocol = GroupProtocol pr,+ giMembers = mbl+ }++fromGroupMemberInfoPtr :: RdKafkaGroupMemberInfoT -> IO GroupMemberInfo+fromGroupMemberInfoPtr mi = do+ mid <- peekCText $ memberId'RdKafkaGroupMemberInfoT mi+ cid <- peekCText $ clientId'RdKafkaGroupMemberInfoT mi+ hst <- peekCText $ clientHost'RdKafkaGroupMemberInfoT mi+ mtd <- peekArray (memberMetadataSize'RdKafkaGroupMemberInfoT mi) (memberMetadata'RdKafkaGroupMemberInfoT mi)+ ass <- peekArray (memberAssignmentSize'RdKafkaGroupMemberInfoT mi) (memberAssignment'RdKafkaGroupMemberInfoT mi)+ return+ GroupMemberInfo+ { gmiMemberId = GroupMemberId mid,+ gmiClientId = ClientId cid,+ gmiClientHost = hst,+ gmiMetadata = pack mtd,+ gmiAssignment = pack ass+ }++fromTopicMetadataPtr :: RdKafkaMetadataTopicT -> IO TopicMetadata+fromTopicMetadataPtr tm = do+ tnm <- peekCText (topic'RdKafkaMetadataTopicT tm)+ pts <- peekArray (partitionCnt'RdKafkaMetadataTopicT tm) (partitions'RdKafkaMetadataTopicT tm)+ pms <- mapM fromPartitionMetadataPtr pts+ return+ TopicMetadata+ { tmTopicName = TopicName tnm,+ tmPartitions = pms,+ tmError = kafkaErrorToMaybe $ KafkaResponseError (err'RdKafkaMetadataTopicT tm)+ }++fromPartitionMetadataPtr :: RdKafkaMetadataPartitionT -> IO PartitionMetadata+fromPartitionMetadataPtr pm = do+ reps <- peekArray (replicaCnt'RdKafkaMetadataPartitionT pm) (replicas'RdKafkaMetadataPartitionT pm)+ isrs <- peekArray (isrCnt'RdKafkaMetadataPartitionT pm) (isrs'RdKafkaMetadataPartitionT pm)+ return+ PartitionMetadata+ { pmPartitionId = PartitionId (id'RdKafkaMetadataPartitionT pm),+ pmError = kafkaErrorToMaybe $ KafkaResponseError (err'RdKafkaMetadataPartitionT pm),+ pmLeader = BrokerId (leader'RdKafkaMetadataPartitionT pm),+ pmReplicas = BrokerId . fromIntegral <$> reps,+ pmInSyncReplicas = BrokerId . fromIntegral <$> isrs+ }++fromBrokerMetadataPtr :: RdKafkaMetadataBrokerT -> IO BrokerMetadata+fromBrokerMetadataPtr bm = do+ host <- peekCText (host'RdKafkaMetadataBrokerT bm)+ return+ BrokerMetadata+ { bmBrokerId = BrokerId (id'RdKafkaMetadataBrokerT bm),+ bmBrokerHost = host,+ bmBrokerPort = port'RdKafkaMetadataBrokerT bm+ }++fromKafkaMetadataPtr :: RdKafkaMetadataTPtr -> IO KafkaMetadata+fromKafkaMetadataPtr ptr =+ withForeignPtr ptr $ \realPtr -> do+ km <- peek realPtr+ pbms <- peekArray (brokerCnt'RdKafkaMetadataT km) (brokers'RdKafkaMetadataT km)+ bms <- mapM fromBrokerMetadataPtr pbms+ ptms <- peekArray (topicCnt'RdKafkaMetadataT km) (topics'RdKafkaMetadataT km)+ tms <- mapM fromTopicMetadataPtr ptms+ return+ KafkaMetadata+ { kmBrokers = bms,+ kmTopics = tms,+ kmOrigBroker = BrokerId $ fromIntegral (origBrokerId'RdKafkaMetadataT km)+ }++groupStateFromKafkaString :: Text -> Either KafkaError GroupState+groupStateFromKafkaString s = case s of+ "PreparingRebalance" -> Right GroupPreparingRebalance+ "CompletingRebalance" -> Right GroupAwaitingSync+ "AwaitingSync" -> Right GroupAwaitingSync+ "Stable" -> Right GroupStable+ "Dead" -> Right GroupDead+ "Empty" -> Right GroupEmpty+ _ -> Left (KafkaError ("Unsupported Kafka consumer group state: " <> s))
+ src/Kafka/Producer.hs view
@@ -0,0 +1,312 @@+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE TupleSections #-}++-----------------------------------------------------------------------------++-----------------------------------------------------------------------------++-- |+-- Module to produce messages to Kafka topics.+--+-- Here's an example of code to produce messages to a topic:+--+-- @+-- import Control.Exception (bracket)+-- import Control.Monad (forM_)+-- import Data.ByteString (ByteString)+-- import Kafka.Producer+--+-- -- Global producer properties+-- producerProps :: 'ProducerProperties'+-- producerProps = 'brokersList' ["localhost:9092"]+-- <> 'logLevel' 'KafkaLogDebug'+--+-- -- Topic to send messages to+-- targetTopic :: 'TopicName'+-- targetTopic = 'TopicName' "kafka-client-example-topic"+--+-- -- Run an example+-- runProducerExample :: IO ()+-- runProducerExample =+-- bracket mkProducer clProducer runHandler >>= print+-- where+-- mkProducer = 'newProducer' producerProps+-- clProducer (Left _) = pure ()+-- clProducer (Right prod) = 'closeProducer' prod+-- runHandler (Left err) = pure $ Left err+-- runHandler (Right prod) = sendMessages prod+--+-- -- Example sending 2 messages and printing the response from Kafka+-- sendMessages :: 'KafkaProducer' -> IO (Either 'KafkaError' ())+-- sendMessages prod = do+-- err1 <- 'produceMessage' prod (mkMessage Nothing (Just "test from producer") )+-- forM_ err1 print+--+-- err2 <- 'produceMessage' prod (mkMessage (Just "key") (Just "test from producer (with key)"))+-- forM_ err2 print+--+-- pure $ Right ()+--+-- mkMessage :: Maybe ByteString -> Maybe ByteString -> 'ProducerRecord'+-- mkMessage k v = 'ProducerRecord'+-- { 'prTopic' = targetTopic+-- , 'prPartition' = 'UnassignedPartition'+-- , 'prKey' = k+-- , 'prValue' = v+-- }+-- @+module Kafka.Producer+ ( KafkaProducer,+ module X,+ runProducer,+ newProducer,+ produceMessage,+ produceMessage',+ flushProducer,+ flushProducerTimeout,+ purgeProducer,+ setSaslCredentials,+ closeProducer,+ RdKafkaRespErrT (..),+ )+where++import Kafka.Internal.CallbackOwner (releaseUnattachedCallbacks)++import Control.Exception (bracket, mask, mask_, onException)+import Control.Monad (forM_)+import Control.Monad.IO.Class (MonadIO (liftIO))+import Data.Bits ((.|.))+import Data.ByteString qualified as BS+import Data.ByteString.Internal qualified as BSI+import Data.Text (Text)+import Data.Text qualified as Text+import Foreign.C.String (withCString)+import Foreign.C.Types (CInt)+import Foreign.ForeignPtr (withForeignPtr)+import Foreign.Marshal.Alloc (allocaBytes)+import Foreign.Marshal.Utils (withMany)+import Foreign.Ptr (Ptr, nullPtr, plusPtr)+import Foreign.StablePtr (castStablePtrToPtr, freeStablePtr, newStablePtr)+import Kafka.Internal.RdKafka (RdKafkaRespErrT (..), RdKafkaTypeT (..), RdKafkaVuT (..), newRdKafkaT, rdKafkaErrorCode, rdKafkaErrorDestroy, rdKafkaFlush, rdKafkaMessageProduceVa, rdKafkaPurge, rdKafkaPurgeFInflight, rdKafkaPurgeFNonBlocking, rdKafkaPurgeFQueue, rdKafkaSetLogLevel)+import Kafka.Internal.Setup (Callback (..), Kafka (..), KafkaConf (..), KafkaProps (..), TopicProps (..), getRdKafka, kafkaConf, setAllKafkaConfValues, topicConf)+import Kafka.Internal.Shared (kafkaErrorToMaybe, pollEvents, setSaslCredentials')+import Kafka.Producer.Convert (copyMsgFlags, handleProduceErrT, producePartitionCInt)+import Kafka.Producer.Types (KafkaProducer (..))++import Kafka.Producer.ProducerProperties as X+import Kafka.Producer.Types as X hiding (KafkaProducer)+import Kafka.Types as X++-- | Runs Kafka Producer.+-- The callback provided is expected to call 'produceMessage'+-- to send messages to Kafka.+{-# DEPRECATED runProducer "Use 'newProducer'/'closeProducer' instead" #-}+runProducer ::+ ProducerProperties ->+ (KafkaProducer -> IO (Either KafkaError a)) ->+ IO (Either KafkaError a)+runProducer props f =+ bracket mkProducer clProducer runHandler+ where+ mkProducer = newProducer props++ clProducer (Left _) = return ()+ clProducer (Right prod) = closeProducer prod++ runHandler (Left err) = return $ Left err+ runHandler (Right prod) = f prod++-- | Creates a new kafka producer+-- A newly created producer must be closed with 'closeProducer' function.+-- Explicit topic properties override matching global properties; unrelated+-- global properties are preserved. Invalid topic properties retain the+-- existing configuration-exception convention.+newProducer :: (MonadIO m) => ProducerProperties -> m (Either KafkaError KafkaProducer)+newProducer pps = liftIO $ mask $ \restore -> do+ kc@(KafkaConf kc' _ _ _ _ _) <- kafkaConf (KafkaProps $ (ppKafkaProps pps))+ flip onException (releaseUnattachedCallbacks (kcfgCallbackOwner kc)) $ restore $ do+ tc <- topicConf (TopicProps $ (ppTopicProps pps))+ -- librdkafka accepts topic properties on the global configuration. Merge+ -- only explicit keys: replacing default_topic_conf would discard topic+ -- properties already supplied through the global map.+ setAllKafkaConfValues kc (KafkaProps (ppTopicProps pps))++ -- add default delivery report callback+ let Callback setDeliveryCallback = deliveryCallback (const mempty)+ setDeliveryCallback kc++ -- set callbacks+ forM_ (ppCallbacks pps) (\(Callback setCb) -> setCb kc)++ mbKafka <- newRdKafkaT (kcfgCallbackOwner kc) RdKafkaProducer kc'+ case mbKafka of+ Left err -> return . Left $ KafkaError err+ Right kafka -> do+ forM_ (ppLogLevel pps) (rdKafkaSetLogLevel kafka . fromEnum)+ let prod = KafkaProducer (Kafka kafka) kc tc+ return (Right prod)++-- | Sends a single message.+-- Since librdkafka is backed by a queue, this function can return before messages are sent. See+-- 'flushProducer' to wait for queue to empty.+produceMessage ::+ (MonadIO m) =>+ KafkaProducer ->+ ProducerRecord ->+ m (Maybe KafkaError)+produceMessage kp m = produceMessage' kp m (pure . mempty) >>= adjustRes+ where+ adjustRes = \case+ Right () -> pure Nothing+ Left (ImmediateError err) -> pure (Just err)++-- | Sends a single message with a registered callback.+--+-- The callback can be a long running process, as it is forked by the thread+-- that handles the delivery reports.+--+-- Absent and empty keys/values remain distinct. Topic and header names+-- containing NUL, and partition numbers outside the native C integer range,+-- return an immediate 'KafkaBadSpecification' before enqueueing.+produceMessage' ::+ (MonadIO m) =>+ KafkaProducer ->+ ProducerRecord ->+ (DeliveryReport -> IO ()) ->+ m (Either ImmediateError ())+produceMessage' kp@(KafkaProducer (Kafka k) _ _) msg cb =+ liftIO $ case recordError msg of+ Just err -> pure (Left (ImmediateError err))+ Nothing -> fireCallbacks >> produceIt+ where+ fireCallbacks =+ pollEvents kp . Just . Timeout $ 0++ produceIt =+ withBS (prValue msg) $ \payloadPtr payloadLength ->+ withBS (prKey msg) $ \keyPtr keyLength ->+ withHeaders (prHeaders msg) $ \hdrs ->+ withCString (Text.unpack . unTopicName . prTopic $ msg) $ \topicName -> mask_ $ do+ callbackPtr <- newStablePtr cb+ let opts =+ [ Topic'RdKafkaVu topicName,+ Partition'RdKafkaVu . producePartitionCInt . prPartition $ msg,+ MsgFlags'RdKafkaVu (fromIntegral copyMsgFlags),+ Value'RdKafkaVu payloadPtr (fromIntegral payloadLength),+ Key'RdKafkaVu keyPtr (fromIntegral keyLength),+ Opaque'RdKafkaVu (castStablePtrToPtr callbackPtr)+ ]++ -- Once enqueue succeeds another poller can already have served+ -- the report and freed this root. Only an immediate rejection+ -- leaves ownership here; no cleanup may cover the success path.+ nativeError <- rdKafkaMessageProduceVa k (hdrs ++ opts) `onException` freeStablePtr callbackPtr+ if nativeError == nullPtr+ then pure (Right ())+ else bracket (pure nativeError) rdKafkaErrorDestroy $ \native -> do+ -- A non-null error object means rejection. Release before+ -- decoding it, so even a conversion exception cannot retain+ -- the callback. Only NULL transfers ownership to delivery.+ freeStablePtr callbackPtr+ code <- rdKafkaErrorCode native+ res <- handleProduceErrT code+ pure $ Left (ImmediateError (maybe KafkaInvalidReturnValue id res))++-- | Closes the producer.+-- Will wait until the outbound queue is drained before returning the control.+closeProducer :: (MonadIO m) => KafkaProducer -> m ()+closeProducer = flushProducer++-- | Drains the outbound queue for a producer, blocking until every queued+-- message has been delivered or has failed and its delivery report has been+-- served.+--+-- This function is also called automatically when the producer is closed+-- with 'closeProducer' to ensure that all queued messages make it to Kafka.+-- It never gives up; use 'flushProducerTimeout' to bound the wait.+flushProducer :: (MonadIO m) => KafkaProducer -> m ()+flushProducer kp = liftIO go+ where+ go =+ flushProducerTimeout kp (Timeout 1000) >>= \case+ Just (KafkaResponseError RdKafkaRespErrTimedOut) -> go+ _ -> pure ()++-- | Waits up to the timeout for every queued message to be delivered or to+-- fail (@rd_kafka_flush@), serving delivery callbacks meanwhile.+--+-- Returns 'Nothing' once the outbound queue is empty, and+-- @'Just' ('KafkaResponseError' 'RdKafkaRespErrTimedOut')@ when messages are+-- still outstanding after the timeout.+flushProducerTimeout :: (MonadIO m) => KafkaProducer -> Timeout -> m (Maybe KafkaError)+flushProducerTimeout kp (Timeout ms) =+ liftIO $ kafkaErrorToMaybe . KafkaResponseError <$> rdKafkaFlush (getRdKafka kp) ms++-- | Purges messages from the producer (@rd_kafka_purge@): those still queued+-- with 'PurgeQueue', those awaiting a broker response with 'PurgeInFlight'.+-- An empty list purges nothing.+--+-- Purged messages are not lost silently: each is reported to the delivery+-- callback as a 'DeliveryFailure' with+-- @'KafkaResponseError' 'RdKafkaRespErrPurgeQueue'@ or+-- @'KafkaResponseError' 'RdKafkaRespErrPurgeInflight'@, the next time+-- callbacks are served (for example by 'flushProducer'). A purge does not+-- abort an in-flight request; its response is ignored. Unless+-- 'PurgeNonBlocking' is given, the call waits for librdkafka's background+-- threads to acknowledge the purge.+purgeProducer :: (MonadIO m) => KafkaProducer -> [PurgeFlag] -> m (Maybe KafkaError)+purgeProducer kp flags =+ liftIO $ kafkaErrorToMaybe . KafkaResponseError <$> rdKafkaPurge (getRdKafka kp) (foldr ((.|.) . purgeFlagBits) 0 flags)+ where+ purgeFlagBits = \case+ PurgeQueue -> rdKafkaPurgeFQueue+ PurgeInFlight -> rdKafkaPurgeFInflight+ PurgeNonBlocking -> rdKafkaPurgeFNonBlocking++-- | Replaces the SASL username and password the producer uses for future+-- authentications (@rd_kafka_sasl_set_credentials@); existing connections+-- are not re-authenticated. librdkafka stores the credentials whether or not+-- SASL is configured.+-- Embedded NUL in either credential returns 'KafkaBadSpecification' before+-- changing the native credentials.+setSaslCredentials ::+ (MonadIO m) =>+ KafkaProducer ->+ -- | username+ Text ->+ -- | password+ Text ->+ m (Maybe KafkaError)+setSaslCredentials kp username password = liftIO $ setSaslCredentials' kp username password++------------------------------------------------------------------------------------++recordError :: ProducerRecord -> Maybe KafkaError+recordError record+ | Text.any (== '\0') (unTopicName (prTopic record)) = invalid "topic name contains NUL"+ | any (BS.elem 0 . fst) (headersToList (prHeaders record)) = invalid "header name contains NUL"+ | SpecifiedPartition partition <- prPartition record,+ toInteger partition < toInteger (minBound :: CInt) || toInteger partition > toInteger (maxBound :: CInt) =+ invalid "partition id is outside the C int range"+ | otherwise = Nothing+ where+ invalid = Just . KafkaBadSpecification++withHeaders :: Headers -> ([RdKafkaVuT] -> IO a) -> IO a+withHeaders hds = withMany allocHeader (headersToList hds)+ where+ allocHeader (nm, val) f =+ BS.useAsCString nm $ \cnm ->+ withBS (Just val) $ \vp vl ->+ f $ Header'RdKafkaVu cnm vp (fromIntegral vl)++withBS :: Maybe BS.ByteString -> (Ptr a -> Int -> IO b) -> IO b+withBS Nothing f = f nullPtr 0+-- The empty ByteString can have a null backing pointer. Native Kafka uses+-- null to mean an absent key/value, even with length zero, so keep Just empty+-- distinct from Nothing with a non-null temporary pointer.+withBS (Just bs) f | BS.null bs = allocaBytes 1 $ \p -> f p 0+withBS (Just bs) f =+ let (d, o, l) = BSI.toForeignPtr bs+ in withForeignPtr d $ \p -> f (p `plusPtr` o) l
+ src/Kafka/Producer/Callbacks.hs view
@@ -0,0 +1,93 @@+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE TypeApplications #-}++module Kafka.Producer.Callbacks+ ( deliveryCallback,+ module X,+ )+where++import Control.Concurrent (forkIOWithUnmask)+import Control.Exception (SomeException, bracket, catch, mask, throwIO, try)+import Control.Monad (void)+import Data.Either (fromRight)+import Foreign.C.Error (getErrno)+import Foreign.Ptr (Ptr, nullPtr)+import Foreign.StablePtr (castPtrToStablePtr, deRefStablePtr, freeStablePtr)+import Foreign.Storable (Storable (peek))+import Kafka.Callbacks as X+import Kafka.Consumer.Types (Offset (..))+import Kafka.Internal.RdKafka (RdKafkaMessageT (..), RdKafkaRespErrT (..), rdKafkaConfSetDrMsgCb)+import Kafka.Internal.Setup (Callback (..), KafkaConf (kcfgCallbackOwner), getRdKafkaConf)+import Kafka.Internal.Shared (kafkaRespErr, readHeaders, readKey, readPayload, readTopic)+import Kafka.Producer.Types (DeliveryReport (..), ProducePartition (..), ProducerRecord (..))+import Kafka.Types (KafkaError (..), TopicName (..))++-- | Sets the callback for delivery reports.+--+-- /Note: A callback should not be a long-running process as it blocks+-- librdkafka from continuing on the thread that handles the delivery+-- callbacks. For callbacks to individual messsages see+-- 'Kafka.Producer.produceMessage\''./+--+-- Exceptions from a global callback are reported through the runtime's+-- uncaught-exception handler on a separate Haskell thread. They do not unwind+-- through librdkafka or prevent the per-message callback from running. A+-- per-message callback runs unmasked on its own thread and uses that same+-- runtime exception policy.+deliveryCallback :: (DeliveryReport -> IO ()) -> Callback+deliveryCallback callback = Callback $ \kc -> rdKafkaConfSetDrMsgCb (kcfgCallbackOwner kc) (getRdKafkaConf kc) realCb+ where+ realCb :: t -> Ptr RdKafkaMessageT -> IO ()+ realCb _ mptr = containCallbackException $ mask $ \restore ->+ if mptr == nullPtr+ then getErrno >>= (restore . callback . NoMessageError . kafkaRespErr)+ else do+ s <- peek mptr+ let cbPtr = opaque'RdKafkaMessageT s+ deliver messageCallback = do+ prodRec <- mkProdRec mptr+ let rep =+ if err'RdKafkaMessageT s /= RdKafkaRespErrNoError+ then mkErrorReport s prodRec+ else mkSuccessReport s prodRec+ outcome <- try @SomeException (restore (callback rep))+ -- Forking transfers the closure to a Haskell thread before+ -- the StablePtr root is released, even if the global callback+ -- threw. A long per-message callback never blocks native poll.+ mapM_ (\msgCb -> void $ forkIOWithUnmask (\unmask -> unmask (msgCb rep))) messageCallback+ either throwIO pure outcome+ if cbPtr == nullPtr+ then deliver Nothing+ else bracket (pure $ castPtrToStablePtr cbPtr) freeStablePtr $ \stablePtr -> do+ msgCb <- deRefStablePtr @(DeliveryReport -> IO ()) stablePtr+ deliver (Just msgCb)++-- A Haskell exception cannot cross a foreign callback frame. Throwing on a+-- fresh Haskell thread retains the ordinary uncaught-exception reporting+-- policy without retaining the native message or its StablePtr.+containCallbackException :: IO () -> IO ()+containCallbackException action =+ action `catch` \(exception :: SomeException) ->+ void $ forkIOWithUnmask (\unmask -> unmask (throwIO exception))++mkErrorReport :: RdKafkaMessageT -> ProducerRecord -> DeliveryReport+mkErrorReport msg prodRec = DeliveryFailure prodRec (KafkaResponseError (err'RdKafkaMessageT msg))++mkSuccessReport :: RdKafkaMessageT -> ProducerRecord -> DeliveryReport+mkSuccessReport msg prodRec = DeliverySuccess prodRec (Offset $ offset'RdKafkaMessageT msg)++mkProdRec :: Ptr RdKafkaMessageT -> IO ProducerRecord+mkProdRec pmsg = do+ msg <- peek pmsg+ topic <- readTopic msg+ key <- readKey msg+ payload <- readPayload msg+ flip fmap (fromRight mempty <$> readHeaders pmsg) $ \headers ->+ ProducerRecord+ { prTopic = TopicName topic,+ prPartition = SpecifiedPartition (partition'RdKafkaMessageT msg),+ prKey = key,+ prValue = payload,+ prHeaders = headers+ }
+ src/Kafka/Producer/Convert.hs view
@@ -0,0 +1,46 @@+module Kafka.Producer.Convert+ ( copyMsgFlags,+ producePartitionInt,+ producePartitionCInt,+ handleProduceErr,+ handleProduceErr',+ handleProduceErrT,+ )+where++import Foreign.C.Error (getErrno)+import Foreign.C.Types (CInt)+import Kafka.Internal.RdKafka (RdKafkaRespErrT (..), rdKafkaMsgFlagCopy)+import Kafka.Internal.Shared (kafkaRespErr)+import Kafka.Producer.Types (ProducePartition (..))+import Kafka.Types (KafkaError (..))++copyMsgFlags :: Int+copyMsgFlags = rdKafkaMsgFlagCopy+{-# INLINE copyMsgFlags #-}++producePartitionInt :: ProducePartition -> Int+producePartitionInt UnassignedPartition = -1+producePartitionInt (SpecifiedPartition n) = n+{-# INLINE producePartitionInt #-}++producePartitionCInt :: ProducePartition -> CInt+producePartitionCInt = fromIntegral . producePartitionInt+{-# INLINE producePartitionCInt #-}++handleProduceErr :: Int -> IO (Maybe KafkaError)+handleProduceErr (-1) = Just . kafkaRespErr <$> getErrno+handleProduceErr 0 = return Nothing+handleProduceErr _ = return $ Just KafkaInvalidReturnValue+{-# INLINE handleProduceErr #-}++handleProduceErrT :: RdKafkaRespErrT -> IO (Maybe KafkaError)+handleProduceErrT RdKafkaRespErrNoError = return Nothing+handleProduceErrT e = return $ Just (KafkaResponseError e)+{-# INLINE handleProduceErrT #-}++handleProduceErr' :: Int -> IO (Either KafkaError ())+handleProduceErr' (-1) = Left . kafkaRespErr <$> getErrno+handleProduceErr' 0 = return (Right ())+handleProduceErr' _ = return $ Left KafkaInvalidReturnValue+{-# INLINE handleProduceErr' #-}
+ src/Kafka/Producer/ProducerProperties.hs view
@@ -0,0 +1,136 @@+{-# LANGUAGE OverloadedStrings #-}++-----------------------------------------------------------------------------++-----------------------------------------------------------------------------++-- |+-- Module with producer properties types and functions.+module Kafka.Producer.ProducerProperties+ ( ProducerProperties (..),+ brokersList,+ setCallback,+ logLevel,+ compression,+ topicCompression,+ sendTimeout,+ statisticsInterval,+ extraProps,+ extraProp,+ suppressDisconnectLogs,+ extraTopicProps,+ debugOptions,+ module Kafka.Producer.Callbacks,+ )+where++import Control.Monad (MonadPlus (mplus))+import Data.Map (Map)+import Data.Map qualified as M+import Data.Semigroup as Sem+import Data.Text (Text)+import Data.Text qualified as Text+import Kafka.Types (BrokerAddress (..), KafkaCompressionCodec (..), KafkaDebug (..), KafkaLogLevel (..), Millis (..), Timeout (..), kafkaCompressionCodecToText, kafkaDebugToText)++import Kafka.Producer.Callbacks++-- | Properties to create 'Kafka.Producer.Types.KafkaProducer'.+data ProducerProperties = ProducerProperties+ { ppKafkaProps :: Map Text Text,+ ppTopicProps :: Map Text Text,+ ppLogLevel :: Maybe KafkaLogLevel,+ ppCallbacks :: [Callback]+ }++instance Sem.Semigroup ProducerProperties where+ (ProducerProperties k1 t1 ll1 cb1) <> (ProducerProperties k2 t2 ll2 cb2) =+ ProducerProperties (M.union k2 k1) (M.union t2 t1) (ll2 `mplus` ll1) (cb1 `mplus` cb2)+ {-# INLINE (<>) #-}++-- | /Right biased/ so we prefer newer properties over older ones.+instance Monoid ProducerProperties where+ mempty =+ ProducerProperties+ { ppKafkaProps = M.empty,+ ppTopicProps = M.empty,+ ppLogLevel = Nothing,+ ppCallbacks = []+ }+ {-# INLINE mempty #-}+ mappend = (Sem.<>)+ {-# INLINE mappend #-}++-- | Set the <https://kafka.apache.org/documentation/#bootstrap.servers list of brokers> to contact to connect to the Kafka cluster.+brokersList :: [BrokerAddress] -> ProducerProperties+brokersList bs =+ let bs' = Text.intercalate "," (unBrokerAddress <$> bs)+ in extraProps $ M.fromList [("bootstrap.servers", bs')]++-- | Set the producer callback.+--+-- For examples of use, see:+--+-- * 'errorCallback'+-- * 'logCallback'+-- * 'statsCallback'+setCallback :: Callback -> ProducerProperties+setCallback cb = mempty {ppCallbacks = [cb]}++-- | Sets the logging level.+-- Usually is used with 'debugOptions' to configure which logs are needed.+logLevel :: KafkaLogLevel -> ProducerProperties+logLevel ll = mempty {ppLogLevel = Just ll}++-- | Set the <https://github.com/edenhill/librdkafka/blob/master/CONFIGURATION.md compression.codec> for the producer.+compression :: KafkaCompressionCodec -> ProducerProperties+compression c =+ extraProps $ M.singleton "compression.codec" (kafkaCompressionCodecToText c)++-- | Set the <https://github.com/edenhill/librdkafka/blob/master/CONFIGURATION.md#topic-configuration-properties compression.codec> for the topic.+topicCompression :: KafkaCompressionCodec -> ProducerProperties+topicCompression c =+ extraTopicProps $ M.singleton "compression.codec" (kafkaCompressionCodecToText c)++-- | Set the <https://github.com/edenhill/librdkafka/blob/master/CONFIGURATION.md#topic-configuration-properties message.timeout.ms>.+sendTimeout :: Timeout -> ProducerProperties+sendTimeout (Timeout t) =+ extraTopicProps $ M.singleton "message.timeout.ms" (Text.pack $ show t)++-- | Set the <https://github.com/edenhill/librdkafka/blob/master/CONFIGURATION.md statistics.interval.ms> for the producer.+statisticsInterval :: Millis -> ProducerProperties+statisticsInterval (Millis t) =+ extraProps $ M.singleton "statistics.interval.ms" (Text.pack $ show t)++-- | Any configuration options that are supported by /librdkafka/.+-- The full list can be found <https://github.com/edenhill/librdkafka/blob/master/CONFIGURATION.md here>+extraProps :: Map Text Text -> ProducerProperties+extraProps m = mempty {ppKafkaProps = m}++-- | Any configuration options that are supported by /librdkafka/.+-- The full list can be found <https://github.com/edenhill/librdkafka/blob/master/CONFIGURATION.md here>+extraProp :: Text -> Text -> ProducerProperties+extraProp k v = mempty {ppKafkaProps = M.singleton k v}+{-# INLINE extraProp #-}++-- | Suppresses producer disconnects logs.+--+-- It might be useful to turn this off when interacting with brokers+-- with an aggressive connection.max.idle.ms value.+suppressDisconnectLogs :: ProducerProperties+suppressDisconnectLogs =+ extraProps $ M.fromList [("log.connection.close", "false")]++-- | Any *topic* configuration options that are supported by /librdkafka/.+-- The full list can be found <https://github.com/edenhill/librdkafka/blob/master/CONFIGURATION.md#topic-configuration-properties here>+-- Explicit topic properties override matching global properties when the+-- producer is created; unrelated global properties remain effective.+extraTopicProps :: Map Text Text -> ProducerProperties+extraTopicProps m = mempty {ppTopicProps = m}++-- | Sets <https://github.com/edenhill/librdkafka/blob/master/CONFIGURATION.md debug> features for the producer+-- Usually is used with 'logLevel'.+debugOptions :: [KafkaDebug] -> ProducerProperties+debugOptions [] = extraProps M.empty+debugOptions d =+ let points = Text.intercalate "," (kafkaDebugToText <$> d)+ in extraProps $ M.fromList [("debug", points)]
+ src/Kafka/Producer/Types.hs view
@@ -0,0 +1,91 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DerivingStrategies #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}++-----------------------------------------------------------------------------++-----------------------------------------------------------------------------++-- |+-- Module holding producer types.+module Kafka.Producer.Types+ ( KafkaProducer (..),+ ProducerRecord (..),+ ProducePartition (..),+ DeliveryReport (..),+ ImmediateError (..),+ PurgeFlag (..),+ )+where++import Data.ByteString+import GHC.Generics (Generic)+import Kafka.Consumer.Types (Offset (..))+import Kafka.Internal.Setup (HasKafka (..), HasKafkaConf (..), HasTopicConf (..), Kafka (..), KafkaConf (..), TopicConf (..))+import Kafka.Types (Headers, KafkaError (..), TopicName (..))++-- | The main type for Kafka message production, used e.g. to send messages.+--+-- Use 'Kafka.Producer.newProducer' to acquire a managed producer.+data KafkaProducer = KafkaProducer+ { kpKafkaPtr :: !Kafka,+ kpKafkaConf :: !KafkaConf,+ kpTopicConf :: !TopicConf+ }++instance HasKafka KafkaProducer where+ getKafka = kpKafkaPtr+ {-# INLINE getKafka #-}++instance HasKafkaConf KafkaProducer where+ getKafkaConf = kpKafkaConf+ {-# INLINE getKafkaConf #-}++instance HasTopicConf KafkaProducer where+ getTopicConf = kpTopicConf+ {-# INLINE getTopicConf #-}++-- | Represents messages /to be enqueued/ onto a Kafka broker (i.e. used for a producer)+data ProducerRecord = ProducerRecord+ { prTopic :: !TopicName,+ prPartition :: !ProducePartition,+ prKey :: Maybe ByteString,+ prValue :: Maybe ByteString,+ prHeaders :: !Headers+ }+ deriving stock (Eq, Show, Generic)++data ProducePartition+ = -- | The partition number of the topic+ SpecifiedPartition {-# UNPACK #-} !Int+ | -- | Let the Kafka broker decide the partition+ UnassignedPartition+ deriving stock (Show, Eq, Ord, Generic)++-- | Data type representing an error that is caused by pre-flight conditions not being met+newtype ImmediateError = ImmediateError KafkaError+ deriving newtype (Eq, Show)++-- | The result of sending a message to the broker, useful for callbacks+data DeliveryReport+ = -- | The message was successfully sent at this offset+ DeliverySuccess ProducerRecord Offset+ | -- | The message could not be sent+ DeliveryFailure ProducerRecord KafkaError+ | -- | An error occurred, but /librdkafka/ did not attach any sent message+ NoMessageError KafkaError+ deriving stock (Show, Eq, Generic)++-- | What 'Kafka.Producer.purgeProducer' purges.+data PurgeFlag+ = -- | Messages still in the producer's queues, not yet sent to a broker+ -- (@RD_KAFKA_PURGE_F_QUEUE@).+ PurgeQueue+ | -- | Messages sent to a broker and awaiting a response+ -- (@RD_KAFKA_PURGE_F_INFLIGHT@).+ PurgeInFlight+ | -- | Do not wait for background threads to acknowledge the purge+ -- (@RD_KAFKA_PURGE_F_NON_BLOCKING@).+ PurgeNonBlocking+ deriving stock (Show, Eq, Ord, Enum, Bounded, Generic)
+ src/Kafka/Topic.hs view
@@ -0,0 +1,196 @@+module Kafka.Topic+ ( module X,+ createTopic,+ deleteTopic,+ )+where++import Control.Exception+import Control.Monad (join)+import Control.Monad.IO.Class+import Control.Monad.Trans.Except+import Data.Bifunctor+import Data.Foldable+import Data.List.NonEmpty+import Data.List.NonEmpty qualified as NEL+import Data.Map qualified as M+import Data.Text qualified as T+import Foreign.C.Types (CInt)+import Foreign.ForeignPtr (finalizeForeignPtr, withForeignPtr)+import GHC.Clock (getMonotonicTimeNSec)+import Kafka.Internal.RdKafka+import Kafka.Internal.Setup++import Kafka.Topic.Types as X+import Kafka.Types as X++-- | Create a topic with the supplied broker-side settings. Invalid C-string+-- inputs or unrepresentable counts return 'KafkaBadSpecification'; other+-- validation is performed by librdkafka and the broker; unknown-property+-- behavior follows the broker. The request wait follows+-- @socket.timeout.ms@ with up to one extra second for native error delivery.+-- A timeout leaves the broker's eventual outcome unknown.++--- CREATE TOPIC ---+createTopic :: (HasKafka k) => k -> NewTopic -> IO (Either KafkaError TopicName)+createTopic k topic+ | Just err <- validateNewTopic topic = pure (Left err)+ | otherwise = withAdminResources (getRdKafka k) $ \queue opts requestTimeout -> do+ let kafkaPtr = getRdKafka k+ topicRes <- withNewTopic topic $ \topic' -> rdKafkaCreateTopic kafkaPtr topic' opts queue++ case topicRes of+ Left err -> do+ pure $ Left (NEL.head err)+ Right _ -> do+ waitForResponse (topicName topic) rdKafkaEventCreateTopicsResult rdKafkaCreateTopicsResultTopics queue requestTimeout++-- | Delete a topic. The request wait follows @socket.timeout.ms@, with up+-- to one second for native error delivery. A timeout leaves the broker's+-- eventual outcome unknown. Embedded NUL names are rejected before+-- calling the native API.++--- DELETE TOPIC ---+deleteTopic ::+ (HasKafka k) =>+ k ->+ TopicName ->+ IO (Either KafkaError TopicName)+deleteTopic k topic+ | Just err <- validateTopicName topic = pure (Left err)+ | otherwise = liftIO $ withAdminResources (getRdKafka k) $ \queue opts requestTimeout -> do+ let kafkaPtr = getRdKafka k+ topicRes <- withOldTopic topic $ \topic' -> rdKafkaDeleteTopics kafkaPtr [topic'] opts queue+ case topicRes of+ Left err -> do+ pure $ Left (NEL.head err)+ Right _ -> do+ waitForResponse topic rdKafkaEventDeleteTopicsResult rdKafkaDeleteTopicsResultTopics queue requestTimeout++-- C strings cannot represent NUL and C integer conversion must not wrap a+-- count into another valid request. Other values retain native validation.+validateTopicName :: TopicName -> Maybe KafkaError+validateTopicName (TopicName name)+ | T.any (== '\0') name = Just (KafkaBadSpecification "topic name must not contain NUL")+ | otherwise = Nothing++validateNewTopic :: NewTopic -> Maybe KafkaError+validateNewTopic topic+ | Just err <- validateTopicName (topicName topic) = Just err+ | outsideCInt (unPartitionCount (topicPartitionCount topic)) =+ Just (KafkaBadSpecification "partition count is outside the C int range")+ | outsideCInt (unReplicationFactor (topicReplicationFactor topic)) =+ Just (KafkaBadSpecification "replication factor is outside the C int range")+ | any (\(key, value) -> '\0' `elem` key || '\0' `elem` value) (M.toList (topicConfig topic)) =+ Just (KafkaBadSpecification "topic configuration keys and values must not contain NUL")+ | otherwise = Nothing+ where+ outsideCInt value = value < fromIntegral (minBound :: CInt) || value > fromIntegral (maxBound :: CInt)++withNewTopic ::+ NewTopic ->+ (RdKafkaNewTopicTPtr -> IO a) ->+ IO (Either (NonEmpty KafkaError) a)+withNewTopic t action =+ fmap join $ withUnsafeOne t mkNewTopicUnsafe rdKafkaNewTopicDestroy $ \native -> do+ configured <- whileRight (uncurry $ rdKafkaNewTopicSetConfig native) (M.toList $ topicConfig t)+ case configured of+ Left err -> pure (Left (singletonList (KafkaResponseError err)))+ Right () -> Right <$> action native++withOldTopic ::+ TopicName ->+ (RdKafkaDeleteTopicTPtr -> IO a) ->+ IO (Either (NonEmpty KafkaError) a)+withOldTopic tName transform =+ bracket (oldTopicPtr tName) (mapM_ finalizeForeignPtr) $ \case+ Left err -> pure (Left (singletonList err))+ Right native -> Right <$> transform native++oldTopicPtr :: TopicName -> IO (Either KafkaError RdKafkaDeleteTopicTPtr)+oldTopicPtr tName = do+ res <- newRdKafkaDeleteTopic $ T.unpack . unTopicName $ tName+ case res of+ Left str -> pure $ Left (KafkaError $ T.pack str)+ Right ptr -> pure $ Right ptr++mkNewTopicUnsafe :: NewTopic -> IO (Either KafkaError RdKafkaNewTopicTPtr)+mkNewTopicUnsafe topic = do+ allocated <- newRdKafkaNewTopicUnsafe (T.unpack $ unTopicName $ topicName topic) (unPartitionCount $ topicPartitionCount topic) (unReplicationFactor $ topicReplicationFactor topic)+ pure (first (KafkaError . T.pack) allocated)++-- Keep the client alive through request completion. Each ForeignPtr owns one+-- finalizer; explicit finalization consumes it, so GC cannot free it twice.+withAdminResources :: RdKafkaTPtr -> (RdKafkaQueueTPtr -> RdKafkaAdminOptionsTPtr -> Int -> IO (Either KafkaError a)) -> IO (Either KafkaError a)+withAdminResources kafka action = withForeignPtr kafka $ \_ ->+ rdKafkaSocketTimeout kafka >>= \case+ Left err -> pure (Left (KafkaError (T.pack err)))+ Right requestTimeout ->+ bracket (newRdKafkaQueue kafka) finalizeForeignPtr $ \queue ->+ bracket (newRdKAdminOptions kafka RdKafkaAdminOpAny) finalizeForeignPtr $ \options ->+ action queue options requestTimeout++withUnsafeOne ::+ -- | Item to handle+ a ->+ -- | Create an unsafe element+ (a -> IO (Either KafkaError b)) ->+ -- | Destroy the unsafe element+ (b -> IO ()) ->+ -- | Handler+ (b -> IO c) ->+ IO (Either (NonEmpty KafkaError) c)+withUnsafeOne a mkOne cleanup f =+ bracket (mkOne a) cleanupOne processOne+ where+ cleanupOne (Right b) = cleanup b+ cleanupOne (Left _) = pure () -- no resource to clean if creation failed+ processOne (Right b) = Right <$> f b+ processOne (Left e) = pure (Left (singletonList e))++whileRight ::+ (Monad m) =>+ (a -> m (Either e ())) ->+ [a] ->+ m (Either e ())+whileRight f as = runExceptT $ traverse_ (ExceptT . f) as++-- One public request contains one topic. Decode the event while it is owned;+-- require that exact topic, and preserve request-level and per-topic errors.+waitForResponse ::+ TopicName ->+ (RdKafkaEventTPtr -> IO (Maybe a)) ->+ (a -> IO [Either (String, RdKafkaRespErrT, String) String]) ->+ RdKafkaQueueTPtr ->+ Int ->+ IO (Either KafkaError TopicName)+waitForResponse topic fromEvent toResults queue requestTimeout = do+ -- Native requests use socket.timeout.ms. Keep one poll quantum of grace+ -- for the native worker to deliver its terminal error at that deadline.+ deadline <- (+ ((fromIntegral requestTimeout + 1000) * 1000000)) <$> getMonotonicTimeNSec+ let go = do+ now <- getMonotonicTimeNSec+ if now >= deadline+ then pure (Left (KafkaResponseError RdKafkaRespErrTimedOut))+ else do+ let remaining = fromIntegral (min 1000 (max 1 ((deadline - now) `div` 1000000)))+ result <- bracket (rdKafkaQueuePoll queue remaining) (mapM_ finalizeForeignPtr) $ \case+ Nothing -> pure Nothing+ Just event -> do+ requestError <- rdKafkaEventError event+ if requestError /= RdKafkaRespErrNoError+ then pure (Just (Left (KafkaResponseError requestError)))+ else+ fromEvent event >>= \case+ Nothing -> pure (Just (Left KafkaInvalidReturnValue))+ Just response -> do+ results <- toResults response+ pure $ Just $ case results of+ [Right name] | TopicName (T.pack name) == topic -> Right topic+ [Left (name, err, _)] | TopicName (T.pack name) == topic -> Left (KafkaResponseError err)+ _ -> Left KafkaInvalidReturnValue+ maybe go pure result+ go++singletonList :: a -> NonEmpty a+singletonList x = x :| []
+ src/Kafka/Topic/Types.hs view
@@ -0,0 +1,24 @@+module Kafka.Topic.Types+ ( PartitionCount (..),+ ReplicationFactor (..),+ NewTopic (..),+ )+where++import Data.Map++import Kafka.Types++newtype PartitionCount = PartitionCount {unPartitionCount :: Int}+ deriving stock (Show, Eq)++newtype ReplicationFactor = ReplicationFactor {unReplicationFactor :: Int}+ deriving stock (Show, Eq)++data NewTopic = NewTopic+ { topicName :: TopicName,+ topicPartitionCount :: PartitionCount,+ topicReplicationFactor :: ReplicationFactor,+ topicConfig :: Map String String+ }+ deriving stock (Show)
+ src/Kafka/Transaction.hs view
@@ -0,0 +1,142 @@+-----------------------------------------------------------------------------++-----------------------------------------------------------------------------++-- |+-- Module to work wih Kafkas transactional producers.+module Kafka.Transaction+ ( initTransactions,+ beginTransaction,+ commitTransaction,+ abortTransaction,+ commitOffsetMessageTransaction,+ -- , commitTransactionWithOffsets++ TxError,+ getKafkaError,+ kafkaErrorIsFatal,+ kafkaErrorIsRetriable,+ kafkaErrorTxnRequiresAbort,+ )+where++import Control.Exception (bracket, evaluate)+import Control.Monad.IO.Class (MonadIO (liftIO))+import Foreign.ForeignPtr (finalizeForeignPtr)+import Kafka.Consumer+import Kafka.Consumer.Convert (toNativeTopicPartitionList, topicPartitionFromMessageForCommit)+import Kafka.Internal.RdKafka (RdKafkaErrorTPtr, rdKafkaAbortTransaction, rdKafkaBeginTransaction, rdKafkaCommitTransaction, rdKafkaErrorCode, rdKafkaErrorDestroy, rdKafkaErrorIsFatal, rdKafkaErrorIsRetriable, rdKafkaErrorTxnRequiresAbort, rdKafkaInitTransactions, rdKafkaSendOffsetsToTransaction)+import Kafka.Internal.Setup (getRdKafka)+import Kafka.Producer+import Kafka.Producer.Convert (handleProduceErrT)++-------------------------------------------------------------------------------------+-- Tx API++data TxError = TxError+ { txErrorKafka :: !KafkaError,+ txErrorFatal :: !Bool,+ txErrorRetriable :: !Bool,+ txErrorTxnReqAbort :: !Bool+ }++-- | Initialises Kafka for transactions+initTransactions ::+ (MonadIO m) =>+ KafkaProducer ->+ Timeout ->+ m (Maybe KafkaError)+initTransactions p (Timeout to) =+ liftIO $ bracket (rdKafkaInitTransactions (getRdKafka p) to) rdKafkaErrorDestroy decodeError++-- | Begins a new transaction+beginTransaction ::+ (MonadIO m) =>+ KafkaProducer ->+ m (Maybe KafkaError)+beginTransaction p =+ liftIO $ bracket (rdKafkaBeginTransaction (getRdKafka p)) rdKafkaErrorDestroy decodeError++-- | Commits an existing transaction+-- Pre-condition: there exists an open transaction, created with beginTransaction+commitTransaction ::+ (MonadIO m) =>+ KafkaProducer ->+ Timeout ->+ m (Maybe TxError)+commitTransaction p (Timeout to) = liftIO $ bracket (rdKafkaCommitTransaction (getRdKafka p) to) rdKafkaErrorDestroy toTxError++-- | Aborts an existing transaction+-- Pre-condition: there exists an open transaction, created with beginTransaction+abortTransaction ::+ (MonadIO m) =>+ KafkaProducer ->+ Timeout ->+ m (Maybe KafkaError)+abortTransaction p (Timeout to) =+ liftIO $ bracket (rdKafkaAbortTransaction (getRdKafka p) to) rdKafkaErrorDestroy decodeError++-- | Commits the message's offset in the current transaction+-- Similar to Kafka.Consumer.commitOffsetMessage but within a transactional context+-- Pre-condition: there exists an open transaction, created with beginTransaction+commitOffsetMessageTransaction ::+ (MonadIO m) =>+ KafkaProducer ->+ KafkaConsumer ->+ ConsumerRecord k v ->+ Timeout ->+ m (Maybe TxError)+commitOffsetMessageTransaction p c m (Timeout to) = liftIO $+ bracket (toNativeTopicPartitionList [topicPartitionFromMessageForCommit m]) finalizeForeignPtr $ \tps ->+ bracket (rdKafkaSendOffsetsToTransaction (getRdKafka p) (getRdKafka c) tps to) rdKafkaErrorDestroy toTxError++-- -- | Commit offsets for all currently assigned partitions in the current transaction+-- -- Similar to Kafka.Consumer.commitAllOffsets but within a transactional context+-- -- Pre-condition: there exists an open transaction, created with beginTransaction+-- commitAllOffsetsTransaction :: MonadIO m+-- => KafkaProducer+-- -> KafkaConsumer+-- -> Timeout+-- -> m (Maybe TxError)+-- commitAllOffsetsTransaction p c (Timeout to) = liftIO $ do+-- -- TODO: this can't be right...+-- tps <- newForeignPtr_ nullPtr+-- rdKafkaSendOffsetsToTransaction (getRdKafka p) (getRdKafka c) tps to >>= toTxError++getKafkaError :: TxError -> KafkaError+getKafkaError = txErrorKafka++kafkaErrorIsFatal :: TxError -> Bool+kafkaErrorIsFatal = txErrorFatal++kafkaErrorIsRetriable :: TxError -> Bool+kafkaErrorIsRetriable = txErrorRetriable++kafkaErrorTxnRequiresAbort :: TxError -> Bool+kafkaErrorTxnRequiresAbort = txErrorTxnReqAbort++----------------------------------------------------------------------------------------------------+-- Implementation detail, used internally+decodeError :: RdKafkaErrorTPtr -> IO (Maybe KafkaError)+decodeError pointer = rdKafkaErrorCode pointer >>= handleProduceErrT++-- The caller scopes ownership around acquisition and all decoding. Strict+-- fields are evaluated before release, so no conversion escapes that scope.+toTxError :: RdKafkaErrorTPtr -> IO (Maybe TxError)+toTxError errPtr = do+ ret <- rdKafkaErrorCode errPtr >>= handleProduceErrT+ case ret of+ Nothing -> pure Nothing+ Just ke -> do+ fatal <- rdKafkaErrorIsFatal errPtr+ retriable <- rdKafkaErrorIsRetriable errPtr+ reqAbort <- rdKafkaErrorTxnRequiresAbort errPtr+ Just+ <$> evaluate+ ( TxError+ { txErrorKafka = ke,+ txErrorFatal = fatal,+ txErrorRetriable = retriable,+ txErrorTxnReqAbort = reqAbort+ }+ )
+ src/Kafka/Types.hs view
@@ -0,0 +1,211 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE OverloadedStrings #-}++-----------------------------------------------------------------------------++-----------------------------------------------------------------------------++-- |+-- Module holding types shared by consumer and producer modules.+module Kafka.Types+ ( BrokerId (..),+ PartitionId (..),+ Millis (..),+ ClientId (..),+ BatchSize (..),+ TopicName (..),+ BrokerAddress (..),+ Timeout (..),+ KafkaLogLevel (..),+ KafkaError (..),+ KafkaDebug (..),+ KafkaCompressionCodec (..),+ TopicType (..),+ Headers,+ headersFromList,+ headersToList,+ topicType,+ kafkaDebugToText,+ kafkaCompressionCodecToText,+ )+where++import Control.Exception (Exception (..))+import Data.ByteString qualified as BS+import Data.Int (Int64)+import Data.String (IsString)+import Data.Text (Text, isPrefixOf)+import GHC.Generics (Generic)+import Kafka.Internal.RdKafka (RdKafkaRespErrT, rdKafkaErr2name, rdKafkaErr2str)++-- | Kafka broker ID+newtype BrokerId = BrokerId {unBrokerId :: Int}+ deriving stock (Show, Eq, Ord, Read, Generic)++-- | Topic partition ID+newtype PartitionId = PartitionId {unPartitionId :: Int}+ deriving stock (Show, Eq, Read, Ord, Generic)+ deriving newtype (Enum)++-- | A number of milliseconds, used to represent durations and timestamps+newtype Millis = Millis {unMillis :: Int64}+ deriving stock (Show, Read, Eq, Ord, Generic)+ deriving newtype (Num)++-- | Client ID used by Kafka to better track requests+--+-- See <https://kafka.apache.org/documentation/#client.id Kafka documentation on client ID>+newtype ClientId = ClientId+ { unClientId :: Text+ }+ deriving stock (Show, Eq, Ord, Generic)+ deriving newtype (IsString)++-- | Batch size used for polling+newtype BatchSize = BatchSize {unBatchSize :: Int}+ deriving stock (Show, Read, Eq, Ord, Generic)+ deriving newtype (Num)++-- | Whether the topic is created by a user or by the system+data TopicType+ = -- | Normal topics that are created by user.+ User+ | -- | Topics starting with a double underscore "\__" (@__consumer_offsets@, @__confluent.support.metrics@, etc.) are considered "system" topics+ System+ deriving stock (Show, Read, Eq, Ord, Generic)++-- | Topic name to consume/produce messages+--+-- Wildcard (regex) topics are supported by the /librdkafka/ assignor:+-- any topic name in the topics list that is prefixed with @^@ will+-- be regex-matched to the full list of topics in the cluster and matching+-- topics will be added to the subscription list.+newtype TopicName = TopicName+ { -- | a simple topic name or a regex if started with @^@+ unTopicName :: Text+ }+ deriving stock (Show, Eq, Ord, Read, Generic)+ deriving newtype (IsString)++-- | Deduce the type of a topic from its name, by checking if it starts with a double underscore "\__"+topicType :: TopicName -> TopicType+topicType (TopicName tn) =+ if "__" `isPrefixOf` tn then System else User+{-# INLINE topicType #-}++-- | Kafka broker address string (e.g. @broker1:9092@)+newtype BrokerAddress = BrokerAddress+ { unBrokerAddress :: Text+ }+ deriving stock (Show, Eq, Generic)+ deriving newtype (IsString)++-- | Timeout in milliseconds+newtype Timeout = Timeout {unTimeout :: Int}+ deriving stock (Show, Eq, Read, Generic)++-- | Log levels for /librdkafka/.+data KafkaLogLevel+ = KafkaLogEmerg+ | KafkaLogAlert+ | KafkaLogCrit+ | KafkaLogErr+ | KafkaLogWarning+ | KafkaLogNotice+ | KafkaLogInfo+ | KafkaLogDebug+ deriving stock (Show, Enum, Eq)++-- | All possible Kafka errors+data KafkaError+ = KafkaError Text+ | KafkaInvalidReturnValue+ | KafkaBadSpecification Text+ | KafkaResponseError RdKafkaRespErrT+ | KafkaInvalidConfigurationValue Text+ | KafkaUnknownConfigurationKey Text+ | KafkaBadConfiguration+ deriving stock (Eq, Show, Generic)++instance Exception KafkaError where+ displayException (KafkaResponseError err) =+ "[" ++ rdKafkaErr2name err ++ "] " ++ rdKafkaErr2str err+ displayException err = show err++-- | Available /librdkafka/ debug contexts+data KafkaDebug+ = DebugGeneric+ | DebugBroker+ | DebugTopic+ | DebugMetadata+ | DebugQueue+ | DebugMsg+ | DebugProtocol+ | DebugCgrp+ | DebugSecurity+ | DebugFetch+ | DebugFeature+ | DebugAll+ deriving stock (Eq, Show, Generic)++-- | Convert a 'KafkaDebug' into its /librdkafka/ string equivalent.+--+-- This is used internally by the library but may be useful to some developers.+kafkaDebugToText :: KafkaDebug -> Text+kafkaDebugToText d = case d of+ DebugGeneric -> "generic"+ DebugBroker -> "broker"+ DebugTopic -> "topic"+ DebugMetadata -> "metadata"+ DebugQueue -> "queue"+ DebugMsg -> "msg"+ DebugProtocol -> "protocol"+ DebugCgrp -> "cgrp"+ DebugSecurity -> "security"+ DebugFetch -> "fetch"+ DebugFeature -> "feature"+ DebugAll -> "all"++-- | Compression codec used by a topic+--+-- See <https://kafka.apache.org/documentation/#compression.type Kafka documentation on compression codecs>+data KafkaCompressionCodec+ = NoCompression+ | Gzip+ | Snappy+ | Lz4+ | Zstd+ deriving stock (Eq, Show, Generic)++-- | Convert a 'KafkaCompressionCodec' into its /librdkafka/ string equivalent.+--+-- This is used internally by the library but may be useful to some developers.+kafkaCompressionCodecToText :: KafkaCompressionCodec -> Text+kafkaCompressionCodecToText c = case c of+ NoCompression -> "none"+ Gzip -> "gzip"+ Snappy -> "snappy"+ Lz4 -> "lz4"+ Zstd -> "zstd"++-- | Headers that might be passed along with a record: an ordered list of+-- @(name, value)@ pairs. Kafka allows a name to repeat, so the list keeps+-- every pair, duplicates included, in wire order. A producer sends the pairs+-- in list order and a consumer decodes them in the order they were sent;+-- selecting a value for a repeated name (for example the last occurrence) is+-- left to the caller.+newtype Headers = Headers {unHeaders :: [(BS.ByteString, BS.ByteString)]}+ deriving stock (Eq, Show, Read, Generic)+ deriving newtype (Semigroup, Monoid)++-- | Headers from @(name, value)@ pairs, sent in list order. Repeated names and+-- identical pairs are kept.+headersFromList :: [(BS.ByteString, BS.ByteString)] -> Headers+headersFromList = Headers++-- | The @(name, value)@ pairs in wire order, with every repeated name and+-- identical pair the record carried.+headersToList :: Headers -> [(BS.ByteString, BS.ByteString)]+headersToList = unHeaders
+ src/Kafka/Version.hs view
@@ -0,0 +1,51 @@+-- | The version of the librdkafka C library this program is linked against.+--+-- rdkafka-hs requires librdkafka 2.15 or newer; the build refuses an older+-- library at configure time. These values come from the library loaded at run+-- time, which can be newer than the headers the package was compiled with.+module Kafka.Version+ ( LibrdkafkaVersion (..),+ librdkafkaVersion,+ librdkafkaVersionNumber,+ librdkafkaVersionParts,+ decodeLibrdkafkaVersion,+ )+where++import Data.Bits (shiftR, (.&.))+import Data.Text (Text)+import Data.Text qualified as Text+import Kafka.Internal.RdKafka (rdKafkaVersion, rdKafkaVersionStr)++-- | A decoded librdkafka version number.+data LibrdkafkaVersion = LibrdkafkaVersion+ { versionMajor :: Int,+ versionMinor :: Int,+ versionRevision :: Int+ }+ deriving stock (Eq, Ord, Show)++-- | The linked library's version string, for example @"2.15.0"@+-- (@rd_kafka_version_str@).+librdkafkaVersion :: Text+librdkafkaVersion = Text.pack rdKafkaVersionStr++-- | The linked library's version number in librdkafka's hex encoding+-- @0xMMmmrrpp@ (major, minor, revision, pre-release), for example+-- @0x020f00ff@ for 2.15.0 (@rd_kafka_version@).+librdkafkaVersionNumber :: Int+librdkafkaVersionNumber = rdKafkaVersion++-- | The linked library's version, decoded from 'librdkafkaVersionNumber'.+librdkafkaVersionParts :: LibrdkafkaVersion+librdkafkaVersionParts = decodeLibrdkafkaVersion librdkafkaVersionNumber++-- | Decode librdkafka's @0xMMmmrrpp@ version encoding. The pre-release byte is+-- ignored.+decodeLibrdkafkaVersion :: Int -> LibrdkafkaVersion+decodeLibrdkafkaVersion n =+ LibrdkafkaVersion+ { versionMajor = (n `shiftR` 24) .&. 0xff,+ versionMinor = (n `shiftR` 16) .&. 0xff,+ versionRevision = (n `shiftR` 8) .&. 0xff+ }
+ test-integration/Kafka/AdminTestSupport.hs view
@@ -0,0 +1,140 @@+{-# LANGUAGE ForeignFunctionInterface #-}++-- | Test executable instrumentation of real native admin ownership. No+-- production module or public API exposes these controls.+module Kafka.AdminTestSupport+ ( NativeKind (..),+ withNativeTracking,+ assertBalanced,+ counts,+ peak,+ failConfiguration,+ blockConfiguration,+ configurationEntered,+ withLeakControl,+ submissions,+ configurationCalls,+ lastConfiguration,+ rejectConfigurationAt,+ ResponseMode (..),+ responseMode,+ timeoutFault,+ timeoutReads,+ )+where++import Control.Exception (bracket, bracket_)+import Data.IORef (newIORef, readIORef, writeIORef)+import Foreign.C.String (CString, peekCString)+import Foreign.C.Types (CInt (..))+import Foreign.Ptr (Ptr, nullPtr)+import Test.Tasty.HUnit (assertBool, (@?=))++foreign import ccall unsafe "rdkafka_hs_test_admin_timeout_fault" setTimeoutFault :: CInt -> IO ()++foreign import ccall unsafe "rdkafka_hs_test_admin_timeout_reads" nativeTimeoutReads :: IO CInt++timeoutFault :: Int -> IO ()+timeoutFault = setTimeoutFault . fromIntegral++timeoutReads :: IO Int+timeoutReads = fromIntegral <$> nativeTimeoutReads++data ResponseMode = NativeResponse | WrongEvent | EmptyResult | WrongTopic | MissingPoll | DelayedResponse+ deriving stock (Enum, Show)++foreign import ccall unsafe "rdkafka_hs_test_admin_configuration_calls" configurationCallCount :: IO CInt++foreign import ccall unsafe "rdkafka_hs_test_admin_response_mode" setResponseMode :: CInt -> IO ()++foreign import ccall unsafe "rdkafka_hs_test_admin_last_key" lastKey :: IO CString++foreign import ccall unsafe "rdkafka_hs_test_admin_last_value" lastValue :: IO CString++lastConfiguration :: IO (String, String)+lastConfiguration = (,) <$> (lastKey >>= peekCString) <*> (lastValue >>= peekCString)++configurationCalls :: IO Int+configurationCalls = fromIntegral <$> configurationCallCount++rejectConfigurationAt :: Int -> IO ()+rejectConfigurationAt = failConfig . fromIntegral++responseMode :: ResponseMode -> IO ()+responseMode = setResponseMode . fromIntegral . fromEnum++data NativeKind = NativeNewTopic | NativeDeleteTopic | NativeQueue | NativeOptions | NativeEvent+ deriving stock (Enum, Bounded, Show)++foreign import ccall unsafe "rdkafka_hs_test_admin_submissions" submissionCount :: IO CInt++submissions :: IO Int+submissions = fromIntegral <$> submissionCount++foreign import ccall unsafe "rdkafka_hs_test_admin_begin" begin :: IO CInt++foreign import ccall unsafe "rdkafka_hs_test_admin_end" end :: IO ()++foreign import ccall unsafe "rdkafka_hs_test_admin_count" count :: CInt -> CInt -> IO CInt++foreign import ccall unsafe "rdkafka_hs_test_admin_fail_config" failConfig :: CInt -> IO ()++foreign import ccall unsafe "rdkafka_hs_test_admin_block_config" blockConfig :: CInt -> IO ()++foreign import ccall unsafe "rdkafka_hs_test_admin_config_entered" configEntered :: IO CInt++foreign import ccall unsafe "rdkafka_hs_test_admin_reject_control" rejectControl :: Ptr () -> IO CInt++foreign import ccall unsafe "rdkafka_hs_test_admin_positive_control" allocateControl :: IO (Ptr ())++foreign import ccall unsafe "rdkafka_hs_test_admin_release_control" releaseControl :: Ptr () -> IO ()++withNativeTracking :: IO a -> IO a+withNativeTracking = bracket_ (begin >>= (@?= 0)) end++counts :: NativeKind -> IO (Int, Int)+counts kind = do+ acquired <- count (fromIntegral (fromEnum kind)) 0+ released <- count (fromIntegral (fromEnum kind)) 1+ pure (fromIntegral acquired, fromIntegral released)++peak :: NativeKind -> IO Int+peak kind = fromIntegral <$> count (fromIntegral (fromEnum kind)) 3++assertBalanced :: IO ()+assertBalanced = mapM_ check [minBound .. maxBound]+ where+ check kind = do+ (allocated, released) <- counts kind+ assertBool (show kind <> " allocation/release imbalance: " <> show (allocated, released)) (allocated == released)++failConfiguration :: Bool -> IO ()+failConfiguration flag = failConfig (if flag then 1 else 0)++blockConfiguration :: Bool -> IO ()+blockConfiguration flag = blockConfig (if flag then 1 else 0)++configurationEntered :: IO Bool+configurationEntered = (/= 0) <$> configEntered++withLeakControl :: IO a -> IO a+withLeakControl action = do+ held <- newIORef Nothing+ let cleanup = failConfig 0 >> (readIORef held >>= mapM_ releaseControl)+ -- Reconstruct the inherited pattern: acquisition allocates a request,+ -- configuration rejects it, then acquisition returns Left. The outer+ -- bracket sees no handle to release. A separate control root allows the+ -- test to reclaim it after observing the missing release.+ oldAcquire = do+ pointer <- allocateControl+ assertBool "native positive control allocation failed" (pointer /= nullPtr)+ writeIORef held (Just pointer)+ failConfig 1+ rejectControl pointer >>= \code -> assertBool "native rejection control was ineffective" (code /= 0)+ pure (Left ())+ oldRelease (Left ()) = pure ()+ oldRelease (Right pointer) = releaseControl pointer+ bracket_ (pure ()) cleanup $ do+ bracket oldAcquire oldRelease (const (pure ()))+ failConfig 0+ action
+ test-integration/Kafka/CallbackLifetimeSupport.hs view
@@ -0,0 +1,28 @@+module Kafka.CallbackLifetimeSupport (withCallbackTracking, awaitCallbackStage, releaseCallbackStage, callbackStat, invalidAccessControl) where++import Control.Concurrent (threadDelay)+import Control.Exception (bracket_)+import Foreign.C.Types (CInt (..))+import System.Timeout (timeout)+import Test.Tasty.HUnit (assertFailure)++foreign import ccall unsafe "rdkafka_hs_test_callbacks_begin" begin :: CInt -> IO ()++foreign import ccall unsafe "rdkafka_hs_test_callbacks_end" end :: IO ()++foreign import ccall unsafe "rdkafka_hs_test_callbacks_release" releaseCallbackStage :: IO ()++foreign import ccall unsafe "rdkafka_hs_test_callbacks_stat" stat :: CInt -> IO CInt++foreign import ccall safe "rdkafka_hs_test_callbacks_invalid_access" invalidAccessControl :: IO CInt++withCallbackTracking :: Int -> IO a -> IO a+withCallbackTracking mode = bracket_ (begin (fromIntegral mode)) end++callbackStat :: Int -> IO Int+callbackStat index = fromIntegral <$> stat (fromIntegral index)++awaitCallbackStage :: IO ()+awaitCallbackStage = timeout 5000000 loop >>= maybe (assertFailure "native callback stage was not reached") pure+ where+ loop = callbackStat 0 >>= \n -> if n > 0 then pure () else threadDelay 1000 >> loop
+ test-integration/Kafka/CallbackTestSupport.hs view
@@ -0,0 +1,56 @@+-- | Weak-reference controls for callback ownership tests. Keeping the Weak+-- value does not retain its key. Callers must create captured values in a+-- separate NOINLINE function so their own stack cannot retain the key.+module Kafka.CallbackTestSupport (awaitCollected, assertRetained, runChildProbe) where++import Control.Concurrent (threadDelay)+import System.Directory (createDirectoryIfMissing)+import System.Environment (getEnvironment, getExecutablePath, lookupEnv)+import System.Exit (ExitCode (ExitSuccess))+import System.Mem (performMajorGC)+import System.Mem.Weak (Weak, deRefWeak)+import System.Process (CreateProcess (env), proc, readCreateProcessWithExitCode)+import System.Random (randomIO)+import System.Timeout (timeout)+import Test.Tasty.HUnit (assertFailure)++-- Isolate foreign-boundary probes and runtime exception handlers. Keep child+-- coverage separate and let the collector merge each successful child.+runChildProbe :: String -> [String] -> IO ()+runChildProbe prefix arguments = do+ executable <- getExecutablePath+ environment <- getEnvironment+ directory <- maybe "dist-callback-probes" id <$> lookupEnv "RDKAFKA_TEST_CHILD_HPC_DIR"+ createDirectoryIfMissing True directory+ nonce <- randomIO :: IO Word+ let output = directory <> "/" <> prefix <> "-" <> show nonce <> ".tix"+ process =+ (proc executable (arguments <> ["+RTS", "--read-tix-file=no", "-RTS"]))+ { env = Just (("HPCTIXFILE", output) : filter ((/= "HPCTIXFILE") . fst) environment)+ }+ result <- timeout 15000000 (readCreateProcessWithExitCode process "")+ case result of+ Just (ExitSuccess, _, _) -> pure ()+ other -> assertFailure ("native callback child failed: " <> show other)++awaitCollected :: Weak a -> IO ()+awaitCollected weak = go (100 :: Int)+ where+ go 0 = assertFailure "callback capture remained reachable after release"+ go retries = do+ performMajorGC+ dead <- isDead weak+ if dead then pure () else threadDelay 10000 >> go (retries - 1)++assertRetained :: Weak a -> IO ()+assertRetained weak = do+ performMajorGC+ dead <- isDead weak+ if dead then assertFailure "callback capture collected while still needed" else pure ()++{-# NOINLINE isDead #-}+isDead :: Weak a -> IO Bool+isDead weak =+ deRefWeak weak >>= \case+ Nothing -> pure True+ Just _ -> pure False
+ test-integration/Kafka/Compatibility/KafkaFixture.hs view
@@ -0,0 +1,252 @@+-- | Disposable Apache processes owned by this test run. The explicit+-- qualification entry point requires a released Kafka distribution and Java.+module Kafka.Compatibility.KafkaFixture+ ( KafkaFixture,+ createKafkaFixture,+ SecureExtension (..),+ createSecureKafkaFixture,+ destroyKafkaFixture,+ fixtureEnv,+ fixtureRoot,+ fixtureCommand,+ ownedCommand,+ stopBroker,+ startBroker,+ awaitBrokers,+ fixtureAllStopped,+ withBrokersStopped,+ )+where++import Control.Concurrent (threadDelay)+import Control.Concurrent.MVar+import Control.Exception (SomeException, bracket, bracketOnError, bracket_, mask, mask_, onException, throwIO, try)+import Control.Monad (forM, forM_, unless, void)+import Data.IORef+import Data.List (intercalate, sort)+import Data.Text qualified as T+import Kafka.Metadata qualified as D+import Kafka.Producer qualified as P+import Kafka.TestEnv+import Kafka.Types+import Network.Socket qualified as N+import System.Directory+import System.Environment (getEnvironment, lookupEnv)+import System.Exit (ExitCode (..))+import System.IO+import System.Posix.Files (setFileMode)+import System.Posix.Signals (sigKILL, signalProcess)+import System.Process+import System.Timeout (timeout)+import Test.Tasty.HUnit (assertFailure)++data Node = Node Int Int FilePath (MVar (Maybe ProcessHandle))++data KafkaFixture = KafkaFixture+ { fixtureEnv :: TestEnv,+ fixtureRoot :: FilePath,+ kafkaHome :: FilePath,+ fixtureNodes :: [Node],+ healthEnv :: TestEnv,+ secureExtension :: Maybe SecureExtension+ }++-- Security owns credentials and policy; this runner owns every process and port.+data SecureExtension = SecureExtension+ { securePrepare :: FilePath -> IO (),+ secureConfiguration :: FilePath -> Int -> Int -> Int -> IO [String],+ secureEnvironment :: FilePath -> [(String, String)],+ secureCleanup :: FilePath -> IO ()+ }++bounded :: Int -> String -> IO a -> IO a+bounded seconds label action = timeout (seconds * 1000000) action >>= maybe (assertFailure label) pure++-- This function can terminate only a ProcessHandle returned by createProcess.+-- It never resolves a machine-global broker or reads an externally supplied PID.+stopProcess :: ProcessHandle -> IO ()+stopProcess process =+ getProcessExitCode process >>= \case+ Just _ -> pure ()+ Nothing -> do+ terminateProcess process+ timeout 15000000 (waitForProcess process) >>= \case+ Just _ -> pure ()+ Nothing -> do+ getPid process >>= mapM_ (signalProcess sigKILL)+ void (bounded 5 "owned Kafka process did not exit after SIGKILL" (waitForProcess process))++fixtureCommand :: KafkaFixture -> String -> [String] -> IO String+fixtureCommand fixture command = ownedCommand (fixtureRoot fixture) (kafkaHome fixture <> "/bin/" <> command <> ".sh")++ownedCommand :: FilePath -> FilePath -> [String] -> IO String+ownedCommand root command args = mask $ \restore -> do+ (outputPath, outputHandle) <- openTempFile root "command-out-"+ (_, errorHandle) <- openTempFile root "command-err-" `onException` hClose outputHandle+ -- createProcess closes the parent's UseHandle copies after duplicating them.+ (_, _, _, process) <-+ createProcess+ (proc command args)+ { std_in = NoStream,+ std_out = UseHandle outputHandle,+ std_err = UseHandle errorHandle+ }+ `onException` (hClose outputHandle >> hClose errorHandle)+ code <- restore (bounded 45 (command <> " timed out") (waitForProcess process)) `onException` stopProcess process+ output <- readFile outputPath+ case code of+ ExitSuccess -> pure output+ _ -> assertFailure ("owned fixture command failed: " <> show (command, code) <> "; private output retained for sanitized inspection")++createKafkaFixture :: IO KafkaFixture+createKafkaFixture = createFixture 3 Nothing++createSecureKafkaFixture :: SecureExtension -> IO KafkaFixture+createSecureKafkaFixture = createFixture 1 . Just++createFixture :: Int -> Maybe SecureExtension -> IO KafkaFixture+createFixture count extension = do+ home <- lookupEnv "RDKAFKA_TEST_KAFKA_HOME" >>= maybe (assertFailure "set RDKAFKA_TEST_KAFKA_HOME to a released Apache Kafka distribution") pure+ forM_ ["kafka-storage", "kafka-server-start", "kafka-topics", "kafka-configs"] $ \name ->+ doesFileExist (home <> "/bin/" <> name <> ".sh") >>= \found -> unless found (assertFailure ("missing Kafka fixture command: " <> name))+ createDirectoryIfMissing True "dist-compatibility/kafka-fixtures"+ (root, handle) <- openTempFile "dist-compatibility/kafka-fixtures" "owned-"+ hClose handle+ removeFile root+ createDirectory root+ setFileMode root 0o700+ writeFile (root <> "/owned-by-rdkafka-hs") "run-owned Apache qualification fixture\n"+ -- Bind all ports while preparing the files. The default primary and+ -- global brokers cannot be selected: occupied ports never bind successfully.+ bracket (reserveAll (3 * count) >>= newIORef) releasePorts $ \reservations -> do+ reserved <- readIORef reservations+ let ports = map snd reserved+ brokerPorts = take count ports+ controllerPorts = take count (drop count ports)+ internalPorts = drop (2 * count) ports+ hostname = maybe "127.0.0.1:" (const "localhost:") extension+ addresses = [BrokerAddress (hostname <> T.pack (show port)) | port <- brokerPorts]+ environment <- newTestEnv addresses+ health <- maybe (pure environment) (const (newTestEnv [BrokerAddress ("127.0.0.1:" <> T.pack (show port)) | port <- internalPorts])) extension+ nodes <- forM (zip [1 ..] brokerPorts) $ \(node, port) -> Node node port (root <> "/node-" <> show node <> ".properties") <$> newMVar Nothing+ let fixture = KafkaFixture environment root home nodes health extension+ voters = intercalate "," [show node <> "@127.0.0.1:" <> show port | (node, port) <- zip [1 .. count] controllerPorts]+ flip onException (destroyKafkaFixture fixture) $ do+ mapM_ (\security -> securePrepare security root) extension+ cluster <- filter (`notElem` ['\r', '\n']) <$> fixtureCommand fixture "kafka-storage" ["random-uuid"]+ forM_ (zip3 nodes controllerPorts internalPorts) $ \(Node node port config _, controller, internal) -> do+ additional <- maybe (pure []) (\security -> secureConfiguration security root port controller internal) extension+ writeFile config $+ unlines $+ [ "process.roles=broker,controller",+ "node.id=" <> show node,+ "controller.quorum.voters=" <> voters,+ "listeners=PLAINTEXT://127.0.0.1:" <> show port <> ",CONTROLLER://127.0.0.1:" <> show controller,+ "advertised.listeners=PLAINTEXT://127.0.0.1:" <> show port <> ",CONTROLLER://127.0.0.1:" <> show controller,+ "inter.broker.listener.name=PLAINTEXT",+ "controller.listener.names=CONTROLLER",+ "listener.security.protocol.map=CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT",+ "log.dirs=" <> root <> "/node-" <> show node <> "-data",+ "default.replication.factor=" <> show count,+ "min.insync.replicas=1",+ "num.partitions=1",+ "offsets.topic.replication.factor=" <> show count,+ "offsets.topic.num.partitions=3",+ "transaction.state.log.replication.factor=" <> show count,+ "transaction.state.log.min.isr=" <> show (min 2 count),+ "transaction.state.log.num.partitions=3",+ "group.initial.rebalance.delay.ms=0",+ "auto.create.topics.enable=false",+ "num.network.threads=2",+ "num.io.threads=2",+ "num.replica.fetchers=1"+ ]+ <> additional+ setFileMode config 0o600+ void (fixtureCommand fixture "kafka-storage" ["format", "-t", cluster, "-c", config])+ -- Transfer the sockets out of the cleanup reference exactly once before+ -- Java binds. Partial acquisition and cancellation retain cleanup.+ releasePorts reservations+ mapM_ (startNode fixture) nodes+ awaitBrokers fixture+ version <- fixtureCommand fixture "kafka-topics" ["--version"]+ writeFile (root <> "/version.txt") version+ putStrLn ("[owned-kafka] root=" <> root <> " brokers=" <> show addresses <> " version=" <> version)+ pure fixture+ where+ releasePorts reference = atomicModifyIORef' reference (\sockets -> ([], sockets)) >>= mapM_ (N.close . fst)+ reserveAll 0 = pure []+ reserveAll remaining = bracketOnError reservePort (N.close . fst) $ \socket -> (socket :) <$> reserveAll (remaining - 1)+ reservePort = do+ socket <- N.socket N.AF_INET N.Stream N.defaultProtocol+ flip onException (N.close socket) $ do+ N.bind socket (N.SockAddrInet 0 (N.tupleToHostAddress (127, 0, 0, 1)))+ port <- fromIntegral <$> N.socketPort socket+ whenForbidden port+ pure (socket, port)+ whenForbidden port = unless (port `notElem` [9092, 39092, 39644]) (assertFailure "reserved a protected broker port")++startNode :: KafkaFixture -> Node -> IO ()+startNode fixture (Node node _ config state) = mask_ $ modifyMVar_ state $ \case+ Just _ -> assertFailure "owned broker is already running"+ Nothing -> do+ variables <- getEnvironment+ let extra = [("KAFKA_HEAP_OPTS", "-Xms256m -Xmx384m"), ("LOG_DIR", fixtureRoot fixture <> "/node-" <> show node <> "-logs")] <> maybe [] (\security -> secureEnvironment security (fixtureRoot fixture)) (secureExtension fixture)+ logHandle <- openFile (fixtureRoot fixture <> "/node-" <> show node <> ".stdout.log") AppendMode+ (_, _, _, process) <-+ createProcess+ (proc (kafkaHome fixture <> "/bin/kafka-server-start.sh") [config])+ { env = Just (extra <> filter (\(key, _) -> key `notElem` map fst extra) variables),+ std_in = NoStream,+ std_out = UseHandle logHandle,+ std_err = UseHandle logHandle+ }+ `onException` hClose logHandle+ pure (Just process)++stopNode :: Node -> IO ()+stopNode (Node _ _ _ state) = modifyMVar_ state $ \process -> mapM_ stopProcess process >> pure Nothing++findNode :: KafkaFixture -> BrokerId -> IO Node+findNode fixture (BrokerId wanted) = case [node | node@(Node identifier _ _ _) <- fixtureNodes fixture, identifier == wanted] of+ [node] -> pure node+ _ -> assertFailure "broker ID is outside this run-owned topology"++stopBroker :: KafkaFixture -> BrokerId -> IO ()+stopBroker fixture broker = findNode fixture broker >>= stopNode++startBroker :: KafkaFixture -> BrokerId -> IO ()+startBroker fixture broker = findNode fixture broker >>= startNode fixture++awaitBrokers :: KafkaFixture -> IO ()+awaitBrokers fixture = bracket (P.newProducer (P.brokersList (teBrokers (healthEnv fixture)) <> P.extraProp "log_level" "0") >>= either throwIO pure) releaseProducer $ \producer ->+ bounded 45 "owned Apache brokers did not become reachable" $+ let await =+ D.allTopicsMetadata producer (Timeout 1000) >>= \case+ Right metadata | sort (map D.bmBrokerId (D.kmBrokers metadata)) == [BrokerId node | Node node _ _ _ <- fixtureNodes fixture] -> pure ()+ _ -> threadDelay 100000 >> await+ in await++destroyKafkaFixture :: KafkaFixture -> IO ()+destroyKafkaFixture fixture = do+ -- Cleanup is installed before any process starts, including partial setup.+ results <- mapM (try @SomeException . stopNode) (fixtureNodes fixture)+ case [exception | Left exception <- results] of+ exception : _ -> throwIO exception+ [] -> pure ()+ mapM_ (\security -> secureCleanup security (fixtureRoot fixture)) (secureExtension fixture)+ forM_ (fixtureNodes fixture) $ \(Node node _ _ _) -> do+ let dataDirectory = fixtureRoot fixture <> "/node-" <> show node <> "-data"+ exists <- doesDirectoryExist dataDirectory+ if exists then removeDirectoryRecursive dataDirectory else pure ()+ writeFile (fixtureRoot fixture <> "/cleanup.txt") "All owned process handles exited; owned broker data removed.\n"++fixtureAllStopped :: KafkaFixture -> IO Bool+fixtureAllStopped fixture = and <$> mapM stopped (fixtureNodes fixture)+ where+ stopped (Node _ _ _ state) = readMVar state >>= maybe (pure True) (fmap (/= Nothing) . getProcessExitCode)++-- Install restoration for each successfully stopped process before stopping+-- the next. Start all controllers before the caller waits for quorum health.+withBrokersStopped :: KafkaFixture -> IO a -> IO a+withBrokersStopped fixture action = foldr (\node next -> bracket_ (stopNode node) (startNode fixture node) next) action (fixtureNodes fixture)
+ test-integration/Kafka/Compatibility/SecurityFixture.hs view
@@ -0,0 +1,164 @@+module Kafka.Compatibility.SecurityFixture+ ( SecurityFixture,+ createSecurityFixture,+ destroySecurityFixture,+ securityKafka,+ securitySettings,+ securityTopic,+ withSecurityCredentials,+ assertGroupAuthorizationDenied,+ )+where++import Control.Exception (onException)+import Control.Monad (forM_, unless, void, when)+import Data.List (isInfixOf, isPrefixOf)+import Data.Map.Strict qualified as M+import Data.Text qualified as T+import Data.Text.IO qualified as T+import Kafka.Compatibility.KafkaFixture+import Kafka.TestEnv+import Kafka.Types+import System.Directory+import System.Posix.Files (setFileMode)+import Test.Tasty.HUnit (assertFailure)++-- No Show instance: passwords must never appear in assertion diagnostics.+data SecurityFixture = SecurityFixture+ { securityKafka :: KafkaFixture,+ identityPasswords :: M.Map String String+ }++labels :: [String]+labels = ["admin", "writer", "reader", "denied", "writer2", "reader2"]++username :: String -> String+username label = "fixture_" <> label++secret :: FilePath -> FilePath -> FilePath+secret root name = root <> "/secret/" <> name++readPassword :: FilePath -> String -> IO String+readPassword root label = T.unpack . T.strip <$> T.readFile (secret root (label <> ".password"))++prepare :: FilePath -> IO ()+prepare root = do+ createDirectory (root <> "/secret")+ setFileMode (root <> "/secret") 0o700+ forM_ ("tls" : labels) $ \label -> do+ void (ownedCommand root "openssl" ["rand", "-hex", "-out", secret root (label <> ".password"), "24"])+ setFileMode (secret root (label <> ".password")) 0o600+ let ssl = void . ownedCommand root "openssl"+ ssl ["req", "-x509", "-newkey", "rsa:2048", "-noenc", "-keyout", secret root "ca.key", "-out", secret root "ca.pem", "-days", "1", "-subj", "/CN=rdkafka-hs-fixture-ca"]+ ssl ["req", "-new", "-newkey", "rsa:2048", "-noenc", "-keyout", secret root "server.key", "-out", secret root "server.csr", "-subj", "/CN=localhost"]+ writeFile (secret root "server.ext") "subjectAltName=DNS:localhost\nextendedKeyUsage=serverAuth\n"+ ssl ["x509", "-req", "-in", secret root "server.csr", "-CA", secret root "ca.pem", "-CAkey", secret root "ca.key", "-CAcreateserial", "-out", secret root "server.pem", "-days", "1", "-extfile", secret root "server.ext"]+ ssl ["pkcs12", "-export", "-in", secret root "server.pem", "-inkey", secret root "server.key", "-certfile", secret root "ca.pem", "-out", secret root "server.p12", "-passout", "file:" <> secret root "tls.password"]+ listDirectory (root <> "/secret") >>= mapM_ (\name -> setFileMode (secret root name) 0o600)+ writeFile (root <> "/log4j2.xml") "<Configuration status=\"WARN\"><Appenders><Console name=\"Console\" target=\"SYSTEM_OUT\"><PatternLayout pattern=\"%d %p %c %m%n\"/></Console></Appenders><Loggers><Logger name=\"kafka.authorizer.logger\" level=\"DEBUG\" additivity=\"false\"><AppenderRef ref=\"Console\"/></Logger><Root level=\"WARN\"><AppenderRef ref=\"Console\"/></Root></Loggers></Configuration>"++configuration :: FilePath -> Int -> Int -> Int -> IO [String]+configuration root port controller internal = do+ passwords <- mapM (readPassword root) labels+ adminPassword <- readPassword root "admin"+ tlsPassword <- readPassword root "tls"+ let login = "org.apache.kafka.common.security.plain.PlainLoginModule required username=\"" <> username "admin" <> "\" password=\"" <> adminPassword <> "\" " <> unwords ["user_" <> username label <> "=\"" <> password <> "\"" | (label, password) <- zip labels passwords] <> ";"+ writeFile (secret root "admin.properties") $+ unlines+ [ "security.protocol=SASL_SSL",+ "sasl.mechanism=PLAIN",+ "sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule required username=\"" <> username "admin" <> "\" password=\"" <> adminPassword <> "\";",+ "ssl.truststore.type=PEM",+ "ssl.truststore.location=" <> secret root "ca.pem",+ "ssl.endpoint.identification.algorithm=https"+ ]+ setFileMode (secret root "admin.properties") 0o600+ pure+ [ "listeners=SASL_SSL://127.0.0.1:" <> show port <> ",INTERNAL://127.0.0.1:" <> show internal <> ",CONTROLLER://127.0.0.1:" <> show controller,+ "advertised.listeners=SASL_SSL://localhost:" <> show port <> ",INTERNAL://127.0.0.1:" <> show internal <> ",CONTROLLER://127.0.0.1:" <> show controller,+ "listener.security.protocol.map=CONTROLLER:PLAINTEXT,INTERNAL:PLAINTEXT,SASL_SSL:SASL_SSL",+ "inter.broker.listener.name=INTERNAL",+ "sasl.enabled.mechanisms=PLAIN",+ "listener.name.sasl_ssl.plain.sasl.jaas.config=" <> login,+ "ssl.keystore.type=PKCS12",+ "ssl.keystore.location=" <> secret root "server.p12",+ "ssl.keystore.password=" <> tlsPassword,+ "ssl.key.password=" <> tlsPassword,+ "ssl.client.auth=none",+ "authorizer.class.name=org.apache.kafka.metadata.authorizer.StandardAuthorizer",+ "super.users=User:ANONYMOUS;User:" <> username "admin",+ "allow.everyone.if.no.acl.found=false"+ ]++-- Stop all Java processes first, remove credentials/configuration, then inspect+-- retained logs. Even a failed setup enters this cleanup through the runner.+cleanup :: FilePath -> IO ()+cleanup root = do+ present <- doesDirectoryExist (root <> "/secret")+ passwords <- if present then mapM (\label -> doesFileExist (secret root (label <> ".password")) >>= \exists -> if exists then readPassword root label else pure "") ("tls" : labels) else pure []+ names <- listDirectory root+ forM_ names $ \name -> when ("node-" `isPrefixOf` name && ".properties" `isInfixOf` name || "command-" `isPrefixOf` name) (removeFile (root <> "/" <> name))+ when present (removeDirectoryRecursive (root <> "/secret"))+ -- No binary broker data is inspected; only owned, textual log files.+ let inspect path = do+ text <- T.unpack <$> T.readFile path+ let leaked = any (\password -> not (null password) && password `isInfixOf` text) passwords+ when leaked (writeFile path "Credential-bearing diagnostic removed by fixture cleanup.\n")+ pure leaked+ logs directory =+ listDirectory directory+ >>= fmap concat+ . mapM+ ( \name -> do+ let path = directory <> "/" <> name+ dir <- doesDirectoryExist path+ if dir then if "-data" `isInfixOf` name then pure [] else logs path else if ".log" `isInfixOf` name then pure [path] else pure []+ )+ leaked <- logs root >>= mapM inspect+ writeFile (root <> "/security-cleanup.txt") "Owned credential files and JAAS configurations removed; owned log files checked for ephemeral passwords.\n"+ unless (not (or leaked)) (assertFailure "ephemeral credential appeared in an owned log; diagnostic removed")++createSecurityFixture :: IO SecurityFixture+createSecurityFixture = do+ kafka <- createSecureKafkaFixture (SecureExtension prepare configuration (\root -> [("KAFKA_LOG4J_OPTS", "-Dlog4j2.configurationFile=" <> root <> "/log4j2.xml")]) cleanup)+ flip onException (destroyKafkaFixture kafka) $ do+ passwords <- M.fromList <$> mapM (\label -> (label,) <$> readPassword (fixtureRoot kafka) label) labels+ let fixture = SecurityFixture kafka passwords+ environment = fixtureEnv kafka+ common = ["--bootstrap-server", T.unpack (T.intercalate "," (map unBrokerAddress (teBrokers environment))), "--command-config", secret (fixtureRoot kafka) "admin.properties"]+ cli command args = void (fixtureCommand kafka command (common <> args))+ forM_ ["primary", "replacement"] $ \suffix -> do+ let TopicName topic = securityTopic fixture suffix+ cli "kafka-topics" ["--create", "--topic", T.unpack topic, "--partitions", "1", "--replication-factor", "1"]+ forM_ [(if suffix == "primary" then "writer" else "writer2", ["Write", "Describe"]), (if suffix == "primary" then "reader" else "reader2", ["Read", "Describe"]), ("denied", ["Describe"])] $ \(label, operations) ->+ cli "kafka-acls" (["--add", "--allow-principal", "User:" <> username label, "--topic", T.unpack topic] <> concatMap (\operation -> ["--operation", operation]) operations)+ forM_ ["reader", "reader2", "denied"] $ \label ->+ cli "kafka-acls" ["--add", "--allow-principal", "User:" <> username label, "--operation", "Read", "--group", T.unpack (prefixedName environment "security-"), "--resource-pattern-type", "prefixed"]+ pure fixture++destroySecurityFixture :: SecurityFixture -> IO ()+destroySecurityFixture = destroyKafkaFixture . securityKafka++securitySettings :: SecurityFixture -> String -> M.Map T.Text T.Text+securitySettings fixture label =+ M.fromList+ [ ("security.protocol", "SASL_SSL"),+ ("sasl.mechanisms", "PLAIN"),+ ("sasl.username", T.pack (username label)),+ ("sasl.password", T.pack (identityPasswords fixture M.! label)),+ ("ssl.ca.location", T.pack (secret (fixtureRoot (securityKafka fixture)) "ca.pem")),+ ("ssl.endpoint.identification.algorithm", "https"),+ ("log_level", "0")+ ]++securityTopic :: SecurityFixture -> T.Text -> TopicName+securityTopic fixture suffix = TopicName (prefixedName (fixtureEnv (securityKafka fixture)) ("security-" <> suffix))++withSecurityCredentials :: SecurityFixture -> String -> (T.Text -> T.Text -> IO a) -> IO a+withSecurityCredentials fixture label action = action (T.pack (username label)) (T.pack (identityPasswords fixture M.! label))++assertGroupAuthorizationDenied :: SecurityFixture -> String -> T.Text -> IO ()+assertGroupAuthorizationDenied fixture label group = do+ output <- T.readFile (fixtureRoot (securityKafka fixture) <> "/node-1.stdout.log")+ let denied line = ("Principal = User:" <> T.pack (username label) <> " is Denied operation = DESCRIBE") `T.isInfixOf` line && ("on resource = Group:LITERAL:" <> group <> " for request = FindCoordinator") `T.isInfixOf` line+ unless (any denied (T.lines output)) (assertFailure "broker did not audit the exact denied group-coordinator request")
+ test-integration/Kafka/ConsumerStateSupport.hs view
@@ -0,0 +1,63 @@+module Kafka.ConsumerStateSupport (withStateFault, endStateFault, stateStat, triggerRebalance, triggerCooperative, stateLeakControl, commitObservation, withQueueTracking, queueEventStat, awaitQueuedRecord) where++import Control.Concurrent (threadDelay)+import Control.Exception (bracket_)+import Data.Text qualified as Text+import Foreign.C.String (CString, withCString)+import Foreign.C.Types (CInt (..))+import Kafka.Types (TopicName (..))+import System.Timeout (timeout)+import Test.Tasty.HUnit (assertFailure)++foreign import ccall unsafe "rdkafka_hs_test_state_begin" begin :: CInt -> IO ()++foreign import ccall unsafe "rdkafka_hs_test_state_end" endStateFault :: IO ()++foreign import ccall unsafe "rdkafka_hs_test_state_stat" stat :: CInt -> IO CInt++foreign import ccall safe "rdkafka_hs_test_state_trigger" trigger :: CString -> IO ()++foreign import ccall safe "rdkafka_hs_test_state_trigger_cooperative" triggerCooperativeNative :: CString -> CInt -> IO ()++triggerCooperative :: TopicName -> Bool -> IO ()+triggerCooperative (TopicName topic) revoke = withCString (Text.unpack topic) (\name -> triggerCooperativeNative name (if revoke then 1 else 0))++foreign import ccall unsafe "rdkafka_hs_test_state_leak_control" stateLeakControl :: IO ()++withStateFault :: Int -> IO a -> IO a+withStateFault mode = bracket_ (begin (fromIntegral mode)) endStateFault++stateStat :: Int -> IO Int+stateStat index = fromIntegral <$> stat (fromIntegral index)++triggerRebalance :: TopicName -> IO ()+triggerRebalance (TopicName topic) = withCString (Text.unpack topic) trigger++foreign import ccall unsafe "rdkafka_hs_test_state_commit_count" commitCount :: IO CInt++foreign import ccall unsafe "rdkafka_hs_test_state_commit_async" commitAsync :: IO CInt++commitObservation :: IO (Int, Int)+commitObservation = (,) <$> (fromIntegral <$> commitCount) <*> (fromIntegral <$> commitAsync)++foreign import ccall unsafe "rdkafka_hs_test_queue_begin" beginQueue :: IO ()++foreign import ccall unsafe "rdkafka_hs_test_queue_end" endQueue :: IO ()++foreign import ccall unsafe "rdkafka_hs_test_queue_stat" statQueue :: CInt -> IO CInt++withQueueTracking :: IO a -> IO a+withQueueTracking = bracket_ beginQueue endQueue++queueEventStat :: Int -> IO Int+queueEventStat index = fromIntegral <$> statQueue (fromIntegral index)++awaitQueuedRecord :: IO () -> IO ()+awaitQueuedRecord refresh = timeout 10000000 loop >>= maybe (assertFailure "record was not queued before enabling notification") pure+ where+ loop = do+ refresh+ count <- queueEventStat 1+ if count < 0+ then assertFailure "notification destination queue was not observed"+ else if count > 0 then pure () else threadDelay 1000 >> loop
+ test-integration/Kafka/DiagnosticTestSupport.hs view
@@ -0,0 +1,30 @@+module Kafka.DiagnosticTestSupport (withDiagnosticFault, diagnosticStat, diagnosticLeakControl, awaitDiagnosticBoundary, releaseDiagnosticBoundary) where++import Control.Concurrent (threadDelay)+import Control.Exception (bracket_)+import Foreign.C.Types (CInt (..))+import System.Timeout (timeout)+import Test.Tasty.HUnit (assertFailure)++foreign import ccall unsafe "rdkafka_hs_test_diagnostic_leak_control" diagnosticLeakControl :: IO ()++foreign import ccall unsafe "rdkafka_hs_test_diagnostic_begin" begin :: CInt -> IO ()++foreign import ccall unsafe "rdkafka_hs_test_diagnostic_end" end :: IO ()++foreign import ccall unsafe "rdkafka_hs_test_diagnostic_stat" stat :: CInt -> IO CInt++foreign import ccall unsafe "rdkafka_hs_test_diagnostic_entered" entered :: IO CInt++foreign import ccall unsafe "rdkafka_hs_test_diagnostic_release" releaseDiagnosticBoundary :: IO ()++withDiagnosticFault :: Int -> IO a -> IO a+withDiagnosticFault mode = bracket_ (begin (fromIntegral mode)) end++diagnosticStat :: Int -> IO Int+diagnosticStat index = fromIntegral <$> stat (fromIntegral index)++awaitDiagnosticBoundary :: IO ()+awaitDiagnosticBoundary = timeout 5000000 loop >>= maybe (assertFailure "native dump boundary was not reached") pure+ where+ loop = entered >>= \n -> if n == 1 then pure () else threadDelay 1000 >> loop
+ test-integration/Kafka/FaultTestSupport.hs view
@@ -0,0 +1,50 @@+-- | Observed thread-stage barriers, with bounded waits. A caller signals+-- arrival at the stage and waits until the controlling test releases it.+module Kafka.FaultTestSupport (Barrier, newBarrier, reachBarrier, awaitBarrier, releaseBarrier, withUnresponsiveBroker) where++import Control.Concurrent (forkIO, killThread)+import Control.Concurrent.MVar (MVar, modifyMVar_, newEmptyMVar, newMVar, putMVar, readMVar, tryPutMVar)+import Control.Exception (bracket, mask_)+import Control.Monad (forever, void)+import Data.Text qualified as Text+import Kafka.Types (BrokerAddress (..))+import Network.Socket qualified as N+import System.Timeout (timeout)+import Test.Tasty.HUnit (assertFailure)++data Barrier = Barrier (MVar ()) (MVar ())++newBarrier :: IO Barrier+newBarrier = Barrier <$> newEmptyMVar <*> newEmptyMVar++reachBarrier :: Barrier -> IO ()+reachBarrier (Barrier reached resume) = putMVar reached () >> bounded (readMVar resume)++awaitBarrier :: Barrier -> IO ()+awaitBarrier (Barrier reached _) = bounded (readMVar reached)++releaseBarrier :: Barrier -> IO ()+releaseBarrier (Barrier _ resume) = putMVar resume ()++bounded :: IO a -> IO a+bounded action = timeout 5000000 action >>= maybe (assertFailure "thread stage barrier timed out") pure++-- | A run-owned loopback endpoint that accepts connections but never replies+-- to Kafka requests. The listener and every accepted socket close on exit.+withUnresponsiveBroker :: (BrokerAddress -> IO () -> IO a) -> IO a+withUnresponsiveBroker action =+ bracket (N.socket N.AF_INET N.Stream N.defaultProtocol) N.close $ \listener -> do+ N.bind listener (N.SockAddrInet 0 (N.tupleToHostAddress (127, 0, 0, 1)))+ N.listen listener 16+ port <- N.socketPort listener+ connections <- newMVar []+ connected <- newEmptyMVar+ let acceptLoop = forever $ mask_ $ do+ (socket, _) <- N.accept listener+ modifyMVar_ connections (pure . (socket :))+ void (tryPutMVar connected ())+ stop thread = do+ killThread thread+ modifyMVar_ connections (\sockets -> mapM_ N.close sockets >> pure [])+ bracket (forkIO acceptLoop) stop $ \_ ->+ action (BrokerAddress ("127.0.0.1:" <> Text.pack (show port))) (bounded (readMVar connected))
+ test-integration/Kafka/FixtureSupport.hs view
@@ -0,0 +1,84 @@+-- | Test-only algorithms with injectable operations. Production fixtures and+-- harness self-tests use the same error policy and deadline handling.+module Kafka.FixtureSupport+ ( collectExactly,+ sendAndConfirm,+ acquirePair,+ )+where++import Control.Concurrent.MVar (newEmptyMVar, putMVar, takeMVar)+import Control.Exception (bracketOnError)+import Data.Word (Word64)+import GHC.Clock (getMonotonicTimeNSec)+import Kafka.Producer++import System.Timeout (timeout)++-- | Only timeouts/EOF are idle. After the requested count, require an idle+-- poll so an unexpected extra record cannot be hidden by truncation.+collectExactly :: IO Word64 -> Word64 -> Int -> IO (Either KafkaError a) -> IO (Either KafkaError [a])+collectExactly clock budget count poll+ | count < 0 = pure (Left (KafkaError "negative expected record count"))+ | otherwise = do+ deadline <- (+ budget) <$> clock+ let go acc = do+ now <- clock+ if now >= deadline+ then pure (Left (KafkaError "record deadline expired before exact count and idle poll"))+ else+ poll >>= \case+ Right record+ | length acc == count -> pure (Left (KafkaError "unexpected extra record"))+ | otherwise -> go (record : acc)+ Left err+ | idle err && length acc == count -> pure (Right (reverse acc))+ | idle err -> go acc+ | otherwise -> pure (Left err)+ go []+ where+ idle (KafkaResponseError RdKafkaRespErrTimedOut) = True+ idle (KafkaResponseError RdKafkaRespErrPartitionEof) = True+ idle _ = False++-- | Immediate rejection, delivery failure, missing callback, and failed flush+-- are distinct failures. One monotonic budget bounds the entire operation.+sendAndConfirm :: Int -> (ProducerRecord -> (DeliveryReport -> IO ()) -> IO (Either ImmediateError ())) -> (Timeout -> IO (Maybe KafkaError)) -> [ProducerRecord] -> IO (Either KafkaError ())+sendAndConfirm budget enqueue flush records = do+ deadline <- (+ fromIntegral budget * 1000) <$> getMonotonicTimeNSec+ let remaining = do+ now <- getMonotonicTimeNSec+ pure (if now >= deadline then 0 else fromIntegral ((deadline - now) `div` 1000))+ bounded action = remaining >>= \n -> if n <= 0 then pure Nothing else timeout n action+ go [] = pure (Right ())+ go (record : rest) = do+ report <- newEmptyMVar+ enqueue record (putMVar report) >>= \case+ Left (ImmediateError err) -> pure (Left err)+ Right () -> do+ micros <- remaining+ flush (Timeout (max 1 (micros `div` 1000))) >>= \case+ Just err -> pure (Left err)+ Nothing ->+ bounded (takeMVar report) >>= \case+ Nothing -> pure (Left (KafkaError "delivery callback deadline expired"))+ Just (DeliverySuccess actual _)+ | sameRecord record actual -> go rest+ | otherwise -> pure (Left (KafkaError "delivery report does not match enqueued record"))+ Just (DeliveryFailure _ err) -> pure (Left err)+ Just (NoMessageError err) -> pure (Left err)+ go records+ where+ sameRecord expected actual =+ prTopic expected == prTopic actual+ && prKey expected == prKey actual+ && prValue expected == prValue actual+ && prHeaders expected == prHeaders actual+ && case prPartition expected of+ UnassignedPartition -> True+ partition -> partition == prPartition actual++-- | Release the first resource when constructing the second fails, including+-- asynchronous exceptions. Successful pairs are released by the caller.+acquirePair :: IO a -> (a -> IO ()) -> IO b -> IO (a, b)+acquirePair first release second = bracketOnError first release $ \a -> (a,) <$> second
+ test-integration/Kafka/FixtureSupportTest.hs view
@@ -0,0 +1,99 @@+module Kafka.FixtureSupportTest (tests) where++import Control.Concurrent (forkFinally, killThread)+import Control.Concurrent.MVar (newEmptyMVar, putMVar, takeMVar)+import Control.Exception (IOException, bracket, throwIO, try)+import Data.IORef (IORef, atomicModifyIORef', mkWeakIORef, newIORef, readIORef, writeIORef)+import Foreign.StablePtr (StablePtr, freeStablePtr, newStablePtr)+import Kafka.CallbackTestSupport (assertRetained, awaitCollected)+import Kafka.Consumer (Offset (..))+import Kafka.FaultTestSupport (awaitBarrier, newBarrier, reachBarrier)+import Kafka.FixtureSupport+import Kafka.Producer+import System.Mem.Weak (Weak)+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.HUnit (assertFailure, testCase, (@?=))++tests :: TestTree+tests =+ testGroup+ "Fixture error controls"+ [ testCase "immediate enqueue rejection propagates" $ do+ result <- sendAndConfirm 100000 (\_ _ -> pure (Left (ImmediateError failure))) (const (pure Nothing)) [record]+ result @?= Left failure,+ testCase "delivery failure propagates" $ do+ result <- sendAndConfirm 100000 (\r cb -> cb (DeliveryFailure r failure) >> pure (Right ())) (const (pure Nothing)) [record]+ result @?= Left failure,+ testCase "flush failure propagates" $ do+ result <- sendAndConfirm 100000 (\_ _ -> pure (Right ())) (const (pure (Just failure))) [record]+ result @?= Left failure,+ testCase "missing delivery callback fails" $ do+ result <- sendAndConfirm 1000 (\_ _ -> pure (Right ())) (const (pure Nothing)) [record]+ requireFailure result,+ testCase "wrong delivery identity fails" $ do+ result <- sendAndConfirm 100000 (\r cb -> cb (DeliverySuccess (r {prValue = Just "wrong"}) (Offset 0)) >> pure (Right ())) (const (pure Nothing)) [record]+ requireFailure result,+ testCase "matching delivery succeeds" $ do+ result <- sendAndConfirm 100000 (\r cb -> cb (DeliverySuccess r (Offset 0)) >> pure (Right ())) (const (pure Nothing)) [record]+ result @?= Right (),+ testCase "unexpected poll error propagates" $ do+ collect [Left failure] 1 >>= (@?= Left failure),+ testCase "missing record fails" $ do+ collect [Right 1] 2 >>= requireFailure,+ testCase "extra record fails" $ do+ collect [Right 1, Right 2] 1 >>= requireFailure,+ testCase "idle before exact records is retried" $ do+ collect [Left idle, Right 1, Left idle, Right 2] 2 >>= (@?= Right [1, 2]),+ testCase "partial setup releases first resource" $ do+ released <- newIORef False+ result <- try @IOException (acquirePair (pure ()) (const (writeIORef released True)) (throwIO (userError "injected setup failure") :: IO ()))+ case result of+ Left _ -> pure ()+ Right _ -> assertFailure "injected setup failure was swallowed"+ readIORef released >>= (@?= True),+ testCase "interrupted partial setup releases first resource" $ do+ released <- newIORef False+ stage <- newBarrier+ finished <- newEmptyMVar+ worker <-+ forkFinally+ (acquirePair (pure ()) (const (writeIORef released True)) (reachBarrier stage))+ (putMVar finished)+ awaitBarrier stage+ killThread worker+ takeMVar finished >>= \case+ Left _ -> pure ()+ Right _ -> assertFailure "interrupted acquisition unexpectedly completed"+ readIORef released >>= (@?= True),+ testCase "weak control retains while rooted and collects after release" $+ do+ weak <- bracket capturedRoot (freeStablePtr . fst) $ \(_, weak) -> do+ assertRetained weak+ pure weak+ awaitCollected weak+ ]+ where+ failure = KafkaError "injected failure"+ idle = KafkaResponseError RdKafkaRespErrTimedOut+ record = ProducerRecord (TopicName "fixture") (SpecifiedPartition 0) Nothing (Just "payload") mempty+ collect :: [Either KafkaError Int] -> Int -> IO (Either KafkaError [Int])+ collect events count = do+ remaining <- newIORef events+ ticks <- newIORef 0+ let clock = atomicModifyIORef' ticks (\n -> (n + 1, n))+ poll = atomicModifyIORef' remaining $ \case+ [] -> ([], Left idle)+ e : es -> (es, e)+ collectExactly clock 20 count poll+ requireFailure :: (Show a) => Either KafkaError a -> IO ()+ requireFailure = \case+ Left _ -> pure ()+ Right value -> assertFailure ("expected failure, got " <> show value)++{-# NOINLINE capturedRoot #-}+capturedRoot :: IO (StablePtr (IO Int), Weak (IORef Int))+capturedRoot = do+ value <- newIORef (42 :: Int)+ weak <- mkWeakIORef value (pure ())+ root <- newStablePtr (readIORef value)+ pure (root, weak)
+ test-integration/Kafka/Integration/AssignOnlyTest.hs view
@@ -0,0 +1,77 @@+-- | An assign-only consumer reads explicitly assigned partitions without+-- joining a group (improvement request IR-2, AC-1), in both callback poll+-- modes.+module Kafka.Integration.AssignOnlyTest+ ( tests,+ )+where++import Control.Exception (finally)+import Control.Monad (void)+import Data.ByteString (ByteString)+import Data.Either (isRight)+import Data.Text qualified as Text+import GHC.Clock (getMonotonicTime)+import Kafka.Consumer+import Kafka.Metadata (allConsumerGroupsInfo, giGroup)+import Kafka.TestEnv+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.HUnit (Assertion, assertBool, assertFailure, testCase, (@?=))++tests :: TestEnv -> TestTree+tests env =+ testGroup+ "assign-only"+ [ testGroup+ label+ [ testCase "newAssignedConsumer" $ scenario env mode (label <> "-alias") newAssignedConsumer,+ testCase "newConsumer with an empty subscription" $+ scenario env mode (label <> "-empty") (`newConsumer` mempty)+ ]+ | (label, mode) <- [("async", CallbackPollModeAsync), ("sync", CallbackPollModeSync)]+ ]++scenario ::+ TestEnv ->+ CallbackPollMode ->+ String ->+ (ConsumerProperties -> IO (Either KafkaError KafkaConsumer)) ->+ Assertion+scenario env mode label construct =+ withTopic env (Text.pack ("assign-only-" <> label)) 1 $ \topic producer -> do+ produceTo producer topic 0 "r0"+ produceTo producer topic 0 "r1"+ let group = makeGroupId env (Text.pack ("assign-only-" <> label))+ props =+ consumerProps env+ <> groupId group+ <> noAutoCommit+ <> callbackPollMode mode+ consumer <- construct props >>= either (assertFailure . ("constructor: " <>) . show) pure+ flip finally (void (closeConsumer consumer)) $ do+ assign consumer [TopicPartition topic (PartitionId 0) (PartitionOffset 0)] >>= (@?= Nothing)+ nextValue consumer "r0" >>= (@?= "r0")++ -- Reassigning at another explicit offset keeps routing correct.+ assign consumer [TopicPartition topic (PartitionId 0) (PartitionOffset 1)] >>= (@?= Nothing)+ nextValue consumer "r1" >>= (@?= "r1")++ groups <- allConsumerGroupsInfo consumer (Timeout 5000)+ assertBool ("allConsumerGroupsInfo: " <> show groups) (isRight groups)+ assertBool+ ("the assign-only group " <> show group <> " was registered with the broker")+ (group `notElem` either (const []) (fmap giGroup) groups)++-- | The value of the next record, polling for at most ten seconds.+nextValue :: KafkaConsumer -> String -> IO ByteString+nextValue consumer expected = do+ deadline <- (+ 10) <$> getMonotonicTime+ let go = do+ now <- getMonotonicTime+ if now > deadline+ then assertFailure ("no record arrived within 10 seconds (expected " <> expected <> ")")+ else+ pollMessage consumer (Timeout 500) >>= \case+ Right record -> maybe go pure (crValue record)+ Left _ -> go+ go
+ test-integration/Kafka/Integration/AttributedErrorTest.hs view
@@ -0,0 +1,90 @@+-- | 'pollMessageAttributed' reports which partition a partition-EOF belongs to+-- (improvement request IR-2, AC-2), in both callback poll modes.+module Kafka.Integration.AttributedErrorTest+ ( tests,+ )+where++import Control.Exception (finally)+import Data.ByteString (ByteString)+import Data.Map qualified as Map+import Data.Text qualified as Text+import GHC.Clock (getMonotonicTime)+import Kafka.Consumer+import Kafka.TestEnv+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.HUnit (Assertion, assertBool, assertFailure, testCase, (@?=))++tests :: TestEnv -> TestTree+tests env =+ testGroup+ "attributed"+ [ testCase "async" (scenario env CallbackPollModeAsync "async"),+ testCase "sync" (scenario env CallbackPollModeSync "sync")+ ]++type Record = ConsumerRecord (Maybe ByteString) (Maybe ByteString)++scenario :: TestEnv -> CallbackPollMode -> String -> Assertion+scenario env mode label =+ withTopic env (Text.pack ("attributed-" <> label)) 2 $ \topic producer -> do+ produceTo producer topic 1 "busy"+ let props =+ consumerProps env+ <> groupId (makeGroupId env (Text.pack ("attributed-" <> label)))+ <> noAutoCommit+ <> extraProps (Map.fromList [("enable.partition.eof", "true")])+ <> callbackPollMode mode+ consumer <- newAssignedConsumer props >>= either (assertFailure . ("newAssignedConsumer: " <>) . show) pure+ flip finally (releaseConsumer consumer) $ do+ assign+ consumer+ [ TopicPartition topic (PartitionId 0) PartitionOffsetBeginning,+ TopicPartition topic (PartitionId 1) PartitionOffsetBeginning+ ]+ >>= (@?= Nothing)++ (records, eofs) <- collectUntilEofs consumer 2+ [(crTopic record, crPartition record, crOffset record, crKey record, crValue record, crHeaders record) | record <- records]+ @?= [(topic, PartitionId 1, Offset 0, Nothing, Just "busy", mempty)]+ case map crTimestamp records of+ [CreateTime (Millis time)] -> assertBool "missing attributed record timestamp" (time > 0)+ other -> assertFailure (show other)++ let eof p o =+ ConsumerMessageError+ (KafkaResponseError RdKafkaRespErrPartitionEof)+ (Just topic)+ (Just (PartitionId p))+ (Just (Offset o))+ assertBool ("expected exactly one EOF per partition, got " <> show eofs) (length eofs == 2)+ assertBool ("partition 0 EOF at offset 0 missing from " <> show eofs) (eof 0 0 `elem` eofs)+ assertBool ("partition 1 EOF at offset 1 missing from " <> show eofs) (eof 1 1 `elem` eofs)++ -- A timeout belongs to no message.+ pollMessageAttributed consumer (Timeout 200) >>= \case+ Left err -> err @?= ConsumerMessageError (KafkaResponseError RdKafkaRespErrTimedOut) Nothing Nothing Nothing+ Right record -> assertFailure ("unexpected record " <> show record)++-- | Poll until @n@ partition-EOF errors have arrived (fifteen seconds), then+-- keep polling for two more seconds to catch duplicates. Timeouts are skipped;+-- any other error fails the test.+collectUntilEofs :: KafkaConsumer -> Int -> IO ([Record], [ConsumerMessageError])+collectUntilEofs consumer n = do+ start <- getMonotonicTime+ let go settleUntil records eofs = do+ now <- getMonotonicTime+ case settleUntil of+ Just t | now > t -> pure (reverse records, reverse eofs)+ Nothing | now > start + 15 -> assertFailure ("saw only " <> show (reverse eofs) <> " within 15 seconds")+ _ ->+ pollMessageAttributed consumer (Timeout 200) >>= \case+ Right record -> go settleUntil (record : records) eofs+ Left err+ | cmeError err == KafkaResponseError RdKafkaRespErrTimedOut -> go settleUntil records eofs+ | cmeError err == KafkaResponseError RdKafkaRespErrPartitionEof -> do+ let eofs' = err : eofs+ settle = if length eofs' >= n then Just (maybe (now + 2) id settleUntil) else settleUntil+ go settle records eofs'+ | otherwise -> assertFailure ("unexpected error " <> show err)+ go Nothing [] []
+ test-integration/Kafka/Integration/AuthenticationTest.hs view
@@ -0,0 +1,265 @@+module Kafka.Integration.AuthenticationTest (tests) where++import Control.Concurrent (forkFinally, killThread, threadDelay)+import Control.Concurrent.MVar+import Control.Exception (AsyncException (ThreadKilled), bracket, finally, fromException, throwIO)+import Control.Monad (forM_, void, when)+import Data.ByteString (ByteString)+import Data.Map.Strict qualified as M+import Data.Text qualified as T+import Kafka.Compatibility.KafkaFixture+import Kafka.Compatibility.SecurityFixture+import Kafka.Consumer qualified as C+import Kafka.Producer qualified as P+import Kafka.TestEnv+import Kafka.Topic qualified as A+import Kafka.Topic.Types+import Kafka.Types+import System.Directory (doesDirectoryExist, doesFileExist)+import System.Timeout (timeout)+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.HUnit++tests :: IO SecurityFixture -> TestTree+tests getFixture =+ testGroup+ "authentication-contract"+ $ [ testCase "verified TLS authenticated delivery and exact consume/commit in both modes" $ do+ fixture <- getFixture+ let environment = fixtureEnv (securityKafka fixture)+ topic = securityTopic fixture "primary"+ record = secureRecord topic+ bracket (newProducer fixture "writer") releaseProducer $ \producer -> do+ report <- newEmptyMVar+ P.produceMessage' producer record (putMVar report) >>= (@?= Right ())+ P.flushProducerTimeout producer (Timeout 10000) >>= (@?= Nothing)+ bounded "authenticated delivery report" (takeMVar report) >>= (@?= P.DeliverySuccess record (C.Offset 0))+ forM_ [("async", C.CallbackPollModeAsync), ("sync", C.CallbackPollModeSync)] $ \(label, mode) -> do+ let properties = C.brokersList (teBrokers environment) <> C.groupId (makeGroupId environment ("security-" <> label)) <> C.noAutoCommit <> C.noAutoOffsetStore <> C.callbackPollMode mode <> C.extraProps (securitySettings fixture "reader")+ bracket (C.newAssignedConsumer properties >>= either throwIO pure) releaseConsumer $ \consumer -> do+ C.assign consumer [C.TopicPartition topic (PartitionId 0) C.PartitionOffsetBeginning] >>= (@?= Nothing)+ received <- bounded "authenticated record" (C.pollMessage consumer (Timeout 10000)) >>= either throwIO pure+ (C.crTopic received, C.crPartition received, C.crOffset received, C.crKey received, C.crValue received, C.crHeaders received)+ @?= (topic, PartitionId 0, C.Offset 0, Just "auth-key", Just "authenticated-record", headersFromList [("security", "verified-tls")])+ C.commitOffsetMessage C.OffsetCommit consumer received >>= (@?= Nothing)+ C.committed consumer (Timeout 5000) [(topic, PartitionId 0)] >>= (@?= Right [C.TopicPartition topic (PartitionId 0) (C.PartitionOffset 1)]),+ testCase "authenticated identity without topic ACL receives exact produce denial" $ do+ fixture <- getFixture+ let record = secureRecord (securityTopic fixture "primary")+ bracket (newProducer fixture "denied") releaseProducer $ \producer -> do+ report <- newEmptyMVar+ P.produceMessage' producer record (putMVar report) >>= (@?= Right ())+ P.flushProducerTimeout producer (Timeout 10000) >>= (@?= Nothing)+ bounded "denied delivery report" (takeMVar report) >>= (@?= P.DeliveryFailure record (KafkaResponseError C.RdKafkaRespErrTopicAuthorizationFailed))+ ]+ <> rejectionTests getFixture+ <> reconnectTests getFixture+ <> [ testCase "interruption destroys owned secure processes, credentials, ACL state and private keys" $ do+ ready <- newEmptyMVar+ blocked <- newEmptyMVar+ done <- newEmptyMVar+ worker <-+ forkFinally+ ( bracket createSecurityFixture destroySecurityFixture $ \fixture ->+ bracket (newProducer fixture "writer") releaseProducer $ \producer -> do+ void (publish producer (secureRecord (securityTopic fixture "primary")))+ putMVar ready fixture+ takeMVar blocked+ )+ (putMVar done)+ let await io = timeout 45000000 io >>= maybe (assertFailure "secure interruption deadline") pure+ flip finally (killThread worker) $ do+ fixture <- await (takeMVar ready)+ await (killThread worker)+ await (readMVar done) >>= \case+ Left exception -> (fromException exception :: Maybe AsyncException) @?= Just ThreadKilled+ Right _ -> assertFailure "secure fixture finished without interruption"+ let kafka = securityKafka fixture+ root = fixtureRoot kafka+ fixtureAllStopped kafka >>= (@?= True)+ doesDirectoryExist (root <> "/secret") >>= (@?= False)+ doesFileExist (root <> "/node-1.properties") >>= (@?= False)+ doesDirectoryExist (root <> "/node-1-data") >>= (@?= False)+ doesFileExist (root <> "/security-cleanup.txt") >>= (@?= True)+ putStrLn "[security-interruption] all owned processes exited; credentials, private keys, JAAS and broker ACL state removed"+ ]++reconnectTests :: IO SecurityFixture -> [TestTree]+reconnectTests getFixture =+ [ testCase "producer credential replacement authenticates a new identity after observed reconnect and recovers from invalid replacement" $ do+ fixture <- getFixture+ observed <- newEmptyMVar+ let kafka = securityKafka fixture+ environment = fixtureEnv kafka+ authenticationError = KafkaResponseError C.RdKafkaRespErrAuthentication+ settings = M.insert "message.timeout.ms" "10000" (M.insert "topic.metadata.refresh.interval.ms" "1000" (securitySettings fixture "writer"))+ properties = P.brokersList (teBrokers environment) <> P.extraProps settings <> P.setCallback (P.errorCallback (\err _ -> when (err == authenticationError) (void (tryPutMVar observed err))))+ bracket (P.newProducer properties >>= either throwIO pure) releaseProducer $ \producer -> do+ void (publish producer (secureRecord (securityTopic fixture "primary")))+ withSecurityCredentials fixture "writer2" $ \username _ -> P.setSaslCredentials producer username "deliberately-invalid-replacement" >>= (@?= Nothing)+ restartOwned kafka+ reports <- newEmptyMVar+ let record = secureRecord (securityTopic fixture "replacement")+ P.produceMessage' producer record (putMVar reports) >>= (@?= Right ())+ let awaitAuthentication =+ tryReadMVar observed >>= \case+ Just err -> err @?= authenticationError+ Nothing -> void (P.flushProducerTimeout producer (Timeout 100)) >> threadDelay 10000 >> awaitAuthentication+ bounded "producer did not authenticate with the invalid replacement" awaitAuthentication+ withSecurityCredentials fixture "writer2" (P.setSaslCredentials producer) >>= (@?= Nothing)+ P.flushProducerTimeout producer (Timeout 15000) >>= (@?= Nothing)+ bounded "replacement identity did not deliver" (takeMVar reports) >>= \case+ P.DeliverySuccess actual _ -> actual @?= record+ _ -> assertFailure "corrected producer credentials failed the replacement-only ACL"+ putStrLn "[security-reconnect] producer observed invalid authentication then replacement-only authorized delivery"+ ]+ <> [ testCase (label <> " consumer credential replacement authenticates after observed reconnect and recovers from invalid replacement") $ do+ fixture <- getFixture+ let kafka = securityKafka fixture+ environment = fixtureEnv kafka+ primary = securityTopic fixture "primary"+ replacement = securityTopic fixture "replacement"+ authenticationError = KafkaResponseError C.RdKafkaRespErrAuthentication+ firstOffset <- bracket (newProducer fixture "writer") releaseProducer $ \producer -> publish producer (secureRecord primary)+ nextOffset <- bracket (newProducer fixture "writer2") releaseProducer $ \producer -> publish producer (secureRecord replacement)+ observed <- newEmptyMVar+ let properties = C.brokersList (teBrokers environment) <> C.groupId (makeGroupId environment ("security-reconnect-" <> T.pack label)) <> C.noAutoCommit <> C.noAutoOffsetStore <> C.callbackPollMode mode <> C.extraProps (M.insert "topic.metadata.refresh.interval.ms" "1000" (securitySettings fixture "reader")) <> C.setCallback (C.errorCallback (\err _ -> when (err == authenticationError) (void (tryPutMVar observed err))))+ bracket (C.newAssignedConsumer properties >>= either throwIO pure) releaseConsumer $ \consumer -> do+ assignAt consumer primary firstOffset+ void (receiveAt consumer primary firstOffset)+ withSecurityCredentials fixture "reader2" $ \username _ -> C.setSaslCredentials consumer username "deliberately-invalid-replacement" >>= (@?= Nothing)+ restartOwned kafka+ assignAt consumer replacement nextOffset+ let awaitAuthentication =+ tryReadMVar observed >>= \case+ Just err -> err @?= authenticationError+ Nothing -> do+ C.pollMessage consumer (Timeout 100) >>= \case+ Left err | err == authenticationError -> void (tryPutMVar observed err)+ Right _ -> assertFailure "invalid replacement fetched a record"+ _ -> pure ()+ awaitAuthentication+ bounded "consumer did not authenticate with invalid replacement" awaitAuthentication+ withSecurityCredentials fixture "reader2" (C.setSaslCredentials consumer) >>= (@?= Nothing)+ assignAt consumer replacement nextOffset+ record <- receiveAt consumer replacement nextOffset+ C.commitOffsetMessage C.OffsetCommit consumer record >>= (@?= Nothing)+ C.committed consumer (Timeout 5000) [(replacement, PartitionId 0)] >>= (@?= Right [C.TopicPartition replacement (PartitionId 0) (C.PartitionOffset (C.unOffset nextOffset + 1))])+ putStrLn ("[security-reconnect] consumer " <> label <> " observed invalid authentication then replacement-only record and exact next commit")+ | (label, mode) <- [("async", C.CallbackPollModeAsync), ("sync", C.CallbackPollModeSync)]+ ]++restartOwned :: KafkaFixture -> IO ()+restartOwned fixture = stopBroker fixture (BrokerId 1) `finally` (startBroker fixture (BrokerId 1) >> awaitBrokers fixture)++assignAt :: C.KafkaConsumer -> TopicName -> C.Offset -> IO ()+assignAt consumer topic offset = C.assign consumer [C.TopicPartition topic (PartitionId 0) (C.PartitionOffset (C.unOffset offset))] >>= (@?= Nothing)++receiveAt :: C.KafkaConsumer -> TopicName -> C.Offset -> IO (C.ConsumerRecord (Maybe ByteString) (Maybe ByteString))+receiveAt consumer topic offset = bounded "missing replacement-authorized record" go+ where+ go =+ C.pollMessage consumer (Timeout 1000) >>= \case+ Left (KafkaResponseError C.RdKafkaRespErrTimedOut) -> go+ Left (KafkaResponseError C.RdKafkaRespErrTopicAuthorizationFailed) -> go+ Left (KafkaResponseError C.RdKafkaRespErrAuthentication) -> go+ Left err -> throwIO err+ Right record -> do+ (C.crTopic record, C.crPartition record, C.crOffset record, C.crKey record, C.crValue record, C.crHeaders record) @?= (topic, PartitionId 0, offset, Just "auth-key", Just "authenticated-record", headersFromList [("security", "verified-tls")])+ pure record++rejectionTests :: IO SecurityFixture -> [TestTree]+rejectionTests getFixture =+ [ testCase (label <> " producer reports the exact connection failure and no delivery") $ do+ fixture <- getFixture+ let environment = fixtureEnv (securityKafka fixture)+ expected = KafkaResponseError code+ record = secureRecord (securityTopic fixture "primary")+ observed <- newEmptyMVar+ reports <- newEmptyMVar+ let properties = P.brokersList (addresses environment) <> P.extraProps (M.insert "message.timeout.ms" "5000" (change (securitySettings fixture "writer"))) <> P.setCallback (P.errorCallback (\err _ -> when (err == expected) (void (tryPutMVar observed err))))+ bracket (P.newProducer properties >>= either throwIO pure) releaseProducer $ \producer -> do+ P.produceMessage' producer record (putMVar reports) >>= (@?= Right ())+ P.flushProducerTimeout producer (Timeout 10000) >>= (@?= Nothing)+ bounded "missing expected producer connection error" (takeMVar observed) >>= (@?= expected)+ bounded "missing rejected delivery" (takeMVar reports) >>= (@?= P.DeliveryFailure record (KafkaResponseError C.RdKafkaRespErrMsgTimedOut))+ | (label, change, addresses, code) <- rejectionVariants+ ]+ <> [ testCase (label <> " " <> modeLabel <> " consumer reports the exact connection failure") $ do+ fixture <- getFixture+ let environment = fixtureEnv (securityKafka fixture)+ expected = KafkaResponseError code+ topic = securityTopic fixture "primary"+ observed <- newEmptyMVar+ let properties = C.brokersList (addresses environment) <> C.groupId (makeGroupId environment ("security-rejected-" <> T.pack label <> T.pack modeLabel)) <> C.noAutoCommit <> C.callbackPollMode mode <> C.extraProps (change (securitySettings fixture "reader")) <> C.setCallback (C.errorCallback (\err _ -> when (err == expected) (void (tryPutMVar observed err))))+ bracket (C.newAssignedConsumer properties >>= either throwIO pure) releaseConsumer $ \consumer -> do+ C.assign consumer [C.TopicPartition topic (PartitionId 0) C.PartitionOffsetBeginning] >>= (@?= Nothing)+ let await =+ tryReadMVar observed >>= \case+ Just actual -> actual @?= expected+ Nothing -> do+ C.pollMessage consumer (Timeout 100) >>= \case+ Left err | err == expected -> void (tryPutMVar observed err)+ Right _ -> assertFailure "rejected authentication/TLS unexpectedly fetched a record"+ _ -> pure ()+ threadDelay 10000+ await+ bounded "missing expected consumer connection error" await+ | (label, change, addresses, code) <- rejectionVariants,+ (modeLabel, mode) <- [("async", C.CallbackPollModeAsync), ("sync", C.CallbackPollModeSync)]+ ]+ <> [ testCase (label <> " exact topic/group/admin authorization denials") $ do+ fixture <- getFixture+ let environment = fixtureEnv (securityKafka fixture)+ topic = securityTopic fixture "primary"+ props identity group = C.brokersList (teBrokers environment) <> C.groupId (makeGroupId environment group) <> C.noAutoCommit <> C.noAutoOffsetStore <> C.callbackPollMode mode <> C.extraProps (M.insert "session.timeout.ms" "6000" (securitySettings fixture identity))+ bracket (C.newAssignedConsumer (props "denied" "security-topic-denied") >>= either throwIO pure) releaseConsumer $ \consumer -> do+ C.assign consumer [C.TopicPartition topic (PartitionId 0) C.PartitionOffsetBeginning] >>= (@?= Nothing)+ let awaitDenial =+ C.pollMessage consumer (Timeout 1000) >>= \case+ Left (KafkaResponseError C.RdKafkaRespErrTimedOut) -> awaitDenial+ result -> result @?= Left (KafkaResponseError C.RdKafkaRespErrTopicAuthorizationFailed)+ bounded "missing topic ACL denial" awaitDenial+ offset <- bracket (newProducer fixture "writer") releaseProducer $ \producer -> publish producer (secureRecord topic)+ bracket (C.newAssignedConsumer (props "reader" "forbidden-security-group") >>= either throwIO pure) releaseConsumer $ \consumer -> do+ C.assign consumer [C.TopicPartition topic (PartitionId 0) (C.PartitionOffset (C.unOffset offset))] >>= (@?= Nothing)+ record <- C.pollMessage consumer (Timeout 10000) >>= either throwIO pure+ -- A denied FindCoordinator leaves no coordinator for the native+ -- synchronous commit. Assert that exact result and the broker's+ -- exact authorization audit, rather than guessing GROUP_AUTH.+ C.commitOffsetMessage C.OffsetCommit consumer record >>= (@?= Just (KafkaResponseError C.RdKafkaRespErrWaitCoord))+ assertGroupAuthorizationDenied fixture "reader" (prefixedName environment "forbidden-security-group")+ bracket (newProducer fixture "denied") releaseProducer $ \producer -> do+ let deniedTopic = TopicName (prefixedName environment ("security-admin-denied-" <> T.pack label))+ A.createTopic producer (NewTopic deniedTopic (PartitionCount 1) (ReplicationFactor 1) M.empty) >>= (@?= Left (KafkaResponseError C.RdKafkaRespErrTopicAuthorizationFailed))+ bracket (newProducer fixture "admin") releaseProducer $ \producer -> do+ let allowedTopic = TopicName (prefixedName environment ("security-admin-allowed-" <> T.pack label))+ A.createTopic producer (NewTopic allowedTopic (PartitionCount 1) (ReplicationFactor 1) M.empty) >>= (@?= Right allowedTopic)+ A.deleteTopic producer allowedTopic >>= (@?= Right allowedTopic)+ | (label, mode) <- [("async", C.CallbackPollModeAsync), ("sync", C.CallbackPollModeSync)]+ ]++rejectionVariants :: [(String, M.Map T.Text T.Text -> M.Map T.Text T.Text, TestEnv -> [BrokerAddress], C.RdKafkaRespErrT)]+rejectionVariants =+ [ ("invalid-password", M.insert "sasl.password" "deliberately-invalid-fixture-password", teBrokers, C.RdKafkaRespErrAuthentication),+ ("untrusted-CA", M.delete "ssl.ca.location", teBrokers, C.RdKafkaRespErrSsl),+ ("hostname-mismatch", id, map (BrokerAddress . T.replace "localhost:" "127.0.0.1:" . unBrokerAddress) . teBrokers, C.RdKafkaRespErrSsl)+ ]++secureRecord :: TopicName -> P.ProducerRecord+secureRecord topic = P.ProducerRecord topic (P.SpecifiedPartition 0) (Just "auth-key") (Just "authenticated-record") (headersFromList [("security", "verified-tls")])++newProducer :: SecurityFixture -> String -> IO P.KafkaProducer+newProducer fixture label = P.newProducer (P.brokersList (teBrokers (fixtureEnv (securityKafka fixture))) <> P.extraProps (M.insert "message.timeout.ms" "5000" (securitySettings fixture label))) >>= either throwIO pure++bounded :: String -> IO a -> IO a+bounded label action = timeout 15000000 action >>= maybe (assertFailure label) pure++publish :: P.KafkaProducer -> P.ProducerRecord -> IO C.Offset+publish producer record = do+ report <- newEmptyMVar+ P.produceMessage' producer record (putMVar report) >>= (@?= Right ())+ P.flushProducerTimeout producer (Timeout 10000) >>= (@?= Nothing)+ bounded "missing authenticated delivery" (takeMVar report) >>= \case+ P.DeliverySuccess actual offset -> (actual @?= record) >> pure offset+ _ -> assertFailure "authenticated record was not delivered"
+ test-integration/Kafka/Integration/BatchTest.hs view
@@ -0,0 +1,34 @@+module Kafka.Integration.BatchTest+ ( tests,+ )+where++import Control.Monad (forM_)+import Data.Either (isRight)+import Kafka.Consumer+import Kafka.TestEnv+import Test.Tasty (DependencyType (AllSucceed), TestTree, dependentTestGroup)+import Test.Tasty.HUnit (assertBool, testCase, (@?=))++tests :: TestEnv -> TestTree+tests env =+ withConsumer env (consumerProps env <> groupId (makeGroupId env "batch-consumer")) $ \getConsumer ->+ dependentTestGroup+ "Batch consumer"+ AllSucceed+ [ testCase "should consume first batch" $ do+ k <- getConsumer+ res <- pollMessageBatch k (Timeout 1000) (BatchSize 5)+ length res @?= 5+ forM_ res $ \r -> assertBool (show r) (isRight r),+ testCase "should consume second batch with not enough messages" $ do+ k <- getConsumer+ res <- pollMessageBatch k (Timeout 1000) (BatchSize 50)+ let res' = Prelude.filter (/= Left (KafkaResponseError RdKafkaRespErrPartitionEof)) res+ assertBool ("expected fewer than 50, got " <> show (length res')) (length res' < 50)+ forM_ res' $ \r -> assertBool (show r) (isRight r),+ testCase "should consume empty batch when there are no messages" $ do+ k <- getConsumer+ res <- pollMessageBatch k (Timeout 1000) (BatchSize 50)+ length res @?= 0+ ]
+ test-integration/Kafka/Integration/BrokerFailureTest.hs view
@@ -0,0 +1,339 @@+module Kafka.Integration.BrokerFailureTest (tests) where++import Control.Concurrent (forkIOWithUnmask, killThread, threadDelay)+import Control.Concurrent.MVar+import Control.Exception (AsyncException (ThreadKilled), SomeException, bracket, finally, fromException, throwIO, try)+import Control.Monad (forM_, forever, void, when)+import Data.ByteString (ByteString)+import Data.IORef+import Data.Int (Int64)+import Data.List (sort, sortOn)+import Data.Map.Strict qualified as M+import Data.Text qualified as T+import Kafka.Compatibility.KafkaFixture+import Kafka.Consumer qualified as C+import Kafka.Metadata qualified as D+import Kafka.Producer qualified as P+import Kafka.TestEnv+import Kafka.Topic qualified as A+import Kafka.Topic.Types+import Kafka.Transaction qualified as X+import Kafka.TransactionTestSupport+import Kafka.Types+import System.Timeout (timeout)+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.HUnit++bounded :: String -> IO a -> IO a+bounded label action = timeout 30000000 action >>= maybe (assertFailure label) pure++tests :: IO KafkaFixture -> TestTree+tests getFixture =+ testGroup+ "broker-failure"+ $ [ testCase (label <> " observed leader election preserves exact records and commits") $ do+ fixture <- getFixture+ let environment = fixtureEnv fixture+ topic = TopicName (prefixedName environment ("leader-" <> T.pack label))+ properties = P.brokersList (teBrokers environment) <> P.extraProps (M.fromList [("enable.idempotence", "true"), ("acks", "all"), ("message.timeout.ms", "15000")])+ bracket (P.newProducer properties >>= either throwIO pure) releaseProducer $ \producer -> do+ A.createTopic producer (NewTopic topic (PartitionCount 1) (ReplicationFactor 3) (M.singleton "min.insync.replicas" "2")) >>= (@?= Right topic)+ flip finally (A.deleteTopic producer topic >>= (@?= Right topic)) $ do+ let props = C.brokersList (teBrokers environment) <> C.groupId (makeGroupId environment ("leader-" <> T.pack label)) <> C.noAutoCommit <> C.noAutoOffsetStore <> C.callbackPollMode mode+ bracket (C.newAssignedConsumer props >>= either throwIO pure) releaseConsumer $ \consumer -> do+ C.assign consumer [C.TopicPartition topic (PartitionId 0) C.PartitionOffsetBeginning] >>= (@?= Nothing)+ sendExact producer topic 0+ first <- receiveExact consumer topic 0+ C.commitOffsetMessage C.OffsetCommit consumer first >>= (@?= Nothing)+ verifyCommit consumer topic 1+ before <- awaitMetadata producer topic (\p -> D.pmError p == Nothing && sort (D.pmInSyncReplicas p) == map BrokerId [1, 2, 3])+ sort (D.pmReplicas before) @?= map BrokerId [1, 2, 3]+ let old = D.pmLeader before+ assertBool (show before) (old `elem` map BrokerId [1, 2, 3])+ putStrLn ("[leader-before] " <> label <> " " <> show before)+ flip finally (startBroker fixture old >> awaitMetadata producer topic (\p -> D.pmError p == Nothing && sort (D.pmInSyncReplicas p) == map BrokerId [1, 2, 3])) $ do+ stopBroker fixture old+ changed <- awaitMetadata producer topic (\p -> D.pmError p == Nothing && D.pmLeader p /= old && D.pmLeader p `elem` filter (/= old) (map BrokerId [1, 2, 3]) && sort (D.pmInSyncReplicas p) == filter (/= old) (map BrokerId [1, 2, 3]))+ putStrLn ("[leader-elected] " <> label <> " " <> show changed)+ sendExact producer topic 1+ second <- receiveExact consumer topic 1+ C.commitOffsetMessage C.OffsetCommit consumer second >>= (@?= Nothing)+ verifyCommit consumer topic 2+ C.pollMessage consumer (Timeout 100) >>= (@?= Left (KafkaResponseError C.RdKafkaRespErrTimedOut))+ putStrLn ("[leader-recovered] " <> label <> " records=[0,1] committed=2")+ | (label, mode) <- [("async", C.CallbackPollModeAsync), ("sync", C.CallbackPollModeSync)]+ ]+ <> distributedTests getFixture+ <> transactionTests getFixture+ <> [ testCase "cancellation during complete outage restores all owned brokers" $ do+ fixture <- getFixture+ stopped <- newEmptyMVar+ completed <- newEmptyMVar+ worker <- forkIOWithUnmask $ \unmask -> do+ outcome <- try @SomeException $ unmask $ withBrokersStopped fixture $ do+ assertBool "some owned broker remained running" =<< fixtureAllStopped fixture+ putMVar stopped ()+ threadDelay maxBound+ putMVar completed outcome+ flip finally (killThread worker) $ do+ bounded "owned outage did not begin" (takeMVar stopped)+ killThread worker+ bounded "owned outage cancellation did not finish restoration" (takeMVar completed) >>= \case+ Left exception -> fromException exception @?= Just ThreadKilled+ Right () -> assertFailure "outage worker returned without cancellation"+ awaitBrokers fixture+ assertBool "restored topology has no live brokers" . not =<< fixtureAllStopped fixture+ putStrLn "[outage-cancellation] ThreadKilled restored all three owned broker/controllers before healthy native metadata"+ ]++sendExact :: P.KafkaProducer -> TopicName -> Int64 -> IO ()+sendExact producer topic offset = do+ report <- newEmptyMVar+ let record = P.ProducerRecord topic (P.SpecifiedPartition 0) (Just "leader-key") (Just (if offset == 0 then "before" else "after")) (headersFromList [("origin", "mp3")])+ P.produceMessage' producer record (putMVar report) >>= (@?= Right ())+ P.flushProducerTimeout producer (Timeout 15000) >>= (@?= Nothing)+ bounded "missing leader-change delivery report" (takeMVar report) >>= (@?= P.DeliverySuccess record (C.Offset offset))++receiveExact :: C.KafkaConsumer -> TopicName -> Int64 -> IO (C.ConsumerRecord (Maybe ByteString) (Maybe ByteString))+receiveExact consumer topic offset = bounded "missing leader-change record" go+ where+ go =+ C.pollMessage consumer (Timeout 1000) >>= \case+ Left (KafkaResponseError C.RdKafkaRespErrTimedOut) -> go+ Left err -> throwIO err+ Right record -> do+ (C.crTopic record, C.crPartition record, C.crOffset record, C.crKey record, C.crValue record, C.crHeaders record)+ @?= (topic, PartitionId 0, C.Offset offset, Just "leader-key", Just (if offset == 0 then "before" else "after"), headersFromList [("origin", "mp3")])+ pure record++verifyCommit :: C.KafkaConsumer -> TopicName -> Int64 -> IO ()+verifyCommit consumer topic offset = C.committed consumer (Timeout 5000) [(topic, PartitionId 0)] >>= (@?= Right [C.TopicPartition topic (PartitionId 0) (C.PartitionOffset offset)])++awaitMetadata :: P.KafkaProducer -> TopicName -> (D.PartitionMetadata -> Bool) -> IO D.PartitionMetadata+awaitMetadata producer topic predicate = bounded "owned leader/ISR transition was not observed" go+ where+ go = do+ result <- D.topicMetadata producer (Timeout 2000) topic >>= either throwIO pure+ case D.kmTopics result of+ [metadata] | D.tmError metadata == Nothing -> case D.tmPartitions metadata of+ [partition] | predicate partition -> pure partition+ _ -> threadDelay 100000 >> go+ _ -> assertFailure (show result)++type Record = C.ConsumerRecord (Maybe ByteString) (Maybe ByteString)++distributedTests :: IO KafkaFixture -> [TestTree]+distributedTests getFixture =+ [ testCase (protocol <> " " <> label <> " handoff pause seek eviction and complete outage recover exact offsets") $ do+ fixture <- getFixture+ let environment = fixtureEnv fixture+ suffix = T.pack (protocol <> "-" <> label)+ group = makeGroupId environment ("distributed-" <> suffix)+ events <- newIORef ([] :: [(String, C.RebalanceEvent, Bool)])+ records <- newIORef []+ withReplicatedTopic fixture ("distributed-" <> suffix) 2 $ \topic producer -> do+ let callback role consumer event = do+ lost <- C.assignmentLost consumer+ atomicModifyIORef' events (\seen -> (seen <> [(role, event, lost)], ()))+ properties role = C.brokersList (teBrokers environment) <> C.groupId group <> C.noAutoCommit <> C.noAutoOffsetStore <> C.callbackPollMode mode <> C.extraProps (M.fromList [("group.protocol", "classic"), ("partition.assignment.strategy", T.pack strategy), ("session.timeout.ms", "6000"), ("heartbeat.interval.ms", "1000"), ("max.poll.interval.ms", "10000"), ("log_level", "0")]) <> C.setCallback (C.rebalanceCallback (callback role))+ acquire role = C.newConsumer (properties role) (C.topics [topic] <> C.offsetReset C.Earliest) >>= either throwIO pure+ bracket (acquire "first") releaseConsumer $ \first ->+ withPolling mode "first" first records $ \stopFirst -> do+ awaitAssignment first topic [PartitionId 0, PartitionId 1]+ bracket (acquire "second") releaseConsumer $ \second ->+ withPolling mode "second" second records $ \_ -> do+ (ownedFirst, ownedSecond) <-+ bounded "group did not split its exact assignment" $+ let await = do+ a <- assigned first topic+ b <- assigned second topic+ if length a == 1 && length b == 1 && sort (a <> b) == [PartitionId 0, PartitionId 1] then pure (a, b) else threadDelay 100000 >> await+ in await+ putStrLn ("[distributed-split] " <> protocol <> " " <> label <> " " <> show (ownedFirst, ownedSecond))+ healthy <- readIORef events+ assertBool (show healthy) (not (null healthy) && all (\(_, _, lost) -> not lost) healthy)+ forM_ [0, 1] $ \partition -> sendDistributed producer topic partition "before"+ takeRecords records 2 >>= assertRecords topic [(0, 0, "before"), (1, 0, "before")]+ (paused, open) <- case (ownedFirst, ownedSecond) of+ ([a], [b]) -> pure (a, b)+ actual -> assertFailure (show actual)+ putStrLn "[distributed-before] exact initial records committed"+ C.pausePartitions first [(topic, paused)] >>= (@?= KafkaResponseError C.RdKafkaRespErrNoError)+ sendDistributed producer topic (unPartitionId paused) "paused"+ sendDistributed producer topic (unPartitionId open) "open"+ takeRecords records 1 >>= assertRecords topic [(unPartitionId open, 1, "open")]+ threadDelay 200000+ readIORef records >>= (@?= [])+ C.seekPartitions first [C.TopicPartition topic paused C.PartitionOffsetBeginning] (Timeout 10000) >>= (@?= Nothing)+ C.resumePartitions first [(topic, paused)] >>= (@?= KafkaResponseError C.RdKafkaRespErrNoError)+ takeRecords records 2 >>= assertRecords topic [(unPartitionId paused, 0, "before"), (unPartitionId paused, 1, "paused")]+ putStrLn "[distributed-pause-seek] exact replay and unpaused partition delivered"+ stopFirst+ releaseConsumer first+ awaitAssignment second topic [PartitionId 0, PartitionId 1]+ forM_ [0, 1] $ \partition -> sendDistributed producer topic partition "handoff"+ takeRecords records 2 >>= assertRecords topic [(0, 2, "handoff"), (1, 2, "handoff")]+ verifyAllCommits second topic 2+ putStrLn "[distributed-handoff] second consumer owns both partitions; stored=3, committed=2"+ withBrokersStopped fixture $ do+ assertBool "some owned broker remained running" =<< fixtureAllStopped fixture+ putStrLn "[distributed-stopped] all owned processes exited"+ result <- C.commitAllOffsets C.OffsetCommit second+ result @?= Just (KafkaResponseError C.RdKafkaRespErrWaitCoord)+ bounded "actual involuntary assignment loss was not observed" $+ let await = do+ seen <- readIORef events+ if any (\(role, event, lost) -> role == "second" && lost && beforeRevoke event) seen then pure () else threadDelay 100000 >> await+ in await+ outageDelivery environment topic+ C.assignment second >>= (@?= Right M.empty)+ C.commitAllOffsets C.OffsetCommit second >>= (@?= Just (KafkaResponseError C.RdKafkaRespErrNoOffset))+ putStrLn ("[distributed-outage] " <> protocol <> " " <> label <> " assignmentLost=True; commit-all=" <> show result)+ awaitBrokers fixture+ awaitAssignment second topic [PartitionId 0, PartitionId 1]+ -- The offline commit failed with every broker stopped. Replay+ -- exactly the uncommitted handoff records, then commit them.+ takeRecords records 2 >>= assertRecords topic [(0, 2, "handoff"), (1, 2, "handoff")]+ C.commitAllOffsets C.OffsetCommit second >>= (@?= Nothing)+ verifyAllCommits second topic 3+ forM_ [0, 1] $ \partition -> sendDistributed producer topic partition "recovered"+ takeRecords records 2 >>= assertRecords topic [(0, 3, "recovered"), (1, 3, "recovered")]+ C.commitAllOffsets C.OffsetCommit second >>= (@?= Nothing)+ verifyAllCommits second topic 4+ threadDelay 200000+ readIORef records >>= (@?= [])+ C.assignmentLost second >>= (@?= False)+ putStrLn ("[distributed-recovered] " <> protocol <> " " <> label <> " partitions=[0,1] committed=[4,4]; no expired or duplicate record")+ | (protocol, strategy) <- [("eager", "range"), ("cooperative", "cooperative-sticky")],+ (label, mode) <- [("async", C.CallbackPollModeAsync), ("sync", C.CallbackPollModeSync)]+ ]+ where+ beforeRevoke (C.RebalanceBeforeRevoke _) = True+ beforeRevoke _ = False++withReplicatedTopic :: KafkaFixture -> T.Text -> Int -> (TopicName -> P.KafkaProducer -> IO a) -> IO a+withReplicatedTopic fixture suffix partitions action =+ let environment = fixtureEnv fixture+ topic = TopicName (prefixedName environment suffix)+ props = P.brokersList (teBrokers environment) <> P.extraProps (M.fromList [("enable.idempotence", "true"), ("acks", "all"), ("message.timeout.ms", "15000"), ("log_level", "0")])+ in bracket (P.newProducer props >>= either throwIO pure) releaseProducer $ \producer -> do+ A.createTopic producer (NewTopic topic (PartitionCount partitions) (ReplicationFactor 3) (M.singleton "min.insync.replicas" "2")) >>= (@?= Right topic)+ action topic producer `finally` (A.deleteTopic producer topic >>= (@?= Right topic))++assigned :: C.KafkaConsumer -> TopicName -> IO [PartitionId]+assigned consumer topic = sort . M.findWithDefault [] topic <$> (C.assignment consumer >>= either throwIO pure)++awaitAssignment :: C.KafkaConsumer -> TopicName -> [PartitionId] -> IO ()+awaitAssignment consumer topic expected = bounded "exact group assignment was not observed" go+ where+ go = assigned consumer topic >>= \actual -> if actual == expected then pure () else threadDelay 100000 >> go++withPolling :: C.CallbackPollMode -> String -> C.KafkaConsumer -> IORef [(String, Record)] -> (IO () -> IO a) -> IO a+withPolling mode role consumer records action = do+ done <- newEmptyMVar+ let loop = forever $ do+ when (mode == C.CallbackPollModeSync) (C.pollConsumerEvents consumer (Just (Timeout 0)))+ C.pollMessage consumer (Timeout 100) >>= \case+ Left (KafkaResponseError code) | code `elem` [C.RdKafkaRespErrTimedOut, C.RdKafkaRespErrPartitionEof, C.RdKafkaRespErrTransport, C.RdKafkaRespErrAllBrokersDown] -> pure ()+ Left err -> throwIO err+ Right record -> do+ C.storeOffsetMessage consumer record >>= (@?= Nothing)+ -- These phases deliberately leave stored offsets for commit-all+ -- and demonstrate exact replay after its failed offline request.+ when (C.crValue record `notElem` [Just "handoff", Just "recovered"]) $+ C.commitOffsetMessage C.OffsetCommit consumer record >>= (@?= Nothing)+ atomicModifyIORef' records (\seen -> (seen <> [(role, record)], ()))+ bracket+ (forkIOWithUnmask (\unmask -> try @SomeException (unmask loop) >>= putMVar done))+ ( \worker -> do+ killThread worker+ bounded "consumer polling worker did not stop" (readMVar done) >>= \case+ Left exception | (fromException exception :: Maybe AsyncException) == Just ThreadKilled -> pure ()+ Left exception -> throwIO exception+ Right _ -> assertFailure "polling worker stopped unexpectedly"+ )+ (\worker -> action (killThread worker >> void (bounded "first consumer worker did not stop" (readMVar done))))++takeRecords :: IORef [(String, Record)] -> Int -> IO [(String, Record)]+takeRecords reference count = bounded "exact distributed records did not arrive" go+ where+ go = do+ seen <- readIORef reference+ if length seen >= count then atomicModifyIORef' reference (\values -> ([], values)) else threadDelay 10000 >> go++assertRecords :: TopicName -> [(Int, Int64, ByteString)] -> [(String, Record)] -> IO ()+assertRecords topic expected actual =+ order [(C.crTopic record, C.crPartition record, C.crOffset record, C.crKey record, C.crValue record, C.crHeaders record) | (_, record) <- actual]+ @?= order [(topic, PartitionId partition, C.Offset offset, Just "distributed-key", Just value, headersFromList [("origin", "mp3-distributed")]) | (partition, offset, value) <- expected]+ where+ order = sortOn (\(_, partition, offset, _, _, _) -> (unPartitionId partition, C.unOffset offset))++sendDistributed :: P.KafkaProducer -> TopicName -> Int -> ByteString -> IO ()+sendDistributed producer topic partition value = do+ report <- newEmptyMVar+ let record = P.ProducerRecord topic (P.SpecifiedPartition partition) (Just "distributed-key") (Just value) (headersFromList [("origin", "mp3-distributed")])+ P.produceMessage' producer record (putMVar report) >>= (@?= Right ())+ P.flushProducerTimeout producer (Timeout 15000) >>= (@?= Nothing)+ bounded "missing distributed delivery" (takeMVar report) >>= \case+ P.DeliverySuccess actual _ -> actual @?= record+ result -> assertFailure (show result)++verifyAllCommits :: C.KafkaConsumer -> TopicName -> Int64 -> IO ()+verifyAllCommits consumer topic offset = C.committed consumer (Timeout 5000) [(topic, PartitionId 0), (topic, PartitionId 1)] >>= (@?= Right [C.TopicPartition topic (PartitionId partition) (C.PartitionOffset offset) | partition <- [0, 1]])++outageDelivery :: TestEnv -> TopicName -> IO ()+outageDelivery environment topic = do+ let properties = P.brokersList (teBrokers environment) <> P.extraProps (M.fromList [("queue.buffering.max.messages", "1"), ("message.timeout.ms", "2000"), ("log_level", "0")])+ record = P.ProducerRecord topic (P.SpecifiedPartition 0) Nothing (Just "must-expire-during-outage") mempty+ bracket (P.newProducer properties >>= either throwIO pure) releaseProducer $ \producer -> do+ report <- newEmptyMVar+ unexpected <- newEmptyMVar+ P.produceMessage' producer record (putMVar report) >>= (@?= Right ())+ P.produceMessage' producer record (putMVar unexpected) >>= (@?= Left (P.ImmediateError (KafkaResponseError C.RdKafkaRespErrQueueFull)))+ P.flushProducerTimeout producer (Timeout 5000) >>= (@?= Nothing)+ bounded "outage delivery timeout report missing" (takeMVar report) >>= (@?= P.DeliveryFailure record (KafkaResponseError C.RdKafkaRespErrMsgTimedOut))+ tryReadMVar unexpected >>= (@?= Nothing)++transactionTests :: IO KafkaFixture -> [TestTree]+transactionTests getFixture =+ [ testCase (label <> " transaction commit timeout across full outage retries and preserves read-committed visibility") $ do+ fixture <- getFixture+ let environment = fixtureEnv fixture+ withReplicatedTopic fixture ("transaction-outage-" <> T.pack label) 1 $ \topic _ -> do+ let props = P.brokersList (teBrokers environment) <> P.extraProps (M.fromList [("transactional.id", prefixedName environment ("transaction-outage-" <> T.pack label)), ("transaction.timeout.ms", "60000"), ("message.timeout.ms", "30000"), ("log_level", "0")])+ bracket (P.newProducer props >>= either throwIO pure) releaseProducer $ \producer -> do+ X.initTransactions producer (Timeout 15000) >>= (@?= Nothing)+ X.beginTransaction producer >>= (@?= Nothing)+ sendDistributed producer topic 0 "committed-after-outage"+ let visibilityProperties = C.brokersList (teBrokers environment) <> C.groupId (makeGroupId environment ("transaction-visibility-" <> T.pack label)) <> C.callbackPollMode mode <> C.noAutoCommit <> C.extraProp "isolation.level" "read_committed" <> C.extraProp "log_level" "0"+ bracket (C.newAssignedConsumer visibilityProperties >>= either throwIO pure) releaseConsumer $ \consumer -> do+ C.assign consumer [C.TopicPartition topic (PartitionId 0) C.PartitionOffsetBeginning] >>= (@?= Nothing)+ C.pollMessage consumer (Timeout 500) >>= (@?= Left (KafkaResponseError C.RdKafkaRespErrTimedOut))+ withBrokersStopped fixture $ withTxFault 0 $ do+ X.commitTransaction producer (Timeout 1000) >>= assertRetry+ txStat 0 >>= (@?= 1)+ txStat 1 >>= (@?= 1)+ txStat 8 >>= (@?= 0)+ awaitBrokers fixture+ bounded "transaction did not finish after owned broker restoration" $+ let retry =+ X.commitTransaction producer (Timeout 10000) >>= \case+ Nothing -> pure ()+ result -> assertRetry result >> retry+ in retry+ record <-+ bounded "committed transaction record was not visible" $+ let receive =+ C.pollMessage consumer (Timeout 1000) >>= \case+ Left (KafkaResponseError C.RdKafkaRespErrTimedOut) -> receive+ Left err -> throwIO err+ Right value -> pure value+ in receive+ assertRecords topic [(0, 0, "committed-after-outage")] [(label, record)]+ C.pollMessage consumer (Timeout 200) >>= (@?= Left (KafkaResponseError C.RdKafkaRespErrTimedOut))+ putStrLn ("[transaction-outage] " <> label <> " timed-out commit retriable=True abort=False fatal=False; restored commit publishes exact offset 0 once")+ | (label, mode) <- [("async", C.CallbackPollModeAsync), ("sync", C.CallbackPollModeSync)]+ ]+ where+ assertRetry Nothing = assertFailure "offline transaction unexpectedly committed"+ assertRetry (Just err) = (X.getKafkaError err, X.kafkaErrorIsFatal err, X.kafkaErrorIsRetriable err, X.kafkaErrorTxnRequiresAbort err) @?= (KafkaResponseError C.RdKafkaRespErrTimedOut, False, True, False)
+ test-integration/Kafka/Integration/CallbackLifetimeTest.hs view
@@ -0,0 +1,660 @@+module Kafka.Integration.CallbackLifetimeTest (tests, runInvalidAccessControl, runThrowingProbe) where++import Control.Concurrent (ThreadId, forkFinally, forkIOWithUnmask, killThread, myThreadId, threadDelay)+import Control.Concurrent.MVar (MVar, newEmptyMVar, putMVar, readMVar, tryPutMVar, tryReadMVar)+import Control.Exception (AsyncException (ThreadKilled), ErrorCall, SomeException, bracket, finally, fromException, throwIO, try)+import Control.Monad (void)+import Data.IORef (IORef, atomicModifyIORef', mkWeakIORef, modifyIORef', newIORef, readIORef, writeIORef)+import Data.List (isInfixOf)+import Data.Map.Strict qualified as M+import Data.Text qualified as Text+import GHC.Conc (BlockReason (BlockedOnException, BlockedOnMVar), ThreadStatus (ThreadBlocked), getUncaughtExceptionHandler, setUncaughtExceptionHandler, threadStatus)+import Kafka.CallbackLifetimeSupport+import Kafka.CallbackTestSupport (assertRetained, awaitCollected)+import Kafka.Consumer qualified as C+import Kafka.Producer qualified as P+import Kafka.TestEnv+import System.Directory (createDirectoryIfMissing)+import System.Environment (getEnvironment, getExecutablePath, lookupEnv)+import System.Exit (ExitCode (ExitSuccess), die)+import System.IO (hFlush, stdout)+import System.Mem.Weak (Weak)+import System.Process (CreateProcess (env), proc, readCreateProcessWithExitCode)+import System.Random (randomIO)+import System.Timeout (timeout)+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.HUnit (assertBool, assertFailure, testCase, (@?=))++tests :: TestEnv -> TestTree+tests env =+ testGroup+ "callback-lifetime"+ ( [ testCase (label <> " throwing " <> kind <> " callback preserves native lifecycle") (throwingChild kind label)+ | label <- ["async", "sync"],+ kind <- ["error", "log", "stats", "rebalance", "commit"]+ ]+ <> [ testCase (label <> " error callback releases after destroy with retained wrapper") $ do+ (consumer, capture) <- consumerProbe env mode label (pure ())+ awaitCollected capture+ -- Keep the destroyed wrapper live through the collection assertion.+ C.closeConsumer consumer >>= (@?= Nothing)+ | (label, mode) <- [("async", C.CallbackPollModeAsync), ("sync", C.CallbackPollModeSync)]+ ]+ <> [ testCase "producer delivery callback releases after native finalization" $+ withTopic env "callback-owner-producer" 1 $ \topic _ ->+ producerProbe env topic >>= awaitCollected,+ testCase "noncaptured control is collectible" $ control >>= awaitCollected+ ]+ <> [ testCase (label <> " " <> kind <> " callback is live then releases") $ do+ (consumer, weak) <- consumerKindProbe env mode label kind (pure ())+ awaitCollected weak+ C.closeConsumer consumer >>= (@?= Nothing)+ | (label, mode) <- [("async", C.CallbackPollModeAsync), ("sync", C.CallbackPollModeSync)],+ kind <- ["log", "stats"]+ ]+ <> [ testCase (label <> " construction failure releases callbacks: " <> stage) $+ if stage == "redirect" || stage == "subscribe"+ then withCallbackTracking 0 $ do+ weak <- failedConsumerProbe env mode label stage+ ( do+ mapM callbackStat [1, 2, 3] >>= (@?= [1, 1, 1])+ callbackStat 8 >>= (@?= if mode == C.CallbackPollModeAsync then 1 else 0)+ )+ `finally` awaitCollected weak+ else failedConsumerProbe env mode label stage >>= awaitCollected+ | (label, mode) <- [("async", C.CallbackPollModeAsync), ("sync", C.CallbackPollModeSync)],+ stage <- ["topic", "native", "redirect", "subscribe"]+ ]+ <> [ testCase "producer native construction failure releases callbacks" $+ failedProducerProbe env >>= awaitCollected+ ]+ <> [ testCase (label <> " constructor exception at " <> stage <> " releases partial native ownership") $+ withCallbackTracking 0 $ do+ weak <- exceptionalConsumerProbe env mode label stage+ let created = if stage == "post-native-loglevel" then 1 else 0+ ( do+ mapM callbackStat [1, 2, 3] >>= (@?= replicate 3 created)+ callbackStat 8 >>= (@?= if created == 1 && mode == C.CallbackPollModeAsync then 1 else 0)+ )+ `finally` awaitCollected weak+ | (label, mode) <- [("async", C.CallbackPollModeAsync), ("sync", C.CallbackPollModeSync)],+ stage <- ["callback-install", "post-native-loglevel"]+ ]+ <> [ testCase (label <> " " <> kind <> " callback releases captured borrowed configuration") $+ withTopic env (Text.pack ("owner-" <> label <> "-" <> kind)) 1 $ \topic producer -> do+ produceTo producer topic 0 "owner-record"+ (consumer, weak) <- consumerStateProbe env mode label kind topic (pure ())+ awaitCollected weak+ C.closeConsumer consumer >>= (@?= Nothing)+ | (label, mode) <- [("async", C.CallbackPollModeAsync), ("sync", C.CallbackPollModeSync)],+ kind <- ["rebalance", "commit"]+ ]+ <> [ testCase "replaced producer delivery callbacks both release" $+ withTopic env "owner-replaced-delivery" 1 $ \topic _ -> do+ (first, second) <- replacedProducerProbe env topic+ awaitCollected first+ awaitCollected second+ ]+ <> [ testCase (label <> " concurrent destruction joins at " <> stage) $+ withCallbackTracking fault (destroyStage env mode label fault)+ | (label, mode) <- [("async", C.CallbackPollModeAsync), ("sync", C.CallbackPollModeSync)],+ (stage, fault) <- [("native entry", 3), ("native completion", 5), ("native shutdown callback", 6)]+ ]+ <> [ testCase (label <> " cancellation at " <> stage <> " preserves exactly-once teardown") $+ withCallbackTracking fault (cancelDestroyStage env mode label fault)+ | (label, mode) <- [("async", C.CallbackPollModeAsync), ("sync", C.CallbackPollModeSync)],+ (stage, fault) <- [("native entry", 3), ("native completion", 5), ("native shutdown callback", 6)]+ ]+ <> [ testCase "async cancellation after poll stop and queue detachment preserves teardown" $+ withCallbackTracking 4 (cancelDestroyStage env C.CallbackPollModeAsync "async-queue" 4)+ ]+ <> [ testCase (role <> " constructor cancellation at " <> stage <> " releases its owner") $+ withCallbackTracking fault $ do+ weak <- cancelledConstructor env role fault+ awaitCollected weak+ let created = if fault == 2 then 1 else 0+ callbackStat 1 >>= (@?= created)+ callbackStat 2 >>= (@?= created)+ callbackStat 3 >>= (@?= created)+ callbackStat 6 >>= (@?= 1)+ | role <- ["producer", "consumer-async", "consumer-sync"],+ (stage, fault) <- [("partial registration", 1), ("native acceptance", 2)]+ ]+ <> [ testCase (label <> " cancellation while waiting for active callback permits retry") $+ withCallbackTracking 0 (cancelWhilePolling env mode label)+ | (label, mode) <- [("async", C.CallbackPollModeAsync), ("sync", C.CallbackPollModeSync)]+ ]+ <> [ testCase (label <> " closed consumer GC releases its registrations once") $+ withCallbackTracking 0 $ do+ closedConsumerProbe env mode label >>= awaitCollected+ callbackStat 1 >>= (@?= 1)+ callbackStat 2 >>= (@?= 1)+ callbackStat 3 >>= (@?= 1)+ | (label, mode) <- [("async", C.CallbackPollModeAsync), ("sync", C.CallbackPollModeSync)]+ ]+ <> [ testCase ("producer " <> kind <> " callback remains live through close and releases on GC") $+ withCallbackTracking 0 $ do+ producerKindProbe env kind >>= awaitCollected+ callbackStat 1 >>= (@?= 1)+ callbackStat 2 >>= (@?= 1)+ callbackStat 3 >>= (@?= 1)+ | kind <- ["error", "log", "stats"]+ ]+ <> [ testCase "failed native construction releases the caller-owned duplicate config" $+ withCallbackTracking 0 $ do+ failedProducerProbe env >>= awaitCollected+ callbackStat 1 >>= (@?= 0)+ callbackStat 2 >>= (@?= 0)+ callbackStat 7 >>= (@?= 1)+ callbackStat 5 >>= (@?= 1)+ ]+ )++{-# NOINLINE control #-}+control :: IO (Weak (IORef Int))+control = newIORef 0 >>= \value -> mkWeakIORef value (pure ())++{-# NOINLINE consumerProbe #-}+consumerProbe :: TestEnv -> C.CallbackPollMode -> String -> IO () -> IO (C.KafkaConsumer, Weak (IORef Int))+consumerProbe env mode label after = do+ capture <- newIORef 0+ weak <- mkWeakIORef capture (pure ())+ called <- newEmptyMVar+ consumer <-+ C.newAssignedConsumer+ ( C.brokersList ["127.0.0.1:1"]+ <> C.groupId (makeGroupId env (Text.pack ("callback-owner-" <> label)))+ <> C.noAutoCommit+ <> C.callbackPollMode mode+ <> C.setCallback (C.errorCallback (\_ _ -> atomicModifyIORef' capture (\n -> (n + 1, ())) >> void (tryPutMVar called ()) >> after))+ )+ >>= either (assertFailure . show) pure+ flip finally (C.destroyConsumer consumer) $ do+ assertRetained weak+ awaitCalled consumer called+ readIORef capture >>= \count -> if count > 0 then pure () else assertFailure "native error callback never ran"+ pure (consumer, weak)++awaitCalled :: C.KafkaConsumer -> MVar () -> IO ()+awaitCalled consumer called = timeout 5000000 loop >>= maybe (assertFailure "native callback was not observed") pure+ where+ loop =+ tryReadMVar called >>= \case+ Just () -> pure ()+ Nothing -> C.pollConsumerEvents consumer (Just (C.Timeout 50)) >> loop++{-# NOINLINE producerProbe #-}+producerProbe :: TestEnv -> P.TopicName -> IO (Weak (IORef Int))+producerProbe env topic = do+ capture <- newIORef 0+ weak <- mkWeakIORef capture (pure ())+ producer <-+ P.newProducer+ (P.brokersList (teBrokers env) <> P.setCallback (P.deliveryCallback (\_ -> atomicModifyIORef' capture (\n -> (n + 1, ())))))+ >>= either (assertFailure . show) pure+ assertRetained weak+ sendMessages [P.ProducerRecord topic (P.SpecifiedPartition 0) Nothing (Just "callback-owner") mempty] producer+ >>= (@?= Right ())+ readIORef capture >>= (@?= 1)+ P.closeProducer producer+ -- Close flushes; it is not a destruction boundary.+ assertRetained weak+ P.flushProducerTimeout producer (P.Timeout 0) >>= (@?= Nothing)+ pure weak++{-# NOINLINE consumerKindProbe #-}+consumerKindProbe :: TestEnv -> C.CallbackPollMode -> String -> String -> IO () -> IO (C.KafkaConsumer, Weak (IORef Int))+consumerKindProbe env mode label kind after = do+ capture <- newIORef 0+ weak <- mkWeakIORef capture (pure ())+ called <- newEmptyMVar+ let observed = atomicModifyIORef' capture (\n -> (n + 1, ())) >> void (tryPutMVar called ()) >> after+ callback = if kind == "log" then C.logCallback (\_ _ _ -> observed) else C.statsCallback (const observed)+ extras = if kind == "log" then M.singleton "debug" "cgrp,topic" else M.singleton "statistics.interval.ms" "100"+ consumer <-+ C.newAssignedConsumer+ ( C.brokersList (teBrokers env)+ <> C.groupId (makeGroupId env (Text.pack ("owner-" <> label <> "-" <> kind)))+ <> C.noAutoCommit+ <> C.callbackPollMode mode+ <> C.extraProps extras+ <> C.setCallback callback+ )+ >>= either (assertFailure . show) pure+ flip finally (C.destroyConsumer consumer) $ do+ assertRetained weak+ awaitCalled consumer called+ readIORef capture >>= \count -> assertBool "native callback ran" (count > 0)+ C.closeConsumer consumer >>= (@?= Nothing)+ assertRetained weak+ pure (consumer, weak)++{-# NOINLINE failedConsumerProbe #-}+failedConsumerProbe :: TestEnv -> C.CallbackPollMode -> String -> String -> IO (Weak (IORef Int))+failedConsumerProbe env mode label stage = do+ capture <- newIORef 0+ weak <- mkWeakIORef capture (pure ())+ let props =+ C.brokersList (teBrokers env)+ <> (if stage == "redirect" then mempty else C.groupId (makeGroupId env (Text.pack ("owner-failure-" <> label <> "-" <> stage))))+ <> C.noAutoCommit+ <> C.callbackPollMode mode+ <> C.setCallback (C.errorCallback (\_ _ -> atomicModifyIORef' capture (\n -> (n + 1, ()))))+ invalid = C.extraProps (M.fromList [("security.protocol", "sasl_plaintext"), ("sasl.mechanism", "PLAIN")])+ sub = C.extraSubscriptionProps (M.singleton "__ownership.invalid" "x")+ result <- try @C.KafkaError $ case stage of+ "topic" -> C.newConsumer props sub+ "subscribe" -> C.newConsumer props (C.topics [C.TopicName ""])+ _ -> C.newAssignedConsumer (if stage == "native" then props <> invalid else props)+ case result of+ Left (C.KafkaUnknownConfigurationKey message)+ | stage == "topic" ->+ assertBool (Text.unpack message) ("__ownership.invalid" `Text.isInfixOf` message)+ Right (Left (C.KafkaError message))+ | stage == "native" ->+ assertBool (Text.unpack message) ("sasl.username and sasl.password must be set" `Text.isInfixOf` message)+ Right (Left (C.KafkaResponseError C.RdKafkaRespErrUnknownGroup))+ | stage == "redirect" -> pure ()+ Right (Left (C.KafkaResponseError C.RdKafkaRespErrInvalidArg))+ | stage == "subscribe" -> pure ()+ Right (Right consumer) -> C.destroyConsumer consumer >> assertFailure "invalid constructor succeeded"+ other -> assertFailure ("unexpected constructor result: " <> case other of Left e -> show e; Right (Left e) -> show e)+ pure weak++{-# NOINLINE exceptionalConsumerProbe #-}+exceptionalConsumerProbe :: TestEnv -> C.CallbackPollMode -> String -> String -> IO (Weak (IORef Int))+exceptionalConsumerProbe env mode label stage = do+ capture <- newIORef 0+ weak <- mkWeakIORef capture (pure ())+ let props = C.brokersList (teBrokers env) <> C.groupId (makeGroupId env (Text.pack ("constructor-exception-" <> label <> stage))) <> C.noAutoCommit <> C.callbackPollMode mode <> C.setCallback (C.errorCallback (\_ _ -> atomicModifyIORef' capture (\n -> (n + 1, ()))))+ injected = if stage == "callback-install" then props <> C.setCallback (error "controlled callback installation exception") else props <> C.logLevel (error "controlled post-native log-level exception")+ result <- try @SomeException (C.newAssignedConsumer injected)+ case result of+ Left exception -> assertBool (show exception) (case fromException exception :: Maybe ErrorCall of Just _ -> True; Nothing -> False)+ Right (Left err) -> assertFailure (show err)+ Right (Right consumer) -> releaseConsumer consumer >> assertFailure "injected constructor exception did not occur"+ pure weak++{-# NOINLINE failedProducerProbe #-}+failedProducerProbe :: TestEnv -> IO (Weak (IORef Int))+failedProducerProbe env = do+ capture <- newIORef 0+ weak <- mkWeakIORef capture (pure ())+ result <-+ P.newProducer+ ( P.brokersList (teBrokers env)+ <> P.extraProps (M.fromList [("security.protocol", "sasl_plaintext"), ("sasl.mechanism", "PLAIN")])+ <> P.setCallback (P.deliveryCallback (\_ -> atomicModifyIORef' capture (\n -> (n + 1, ()))))+ )+ case result of+ Left (P.KafkaError message) -> assertBool (Text.unpack message) ("sasl.username and sasl.password must be set" `Text.isInfixOf` message)+ Left other -> assertFailure (show other)+ Right producer -> releaseProducer producer >> assertFailure "invalid native producer succeeded"+ pure weak++{-# NOINLINE consumerStateProbe #-}+consumerStateProbe :: TestEnv -> C.CallbackPollMode -> String -> String -> C.TopicName -> IO () -> IO (C.KafkaConsumer, Weak (IORef (Maybe C.KafkaConsumer)))+consumerStateProbe env mode label kind topic after = do+ capture <- newIORef Nothing+ weak <- mkWeakIORef capture (pure ())+ events <- newIORef []+ called <- newEmptyMVar+ committed <- newEmptyMVar+ let onRebalance borrowed event = do+ writeIORef capture (Just borrowed)+ modifyIORef' events (<> [event])+ case event of+ C.RebalanceAssign _ -> void (tryPutMVar called ())+ _ -> pure ()+ after+ onCommit borrowed err partitions = do+ writeIORef capture (Just borrowed)+ void (tryPutMVar committed (err, partitions))+ void (tryPutMVar called ())+ after+ callback = if kind == "rebalance" then C.rebalanceCallback onRebalance else C.offsetCommitCallback onCommit+ props =+ C.brokersList (teBrokers env)+ <> C.groupId (makeGroupId env (Text.pack ("owner-state-" <> label <> "-" <> kind)))+ <> C.noAutoCommit+ <> C.callbackPollMode mode+ <> C.setCallback callback+ sub = if kind == "rebalance" then C.topics [topic] <> C.offsetReset C.Earliest else mempty+ consumer <- C.newConsumer props sub >>= either (assertFailure . show) pure+ flip finally (releaseConsumer consumer) $ do+ assertRetained weak+ if kind == "commit" then C.assign consumer [C.TopicPartition topic (C.PartitionId 0) (C.PartitionOffset 0)] >>= (@?= Nothing) else pure ()+ record <- C.pollMessage consumer (C.Timeout 10000) >>= either (assertFailure . show) pure+ (C.crTopic record, C.crPartition record, C.crOffset record, C.crValue record)+ @?= (topic, C.PartitionId 0, C.Offset 0, Just "owner-record")+ if kind == "commit" then C.commitOffsetMessage C.OffsetCommit consumer record >>= (@?= Nothing) else pure ()+ awaitCalled consumer called+ if kind == "commit"+ then readMVar committed >>= (@?= (C.KafkaResponseError C.RdKafkaRespErrNoError, [C.TopicPartition topic (C.PartitionId 0) (C.PartitionOffset 1)]))+ else readIORef events >>= (@?= [C.RebalanceBeforeAssign [(topic, C.PartitionId 0)], C.RebalanceAssign [(topic, C.PartitionId 0)]])+ C.closeConsumer consumer >>= (@?= Nothing)+ assertRetained weak+ if kind == "rebalance"+ then readIORef events >>= (@?= [C.RebalanceBeforeAssign [(topic, C.PartitionId 0)], C.RebalanceAssign [(topic, C.PartitionId 0)], C.RebalanceBeforeRevoke [(topic, C.PartitionId 0)], C.RebalanceRevoke [(topic, C.PartitionId 0)]])+ else pure ()+ pure (consumer, weak)++{-# NOINLINE replacedProducerProbe #-}+replacedProducerProbe :: TestEnv -> P.TopicName -> IO (Weak (IORef Int), Weak (IORef Int))+replacedProducerProbe env topic = do+ first <- newIORef 0+ second <- newIORef 0+ weakFirst <- mkWeakIORef first (pure ())+ weakSecond <- mkWeakIORef second (pure ())+ producer <-+ P.newProducer+ ( P.brokersList (teBrokers env)+ <> P.setCallback (P.deliveryCallback (\_ -> modifyIORef' first (+ 1)))+ <> P.setCallback (P.deliveryCallback (\_ -> modifyIORef' second (+ 1)))+ )+ >>= either (assertFailure . show) pure+ flip finally (releaseProducer producer) $ do+ assertRetained weakFirst+ assertRetained weakSecond+ sendMessages [P.ProducerRecord topic (P.SpecifiedPartition 0) Nothing (Just "replacement") mempty] producer >>= (@?= Right ())+ readIORef first >>= (@?= 0)+ readIORef second >>= (@?= 1)+ pure (weakFirst, weakSecond)++{-# NOINLINE trackedConsumer #-}+trackedConsumer :: TestEnv -> C.CallbackPollMode -> String -> IO (C.KafkaConsumer, Weak (IORef Int), MVar ())+trackedConsumer env mode label = do+ capture <- newIORef 0+ weak <- mkWeakIORef capture (pure ())+ called <- newEmptyMVar+ let callback _ facility _ = do+ atomicModifyIORef' capture (\n -> (n + 1, ()))+ if facility == "DESTROY" then void (tryPutMVar called ()) else pure ()+ consumer <-+ C.newAssignedConsumer+ ( C.brokersList (teBrokers env)+ <> C.groupId (makeGroupId env (Text.pack ("owner-destroy-" <> label)))+ <> C.noAutoCommit+ <> C.callbackPollMode mode+ <> C.extraProps (M.singleton "debug" "generic,topic,cgrp")+ <> C.setCallback (C.logCallback callback)+ )+ >>= either (assertFailure . show) pure+ pure (consumer, weak, called)++destroyStage :: TestEnv -> C.CallbackPollMode -> String -> Int -> IO ()+destroyStage env mode label fault = do+ (consumer, weak, logged) <- trackedConsumer env mode (label <> show fault)+ first <- newEmptyMVar+ void $ forkFinally (C.destroyConsumer consumer) (putMVar first)+ let awaitFinished =+ callbackStat 3 >>= \count ->+ if count == 1 then pure () else threadDelay 1000 >> awaitFinished+ finish = do+ releaseCallbackStage+ bounded (readMVar first) >>= either throwIO pure+ bounded awaitFinished+ awaitCollected weak+ flip finally finish $ do+ awaitCallbackStage+ callbackStat 1 >>= (@?= 1)+ callbackStat 2 >>= (@?= 1)+ callbackStat 3 >>= (@?= if fault == 5 then 1 else 0)+ if fault == 6 then bounded (readMVar logged) else pure ()+ assertRetained weak+ second <- newEmptyMVar+ secondThread <- forkFinally (C.destroyConsumer consumer) (putMVar second)+ flip finally (releaseCallbackStage >> bounded (readMVar second) >>= either throwIO pure) $ do+ let awaitBlocked =+ threadStatus secondThread >>= \status ->+ if status == ThreadBlocked BlockedOnMVar then pure () else threadDelay 1000 >> awaitBlocked+ bounded awaitBlocked+ tryReadMVar first >>= maybe (pure ()) (const (assertFailure "first destroy returned while native stage held"))+ tryReadMVar second >>= maybe (pure ()) (const (assertFailure "concurrent destroy returned while native stage held"))+ releaseCallbackStage+ bounded (readMVar first) >>= either throwIO pure+ bounded (readMVar second) >>= either throwIO pure+ awaitCollected weak+ callbackStat 2 >>= (@?= 1)+ callbackStat 3 >>= (@?= 1)+ callbackStat 4 >>= \count -> assertBool "real native shutdown called the Haskell log bridge" (count > 0)+ C.destroyConsumer consumer+ C.closeConsumer consumer >>= (@?= Nothing)+ callbackStat 2 >>= (@?= 1)++bounded :: IO a -> IO a+bounded action = timeout 10000000 action >>= maybe (assertFailure "callback lifetime stage timed out") pure++cancelDestroyStage :: TestEnv -> C.CallbackPollMode -> String -> Int -> IO ()+cancelDestroyStage env mode label fault = do+ (consumer, weak, _) <- trackedConsumer env mode (label <> "-cancel-" <> show fault)+ done <- newEmptyMVar+ worker <- forkUnmaskedFinally (C.destroyConsumer consumer) (putMVar done)+ flip finally (releaseCallbackStage >> bounded (readMVar done) >> C.destroyConsumer consumer) $ do+ awaitCallbackStage+ assertRetained weak+ if fault == 4 then callbackStat 8 >>= (@?= 1) else callbackStat 2 >>= (@?= 1)+ killed <- newEmptyMVar+ killer <- forkFinally (killThread worker) (putMVar killed)+ let awaitPending =+ threadStatus killer >>= \status ->+ if status == ThreadBlocked BlockedOnException then pure () else threadDelay 1000 >> awaitPending+ bounded awaitPending+ tryReadMVar done >>= maybe (pure ()) (const (assertFailure "destroy returned before cancellation stage released"))+ releaseCallbackStage+ result <- bounded (readMVar done)+ case result of+ Left exception -> (fromException exception :: Maybe AsyncException) @?= Just ThreadKilled+ Right () -> assertFailure "observed pending cancellation was not delivered"+ bounded (readMVar killed) >>= either throwIO pure+ C.destroyConsumer consumer+ awaitCollected weak+ callbackStat 1 >>= (@?= 1)+ callbackStat 2 >>= (@?= 1)+ callbackStat 3 >>= (@?= 1)+ C.closeConsumer consumer >>= (@?= Nothing)++-- Tasty may enter a case masked. Restore an explicitly unmasked worker rather+-- than inheriting the controller's masking state through forkFinally.+forkUnmaskedFinally :: IO a -> (Either SomeException a -> IO ()) -> IO ThreadId+forkUnmaskedFinally action completed = forkIOWithUnmask $ \unmask ->+ try @SomeException (unmask action) >>= completed++runInvalidAccessControl :: IO ()+runInvalidAccessControl = do+ putStrLn "native diagnostic negative control: reading a freed configuration"+ hFlush stdout+ _ <- invalidAccessControl+ die "Native invalid-access control returned without a sanitizer diagnosis"++{-# NOINLINE cancelledConstructor #-}+cancelledConstructor :: TestEnv -> String -> Int -> IO (Weak (IORef Int))+cancelledConstructor env role fault = do+ capture <- newIORef 0+ weak <- mkWeakIORef capture (pure ())+ let observed _ = atomicModifyIORef' capture (\n -> (n + 1, ()))+ construct+ | role == "producer" =+ P.newProducer+ (P.brokersList (teBrokers env) <> P.setCallback (P.statsCallback observed))+ >>= either throwIO releaseProducer+ | otherwise =+ C.newAssignedConsumer+ ( C.brokersList (teBrokers env)+ <> C.groupId (makeGroupId env (Text.pack ("owner-cancel-" <> role <> show fault)))+ <> C.noAutoCommit+ <> C.callbackPollMode (if role == "consumer-async" then C.CallbackPollModeAsync else C.CallbackPollModeSync)+ <> C.setCallback (C.statsCallback observed)+ )+ >>= either throwIO C.destroyConsumer+ done <- newEmptyMVar+ worker <- forkUnmaskedFinally construct (putMVar done)+ flip finally (releaseCallbackStage >> bounded (readMVar done) >> pure ()) $ do+ awaitCallbackStage+ assertRetained weak+ killed <- newEmptyMVar+ killer <- forkFinally (killThread worker) (putMVar killed)+ let awaitPending =+ threadStatus killer >>= \status ->+ if status == ThreadBlocked BlockedOnException then pure () else threadDelay 1000 >> awaitPending+ bounded awaitPending+ releaseCallbackStage+ bounded (readMVar done) >>= \case+ Left exception -> (fromException exception :: Maybe AsyncException) @?= Just ThreadKilled+ Right () -> assertFailure "constructor escaped an observed pending cancellation"+ bounded (readMVar killed) >>= either throwIO pure+ pure weak++{-# NOINLINE closedConsumerProbe #-}+closedConsumerProbe :: TestEnv -> C.CallbackPollMode -> String -> IO (Weak (IORef Int))+closedConsumerProbe env mode label = do+ (consumer, weak, _) <- trackedConsumer env mode (label <> "-closed-gc")+ C.closeConsumer consumer >>= (@?= Nothing)+ assertRetained weak+ callbackStat 2 >>= (@?= 0)+ C.consumerClosed consumer >>= (@?= True)+ pure weak++{-# NOINLINE producerKindProbe #-}+producerKindProbe :: TestEnv -> String -> IO (Weak (IORef Int))+producerKindProbe env kind = do+ capture <- newIORef 0+ weak <- mkWeakIORef capture (pure ())+ called <- newEmptyMVar+ let observed = atomicModifyIORef' capture (\n -> (n + 1, ())) >> void (tryPutMVar called ())+ callback = case kind of+ "log" -> P.logCallback (\_ _ _ -> observed)+ "stats" -> P.statsCallback (const observed)+ _ -> P.errorCallback (\_ _ -> observed)+ extras = if kind == "log" then M.singleton "debug" "generic" else M.singleton "statistics.interval.ms" "100"+ producer <-+ P.newProducer+ ( P.brokersList ["127.0.0.1:1"]+ <> P.sendTimeout (P.Timeout 1000)+ <> P.extraProps extras+ <> P.setCallback callback+ )+ >>= either (assertFailure . show) pure+ flip finally (releaseProducer producer) $ do+ let record = P.ProducerRecord (P.TopicName (prefixedName env (Text.pack ("owner-producer-" <> kind)))) P.UnassignedPartition Nothing (Just "pending") mempty+ P.produceMessage producer record >>= (@?= Nothing)+ let awaitEvent =+ tryReadMVar called >>= \case+ Just () -> pure ()+ Nothing -> do+ P.flushProducerTimeout producer (P.Timeout 100) >>= \case+ Nothing -> pure ()+ Just (P.KafkaResponseError P.RdKafkaRespErrTimedOut) -> pure ()+ Just err -> assertFailure (show err)+ awaitEvent+ bounded awaitEvent+ assertRetained weak+ P.purgeProducer producer [P.PurgeQueue, P.PurgeInFlight] >>= (@?= Nothing)+ P.flushProducerTimeout producer (P.Timeout 5000) >>= (@?= Nothing)+ P.closeProducer producer+ assertRetained weak+ pure weak++{-# NOINLINE lockedConsumer #-}+lockedConsumer :: TestEnv -> C.CallbackPollMode -> String -> IO (C.KafkaConsumer, Weak (IORef Int), MVar (), MVar ())+lockedConsumer env mode label = do+ capture <- newIORef 0+ weak <- mkWeakIORef capture (pure ())+ reached <- newEmptyMVar+ resume <- newEmptyMVar+ let onError _ _ = do+ atomicModifyIORef' capture (\n -> (n + 1, ()))+ void (tryPutMVar reached ())+ bounded (readMVar resume)+ consumer <-+ C.newAssignedConsumer+ ( C.brokersList ["127.0.0.1:1"]+ <> C.groupId (makeGroupId env (Text.pack ("owner-locked-" <> label)))+ <> C.noAutoCommit+ <> C.callbackPollMode mode+ <> C.setCallback (C.errorCallback onError)+ )+ >>= either (assertFailure . show) pure+ pure (consumer, weak, reached, resume)++cancelWhilePolling :: TestEnv -> C.CallbackPollMode -> String -> IO ()+cancelWhilePolling env mode label = do+ (consumer, weak, reached, resume) <- lockedConsumer env mode label+ polled <- newEmptyMVar+ let pollUntilReached =+ tryReadMVar reached >>= \case+ Just () -> pure ()+ Nothing -> C.pollConsumerEvents consumer (Just (C.Timeout 100)) >> pollUntilReached+ release = void (tryPutMVar resume ())+ void $ forkUnmaskedFinally pollUntilReached (putMVar polled)+ flip finally (release >> bounded (readMVar polled) >> C.destroyConsumer consumer) $ do+ bounded (readMVar reached)+ done <- newEmptyMVar+ worker <- forkUnmaskedFinally (C.destroyConsumer consumer) (putMVar done)+ let awaitBlocked =+ threadStatus worker >>= \status ->+ if status == ThreadBlocked BlockedOnMVar then pure () else threadDelay 1000 >> awaitBlocked+ bounded awaitBlocked+ killThread worker+ bounded (readMVar done) >>= \case+ Left exception -> (fromException exception :: Maybe AsyncException) @?= Just ThreadKilled+ Right () -> assertFailure "destroy did not wait for the active callback"+ callbackStat 2 >>= (@?= 0)+ assertRetained weak+ release+ bounded (readMVar polled) >>= either throwIO pure+ C.destroyConsumer consumer+ awaitCollected weak+ callbackStat 2 >>= (@?= 1)+ callbackStat 3 >>= (@?= 1)+ C.closeConsumer consumer >>= (@?= Nothing)++-- Foreign-boundary failures and the process-wide exception handler are isolated.+throwingChild :: String -> String -> IO ()+throwingChild kind label = do+ executable <- getExecutablePath+ environment <- getEnvironment+ directory <- maybe "dist-callback-probes" id <$> lookupEnv "RDKAFKA_TEST_CHILD_HPC_DIR"+ createDirectoryIfMissing True directory+ nonce <- randomIO :: IO Word+ let output = directory <> "/lifetime-" <> kind <> "-" <> label <> "-" <> show nonce <> ".tix"+ process =+ (proc executable ["--lifetime-callback-probe", kind, label, "+RTS", "--read-tix-file=no", "-RTS"])+ { env = Just (("HPCTIXFILE", output) : filter ((/= "HPCTIXFILE") . fst) environment)+ }+ result <- timeout 20000000 (readCreateProcessWithExitCode process "")+ case result of+ Just (ExitSuccess, _, _) -> pure ()+ other -> assertFailure ("callback lifetime child failed: " <> show other)++runThrowingProbe :: String -> String -> IO ()+runThrowingProbe kind label = do+ brokers <- lookupEnv "RDKAFKA_TEST_BROKER" >>= either die pure . resolveBrokers+ testEnv <- newTestEnv brokers+ reported <- newEmptyMVar+ callbackThreads <- newIORef []+ let marker = "lifetime-throw-" <> kind+ after = do+ callbackThread <- myThreadId+ atomicModifyIORef' callbackThreads (\threads -> (callbackThread : threads, ()))+ throwIO (userError marker)+ mode = if label == "async" then C.CallbackPollModeAsync else C.CallbackPollModeSync+ bracket getUncaughtExceptionHandler setUncaughtExceptionHandler $ \_ -> do+ setUncaughtExceptionHandler $ \exception -> do+ reportingThread <- myThreadId+ void (tryPutMVar reported (show exception, reportingThread))+ let finish :: (C.KafkaConsumer, Weak a) -> IO ()+ finish (consumer, weak) = do+ (exception, reportingThread) <- bounded (readMVar reported)+ assertBool exception (marker `isInfixOf` exception)+ nativeThreads <- readIORef callbackThreads+ assertBool "exception reported on a separate Haskell thread" (reportingThread `notElem` nativeThreads)+ awaitCollected weak+ C.closeConsumer consumer >>= (@?= Nothing)+ case kind of+ "error" -> consumerProbe testEnv mode label after >>= finish+ "log" -> consumerKindProbe testEnv mode label kind after >>= finish+ "stats" -> consumerKindProbe testEnv mode label kind after >>= finish+ _ -> withTopic testEnv (Text.pack ("throw-" <> label <> "-" <> kind)) 1 $ \topic producer -> do+ produceTo producer topic 0 "owner-record"+ consumerStateProbe testEnv mode label kind topic after >>= finish
+ test-integration/Kafka/Integration/ConfigStringContractTest.hs view
@@ -0,0 +1,62 @@+module Kafka.Integration.ConfigStringContractTest (tests) where++import Control.Exception (bracket, throwIO, try)+import Data.Map.Strict qualified as M+import Data.Text qualified as Text+import Kafka.Consumer qualified as C+import Kafka.Dump (dumpKafkaConf)+import Kafka.Producer qualified as P+import Kafka.TestEnv+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.HUnit (assertBool, assertFailure, testCase, (@?=))++tests :: TestEnv -> TestTree+tests env =+ testGroup "config-strings" $+ [ testCase ("producer global rejects " <> label) $+ rejected (P.newProducer (P.brokersList (teBrokers env) <> P.extraProp key value)) releaseProducer+ | (label, key, value) <- globalInvalid+ ]+ <> [ testCase ("producer topic rejects " <> label) $+ rejected (P.newProducer (P.brokersList (teBrokers env) <> P.extraTopicProps (M.singleton key value))) releaseProducer+ | (label, key, value) <- [("NUL key", "message.timeout.ms\0ignored", "5000"), ("NUL value", "message.timeout.ms", "5000\0ignored")]+ ]+ <> [ testCase (label <> " consumer global rejects " <> field) $+ rejected (C.newAssignedConsumer (base label mode <> C.extraProp key value)) releaseConsumer+ | (label, mode) <- modes,+ (field, key, value) <- globalInvalid+ ]+ <> [ testCase (label <> " subscription rejects " <> field) $+ rejected (C.newConsumer (base label mode) (C.extraSubscriptionProps (M.singleton key value))) releaseConsumer+ | (label, mode) <- modes,+ (field, key, value) <- [("NUL key", "auto.offset.reset\0ignored", "earliest"), ("NUL value", "auto.offset.reset", "earliest\0ignored")]+ ]+ <> [ testCase "empty producer client id retains the native default" $+ bracket (P.newProducer (P.brokersList (teBrokers env) <> P.extraProp "client.id" "") >>= either throwIO pure) releaseProducer $ \producer -> do+ config <- dumpKafkaConf producer+ M.lookup "client.id" config @?= Just "rdkafka",+ testCase "consumer ordinary UTF8 values remain exact" $+ bracket (C.newAssignedConsumer (base "ordinary" C.CallbackPollModeSync <> C.extraProp "client.id" "配置-λ") >>= either throwIO pure) releaseConsumer $ \consumer -> do+ config <- dumpKafkaConf consumer+ M.lookup "client.id" config @?= Just "配置-λ",+ testCase "empty global key retains native unknown-key rejection" $ do+ result <- try @C.KafkaError (P.newProducer (P.brokersList (teBrokers env) <> P.extraProp "" "value"))+ case result of+ Left (C.KafkaUnknownConfigurationKey _) -> pure ()+ Left failure -> assertFailure (show failure)+ Right (Left failure) -> assertFailure (show failure)+ Right (Right producer) -> releaseProducer producer >> assertFailure "empty key was accepted"+ ]+ where+ base label mode = C.brokersList (teBrokers env) <> C.groupId (makeGroupId env ("config-string-" <> Text.pack label)) <> C.callbackPollMode mode+ modes = [("async", C.CallbackPollModeAsync), ("sync", C.CallbackPollModeSync)]+ globalInvalid = [("NUL key", "client.id\0ignored", "client"), ("NUL value", "client.id", "client\0ignored")]++rejected :: IO (Either C.KafkaError a) -> (a -> IO ()) -> IO ()+rejected action release = do+ result <- try @C.KafkaError action+ case result of+ Left (C.KafkaInvalidConfigurationValue message) -> assertBool (show message) ("NUL" `Text.isInfixOf` message)+ Left failure -> assertFailure (show failure)+ Right (Left failure) -> assertFailure (show failure)+ Right (Right client) -> release client >> assertFailure "configuration silently accepted a NUL prefix"
+ test-integration/Kafka/Integration/ConfigurationTest.hs view
@@ -0,0 +1,40 @@+-- | Broker selection is checked before any client exists, so these tests need+-- no network access.+module Kafka.Integration.ConfigurationTest+ ( tests,+ )+where++import Data.Either (isLeft)+import Kafka.Consumer (BrokerAddress (..))+import Kafka.TestEnv (resolveBrokers)+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.HUnit (assertBool, testCase, (@?=))++tests :: TestTree+tests =+ testGroup+ "configuration"+ [ testCase "defaults to the private broker" $+ resolveBrokers Nothing @?= Right [BrokerAddress "127.0.0.1:39092"],+ testCase "accepts another private endpoint" $+ resolveBrokers (Just "127.0.0.1:1") @?= Right [BrokerAddress "127.0.0.1:1"],+ testCase "accepts a list of private endpoints" $+ resolveBrokers (Just "127.0.0.1:39092, 127.0.0.1:39093")+ @?= Right [BrokerAddress "127.0.0.1:39092", BrokerAddress "127.0.0.1:39093"],+ testCase "rejects an empty value" $+ assertRejected "",+ testCase "rejects localhost:9092" $+ assertRejected "localhost:9092",+ testCase "rejects 127.0.0.1:9092" $+ assertRejected "127.0.0.1:9092",+ testCase "rejects [::1]:9092" $+ assertRejected "[::1]:9092",+ testCase "rejects a loopback host without a port" $+ assertRejected "localhost",+ testCase "rejects the shared broker anywhere in a list" $+ assertRejected "127.0.0.1:39092,LOCALHOST:9092"+ ]+ where+ assertRejected value =+ assertBool ("expected " <> show value <> " to be rejected") (isLeft (resolveBrokers (Just value)))
+ test-integration/Kafka/Integration/ConsumerCommitContractTest.hs view
@@ -0,0 +1,167 @@+module Kafka.Integration.ConsumerCommitContractTest (tests) where++import Control.Concurrent (threadDelay)+import Control.Concurrent.MVar (MVar, newEmptyMVar, tryPutMVar, tryTakeMVar)+import Control.Exception (bracket, throwIO)+import Control.Monad (forM_, void)+import Data.List (find, sort)+import Data.Map.Strict qualified as Map+import Data.Text qualified as Text+import Data.Text.Encoding qualified as TE+import Kafka.Consumer+import Kafka.ConsumerStateSupport (commitObservation, withStateFault)+import Kafka.TestEnv+import System.Timeout (timeout)+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.HUnit (assertFailure, testCase, (@?=))++tests :: TestEnv -> TestTree+tests env =+ testGroup "consumer-commit" $+ [ testCase (label <> " commit modes preserve native flags callback offsets and broker state") $+ withTopic env (Text.pack ("commit-modes-" <> label)) 1 $ \topic producer -> do+ produceTo producer topic 0 "commit-record"+ events <- newEmptyMVar+ let props =+ brokersList (teBrokers env)+ <> groupId (makeGroupId env (Text.pack ("commit-modes-" <> label)))+ <> noAutoCommit+ <> noAutoOffsetStore+ <> callbackPollMode mode+ <> setCallback+ ( offsetCommitCallback+ ( \consumer reportedError partitions -> do+ assignment consumer >>= (@?= Right (Map.singleton topic [PartitionId 0]))+ void (tryPutMVar events (reportedError, partitions))+ )+ )+ part offset = TopicPartition topic (PartitionId 0) (PartitionOffset offset)+ withStateFault 0 $+ bracket (newAssignedConsumer props >>= either throwIO pure) releaseConsumer $ \consumer -> do+ assign consumer [part 0] >>= (@?= Nothing)+ record <- pollMessage consumer (Timeout 10000) >>= either throwIO pure+ (crTopic record, crOffset record, crValue record) @?= (topic, Offset 0, Just "commit-record")+ commitOffsetMessage OffsetCommitAsync consumer record >>= (@?= Nothing)+ commitObservation >>= (@?= (1, 1))+ awaitCommit consumer events >>= (@?= (KafkaResponseError RdKafkaRespErrNoError, [part 1]))+ committed consumer (Timeout 5000) [(topic, PartitionId 0)] >>= (@?= Right [part 1])+ commitPartitionsOffsets OffsetCommitAsync consumer [part 0] >>= (@?= Nothing)+ commitObservation >>= (@?= (2, 1))+ awaitCommit consumer events >>= (@?= (KafkaResponseError RdKafkaRespErrNoError, [part 0]))+ committed consumer (Timeout 5000) [(topic, PartitionId 0)] >>= (@?= Right [part 0])+ storeOffsets consumer [part 1] >>= (@?= Nothing)+ commitAllOffsets OffsetCommitAsync consumer >>= (@?= Nothing)+ commitObservation >>= (@?= (3, 1))+ awaitCommit consumer events >>= (@?= (KafkaResponseError RdKafkaRespErrNoError, [part 1]))+ committed consumer (Timeout 5000) [(topic, PartitionId 0)] >>= (@?= Right [part 1])+ commitPartitionsOffsets OffsetCommit consumer [part 2] >>= (@?= Nothing)+ commitObservation >>= (@?= (4, 0))+ awaitCommit consumer events >>= (@?= (KafkaResponseError RdKafkaRespErrNoError, [part 2]))+ committed consumer (Timeout 5000) [(topic, PartitionId 0)] >>= (@?= Right [part 2])+ | (label, mode) <- [("async", CallbackPollModeAsync), ("sync", CallbackPollModeSync)]+ ]+ <> multiPartitionCommitTests env+ <> emptyCommitTests env+ <> mixedCommitTests env+ <> timeoutCommitTests env++emptyCommitTests :: TestEnv -> [TestTree]+emptyCommitTests env =+ [ testCase (label <> " empty commit requests preserve no-offset callbacks") $+ withTopic env (Text.pack ("commit-empty-" <> label)) 1 $ \_ _ -> do+ events <- newEmptyMVar+ let props = brokersList (teBrokers env) <> groupId (makeGroupId env (Text.pack ("commit-empty-" <> label))) <> noAutoCommit <> noAutoOffsetStore <> callbackPollMode mode <> setCallback (offsetCommitCallback (\_ reportedError partitions -> void (tryPutMVar events (reportedError, partitions))))+ noOffset = KafkaResponseError RdKafkaRespErrNoOffset+ withStateFault 0 $+ bracket (newAssignedConsumer props >>= either throwIO pure) releaseConsumer $ \consumer -> do+ committed consumer (Timeout 5000) [] >>= (@?= Right [])+ commitPartitionsOffsets OffsetCommit consumer [] >>= (@?= Just noOffset)+ awaitCommit consumer events >>= (@?= (noOffset, []))+ commitAllOffsets OffsetCommit consumer >>= (@?= Just noOffset)+ awaitCommit consumer events >>= (@?= (noOffset, []))+ commitPartitionsOffsets OffsetCommitAsync consumer [] >>= (@?= Nothing)+ commitObservation >>= (@?= (3, 1))+ awaitCommit consumer events >>= (@?= (noOffset, []))+ | (label, mode) <- [("async", CallbackPollModeAsync), ("sync", CallbackPollModeSync)]+ ]++mixedCommitTests :: TestEnv -> [TestTree]+mixedCommitTests env =+ [ testCase (label <> " mixed broker commit failures preserve successful offsets") $+ withTopic env (Text.pack ("commit-mixed-" <> label)) 1 $ \topic producer -> do+ produceTo producer topic 0 "commit-record"+ events <- newEmptyMVar+ let props = brokersList (teBrokers env) <> groupId (makeGroupId env (Text.pack ("commit-mixed-" <> label))) <> noAutoCommit <> noAutoOffsetStore <> callbackPollMode mode <> setCallback (offsetCommitCallback (\_ reportedError partitions -> void (tryPutMVar events (reportedError, partitions))))+ part partition offset = TopicPartition topic (PartitionId partition) (PartitionOffset offset)+ failure = KafkaResponseError RdKafkaRespErrUnknownTopicOrPart+ bracket (newAssignedConsumer props >>= either throwIO pure) releaseConsumer $ \consumer -> do+ assign consumer [part 0 0] >>= (@?= Nothing)+ _ <- pollMessage consumer (Timeout 10000) >>= either throwIO pure+ commitPartitionsOffsets OffsetCommit consumer [part 0 1, part 42 9] >>= (@?= Just failure)+ awaitCommit consumer events >>= (@?= (failure, [part 0 1, part 42 9]))+ committed consumer (Timeout 5000) [(topic, PartitionId 0)] >>= (@?= Right [part 0 1])+ committed consumer (Timeout 5000) [(topic, PartitionId 0), (topic, PartitionId 42)] >>= (@?= Right [part 0 1, TopicPartition topic (PartitionId 42) PartitionOffsetInvalid])+ | (label, mode) <- [("async", CallbackPollModeAsync), ("sync", CallbackPollModeSync)]+ ]++timeoutCommitTests :: TestEnv -> [TestTree]+timeoutCommitTests env =+ [ testCase (label <> " committed query preserves an unavailable coordinator timeout") $+ bracket (newAssignedConsumer (brokersList ["127.0.0.1:1"] <> groupId (makeGroupId env (Text.pack ("commit-timeout-" <> label))) <> noAutoCommit <> callbackPollMode mode <> extraProp "log_level" "0") >>= either throwIO pure) releaseConsumer $ \consumer -> do+ committed consumer (Timeout 200) [(TopicName (prefixedName env "commit-timeout"), PartitionId 0)] >>= (@?= Left (KafkaResponseError RdKafkaRespErrTimedOut))+ | (label, mode) <- [("async", CallbackPollModeAsync), ("sync", CallbackPollModeSync)]+ ]++awaitCommit :: KafkaConsumer -> MVar (KafkaError, [TopicPartition]) -> IO (KafkaError, [TopicPartition])+awaitCommit consumer events = timeout 10000000 loop >>= maybe (assertFailure "commit callback timed out") pure+ where+ loop =+ tryTakeMVar events >>= \case+ Just result -> pure result+ Nothing -> do+ pollMessage consumer (Timeout 50) >>= \case+ Left (KafkaResponseError RdKafkaRespErrTimedOut) -> pure ()+ Left failure -> throwIO failure+ Right record -> assertFailure ("unexpected extra record while awaiting callback: " <> show record)+ threadDelay 1000+ loop++multiPartitionCommitTests :: TestEnv -> [TestTree]+multiPartitionCommitTests env =+ [ testCase (label <> " message and stored commits preserve unrelated partition offsets") $+ withTopic env (Text.pack ("commit-multiple-" <> label)) 2 $ \topic producer -> do+ forM_ [0, 1] $ \partition -> forM_ [0 .. 2 :: Int] $ \offset -> produceTo producer topic partition (TE.encodeUtf8 (Text.pack (show (partition, offset))))+ events <- newEmptyMVar+ let props = brokersList (teBrokers env) <> groupId (makeGroupId env (Text.pack ("commit-multiple-" <> label))) <> noAutoCommit <> noAutoOffsetStore <> callbackPollMode mode <> setCallback (offsetCommitCallback (\_ err partitions -> void (tryPutMVar events (err, partitions))))+ part partition offset = TopicPartition topic (PartitionId partition) (PartitionOffset offset)+ report consumer expected = awaitCommit consumer events >>= (@?= (KafkaResponseError RdKafkaRespErrNoError, expected))+ query consumer expected = committed consumer (Timeout 5000) [(topic, PartitionId 0), (topic, PartitionId 1)] >>= (@?= Right expected)+ bracket (newAssignedConsumer props >>= either throwIO pure) releaseConsumer $ \consumer -> do+ assign consumer [part 0 0, part 1 0] >>= (@?= Nothing)+ records <- receiveMessages consumer 6 >>= either throwIO pure+ sort [(crPartition r, crOffset r) | r <- records] @?= [(PartitionId p, Offset n) | p <- [0, 1], n <- [0 .. 2]]+ let record p n = maybe (assertFailure "expected source record is absent") pure (find (\r -> crPartition r == PartitionId p && crOffset r == Offset n) records)+ record 0 0 >>= commitOffsetMessage OffsetCommit consumer >>= (@?= Nothing)+ report consumer [part 0 1]+ query consumer [part 0 1, TopicPartition topic (PartitionId 1) PartitionOffsetInvalid]+ record 1 1 >>= commitOffsetMessage OffsetCommitAsync consumer >>= (@?= Nothing)+ report consumer [part 1 2]+ query consumer [part 0 1, part 1 2]+ record 0 2 >>= storeOffsetMessage consumer >>= (@?= Nothing)+ commitAllOffsets OffsetCommit consumer >>= (@?= Nothing)+ report consumer [part 0 3, TopicPartition topic (PartitionId 1) PartitionOffsetInvalid]+ query consumer [part 0 3, part 1 2]+ record 1 0 >>= storeOffsetMessage consumer >>= (@?= Nothing)+ commitAllOffsets OffsetCommit consumer >>= (@?= Just (KafkaResponseError RdKafkaRespErrNoOffset))+ awaitCommit consumer events >>= (@?= (KafkaResponseError RdKafkaRespErrNoOffset, [TopicPartition topic (PartitionId p) PartitionOffsetInvalid | p <- [0, 1]]))+ query consumer [part 0 3, part 1 2]+ record 1 2 >>= storeOffsetMessage consumer >>= (@?= Nothing)+ commitAllOffsets OffsetCommit consumer >>= (@?= Nothing)+ report consumer [TopicPartition topic (PartitionId 0) PartitionOffsetInvalid, part 1 3]+ query consumer [part 0 3, part 1 3]+ storeOffsets consumer [part 0 4, part 1 5] >>= (@?= Nothing)+ commitAllOffsets OffsetCommitAsync consumer >>= (@?= Nothing)+ report consumer [part 0 4, part 1 5]+ query consumer [part 0 4, part 1 5]+ | (label, mode) <- [("async", CallbackPollModeAsync), ("sync", CallbackPollModeSync)]+ ]
+ test-integration/Kafka/Integration/ConsumerPropertyTest.hs view
@@ -0,0 +1,110 @@+module Kafka.Integration.ConsumerPropertyTest (tests) where++import Control.Concurrent.MVar (newEmptyMVar, tryPutMVar, tryReadMVar)+import Control.Exception (bracket, finally, throwIO)+import Control.Monad (void)+import Data.Int (Int64)+import Data.Text qualified as Text+import Kafka.Consumer+import Kafka.FixtureSupport (acquirePair)+import Kafka.Producer qualified as P+import Kafka.PropertySupport+import Kafka.TestEnv (TestEnv, makeGroupId, produceTo, releaseConsumer, releaseProducer, teBrokers, withTopic)+import Kafka.Transaction qualified as T+import Kafka.TransactionTestSupport+import System.Mem (performMajorGC)+import System.Timeout (timeout)+import Test.Tasty (TestTree, withResource)+import Test.Tasty.HUnit (assertFailure, testCase, (@?=))+import Test.Tasty.QuickCheck qualified as QC++tests :: TestEnv -> TestTree+tests testEnv =+ generatedGroup+ "consumer-properties"+ $ [ QC.testProperty "consumer callback composition preserves registration order and identity" $+ QC.forAllShrink programs shrinkPrograms $ \input@(a, b, c, leftAssociated, mode) -> QC.ioProperty $ do+ result <- observe a b c leftAssociated mode+ performMajorGC+ let labels = a <> b <> c+ expected = case reverse labels of [] -> Nothing; value : _ -> Just value+ pure (QC.counterexample (show input) (result QC.=== (length labels, expected))),+ withResource offsetClients releaseOffsetClients $ \clients ->+ QC.testProperty "generated source offsets reach native code as the representable next position" $+ QC.forAllShrink nextOffset (filter (>= 0) . QC.shrink) $ \n -> QC.ioProperty $ do+ (producer, consumer) <- clients+ withTxFault 100 $ do+ let message = ConsumerRecord (TopicName "generated-source-offset") (PartitionId 0) (Offset n) NoTimestamp mempty () ()+ result <- T.commitOffsetMessageTransaction producer consumer message (Timeout 1000)+ actualOffset <- txStat 12+ created <- txStat 0+ destroyed <- txStat 1+ metadata <- txStat 6+ freedMetadata <- txStat 7+ afterFree <- txStat 8+ pure $+ (fmap T.getKafkaError result, actualOffset, created, destroyed, metadata, freedMetadata, afterFree)+ QC.=== (Just (KafkaResponseError RdKafkaRespErrState), n + 1, 1, 1, 1, 1, 0)+ ]+ <> [ testCase (label <> " later subscription reset reaches the native consumer") $+ withTopic testEnv (Text.pack ("subscription-last-" <> label)) 1 $ \topic producer -> do+ produceTo producer topic 0 "existing"+ let props = brokersList (teBrokers testEnv) <> groupId (makeGroupId testEnv (Text.pack ("subscription-last-" <> label))) <> noAutoCommit <> callbackPollMode mode+ bracket (newConsumer props (topics [topic] <> offsetReset Latest <> offsetReset Earliest) >>= either throwIO pure) releaseConsumer $ \consumer -> do+ record <- pollMessage consumer (Timeout 10000) >>= either throwIO pure+ (crOffset record, crValue record) @?= (Offset 0, Just "existing")+ | (label, mode) <- [("async", CallbackPollModeAsync), ("sync", CallbackPollModeSync)]+ ]++-- Public records consumed from Kafka have nonnegative offsets; generation is+-- restricted to offsets whose next position fits the native signed field.+nextOffset :: QC.Gen Int64+nextOffset = QC.frequency [(1, QC.elements [0, 1, maxBound - 1]), (4, QC.choose (0, maxBound - 1))]++offsetClients :: IO (P.KafkaProducer, KafkaConsumer)+offsetClients =+ acquirePair+ (P.newProducer (P.brokersList ["127.0.0.1:1"] <> P.extraProp "log_level" "0") >>= either throwIO pure)+ releaseProducer+ (newAssignedConsumer (brokersList ["127.0.0.1:1"] <> groupId "generated-offset-unused-group" <> callbackPollMode CallbackPollModeSync <> extraProp "log_level" "0") >>= either throwIO pure)++releaseOffsetClients :: (P.KafkaProducer, KafkaConsumer) -> IO ()+releaseOffsetClients (producer, consumer) = destroyConsumer consumer `finally` releaseProducer producer++programs :: QC.Gen ([Int], [Int], [Int], Bool, CallbackPollMode)+programs = (,,,,) <$> labels <*> labels <*> labels <*> QC.arbitrary <*> QC.elements [CallbackPollModeAsync, CallbackPollModeSync]+ where+ labels = boundedList 6 (QC.choose (0, 5))++shrinkPrograms :: ([Int], [Int], [Int], Bool, CallbackPollMode) -> [([Int], [Int], [Int], Bool, CallbackPollMode)]+shrinkPrograms (a, b, c, association, mode) =+ [(a', b, c, association, mode) | a' <- QC.shrinkList QC.shrink a]+ <> [(a, b', c, association, mode) | b' <- QC.shrinkList QC.shrink b]+ <> [(a, b, c', association, mode) | c' <- QC.shrinkList QC.shrink c]+ <> [(a, b, c, False, mode) | association]++{-# NOINLINE observe #-}+observe :: [Int] -> [Int] -> [Int] -> Bool -> CallbackPollMode -> IO (Int, Maybe Int)+observe a b c association mode = do+ called <- newEmptyMVar+ let callback label = logCallback (\_ _ _ -> void (tryPutMVar called label))+ callbacks = foldMap (setCallback . callback . Just)+ p = callbacks a+ q = callbacks b+ r = callbacks c+ composed = if association then ((p <> mempty) <> q) <> r else p <> (mempty <> (q <> r))+ props =+ brokersList [BrokerAddress "127.0.0.1:1"]+ <> groupId (ConsumerGroupId "consumer-property-unused-group")+ <> extraProp "debug" "generic"+ <> extraProp "log_level" "7"+ <> callbackPollMode mode+ <> setCallback (callback Nothing)+ <> composed+ bracket (newAssignedConsumer props >>= either throwIO pure) destroyConsumer $ \consumer -> do+ let poll =+ tryReadMVar called >>= \case+ Just value -> pure value+ Nothing -> pollConsumerEvents consumer (Just (Timeout 50)) >> poll+ label <- timeout 5000000 poll >>= maybe (assertFailure "generated consumer callback did not run") pure+ pure (length (cpCallbacks composed), label)
+ test-integration/Kafka/Integration/ConsumerStateContractTest.hs view
@@ -0,0 +1,330 @@+{-# OPTIONS_GHC -Wno-deprecations #-}++module Kafka.Integration.ConsumerStateContractTest (tests) where++import Control.Concurrent.MVar (newEmptyMVar, readMVar, tryPutMVar)+import Control.Exception (bracket, throwIO)+import Control.Monad (forM_, void)+import Data.ByteString.Char8 qualified as BS+import Data.List (sort)+import Data.Map.Strict qualified as M+import Data.Text qualified as Text+import Kafka.Consumer+import Kafka.ConsumerStateSupport (triggerCooperative, withStateFault)+import Kafka.MessageTestSupport (messageStat, withMessageFault)+import Kafka.Producer qualified as P+import Kafka.TestEnv+import System.Timeout (timeout)+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.HUnit (assertBool, assertFailure, testCase, (@?=))++tests :: TestEnv -> TestTree+tests env =+ testGroup "consumer-state" $+ [ testGroup label $+ [ scenario "assignment-replacement" $ \topic consumer -> do+ subscription consumer >>= (@?= Right [])+ assignment consumer >>= (@?= Right M.empty)+ assign consumer [part topic 0 (PartitionOffset 0)] >>= (@?= Nothing)+ record consumer topic 0 0+ assign consumer [part topic 1 (PartitionOffset 1)] >>= (@?= Nothing)+ assignment consumer >>= (@?= Right (M.singleton topic [PartitionId 1]))+ record consumer topic 1 1+ assign consumer [] >>= (@?= Nothing)+ assignment consumer >>= (@?= Right M.empty)+ pollMessage consumer (Timeout 100) >>= (@?= Left (KafkaResponseError RdKafkaRespErrTimedOut)),+ testCase "unknown-assignment-reports-through-error-callback-and-recovers" $+ withTopic env (Text.pack ("state-" <> label <> "-unknown-assignment")) 1 $ \topic producer -> do+ produceTo producer topic 0 "recovered"+ events <- newEmptyMVar+ let props = base "unknown-assignment" <> setCallback (errorCallback (\err reason -> void (tryPutMVar events (err, reason))))+ bracket (newAssignedConsumer props >>= either throwIO pure) releaseConsumer $ \consumer -> do+ assign consumer [part topic 42 (PartitionOffset 0)] >>= (@?= Nothing)+ assignment consumer >>= (@?= Right (M.singleton topic [PartitionId 42]))+ pollMessage consumer (Timeout 1000) >>= (@?= Left (KafkaResponseError RdKafkaRespErrTimedOut))+ timeout 5000000 (readMVar events) >>= \case+ Just (err, reason) -> do+ err @?= KafkaResponseError RdKafkaRespErrUnknownPartition+ assertBool reason (unTopicName topic `Text.isInfixOf` Text.pack reason)+ Nothing -> assertFailure "missing native assignment error callback"+ assignmentLost consumer >>= (@?= False)+ assign consumer [part topic 0 (PartitionOffset 0)] >>= (@?= Nothing)+ message <- pollMessage consumer (Timeout 10000) >>= either throwIO pure+ (crTopic message, crPartition message, crOffset message, crValue message) @?= (topic, PartitionId 0, Offset 0, Just "recovered"),+ scenario "representable-partition-boundaries-keep-native-query-semantics" $ \topic consumer -> do+ let requested = [TopicPartition topic (PartitionId p) PartitionOffsetInvalid | p <- [-2147483648, 2147483647]]+ position consumer [(tpTopicName p, tpPartition p) | p <- requested] >>= (@?= Right requested),+ scenario "deprecated-seek-reports-unassigned-state-and-recovers-after-assignment" $ \topic consumer -> do+ assign consumer [part topic 0 (PartitionOffset 0)] >>= (@?= Nothing)+ record consumer topic 0 0+ observed <- assignment consumer+ observed @?= Right (M.singleton topic [PartitionId 0])+ assign consumer [] >>= (@?= Nothing)+ -- The earlier successful query does not establish seek's later+ -- active-fetcher precondition; preserve the native State response.+ seek consumer (Timeout 2000) [part topic 0 (PartitionOffset 1)] >>= (@?= Just (KafkaResponseError RdKafkaRespErrState))+ assignment consumer >>= (@?= Right M.empty)+ assign consumer [part topic 0 (PartitionOffset 2)] >>= (@?= Nothing)+ record consumer topic 0 2,+ testCase "subscription-preserves-the-exact-multiple-topic-set" $+ withTopic env (Text.pack ("state-" <> label <> "-subscription-a")) 1 $ \first producerA ->+ withTopic env (Text.pack ("state-" <> label <> "-subscription-b")) 1 $ \second producerB -> do+ produceTo producerA first 0 "first-topic"+ produceTo producerB second 0 "second-topic"+ bracket (newConsumer (base "multiple-topics" <> logLevel KafkaLogWarning) (topics [second, first, second] <> offsetReset Earliest) >>= either throwIO pure) releaseConsumer $ \consumer -> do+ subscription consumer >>= (@?= Right [(first, SubscribedPartitionsAll), (second, SubscribedPartitionsAll)])+ records <- receiveMessages consumer 2 >>= either throwIO pure+ sort [(crTopic r, crPartition r, crOffset r, crValue r) | r <- records] @?= [(first, PartitionId 0, Offset 0, Just "first-topic"), (second, PartitionId 0, Offset 0, Just "second-topic")],+ scenario "empty-requests-preserve-empty-assignment" $ \_ consumer -> do+ pausePartitions consumer [] >>= (@?= KafkaResponseError RdKafkaRespErrNoError)+ resumePartitions consumer [] >>= (@?= KafkaResponseError RdKafkaRespErrNoError)+ storeOffsets consumer [] >>= (@?= Nothing)+ position consumer [] >>= (@?= Right [])+ assignment consumer >>= (@?= Right M.empty),+ scenario "unknown-position-is-invalid-without-native-error" $ \topic consumer -> do+ position consumer [(topic, PartitionId 42)] >>= (@?= Right [part topic 42 PartitionOffsetInvalid]),+ scenario "multiple-assigned-partitions-retain-the-exact-topic-map" $ \topic consumer -> do+ assign consumer [part topic 0 (PartitionOffset 0), part topic 1 (PartitionOffset 0)] >>= (@?= Nothing)+ fmap (M.map sort) <$> assignment consumer >>= (@?= Right (M.singleton topic [PartitionId 0, PartitionId 1])),+ scenario "legacy-seek-constructor-failure-does-not-execute-an-earlier-valid-seek" $ \topic consumer -> do+ assign consumer [part topic 0 (PartitionOffset 0)] >>= (@?= Nothing)+ record consumer topic 0 0+ seek consumer (Timeout 200) [part topic 0 (PartitionOffset 2), part (TopicName (Text.replicate 513 "x")) 0 (PartitionOffset 0)]+ >>= (@?= Just (KafkaError "Local: Invalid argument or configuration"))+ assignment consumer >>= (@?= Right (M.singleton topic [PartitionId 0]))+ record consumer topic 0 1,+ scenario "pause-resume-preserves-records" $ \topic consumer -> do+ assign consumer [part topic 0 (PartitionOffset 0)] >>= (@?= Nothing)+ record consumer topic 0 0+ pausePartitions consumer [(topic, PartitionId 0)] >>= (@?= KafkaResponseError RdKafkaRespErrNoError)+ pollMessage consumer (Timeout 100) >>= (@?= Left (KafkaResponseError RdKafkaRespErrTimedOut))+ position consumer [(topic, PartitionId 0)] >>= (@?= Right [part topic 0 (PartitionOffset 1)])+ resumePartitions consumer [(topic, PartitionId 0)] >>= (@?= KafkaResponseError RdKafkaRespErrNoError)+ record consumer topic 0 1+ record consumer topic 0 2,+ scenario "callback-event-poll-preserves-application-records" $ \topic consumer -> do+ assign consumer [part topic 0 (PartitionOffset 0)] >>= (@?= Nothing)+ pollConsumerEvents consumer (Just (Timeout 1000))+ forM_ [0 .. 2] (record consumer topic 0),+ scenario "callback-buffer-seek-replaces-pending-records" $ \topic consumer -> do+ assign consumer [part topic 0 (PartitionOffset 0)] >>= (@?= Nothing)+ pollConsumerEvents consumer (Just (Timeout 1000))+ seekPartitions consumer [part topic 0 (PartitionOffset 2)] (Timeout 2000) >>= (@?= Nothing)+ record consumer topic 0 2+ position consumer [(topic, PartitionId 0)] >>= (@?= Right [part topic 0 (PartitionOffset 3)]),+ scenario "callback-buffer-reassignment-replaces-pending-records" $ \topic consumer -> do+ assign consumer [part topic 0 (PartitionOffset 0)] >>= (@?= Nothing)+ pollConsumerEvents consumer (Just (Timeout 1000))+ assign consumer [part topic 1 (PartitionOffset 1)] >>= (@?= Nothing)+ record consumer topic 1 1,+ scenario "callback-buffer-pause-defers-pending-records" $ \topic consumer -> do+ assign consumer [part topic 0 (PartitionOffset 0)] >>= (@?= Nothing)+ pollConsumerEvents consumer (Just (Timeout 1000))+ pausePartitions consumer [(topic, PartitionId 0)] >>= (@?= KafkaResponseError RdKafkaRespErrNoError)+ pollMessage consumer (Timeout 100) >>= (@?= Left (KafkaResponseError RdKafkaRespErrTimedOut))+ resumePartitions consumer [(topic, PartitionId 0)] >>= (@?= KafkaResponseError RdKafkaRespErrNoError)+ forM_ [0 .. 2] (record consumer topic 0),+ scenario "callback-buffer-legacy-seek-replaces-pending-records" $ \topic consumer -> do+ assign consumer [part topic 0 (PartitionOffset 0)] >>= (@?= Nothing)+ pollConsumerEvents consumer (Just (Timeout 1000))+ seek consumer (Timeout 2000) [part topic 0 (PartitionOffset 2)] >>= (@?= Nothing)+ record consumer topic 0 2,+ scenario "callback-buffer-legacy-partial-seek-keeps-success" $ \topic consumer -> do+ assign consumer [part topic 0 (PartitionOffset 0)] >>= (@?= Nothing)+ pollConsumerEvents consumer (Just (Timeout 1000))+ seek consumer (Timeout 2000) [part topic 0 (PartitionOffset 2), part topic 1 (PartitionOffset 2)] >>= (@?= Just (KafkaResponseError RdKafkaRespErrState))+ record consumer topic 0 2,+ scenario "callback-buffer-paused-partition-does-not-block-another" $ \topic consumer -> do+ assign consumer [part topic 0 (PartitionOffset 0), part topic 1 (PartitionOffset 0)] >>= (@?= Nothing)+ forM_ [1 .. if mode == CallbackPollModeSync then 6 else 1 :: Int] $ \_ -> pollConsumerEvents consumer (Just (Timeout 1000))+ pausePartitions consumer [(topic, PartitionId 0), (unknown topic, PartitionId 42)] >>= (@?= KafkaResponseError RdKafkaRespErrUnknownPartition)+ forM_ [0 .. 2] (record consumer topic 1)+ pollMessage consumer (Timeout 100) >>= (@?= Left (KafkaResponseError RdKafkaRespErrTimedOut))+ resumePartitions consumer [(unknown topic, PartitionId 42), (topic, PartitionId 0)] >>= (@?= KafkaResponseError RdKafkaRespErrUnknownPartition)+ forM_ [0 .. 2] (record consumer topic 0),+ scenario "callback-buffer-unassignment-discards-pending-records" $ \topic consumer -> do+ assign consumer [part topic 0 (PartitionOffset 0)] >>= (@?= Nothing)+ pollConsumerEvents consumer (Just (Timeout 1000))+ assign consumer [] >>= (@?= Nothing)+ pollMessage consumer (Timeout 100) >>= (@?= Left (KafkaResponseError RdKafkaRespErrTimedOut)),+ scenario "pausing-one-partition-leaves-the-other-running" $ \topic consumer -> do+ assign consumer [part topic 0 (PartitionOffset 0), part topic 1 (PartitionOffset 0)] >>= (@?= Nothing)+ forM_ [1 .. 2 :: Int] $ \_ -> pausePartitions consumer [(topic, PartitionId 0)] >>= (@?= KafkaResponseError RdKafkaRespErrNoError)+ forM_ [0 .. 2] (record consumer topic 1)+ pollMessage consumer (Timeout 100) >>= (@?= Left (KafkaResponseError RdKafkaRespErrTimedOut))+ forM_ [1 .. 2 :: Int] $ \_ -> resumePartitions consumer [(topic, PartitionId 0)] >>= (@?= KafkaResponseError RdKafkaRespErrNoError)+ forM_ [0 .. 2] (record consumer topic 0),+ scenario "pause-mixed-member-error" $ \topic consumer -> do+ assign consumer [part topic 0 (PartitionOffset 0)] >>= (@?= Nothing)+ record consumer topic 0 0+ pausePartitions consumer [(topic, PartitionId 0), (unknown topic, PartitionId 42)] >>= (@?= KafkaResponseError RdKafkaRespErrUnknownPartition)+ pollMessage consumer (Timeout 100) >>= (@?= Left (KafkaResponseError RdKafkaRespErrTimedOut))+ resumePartitions consumer [(topic, PartitionId 0)] >>= (@?= KafkaResponseError RdKafkaRespErrNoError)+ record consumer topic 0 1,+ scenario "resume-mixed-member-error" $ \topic consumer -> do+ assign consumer [part topic 0 (PartitionOffset 0)] >>= (@?= Nothing)+ record consumer topic 0 0+ pausePartitions consumer [(topic, PartitionId 0)] >>= (@?= KafkaResponseError RdKafkaRespErrNoError)+ resumePartitions consumer [(unknown topic, PartitionId 42), (topic, PartitionId 0)] >>= (@?= KafkaResponseError RdKafkaRespErrUnknownPartition)+ record consumer topic 0 1,+ scenario "store-commit-next-offset" $ \topic consumer -> do+ assign consumer [part topic 0 (PartitionOffset 0)] >>= (@?= Nothing)+ position consumer [(topic, PartitionId 0)] >>= (@?= Right [part topic 0 PartitionOffsetInvalid])+ committed consumer (Timeout 3000) [(topic, PartitionId 0)] >>= (@?= Right [part topic 0 PartitionOffsetInvalid])+ message <- pollMessage consumer (Timeout 10000) >>= either throwIO pure+ (crOffset message, crValue message) @?= (Offset 0, Just (payload 0 0))+ commitAllOffsets OffsetCommit consumer >>= (@?= Just (KafkaResponseError RdKafkaRespErrNoOffset))+ storeOffsetMessage consumer message >>= (@?= Nothing)+ committed consumer (Timeout 3000) [(topic, PartitionId 0)] >>= (@?= Right [part topic 0 PartitionOffsetInvalid])+ commitAllOffsets OffsetCommit consumer >>= (@?= Nothing)+ committed consumer (Timeout 3000) [(topic, PartitionId 0)] >>= (@?= Right [part topic 0 (PartitionOffset 1)])+ commitPartitionsOffsets OffsetCommit consumer [part topic 0 (PartitionOffset 2)] >>= (@?= Nothing)+ committed consumer (Timeout 3000) [(topic, PartitionId 0)] >>= (@?= Right [part topic 0 (PartitionOffset 2)]),+ scenario "store-mixed-member-error" $ \topic consumer -> do+ assign consumer [part topic 0 (PartitionOffset 0)] >>= (@?= Nothing)+ record consumer topic 0 0+ storeOffsets consumer [part topic 0 (PartitionOffset 2), part (unknown topic) 42 (PartitionOffset 1)] >>= (@?= Just (KafkaResponseError RdKafkaRespErrUnknownPartition))+ commitAllOffsets OffsetCommit consumer >>= (@?= Nothing)+ committed consumer (Timeout 3000) [(topic, PartitionId 0)] >>= (@?= Right [part topic 0 (PartitionOffset 2)]),+ scenario "position-mixed-member-error" $ \topic consumer -> do+ assign consumer [part topic 0 (PartitionOffset 0)] >>= (@?= Nothing)+ record consumer topic 0 0+ position consumer [(topic, PartitionId 0), (TopicName (Text.replicate 513 "x"), PartitionId 0)] >>= (@?= Left (KafkaResponseError RdKafkaRespErrUnknownPartition)),+ scenario "deprecated-seek-exact-repeated-replay" $ \topic consumer -> do+ assign consumer [part topic 0 (PartitionOffset 0)] >>= (@?= Nothing)+ forM_ [0 .. 2] (record consumer topic 0)+ forM_ ([0 .. 19] :: [Int]) $ \iteration -> do+ let offset = iteration `mod` 3+ seek consumer (Timeout 2000) [part topic 0 (PartitionOffset (fromIntegral offset))] >>= (@?= Nothing)+ record consumer topic 0 offset,+ testCase "explicit-subscription-overrides-global-reset" $+ withTopic env (Text.pack ("state-" <> label <> "-explicit-reset")) 1 $ \topic producer -> do+ produceTo producer topic 0 "existing"+ bracket (newConsumer (base "explicit-reset" <> extraProp "auto.offset.reset" "latest") (topics [topic] <> offsetReset Earliest) >>= either throwIO pure) releaseConsumer $ \consumer -> do+ message <- pollMessage consumer (Timeout 10000) >>= either throwIO pure+ (crTopic message, crOffset message, crValue message) @?= (topic, Offset 0, Just "existing"),+ testCase "regex-subscription-selects-run-owned-topic" $+ withTopic env (Text.pack ("state-" <> label <> "-regex")) 1 $ \topic@(TopicName name) producer -> do+ produceTo producer topic 0 "matched"+ let patternTopic = TopicName ("^" <> name <> "$")+ bracket (newConsumer (base "regex") (topics [patternTopic] <> offsetReset Earliest) >>= either throwIO pure) releaseConsumer $ \consumer -> do+ message <- pollMessage consumer (Timeout 10000) >>= either throwIO pure+ (crTopic message, crOffset message, crValue message) @?= (topic, Offset 0, Just "matched")+ subscription consumer >>= (@?= Right [(patternTopic, SubscribedPartitionsAll)]),+ testCase "global-topic-setting-survives-empty-subscription-properties" $+ withTopic env (Text.pack ("state-" <> label <> "-global-reset")) 1 $ \topic producer -> do+ produceTo producer topic 0 "existing"+ let props = base "global-reset" <> extraProp "auto.offset.reset" "earliest"+ bracket (newConsumer props (topics [topic]) >>= either throwIO pure) releaseConsumer $ \consumer -> do+ message <- pollMessage consumer (Timeout 3000) >>= either throwIO pure+ (crTopic message, crOffset message, crValue message) @?= (topic, Offset 0, Just "existing")+ ]+ | (label, mode) <- [("async", CallbackPollModeAsync), ("sync", CallbackPollModeSync)],+ let base name = brokersList (teBrokers env) <> groupId (makeGroupId env (Text.pack ("state-" <> label <> "-" <> name))) <> noAutoCommit <> noAutoOffsetStore <> callbackPollMode mode,+ let scenario name action = testCase name $+ withTopic env (Text.pack ("state-" <> label <> "-" <> name)) 2 $ \topic producer -> do+ forM_ [0, 1] $ \partition -> forM_ [0 .. 2] $ \offset -> produceTo producer topic partition (payload partition offset)+ bracket (newAssignedConsumer (base name) >>= either throwIO pure) releaseConsumer (action topic)+ ]+ <> bufferFieldTests env+ <> [cooperativeBufferTest env, mixedBufferTest env]++bufferFieldTests :: TestEnv -> [TestTree]+bufferFieldTests env =+ [ testCase ("sync-buffer-fields-" <> label) $+ withTopic env (Text.pack ("buffer-fields-" <> label)) 1 $ \topic producer -> do+ let fields = [(Just "\0\255key", Just "\255\0value", headersFromList [("same", ""), ("same", "\0\255")]), (Nothing, Nothing, mempty), (Just "", Just "", mempty)]+ forM_ fields $ \(key, value, headers) -> P.produceMessage producer (P.ProducerRecord topic (P.SpecifiedPartition 0) key value headers) >>= (@?= Nothing)+ P.flushProducerTimeout producer (Timeout 5000) >>= (@?= Nothing)+ let props = brokersList (teBrokers env) <> groupId (makeGroupId env (Text.pack ("buffer-fields-" <> label))) <> noAutoCommit <> callbackPollMode CallbackPollModeSync <> extraProp "enable.partition.eof" "true"+ bracket (newAssignedConsumer props >>= either throwIO pure) releaseConsumer $ \consumer -> do+ assign consumer [part topic 0 (PartitionOffset 0)] >>= (@?= Nothing)+ forM_ [1 .. 3 :: Int] $ \_ -> withMessageFault fault $ do+ pollConsumerEvents consumer (Just (Timeout 3000))+ mapM messageStat [1, 2, 5] >>= (@?= [1, 1, 0])+ -- EOF is retained with its origin; an empty poll must not add a timeout.+ pollConsumerEvents consumer (Just (Timeout 1000))+ pollConsumerEvents consumer (Just (Timeout 100))+ forM_ (zip [0 ..] fields) $ \(offset, (key, value, headers)) -> do+ message <- if offset == 1 then pollMessageAttributed consumer (Timeout 0) >>= either (assertFailure . show) pure else pollMessage consumer (Timeout 0) >>= either throwIO pure+ (crTopic message, crPartition message, crOffset message, crKey message, crValue message, crHeaders message) @?= (topic, PartitionId 0, Offset offset, key, value, headers)+ case timestamp of+ Just expected -> crTimestamp message @?= expected+ Nothing -> case crTimestamp message of+ CreateTime (Millis time) -> assertBool "timestamp is missing" (time > 0)+ other -> assertFailure (show other)+ pollMessageAttributed consumer (Timeout 0) >>= (@?= Left (ConsumerMessageError (KafkaResponseError RdKafkaRespErrPartitionEof) (Just topic) (Just (PartitionId 0)) (Just (Offset 3))))+ pollMessage consumer (Timeout 50) >>= (@?= Left (KafkaResponseError RdKafkaRespErrTimedOut))+ | (label, fault, timestamp) <- [("native-time", 16, Nothing), ("no-time", 17, Just NoTimestamp), ("append-time", 18, Just (LogAppendTime (Millis 123456789))), ("create-time", 19, Just (CreateTime (Millis 987654321)))]+ ]++part :: TopicName -> Int -> PartitionOffset -> TopicPartition+part topic partition = TopicPartition topic (PartitionId partition)++payload :: Int -> Int -> BS.ByteString+payload partition offset = BS.pack (show partition <> ":" <> show offset)++record :: KafkaConsumer -> TopicName -> Int -> Int -> IO ()+record consumer topic partition offset = do+ message <- pollMessage consumer (Timeout 10000) >>= either throwIO pure+ (crTopic message, crPartition message, crOffset message, crKey message, crValue message, crHeaders message)+ @?= (topic, PartitionId partition, Offset (fromIntegral offset), Nothing, Just (payload partition offset), mempty)++unknown :: TopicName -> TopicName+unknown (TopicName topic) = TopicName (topic <> "-absent")++-- Installed callback frames exercise exact subsets while all native protocol,+-- assignment, queue and incremental actions remain real.+cooperativeBufferTest :: TestEnv -> TestTree+cooperativeBufferTest env = testCase "cooperative subset callbacks preserve unrelated buffers pauses and originless errors" $+ withTopic env "cooperative-buffer-subset" 2 $ \topic producer -> do+ forM_ [0, 1] $ \partition -> forM_ [0 .. 2] $ \offset -> produceTo producer topic partition (payload partition offset)+ let props = consumerPropsNoStore env <> groupId (makeGroupId env "cooperative-buffer-subset") <> callbackPollMode CallbackPollModeSync <> extraProp "partition.assignment.strategy" "cooperative-sticky"+ withStateFault 9 $ bracket (newConsumer props (topics [topic] <> offsetReset Earliest) >>= either throwIO pure) releaseConsumer $ \consumer -> do+ timeout 10000000 (withMessageFault 16 (collect consumer 6)) >>= maybe (assertFailure "six callback records were not copied") pure+ fmap (M.map sort) <$> assignment consumer >>= (@?= Right (M.singleton topic [PartitionId 0, PartitionId 1]))+ produceTo producer topic 0 "originless-error-frame"+ withMessageFault 24 $ do+ pollConsumerEvents consumer (Just (Timeout 10000))+ messageStat 1 >>= (@?= 1)+ messageStat 2 >>= (@?= 1)+ pausePartitions consumer [(topic, PartitionId 0), (topic, PartitionId 1)] >>= (@?= KafkaResponseError RdKafkaRespErrNoError)+ triggerCooperative topic True+ fmap (M.map sort) <$> assignment consumer >>= (@?= Right (M.singleton topic [PartitionId 1]))+ -- Partition 1 remains paused across both subset actions. Partition 0's+ -- copied records must be discarded. The controlled re-assignment starts+ -- at END, so no copied record from partition 0 may reappear.+ triggerCooperative topic False+ fmap (M.map sort) <$> assignment consumer >>= (@?= Right (M.singleton topic [PartitionId 0, PartitionId 1]))+ resumePartitions consumer [(topic, PartitionId 0)] >>= (@?= KafkaResponseError RdKafkaRespErrNoError)+ pollMessageAttributed consumer (Timeout 0)+ >>= (@?= Left (ConsumerMessageError (KafkaResponseError RdKafkaRespErrBadMsg) Nothing Nothing Nothing))+ pollMessage consumer (Timeout 100) >>= (@?= Left (KafkaResponseError RdKafkaRespErrTimedOut))+ resumePartitions consumer [(topic, PartitionId 1)] >>= (@?= KafkaResponseError RdKafkaRespErrNoError)+ forM_ [0 .. 2] (record consumer topic 1)+ pollMessage consumer (Timeout 100) >>= (@?= Left (KafkaResponseError RdKafkaRespErrTimedOut))+ where+ collect consumer count = do+ pollConsumerEvents consumer (Just (Timeout 1000))+ acquired <- messageStat 1+ if acquired == count then messageStat 2 >>= (@?= count) else collect consumer count++mixedBufferTest :: TestEnv -> TestTree+mixedBufferTest env = testCase "sync callback mixed seek retains only the failed partition's copied records" $+ withTopic env "mixed-seek-buffer" 2 $ \topic producer -> do+ forM_ [0, 1] $ \partition -> forM_ [0 .. 2] $ \offset -> produceTo producer topic partition (payload partition offset)+ let props = consumerPropsNoStore env <> groupId (makeGroupId env "mixed-seek-buffer") <> callbackPollMode CallbackPollModeSync+ bracket (newAssignedConsumer props >>= either throwIO pure) releaseConsumer $ \consumer -> do+ assign consumer [part topic 0 (PartitionOffset 0), part topic 1 (PartitionOffset 0)] >>= (@?= Nothing)+ timeout 10000000 (withMessageFault 16 (collect consumer)) >>= maybe (assertFailure "six callback records were not copied") pure+ seekPartitions consumer [part topic 0 PartitionOffsetStored, part topic 1 (PartitionOffset 2)] (Timeout 2000)+ >>= (@?= Just (KafkaResponseError RdKafkaRespErrInvalidArg))+ records <- receiveMessages consumer 4 >>= either throwIO pure+ sort [(crTopic r, crPartition r, crOffset r, crValue r) | r <- records]+ @?= [(topic, PartitionId partition, Offset offset, Just (payload partition (fromIntegral offset))) | (partition, offsets) <- [(0, [0, 1, 2]), (1, [2])], offset <- offsets]+ pollMessage consumer (Timeout 100) >>= (@?= Left (KafkaResponseError RdKafkaRespErrTimedOut))+ where+ collect consumer = do+ pollConsumerEvents consumer (Just (Timeout 1000))+ acquired <- messageStat 1+ if acquired == 6 then messageStat 2 >>= (@?= 6) else collect consumer
+ test-integration/Kafka/Integration/ConsumerTest.hs view
@@ -0,0 +1,171 @@+-- The inherited seek checks cover the deprecated seek.+{-# OPTIONS_GHC -Wno-deprecations #-}++-- | The inherited main consumer scenario: produce, then run the same consumer+-- checks once per callback poll mode.+module Kafka.Integration.ConsumerTest+ ( tests,+ )+where++import Control.Concurrent.MVar (newEmptyMVar, putMVar, takeMVar)+import Control.Exception (bracket, throwIO)+import Control.Monad (forM_)+import Data.Either (isRight)+import Data.Map (fromList)+import Kafka.Consumer+import Kafka.Metadata+import Kafka.Producer+import Kafka.TestEnv+import Test.Tasty (DependencyType (AllSucceed), TestTree, dependentTestGroup)+import Test.Tasty.HUnit (assertBool, assertFailure, testCase, (@?=))++tests :: TestEnv -> TestTree+tests env =+ dependentTestGroup+ "Consumer"+ AllSucceed+ [ withProducer env $ \getProducer ->+ dependentTestGroup+ "Run producer"+ AllSucceed+ [ testCase "sends messages to test topic" $ do+ res <- getProducer >>= sendMessages (testMessages (teTopic env))+ res @?= Right (),+ testCase "sends messages with callback to test topic" $ do+ prod <- getProducer+ var <- newEmptyMVar+ let msg =+ ProducerRecord+ { prTopic = TopicName (prefixedName env "callback-topic"),+ prPartition = UnassignedPartition,+ prKey = Nothing,+ prValue = Just "test from producer",+ prHeaders = mempty+ }++ res <- produceMessage' prod msg (putMVar var)+ res @?= Right ()+ callbackRes <- flushProducer prod *> takeMVar var+ case callbackRes of+ DeliverySuccess _ _ -> pure ()+ DeliveryFailure _ err -> assertFailure ("delivery failed: " <> show err)+ NoMessageError err -> assertFailure ("no message: " <> show err)+ ],+ withConsumer env (consumerProps env <> groupId (makeGroupId env "async")) $+ dependentTestGroup "Run consumer with async polling" AllSucceed . consumerChecks env CallbackPollModeAsync,+ withConsumer env (consumerProps env <> groupId (makeGroupId env "sync") <> callbackPollMode CallbackPollModeSync) $+ dependentTestGroup "Run consumer with sync polling" AllSucceed . consumerChecks env CallbackPollModeSync+ ]++consumerChecks :: TestEnv -> CallbackPollMode -> IO KafkaConsumer -> [TestTree]+consumerChecks env mode getConsumer =+ [ check "should receive messages" $ \k -> do+ res <- receiveTestMessages env k 14 0+ length <$> res @?= Right 14++ let timestamps = crTimestamp <$> either (const []) id res+ forM_ timestamps $ \ts ->+ assertBool "expected a timestamp" (ts /= NoTimestamp)++ comRes <- commitAllOffsets OffsetCommit k+ comRes @?= Nothing,+ check "should get committed" $ \k -> do+ res <- committed k (Timeout 1000) [(testTopic, PartitionId 0)]+ assertBool (show res) (isRight res),+ check "should get position" $ \k -> do+ res <- position k [(testTopic, PartitionId 0)]+ assertBool (show res) (isRight res),+ check "should get watermark offsets" $ \k -> do+ res <- sequence <$> watermarkOffsets k (Timeout 1000) testTopic+ assertBool (show res) (isRight res)+ length <$> res @?= Right 1,+ check "should return subscription" $ \k -> do+ res <- subscription k+ assertBool (show res) (isRight res)+ length <$> res @?= Right 1,+ check "should return assignment" $ \k -> do+ res <- assignment k+ res @?= Right (fromList [(testTopic, [PartitionId 0])]),+ check "assignment is not lost" $ \k ->+ assignmentLost k >>= (@?= False),+ check "should return all topics metadata" $ \k -> do+ res <- allTopicsMetadata k (Timeout 1000)+ assertBool (show res) (isRight res)+ let filterUserTopics m = m {kmTopics = filter (\t -> topicType (tmTopicName t) == User) (kmTopics m)}+ let res' = fmap filterUserTopics res+ length . kmBrokers <$> res' @?= Right 1++ let topicsLen = either (const 0) (length . kmTopics) res'+ let hasTopic = either (const False) (any (\t -> tmTopicName t == testTopic) . kmTopics) res'++ assertBool "expected user topics" (topicsLen > 0)+ hasTopic @?= True,+ check "should return topic metadata" $ \k -> do+ res <- topicMetadata k (Timeout 2000) testTopic+ assertBool (show res) (isRight res)+ length . kmBrokers <$> res @?= Right 1+ length . kmTopics <$> res @?= Right 1,+ check "should describe all consumer groups" $ \k -> do+ res <- allConsumerGroupsInfo k (Timeout 2000)+ assertBool (show res) (isRight res)+ let groups = either (const []) (fmap giGroup) res+ let prefixedGroups = filter (isTestGroupId env) groups+ assertBool "expected this run's consumer groups" (not (null prefixedGroups)),+ check "should describe a given consumer group" $ \k -> do+ res <- consumerGroupInfo k (Timeout 2000) (testGroupId env)+ fmap giGroup <$> res @?= Right [testGroupId env],+ check "should describe non-existent consumer group" $ \k -> do+ res <- consumerGroupInfo k (Timeout 2000) (makeGroupId env "does-not-exist")+ res @?= Right [],+ check "should read topic offsets for time" $ \k -> do+ res <- topicOffsetsForTime k (Timeout 2000) (Millis 1904057189508) testTopic+ assertBool (show res) (isRight res)+ fmap tpOffset <$> res @?= Right [PartitionOffsetEnd],+ checkSeek "should seek and return no error" "offset" $ \seekTopic k -> do+ res <- seek k (Timeout 1000) [TopicPartition seekTopic (PartitionId 0) (PartitionOffset 1)]+ res @?= Nothing+ msg <- pollMessage k (Timeout 1000)+ fmap (\m -> (crTopic m, crPartition m, crOffset m, crValue m)) msg @?= Right (seekTopic, PartitionId 0, Offset 1, Just "one"),+ checkSeek "should seek to the beginning" "beginning" $ \seekTopic k -> do+ res <- seek k (Timeout 1000) [TopicPartition seekTopic (PartitionId 0) PartitionOffsetBeginning]+ res @?= Nothing+ msg <- pollMessage k (Timeout 1000)+ fmap (\m -> (crTopic m, crPartition m, crOffset m, crValue m)) msg @?= Right (seekTopic, PartitionId 0, Offset 0, Just "zero"),+ checkSeek "should seek to the end" "end" $ \seekTopic k -> do+ res <- seek k (Timeout 1000) [TopicPartition seekTopic (PartitionId 0) PartitionOffsetEnd]+ res @?= Nothing+ msg <- pollMessage k (Timeout 1000)+ let offset = crOffset <$> msg+ assertBool+ ("expected partition EOF or a timeout, got " <> show offset)+ ( offset == Left (KafkaResponseError RdKafkaRespErrPartitionEof)+ || offset == Left (KafkaResponseError RdKafkaRespErrTimedOut)+ ),+ checkSeek "should respect out-of-bound offsets (invalid offset)" "invalid" $ \seekTopic k -> do+ res <- seek k (Timeout 2000) [TopicPartition seekTopic (PartitionId 0) PartitionOffsetInvalid]+ res @?= Nothing+ msg <- pollMessage k (Timeout 1000)+ fmap (\m -> (crTopic m, crPartition m, crOffset m, crValue m)) msg @?= Right (seekTopic, PartitionId 0, Offset 0, Just "zero"),+ checkSeek "should respect out-of-bound offsets (huge offset)" "huge" $ \seekTopic k -> do+ res <- seek k (Timeout 3000) [TopicPartition seekTopic (PartitionId 0) (PartitionOffset 123456)]+ res @?= Nothing+ msg <- pollMessage k (Timeout 2000)+ fmap (\m -> (crTopic m, crPartition m, crOffset m, crValue m)) msg @?= Right (seekTopic, PartitionId 0, Offset 0, Just "zero")+ ]+ where+ testTopic = teTopic env+ check name f = testCase name (getConsumer >>= f)++ -- A previous assignment query is a snapshot, not proof that a fetcher is+ -- still active after unrelated blocking metadata operations. Each positive+ -- seek begins immediately after this fresh grouped consumer reads record 0.+ checkSeek name suffix action = testCase name $+ withTopic env ("legacy-seek-" <> label <> "-" <> suffix) 1 $ \topic producer -> do+ forM_ ["zero", "one", "two"] (produceTo producer topic 0)+ let props = consumerProps env <> groupId (makeGroupId env ("legacy-seek-" <> label <> "-" <> suffix)) <> noAutoOffsetStore <> callbackPollMode mode+ bracket (mkConsumerFor topic props) releaseConsumer $ \consumer -> do+ first <- pollMessage consumer (Timeout 10000) >>= either throwIO pure+ (crTopic first, crPartition first, crOffset first, crValue first) @?= (topic, PartitionId 0, Offset 0, Just "zero")+ action topic consumer+ label = if mode == CallbackPollModeSync then "sync" else "async"
+ test-integration/Kafka/Integration/DeprecatedRunnerContractTest.hs view
@@ -0,0 +1,120 @@+{-# OPTIONS_GHC -Wno-deprecations #-}++module Kafka.Integration.DeprecatedRunnerContractTest (tests) where++import Control.Concurrent.MVar (newEmptyMVar, tryPutMVar, tryTakeMVar)+import Control.Exception (Exception, finally, throwIO, try)+import Control.Monad (void, when)+import Data.IORef (newIORef, readIORef, writeIORef)+import Data.Map.Strict qualified as M+import Data.Text qualified as Text+import Kafka.Consumer qualified as C+import Kafka.Consumer.Types qualified as CT+import Kafka.Dump (dumpKafkaConf, dumpTopicConf)+import Kafka.Metadata (kmTopics, tmTopicName, topicMetadata)+import Kafka.Producer qualified as P+import Kafka.Producer.Types qualified as PT+import Kafka.TestEnv+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.HUnit (assertBool, assertFailure, testCase, (@?=))++data Outcome = Returned | Refused | Thrown deriving (Eq, Show)++data HandlerFailure = HandlerFailure deriving (Eq, Show)++instance Exception HandlerFailure++marker :: C.KafkaError+marker = C.KafkaBadSpecification "runner-handler-result"++finish :: Outcome -> IO (Either C.KafkaError Int)+finish Returned = pure (Right 42)+finish Refused = pure (Left marker)+finish Thrown = throwIO HandlerFailure++checkResult :: Outcome -> Either HandlerFailure (Either C.KafkaError Int) -> IO ()+checkResult Returned result = result @?= Right (Right 42)+checkResult Refused result = result @?= Right (Left marker)+checkResult Thrown result = result @?= Left HandlerFailure++tests :: TestEnv -> TestTree+tests env =+ testGroup "deprecated-runners" $+ [ testCase ("producer flushes after " <> show outcome) $+ withTopic env (Text.pack ("runner-producer-" <> show outcome)) 1 $ \topic _ -> do+ retained <- newIORef Nothing+ reports <- newEmptyMVar+ let props = P.brokersList (teBrokers env) <> P.sendTimeout (C.Timeout 5000) <> P.extraProp "client.id" "raw-producer-holder" <> P.setCallback (P.deliveryCallback (void . tryPutMVar reports))+ cleanup = readIORef retained >>= mapM_ releaseProducer+ flip finally cleanup $ do+ result <- try @HandlerFailure $ P.runProducer props $ \producer -> do+ let alias = PT.KafkaProducer (PT.kpKafkaPtr producer) (PT.kpKafkaConf producer) (PT.kpTopicConf producer)+ writeIORef retained (Just alias)+ when (outcome == Returned) $ do+ dumpTopicConf (PT.kpTopicConf alias) >>= (\values -> M.lookup "message.timeout.ms" values @?= Just "5000")+ dumpKafkaConf (PT.kpKafkaConf alias) >>= (\values -> M.lookup "client.id" values @?= Just "raw-producer-holder")+ metadata <- topicMetadata (PT.kpKafkaPtr alias) (C.Timeout 5000) topic >>= either throwIO pure+ map tmTopicName (kmTopics metadata) @?= [topic]+ P.produceMessage alias (P.ProducerRecord topic (P.SpecifiedPartition 0) (Just "runner-key") (Just "runner-value") mempty) >>= (@?= Nothing)+ finish outcome+ checkResult outcome result+ tryTakeMVar reports >>= \case+ Just (P.DeliverySuccess record offset) -> (P.prTopic record, P.prKey record, P.prValue record, offset) @?= (topic, Just "runner-key", Just "runner-value", C.Offset 0)+ other -> assertFailure ("wrapper did not flush its delivery report: " <> show other)+ | outcome <- [Returned, Refused, Thrown]+ ]+ <> [ testCase (label <> " consumer closes after " <> show outcome) $+ withTopic env (Text.pack ("runner-consumer-" <> label <> "-" <> show outcome)) 1 $ \topic producer -> do+ produceTo producer topic 0 "runner-record"+ retained <- newIORef Nothing+ let props = C.brokersList (teBrokers env) <> C.groupId (makeGroupId env (Text.pack ("runner-" <> label <> "-" <> show outcome))) <> C.noAutoCommit <> C.clientId (C.ClientId "raw-consumer-holder") <> C.callbackPollMode mode+ cleanup = readIORef retained >>= mapM_ releaseConsumer+ flip finally cleanup $ do+ result <- try @HandlerFailure $ C.runConsumer props (C.topics [topic] <> C.offsetReset C.Earliest) $ \consumer -> do+ let alias = CT.KafkaConsumer (CT.kcKafkaPtr consumer) (CT.kcKafkaConf consumer)+ writeIORef retained (Just alias)+ when (outcome == Returned) $ do+ dumpKafkaConf (CT.kcKafkaConf alias) >>= (\values -> M.lookup "client.id" values @?= Just "raw-consumer-holder")+ metadata <- topicMetadata (CT.kcKafkaPtr alias) (C.Timeout 5000) topic >>= either throwIO pure+ map tmTopicName (kmTopics metadata) @?= [topic]+ C.consumerFatalError alias >>= (@?= Nothing)+ message <- C.pollMessage alias (C.Timeout 10000) >>= either throwIO pure+ (C.crTopic message, C.crPartition message, C.crOffset message, C.crValue message) @?= (topic, C.PartitionId 0, C.Offset 0, Just "runner-record")+ finish outcome+ checkResult outcome result+ readIORef retained >>= maybe (assertFailure "runner did not invoke handler") (\consumer -> C.consumerClosed consumer >>= (@?= True))+ | (label, mode) <- [("async", C.CallbackPollModeAsync), ("sync", C.CallbackPollModeSync)],+ outcome <- [Returned, Refused, Thrown]+ ]+ <> [ testCase "producer preserves native construction failure without invoking handler" $ do+ called <- newIORef False+ result <- P.runProducer (P.brokersList (teBrokers env) <> P.extraProps sasl) (\_ -> writeIORef called True >> pure (Right (42 :: Int)))+ nativeFailure result+ readIORef called >>= (@?= False),+ testCase "producer preserves configuration exceptions without invoking handler" $ do+ called <- newIORef False+ result <- try @C.KafkaError $ P.runProducer (P.extraProp "not.a.kafka.property" "x") (\_ -> writeIORef called True >> pure (Right (42 :: Int)))+ unknownConfiguration result+ readIORef called >>= (@?= False)+ ]+ <> [ testCase (label <> " consumer preserves " <> kind <> " construction failure") $ do+ called <- newIORef False+ let base = C.brokersList (teBrokers env) <> C.groupId (makeGroupId env (Text.pack ("runner-failure-" <> label <> "-" <> kind))) <> C.callbackPollMode mode+ if kind == "native"+ then C.runConsumer (base <> C.extraProps sasl) mempty (\_ -> writeIORef called True >> pure (Right (42 :: Int))) >>= nativeFailure+ else (try @C.KafkaError $ C.runConsumer (base <> C.extraProp "not.a.kafka.property" "x") mempty (\_ -> writeIORef called True >> pure (Right (42 :: Int)))) >>= unknownConfiguration+ readIORef called >>= (@?= False)+ | (label, mode) <- [("async", C.CallbackPollModeAsync), ("sync", C.CallbackPollModeSync)],+ kind <- ["native", "configuration"]+ ]++sasl :: M.Map Text.Text Text.Text+sasl = M.fromList [("security.protocol", "SASL_PLAINTEXT"), ("sasl.mechanisms", "PLAIN")]++nativeFailure :: Either C.KafkaError Int -> IO ()+nativeFailure (Left (C.KafkaError message)) = assertBool (show message) ("sasl.username" `Text.isInfixOf` message)+nativeFailure other = assertFailure (show other)++unknownConfiguration :: Either C.KafkaError (Either C.KafkaError Int) -> IO ()+unknownConfiguration (Left (C.KafkaUnknownConfigurationKey _)) = pure ()+unknownConfiguration other = assertFailure (show other)
+ test-integration/Kafka/Integration/DestroyTest.hs view
@@ -0,0 +1,182 @@+-- | 'destroyConsumer' tears the client down synchronously (improvement+-- request IR-2, AC-3), in both callback poll modes, and the close/destroy+-- transitions are idempotent.+module Kafka.Integration.DestroyTest+ ( tests,+ )+where++import Control.Concurrent (forkIO, killThread, threadDelay)+import Control.Concurrent.MVar (MVar, modifyMVar_, newEmptyMVar, newMVar, putMVar, readMVar, tryPutMVar)+import Control.Exception (SomeException, bracket, finally, try)+import Control.Monad (forM_, forever, replicateM, void)+import Data.ByteString qualified as BS+import Data.Text qualified as Text+import GHC.Clock (getMonotonicTime)+import Kafka.Consumer+import Kafka.TestEnv+import Network.Socket qualified as N+import Network.Socket.ByteString qualified as NB+import System.Timeout (timeout)+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.HUnit (Assertion, assertBool, assertFailure, testCase, testCaseInfo, (@?=))++tests :: TestEnv -> TestTree+tests env =+ testGroup+ "destroy"+ [ testGroup label (modeCases env label mode)+ | (label, mode) <- [("async", CallbackPollModeAsync), ("sync", CallbackPollModeSync)]+ ]++modeCases :: TestEnv -> String -> CallbackPollMode -> [TestTree]+modeCases env label mode =+ [ testCaseInfo "closes broker connections within one second" $+ withSilentBroker $ \broker -> do+ consumer <- silentConsumer env mode (label <> "-sockets") broker+ connections <- awaitConnections broker+ start <- getMonotonicTime+ destroyConsumer consumer+ returned <- getMonotonicTime+ allClosedBy broker connections (start + 1)+ closed <- getMonotonicTime+ pure $+ "destroyConsumer returned after "+ <> showMillis (returned - start)+ <> "; all "+ <> show (length connections)+ <> " connection(s) closed after "+ <> showMillis (closed - start),+ testCase "is safe to repeat" $+ withSilentBroker $ \broker -> do+ consumer <- silentConsumer env mode (label <> "-repeat") broker+ connections <- awaitConnections broker+ start <- getMonotonicTime+ destroyConsumer consumer+ destroyConsumer consumer+ allClosedBy broker connections (start + 1)+ closeConsumer consumer >>= (@?= Nothing),+ testCase "concurrent destroys both return after cleanup" $+ withSilentBroker $ \broker -> do+ consumer <- silentConsumer env mode (label <> "-concurrent") broker+ connections <- awaitConnections broker+ start <- getMonotonicTime+ done <- replicateM 2 newEmptyMVar+ forM_ done $ \var -> forkIO (try (destroyConsumer consumer) >>= putMVar var)+ forM_ done $ \var -> do+ result <- timeout 2000000 (readMVar var)+ case result of+ Just (Right ()) -> do+ -- Neither caller returns before the sockets are gone.+ closed <- countClosed broker connections+ closed @?= length connections+ Just (Left err) -> assertFailure ("destroyConsumer threw " <> show (err :: SomeException))+ Nothing -> assertFailure "destroyConsumer did not return within 2 seconds"+ allClosedBy broker connections (start + 1),+ testCase "completes after an interrupted destroy" $+ withSilentBroker $ \broker -> do+ consumer <- silentConsumer env mode (label <> "-interrupted") broker+ connections <- awaitConnections broker+ interrupted <- forkIO (destroyConsumer consumer)+ killThread interrupted+ start <- getMonotonicTime+ destroyConsumer consumer+ allClosedBy broker connections (start + 1),+ testCase "close then destroy, destroy then close" $ do+ let props suffix =+ consumerProps env+ <> groupId (makeGroupId env (Text.pack ("destroy-" <> label <> "-" <> suffix)))+ <> noAutoCommit+ <> callbackPollMode mode+ closing <- newAssignedConsumer (props "close-first") >>= either (assertFailure . show) pure+ closeConsumer closing >>= (@?= Nothing)+ closeConsumer closing >>= (@?= Nothing)+ destroyConsumer closing+ destroyConsumer closing++ destroying <- newAssignedConsumer (props "destroy-first") >>= either (assertFailure . show) pure+ destroyConsumer destroying+ closeConsumer destroying >>= (@?= Nothing)+ ]++-- | A consumer whose only bootstrap broker is the silent listener.+silentConsumer :: TestEnv -> CallbackPollMode -> String -> SilentBroker -> IO KafkaConsumer+silentConsumer env mode label broker =+ newAssignedConsumer+ ( brokersList [BrokerAddress ("127.0.0.1:" <> Text.pack (show (sbPort broker)))]+ <> groupId (makeGroupId env (Text.pack ("destroy-" <> label)))+ <> noAutoCommit+ <> callbackPollMode mode+ )+ >>= either (assertFailure . ("newAssignedConsumer: " <>) . show) pure++-- | A TCP listener on loopback that accepts connections and reads from them+-- but never writes, so a Kafka client connected to it waits forever.+data SilentBroker = SilentBroker+ { sbPort :: N.PortNumber,+ -- | One variable per accepted connection, filled when the peer closes it.+ sbConnections :: MVar [MVar ()]+ }++showMillis :: Double -> String+showMillis seconds = show (round (seconds * 1000) :: Int) <> " ms"++withSilentBroker :: (SilentBroker -> IO a) -> IO a+withSilentBroker body =+ bracket open close $ \(_, _, broker) -> body broker+ where+ open = do+ sock <- N.socket N.AF_INET N.Stream N.defaultProtocol+ N.setSocketOption sock N.ReuseAddr 1+ N.bind sock (N.SockAddrInet 0 (N.tupleToHostAddress (127, 0, 0, 1)))+ N.listen sock 16+ port <- N.socketPort sock+ connections <- newMVar []+ acceptor <- forkIO . forever $ do+ (conn, _) <- N.accept sock+ closed <- newEmptyMVar+ modifyMVar_ connections (pure . (closed :))+ void . forkIO $ readUntilClosed conn closed `finally` N.close conn+ pure (sock, acceptor, SilentBroker port connections)+ close (sock, acceptor, _) = killThread acceptor >> N.close sock+ readUntilClosed conn closed =+ (try (NB.recv conn 4096) :: IO (Either SomeException BS.ByteString)) >>= \case+ Right bytes | not (BS.null bytes) -> readUntilClosed conn closed+ _ -> void (tryPutMVar closed ())++-- | Wait (five seconds at most) until the client has connected, and return+-- the connections accepted so far.+awaitConnections :: SilentBroker -> IO [MVar ()]+awaitConnections broker = do+ deadline <- (+ 5) <$> getMonotonicTime+ let go = do+ connections <- readMVar (sbConnections broker)+ now <- getMonotonicTime+ if not (null connections)+ then pure connections+ else+ if now > deadline+ then assertFailure "the consumer did not connect within 5 seconds"+ else threadDelay 20000 >> go+ go++-- | Require every connection accepted so far to be closed by the deadline+-- (monotonic seconds).+allClosedBy :: SilentBroker -> [MVar ()] -> Double -> Assertion+allClosedBy broker earlier deadline = do+ connections <- readMVar (sbConnections broker)+ assertBool "connections accepted before destroy are tracked" (length connections >= length earlier)+ forM_ connections $ \closed -> do+ now <- getMonotonicTime+ let remaining = max 0 (deadline - now)+ result <- timeout (round (remaining * 1000000)) (readMVar closed)+ case result of+ Just () -> pure ()+ Nothing -> assertFailure "a broker connection was still open one second after destroyConsumer started"++-- | How many of the given connections the client has closed, allowing 200 ms+-- for the end-of-file to reach the listener.+countClosed :: SilentBroker -> [MVar ()] -> IO Int+countClosed _ connections =+ length . filter id+ <$> mapM (\closed -> maybe False (const True) <$> timeout 200000 (readMVar closed)) connections
+ test-integration/Kafka/Integration/DiagnosticContractTest.hs view
@@ -0,0 +1,133 @@+module Kafka.Integration.DiagnosticContractTest (tests) where++import Control.Concurrent (forkFinally, forkIOWithUnmask, killThread, threadDelay)+import Control.Concurrent.MVar (newEmptyMVar, putMVar, readMVar)+import Control.Exception (AsyncException (ThreadKilled), IOException, SomeException, bracket, finally, fromException, throwIO, try)+import Control.Monad (replicateM_)+import Data.ByteString.Char8 qualified as BS+import Data.Map.Strict qualified as M+import GHC.Conc (BlockReason (BlockedOnException), ThreadStatus (ThreadBlocked), threadStatus)+import Kafka.Consumer qualified as C+import Kafka.DiagnosticTestSupport+import Kafka.Dump+import Kafka.Producer qualified as P+import Kafka.ProducerTestSupport (nativeProducerProperty, withProducerTracking)+import Kafka.TestEnv+import System.Directory (getTemporaryDirectory, removeFile)+import System.IO (Handle, SeekMode (AbsoluteSeek), hClose, hFlush, hIsClosed, hPutStr, hSeek, hTell, openBinaryTempFile)+import System.IO.Error (ioeGetLocation)+import System.Timeout (timeout)+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.HUnit (assertBool, testCase, (@?=))++tests :: TestEnv -> TestTree+tests env =+ testGroup "diagnostics" $+ [ testCase "supported-property print flushes and preserves the caller handle" $+ withDiagnosticFault 0 $+ withOutput $ \_ handle -> do+ hPutStr handle "before\n"+ hPrintSupportedKafkaConf handle+ hIsClosed handle >>= (@?= False)+ mapM diagnosticStat [2, 3] >>= (@?= [1, 1])+ output <- readOutput handle+ assertBool (show output) ("before\n" `BS.isPrefixOf` output && "bootstrap.servers" `BS.isInfixOf` output && "auto.offset.reset" `BS.isInfixOf` output)+ hPutStr handle "after\n"+ hFlush handle+ readOutput handle >>= \result -> assertBool (show result) ("after\n" `BS.isSuffixOf` result),+ testCase "client print flushes and preserves the caller handle" $+ bracket (P.newProducer (P.brokersList (teBrokers env) <> P.extraProp "client.id" "diagnostic-client") >>= either throwIO pure) releaseProducer $ \producer ->+ withDiagnosticFault 0 $ withOutput $ \_ handle -> do+ hPrintKafka handle producer+ hIsClosed handle >>= (@?= False)+ mapM diagnosticStat [2, 3] >>= (@?= [1, 1])+ output <- readOutput handle+ assertBool (show output) ("diagnostic-client" `BS.isInfixOf` output)+ hPutStr handle "after\n"+ hFlush handle+ readOutput handle >>= \result -> assertBool (show result) ("after\n" `BS.isSuffixOf` result),+ testCase "failed fdopen releases the duplicate and preserves the original" $+ withDiagnosticFault 3 $+ withOutput $ \_ handle -> do+ result <- try @IOException (hPrintSupportedKafkaConf handle)+ case result of+ Left exception -> ioeGetLocation exception @?= "fdopen"+ Right _ -> throwIO (userError "injected fdopen failure was suppressed")+ hIsClosed handle >>= (@?= False)+ mapM diagnosticStat [2, 3, 4] >>= (@?= [0, 0, 0])+ hPutStr handle "still usable"+ hFlush handle,+ testCase "failed native flush is reported after closing the duplicate" $+ withDiagnosticFault 4 $+ withOutput $ \_ handle -> do+ result <- try @IOException (hPrintSupportedKafkaConf handle)+ case result of+ Left exception -> ioeGetLocation exception @?= "fclose"+ Right _ -> throwIO (userError "injected fclose failure was suppressed")+ hIsClosed handle >>= (@?= False)+ mapM diagnosticStat [2, 3, 4] >>= (@?= [1, 1, 0])+ hPutStr handle "still usable"+ hFlush handle,+ testCase "producer configuration dumps retain exact explicit and global settings" $+ bracket (P.newProducer (P.brokersList (teBrokers env) <> P.extraProp "client.id" "diagnostic-global" <> P.extraTopicProps (M.fromList [("message.timeout.ms", "2345"), ("compression.codec", "gzip")])) >>= either throwIO pure) releaseProducer $ \producer ->+ withDiagnosticFault 0 $ do+ replicateM_ 100 $ do+ global <- dumpKafkaConf producer+ M.lookup "client.id" global @?= Just "diagnostic-global"+ topic <- dumpTopicConf producer+ M.lookup "message.timeout.ms" topic @?= Just "2345"+ M.lookup "compression.codec" topic @?= Just "gzip"+ mapM diagnosticStat [0, 1] >>= (@?= [200, 200]),+ testCase "producer constructor log level overrides the global property on the native client" $+ withTopic env "producer-constructor-log" 1 $ \topic _ ->+ bracket (P.newProducer (P.brokersList (teBrokers env) <> P.extraProp "log_level" "2" <> P.logLevel P.KafkaLogWarning) >>= either throwIO pure) releaseProducer $ \producer -> withProducerTracking 0 $ do+ produceTo producer topic 0 "native-log-level"+ nativeProducerProperty 5 >>= (@?= Just "4")+ config <- dumpKafkaConf producer+ M.lookup "log_level" config @?= Just "2",+ testCase "consumer configuration dump preserves global settings after subscription merge" $+ bracket (C.newAssignedConsumer (C.brokersList (teBrokers env) <> C.groupId (makeGroupId env "diagnostic") <> C.extraProp "client.id" "diagnostic-consumer" <> C.callbackPollMode C.CallbackPollModeSync) >>= either throwIO pure) releaseConsumer $ \consumer -> do+ config <- dumpKafkaConf consumer+ M.lookup "client.id" config @?= Just "diagnostic-consumer"+ M.lookup "group.id" config @?= Just (C.unConsumerGroupId (makeGroupId env "diagnostic")),+ testCase "native dump counter detects an unreleased array" $ withDiagnosticFault 0 $ do+ diagnosticLeakControl+ mapM diagnosticStat [0, 1] >>= (@?= [1, 0])+ ]+ <> [ testCase (label <> " cancellation at native acquisition releases its array") $+ bracket (P.newProducer (P.brokersList (teBrokers env)) >>= either throwIO pure) releaseProducer $ \producer ->+ withDiagnosticFault fault (cancelled (action producer))+ | (label, fault, action) <- [("global", 1, dumpKafkaConf), ("topic", 2, dumpTopicConf)]+ ]++cancelled :: IO a -> IO ()+cancelled action = do+ done <- newEmptyMVar+ worker <- forkIOWithUnmask $ \unmask -> try @SomeException (unmask action) >>= putMVar done+ let bounded operation = timeout 5000000 operation >>= maybe (throwIO (userError "dump worker timed out")) pure+ flip finally (releaseDiagnosticBoundary >> bounded (readMVar done)) $ do+ awaitDiagnosticBoundary+ mapM diagnosticStat [0, 1] >>= (@?= [1, 0])+ killed <- newEmptyMVar+ killer <- forkFinally (killThread worker) (putMVar killed)+ let pending = threadStatus killer >>= \status -> if status == ThreadBlocked BlockedOnException then pure () else threadDelay 1000 >> pending+ bounded pending+ releaseDiagnosticBoundary+ bounded (readMVar done) >>= \case+ Left exception -> (fromException exception :: Maybe AsyncException) @?= Just ThreadKilled+ Right _ -> throwIO (userError "dump cancellation was not delivered")+ bounded (readMVar killed) >>= either throwIO pure+ mapM diagnosticStat [0, 1] >>= (@?= [1, 1])++withOutput :: (FilePath -> Handle -> IO a) -> IO a+withOutput action = do+ directory <- getTemporaryDirectory+ bracket (openBinaryTempFile directory "rdkafka-diagnostic-") (\(path, handle) -> hClose handle `finally` removeFile path) (uncurry action)++readOutput :: Handle -> IO BS.ByteString+readOutput handle = do+ end <- hTell handle+ hSeek handle AbsoluteSeek 0+ result <- BS.hGet handle (fromIntegral end)+ hSeek handle AbsoluteSeek end+ pure result
+ test-integration/Kafka/Integration/FatalErrorTest.hs view
@@ -0,0 +1,108 @@+-- | Regression test for the fork's consumer fatal-error fix.+--+-- A consumer with a @group.instance.id@ is a static group member. When a+-- second consumer joins the same group with the same instance id, the broker+-- fences the first one and librdkafka raises the fatal error+-- 'RdKafkaRespErrFencedInstanceId' on it. librdkafka delivers that only as a+-- consumer error on the consumer queue, never through @error_cb@, so before+-- the fix a consumer in 'CallbackPollModeAsync' could not observe it at all.+-- Both poll modes must now report @Left ('KafkaResponseError'+-- 'RdKafkaRespErrFatal')@ from every poll, with the cause recoverable from+-- 'consumerFatalError'.+module Kafka.Integration.FatalErrorTest+ ( tests,+ )+where++import Control.Concurrent (threadDelay)+import Control.Exception (bracket, finally, throwIO)+import Control.Monad (forM_, replicateM, void)+import Data.Map qualified as Map+import Data.Text qualified as Text+import Kafka.Consumer+import Kafka.TestEnv+import System.Timeout (timeout)+import Test.Tasty (TestTree, localOption, mkTimeout, testGroup)+import Test.Tasty.HUnit (Assertion, assertBool, assertFailure, testCase, (@?=))++tests :: TestEnv -> TestTree+tests env =+ localOption (mkTimeout 120000000) $+ testGroup+ "fatal"+ [ testCase "async" (fencedStaticMember env CallbackPollModeAsync),+ testCase "sync" (fencedStaticMember env CallbackPollModeSync)+ ]++fatal :: KafkaError+fatal = KafkaResponseError RdKafkaRespErrFatal++fencedStaticMember :: TestEnv -> CallbackPollMode -> Assertion+fencedStaticMember env mode = do+ let label = case mode of+ CallbackPollModeAsync -> "async"+ CallbackPollModeSync -> "sync"+ props =+ consumerProps env+ <> groupId (makeGroupId env ("fatal-" <> label))+ <> extraProps (Map.fromList [("group.instance.id", prefixedName env ("fatal-" <> label <> "-member"))])+ <> callbackPollMode mode+ withTopic env ("fatal-" <> label) 1 $ \topic producer -> do+ produceTo producer topic 0 "active-member"+ let acquireA = newConsumer props (topics [topic] <> offsetReset Earliest) >>= either throwIO pure+ releaseFenced consumer =+ ( closeConsumer consumer >>= \case+ Nothing -> pure ()+ Just err | err == fatal -> pure ()+ Just err -> throwIO err+ )+ `finally` destroyConsumer consumer+ bracket acquireA releaseFenced $ \a -> do+ first <- pollMessage a (Timeout 10000) >>= either throwIO pure+ (crTopic first, crPartition first, crOffset first, crValue first) @?= (topic, PartitionId 0, Offset 0, Just "active-member")+ assignmentLost a >>= (@?= False)+ -- B replaces A's static membership; the broker fences A.+ bracket (mkConsumerFor topic props) releaseConsumer $ \b -> do+ result <- timeout 30000000 (awaitFatal a b)+ case result of+ Nothing -> assertFailure "consumer A did not report a fatal error within 30 seconds of being fenced"+ Just () -> pure ()++ pollConsumerEvents a (Just (Timeout 0))+ assignmentLost b >>= (@?= False)++ again <- pollMessage a (Timeout 100)+ either Just (const Nothing) again @?= Just fatal++ -- The attributed poll reports the same fatal error, with no origin.+ pollMessageAttributed a (Timeout 100) >>= \case+ Left err -> err @?= ConsumerMessageError fatal Nothing Nothing Nothing+ Right record -> assertFailure ("unexpected record " <> show record)++ cause <- consumerFatalError a+ case cause of+ Just (err, description) -> do+ err @?= KafkaResponseError RdKafkaRespErrFencedInstanceId+ assertBool "expected a non-empty fatal error description" (not (Text.null description))+ Nothing -> assertFailure "consumerFatalError returned Nothing after a fatal poll"++ case mode of+ CallbackPollModeAsync -> do+ batches <- replicateM 3 (pollMessageBatch a (Timeout 100) (BatchSize 10))+ forM_ batches $ \batch ->+ (either Just (const Nothing) <$> batch) @?= [Just fatal]+ CallbackPollModeSync -> pure ()++-- | Poll A, and keep B's membership active, until A's poll reports the fatal+-- error. In sync mode A's own poll is also what serves its callbacks.+awaitFatal :: KafkaConsumer -> KafkaConsumer -> IO ()+awaitFatal a b = loop+ where+ loop = do+ res <- pollMessage a (Timeout 200)+ case res of+ Left err | err == fatal -> pure ()+ _ -> do+ void (pollMessage b (Timeout 200))+ threadDelay 50000+ loop
+ test-integration/Kafka/Integration/HeadersTest.hs view
@@ -0,0 +1,119 @@+-- | Record headers survive the real broker path in wire order (IR-3): the+-- list a consumer decodes is exactly the list the producer sent, repeated+-- names and identical pairs included, through both polling APIs in both+-- callback modes.+module Kafka.Integration.HeadersTest+ ( tests,+ )+where++import Control.Exception (bracket, throwIO)+import Control.Monad (forM_)+import Data.Bifunctor (first)+import Data.ByteString (ByteString)+import Data.Text (Text)+import Data.Text.Encoding (encodeUtf8)+import GHC.Clock (getMonotonicTime)+import Kafka.Consumer+import Kafka.Producer (ProducePartition (..), ProducerRecord (..))+import Kafka.TestEnv+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.HUnit (Assertion, assertFailure, testCase, (@?=))++-- | Which public polling function a case reads through.+data PollApi = PollMessage | PollMessageAttributed++data Fixture = Fixture+ { fxSlug :: Text,+ fxName :: String,+ fxHeaders :: [(ByteString, ByteString)],+ -- | header names and the value last-occurrence selection must return+ fxLast :: [(ByteString, Maybe ByteString)]+ }++tests :: TestEnv -> TestTree+tests env =+ testGroup+ "Headers wire order"+ [ testGroup+ (apiName <> " " <> modeName)+ [ testCase (fxName fx) (scenario env api mode (apiSlug <> "-" <> modeSlug) fx)+ | fx <- fixtures+ ]+ | (api, apiName, apiSlug) <- [(PollMessage, "pollMessage", "plain"), (PollMessageAttributed, "pollMessageAttributed", "attributed")],+ (mode, modeName, modeSlug) <- [(CallbackPollModeSync, "sync", "sync"), (CallbackPollModeAsync, "async", "async")]+ ]++fixtures :: [Fixture]+fixtures =+ [ Fixture+ "interleaved"+ "interleaved duplicate names keep wire order and last values"+ [("event-type", "Other"), ("account", "two"), ("account", "one"), ("event-type", "Happened")]+ [("event-type", Just "Happened"), ("account", Just "one"), ("absent", Nothing)],+ Fixture+ "distinct"+ "distinct names keep wire order"+ [("a-header", "1"), ("b-header", "2"), ("c-header", "3")]+ [("b-header", Just "2"), ("absent", Nothing)],+ Fixture+ "identical"+ "identical repeated pairs are not deduplicated"+ [("repeat", "same"), ("repeat", "same"), ("tail", "end")]+ [("repeat", Just "same"), ("tail", Just "end")],+ Fixture+ "single"+ "a single header round-trips"+ [("only", "value")]+ [("only", Just "value"), ("absent", Nothing)],+ Fixture+ "none"+ "no headers decode as an empty list"+ []+ [("absent", Nothing)]+ ]++-- | Produce one record carrying the fixture's headers to a fresh topic, read+-- it back through a fresh consumer group, and compare the complete list.+scenario :: TestEnv -> PollApi -> CallbackPollMode -> Text -> Fixture -> Assertion+scenario env api mode label fx =+ withTopic env suffix 1 $ \topic producer -> do+ let payload = encodeUtf8 suffix+ sendMessagesWithHeaders [ProducerRecord topic (SpecifiedPartition 0) Nothing (Just payload) mempty] (headersFromList (fxHeaders fx)) producer+ >>= either throwIO pure+ let props = consumerProps env <> groupId (makeGroupId env suffix) <> callbackPollMode mode+ bracket (mkConsumerFor topic props) releaseConsumer $ \consumer -> do+ record <- awaitRecord api consumer+ crTopic record @?= topic+ crPartition record @?= PartitionId 0+ crValue record @?= Just payload+ let received = headersToList (crHeaders record)+ received @?= fxHeaders fx+ forM_ (fxLast fx) $ \(name, expected) ->+ lastValue name received @?= expected+ where+ suffix = "headers-" <> label <> "-" <> fxSlug fx++-- | The value of the last header with the given name.+lastValue :: ByteString -> [(ByteString, ByteString)] -> Maybe ByteString+lastValue name = foldl' (\acc (n, v) -> if n == name then Just v else acc) Nothing++-- | The next record, retrying poll timeouts for at most ten seconds. Any other+-- error, or no record by the deadline, fails the case.+awaitRecord :: PollApi -> KafkaConsumer -> IO (ConsumerRecord (Maybe ByteString) (Maybe ByteString))+awaitRecord api consumer = do+ deadline <- (+ 10) <$> getMonotonicTime+ let go = do+ now <- getMonotonicTime+ if now > deadline+ then assertFailure "no record arrived within 10 seconds"+ else+ poll (Timeout 200) >>= \case+ Right record -> pure record+ Left (KafkaResponseError RdKafkaRespErrTimedOut) -> go+ Left err -> assertFailure ("poll failed: " <> show err)+ go+ where+ poll = case api of+ PollMessage -> pollMessage consumer+ PollMessageAttributed -> fmap (first cmeError) . pollMessageAttributed consumer
+ test-integration/Kafka/Integration/InputBoundaryContractTest.hs view
@@ -0,0 +1,89 @@+{-# OPTIONS_GHC -Wno-deprecations #-}++module Kafka.Integration.InputBoundaryContractTest (tests) where++import Control.Exception (bracket, throwIO)+import Control.Monad (void)+import Data.Map.Strict qualified as Map+import Data.Text qualified as Text+import Kafka.Consumer+import Kafka.Metadata+import Kafka.TestEnv+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.HUnit++tests :: TestEnv -> TestTree+tests env =+ testGroup "input-boundaries" $+ [ testCase (label <> " " <> name <> " rejects " <> invalid) $+ withTopic env (Text.pack ("input-" <> label <> "-" <> name <> "-" <> invalid)) 2 $ \topic producer -> do+ produceTo producer topic 1 "first"+ produceTo producer topic 1 "second"+ let props = brokersList (teBrokers env) <> groupId (makeGroupId env (Text.pack ("input-" <> label <> "-" <> name <> "-" <> invalid))) <> noAutoCommit <> noAutoOffsetStore <> callbackPollMode mode+ bracket (newAssignedConsumer props >>= either throwIO pure) releaseConsumer $ \consumer -> do+ assign consumer [TopicPartition topic (PartitionId 1) (PartitionOffset 0)] >>= (@?= Nothing)+ first <- pollMessage consumer (Timeout 10000) >>= either throwIO pure+ (crPartition first, crOffset first, crValue first) @?= (PartitionId 1, Offset 0, Just "first")+ let (badTopic, badPartition, expected) = bad topic+ record = first {crTopic = badTopic, crPartition = badPartition}+ action consumer record >>= (@?= Left expected)+ assignment consumer >>= (@?= Right (Map.singleton topic [PartitionId 1]))+ second <- pollMessage consumer (Timeout 10000) >>= either throwIO pure+ (crTopic second, crPartition second, crOffset second, crValue second) @?= (topic, PartitionId 1, Offset 1, Just "second")+ | (label, mode) <- [("async", CallbackPollModeAsync), ("sync", CallbackPollModeSync)],+ (invalid, bad) <- invalidInputs,+ (name, action) <- operations+ ]+ <> stringTests env+ where+ invalidInputs =+ [ ("nul-topic", \(TopicName name) -> (TopicName (name <> "\0suffix"), PartitionId 0, KafkaBadSpecification "topic name contains NUL")),+ ("overflow-partition", \topic -> (topic, PartitionId 4294967296, KafkaBadSpecification "partition is outside the C int range")),+ ("underflow-partition", \topic -> (topic, PartitionId (-2147483649), KafkaBadSpecification "partition is outside the C int range"))+ ]+ pairs record = [(crTopic record, crPartition record)]+ parts record = [TopicPartition (crTopic record) (crPartition record) (PartitionOffset 0)]+ maybeError action = maybe (Right ()) Left <$> action+ response action = action >>= \err -> pure (if err == KafkaResponseError RdKafkaRespErrNoError then Right () else Left err)+ operations =+ [ ("assign", \c r -> maybeError (assign c (parts r))),+ ("pause", \c r -> response (pausePartitions c (pairs r))),+ ("resume", \c r -> response (resumePartitions c (pairs r))),+ ("store", \c r -> maybeError (storeOffsets c (parts r))),+ ("store-message", \c r -> maybeError (storeOffsetMessage c r)),+ ("commit", \c r -> maybeError (commitPartitionsOffsets OffsetCommit c (parts r))),+ ("commit-message", \c r -> maybeError (commitOffsetMessage OffsetCommit c r)),+ ("committed", \c r -> void <$> committed c (Timeout 200) (pairs r)),+ ("position", \c r -> void <$> position c (pairs r)),+ ("legacy-seek", \c r -> maybeError (seek c (Timeout 200) (parts r))),+ ("seek", \c r -> maybeError (seekPartitions c (parts r) (Timeout 200))),+ ("timestamp", \c r -> void <$> offsetsForTime c (Timeout 200) (Millis 0) (pairs r)),+ ("watermark", \c r -> void <$> partitionWatermarkOffsets c (Timeout 200) (crTopic r) (crPartition r))+ ]++stringTests :: TestEnv -> [TestTree]+stringTests env =+ [ testCase (label <> " string queries and subscription reject NUL before native effects") $+ withTopic env (Text.pack ("input-strings-" <> label)) 1 $ \topic producer -> do+ let bad = TopicName (unTopicName topic <> "\0suffix")+ failure = KafkaBadSpecification "topic name contains NUL"+ partition = PartitionMetadata (PartitionId 0) Nothing (BrokerId 0) [BrokerId 0] [BrokerId 0]+ metadata = TopicMetadata bad [partition] Nothing+ props = brokersList (teBrokers env) <> groupId (makeGroupId env (Text.pack ("input-strings-" <> label))) <> noAutoCommit <> callbackPollMode mode+ topicMetadata producer (Timeout 200) bad >>= (@?= Left failure)+ watermarkOffsets producer (Timeout 200) bad >>= (@?= [Left failure])+ watermarkOffsets' producer (Timeout 200) metadata >>= (@?= [Left failure])+ topicOffsetsForTime producer (Timeout 200) (Millis 0) bad >>= (@?= Left failure)+ offsetsForTime' producer (Timeout 200) (Millis 0) metadata >>= (@?= Left failure)+ consumerGroupInfo producer (Timeout 200) (ConsumerGroupId "group\0suffix") >>= (@?= Left (KafkaBadSpecification "consumer group contains NUL"))+ created <- newConsumer props (topics [bad] <> offsetReset Earliest)+ case created of+ Left err -> err @?= failure+ Right consumer -> releaseConsumer consumer >> assertFailure "subscription accepted a truncated topic"+ bracket (newAssignedConsumer props >>= either throwIO pure) releaseConsumer $ \consumer -> do+ assign consumer [TopicPartition topic (PartitionId 0) (PartitionOffset 0)] >>= (@?= Nothing)+ assign consumer [TopicPartition topic (PartitionId 0) (PartitionOffset 1), TopicPartition bad (PartitionId 0) (PartitionOffset 0)] >>= (@?= Just failure)+ assignment consumer >>= (@?= Right (Map.singleton topic [PartitionId 0]))+ position consumer [(topic, PartitionId 2147483647)] >>= (@?= Right [TopicPartition topic (PartitionId 2147483647) PartitionOffsetInvalid])+ | (label, mode) <- [("async", CallbackPollModeAsync), ("sync", CallbackPollModeSync)]+ ]
+ test-integration/Kafka/Integration/LifecycleTest.hs view
@@ -0,0 +1,133 @@+-- | Client-lifecycle bindings against an address nothing listens on, so no+-- message can ever be delivered.+module Kafka.Integration.LifecycleTest+ ( tests,+ )+where++import Control.Concurrent (forkFinally, forkIOWithUnmask, killThread, threadDelay)+import Control.Concurrent.MVar (newEmptyMVar, putMVar, readMVar, tryPutMVar, tryReadMVar)+import Control.Exception (AsyncException (ThreadKilled), SomeException, bracket, finally, fromException, throwIO, try)+import Control.Monad (void)+import GHC.Clock (getMonotonicTime)+import GHC.Conc (BlockReason (BlockedOnException), ThreadStatus (ThreadBlocked), threadStatus)+import Kafka.Consumer qualified as C+import Kafka.Producer qualified as P+import Kafka.TestEnv (TestEnv, makeGroupId, prefixedName, releaseConsumer)+import Kafka.TransactionTestSupport+import System.Timeout (timeout)+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.HUnit (assertBool, assertFailure, testCase, (@?=))++-- | Port 1 on loopback: privileged, so nothing in the test environment+-- listens there.+unreachable :: P.BrokerAddress+unreachable = P.BrokerAddress "127.0.0.1:1"++tests :: TestEnv -> TestTree+tests env =+ testGroup+ "lifecycle"+ $ [ testCase "flushProducerTimeout times out, purgeProducer empties the queue" $ do+ reports <- newEmptyMVar+ let props =+ P.brokersList [unreachable]+ <> P.setCallback (P.deliveryCallback (void . tryPutMVar reports))+ withProducer props $ \prod -> do+ let record =+ P.ProducerRecord+ { P.prTopic = P.TopicName (prefixedName env "lifecycle"),+ P.prPartition = P.UnassignedPartition,+ P.prKey = Nothing,+ P.prValue = Just "never delivered",+ P.prHeaders = mempty+ }+ P.produceMessage prod record >>= (@?= Nothing)++ start <- getMonotonicTime+ flushed <- P.flushProducerTimeout prod (P.Timeout 500)+ elapsed <- subtract start <$> getMonotonicTime+ flushed @?= Just (P.KafkaResponseError P.RdKafkaRespErrTimedOut)+ assertBool ("flush took " <> show elapsed <> "s") (elapsed >= 0.4 && elapsed < 2)++ P.purgeProducer prod [P.PurgeQueue] >>= (@?= Nothing)+ P.flushProducerTimeout prod (P.Timeout 100) >>= (@?= Nothing)++ tryReadMVar reports >>= \case+ Just (P.DeliveryFailure _ err) -> err @?= P.KafkaResponseError P.RdKafkaRespErrPurgeQueue+ other -> assertFailure ("expected a purged delivery report, got " <> show other),+ testCase "consumerClosed is False until closeConsumer" $ do+ consumer <- newConsumer+ C.consumerClosed consumer >>= (@?= False)+ void (C.closeConsumer consumer)+ C.consumerClosed consumer >>= (@?= True),+ testCase "setSaslCredentials replaces credentials on a consumer" $ do+ consumer <- newConsumer+ C.setSaslCredentials consumer "user-1" "secret-1" >>= (@?= Nothing)+ C.setSaslCredentials consumer "user-2" "secret-2" >>= (@?= Nothing)+ void (C.closeConsumer consumer),+ testCase "setSaslCredentials replaces credentials on a producer" $+ withProducer (P.brokersList [unreachable]) $ \prod -> do+ P.setSaslCredentials prod "user-1" "secret-1" >>= (@?= Nothing)+ P.setSaslCredentials prod "user-2" "secret-2" >>= (@?= Nothing)+ ]+ <> [ testCase ("setSaslCredentials rejects NUL in " <> label <> " without changing producer or consumer identity") $ do+ let expected = Just (P.KafkaBadSpecification ("SASL " <> field <> " contains NUL"))+ withProducer (P.brokersList [unreachable]) $ \producer ->+ P.setSaslCredentials producer username password >>= (@?= expected)+ bracket newConsumer releaseConsumer $ \consumer ->+ C.setSaslCredentials consumer username password >>= (@?= expected)+ | (label, field, username, password) <- [("username", "username", "fixture\0other", "password"), ("password", "password", "fixture", "password\0other")]+ ]+ <> [ testCase "setSaslCredentials releases each actual native error after decoding its exact code" $ do+ withProducer (P.brokersList [unreachable]) $ \producer -> withTxFault 300 $ do+ P.setSaslCredentials producer "fixture" "password" >>= (@?= Just (P.KafkaResponseError P.RdKafkaRespErrInvalidArg))+ txStat 0 >>= (@?= 1)+ txStat 1 >>= (@?= 1)+ txStat 2 >>= (@?= 1)+ txStat 8 >>= (@?= 0)+ bracket newConsumer releaseConsumer $ \consumer -> withTxFault 300 $ do+ C.setSaslCredentials consumer "fixture" "password" >>= (@?= Just (C.KafkaResponseError C.RdKafkaRespErrInvalidArg))+ txStat 0 >>= (@?= 1)+ txStat 1 >>= (@?= 1)+ txStat 2 >>= (@?= 1)+ txStat 8 >>= (@?= 0)+ ]+ <> [ testCase ("setSaslCredentials cancellation at error " <> label <> " releases the owned error") $+ withProducer (P.brokersList [unreachable]) $ \producer ->+ withTxFault fault $+ cancelSetter (P.setSaslCredentials producer "fixture" "password")+ | (label, fault) <- [("decoding", 20), ("acquisition", 301)]+ ]+ where+ newConsumer =+ C.newConsumer (C.brokersList [unreachable] <> C.groupId (makeGroupId env "lifecycle")) mempty+ >>= either (assertFailure . ("newConsumer: " <>) . show) pure+ withProducer props =+ bracket+ (P.newProducer props >>= either (assertFailure . ("newProducer: " <>) . show) pure)+ -- Purge before closing: closeProducer flushes, which would wait forever+ -- for a broker that never answers.+ (\prod -> P.purgeProducer prod [P.PurgeQueue, P.PurgeInFlight] >> P.closeProducer prod)++cancelSetter :: IO (Maybe P.KafkaError) -> IO ()+cancelSetter action = do+ let bounded io = timeout 5000000 io >>= maybe (assertFailure "credential cancellation deadline") pure+ done <- newEmptyMVar+ worker <- forkIOWithUnmask $ \unmask -> try @SomeException (unmask action) >>= putMVar done+ flip finally (releaseTxBoundary >> bounded (readMVar done)) $ do+ awaitTxBoundary+ txStat 0 >>= (@?= 1)+ txStat 1 >>= (@?= 0)+ killed <- newEmptyMVar+ killer <- forkFinally (killThread worker) (putMVar killed)+ let awaitPending = threadStatus killer >>= \status -> if status == ThreadBlocked BlockedOnException then pure () else threadDelay 1000 >> awaitPending+ bounded awaitPending+ releaseTxBoundary+ bounded (readMVar done) >>= \case+ Left exception -> (fromException exception :: Maybe AsyncException) @?= Just ThreadKilled+ Right _ -> assertFailure "pending credential cancellation was not delivered"+ bounded (readMVar killed) >>= either throwIO pure+ txStat 0 >>= (@?= 1)+ txStat 1 >>= (@?= 1)+ txStat 8 >>= (@?= 0)
+ test-integration/Kafka/Integration/MetadataContractTest.hs view
@@ -0,0 +1,237 @@+module Kafka.Integration.MetadataContractTest (tests, runCancellationProbe) where++import Control.Concurrent (forkFinally, forkIOWithUnmask, killThread, threadDelay)+import Control.Concurrent.MVar (newEmptyMVar, putMVar, readMVar)+import Control.Exception (AsyncException (ThreadKilled), SomeException, bracket, finally, fromException, throwIO, try)+import Control.Monad (forM, forM_, replicateM_)+import Data.ByteString qualified as BS+import Data.List (sort)+import Data.Text qualified as Text+import GHC.Conc (BlockReason (BlockedOnException), ThreadStatus (ThreadBlocked), threadStatus)+import Kafka.CallbackTestSupport (runChildProbe)+import Kafka.Consumer+import Kafka.Metadata+import Kafka.MetadataTestSupport+import Kafka.Producer qualified as P+import Kafka.TestEnv+import System.Environment (lookupEnv)+import System.Exit (die)+import System.Timeout (timeout)+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.HUnit (assertBool, assertFailure, testCase, (@?=))++tests :: TestEnv -> TestTree+tests env =+ testGroup "metadata-contract" $+ [ testCase "native metadata counter detects an unreleased result" $ withMetadataFault 0 $ do+ metadataLeakControl (teBrokers env)+ mapM metadataStat [0, 1] >>= (@?= [1, 0]),+ testCase "native topic-constructor failure survives metadata convenience queries" $+ withClient env "native-topic-failure" $ \consumer -> do+ let tooLong = TopicName (Text.replicate 513 "x")+ failure = KafkaError "Local: Invalid argument or configuration"+ topicMetadata consumer (Timeout 200) tooLong >>= (@?= Left failure)+ watermarkOffsets consumer (Timeout 200) tooLong >>= (@?= [Left failure])+ topicOffsetsForTime consumer (Timeout 200) (Millis 0) tooLong >>= (@?= Left failure),+ testCase "empty native metadata remains empty and releases every result" $+ withTopic env "metadata-empty-frame" 1 $ \topic producer -> withMetadataFault 20 $ do+ metadata <- topicMetadata producer (Timeout 5000) topic >>= either throwIO pure+ kmTopics metadata @?= []+ watermarkOffsets producer (Timeout 5000) topic >>= (@?= [])+ topicOffsetsForTime producer (Timeout 5000) (Millis 0) topic >>= (@?= Left (KafkaResponseError RdKafkaRespErrInvalidArg))+ mapM metadataStat [0, 1] >>= (@?= [3, 3]),+ testCase "timestamp lookup preserves native overall errors" $+ withTopic env "metadata-overall-time-error" 1 $ \topic producer -> withMetadataFault 21 $ do+ offsetsForTime producer (Timeout 5000) (Millis 0) [(topic, PartitionId 0)] >>= (@?= Left (KafkaResponseError RdKafkaRespErrTimedOut))+ metadataStat 4 >>= (@?= 1),+ testCase "watermark queries preserve unknown partition errors and empty provided metadata" $+ withTopic env "metadata-watermark-boundaries" 1 $ \topic producer -> do+ partitionWatermarkOffsets producer (Timeout 5000) topic (PartitionId 42) >>= (@?= Left (KafkaResponseError RdKafkaRespErrUnknownPartition))+ let empty = TopicMetadata topic [] Nothing+ watermarkOffsets' producer (Timeout 5000) empty >>= (@?= [])+ offsetsForTime' producer (Timeout 5000) (Millis 0) empty >>= (@?= Left (KafkaResponseError RdKafkaRespErrInvalidArg)),+ testCase "topic identity replica sets and exact watermarks" $+ withTopic env "metadata-exact" 2 $ \topic producer -> do+ replicateM_ 3 (produceTo producer topic 0 "partition-zero")+ produceTo producer topic 1 "partition-one"+ withMetadataFault 0 $ do+ metadata <- topicMetadata producer (Timeout 5000) topic >>= either throwIO pure+ map tmTopicName (kmTopics metadata) @?= [topic]+ let brokers = map bmBrokerId (kmBrokers metadata)+ assertBool (show metadata) (kmOrigBroker metadata `elem` brokers)+ case kmTopics metadata of+ [tm] -> do+ tmError tm @?= Nothing+ sort (map pmPartitionId (tmPartitions tm)) @?= [PartitionId 0, PartitionId 1]+ forM_ (tmPartitions tm) $ \partition -> do+ pmError partition @?= Nothing+ assertBool (show partition) (pmLeader partition `elem` brokers)+ pmReplicas partition @?= [pmLeader partition]+ pmInSyncReplicas partition @?= [pmLeader partition]+ let expected = Right [WatermarkOffsets topic (PartitionId 0) (Offset 0) (Offset 3), WatermarkOffsets topic (PartitionId 1) (Offset 0) (Offset 1)]+ sequence <$> watermarkOffsets producer (Timeout 5000) topic >>= (@?= expected)+ sequence <$> watermarkOffsets' producer (Timeout 5000) tm >>= (@?= expected)+ other -> assertFailure (show other)+ allMetadata <- allTopicsMetadata producer (Timeout 5000) >>= either throwIO pure+ map tmTopicName (filter ((== topic) . tmTopicName) (kmTopics allMetadata)) @?= [topic]+ created <- metadataStat 0+ destroyed <- metadataStat 1+ (created, destroyed) @?= (3, 3),+ testCase "distinct native metadata fields retain exact identities and errors" $+ withTopic env "metadata-distinct-fields" 1 $ \topic producer ->+ withMetadataFault 19 $ do+ result <- topicMetadata producer (Timeout 5000) topic+ result @?= Right (KafkaMetadata [BrokerMetadata (BrokerId 7) "λ" 19092] [TopicMetadata topic [PartitionMetadata (PartitionId 42) (Just partitionFailure) (BrokerId 11) [BrokerId 13] [BrokerId 17]] (Just unknownTopic)] (BrokerId 19))+ mapM metadataStat [0, 1] >>= (@?= [1, 1]),+ testCase "provided metadata preserves partition failures in convenience helpers" $+ withTopic env "metadata-provided-errors" 2 $ \topic producer -> do+ produceTo producer topic 0 "zero"+ produceTo producer topic 1 "one"+ actual <- topicMetadata producer (Timeout 5000) topic >>= either throwIO pure+ case kmTopics actual of+ [metadata] -> do+ let failed = metadata {tmPartitions = [partition {pmError = if pmPartitionId partition == PartitionId 0 then Just partitionFailure else Nothing} | partition <- tmPartitions metadata]}+ watermarkOffsets' producer (Timeout 5000) failed >>= (@?= [Left partitionFailure, Right (WatermarkOffsets topic (PartitionId 1) (Offset 0) (Offset 1))])+ offsetsForTime' producer (Timeout 5000) (Millis 0) failed >>= (@?= Left partitionFailure)+ other -> assertFailure (show other),+ testCase "native metadata partition failures survive convenience helpers" $+ withTopic env "metadata-native-errors" 2 $ \topic producer -> do+ produceTo producer topic 0 "zero"+ produceTo producer topic 1 "one"+ withMetadataFault 3 $ do+ metadata <- topicMetadata producer (Timeout 5000) topic >>= either throwIO pure+ map (map pmError . tmPartitions) (kmTopics metadata) @?= [[Just partitionFailure, Nothing]]+ watermarkOffsets producer (Timeout 5000) topic >>= (@?= [Left partitionFailure, Right (WatermarkOffsets topic (PartitionId 1) (Offset 0) (Offset 1))])+ topicOffsetsForTime producer (Timeout 5000) (Millis 0) topic >>= (@?= Left partitionFailure)+ mapM metadataStat [0, 1] >>= (@?= [3, 3]),+ testCase "group query timeout preserves initial metadata wait failure" $+ bracket (P.newProducer (P.brokersList ["127.0.0.1:1"] <> P.suppressDisconnectLogs) >>= either throwIO pure) releaseProducer $ \producer -> do+ allConsumerGroupsInfo producer (Timeout 200) >>= (@?= Left (KafkaResponseError RdKafkaRespErrTimedOut))+ consumerGroupInfo producer (Timeout 200) (makeGroupId env "unreachable-group") >>= (@?= Left (KafkaResponseError RdKafkaRespErrTimedOut)),+ testCase "missing topic errors survive convenience helpers" $+ withClient env "missing-topic" $ \consumer -> do+ let absent = TopicName (prefixedName env "metadata-absent")+ metadata <- topicMetadata consumer (Timeout 5000) absent >>= either throwIO pure+ map (\topic -> (tmTopicName topic, tmError topic, tmPartitions topic)) (kmTopics metadata)+ @?= [(absent, Just unknownTopic, [])]+ watermarkOffsets consumer (Timeout 5000) absent >>= (@?= [Left unknownTopic])+ topicOffsetsForTime consumer (Timeout 5000) (Millis 0) absent >>= (@?= Left unknownTopic)+ let failed = TopicMetadata absent [] (Just unknownTopic)+ watermarkOffsets' consumer (Timeout 5000) failed >>= (@?= [Left unknownTopic])+ offsetsForTime' consumer (Timeout 5000) (Millis 0) failed >>= (@?= Left unknownTopic),+ testCase "timestamp lookup distinguishes before at and after actual record times" $+ withTopic env "metadata-times" 1 $ \topic producer -> do+ forM_ ["one", "two", "three"] $ \value -> produceTo producer topic 0 value >> threadDelay 5000+ withClient env "timestamps" $ \consumer -> do+ assign consumer [TopicPartition topic (PartitionId 0) (PartitionOffset 0)] >>= (@?= Nothing)+ records <- forM [0 .. 2] $ \offset -> do+ message <- pollMessage consumer (Timeout 10000) >>= either throwIO pure+ crOffset message @?= Offset offset+ case crTimestamp message of+ CreateTime (Millis time) -> pure time+ other -> assertFailure (show other)+ case records of+ [first, second, third] -> do+ assertBool (show records) (first < second && second < third)+ forM_ [(first - 1, PartitionOffset 0), (first, PartitionOffset 0), (second, PartitionOffset 1), (third, PartitionOffset 2), (third + 1, PartitionOffsetEnd)] $ \(time, expected) -> do+ let result = Right [TopicPartition topic (PartitionId 0) expected]+ offsetsForTime consumer (Timeout 5000) (Millis time) [(topic, PartitionId 0), (topic, PartitionId 0)] >>= (@?= result)+ topicOffsetsForTime consumer (Timeout 5000) (Millis time) topic >>= (@?= result)+ metadata <- topicMetadata consumer (Timeout 5000) topic >>= either throwIO pure+ case kmTopics metadata of+ [tm] -> offsetsForTime' consumer (Timeout 5000) (Millis second) tm >>= (@?= Right [TopicPartition topic (PartitionId 0) (PartitionOffset 1)])+ other -> assertFailure (show other)+ other -> assertFailure (show other)+ offsetsForTime consumer (Timeout 100) (Millis 0) [] >>= (@?= Left (KafkaResponseError RdKafkaRespErrInvalidArg)),+ testCase "mixed timestamp request preserves native partition failure" $+ withTopic env "metadata-mixed" 1 $ \topic producer -> do+ produceTo producer topic 0 "record"+ withClient env "mixed-time" $ \consumer -> do+ result <- offsetsForTime consumer (Timeout 5000) (Millis 0) [(topic, PartitionId 0), (topic, PartitionId 42)]+ result @?= Left (KafkaResponseError RdKafkaRespErrUnknownPartition),+ testCase "metadata timeouts preserve the native error" $+ bracket (P.newProducer (P.brokersList ["127.0.0.1:1"] <> P.extraProp "log_level" "0") >>= either throwIO pure) releaseProducer $ \producer -> do+ allTopicsMetadata producer (Timeout 100) >>= (@?= Left (KafkaResponseError RdKafkaRespErrTransport))+ topicMetadata producer (Timeout 100) (TopicName (prefixedName env "metadata-timeout")) >>= (@?= Left (KafkaResponseError RdKafkaRespErrTransport))+ ]+ <> [ testCase (label <> " native acquisition cancellation releases its result") $+ runChildProbe ("metadata-" <> label) ["--metadata-cancellation-probe", label]+ | label <- ["metadata", "groups"]+ ]+ <> [ testCase (label <> " group identity lifecycle and supported native states") $+ withTopic env (Text.pack ("metadata-group-" <> label)) 1 $ \topic producer -> do+ produceTo producer topic 0 "group-record"+ let group = makeGroupId env (Text.pack ("metadata-group-λ-配置-" <> label))+ props = brokersList (teBrokers env) <> groupId group <> clientId (ClientId (Text.pack ("metadata-client-λ-配置-" <> label))) <> noAutoCommit <> callbackPollMode mode <> extraProp "partition.assignment.strategy" "range"+ bracket (newConsumer props (topics [topic] <> offsetReset Earliest) >>= either throwIO pure) releaseConsumer $ \consumer -> do+ message <- pollMessage consumer (Timeout 10000) >>= either throwIO pure+ crValue message @?= Just "group-record"+ withMetadataFault 0 $ do+ described <- consumerGroupInfo producer (Timeout 5000) group >>= either throwIO pure+ map (\info -> (giGroup info, giError info, giState info, giProtocolType info)) described @?= [(group, Nothing, GroupStable, GroupProtocolType "consumer")]+ case described of+ [info] -> do+ map gmiClientId (giMembers info) @?= [ClientId (Text.pack ("metadata-client-λ-配置-" <> label))]+ giProtocol info @?= GroupProtocol "range"+ other -> assertFailure (show other)+ allGroups <- allConsumerGroupsInfo producer (Timeout 5000) >>= either throwIO pure+ filter ((== group) . giGroup) allGroups @?= described+ mapM metadataStat [2, 3] >>= (@?= [2, 2])+ forM_ [(10, GroupPreparingRebalance), (11, GroupAwaitingSync), (12, GroupAwaitingSync), (13, GroupStable), (14, GroupDead), (15, GroupEmpty)] $ \(fault, expected) ->+ withMetadataFault fault $ do+ result <- consumerGroupInfo producer (Timeout 5000) group+ fmap (map giState) result @?= Right [expected]+ mapM metadataStat [2, 3] >>= (@?= [1, 1])+ withMetadataFault 16 $ do+ result <- consumerGroupInfo producer (Timeout 5000) group+ result @?= Left (KafkaError "Unsupported Kafka consumer group state: FutureState")+ mapM metadataStat [2, 3] >>= (@?= [1, 1])+ withMetadataFault 18 $ do+ described <- consumerGroupInfo producer (Timeout 5000) group >>= either throwIO pure+ map giError described @?= [Just (KafkaResponseError RdKafkaRespErrGroupAuthorizationFailed)]+ mapM metadataStat [2, 3] >>= (@?= [1, 1])+ withMetadataFault 17 $ do+ described <- consumerGroupInfo producer (Timeout 5000) group >>= either throwIO pure+ map giMembers described @?= [[GroupMemberInfo (GroupMemberId "member-field-λ-配置") (ClientId "client-field-λ-配置") "host-field-λ-配置" (BS.pack [0, 1, 0, 255]) (BS.pack [255, 0, 2, 0, 3])]]+ mapM metadataStat [2, 3] >>= (@?= [1, 1])+ described <- consumerGroupInfo producer (Timeout 5000) group >>= either throwIO pure+ map giState described @?= [GroupEmpty]+ consumerGroupInfo producer (Timeout 5000) (makeGroupId env (Text.pack ("metadata-nonexistent-" <> label))) >>= (@?= Right [])+ | (label, mode) <- [("async", CallbackPollModeAsync), ("sync", CallbackPollModeSync)]+ ]++partitionFailure :: KafkaError+partitionFailure = KafkaResponseError RdKafkaRespErrTopicAuthorizationFailed++unknownTopic :: KafkaError+unknownTopic = KafkaResponseError RdKafkaRespErrUnknownTopicOrPart++withClient :: TestEnv -> Text.Text -> (KafkaConsumer -> IO a) -> IO a+withClient env label = bracket (newAssignedConsumer (brokersList (teBrokers env) <> groupId (makeGroupId env ("metadata-" <> label)) <> noAutoCommit <> callbackPollMode CallbackPollModeSync <> extraProp "allow.auto.create.topics" "false") >>= either throwIO pure) releaseConsumer++runCancellationProbe :: String -> IO ()+runCancellationProbe label = do+ brokers <- lookupEnv "RDKAFKA_TEST_BROKER" >>= either die pure . resolveBrokers+ env <- newTestEnv brokers+ withTopic env "metadata-cancel" 1 $ \topic producer -> case label of+ "metadata" -> withMetadataFault 1 (cancelled [1, 1, 0, 0] (topicMetadata producer (Timeout 5000) topic))+ "groups" -> withMetadataFault 2 (cancelled [0, 0, 1, 1] (consumerGroupInfo producer (Timeout 5000) (makeGroupId env "metadata-cancel-absent")))+ _ -> die "invalid metadata cancellation probe"++cancelled :: [Int] -> IO a -> IO ()+cancelled expected action = do+ done <- newEmptyMVar+ worker <- forkIOWithUnmask $ \unmask -> try @SomeException (unmask action) >>= putMVar done+ let bounded operation = timeout 10000000 operation >>= maybe (assertFailure "metadata worker timed out") pure+ flip finally (releaseMetadataBoundary >> bounded (readMVar done)) $ do+ awaitMetadataBoundary+ killed <- newEmptyMVar+ killer <- forkFinally (killThread worker) (putMVar killed)+ let pending = threadStatus killer >>= \status -> if status == ThreadBlocked BlockedOnException then pure () else threadDelay 1000 >> pending+ bounded pending+ releaseMetadataBoundary+ bounded (readMVar done) >>= \case+ Left exception -> (fromException exception :: Maybe AsyncException) @?= Just ThreadKilled+ Right _ -> assertFailure "metadata cancellation was not delivered"+ bounded (readMVar killed) >>= either throwIO pure+ mapM metadataStat [0 .. 3] >>= (@?= expected)
+ test-integration/Kafka/Integration/ObserverTest.hs view
@@ -0,0 +1,104 @@+-- | The queue event notification (IR-1) on an assign-only observer consumer+-- (IR-2), followed by teardown: the combined acceptance of+-- [consumer queue and teardown ownership](docs/adr/consumer-queue-and-teardown-ownership.md).+module Kafka.Integration.ObserverTest+ ( tests,+ )+where++import Control.Concurrent (threadWaitRead)+import Control.Exception (finally, onException, try)+import Control.Monad (void)+import Data.ByteString (ByteString)+import Data.ByteString qualified as BS+import Data.Text qualified as Text+import Foreign.Marshal.Alloc (allocaBytes)+import Foreign.Ptr (castPtr)+import GHC.Clock (getMonotonicTime)+import Kafka.Consumer+import Kafka.TestEnv+import System.Posix.IO (FdOption (..), closeFd, createPipe, fdReadBuf, setFdOption)+import System.Posix.Types (ByteCount, Fd)+import System.Timeout (timeout)+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.HUnit (Assertion, assertFailure, testCase, (@?=))++tests :: TestEnv -> TestTree+tests env =+ testGroup+ "observer"+ [ testCase "async" (scenario env CallbackPollModeAsync "async"),+ testCase "sync" (scenario env CallbackPollModeSync "sync")+ ]++scenario :: TestEnv -> CallbackPollMode -> String -> Assertion+scenario env mode label =+ withTopic env (Text.pack ("observer-" <> label)) 1 $ \topic producer -> do+ produceTo producer topic 0 "before"+ let props =+ consumerProps env+ <> groupId (makeGroupId env (Text.pack ("observer-" <> label)))+ <> noAutoCommit+ <> callbackPollMode mode+ consumer <- newAssignedConsumer props >>= either (assertFailure . ("newAssignedConsumer: " <>) . show) pure+ (rfd, wfd) <- createPipe+ -- On failure: disable the event, destroy the consumer, then close the+ -- descriptors. On success the scenario does the first two itself.+ let cleanup = setConsumerQueueIOEvent consumer Nothing >> destroyConsumer consumer+ flip finally (closeFd rfd >> closeFd wfd) . (`onException` cleanup) $ do+ setFdOption rfd NonBlockingRead True+ setFdOption wfd NonBlockingRead True++ -- Start at the end of the partition: the observer is idle.+ assign consumer [TopicPartition topic (PartitionId 0) (PartitionOffset 1)] >>= (@?= Nothing)+ setConsumerQueueIOEvent consumer (Just (wfd, "1"))+ void (drainQueue consumer)+ void (drainPipe rfd)++ produceTo producer topic 0 "first"+ timeout 10000000 (threadWaitRead rfd) >>= (@?= Just ())+ void (drainPipe rfd)+ awaitAttributed consumer >>= (@?= (PartitionId 0, Offset 1, "first"))++ -- Reassigning (back to the start) keeps the notification flowing.+ void (drainQueue consumer)+ void (drainPipe rfd)+ assign consumer [TopicPartition topic (PartitionId 0) (PartitionOffset 0)] >>= (@?= Nothing)+ timeout 10000000 (threadWaitRead rfd) >>= (@?= Just ())+ void (drainPipe rfd)+ awaitAttributed consumer >>= (@?= (PartitionId 0, Offset 0, "before"))++ setConsumerQueueIOEvent consumer Nothing+ destroyConsumer consumer++-- | The next record's origin and value via 'pollMessageAttributed', skipping+-- timeouts and non-record events, for at most ten seconds.+awaitAttributed :: KafkaConsumer -> IO (PartitionId, Offset, ByteString)+awaitAttributed consumer = do+ deadline <- (+ 10) <$> getMonotonicTime+ let go = do+ now <- getMonotonicTime+ if now > deadline+ then assertFailure "no record arrived within 10 seconds"+ else+ pollMessageAttributed consumer (Timeout 500) >>= \case+ Right record -> pure (crPartition record, crOffset record, maybe "" id (crValue record))+ Left _ -> go+ go++drainQueue :: KafkaConsumer -> IO Int+drainQueue consumer = go (0 :: Int) (50 :: Int)+ where+ go n 0 = pure n+ go n budget =+ pollMessage consumer (Timeout 200) >>= \case+ Right _ -> go (n + 1) (budget - 1)+ Left (KafkaResponseError RdKafkaRespErrTimedOut) -> pure n+ Left _ -> go n (budget - 1)++drainPipe :: Fd -> IO ByteString+drainPipe fd =+ allocaBytes 64 $ \buf ->+ (try (fdReadBuf fd buf 64) :: IO (Either IOError ByteCount)) >>= \case+ Right count | count > 0 -> (<>) <$> BS.packCStringLen (castPtr buf, fromIntegral count) <*> drainPipe fd+ _ -> pure BS.empty
+ test-integration/Kafka/Integration/PartitionListContractTest.hs view
@@ -0,0 +1,137 @@+module Kafka.Integration.PartitionListContractTest (tests) where++import Control.Concurrent (forkFinally, forkIOWithUnmask, killThread, threadDelay)+import Control.Concurrent.MVar (newEmptyMVar, putMVar, readMVar, tryReadMVar)+import Control.Exception (AsyncException (ThreadKilled), IOException, SomeException, bracket, bracket_, finally, fromException, throwIO, try)+import Control.Monad (replicateM_)+import Data.Either (isLeft)+import Data.Map.Strict qualified as Map+import Data.Text qualified as Text+import Foreign.C.Types (CInt (..))+import GHC.Conc (BlockReason (BlockedOnException), ThreadStatus (ThreadBlocked), threadStatus)+import GHC.IO.Encoding (TextEncoding, getForeignEncoding, latin1, setForeignEncoding, utf8)+import Kafka.Consumer+import Kafka.TestEnv+import System.Mem (performGC)+import System.Timeout (timeout)+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.HUnit++foreign import ccall unsafe "rdkafka_hs_test_lists_begin" begin :: CInt -> IO ()++foreign import ccall unsafe "rdkafka_hs_test_lists_end" end :: IO ()++foreign import ccall unsafe "rdkafka_hs_test_lists_release" release :: IO ()++foreign import ccall unsafe "rdkafka_hs_test_lists_stat" stat :: CInt -> IO CInt++foreign import ccall unsafe "rdkafka_hs_test_lists_control" control :: CInt -> IO ()++withLists :: Int -> IO a -> IO a+withLists mode = bracket_ (begin (fromIntegral mode)) (release >> performGC >> threadDelay 10000 >> end)++counts :: IO (Int, Int, Int)+counts = (,,) <$> value 0 <*> value 1 <*> value 2+ where+ value i = fromIntegral <$> stat i++balanced :: Int -> IO ()+balanced n = counts >>= (@?= (n, n, 0))++encoding :: TextEncoding -> IO a -> IO a+encoding selected action = bracket getForeignEncoding setForeignEncoding $ \_ -> setForeignEncoding selected >> action++tests :: TestEnv -> TestTree+tests env =+ testGroup "partition-list-ownership" $+ [ testCase "counter detects a retained native list before explicit release" $ withLists 0 $ do+ control 0+ flip finally (control 1) (counts >>= (@?= (1, 0, 1)))+ balanced 1+ ]+ <> [ testGroup+ label+ [ testCase "pair conversion failure releases the partial list before GC" $ fixture False "pair-encoding" $ \_ c -> withLists 0 $ do+ result <- try @IOException $ encoding latin1 $ position c [("ascii", PartitionId 0), ("λ", PartitionId 0)]+ assertBool (show result) (isLeft result)+ balanced 1,+ testCase "offset conversion failure releases the partial list before GC" $ fixture False "offset-encoding" $ \_ c -> withLists 0 $ do+ result <- try @IOException $ encoding latin1 $ storeOffsets c [part "ascii", part "λ"]+ assertBool (show result) (isLeft result)+ balanced 1,+ testCase "ordinary input lists release after exact native results" $ fixture False "input-success" $ \topic c -> withLists 0 $ do+ replicateM_ 3 $ position c [(topic, PartitionId 0)] >>= (@?= Right [TopicPartition topic (PartitionId 0) PartitionOffsetInvalid])+ balanced 3+ assign c [part topic] >>= (@?= Nothing)+ balanced (if mode == CallbackPollModeAsync then 5 else 4),+ testCase "native logical offsets decode independently without losing partition identity" $ fixture False "logical-offsets" $ \topic c -> withLists 6 $ do+ let offsets = [PartitionOffsetBeginning, PartitionOffsetEnd, PartitionOffsetStored, PartitionOffsetInvalid, PartitionOffsetInvalid, PartitionOffset 0, PartitionOffset maxBound]+ position c [(topic, PartitionId p) | p <- [0 .. 6]]+ >>= (@?= Right [TopicPartition topic (PartitionId p) offset | (p, offset) <- zip [0 ..] offsets])+ balanced 1,+ testCase "missing native partition queue preserves assignment and later forwarding" $ fixture False "missing-queue" $ \topic c -> do+ withLists 8 $ do+ assign c [part topic] >>= (@?= Nothing)+ stat 4 >>= (@?= if mode == CallbackPollModeAsync then 2 else 0)+ balanced (if mode == CallbackPollModeAsync then 2 else 1)+ withLists 0 $ do+ assign c [part topic] >>= (@?= Nothing)+ assignment c >>= (@?= Right (Map.singleton topic [PartitionId 0]))+ balanced (if mode == CallbackPollModeAsync then 3 else 2),+ testCase "assignment outputs release after exact decoding" $ fixture False "assignment-success" $ \topic c -> do+ assign c [part topic] >>= (@?= Nothing)+ withLists 0 $ do+ replicateM_ 3 $ assignment c >>= (@?= Right (Map.singleton topic [PartitionId 0]))+ balanced 3,+ testCase "subscription outputs release after exact decoding" $ fixture True "subscription-success" $ \topic c -> withLists 0 $ do+ replicateM_ 3 $ subscription c >>= (@?= Right [(topic, SubscribedPartitionsAll)])+ balanced 3,+ testCase "subscription acquisition failure preserves the native error without a list" $ fixture False "subscription-error" $ \_ c -> withLists 7 $ do+ subscription c >>= (@?= Left (KafkaResponseError RdKafkaRespErrUnknownGroup))+ balanced 0,+ testCase "assignment decoder failure releases the owned output" $ fixture False "assignment-decode" $ \topic c -> do+ assign c [part topic] >>= (@?= Nothing)+ withLists 2 $ do+ result <- try @IOException $ encoding utf8 $ assignment c+ assertBool (show result) (isLeft result)+ balanced 1,+ testCase "subscription decoder failure releases the owned output" $ fixture True "subscription-decode" $ \_ c -> withLists 3 $ do+ result <- try @IOException $ encoding utf8 $ subscription c+ assertBool (show result) (isLeft result)+ balanced 1,+ testCase "cancellation at input allocation releases the owned list" $ fixture False "input-cancel" $ \topic c -> withLists 4 $ cancelled (position c [(topic, PartitionId 0)]),+ testCase "cancellation at assignment return releases the owned output" $ fixture False "output-cancel" $ \topic c -> do+ assign c [part topic] >>= (@?= Nothing)+ withLists 5 $ cancelled (assignment c)+ ]+ | (label, mode) <- [("async", CallbackPollModeAsync), ("sync", CallbackPollModeSync)],+ let fixture subscribed name action = withTopic env (Text.pack ("lists-" <> label <> "-" <> name)) 1 $ \topic _ ->+ let props = brokersList (teBrokers env) <> groupId (makeGroupId env (Text.pack ("lists-" <> label <> "-" <> name))) <> noAutoCommit <> callbackPollMode mode+ create = if subscribed then newConsumer props (topics [topic] <> offsetReset Earliest) else newAssignedConsumer props+ in bracket (create >>= either throwIO pure) releaseConsumer (action topic)+ ]+ where+ part topic = TopicPartition topic (PartitionId 0) (PartitionOffset 0)++bounded :: IO a -> IO a+bounded action = timeout 10000000 action >>= maybe (assertFailure "partition-list boundary timed out") pure++cancelled :: IO a -> IO ()+cancelled action = do+ done <- newEmptyMVar+ worker <- forkIOWithUnmask $ \unmask -> try @SomeException (unmask action) >>= putMVar done+ flip finally (release >> bounded (readMVar done)) $ do+ let awaitBoundary = stat 3 >>= \n -> if n > 0 then pure () else threadDelay 1000 >> awaitBoundary+ bounded awaitBoundary+ counts >>= (@?= (1, 0, 1))+ killed <- newEmptyMVar+ killer <- forkFinally (killThread worker) (putMVar killed)+ let awaitPending = threadStatus killer >>= \s -> if s == ThreadBlocked BlockedOnException then pure () else threadDelay 1000 >> awaitPending+ bounded awaitPending+ tryReadMVar done >>= maybe (pure ()) (const (assertFailure "operation returned while allocation was held"))+ release+ bounded (readMVar done) >>= \case+ Left err -> (fromException err :: Maybe AsyncException) @?= Just ThreadKilled+ Right _ -> assertFailure "pending cancellation was not delivered"+ bounded (readMVar killed) >>= either throwIO pure+ balanced 1
+ test-integration/Kafka/Integration/PerMessageCommitTest.hs view
@@ -0,0 +1,41 @@+module Kafka.Integration.PerMessageCommitTest+ ( tests,+ )+where++import Control.Monad (forM)+import Kafka.Consumer+import Kafka.TestEnv+import Test.Tasty (DependencyType (AllSucceed), TestTree, dependentTestGroup)+import Test.Tasty.HUnit (testCase, (@?=))++tests :: TestEnv -> TestTree+tests env =+ dependentTestGroup+ "Per-message commit"+ AllSucceed+ [ withProducer env $ \getProducer ->+ testCase "1. sends 2 messages to test topic" $ do+ res <- getProducer >>= sendMessages (testMessages (teTopic env))+ res @?= Right (),+ withConsumer env (consumerProps env) $ \getConsumer ->+ testCase "2. should receive 2 messages" $ do+ k <- getConsumer+ res <- receiveTestMessages env k 2 0+ length <$> res @?= Right 2++ comRes <- forM res . mapM $ commitOffsetMessage OffsetCommit k+ comRes @?= Right [Nothing, Nothing],+ withProducer env $ \getProducer ->+ testCase "3. sends 2 messages to test topic" $ do+ res <- getProducer >>= sendMessages (testMessages (teTopic env))+ res @?= Right (),+ withConsumer env (consumerProps env) $ \getConsumer ->+ testCase "4. should receive 2 messages again" $ do+ k <- getConsumer+ res <- receiveTestMessages env k 2 2+ comRes <- commitAllOffsets OffsetCommit k++ length <$> res @?= Right 2+ comRes @?= Nothing+ ]
+ test-integration/Kafka/Integration/ProducerPropertyTest.hs view
@@ -0,0 +1,65 @@+module Kafka.Integration.ProducerPropertyTest (tests) where++import Control.Concurrent.MVar (newEmptyMVar, putMVar, takeMVar)+import Control.Exception (bracket, throwIO)+import Data.IORef (atomicModifyIORef', newIORef, readIORef)+import Kafka.Producer+import Kafka.PropertySupport+import Kafka.TestEnv (releaseProducer)+import System.Mem (performMajorGC)+import System.Timeout (timeout)+import Test.Tasty (TestTree)+import Test.Tasty.HUnit (assertFailure, (@?=))+import Test.Tasty.QuickCheck qualified as QC++tests :: TestTree+tests =+ generatedGroup+ "producer-properties"+ [ QC.testProperty "callback composition preserves order and identity" $+ QC.forAllShrink programs shrinkPrograms $ \input@(a, b, c, leftAssociated) -> QC.ioProperty $ do+ result <- observeCallbacks a b c leftAssociated+ -- The helper has returned, so this GC does not root a producer on the+ -- property's stack while subsequent native cases allocate clients.+ performMajorGC+ let labels = a <> b <> c+ expected = case reverse labels of [] -> []; lastLabel : _ -> [(lastLabel, expectedReport)]+ pure $ QC.counterexample (show input) (result QC.=== (length labels, expected, expectedReport))+ ]++programs :: QC.Gen ([Int], [Int], [Int], Bool)+programs = (,,,) <$> labels <*> labels <*> labels <*> QC.elements [False, True]+ where+ labels = boundedList 6 (QC.choose (0, 5))++shrinkPrograms :: ([Int], [Int], [Int], Bool) -> [([Int], [Int], [Int], Bool)]+shrinkPrograms (a, b, c, association) =+ [(a', b, c, association) | a' <- QC.shrinkList QC.shrink a]+ <> [(a, b', c, association) | b' <- QC.shrinkList QC.shrink b]+ <> [(a, b, c', association) | c' <- QC.shrinkList QC.shrink c]+ <> [(a, b, c, False) | association]++record :: ProducerRecord+record = ProducerRecord (TopicName "producer-property-callbacks") (SpecifiedPartition 0) Nothing (Just "generated callback") mempty++expectedReport :: DeliveryReport+expectedReport = DeliveryFailure record (KafkaResponseError RdKafkaRespErrPurgeQueue)++{-# NOINLINE observeCallbacks #-}+observeCallbacks :: [Int] -> [Int] -> [Int] -> Bool -> IO (Int, [(Int, DeliveryReport)], DeliveryReport)+observeCallbacks a b c leftAssociated = do+ observed <- newIORef []+ done <- newEmptyMVar+ let callbacks = foldMap $ \label -> setCallback (deliveryCallback (\report -> atomicModifyIORef' observed (\reports -> (reports <> [(label, report)], ()))))+ p = callbacks a+ q = callbacks b+ r = callbacks c+ composed = if leftAssociated then ((p <> mempty) <> q) <> r else p <> (mempty <> (q <> r))+ props = brokersList [BrokerAddress "127.0.0.1:1"] <> extraProp "log_level" "0" <> composed+ bracket (newProducer props >>= either throwIO pure) releaseProducer $ \producer -> do+ produceMessage' producer record (putMVar done) >>= (@?= Right ())+ purgeProducer producer [PurgeQueue] >>= (@?= Nothing)+ flushProducerTimeout producer (Timeout 1000) >>= (@?= Nothing)+ report <- timeout 5000000 (takeMVar done) >>= maybe (assertFailure "generated callback did not complete") pure+ reports <- readIORef observed+ pure (length (ppCallbacks composed), reports, report)
+ test-integration/Kafka/Integration/ProducerRegressionTest.hs view
@@ -0,0 +1,541 @@+module Kafka.Integration.ProducerRegressionTest (tests, runCallbackProbe) where++import Control.Concurrent (forkFinally, killThread, runInBoundThread, threadDelay)+import Control.Concurrent.MVar (MVar, newEmptyMVar, putMVar, readMVar, takeMVar, tryPutMVar, tryReadMVar)+import Control.Exception (AsyncException (ThreadKilled), MaskingState (Unmasked), SomeException, bracket, finally, fromException, getMaskingState, throwIO, try)+import Control.Monad (forM_, replicateM, void)+import Data.ByteString qualified as BS+import Data.IORef (IORef, atomicModifyIORef', mkWeakIORef, newIORef, readIORef)+import Data.List (isInfixOf)+import Data.Map qualified as Map+import Data.Text qualified as Text+import Foreign.C.Types (CInt)+import GHC.Conc (BlockReason (BlockedOnException), ThreadStatus (ThreadBlocked), getUncaughtExceptionHandler, setUncaughtExceptionHandler, threadStatus)+import Kafka.CallbackTestSupport (assertRetained, awaitCollected)+import Kafka.Consumer qualified as C+import Kafka.Metadata (KafkaMetadata (..), PartitionMetadata (..), TopicMetadata (..), topicMetadata)+import Kafka.Producer+import Kafka.ProducerTestSupport+import Kafka.TestEnv (TestEnv, consumerProps, makeGroupId, prefixedName, producerProps, receiveMessages, releaseConsumer, releaseProducer, sendMessages, withTopic)+import System.Directory (createDirectoryIfMissing)+import System.Environment (getEnvironment, getExecutablePath, lookupEnv)+import System.Exit (ExitCode (ExitSuccess))+import System.Mem.Weak (Weak)+import System.Process (CreateProcess (env), proc, readCreateProcessWithExitCode)+import System.Random (randomIO)+import System.Timeout (timeout)+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.HUnit (assertBool, assertFailure, testCase, (@?=))++tests :: TestEnv -> TestTree+tests env =+ testGroup+ "producer-regressions"+ $ [ testCase "explicit topic timeout expires an accepted message" $+ checkTimeout (sendTimeout (Timeout 1000)),+ testCase "global timeout still expires an accepted message" $+ checkTimeout (extraProp "message.timeout.ms" "1000"),+ testCase "queue-full rejection releases callback capture without invoking it" $+ withProducer (extraProp "queue.buffering.max.messages" "1") $ \producer -> do+ produceMessage producer record >>= (@?= Nothing)+ calls <- newIORef 0+ (result, weak) <- enqueueCapture producer record calls Nothing+ result @?= Left (ImmediateError (KafkaResponseError RdKafkaRespErrQueueFull))+ awaitCollected weak+ readIORef calls >>= (@?= 0),+ testCase "accepted callback retains its capture until a purged report completes" $+ withProducer mempty $ \producer -> do+ calls <- newIORef 0+ reports <- newEmptyMVar+ (result, weak) <- enqueueCapture producer record calls (Just reports)+ result @?= Right ()+ assertRetained weak+ purgeProducer producer [PurgeQueue] >>= (@?= Nothing)+ flushProducerTimeout producer (Timeout 1000) >>= (@?= Nothing)+ takeWithin reports >>= (@?= DeliveryFailure record (KafkaResponseError RdKafkaRespErrPurgeQueue))+ awaitCollected weak+ readIORef calls >>= (@?= 1),+ testCase "throwing global callback preserves per-message delivery and releases capture" $+ callbackChild "global",+ testCase "throwing per-message callback reports exception and releases capture" $+ callbackChild "message",+ testCase "repeated queue-full rejections release every callback capture" $+ withProducer (extraProp "queue.buffering.max.messages" "1") $ \producer -> do+ produceMessage producer record >>= (@?= Nothing)+ calls <- newIORef 0+ captures <- replicateM 50 $ do+ (result, weak) <- enqueueCapture producer record calls Nothing+ result @?= Left (ImmediateError (KafkaResponseError RdKafkaRespErrQueueFull))+ pure weak+ mapM_ awaitCollected captures+ readIORef calls >>= (@?= 0),+ testCase "cancellation at a rejected enqueue releases capture before unmasking" $+ withProducer mempty $ \producer -> withProducerTracking 1 $ do+ weakReady <- newEmptyMVar+ completed <- newEmptyMVar+ reports <- newEmptyMVar+ calls <- newIORef 0+ worker <- forkFinally (enqueueObservedCapture producer record calls weakReady reports) (putMVar completed)+ flip finally (releaseEnqueueBoundary >> killThread worker) $ do+ awaitEnqueueBoundary+ weak <- takeWithin weakReady+ assertRetained weak+ killed <- newEmptyMVar+ killer <- forkFinally (killThread worker) (putMVar killed)+ awaitCondition ((== ThreadBlocked BlockedOnException) <$> threadStatus killer)+ releaseEnqueueBoundary+ takeWithin completed >>= \case+ Left exception -> fromException exception @?= Just ThreadKilled+ Right value -> assertFailure ("cancellation failed: " <> show value)+ takeWithin killed >>= either throwIO pure+ awaitCollected weak+ readIORef calls >>= (@?= 0)+ flushProducerTimeout producer (Timeout 0) >>= (@?= Nothing),+ testCase "cancellation after native acceptance retains callback until its report" $+ withProducer mempty $ \producer -> withProducerTracking 2 $ do+ weakReady <- newEmptyMVar+ reports <- newEmptyMVar+ completed <- newEmptyMVar+ calls <- newIORef 0+ worker <- forkFinally (enqueueObservedCapture producer record calls weakReady reports) (putMVar completed)+ flip finally (releaseEnqueueBoundary >> killThread worker) $ do+ awaitEnqueueBoundary+ weak <- takeWithin weakReady+ assertRetained weak+ killed <- newEmptyMVar+ killer <- forkFinally (killThread worker) (putMVar killed)+ awaitCondition ((== ThreadBlocked BlockedOnException) <$> threadStatus killer)+ releaseEnqueueBoundary+ takeWithin completed >>= \case+ Left exception -> fromException exception @?= Just ThreadKilled+ Right value -> assertFailure ("cancellation failed: " <> show value)+ takeWithin killed >>= either throwIO pure+ assertRetained weak+ purgeProducer producer [PurgeQueue] >>= (@?= Nothing)+ flushProducerTimeout producer (Timeout 1000) >>= (@?= Nothing)+ takeWithin reports >>= (@?= DeliveryFailure record (KafkaResponseError RdKafkaRespErrPurgeQueue))+ awaitCollected weak+ readIORef calls >>= (@?= 1),+ testCase "another poller can deliver before successful enqueue returns" $+ withTopic env "producer-transfer-race" 1 $ \topic producer -> withProducerTracking 2 $ do+ let actual = record {prTopic = topic}+ calls <- newIORef 0+ reports <- newEmptyMVar+ completed <- newEmptyMVar+ worker <- forkFinally (enqueueCapture producer actual calls (Just reports)) (putMVar completed)+ flip finally (releaseEnqueueBoundary >> killThread worker) $ do+ awaitEnqueueBoundary+ flushProducerTimeout producer (Timeout 5000) >>= (@?= Nothing)+ takeWithin reports >>= (@?= DeliverySuccess actual (C.Offset 0))+ tryReadMVar completed >>= \case+ Nothing -> pure ()+ Just _ -> assertFailure "enqueue caller passed the native barrier before release"+ releaseEnqueueBoundary+ takeWithin completed >>= \case+ Left exception -> throwIO exception+ Right (result, weak) -> do+ result @?= Right ()+ awaitCollected weak+ readIORef calls >>= (@?= 1),+ testCase "running callback keeps its capture after the native root is released" $+ withProducer mempty $ \producer -> do+ started <- newEmptyMVar+ done <- newEmptyMVar+ (weak, _) <- bracket newEmptyMVar (`putMVar` ()) $ \resume -> do+ weak <- enqueueBlockedCapture producer record started resume done+ purgeProducer producer [PurgeQueue] >>= (@?= Nothing)+ flushProducerTimeout producer (Timeout 1000) >>= (@?= Nothing)+ takeWithin started+ assertRetained weak+ flushProducerTimeout producer (Timeout 0) >>= (@?= Nothing)+ pure (weak, ())+ takeWithin done+ awaitCollected weak,+ testCase "native error decoding failure releases rejected callback capture" $+ withProducer mempty $ \producer -> withProducerTracking 3 $ do+ calls <- newIORef 0+ ready <- newEmptyMVar+ reports <- newEmptyMVar+ outcome <- try @SomeException (enqueueObservedCapture producer record calls ready reports)+ case outcome of+ Left exception -> assertBool (show exception) ("32767" `isInfixOf` show exception)+ Right result -> assertFailure ("undecodable native error returned " <> show result)+ weak <- takeWithin ready+ nativeProducerProperty 1 >>= (@?= Just "60000")+ awaitCollected weak+ flushProducerTimeout producer (Timeout 0) >>= (@?= Nothing)+ readIORef calls >>= (@?= 0),+ testCase "non-null native success-code error rejects and releases capture" $+ withProducer mempty $ \producer -> withProducerTracking 4 $ do+ calls <- newIORef 0+ (result, weak) <- enqueueCapture producer record calls Nothing+ result @?= Left (ImmediateError KafkaInvalidReturnValue)+ awaitCollected weak+ flushProducerTimeout producer (Timeout 0) >>= (@?= Nothing)+ readIORef calls >>= (@?= 0),+ testCase "unknown native error code is preserved instead of reading errno" $+ runInBoundThread $+ withProducer mempty $ \producer -> withProducerTracking 5 $ do+ calls <- newIORef 0+ (result, weak) <- enqueueCapture producer record calls Nothing+ result @?= Left (ImmediateError (KafkaResponseError RdKafkaRespErrUnknown))+ awaitCollected weak+ flushProducerTimeout producer (Timeout 0) >>= (@?= Nothing)+ readIORef calls >>= (@?= 0)+ ]+ <> [ testCase ("actual client configuration: " <> label) $+ withProducerRaw props $ \producer -> withProducerTracking 0 $ do+ produceMessage producer record >>= (@?= Nothing)+ nativeProducerProperty 1 >>= (@?= Just expected)+ forM_ extras $ \(index, value) -> nativeProducerProperty index >>= (@?= Just value)+ | (label, props, expected, extras) <-+ [ ("defaults", mempty, "300000", [(2, "none")]),+ ("global only", extraProp "message.timeout.ms" "1200", "1200", []),+ ("topic only", sendTimeout (Timeout 1300), "1300", []),+ ("disjoint maps", extraProp "client.id" "preserved-client" <> extraProp "acks" "1" <> sendTimeout (Timeout 1400), "1400", [(0, "preserved-client"), (3, "1")]),+ ("explicit topic wins duplicate", extraProp "message.timeout.ms" "60000" <> sendTimeout (Timeout 1500), "1500", []),+ ("last topic property wins", sendTimeout (Timeout 1600) <> sendTimeout (Timeout 1700), "1700", []),+ ("empty topic map preserves global", extraProp "message.timeout.ms" "1800" <> mempty, "1800", []),+ ("zero topic timeout is infinite", sendTimeout (Timeout 0), "0", []),+ ("maximum native topic timeout", sendTimeout (Timeout (fromIntegral (maxBound :: CInt))), show (maxBound :: CInt), []),+ ("explicit topic wins native timeout alias", extraProp "delivery.timeout.ms" "60000" <> sendTimeout (Timeout 2000), "2000", []),+ ("topic codec overrides global codec", compression Gzip <> topicCompression Lz4, "300000", [(2, "lz4")]),+ ("global codec survives unrelated topic keys", compression Gzip <> sendTimeout (Timeout 1900), "1900", [(2, "gzip")])+ ]+ ]+ <> [testCase ("byte-exact round trip with " <> show codec) (roundTrip env codec) | codec <- [NoCompression, Gzip, Snappy, Lz4, Zstd]]+ <> [ testCase ("queued purge flags: " <> label) $+ withProducer mempty $ \producer -> do+ calls <- newIORef 0+ reports <- newEmptyMVar+ (result, weak) <- enqueueCapture producer record calls (Just reports)+ result @?= Right ()+ purgeProducer producer flags >>= (@?= Nothing)+ if PurgeQueue `elem` flags+ then pure ()+ else do+ flushProducerTimeout producer (Timeout 0) >>= (@?= Just (KafkaResponseError RdKafkaRespErrTimedOut))+ assertRetained weak+ purgeProducer producer [PurgeQueue] >>= (@?= Nothing)+ flushProducerTimeout producer (Timeout 1000) >>= (@?= Nothing)+ takeWithin reports >>= (@?= DeliveryFailure record (KafkaResponseError RdKafkaRespErrPurgeQueue))+ awaitCollected weak+ closeProducer producer+ closeProducer producer+ readIORef calls >>= (@?= 1)+ | (label, flags) <- purgeCases+ ]+ <> [ testCase ("in-flight purge flags: " <> label) $+ withMockProducer $ \mock producer -> do+ calls <- newIORef 0+ reports <- newEmptyMVar+ delayMockProduce mock 10000+ (result, weak) <- enqueueCapture producer mockRecord calls (Just reports)+ result @?= Right ()+ awaitCondition ((== 1) <$> mockReceivedProduce mock)+ flushProducerTimeout producer (Timeout 0) >>= (@?= Just (KafkaResponseError RdKafkaRespErrTimedOut))+ purgeProducer producer flags >>= (@?= Nothing)+ if PurgeInFlight `elem` flags+ then pure ()+ else do+ flushProducerTimeout producer (Timeout 0) >>= (@?= Just (KafkaResponseError RdKafkaRespErrTimedOut))+ assertRetained weak+ purgeProducer producer [PurgeInFlight] >>= (@?= Nothing)+ flushProducerTimeout producer (Timeout 1000) >>= (@?= Nothing)+ takeWithin reports >>= (@?= DeliveryFailure mockRecord (KafkaResponseError RdKafkaRespErrPurgeInflight))+ awaitCollected weak+ flushProducerTimeout producer (Timeout 0) >>= (@?= Nothing)+ readIORef calls >>= (@?= 1)+ | (label, flags) <- purgeCases+ ]+ <> [ testCase "bounded flush timeout recovers when the delayed response arrives" $+ withMockProducer $ \mock producer -> do+ calls <- newIORef 0+ reports <- newEmptyMVar+ delayMockProduce mock 300+ (result, weak) <- enqueueCapture producer mockRecord calls (Just reports)+ result @?= Right ()+ awaitCondition ((== 1) <$> mockReceivedProduce mock)+ flushProducerTimeout producer (Timeout 0) >>= (@?= Just (KafkaResponseError RdKafkaRespErrTimedOut))+ assertRetained weak+ flushProducerTimeout producer (Timeout 5000) >>= (@?= Nothing)+ takeWithin reports >>= (@?= DeliverySuccess mockRecord (C.Offset 0))+ awaitCollected weak+ readIORef calls >>= (@?= 1)+ flushProducerTimeout producer (Timeout 0) >>= (@?= Nothing)+ closeProducer producer+ closeProducer producer,+ testCase "close retries a timed-out flush until the delayed delivery completes" $+ withMockProducer $ \mock producer -> do+ calls <- newIORef 0+ reports <- newEmptyMVar+ delayMockProduce mock 1600+ (result, weak) <- enqueueCapture producer mockRecord calls (Just reports)+ result @?= Right ()+ awaitCondition ((== 1) <$> mockReceivedProduce mock)+ closeProducer producer+ takeWithin reports >>= (@?= DeliverySuccess mockRecord (C.Offset 0))+ awaitCollected weak+ readIORef calls >>= (@?= 1)+ flushProducerTimeout producer (Timeout 0) >>= (@?= Nothing),+ testCase "oversized rejection releases capture without a delivery report" $+ withProducer (extraProp "message.max.bytes" "1000") $ \producer -> do+ calls <- newIORef 0+ let oversized = record {prValue = Just (BS.replicate 2000 42)}+ (result, weak) <- enqueueCapture producer oversized calls Nothing+ result @?= Left (ImmediateError (KafkaResponseError RdKafkaRespErrMsgSizeTooLarge))+ awaitCollected weak+ flushProducerTimeout producer (Timeout 0) >>= (@?= Nothing)+ readIORef calls >>= (@?= 0),+ testCase "known invalid partition rejection releases capture" $+ withMockProducer $ \_ producer -> do+ calls <- newIORef 0+ let invalid = mockRecord {prPartition = SpecifiedPartition 2}+ (result, weak) <- enqueueCapture producer invalid calls Nothing+ result @?= Left (ImmediateError (KafkaResponseError RdKafkaRespErrUnknownPartition))+ awaitCollected weak+ produceMessage producer invalid >>= (@?= Just (KafkaResponseError RdKafkaRespErrUnknownPartition))+ flushProducerTimeout producer (Timeout 0) >>= (@?= Nothing)+ readIORef calls >>= (@?= 0),+ testCase "empty queue supports repeated flush and close" $+ withProducer mempty $ \producer -> do+ flushProducerTimeout producer (Timeout 0) >>= (@?= Nothing)+ purgeProducer producer [] >>= (@?= Nothing)+ closeProducer producer+ flushProducer producer+ closeProducer producer+ ]+ <> [ testCase ("rejects before native enqueue: " <> label) $+ withProducer mempty $ \producer -> withProducerTracking 0 $ do+ calls <- newIORef 0+ (result, weak) <- enqueueCapture producer invalid calls Nothing+ result @?= Left (ImmediateError (KafkaBadSpecification reason))+ awaitCollected weak+ nativeProducerProperty 1 >>= (@?= Nothing)+ flushProducerTimeout producer (Timeout 0) >>= (@?= Nothing)+ readIORef calls >>= (@?= 0)+ | (label, invalid, reason) <-+ [ ("NUL topic name", record {prTopic = TopicName (prefixedName env "producer-nul\0tail")}, "topic name contains NUL"),+ ("NUL header name", record {prHeaders = headersFromList [("name\0tail", "value")]}, "header name contains NUL"),+ ("maximum unrepresentable partition", record {prPartition = SpecifiedPartition maxBound}, "partition id is outside the C int range"),+ ("minimum unrepresentable partition", record {prPartition = SpecifiedPartition minBound}, "partition id is outside the C int range")+ ]+ ]+ <> [ testCase ("configuration rejection: " <> label) $ do+ result <- try @KafkaError (newProducer (brokersList [BrokerAddress "127.0.0.1:1"] <> props))+ case result of+ Left (KafkaUnknownConfigurationKey message) | unknown -> assertBool (Text.unpack message) (key `Text.isInfixOf` message)+ Left (KafkaInvalidConfigurationValue message) | not unknown -> assertBool (Text.unpack message) (key `Text.isInfixOf` message)+ Left exception -> assertFailure ("unexpected configuration exception: " <> show exception)+ Right (Left err) -> assertFailure ("configuration returned rather than throwing: " <> show err)+ Right (Right producer) -> releaseProducer producer >> assertFailure "invalid configuration was accepted"+ | (label, props, key, unknown) <-+ [ ("unknown global key", extraProp "not.a.producer.setting" "value", "not.a.producer.setting", True),+ ("unknown topic key", extraTopicProps (Map.singleton "not.a.topic.setting" "value"), "not.a.topic.setting", True),+ ("invalid topic timeout", sendTimeout (Timeout (-1)), "message.timeout.ms", False),+ ("excessive topic timeout", sendTimeout (Timeout maxBound), "message.timeout.ms", False),+ ("global-only key in topic map", extraTopicProps (Map.singleton "queue.buffering.max.messages" "1"), "queue.buffering.max.messages", True)+ ]+ ]+ <> [ testCase "later delivery callback replaces the earlier callback" $ do+ first <- newIORef (0 :: Int)+ lastReports <- newEmptyMVar+ let props =+ setCallback (deliveryCallback (\_ -> atomicModifyIORef' first (\n -> (n + 1, ()))))+ <> setCallback (deliveryCallback (putMVar lastReports))+ withProducer props $ \producer -> do+ produceMessage producer record >>= (@?= Nothing)+ purgeProducer producer [PurgeQueue] >>= (@?= Nothing)+ flushProducerTimeout producer (Timeout 1000) >>= (@?= Nothing)+ takeWithin lastReports >>= (@?= DeliveryFailure record (KafkaResponseError RdKafkaRespErrPurgeQueue))+ readIORef first >>= (@?= 0)+ ]+ <> [ testCase "null native delivery frame reports the generic errno fallback without dereferencing a message" $ withProducerTracking 6 $ do+ reports <- newEmptyMVar+ bracket (newProducer (producerProps env <> setCallback (deliveryCallback (putMVar reports))) >>= either throwIO pure) releaseProducer $ \_ -> do+ triggerNullDelivery >>= (@?= fromEnum RdKafkaRespErrFail)+ takeWithin reports >>= (@?= NoMessageError (KafkaResponseError RdKafkaRespErrFail)),+ testCase "native delivery without an opaque Haskell callback preserves the complete record" $+ withTopic env "producer-no-opaque" 1 $ \topic _ -> withProducerTracking 6 $ do+ reports <- newEmptyMVar+ bracket (newProducer (producerProps env <> setCallback (deliveryCallback (putMVar reports))) >>= either throwIO pure) releaseProducer $ \producer -> do+ enqueueWithoutOpaque topic+ flushProducerTimeout producer (Timeout 10000) >>= (@?= Nothing)+ let expected = ProducerRecord topic (SpecifiedPartition 0) (Just "native-key") (Just "native-without-opaque") mempty+ takeWithin reports >>= (@?= DeliverySuccess expected (C.Offset 0)),+ testCase "delivery header acquisition failure preserves the outcome with empty headers" $+ withTopic env "producer-header-failure" 1 $ \topic _ -> withProducerTracking 7 $ do+ global <- newEmptyMVar+ individual <- newEmptyMVar+ bracket (newProducer (producerProps env <> setCallback (deliveryCallback (putMVar global))) >>= either throwIO pure) releaseProducer $ \producer -> do+ let original = ProducerRecord topic (SpecifiedPartition 0) (Just "key") (Just "payload") (headersFromList [("present", "before-failure")])+ expected = DeliverySuccess (original {prHeaders = mempty}) (C.Offset 0)+ produceMessage' producer original (putMVar individual) >>= (@?= Right ())+ flushProducerTimeout producer (Timeout 10000) >>= (@?= Nothing)+ takeWithin global >>= (@?= expected)+ takeWithin individual >>= (@?= expected)+ ]+ where+ record = ProducerRecord (TopicName (prefixedName env "producer-regression")) (SpecifiedPartition 0) Nothing (Just "callback payload") (headersFromList [("producer-test", "present"), ("producer-test", BS.pack [0, 255])])+ withProducer props = withProducerRaw (extraProp "message.timeout.ms" "60000" <> props)+ withProducerRaw props =+ bracket+ ( newProducer (brokersList [BrokerAddress "127.0.0.1:1"] <> extraProp "log_level" "0" <> props)+ >>= either (assertFailure . show) pure+ )+ releaseProducer+ checkTimeout props = withProducer props $ \producer -> do+ reports <- newEmptyMVar+ produceMessage' producer record (putMVar reports) >>= (@?= Right ())+ flushProducerTimeout producer (Timeout 5000) >>= (@?= Nothing)+ takeWithin reports >>= (@?= DeliveryFailure record (KafkaResponseError RdKafkaRespErrMsgTimedOut))+ mockRecord = record {prTopic = TopicName "producer-inflight"}+ withMockProducer action = withProducerMock $ \mock addresses ->+ bracket (newProducer (brokersList addresses <> extraProp "log_level" "0") >>= either throwIO pure) releaseProducer $ \producer -> do+ metadata <- topicMetadata producer (Timeout 5000) (prTopic mockRecord)+ map (\t -> (tmTopicName t, map pmPartitionId (tmPartitions t))) . kmTopics <$> metadata+ @?= Right [(prTopic mockRecord, [PartitionId 0])]+ action mock producer++purgeCases :: [(String, [PurgeFlag])]+purgeCases =+ [ ("none", []),+ ("queue", [PurgeQueue]),+ ("inflight", [PurgeInFlight]),+ ("nonblocking", [PurgeNonBlocking]),+ ("queue+inflight", [PurgeQueue, PurgeInFlight]),+ ("queue+nonblocking", [PurgeQueue, PurgeNonBlocking]),+ ("inflight+nonblocking", [PurgeInFlight, PurgeNonBlocking]),+ ("all", [PurgeQueue, PurgeInFlight, PurgeNonBlocking])+ ]++-- Keep the captured IORef out of the caller's stack. The external count and+-- completion MVar let tests wait for the forked callback without rooting it.+{-# NOINLINE enqueueCapture #-}+enqueueCapture :: KafkaProducer -> ProducerRecord -> IORef Int -> Maybe (MVar DeliveryReport) -> IO (Either ImmediateError (), Weak (IORef Int))+enqueueCapture producer record calls completed = do+ captured <- newIORef (42 :: Int)+ weak <- mkWeakIORef captured (pure ())+ result <- produceMessage' producer record $ \report -> do+ readIORef captured >>= (@?= 42)+ atomicModifyIORef' calls (\n -> (n + 1, ()))+ mapM_ (`putMVar` report) completed+ pure (result, weak)++takeWithin :: MVar a -> IO a+takeWithin var = timeout 5000000 (takeMVar var) >>= maybe (assertFailure "callback did not complete within five seconds") pure++-- Separate processes contain foreign-boundary failures and changes to the+-- runtime's uncaught-exception handler. Preserve child coverage for the+-- collector, using unique files instead of the parent's HPCTIXFILE.+callbackChild :: String -> IO ()+callbackChild mode = do+ executable <- getExecutablePath+ environment <- getEnvironment+ directory <- maybe "dist-callback-probes" id <$> lookupEnv "RDKAFKA_TEST_CHILD_HPC_DIR"+ createDirectoryIfMissing True directory+ nonce <- randomIO :: IO Word+ let output = directory <> "/producer-" <> mode <> "-" <> show nonce <> ".tix"+ process =+ (proc executable ["--producer-callback-probe", mode, "+RTS", "--read-tix-file=no", "-RTS"])+ { env = Just (("HPCTIXFILE", output) : filter ((/= "HPCTIXFILE") . fst) environment)+ }+ result <- timeout 15000000 (readCreateProcessWithExitCode process "")+ case result of+ Just (ExitSuccess, _, _) -> pure ()+ other -> assertFailure ("callback probe failed: " <> show other)++runCallbackProbe :: String -> IO ()+runCallbackProbe mode = do+ reported <- newEmptyMVar+ bracket getUncaughtExceptionHandler setUncaughtExceptionHandler $ \_ -> do+ setUncaughtExceptionHandler (void . tryPutMVar reported . show)+ let global _ = if mode == "global" then throwIO (userError "producer-global-probe") else pure ()+ props = brokersList [BrokerAddress "127.0.0.1:1"] <> setCallback (deliveryCallback global)+ record = ProducerRecord (TopicName "producer-exception-probe") (SpecifiedPartition 0) Nothing (Just "payload") mempty+ bracket (newProducer props >>= either (assertFailure . show) pure) releaseProducer $ \producer -> do+ done <- newEmptyMVar+ calls <- newIORef 0+ weak <- enqueueThrowingCapture producer record calls done (mode == "message")+ assertRetained weak+ purgeProducer producer [PurgeQueue] >>= (@?= Nothing)+ flushProducerTimeout producer (Timeout 1000) >>= (@?= Nothing)+ takeWithin done >>= (@?= DeliveryFailure record (KafkaResponseError RdKafkaRespErrPurgeQueue))+ exception <- takeWithin reported+ assertBool exception (("producer-" <> mode <> "-probe") `isInfixOf` exception)+ awaitCollected weak+ readIORef calls >>= (@?= 1)++{-# NOINLINE enqueueThrowingCapture #-}+enqueueThrowingCapture :: KafkaProducer -> ProducerRecord -> IORef Int -> MVar DeliveryReport -> Bool -> IO (Weak (IORef Int))+enqueueThrowingCapture producer record calls done shouldThrow = do+ captured <- newIORef (42 :: Int)+ weak <- mkWeakIORef captured (pure ())+ produceMessage'+ producer+ record+ ( \report -> do+ readIORef captured >>= (@?= 42)+ atomicModifyIORef' calls (\n -> (n + 1, ()))+ putMVar done report+ if shouldThrow then throwIO (userError "producer-message-probe") else pure ()+ )+ >>= (@?= Right ())+ pure weak++{-# NOINLINE enqueueObservedCapture #-}+enqueueObservedCapture :: KafkaProducer -> ProducerRecord -> IORef Int -> MVar (Weak (IORef Int)) -> MVar DeliveryReport -> IO (Either ImmediateError ())+enqueueObservedCapture producer record calls ready reports = do+ captured <- newIORef (42 :: Int)+ weak <- mkWeakIORef captured (pure ())+ putMVar ready weak+ produceMessage' producer record $ \report -> do+ readIORef captured >>= (@?= 42)+ atomicModifyIORef' calls (\n -> (n + 1, ()))+ putMVar reports report++{-# NOINLINE enqueueBlockedCapture #-}+enqueueBlockedCapture :: KafkaProducer -> ProducerRecord -> MVar () -> MVar () -> MVar () -> IO (Weak (IORef Int))+enqueueBlockedCapture producer record started resume done = do+ captured <- newIORef (42 :: Int)+ weak <- mkWeakIORef captured (pure ())+ produceMessage'+ producer+ record+ ( \_ -> do+ getMaskingState >>= (@?= Unmasked)+ putMVar started ()+ readMVar resume+ readIORef captured >>= (@?= 42)+ putMVar done ()+ )+ >>= (@?= Right ())+ pure weak++awaitCondition :: IO Bool -> IO ()+awaitCondition condition = timeout 5000000 loop >>= maybe (assertFailure "thread state was not observed") pure+ where+ loop = condition >>= \ready -> if ready then pure () else threadDelay 1000 >> loop++roundTrip :: TestEnv -> KafkaCompressionCodec -> IO ()+roundTrip testEnv codec =+ withTopic testEnv suffix 1 $ \topic _ ->+ bracket+ (newProducer (producerProps testEnv <> topicCompression codec) >>= either throwIO pure)+ releaseProducer+ $ \producer -> withProducerTracking 0 $ do+ let values = [Nothing, Just BS.empty, Just (BS.pack [0, 255, 1])]+ headers = headersFromList [("", ""), ("duplicate", ""), ("duplicate", BS.pack [0, 255])]+ records = [ProducerRecord topic partition key value headers | (n, (key, value)) <- zip [0 :: Int ..] [(k, v) | k <- values, v <- values], let partition = if even n then SpecifiedPartition 0 else UnassignedPartition]+ sendMessages records producer >>= either throwIO pure+ nativeProducerProperty 2 >>= (@?= Just (Text.unpack (kafkaCompressionCodecToText codec)))+ let props = consumerProps testEnv <> C.groupId (makeGroupId testEnv suffix) <> C.callbackPollMode C.CallbackPollModeSync+ bracket (C.newAssignedConsumer props >>= either throwIO pure) releaseConsumer $ \consumer -> do+ C.assign consumer [C.TopicPartition topic (PartitionId 0) C.PartitionOffsetBeginning] >>= (@?= Nothing)+ actual <- receiveMessages consumer (length records) >>= either throwIO pure+ let identities = [ProducerRecord (C.crTopic r) (SpecifiedPartition 0) (C.crKey r) (C.crValue r) (C.crHeaders r) | r <- actual]+ identities @?= [r {prPartition = SpecifiedPartition 0} | r <- records]+ map C.crPartition actual @?= replicate (length records) (PartitionId 0)+ map C.crOffset actual @?= map C.Offset [0 .. fromIntegral (length records) - 1]+ where+ suffix = "producer-bytes-" <> kafkaCompressionCodecToText codec
+ test-integration/Kafka/Integration/PublicConsumerContractTest.hs view
@@ -0,0 +1,407 @@+module Kafka.Integration.PublicConsumerContractTest (tests, runRebalanceProbe) where++import Control.Concurrent (forkFinally, forkIOWithUnmask, killThread, threadDelay)+import Control.Concurrent.MVar (newEmptyMVar, putMVar, readMVar, tryReadMVar)+import Control.Exception (AsyncException (ThreadKilled), ErrorCall, SomeException, bracket, finally, fromException, throwIO, try)+import Control.Monad (forM_)+import Data.Either (isLeft)+import Data.IORef (modifyIORef', newIORef, readIORef)+import Data.Map.Strict qualified as M+import Data.Maybe (isJust)+import Data.Text qualified as Text+import GHC.Clock (getMonotonicTimeNSec)+import GHC.Conc (BlockReason (BlockedOnException), ThreadStatus (ThreadBlocked), getUncaughtExceptionHandler, setUncaughtExceptionHandler, threadStatus)+import Kafka.CallbackTestSupport (runChildProbe)+import Kafka.Consumer+import Kafka.ConsumerStateSupport+import Kafka.Integration.ConfigStringContractTest qualified as ConfigStringContractTest+import Kafka.Integration.ConsumerCommitContractTest qualified as ConsumerCommitContractTest+import Kafka.Integration.ConsumerStateContractTest qualified as ConsumerStateContractTest+import Kafka.Integration.DeprecatedRunnerContractTest qualified as DeprecatedRunnerContractTest+import Kafka.Integration.DiagnosticContractTest qualified as DiagnosticContractTest+import Kafka.Integration.FatalErrorTest qualified as FatalErrorTest+import Kafka.Integration.InputBoundaryContractTest qualified as InputBoundaryContractTest+import Kafka.Integration.MetadataContractTest qualified as MetadataContractTest+import Kafka.Integration.PartitionListContractTest qualified as PartitionListContractTest+import Kafka.Integration.QueueEventTest qualified as QueueEventTest+import Kafka.Integration.RuntimeContractTest qualified as RuntimeContractTest+import Kafka.MessageTestSupport+import Kafka.Producer qualified as P+import Kafka.TestEnv+import System.Environment (lookupEnv)+import System.Exit (die)+import System.Timeout (timeout)+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.HUnit (assertBool, assertFailure, testCase, (@?=))++tests :: TestEnv -> TestTree+tests testEnv =+ testGroup+ "public-contract"+ [ PartitionListContractTest.tests testEnv,+ testGroup "messages" $+ [ testCase "batch conversion releases every returned native message" $+ withRecords testEnv "batch-success" CallbackPollModeAsync $ \_ consumer -> withMessageFault 0 $ do+ records <- pollMessageBatch consumer (Timeout 1000) (BatchSize 3)+ map (fmap crValue) records @?= map (Right . Just) ["first", "second", "third"]+ balanced 3,+ testCase "native message counter detects a retained final object" $+ withRecords testEnv "batch-control" CallbackPollModeAsync $ \_ consumer -> withMessageFault 5 $ do+ records <- pollMessageBatch consumer (Timeout 1000) (BatchSize 3)+ length records @?= 3+ messageStat 1 >>= (@?= 3)+ messageStat 2 >>= (@?= 2)+ messageStat 7 >>= (@?= 1),+ testCase "batch decoder exception releases unprocessed messages" $+ withRecords testEnv "batch-decode" CallbackPollModeAsync $ \_ consumer -> withMessageFault 1 $ do+ result <- try @SomeException (pollMessageBatch consumer (Timeout 1000) (BatchSize 3))+ assertBool (show result) (isLeft result)+ balanced 3,+ testCase "batch native header errors remain errors while later records are released" $+ withRecords testEnv "batch-header" CallbackPollModeAsync $ \_ consumer -> withMessageFault 6 $ do+ records <- pollMessageBatch consumer (Timeout 1000) (BatchSize 3)+ map (fmap crValue) records @?= [Right (Just "first"), Left (KafkaResponseError RdKafkaRespErrBadMsg), Right (Just "third")]+ balanced 3+ ]+ <> [ testCase ("batch cancellation at " <> label <> " releases every acquired message") $+ withRecords testEnv ("batch-cancel-" <> label) CallbackPollModeAsync $ \_ consumer ->+ withMessageFault stage (cancelled 3 (pollMessageBatch consumer (Timeout 1000) (BatchSize 3)))+ | (label, stage) <- [("native return", 2), ("middle conversion", 3)]+ ]+ <> [ testCase (label <> " single cancellation at " <> stageName <> " releases its native message") $+ withRecords testEnv (label <> "-single-" <> stageName) mode $ \_ consumer ->+ withMessageFault (stage + if mode == CallbackPollModeSync then 3 else 0) (cancelled 1 (pollMessage consumer (Timeout 10000)))+ | (label, mode) <- [("async", CallbackPollModeAsync), ("sync", CallbackPollModeSync)],+ (stageName, stage) <- [("native return", 10), ("inside conversion", 11)]+ ]+ <> [ testCase (label <> " header failure preserves the polled record origin") $+ withRecords testEnv (label <> "-attributed-header") mode $ \topic consumer -> withMessageFault fault $ do+ result <- pollMessageAttributed consumer (Timeout 10000)+ result @?= Left (ConsumerMessageError (KafkaResponseError RdKafkaRespErrBadMsg) (Just topic) (Just (PartitionId 0)) (Just (Offset 0)))+ balanced 1+ | (label, mode, fault) <- [("async", CallbackPollModeAsync, 12), ("sync", CallbackPollModeSync, 15)]+ ]+ <> [ testCase (label <> " plain polling surfaces native header failure") $+ withRecords testEnv (label <> "-plain-header") mode $ \_ consumer -> withMessageFault fault $ do+ pollMessage consumer (Timeout 10000) >>= (@?= Left (KafkaResponseError RdKafkaRespErrBadMsg))+ balanced 1+ | (label, mode, fault) <- [("async", CallbackPollModeAsync, 12), ("sync", CallbackPollModeSync, 15)]+ ]+ <> [ testCase (label <> " attributed error preserves independently absent " <> absent) $+ withRecords testEnv (label <> "-absent-" <> absent) mode $ \topic consumer -> withMessageFault fault $ do+ pollMessageAttributed consumer (Timeout 10000)+ >>= (@?= Left (ConsumerMessageError (KafkaResponseError RdKafkaRespErrBadMsg) (Just topic) partition offset))+ balanced 1+ | (label, mode) <- [("async", CallbackPollModeAsync), ("sync", CallbackPollModeSync)],+ (absent, fault, partition, offset) <- [("partition-and-offset", 21, Nothing, Nothing), ("offset", 22, Just (PartitionId 0), Nothing), ("partition", 23, Nothing, Just (Offset 0))]+ ]+ <> [ testCase "callback-event polling cancellation releases a returned message" $+ withRecords testEnv "events-cancel" CallbackPollModeSync $ \_ consumer ->+ withMessageFault 13 (cancelled 1 (pollConsumerEvents consumer (Just (Timeout 10000)))),+ testCase "callback buffer preserves attributed header failure" $+ withRecords testEnv "buffer-attributed-header" CallbackPollModeSync $ \topic consumer -> do+ withMessageFault 15 $ do+ pollConsumerEvents consumer (Just (Timeout 10000))+ balanced 1+ pollMessageAttributed consumer (Timeout 0) >>= (@?= Left (ConsumerMessageError (KafkaResponseError RdKafkaRespErrBadMsg) (Just topic) (Just (PartitionId 0)) (Just (Offset 0))))+ message <- pollMessage consumer (Timeout 10000) >>= either throwIO pure+ crOffset message @?= Offset 1,+ testCase "callback buffer preserves plain header failure" $+ withRecords testEnv "buffer-plain-header" CallbackPollModeSync $ \_ consumer -> do+ withMessageFault 15 $ do+ pollConsumerEvents consumer (Just (Timeout 10000))+ balanced 1+ pollMessage consumer (Timeout 0) >>= (@?= Left (KafkaResponseError RdKafkaRespErrBadMsg))+ message <- pollMessage consumer (Timeout 10000) >>= either throwIO pure+ crOffset message @?= Offset 1,+ testCase "originless callback error survives seek filtering and a paused partition" $+ withRecords testEnv "buffer-originless-error" CallbackPollModeSync $ \topic consumer -> do+ withMessageFault 24 $ do+ pollConsumerEvents consumer (Just (Timeout 10000))+ balanced 1+ seekPartitions consumer [TopicPartition topic (PartitionId 0) (PartitionOffset 2)] (Timeout 2000) >>= (@?= Nothing)+ pausePartitions consumer [(topic, PartitionId 0)] >>= (@?= KafkaResponseError RdKafkaRespErrNoError)+ pollMessageAttributed consumer (Timeout 0)+ >>= (@?= Left (ConsumerMessageError (KafkaResponseError RdKafkaRespErrBadMsg) Nothing Nothing Nothing))+ resumePartitions consumer [(topic, PartitionId 0)] >>= (@?= KafkaResponseError RdKafkaRespErrNoError)+ record <- pollMessage consumer (Timeout 10000) >>= either throwIO pure+ (crTopic record, crPartition record, crOffset record, crValue record) @?= (topic, PartitionId 0, Offset 2, Just "third"),+ testCase "callback-event polling releases and discards a returned fatal frame" $+ withRecords testEnv "buffer-fatal-discard" CallbackPollModeSync $ \topic consumer -> do+ withMessageFault 25 $ do+ pollConsumerEvents consumer (Just (Timeout 10000))+ balanced 1+ record <- pollMessage consumer (Timeout 10000) >>= either throwIO pure+ (crTopic record, crOffset record, crValue record) @?= (topic, Offset 1, Just "second"),+ testCase "zero batch size leaves the queued records available" $+ withRecords testEnv "batch-zero" CallbackPollModeAsync $ \_ consumer -> withMessageFault 0 $ do+ pollMessageBatch consumer (Timeout 1000) (BatchSize 0) >>= (@?= [])+ records <- pollMessageBatch consumer (Timeout 1000) (BatchSize 3)+ map (fmap crValue) records @?= map (Right . Just) ["first", "second", "third"]+ balanced 3,+ testCase "unsupported sync batch does not discard a record" $+ withRecords testEnv "batch-sync" CallbackPollModeSync $ \_ consumer -> withMessageFault 20 $ do+ pollMessageBatch consumer (Timeout 0) (BatchSize 3) >>= (@?= [Left (KafkaBadSpecification "Calling pollMessageBatch while CallbackPollMode is set to CallbackPollModeSync.")])+ messageStat 0 >>= (@?= 0)+ record <- pollMessage consumer (Timeout 10000) >>= either throwIO pure+ (crOffset record, crValue record) @?= (Offset 0, Just "first"),+ testCase "signed native batch failure preserves its error and queued data" $+ withRecords testEnv "batch-native-error" CallbackPollModeAsync $ \_ consumer -> do+ withMessageFault 4 $ do+ pollMessageBatch consumer (Timeout 1000) (BatchSize 3) >>= (@?= [Left (KafkaResponseError RdKafkaRespErrTimedOut)])+ balanced 0+ withMessageFault 0 $ do+ records <- pollMessageBatch consumer (Timeout 1000) (BatchSize 3)+ map (fmap crValue) records @?= map (Right . Just) ["first", "second", "third"]+ balanced 3,+ testCase "infinite batch timeout returns available records" $+ withRecords testEnv "batch-infinite" CallbackPollModeAsync $ \_ consumer -> withMessageFault 0 $ do+ records <- pollMessageBatch consumer (Timeout (-1)) (BatchSize 3)+ map (fmap crValue) records @?= map (Right . Just) ["first", "second", "third"]+ balanced 3+ ]+ <> [ testCase ("batch capacity " <> show capacity <> " preserves complete ordered records across partial batches") $+ withRecords testEnv ("batch-fields-" <> show capacity) CallbackPollModeAsync $ \topic consumer -> withMessageFault 20 $ do+ let collect records+ | length records == 3 = pure records+ | otherwise = do+ batch <- pollMessageBatch consumer (Timeout 500) (BatchSize capacity)+ assertBool (show batch) (length batch <= capacity)+ next <- traverse (either throwIO pure) batch+ assertBool (show (records <> next)) (length records + length next <= 3)+ collect (records <> next)+ records <- bounded (collect [])+ forM_ (zip3 records [0 ..] ["first", "second", "third"]) $ \(record, offset, value) -> do+ (crTopic record, crPartition record, crOffset record, crKey record, crValue record, crHeaders record)+ @?= (topic, PartitionId 0, Offset offset, Nothing, Just value, mempty)+ case crTimestamp record of+ CreateTime (Millis time) -> assertBool "missing batch timestamp" (time > 0)+ other -> assertFailure (show other)+ pollMessageBatch consumer (Timeout 0) (BatchSize capacity) >>= (@?= [])+ balanced 3+ | capacity <- [1, 2, 5]+ ]+ <> [ testCase ("invalid batch array size is rejected before native acquisition: " <> show size) $+ withRecords testEnv ("batch-size-" <> show size) CallbackPollModeAsync $ \_ consumer -> withMessageFault 20 $ do+ pollMessageBatch consumer (Timeout 0) (BatchSize size) >>= (@?= [Left (KafkaBadSpecification "Batch size must be nonnegative and fit a native pointer array.")])+ messageStat 0 >>= (@?= 0)+ balanced 0+ | size <- [-1, minBound, maxBound]+ ]+ <> [ testCase "batch preserves complete records followed by exact partition EOF and idle timeout" $+ withTopic testEnv "batch-eof-fields" 1 $ \topic producer -> do+ forM_ ["first", "second", "third"] (produceTo producer topic 0)+ let props = brokersList (teBrokers testEnv) <> groupId (makeGroupId testEnv "batch-eof-fields") <> noAutoCommit <> noAutoOffsetStore <> callbackPollMode CallbackPollModeAsync <> extraProp "enable.partition.eof" "true"+ bracket (newAssignedConsumer props >>= either throwIO pure) releaseConsumer $ \consumer -> do+ assign consumer [TopicPartition topic (PartitionId 0) PartitionOffsetBeginning] >>= (@?= Nothing)+ withMessageFault 0 $ do+ let eof = KafkaResponseError RdKafkaRespErrPartitionEof+ collect values+ | any (\case Left err -> err == eof; _ -> False) values = pure values+ | otherwise = do+ batch <- pollMessageBatch consumer (Timeout 500) (BatchSize 5)+ assertBool (show batch) (length batch <= 5)+ collect (values <> batch)+ results <- bounded (collect [])+ map (fmap (\record -> (crTopic record, crPartition record, crOffset record, crKey record, crValue record, crHeaders record))) results+ @?= [Right (topic, PartitionId 0, Offset offset, Nothing, Just value, mempty) | (offset, value) <- zip [0 ..] ["first", "second", "third"]] <> [Left eof]+ forM_ results $ \case+ Right record -> case crTimestamp record of CreateTime (Millis time) -> assertBool "missing EOF batch record timestamp" (time > 0); other -> assertFailure (show other)+ Left _ -> pure ()+ pollMessageBatch consumer (Timeout 100) (BatchSize 5) >>= (@?= [])+ balanced 4+ ]+ <> [ testCase ("empty batch respects timeout " <> show milliseconds)+ $ bracket+ (newAssignedConsumer (brokersList (teBrokers testEnv) <> groupId (makeGroupId testEnv (Text.pack ("batch-empty-" <> show milliseconds))) <> noAutoCommit) >>= either throwIO pure)+ releaseConsumer+ $ \consumer -> withMessageFault 20 $ do+ start <- getMonotonicTimeNSec+ pollMessageBatch consumer (Timeout milliseconds) (BatchSize 3) >>= (@?= [])+ elapsed <- subtract start <$> getMonotonicTimeNSec+ assertBool ("empty batch took " <> show elapsed <> " ns") (elapsed < 3000000000)+ balanced 0+ | milliseconds <- [0, 100]+ ],+ rebalanceErrorTests testEnv,+ ConsumerStateContractTest.tests testEnv,+ ConsumerCommitContractTest.tests testEnv,+ DiagnosticContractTest.tests testEnv,+ InputBoundaryContractTest.tests testEnv,+ DeprecatedRunnerContractTest.tests testEnv,+ FatalErrorTest.tests testEnv,+ QueueEventTest.tests testEnv,+ RuntimeContractTest.tests testEnv,+ MetadataContractTest.tests testEnv,+ ConfigStringContractTest.tests testEnv+ ]++withRecords :: TestEnv -> String -> CallbackPollMode -> (TopicName -> KafkaConsumer -> IO a) -> IO a+withRecords testEnv label mode action = withTopic testEnv ("message-owner-" <> safeLabel) 1 $ \topic producer -> do+ sendMessages [P.ProducerRecord topic (P.SpecifiedPartition 0) Nothing (Just value) mempty | value <- ["first", "second", "third"]] producer >>= either throwIO pure+ let props = brokersList (teBrokers testEnv) <> groupId (makeGroupId testEnv ("message-owner-" <> safeLabel)) <> noAutoCommit <> callbackPollMode mode+ bracket (newAssignedConsumer props >>= either throwIO pure) releaseConsumer $ \consumer -> do+ assign consumer [TopicPartition topic (PartitionId 0) PartitionOffsetBeginning] >>= (@?= Nothing)+ action topic consumer+ where+ safeLabel = Text.replace " " "-" (Text.pack label)++balanced :: Int -> IO ()+balanced count = do+ messageStat 1 >>= (@?= count)+ messageStat 2 >>= (@?= count)+ messageStat 5 >>= (@?= 0)++bounded :: IO a -> IO a+bounded action = timeout 10000000 action >>= maybe (assertFailure "message worker timed out") pure++cancelled :: Int -> IO a -> IO ()+cancelled count action = do+ done <- newEmptyMVar+ worker <- forkIOWithUnmask $ \unmask -> try @SomeException (unmask action) >>= putMVar done+ flip finally (releaseMessageBoundary >> bounded (readMVar done)) $ do+ awaitMessageBoundary+ messageStat 1 >>= (@?= count)+ killed <- newEmptyMVar+ killer <- forkFinally (killThread worker) (putMVar killed)+ let awaitPending =+ threadStatus killer >>= \status ->+ if status == ThreadBlocked BlockedOnException then pure () else threadDelay 1000 >> awaitPending+ bounded awaitPending+ tryReadMVar done >>= maybe (pure ()) (const (assertFailure "poll returned while the native boundary was held"))+ releaseMessageBoundary+ bounded (readMVar done) >>= \case+ Left exception -> (fromException exception :: Maybe AsyncException) @?= Just ThreadKilled+ Right _ -> assertFailure "pending polling cancellation was not delivered"+ bounded (readMVar killed) >>= either throwIO pure+ balanced count++rebalanceErrorTests :: TestEnv -> TestTree+rebalanceErrorTests testEnv =+ testGroup "rebalance-errors" $+ [ testCase+ "native rebalance counter detects an undisposed error"+ ( withStateFault 1 $ do+ stateLeakControl+ stateStat 0 >>= (@?= 1)+ stateStat 1 >>= (@?= 0)+ )+ ]+ <> [ testCase (label <> " real cooperative assignment and revocation preserve records") $+ withTopic testEnv ("cooperative-" <> Text.pack label) 1 $ \topic producer -> do+ produceTo producer topic 0 "cooperative-record"+ events <- newIORef []+ observedAssignments <- newIORef []+ let partitions = [(topic, PartitionId 0)]+ props =+ brokersList (teBrokers testEnv)+ <> groupId (makeGroupId testEnv ("cooperative-" <> Text.pack label))+ <> noAutoCommit+ <> callbackPollMode mode+ <> extraProps (M.singleton "partition.assignment.strategy" "cooperative-sticky")+ <> setCallback+ ( rebalanceCallback+ ( \consumer event -> do+ modifyIORef' events (<> [event])+ current <- assignment consumer+ modifyIORef' observedAssignments (<> [current])+ )+ )+ bracket (newConsumer props (topics [topic] <> offsetReset Earliest) >>= either throwIO pure) releaseConsumer $ \consumer -> do+ record <- pollMessage consumer (Timeout 10000) >>= either throwIO pure+ (crOffset record, crValue record) @?= (Offset 0, Just "cooperative-record")+ readIORef events >>= (@?= [RebalanceBeforeAssign partitions, RebalanceAssign partitions])+ readIORef events >>= (@?= [RebalanceBeforeAssign partitions, RebalanceAssign partitions, RebalanceBeforeRevoke partitions, RebalanceRevoke partitions])+ readIORef observedAssignments >>= (@?= map Right [M.empty, M.singleton topic [PartitionId 0], M.singleton topic [PartitionId 0], M.empty])+ | (label, mode) <- [("async", CallbackPollModeAsync), ("sync", CallbackPollModeSync)]+ ]+ <> [ testCase (protocol <> " " <> operation <> " " <> poll <> " " <> failure <> " reports failure without a success event") $+ runChildProbe ("rebalance-" <> protocol <> "-" <> operation <> "-" <> poll <> "-" <> failure) ["--rebalance-error-probe", protocol, operation, poll, failure]+ | protocol <- ["cooperative", "eager"],+ operation <- ["assign", "revoke"],+ poll <- ["async", "sync"],+ failure <- if protocol == "cooperative" then ["native", "decode"] else ["native"]+ ]+ <> [ testCase (poll <> " unexpected rebalance error " <> description) $+ runChildProbe ("rebalance-unexpected-" <> poll <> "-" <> failure) ["--rebalance-error-probe", "unexpected", "failure", poll, failure]+ | poll <- ["async", "sync"],+ (failure, description) <- [("native", "clears assignment and pending records"), ("reset-failure", "preserves state when native reset fails")]+ ]++runRebalanceProbe :: String -> String -> String -> String -> IO ()+runRebalanceProbe "unexpected" _ poll failure = runUnexpectedRebalanceProbe poll failure+runRebalanceProbe protocol operation poll failure = do+ fault <- case (protocol, operation, failure) of+ ("cooperative", "assign", "native") -> pure 1+ ("cooperative", "revoke", "native") -> pure 2+ ("cooperative", "assign", "decode") -> pure 3+ ("cooperative", "revoke", "decode") -> pure 4+ ("eager", "assign", "native") -> pure 5+ ("eager", "revoke", "native") -> pure 6+ _ -> die "invalid rebalance error probe"+ brokers <- lookupEnv "RDKAFKA_TEST_BROKER" >>= either die pure . resolveBrokers+ testEnv <- newTestEnv brokers+ events <- newIORef []+ reported <- newEmptyMVar+ let topic = TopicName (prefixedName testEnv "rebalance-error")+ mode = if poll == "async" then CallbackPollModeAsync else CallbackPollModeSync+ props =+ brokersList brokers+ <> groupId (makeGroupId testEnv "rebalance-error")+ <> noAutoCommit+ <> callbackPollMode mode+ <> setCallback (rebalanceCallback (\_ event -> modifyIORef' events (<> [event])))+ before = if operation == "assign" then RebalanceBeforeAssign [(topic, PartitionId 0)] else RebalanceBeforeRevoke [(topic, PartitionId 0)]+ bracket getUncaughtExceptionHandler setUncaughtExceptionHandler $ \_ -> do+ setUncaughtExceptionHandler (putMVar reported)+ withStateFault fault+ $ bracket+ (newAssignedConsumer props >>= either throwIO pure)+ (\consumer -> endStateFault `finally` destroyConsumer consumer)+ $ \_ -> do+ triggerRebalance topic+ result <- timeout 1000000 (readMVar reported)+ observed <- mapM stateStat [0 .. 6]+ seen <- readIORef events+ let expectedObject = if protocol == "cooperative" then 1 else 0+ expected = [expectedObject, expectedObject, if protocol == "cooperative" && operation == "assign" then 1 else 0, if protocol == "cooperative" && operation == "revoke" then 1 else 0, 1, if protocol == "eager" then 1 else 0, 1]+ expectedError = case result of+ Nothing -> False+ Just exception ->+ if failure == "decode"+ then isJust (fromException exception :: Maybe ErrorCall)+ else (fromException exception :: Maybe KafkaError) == Just (KafkaResponseError RdKafkaRespErrState)+ assertBool (show (observed, seen, fmap show result)) (observed == expected && seen == [before] && expectedError)++runUnexpectedRebalanceProbe :: String -> String -> IO ()+runUnexpectedRebalanceProbe poll failure = do+ brokers <- lookupEnv "RDKAFKA_TEST_BROKER" >>= either die pure . resolveBrokers+ testEnv <- newTestEnv brokers+ events <- newIORef []+ reported <- newEmptyMVar+ let mode = if poll == "async" then CallbackPollModeAsync else CallbackPollModeSync+ fault = if failure == "native" then 7 else 8+ expected = KafkaResponseError (if failure == "native" then RdKafkaRespErrGroupAuthorizationFailed else RdKafkaRespErrState)+ props = brokersList brokers <> groupId (makeGroupId testEnv "unexpected-rebalance") <> noAutoCommit <> noAutoOffsetStore <> callbackPollMode mode <> setCallback (rebalanceCallback (\_ event -> modifyIORef' events (<> [event])))+ bracket getUncaughtExceptionHandler setUncaughtExceptionHandler $ \_ -> do+ setUncaughtExceptionHandler (putMVar reported)+ withTopic testEnv (Text.pack ("unexpected-rebalance-" <> poll <> failure)) 1 $ \topic producer ->+ withStateFault fault $+ bracket (newAssignedConsumer props >>= either throwIO pure) (\consumer -> endStateFault `finally` releaseConsumer consumer) $ \consumer -> do+ assign consumer [TopicPartition topic (PartitionId 0) PartitionOffsetBeginning] >>= (@?= Nothing)+ produceTo producer topic 0 "pending-before-rebalance-error"+ if mode == CallbackPollModeSync then pollConsumerEvents consumer (Just (Timeout 10000)) else pure ()+ beforeCalls <- stateStat 5+ triggerRebalance topic+ result <- timeout 1000000 (readMVar reported)+ fmap (\exception -> fromException exception :: Maybe KafkaError) result @?= Just (Just expected)+ stateStat 5 >>= (@?= beforeCalls + 1)+ readIORef events >>= (@?= [])+ if failure == "native"+ then do+ assignment consumer >>= (@?= Right M.empty)+ pollMessage consumer (Timeout 0) >>= (@?= Left (KafkaResponseError RdKafkaRespErrTimedOut))+ else do+ assignment consumer >>= (@?= Right (M.singleton topic [PartitionId 0]))+ record <- pollMessage consumer (Timeout 10000) >>= either throwIO pure+ (crTopic record, crPartition record, crOffset record, crValue record) @?= (topic, PartitionId 0, Offset 0, Just "pending-before-rebalance-error")
+ test-integration/Kafka/Integration/QueueEventTest.hs view
@@ -0,0 +1,200 @@+-- | Pipe notifications for the actual queue read by the public polling APIs.+module Kafka.Integration.QueueEventTest (tests) where++import Control.Concurrent (threadWaitRead)+import Control.Exception (bracket, throwIO, try)+import Data.ByteString (ByteString)+import Data.ByteString qualified as BS+import Data.Text qualified as Text+import Foreign.C.Error (Errno (..), eAGAIN, eBADF, eWOULDBLOCK)+import Foreign.Marshal.Alloc (allocaBytes)+import Foreign.Ptr (castPtr)+import GHC.Clock (getMonotonicTimeNSec)+import GHC.IO.Exception (ioe_errno)+import Kafka.Consumer+import Kafka.ConsumerStateSupport (awaitQueuedRecord, queueEventStat, withQueueTracking)+import Kafka.FixtureSupport (collectExactly)+import Kafka.MessageTestSupport (messageStat, withMessageFault)+import Kafka.Producer (KafkaProducer, ProducePartition (..), ProducerRecord (..))+import Kafka.TestEnv+import System.Posix.IO (FdOption (..), closeFd, createPipe, fdReadBuf, fdWrite, setFdOption)+import System.Posix.Types (ByteCount, Fd (..))+import System.Timeout (timeout)+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.HUnit (Assertion, assertFailure, testCase, (@?=))++tests :: TestEnv -> TestTree+tests env =+ testGroup+ "queue event"+ [ testCase "empty pipes are idle but invalid descriptor errors are preserved" $+ bracket createPipe closePipe $ \(rfd, _) -> do+ setFdOption rfd NonBlockingRead True+ fdRead rfd 1 >>= (@?= BS.empty)+ try @IOError (fdRead (Fd (-1)) 1) >>= \case+ Left err -> let Errno code = eBADF in ioe_errno err @?= Just code+ Right bytes -> assertFailure ("invalid descriptor appeared idle: " <> show bytes),+ modeGroup env "async" CallbackPollModeAsync,+ modeGroup env "sync" CallbackPollModeSync+ ]++modeGroup :: TestEnv -> String -> CallbackPollMode -> TestTree+modeGroup env label mode =+ testGroup+ label+ [ testCase "wakes an idle consumer and stays quiet once disabled" $+ withQueueEvent env mode (label <> "-idle") $ \consumer producer topic pipe@(rfd, wfd) -> do+ register consumer topic pipe+ send producer topic "first"+ timeout 10000000 (threadWaitRead rfd) >>= (@?= Just ())+ fdRead rfd 1 >>= (@?= "1")+ awaitRecord consumer topic 0 "first"+ drainQueue consumer topic >>= (@?= [])+ setConsumerQueueIOEvent consumer Nothing+ _ <- drainPipe rfd+ send producer topic "second"+ timeout 2000000 (threadWaitRead rfd) >>= (@?= Nothing)+ awaitRecord consumer topic 1 "second",+ testCase "finds records queued before it was enabled, then rearms" $+ withQueueEvent env mode (label <> "-preloaded") $ \consumer producer topic (rfd, wfd) -> do+ send producer topic "early"+ -- Observe a real queued record, rather than infer prefetch from a delay.+ awaitQueuedRecord (setConsumerQueueIOEvent consumer Nothing)+ setConsumerQueueIOEvent consumer (Just (wfd, "1"))+ drainQueue consumer topic >>= (@?= [(Offset 0, "early")])+ _ <- drainPipe rfd+ send producer topic "later"+ timeout 10000000 (threadWaitRead rfd) >>= (@?= Just ())+ awaitRecord consumer topic 1 "later",+ testCase "one wake-up covers several records, then rearms" $+ withQueueEvent env mode (label <> "-multiple") $ \consumer producer topic pipe@(rfd, _) -> do+ register consumer topic pipe+ sendAll producer topic ["one", "two", "three"]+ timeout 10000000 (threadWaitRead rfd) >>= (@?= Just ())+ drainPipe rfd >>= (@?= "1")+ collect consumer topic 3 >>= (@?= [(Offset 0, "one"), (Offset 1, "two"), (Offset 2, "three")])+ drainQueue consumer topic >>= (@?= [])+ _ <- drainPipe rfd+ send producer topic "four"+ timeout 10000000 (threadWaitRead rfd) >>= (@?= Just ())+ awaitRecord consumer topic 3 "four",+ testCase "binary payloads retain every byte and empty payloads preserve records" $+ withQueueEvent env mode (label <> "-payload") $ \consumer producer topic (rfd, wfd) -> do+ let payload = BS.pack [0, 255, 0, 65, 66, 67, 0, 128]+ setConsumerQueueIOEvent consumer (Just (wfd, payload))+ drainQueue consumer topic >>= (@?= [])+ _ <- drainPipe rfd+ send producer topic "binary-payload"+ timeout 10000000 (threadWaitRead rfd) >>= (@?= Just ())+ fdRead rfd (BS.length payload) >>= (@?= payload)+ awaitRecord consumer topic 0 "binary-payload"+ drainPipe rfd >>= (@?= BS.empty)+ setConsumerQueueIOEvent consumer (Just (wfd, BS.empty))+ send producer topic "empty-payload"+ awaitQueuedRecord (setConsumerQueueIOEvent consumer (Just (wfd, BS.empty)))+ timeout 500000 (threadWaitRead rfd) >>= (@?= Nothing)+ awaitRecord consumer topic 1 "empty-payload"+ drainPipe rfd >>= (@?= BS.empty),+ testCase "native record errors are never treated as idle" $+ withQueueEvent env mode (label <> "-error") $ \consumer producer topic _ -> do+ send producer topic "error-record"+ awaitQueuedRecord (setConsumerQueueIOEvent consumer Nothing)+ withMessageFault (if mode == CallbackPollModeAsync then 12 else 15) $ do+ result <- try @KafkaError (drainQueue consumer topic)+ result @?= Left (KafkaResponseError RdKafkaRespErrBadMsg)+ mapM messageStat [1, 2] >>= (@?= [1, 1]),+ testCase "close stops notifications and keeps caller descriptors open" $+ withQueueEvent env mode (label <> "-close") $ \consumer _ topic pipe@(rfd, wfd) -> do+ register consumer topic pipe+ closeConsumer consumer >>= (@?= Nothing)+ consumerClosed consumer >>= (@?= True)+ calls <- queueEventStat 0+ setConsumerQueueIOEvent consumer (Just (wfd, "1"))+ queueEventStat 0 >>= (@?= calls)+ _ <- drainPipe rfd+ timeout 500000 (threadWaitRead rfd) >>= (@?= Nothing)+ assertPipeOwned pipe,+ testCase "destroy stops notifications and keeps caller descriptors open" $+ withQueueEvent env mode (label <> "-destroy") $ \consumer _ topic pipe@(rfd, _) -> do+ register consumer topic pipe+ destroyConsumer consumer+ _ <- drainPipe rfd+ timeout 500000 (threadWaitRead rfd) >>= (@?= Nothing)+ assertPipeOwned pipe+ ]++register :: KafkaConsumer -> TopicName -> (Fd, Fd) -> IO ()+register consumer topic (rfd, wfd) = do+ setConsumerQueueIOEvent consumer (Just (wfd, "1"))+ drainQueue consumer topic >>= (@?= [])+ _ <- drainPipe rfd+ pure ()++-- Descriptors outlive consumer destruction, including failing test actions.+withQueueEvent :: TestEnv -> CallbackPollMode -> String -> (KafkaConsumer -> KafkaProducer -> TopicName -> (Fd, Fd) -> Assertion) -> Assertion+withQueueEvent env mode label body = withQueueTracking $+ withTopic env ("queue-event-" <> Text.pack label) 1 $ \topic producer ->+ bracket createPipe closePipe $ \pipe@(rfd, wfd) -> do+ setFdOption wfd NonBlockingRead True+ setFdOption rfd NonBlockingRead True+ let props = consumerProps env <> groupId (makeGroupId env ("queue-event-" <> Text.pack label)) <> callbackPollMode mode+ bracket (mkConsumerFor topic props) releaseConsumer $ \consumer -> do+ -- The observer borrows this final destination queue only while open.+ setConsumerQueueIOEvent consumer Nothing+ drainQueue consumer topic >>= (@?= [])+ body consumer producer topic pipe++closePipe :: (Fd, Fd) -> IO ()+closePipe (rfd, wfd) = closeFd rfd >> closeFd wfd++assertPipeOwned :: (Fd, Fd) -> Assertion+assertPipeOwned (rfd, wfd) = do+ fdWrite wfd "owner" >>= (@?= 5)+ fdRead rfd 5 >>= (@?= "owner")++send :: KafkaProducer -> TopicName -> ByteString -> IO ()+send producer topic value = sendAll producer topic [value]++sendAll :: KafkaProducer -> TopicName -> [ByteString] -> IO ()+sendAll producer topic values =+ sendMessages [ProducerRecord topic (SpecifiedPartition 0) Nothing (Just value) mempty | value <- values] producer >>= either throwIO pure++recordValue :: TopicName -> ConsumerRecord (Maybe ByteString) (Maybe ByteString) -> IO (Offset, ByteString)+recordValue topic record = do+ (crTopic record, crPartition record, crKey record, crHeaders record) @?= (topic, PartitionId 0, Nothing, mempty)+ value <- maybe (assertFailure "unexpected tombstone") pure (crValue record)+ pure (crOffset record, value)++drainQueue :: KafkaConsumer -> TopicName -> IO [(Offset, ByteString)]+drainQueue consumer topic = go (50 :: Int)+ where+ go 0 = assertFailure "queue did not become idle within fifty polls"+ go n =+ pollMessage consumer (Timeout 200) >>= \case+ Right record -> do+ value <- recordValue topic record+ (value :) <$> go (n - 1)+ Left (KafkaResponseError RdKafkaRespErrTimedOut) -> pure []+ Left (KafkaResponseError RdKafkaRespErrPartitionEof) -> go (n - 1)+ Left err -> throwIO err++fdRead :: Fd -> Int -> IO ByteString+fdRead fd n = allocaBytes n $ \buf ->+ (try (fdReadBuf fd buf (fromIntegral n)) :: IO (Either IOError ByteCount)) >>= \case+ Right count -> BS.packCStringLen (castPtr buf, fromIntegral count)+ Left err | maybe False ((`elem` [eAGAIN, eWOULDBLOCK]) . Errno) (ioe_errno err) -> pure BS.empty+ Left err -> throwIO err++drainPipe :: Fd -> IO ByteString+drainPipe rfd =+ fdRead rfd 64 >>= \case+ bytes | not (BS.null bytes) -> (bytes <>) <$> drainPipe rfd+ _ -> pure BS.empty++awaitRecord :: KafkaConsumer -> TopicName -> Int -> ByteString -> Assertion+awaitRecord consumer topic offset value = collect consumer topic 1 >>= (@?= [(Offset (fromIntegral offset), value)])++collect :: KafkaConsumer -> TopicName -> Int -> IO [(Offset, ByteString)]+collect consumer topic n =+ collectExactly getMonotonicTimeNSec 10000000000 n (pollMessage consumer (Timeout 500))+ >>= either throwIO (traverse (recordValue topic))
+ test-integration/Kafka/Integration/ReadCommittedTest.hs view
@@ -0,0 +1,72 @@+-- | Watermark queries honour the consumer's @isolation.level@ (improvement+-- request IR-2, AC-4): on a @read_committed@ consumer the high watermark is the+-- last stable offset, which stops before an open transaction.+module Kafka.Integration.ReadCommittedTest+ ( tests,+ )+where++import Control.Exception (finally)+import Data.Map qualified as Map+import Data.Text (Text)+import GHC.Clock (getMonotonicTime)+import Kafka.Consumer+import Kafka.Metadata (WatermarkOffsets (..), partitionWatermarkOffsets)+import Kafka.Producer qualified as P+import Kafka.TestEnv+import Kafka.Transaction (beginTransaction, commitTransaction, initTransactions)+import Test.Tasty (TestTree)+import Test.Tasty.HUnit (assertBool, assertFailure, testCase, (@?=))++tests :: TestEnv -> TestTree+tests env =+ testCase "read_committed watermark stops before an open transaction" $+ withTopic env "read-committed" 1 $ \topic _ -> do+ producer <-+ P.newProducer+ (producerProps env <> P.extraProps (Map.fromList [("transactional.id", prefixedName env "read-committed-tx")]))+ >>= either (assertFailure . ("newProducer: " <>) . show) pure+ flip finally (P.closeProducer producer) $ do+ initTransactions producer (Timeout 10000) >>= (@?= Nothing)+ beginTransaction producer >>= (@?= Nothing)+ P.produceMessage producer (P.ProducerRecord topic (P.SpecifiedPartition 0) Nothing (Just "pending") mempty)+ >>= (@?= Nothing)+ P.flushProducer producer++ readCommitted <- observer topic "read_committed"+ readUncommitted <- observer topic "read_uncommitted"+ flip finally (destroyConsumer readCommitted >> destroyConsumer readUncommitted) $ do+ openRc <- high readCommitted topic+ openRu <- high readUncommitted topic+ assertBool+ ("while the transaction is open, read_committed high " <> show openRc <> " must be below read_uncommitted high " <> show openRu)+ (openRc < openRu)++ commitTransaction producer (Timeout 10000) >>= assertBool "commitTransaction failed" . null+ deadline <- (+ 10) <$> getMonotonicTime+ let converge = do+ rc <- high readCommitted topic+ ru <- high readUncommitted topic+ now <- getMonotonicTime+ if rc == ru+ then assertBool ("read_committed high " <> show rc <> " did not advance past " <> show openRc) (rc > openRc)+ else+ if now > deadline+ then assertFailure ("after commit, read_committed high " <> show rc <> " never reached " <> show ru)+ else converge+ converge+ where+ observer topic (level :: Text) = do+ consumer <-+ newAssignedConsumer+ ( consumerProps env+ <> groupId (makeGroupId env ("read-committed-" <> level))+ <> noAutoCommit+ <> extraProps (Map.fromList [("isolation.level", level)])+ )+ >>= either (assertFailure . ("newAssignedConsumer: " <>) . show) pure+ assign consumer [TopicPartition topic (PartitionId 0) PartitionOffsetBeginning] >>= (@?= Nothing)+ pure consumer+ high consumer topic =+ partitionWatermarkOffsets consumer (Timeout 5000) topic (PartitionId 0)+ >>= either (assertFailure . ("partitionWatermarkOffsets: " <>) . show) (pure . woHighWatermark)
+ test-integration/Kafka/Integration/RuntimeContractTest.hs view
@@ -0,0 +1,56 @@+{-# OPTIONS_GHC -Wno-deprecations #-}++module Kafka.Integration.RuntimeContractTest (tests) where++import Control.Concurrent (rtsSupportsBoundThreads)+import Control.Exception (bracket, finally, throwIO)+import Data.IORef (modifyIORef', newIORef, readIORef, writeIORef)+import Kafka.Consumer+import Kafka.TestEnv+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.HUnit (assertBool, assertFailure, testCase, (@?=))++tests :: TestEnv -> TestTree+tests env =+ testGroup+ "runtime-contract"+ [ testCase "RTS capability is observed by async construction" $ do+ result <- newAssignedConsumer (base "async")+ if rtsSupportsBoundThreads+ then either throwIO destroyConsumer result+ else case result of+ Left (KafkaBadSpecification message) -> assertBool (show message) (message == "Async callback polling requires -threaded; select CallbackPollModeSync for a nonthreaded runtime.")+ Left err -> assertFailure (show err)+ Right consumer -> destroyConsumer consumer >> assertFailure "nonthreaded async construction silently succeeded",+ testCase "explicit async construction checks the runtime" $ do+ result <- newAssignedConsumer (base "explicit-async" <> callbackPollMode CallbackPollModeAsync)+ if rtsSupportsBoundThreads+ then either throwIO destroyConsumer result+ else case result of+ Left (KafkaBadSpecification _) -> pure ()+ Left err -> assertFailure (show err)+ Right consumer -> destroyConsumer consumer >> assertFailure "explicit nonthreaded async construction silently succeeded",+ testCase "sync subscription delivers an exact record" $+ withTopic env "runtime-sync" 1 $ \topic producer -> do+ produceTo producer topic 0 "runtime-record"+ events <- newIORef []+ let props = base "sync" <> callbackPollMode CallbackPollModeSync <> setCallback (rebalanceCallback (\_ event -> modifyIORef' events (<> [event])))+ bracket (newConsumer props (topics [topic] <> offsetReset Earliest) >>= either throwIO pure) releaseConsumer $ \consumer -> do+ pollConsumerEvents consumer (Just (Timeout 10000))+ readIORef events >>= (@?= [RebalanceBeforeAssign [(topic, PartitionId 0)], RebalanceAssign [(topic, PartitionId 0)]])+ message <- pollMessage consumer (Timeout 0) >>= either throwIO pure+ (crTopic message, crPartition message, crOffset message, crValue message) @?= (topic, PartitionId 0, Offset 0, Just "runtime-record"),+ testCase "deprecated sync runner closes after an exact record" $+ withTopic env "runtime-runner" 1 $ \topic producer -> do+ produceTo producer topic 0 "runner-record"+ retained <- newIORef Nothing+ let cleanup = readIORef retained >>= mapM_ destroyConsumer+ flip finally cleanup $ do+ result <- runConsumer (base "runner" <> callbackPollMode CallbackPollModeSync) (topics [topic] <> offsetReset Earliest) $ \consumer -> do+ writeIORef retained (Just consumer)+ fmap (fmap (\message -> (crOffset message, crValue message))) (pollMessage consumer (Timeout 10000))+ result @?= Right (Offset 0, Just "runner-record")+ readIORef retained >>= maybe (assertFailure "runner did not invoke its handler") (\consumer -> consumerClosed consumer >>= (@?= True))+ ]+ where+ base name = brokersList (teBrokers env) <> groupId (makeGroupId env ("runtime-" <> name)) <> noAutoCommit
+ test-integration/Kafka/Integration/SeekPartitionsTest.hs view
@@ -0,0 +1,268 @@+module Kafka.Integration.SeekPartitionsTest (tests) where++import Control.Concurrent (forkFinally)+import Control.Concurrent.MVar (newEmptyMVar, putMVar, readMVar)+import Control.Exception (SomeException, bracket, finally, throwIO, try)+import Control.Monad (forM_, void)+import Data.ByteString.Char8 qualified as BS+import Data.Either (isLeft)+import Data.List (sort)+import Data.Map.Strict qualified as M+import Data.Text qualified as Text+import GHC.Clock (getMonotonicTimeNSec)+import Kafka.Consumer+import Kafka.Metadata (WatermarkOffsets (..), watermarkOffsets)+import Kafka.SeekTestSupport+import Kafka.TestEnv+import System.Environment (lookupEnv)+import System.Exit (ExitCode (..))+import System.Process (readProcessWithExitCode)+import System.Timeout (timeout)+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.HUnit (assertBool, assertFailure, testCase, (@?=))++tests :: TestEnv -> TestTree+tests env =+ testGroup+ "seek-partitions"+ [ testGroup label $+ [ testCase "unassigned member reports native error" $+ withClient env mode (label <> "-unassigned") $ \consumer ->+ seekPartitions consumer [TopicPartition (TopicName (prefixedName env "never-assigned")) (PartitionId 42) (PartitionOffset 0)] (Timeout 1000)+ >>= (@?= Just (KafkaResponseError RdKafkaRespErrUnknownPartition)),+ testCase "empty list preserves top-level invalid argument" $+ withClient env mode (label <> "-empty") $ \consumer ->+ seekPartitions consumer [] (Timeout 1000) >>= (@?= Just (KafkaResponseError RdKafkaRespErrInvalidArg)),+ testCase "zero-timeout unassigned failure is immediate" $+ withClient env mode (label <> "-zero-unknown") $ \consumer -> do+ start <- getMonotonicTimeNSec+ seekPartitions consumer [TopicPartition (TopicName (prefixedName env "never-assigned")) (PartitionId 42) (PartitionOffset 0)] (Timeout 0)+ >>= (@?= Just (KafkaResponseError RdKafkaRespErrUnknownPartition))+ elapsed <- subtract start <$> getMonotonicTimeNSec+ assertBool ("zero timeout took " <> show elapsed <> " ns") (elapsed < 1000000000),+ testCase "empty zero-timeout preserves top-level error" $+ withClient env mode (label <> "-zero-empty") $ \consumer ->+ seekPartitions consumer [] (Timeout 0) >>= (@?= Just (KafkaResponseError RdKafkaRespErrInvalidArg)),+ testCase "rewind without assignment does not seek" $+ withClient env mode (label <> "-no-assignment") $ \consumer -> withSeekFault 1 $ do+ rewindConsumer consumer (Timeout 1000) >>= (@?= Nothing)+ seekStat 1 >>= (@?= 0)+ ]+ <> boundaryTests env mode label+ <> brokerTests env mode label+ | (label, mode) <- [("async", CallbackPollModeAsync), ("sync", CallbackPollModeSync)]+ ]++withClient :: TestEnv -> CallbackPollMode -> String -> (KafkaConsumer -> IO a) -> IO a+withClient env mode label = bracket acquire releaseConsumer+ where+ acquire =+ newConsumer+ (consumerPropsNoStore env <> groupId (makeGroupId env (Text.pack ("seek-" <> label))) <> callbackPollMode mode)+ (offsetReset Earliest)+ >>= either (assertFailure . show) pure++boundaryTests :: TestEnv -> CallbackPollMode -> String -> [TestTree]+boundaryTests env mode label =+ [ probe "top-level error precedes member error and is destroyed" 3 1000 [42, 43] (Just RdKafkaRespErrTimedOut),+ probe "first substantive error follows input order" 5 1000 [42, 43] (Just RdKafkaRespErrInvalidArg),+ probe "reversed input selects the other substantive error" 5 1000 [43, 42] (Just RdKafkaRespErrUnknownPartition),+ probe "zero-timeout skips pending but reports later failure" 4 0 [42, 43] (Just RdKafkaRespErrUnknownPartition),+ probe "nonzero-timeout preserves residual pending" 4 1000 [42, 43] (Just RdKafkaRespErrInProgress),+ probe "zero-timeout all pending promises initiation only" 6 0 [42, 43] Nothing,+ probe "nonzero-timeout all pending is not success" 6 1000 [42, 43] (Just RdKafkaRespErrInProgress),+ testCase "top-level decoder exception still destroys error object" $+ withClient env mode (label <> "-decode") $ \consumer -> withSeekFault 7 $ do+ result <- try @SomeException $ seekPartitions consumer [TopicPartition (TopicName "controlled") (PartitionId 42) (PartitionOffset 0)] (Timeout 1000)+ assertBool (show result) (isLeft result)+ seekStat 2 >>= (@?= 1)+ seekStat 3 >>= (@?= 1),+ testCase "rewind assignment failure prevents seek" $+ withClient env mode (label <> "-assignment-error") $ \consumer -> withSeekFault 12 $ do+ rewindConsumer consumer (Timeout 1000) >>= (@?= Just (KafkaResponseError RdKafkaRespErrState))+ seekStat 1 >>= (@?= 0)+ ]+ where+ probe name fault milliseconds partitions expected = testCase name $+ withClient env mode (label <> "-" <> name) $ \consumer -> withSeekFault fault $ do+ seekPartitions consumer [TopicPartition (TopicName "controlled") (PartitionId p) (PartitionOffset 0) | p <- partitions] (Timeout milliseconds)+ >>= (@?= fmap KafkaResponseError expected)+ seekStat 1 >>= (@?= 1)+ seekStat 2 >>= (@?= if fault == 3 then 1 else 0)+ seekStat 3 >>= (@?= if fault == 3 then 1 else 0)++brokerTests :: TestEnv -> CallbackPollMode -> String -> [TestTree]+brokerTests env mode label =+ [ scenario "single seek replays exact record" $ \topic consumer -> do+ warm topic consumer+ seekPartitions consumer [part topic 0 (PartitionOffset 1)] (Timeout 2000) >>= (@?= Nothing)+ expectRecord consumer topic 0 1,+ scenario "multiple successful seeks replay both partitions" $ \topic consumer -> do+ assign consumer [part topic p (PartitionOffset 0) | p <- [0, 1]] >>= (@?= Nothing)+ records <- receiveMessages consumer 8 >>= either (assertFailure . show) pure+ sort [(crPartition r, crOffset r, crValue r) | r <- records]+ @?= sort [(PartitionId p, Offset (fromIntegral n), Just (payload p n)) | p <- [0, 1], n <- [0 .. 3]]+ seekPartitions consumer [part topic 0 (PartitionOffset 2), part topic 1 (PartitionOffset 1)] (Timeout 2000) >>= (@?= Nothing)+ replay <- receiveMessages consumer 5 >>= either (assertFailure . show) pure+ sort [(crPartition r, crOffset r, crValue r) | r <- replay]+ @?= sort [(PartitionId p, Offset (fromIntegral n), Just (payload p n)) | (p, ns) <- [(0, [2, 3]), (1, [1, 2, 3])], n <- ns],+ scenario "mixed seek reports failure without rolling back success" $ \topic consumer -> do+ warm topic consumer+ seekPartitions consumer [part topic 0 (PartitionOffset 1), part (TopicName (prefixedName env "seek-never-assigned")) 42 (PartitionOffset 0)] (Timeout 2000)+ >>= (@?= Just (KafkaResponseError RdKafkaRespErrUnknownPartition))+ expectRecord consumer topic 0 1,+ scenario "mixed errors follow actual request order" $ \topic consumer -> do+ warm topic consumer+ seekPartitions consumer [part topic 0 PartitionOffsetStored, part (TopicName (prefixedName env "seek-never-assigned")) 42 (PartitionOffset 0)] (Timeout 2000)+ >>= (@?= Just (KafkaResponseError RdKafkaRespErrInvalidArg))+ seekPartitions consumer [part (TopicName (prefixedName env "seek-never-assigned")) 42 (PartitionOffset 0), part topic 0 PartitionOffsetStored] (Timeout 2000)+ >>= (@?= Just (KafkaResponseError RdKafkaRespErrUnknownPartition)),+ scenario "zero-timeout valid seek is followed by synchronous replay" $ \topic consumer -> do+ warm topic consumer+ start <- getMonotonicTimeNSec+ seekPartitions consumer [part topic 0 (PartitionOffset 1)] (Timeout 0) >>= (@?= Nothing)+ elapsed <- subtract start <$> getMonotonicTimeNSec+ assertBool (show elapsed) (elapsed < 1000000000)+ -- Zero timeout promises no completion barrier. A synchronous seek supplies it.+ seekPartitions consumer [part topic 0 (PartitionOffset 1)] (Timeout 2000) >>= (@?= Nothing)+ expectRecord consumer topic 0 1,+ scenario "zero-timeout mixed request keeps immediate unknown error" $ \topic consumer -> do+ warm topic consumer+ seekPartitions consumer [part topic 0 (PartitionOffset 1), part (TopicName (prefixedName env "seek-never-assigned")) 42 (PartitionOffset 0)] (Timeout 0)+ >>= (@?= Just (KafkaResponseError RdKafkaRespErrUnknownPartition)),+ scenario "zero-timeout logical offsets promise initiation only" $ \topic consumer -> do+ warm topic consumer+ forM_ [PartitionOffsetBeginning, PartitionOffsetEnd, PartitionOffsetInvalid, PartitionOffsetStored, PartitionOffset (-2002)] $ \offset -> do+ seekPartitions consumer [part topic 0 offset] (Timeout 0) >>= (@?= Nothing)+ -- Even a later native rejection (STORED) cannot be reported by an+ -- initiation-only call. Synchronize with a supported absolute seek.+ seekPartitions consumer [part topic 0 (PartitionOffset 0)] (Timeout 2000) >>= (@?= Nothing)+ expectRecord consumer topic 0 0,+ scenario "infinite native timeout completes a valid seek" $ \topic consumer -> do+ warm topic consumer+ seekPartitions consumer [part topic 0 (PartitionOffset 2)] (Timeout (-1)) >>= (@?= Nothing)+ expectRecord consumer topic 0 2,+ scenario "duplicate entries preserve residual native pending error" $ \topic consumer -> do+ warm topic consumer+ -- Native replies update the first matching duplicate, leaving the second+ -- pending. Do not claim completion of both members or deduplicate silently.+ seekPartitions consumer [part topic 0 (PartitionOffset 1), part topic 0 (PartitionOffset 2)] (Timeout 2000)+ >>= (@?= Just (KafkaResponseError RdKafkaRespErrInProgress)),+ scenario "unassigned existing partition returns state error" $ \topic consumer -> do+ warm topic consumer+ assign consumer [] >>= (@?= Nothing)+ seekPartitions consumer [part topic 0 (PartitionOffset 0)] (Timeout 2000)+ >>= (@?= Just (KafkaResponseError RdKafkaRespErrState)),+ scenario "unknown topic reports member error" $ \_ consumer ->+ seekPartitions consumer [part (TopicName (prefixedName env "seek-unknown-topic")) 0 (PartitionOffset 0)] (Timeout 2000)+ >>= (@?= Just (KafkaResponseError RdKafkaRespErrUnknownPartition)),+ scenario "stored sentinel is rejected without altering position" $ \topic consumer -> do+ warm topic consumer+ seekPartitions consumer [part topic 0 PartitionOffsetStored] (Timeout 2000)+ >>= (@?= Just (KafkaResponseError RdKafkaRespErrInvalidArg))+ position consumer [(topic, PartitionId 0)] >>= (@?= Right [part topic 0 (PartitionOffset 4)]),+ scenario "end and exact high watermark produce no record" $ \topic consumer -> do+ warm topic consumer+ forM_ [PartitionOffsetEnd, PartitionOffset 4] $ \offset -> do+ seekPartitions consumer [part topic 0 offset] (Timeout 2000) >>= (@?= Nothing)+ pollMessage consumer (Timeout 250) >>= (@?= Left (KafkaResponseError RdKafkaRespErrTimedOut)),+ scenario "seek before retained log range resets to actual low watermark" $ \topic consumer -> do+ warm topic consumer+ trimPrefix topic+ -- Query the broker, rather than trusting the CLI's acknowledgement.+ offsets <- sequence <$> watermarkOffsets consumer (Timeout 5000) topic+ offsets @?= Right [WatermarkOffsets topic (PartitionId 0) (Offset 2) (Offset 4), WatermarkOffsets topic (PartitionId 1) (Offset 0) (Offset 4)]+ forM_ [PartitionOffset 0, PartitionOffsetBeginning, PartitionOffset 2] $ \offset -> do+ seekPartitions consumer [part topic 0 offset] (Timeout 2000) >>= (@?= Nothing)+ expectRecord consumer topic 0 2,+ scenario "rewind without committed offset starts at beginning" $ \topic consumer -> do+ warm topic consumer+ committed consumer (Timeout 5000) [(topic, PartitionId 0)] >>= (@?= Right [part topic 0 PartitionOffsetInvalid])+ rewindConsumer consumer (Timeout 5000) >>= (@?= Nothing)+ expectRecord consumer topic 0 0,+ scenario "rewind uses committed next offset exactly" $ \topic consumer -> do+ warm topic consumer+ commitPartitionsOffsets OffsetCommit consumer [part topic 0 (PartitionOffset 2)] >>= (@?= Nothing)+ committed consumer (Timeout 5000) [(topic, PartitionId 0)] >>= (@?= Right [part topic 0 (PartitionOffset 2)])+ rewindConsumer consumer (Timeout 5000) >>= (@?= Nothing)+ expectRecord consumer topic 0 2,+ scenario "rewind message commit resumes after committed message" $ \topic consumer -> do+ assign consumer [part topic 0 (PartitionOffset 0)] >>= (@?= Nothing)+ record <- nextRecord consumer+ crOffset record @?= Offset 0+ commitOffsetMessage OffsetCommit consumer record >>= (@?= Nothing)+ committed consumer (Timeout 5000) [(topic, PartitionId 0)] >>= (@?= Right [part topic 0 (PartitionOffset 1)])+ rewindConsumer consumer (Timeout 5000) >>= (@?= Nothing)+ expectRecord consumer topic 0 1,+ scenario "rewind lookup failure prevents seek" $ \topic consumer -> do+ warm topic consumer+ withSeekFault 11 $ do+ rewindConsumer consumer (Timeout 1000) >>= (@?= Just (KafkaResponseError RdKafkaRespErrTimedOut))+ seekStat 1 >>= (@?= 0),+ scenario "rewind propagates assignment change after committed lookup" $ \topic consumer -> do+ warm topic consumer+ commitPartitionsOffsets OffsetCommit consumer [part topic 0 (PartitionOffset 1)] >>= (@?= Nothing)+ withSeekFault 10 $ do+ result <- newEmptyMVar+ void $ forkFinally (rewindConsumer consumer (Timeout 5000)) (putMVar result)+ let join = timeout 10000000 (readMVar result) >>= maybe (assertFailure "rewind thread did not complete") (either throwIO pure)+ flip finally (releaseCommittedBoundary >> void join) $ do+ awaitCommittedBoundary+ assignment consumer >>= (@?= Right (M.singleton topic [PartitionId 0]))+ assign consumer [] >>= (@?= Nothing)+ assignment consumer >>= (@?= Right M.empty)+ releaseCommittedBoundary+ join >>= (@?= Just (KafkaResponseError RdKafkaRespErrState))+ seekStat 1 >>= (@?= 1)+ ]+ <> [ scenario name $ \topic consumer -> do+ warm topic consumer+ seekPartitions consumer [part topic 0 offset] (Timeout 2000) >>= (@?= Nothing)+ expectRecord consumer topic 0 expected+ | (name, offset, expected) <-+ [ ("beginning sentinel replays offset zero", PartitionOffsetBeginning, 0),+ ("absolute low watermark replays offset zero", PartitionOffset 0, 0),+ ("invalid sentinel uses configured earliest reset", PartitionOffsetInvalid, 0),+ ("above high watermark uses configured earliest reset", PartitionOffset 999999, 0),+ ("native tail sentinel replays final two records", PartitionOffset (-2002), 2)+ ]+ ]+ where+ scenario name action = testCase name $+ withTopic env (Text.pack ("seek-" <> label <> "-" <> take 48 (map slug name))) 2 $ \topic producer -> do+ forM_ [0, 1] $ \p -> forM_ [0 .. 3] $ \n -> produceTo producer topic p (payload p n)+ withClient env mode (label <> "-" <> map slug name) (action topic)+ slug c+ | c >= 'a' && c <= 'z' = c+ | otherwise = '-'++part :: TopicName -> Int -> PartitionOffset -> TopicPartition+part topic partition = TopicPartition topic (PartitionId partition)++payload :: Int -> Int -> BS.ByteString+payload partition offset = BS.pack ("partition=" <> show partition <> ";offset=" <> show offset)++warm :: TopicName -> KafkaConsumer -> IO ()+warm topic consumer = do+ assign consumer [part topic 0 (PartitionOffset 0)] >>= (@?= Nothing)+ forM_ [0 .. 3] (expectRecord consumer topic 0)++nextRecord :: KafkaConsumer -> IO (ConsumerRecord (Maybe BS.ByteString) (Maybe BS.ByteString))+nextRecord consumer = pollMessage consumer (Timeout 10000) >>= either (assertFailure . show) pure++expectRecord :: KafkaConsumer -> TopicName -> Int -> Int -> IO ()+expectRecord consumer topic partition offset = do+ record <- nextRecord consumer+ (crTopic record, crPartition record, crOffset record, crKey record, crValue record, crHeaders record)+ @?= (topic, PartitionId partition, Offset (fromIntegral offset), Nothing, Just (payload partition offset), mempty)++trimPrefix :: TopicName -> IO ()+trimPrefix (TopicName topic) = do+ configured <- lookupEnv "RDKAFKA_TEST_RPK"+ let args = ["topic", "trim-prefix", Text.unpack topic, "--offset", "2", "--partitions", "0", "--no-confirm"]+ (command, commandArgs) = case configured of+ Just path -> (path, args)+ Nothing -> ("container", ["exec", "rdkafka-hs-rp-0", "rpk"] <> args)+ (exit, output, errors) <- readProcessWithExitCode command commandArgs ""+ exit @?= ExitSuccess+ assertBool (errors <> output) (not (null output))
+ test-integration/Kafka/Integration/StoreOffsetsTest.hs view
@@ -0,0 +1,72 @@+module Kafka.Integration.StoreOffsetsTest+ ( tests,+ )+where++import Control.Monad (forM)+import Kafka.Consumer+import Kafka.TestEnv+import Test.Tasty (DependencyType (AllSucceed), TestTree, dependentTestGroup)+import Test.Tasty.HUnit (testCase, (@?=))++tests :: TestEnv -> TestTree+tests env =+ dependentTestGroup+ "Store offsets"+ AllSucceed+ [ produce "1. sends 2 messages to test topic",+ withConsumer env (consumerPropsNoStore env) $ \getConsumer ->+ testCase "2. should receive 2 messages without storing" $ do+ k <- getConsumer+ res <- receiveTestMessages env k 2 4+ length <$> res @?= Right 2++ comRes <- commitAllOffsets OffsetCommit k+ comRes @?= Just (KafkaResponseError RdKafkaRespErrNoOffset),+ produce "3. sends 2 messages to test topic",+ withConsumer env (consumerPropsNoStore env) $ \getConsumer ->+ testCase "4. should receive 4 messages and store them" $ do+ k <- getConsumer+ res <- receiveTestMessages env k 4 4+ storeRes <- forM res . mapM $ storeOffsetMessage k+ comRes <- commitAllOffsets OffsetCommit k++ storeRes @?= Right (replicate 4 Nothing)+ length <$> res @?= Right 4+ comRes @?= Nothing,+ produce "5. sends 2 messages to test topic",+ withConsumer env (consumerPropsNoStore env) $ \getConsumer ->+ testCase "6. should receive 2 messages" $ do+ k <- getConsumer+ res <- receiveTestMessages env k 2 8+ storeRes <- forM res $ mapM (storeOffsetMessage k)+ comRes <- commitAllOffsets OffsetCommit k++ length <$> res @?= Right 2+ storeRes @?= Right [Nothing, Nothing]+ comRes @?= Nothing,+ withKafka env (consumerPropsNoStore env) $ \getKafka ->+ dependentTestGroup+ "Part 3 - Consume after committing stored offsets"+ AllSucceed+ [ testCase "5. sends 2 messages to test topic" $ do+ (_, prod) <- getKafka+ res <- sendMessages (testMessages (teTopic env)) prod+ res @?= Right (),+ testCase "6. should receive 2 messages" $ do+ (k, _) <- getKafka+ res <- receiveTestMessages env k 2 10+ storeRes <- forM res $ mapM (storeOffsetMessage k)+ comRes <- commitAllOffsets OffsetCommit k++ length <$> res @?= Right 2+ storeRes @?= Right [Nothing, Nothing]+ comRes @?= Nothing+ ]+ ]+ where+ produce name =+ withProducer env $ \getProducer ->+ testCase name $ do+ res <- getProducer >>= sendMessages (testMessages (teTopic env))+ res @?= Right ()
+ test-integration/Kafka/Integration/TopicConfigurationTest.hs view
@@ -0,0 +1,527 @@+module Kafka.Integration.TopicConfigurationTest (tests) where++import Control.Concurrent (forkFinally, killThread, threadDelay)+import Control.Concurrent.MVar (newEmptyMVar, putMVar, readMVar, takeMVar)+import Control.Exception (AsyncException (ThreadKilled), bracket, finally, fromException, throwIO)+import Control.Monad (forM_, unless, when)+import Data.List (sort)+import Data.Map qualified as Map+import Data.Text qualified as Text+import Foreign.C.Types (CInt)+import GHC.Clock (getMonotonicTime)+import GHC.Conc (BlockReason (BlockedOnException), ThreadStatus (ThreadBlocked), threadStatus)+import Kafka.AdminTestSupport+import Kafka.Consumer qualified as C+import Kafka.FaultTestSupport (withUnresponsiveBroker)+import Kafka.Metadata+import Kafka.Producer+import Kafka.TestEnv+import Kafka.Topic+import System.Environment (lookupEnv)+import System.Exit (ExitCode (..))+import System.Process (readProcessWithExitCode)+import System.Timeout (timeout)+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.HUnit (assertBool, assertFailure, testCase, (@?=))++tests :: TestEnv -> TestTree+tests env =+ testGroup "topic-configuration" $+ [ testCase "singleton configuration reaches the broker" $+ bracket (mkProducer env) releaseProducer $ \producer -> withNativeTracking $ do+ let topic = TopicName (prefixedName env "config-singleton")+ create =+ createTopic producer (NewTopic topic (PartitionCount 1) (ReplicationFactor 1) (Map.singleton "cleanup.policy" "compact"))+ >>= either throwIO pure+ remove name = deleteTopic producer name >>= (@?= Right name)+ bracket create remove $ \created -> do+ created @?= topic+ metadata <- topicMetadata producer (Timeout 5000) topic+ map (\t -> (tmTopicName t, map pmPartitionId (tmPartitions t))) . kmTopics <$> metadata+ @?= Right [(topic, [PartitionId 0])]+ values <- configValues topic "cleanup.policy"+ values @?= ["compact"]+ submissions >>= (@?= 1)+ counts NativeNewTopic >>= (@?= (1, 1))+ counts NativeDeleteTopic >>= (@?= (1, 1))+ mapM_ (\kind -> counts kind >>= \(allocated, _) -> assertBool ("unobserved " <> show kind) (allocated > 0)) [NativeQueue, NativeOptions, NativeEvent]+ assertBalanced,+ testCase "native allocation control detects a retained request" $+ withNativeTracking $ do+ withLeakControl $ counts NativeNewTopic >>= (@?= (1, 0))+ counts NativeNewTopic >>= (@?= (1, 1))+ assertBalanced,+ testCase "setter rejection releases allocated request before submission" $+ bracket (mkProducer env) releaseProducer $ \producer -> withNativeTracking $ do+ let topic = TopicName (prefixedName env "config-rejected-setter")+ failConfiguration True+ result <- createTopic producer (NewTopic topic (PartitionCount 1) (ReplicationFactor 1) (Map.singleton "cleanup.policy" "compact"))+ result @?= Left (KafkaResponseError RdKafkaRespErrInvalidArg)+ counts NativeNewTopic >>= (@?= (1, 1))+ counts NativeEvent >>= (@?= (0, 0))+ metadata <- allTopicsMetadata producer (Timeout 5000)+ (elem topic . map tmTopicName . kmTopics) <$> metadata @?= Right False+ submissions >>= (@?= 0)+ assertBalanced,+ testCase "interruption after allocation releases request before submission" $+ bracket (mkProducer env) releaseProducer $ \producer -> withNativeTracking $ do+ let topic = TopicName (prefixedName env "config-interrupted")+ blockConfiguration True+ completed <- newEmptyMVar+ worker <-+ forkFinally+ (createTopic producer (NewTopic topic (PartitionCount 1) (ReplicationFactor 1) (Map.singleton "cleanup.policy" "compact")))+ (putMVar completed)+ flip finally (blockConfiguration False >> killThread worker) $ do+ await configurationEntered+ counts NativeNewTopic >>= (@?= (1, 0))+ interrupted <- newEmptyMVar+ killer <- forkFinally (killThread worker) (putMVar interrupted)+ -- The killer is observed waiting for delivery while the native+ -- setter remains blocked. No scheduling delay defines the window.+ await ((== ThreadBlocked BlockedOnException) <$> threadStatus killer)+ blockConfiguration False+ result <- bounded (takeMVar completed)+ case result of+ Left exception -> fromException exception @?= Just ThreadKilled+ Right value -> assertFailure ("interrupted create returned " <> show value)+ bounded (takeMVar interrupted) >>= either throwIO pure+ submissions >>= (@?= 0)+ counts NativeNewTopic >>= (@?= (1, 1))+ assertBalanced,+ testCase "multiple configuration entries reach the broker" $+ bracket (mkProducer env) releaseProducer $ \producer -> withNativeTracking $ do+ let topic = TopicName (prefixedName env "config-multiple")+ settings = Map.fromList [("cleanup.policy", "compact"), ("retention.ms", "120000")]+ bracket+ (createTopic producer (NewTopic topic (PartitionCount 2) (ReplicationFactor 1) settings) >>= either throwIO pure)+ (\created -> deleteTopic producer created >>= (@?= Right created))+ $ \created -> do+ created @?= topic+ configValues topic "cleanup.policy" >>= (@?= ["compact"])+ configValues topic "retention.ms" >>= (@?= ["120000"])+ metadata <- topicMetadata producer (Timeout 5000) topic+ map (\t -> (tmTopicName t, map pmPartitionId (tmPartitions t))) . kmTopics <$> metadata+ @?= Right [(topic, [PartitionId 0, PartitionId 1])]+ assertBalanced,+ testCase "broker-rejected values release requests and response events repeatedly" $+ bracket (mkProducer env) releaseProducer $ \producer -> withNativeTracking $ do+ let topicsToReject = [TopicName (prefixedName env ("config-invalid-value-" <> Text.pack (show n))) | n <- [1 .. 20 :: Int]]+ forM_ topicsToReject $ \topic -> do+ result <- createTopic producer (NewTopic topic (PartitionCount 1) (ReplicationFactor 1) (Map.singleton "cleanup.policy" "not-a-policy"))+ result @?= Left (KafkaResponseError RdKafkaRespErrInvalidConfig)+ assertBalanced+ counts NativeNewTopic >>= (@?= (20, 20))+ counts NativeEvent >>= (@?= (20, 20))+ metadata <- allTopicsMetadata producer (Timeout 5000)+ (filter (`elem` topicsToReject) . map tmTopicName . kmTopics) <$> metadata @?= Right [],+ testCase "mismatched topic in an error response cannot report another topic's error" $+ bracket (mkProducer env) releaseProducer $ \producer -> withNativeTracking $ do+ let topic = TopicName (prefixedName env "config-wrong-error-topic")+ responseMode WrongTopic+ createTopic producer (NewTopic topic (PartitionCount 1) (ReplicationFactor 1) (Map.singleton "cleanup.policy" "not-a-policy"))+ >>= (@?= Left KafkaInvalidReturnValue)+ counts NativeNewTopic >>= (@?= (1, 1))+ counts NativeEvent >>= (@?= (1, 1))+ assertAbsent producer topic+ assertBalanced,+ testCase "unrepresentable partition count never wraps to broker defaults" $+ bracket (mkProducer env) releaseProducer $ \producer -> do+ let topic = TopicName (prefixedName env "config-partition-overflow")+ result <- createTopic producer (NewTopic topic (PartitionCount maxBound) (ReplicationFactor 1) mempty)+ forM_ result $ \created -> deleteTopic producer created >>= (@?= Right created)+ result @?= Left (KafkaBadSpecification "partition count is outside the C int range"),+ testCase "NUL in a topic name never creates a truncated topic" $+ bracket (mkProducer env) releaseProducer $ \producer -> do+ let prefix = TopicName (prefixedName env "config-nul-name")+ topic = TopicName (unTopicName prefix <> "\0ignored")+ flip finally (removeIfPresent producer prefix) $ withNativeTracking $ do+ result <- createTopic producer (NewTopic topic (PartitionCount 1) (ReplicationFactor 1) mempty)+ result @?= Left (KafkaBadSpecification "topic name must not contain NUL")+ counts NativeNewTopic >>= (@?= (0, 0))+ metadata <- allTopicsMetadata producer (Timeout 5000)+ (elem prefix . map tmTopicName . kmTopics) <$> metadata @?= Right False+ assertBalanced,+ testCase "unresponsive broker preserves the native timeout error" $+ withUnresponsiveBroker $ \address connected ->+ bracket+ (newProducer (brokersList [address] <> extraProps (Map.fromList [("socket.timeout.ms", "100"), ("log_level", "0")])) >>= either throwIO pure)+ releaseProducer+ $ \producer -> do+ connected+ withNativeTracking $ do+ let topic = TopicName (prefixedName env "config-unresponsive")+ result <- bounded (createTopic producer (NewTopic topic (PartitionCount 1) (ReplicationFactor 1) mempty))+ result @?= Left (KafkaResponseError RdKafkaRespErrTimedOut)+ counts NativeNewTopic >>= (@?= (1, 1))+ counts NativeEvent >>= (@?= (1, 1))+ assertBalanced+ ]+ <> boundaryTests env+ <> modeAndConcurrencyTests env+ <> timeoutDecodeTests env++-- | The default CLI runs inside the project-owned container. Other isolated+-- environments provide an rpk executable using RDKAFKA_TEST_RPK; it inherits+-- that environment's broker configuration. No shell interpolates topic names.+configValues :: TopicName -> String -> IO [String]+configValues (TopicName topic) key = do+ localRpk <- lookupEnv "RDKAFKA_TEST_RPK"+ let args = ["topic", "describe", Text.unpack topic, "-c"]+ (command, commandArgs) = case localRpk of+ Just path -> (path, args)+ Nothing -> ("container", ["exec", "rdkafka-hs-rp-0", "rpk"] <> args)+ (exit, output, errors) <- readProcessWithExitCode command commandArgs ""+ case exit of+ ExitFailure code -> assertFailure ("rpk failed (" <> show code <> "): " <> errors <> output)+ ExitSuccess -> pure [value | line <- lines output, name : value : _ <- [words line], name == key]++await :: IO Bool -> IO ()+await predicate = bounded go+ where+ go = predicate >>= \ready -> unless ready (threadDelay 1000 >> go)++bounded :: IO a -> IO a+bounded action = timeout 5000000 action >>= maybe (assertFailure "native ownership stage timed out") pure++removeIfPresent :: KafkaProducer -> TopicName -> IO ()+removeIfPresent producer topic =+ deleteTopic producer topic >>= \case+ Right actual -> actual @?= topic+ Left (KafkaResponseError RdKafkaRespErrUnknownTopicOrPart) -> pure ()+ Left err -> throwIO err++boundaryTests :: TestEnv -> [TestTree]+boundaryTests env =+ [ testCase "empty configuration creates a usable topic" $+ bracket (mkProducer env) releaseProducer $ \producer -> do+ let topic = TopicName (prefixedName env "config-empty")+ bracket+ ( withNativeTracking $ do+ result <- createTopic producer (NewTopic topic (PartitionCount 1) (ReplicationFactor 1) mempty)+ result @?= Right topic+ assertBalanced+ pure topic+ )+ (\created -> withNativeTracking $ deleteTopic producer created >>= (@?= Right created) >> assertBalanced)+ $ \created -> do+ sendMessages [ProducerRecord created (SpecifiedPartition 0) Nothing (Just "empty-configuration") mempty] producer >>= (@?= Right ())+ bracket (mkConsumerFor created (consumerProps env <> C.groupId (makeGroupId env "config-empty"))) releaseConsumer $ \consumer -> do+ records <- receiveMessages consumer 1+ map (\r -> (C.crTopic r, C.crPartition r, C.crOffset r, C.crKey r, C.crValue r, headersToList (C.crHeaders r))) <$> records+ @?= Right [(created, PartitionId 0, C.Offset 0, Nothing, Just "empty-configuration", [])],+ testCase "later setter rejection releases partially configured request" $+ bracket (mkProducer env) releaseProducer $ \producer -> withNativeTracking $ do+ let topic = TopicName (prefixedName env "config-second-rejected")+ settings = Map.fromList [("cleanup.policy", "compact"), ("retention.ms", "120000"), ("segment.ms", "60000")]+ rejectConfigurationAt 2+ createTopic producer (NewTopic topic (PartitionCount 1) (ReplicationFactor 1) settings)+ >>= (@?= Left (KafkaResponseError RdKafkaRespErrInvalidArg))+ configurationCalls >>= (@?= 2)+ submissions >>= (@?= 0)+ counts NativeNewTopic >>= (@?= (1, 1))+ assertAbsent producer topic+ assertBalanced,+ testCase "duplicate creation preserves the existing topic" $+ bracket (mkProducer env) releaseProducer $ \producer -> withNativeTracking $ do+ let topic = TopicName (prefixedName env "config-duplicate")+ specification = NewTopic topic (PartitionCount 2) (ReplicationFactor 1) mempty+ bracket (createTopic producer specification >>= either throwIO pure) (removeIfPresent producer) $ \created -> do+ created @?= topic+ createTopic producer specification >>= (@?= Left (KafkaResponseError RdKafkaRespErrTopicAlreadyExists))+ metadata <- topicMetadata producer (Timeout 5000) topic+ map (\t -> (tmTopicName t, map pmPartitionId (tmPartitions t))) . kmTopics <$> metadata+ @?= Right [(topic, [PartitionId 0, PartitionId 1])]+ assertBalanced,+ testCase "deletion removes exactly the existing topic" $+ bracket (mkProducer env) releaseProducer $ \producer -> do+ let topic = TopicName (prefixedName env "config-delete")+ bracket (createTopic producer (NewTopic topic (PartitionCount 1) (ReplicationFactor 1) mempty) >>= either throwIO pure) (removeIfPresent producer) $ \_ -> withNativeTracking $ do+ let survivor = TopicName (prefixedName env "config-delete-survivor")+ bracket+ (createTopic producer (NewTopic survivor (PartitionCount 1) (ReplicationFactor 1) mempty) >>= either throwIO pure)+ (removeIfPresent producer)+ $ \_ -> do+ deleteTopic producer topic >>= (@?= Right topic)+ awaitAbsent producer topic+ assertPresent producer survivor+ assertBalanced,+ testCase "missing topic deletion preserves its error and releases the request" $+ bracket (mkProducer env) releaseProducer $ \producer -> withNativeTracking $ do+ let topic = TopicName (prefixedName env "config-delete-missing")+ deleteTopic producer topic >>= (@?= Left (KafkaResponseError RdKafkaRespErrUnknownTopicOrPart))+ counts NativeDeleteTopic >>= (@?= (1, 1))+ assertAbsent producer topic+ assertBalanced,+ testCase "NUL deletion cannot remove a truncated victim name" $+ withTopic env "config-delete-nul-victim" 1 $ \victim producer -> withNativeTracking $ do+ deleteTopic producer (TopicName (unTopicName victim <> "\0ignored"))+ >>= (@?= Left (KafkaBadSpecification "topic name must not contain NUL"))+ counts NativeDeleteTopic >>= (@?= (0, 0))+ assertPresent producer victim+ assertBalanced,+ testCase "broker default partition and replication counts remain supported" $+ bracket (mkProducer env) releaseProducer $ \producer -> withNativeTracking $ do+ let topic = TopicName (prefixedName env "config-default-counts")+ bracket+ (createTopic producer (NewTopic topic (PartitionCount (-1)) (ReplicationFactor (-1)) mempty) >>= either throwIO pure)+ (removeIfPresent producer)+ $ \created -> do+ created @?= topic+ metadata <- topicMetadata producer (Timeout 5000) topic+ map (\t -> (tmTopicName t, map (\p -> (pmPartitionId p, length (pmReplicas p))) (tmPartitions t))) . kmTopics <$> metadata+ @?= Right [(topic, [(PartitionId 0, 1)])]+ assertBalanced,+ testCase "replication above the available broker count is rejected" $+ bracket (mkProducer env) releaseProducer $ \producer -> do+ metadata <- allTopicsMetadata producer (Timeout 5000) >>= either throwIO pure+ let topic = TopicName (prefixedName env "config-replication-unavailable")+ withNativeTracking $ do+ result <- createTopic producer (NewTopic topic (PartitionCount 1) (ReplicationFactor (length (kmBrokers metadata) + 1)) mempty)+ forM_ result (removeIfPresent producer)+ result @?= Left (KafkaResponseError RdKafkaRespErrInvalidReplicationFactor)+ assertAbsent producer topic+ assertBalanced,+ testCase "unsupported configuration follows the declared broker policy" $+ bracket (mkProducer env) releaseProducer $ \producer -> do+ suppliedPolicy <- lookupEnv "RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY"+ policy <- case suppliedPolicy of+ Just "ignore" -> pure ("ignore" :: String)+ Just "reject" -> pure "reject"+ Nothing | teBrokers env == [BrokerAddress defaultBroker] -> pure "ignore"+ _ -> assertFailure "set RDKAFKA_TEST_UNKNOWN_TOPIC_CONFIG_POLICY to the isolated broker fixture's ignore/reject policy"+ let topic = TopicName (prefixedName env "config-unsupported")+ settings = Map.fromList [("cleanup.policy", "compact"), ("rdkafka-hs.unsupported.setting", "value")]+ flip finally (removeIfPresent producer topic) $ withNativeTracking $ do+ result <- createTopic producer (NewTopic topic (PartitionCount 1) (ReplicationFactor 1) settings)+ configurationCalls >>= (@?= 2)+ lastConfiguration >>= (@?= ("rdkafka-hs.unsupported.setting", "value"))+ if policy == "reject"+ then do+ result @?= Left (KafkaResponseError RdKafkaRespErrInvalidConfig)+ assertAbsent producer topic+ else do+ result @?= Right topic+ assertPresent producer topic+ configValues topic "cleanup.policy" >>= (@?= ["compact"])+ configValues topic "rdkafka-hs.unsupported.setting" >>= (@?= [])+ assertBalanced+ ]+ <> [ testCase name $+ bracket (mkProducer env) releaseProducer $ \producer -> withNativeTracking $ do+ let topic = TopicName (prefixedName env suffix)+ result <- createTopic producer (NewTopic topic partitions replicas settings)+ forM_ result (removeIfPresent producer)+ result @?= Left (KafkaBadSpecification reason)+ counts NativeNewTopic >>= (@?= (0, 0))+ counts NativeQueue >>= (@?= (0, 0))+ submissions >>= (@?= 0)+ assertAbsent producer topic+ assertBalanced+ | (name, suffix, partitions, replicas, settings, reason) <-+ [ ("minimum unrepresentable partition count is rejected", "config-partition-min", PartitionCount minBound, ReplicationFactor 1, mempty, "partition count is outside the C int range"),+ ("maximum unrepresentable replication count is rejected", "config-replication-max", PartitionCount 1, ReplicationFactor maxBound, mempty, "replication factor is outside the C int range"),+ ("minimum unrepresentable replication count is rejected", "config-replication-min", PartitionCount 1, ReplicationFactor minBound, mempty, "replication factor is outside the C int range"),+ ("NUL configuration key is rejected before native allocation", "config-key-nul", PartitionCount 1, ReplicationFactor 1, Map.singleton "cleanup.policy\0ignored" "compact", "topic configuration keys and values must not contain NUL"),+ ("NUL configuration value is rejected before native allocation", "config-value-nul", PartitionCount 1, ReplicationFactor 1, Map.singleton "cleanup.policy" "compact\0ignored", "topic configuration keys and values must not contain NUL")+ ]+ ]+ <> [ testCase name $+ bracket (mkProducer env) releaseProducer $ \producer -> withNativeTracking $ do+ let topic = TopicName (prefixedName env suffix)+ result <- createTopic producer (NewTopic topic partitions replicas mempty)+ case result of+ Left (KafkaError message) -> assertBool (show message) (reason `Text.isPrefixOf` message)+ other -> do+ forM_ other (removeIfPresent producer)+ assertFailure ("expected native constructor validation, got " <> show other)+ counts NativeNewTopic >>= (@?= (0, 0))+ submissions >>= (@?= 0)+ assertAbsent producer topic+ assertBalanced+ | (name, suffix, partitions, replicas, reason) <-+ [ ("negative invalid partition count retains native validation", "config-partition-negative", PartitionCount (-2), ReplicationFactor 1, "num_partitions out of expected range"),+ ("maximum C partition count retains native validation", "config-partition-cmax", PartitionCount (fromIntegral (maxBound :: CInt)), ReplicationFactor 1, "num_partitions out of expected range"),+ ("negative invalid replication count retains native validation", "config-replication-negative", PartitionCount 1, ReplicationFactor (-2), "replication_factor out of expected range"),+ ("maximum C replication count retains native validation", "config-replication-cmax", PartitionCount 1, ReplicationFactor (fromIntegral (maxBound :: CInt)), "replication_factor out of expected range")+ ]+ ]+ <> [ testCase name $+ bracket (mkProducer env) releaseProducer $ \producer -> withNativeTracking $ do+ let topic = if suffix == "" then TopicName "" else TopicName (prefixedName env suffix)+ result <- createTopic producer (NewTopic topic partitions replicas mempty)+ forM_ result (removeIfPresent producer)+ result @?= Left (KafkaResponseError expected)+ assertAbsent producer topic+ assertBalanced+ | (name, suffix, partitions, replicas, expected) <-+ [ ("empty topic name is rejected by the broker", "", PartitionCount 1, ReplicationFactor 1, RdKafkaRespErrTopicException),+ ("space in a topic name is rejected by the broker", "config invalid name", PartitionCount 1, ReplicationFactor 1, RdKafkaRespErrTopicException),+ ("overlong topic name is rejected by the broker", "config-long-" <> Text.replicate 250 "x", PartitionCount 1, ReplicationFactor 1, RdKafkaRespErrTopicException),+ ("zero partition count is rejected by the broker", "config-partition-zero", PartitionCount 0, ReplicationFactor 1, RdKafkaRespErrInvalidPartitions),+ ("zero replication count is rejected by the broker", "config-replication-zero", PartitionCount 1, ReplicationFactor 0, RdKafkaRespErrInvalidReplicationFactor)+ ]+ ]+ <> [ testCase name $+ bracket (shortRequestProducer env) releaseProducer $ \producer -> do+ let topic = TopicName (prefixedName env suffix)+ flip finally (removeIfPresent producer topic) $ withNativeTracking $ do+ responseMode mode+ result <- createTopic producer (NewTopic topic (PartitionCount 1) (ReplicationFactor 1) mempty)+ result @?= Left expected+ counts NativeEvent >>= (@?= (1, 1))+ -- The broker completed creation before the shim damaged/dropped+ -- its response. Observe that state and always remove the topic.+ assertPresent producer topic+ assertBalanced+ | (name, suffix, mode, expected) <-+ [ ("wrong event type fails and releases its event", "config-wrong-event", WrongEvent, KafkaInvalidReturnValue),+ ("empty response fails and releases its event", "config-empty-result", EmptyResult, KafkaInvalidReturnValue),+ ("wrong topic response cannot report success", "config-wrong-result", WrongTopic, KafkaInvalidReturnValue),+ ("missing polled event reports a timeout", "config-missing-event", MissingPoll, KafkaResponseError RdKafkaRespErrTimedOut)+ ]+ ]+ <> [ testCase "delayed response succeeds with balanced ownership" $+ bracket (mkProducer env) releaseProducer $ \producer -> withNativeTracking $ do+ let topic = TopicName (prefixedName env "config-delayed")+ responseMode DelayedResponse+ start <- getMonotonicTime+ bracket+ (bounded (createTopic producer (NewTopic topic (PartitionCount 1) (ReplicationFactor 1) mempty)) >>= either throwIO pure)+ (removeIfPresent producer)+ $ \created -> do+ created @?= topic+ elapsed <- subtract start <$> getMonotonicTime+ assertBool ("response delay was not exercised: " <> show elapsed) (elapsed >= 0.1)+ assertPresent producer topic+ assertBalanced+ ]++assertAbsent :: KafkaProducer -> TopicName -> IO ()+assertAbsent producer topic = do+ metadata <- allTopicsMetadata producer (Timeout 5000)+ (elem topic . map tmTopicName . kmTopics) <$> metadata @?= Right False++assertPresent :: KafkaProducer -> TopicName -> IO ()+assertPresent producer topic = do+ metadata <- allTopicsMetadata producer (Timeout 5000)+ (elem topic . map tmTopicName . kmTopics) <$> metadata @?= Right True++awaitAbsent :: KafkaProducer -> TopicName -> IO ()+awaitAbsent producer topic = bounded go+ where+ go = do+ metadata <- allTopicsMetadata producer (Timeout 5000) >>= either throwIO pure+ if topic `elem` map tmTopicName (kmTopics metadata)+ then threadDelay 10000 >> go+ else pure ()++modeAndConcurrencyTests :: TestEnv -> [TestTree]+modeAndConcurrencyTests env =+ [ testCase ("consumer administration applies settings in " <> label <> " mode")+ $ bracket+ (C.newAssignedConsumer (consumerProps env <> C.groupId (makeGroupId env ("config-consumer-" <> Text.pack label)) <> C.callbackPollMode mode) >>= either throwIO pure)+ releaseConsumer+ $ \consumer -> do+ when closeFirst (C.closeConsumer consumer >>= (@?= Nothing))+ withNativeTracking $ do+ let topic = TopicName (prefixedName env ("config-consumer-" <> Text.pack label))+ bracket+ (createTopic consumer (NewTopic topic (PartitionCount 1) (ReplicationFactor 1) (Map.singleton "cleanup.policy" "compact")) >>= either throwIO pure)+ (\created -> deleteTopic consumer created >>= (@?= Right created))+ $ \created -> do+ created @?= topic+ configValues topic "cleanup.policy" >>= (@?= ["compact"])+ metadata <- allTopicsMetadata consumer (Timeout 5000)+ (elem topic . map tmTopicName . kmTopics) <$> metadata @?= Right True+ counts NativeNewTopic >>= (@?= (1, 1))+ counts NativeDeleteTopic >>= (@?= (1, 1))+ assertBalanced+ | (mode, label, closeFirst) <- [(C.CallbackPollModeAsync, "async", False), (C.CallbackPollModeSync, "sync", False), (C.CallbackPollModeAsync, "async-closed", True), (C.CallbackPollModeSync, "sync-closed", True)]+ ]+ <> [ testCase "concurrent requests keep their own queues and responses" $+ bracket (newProducer (producerProps env <> extraProps (Map.singleton "socket.timeout.ms" "10000")) >>= either throwIO pure) releaseProducer $ \producer -> do+ let topics = [TopicName (prefixedName env ("config-concurrent-" <> Text.pack (show n))) | n <- [1 .. 20 :: Int]]+ spawn topic = do+ done <- newEmptyMVar+ thread <- forkFinally (createTopic producer (NewTopic topic (PartitionCount 1) (ReplicationFactor 1) (Map.singleton "cleanup.policy" "compact"))) (putMVar done)+ pure (topic, thread, done)+ joinResult done = timeout 12000000 (readMVar done) >>= maybe (assertFailure "concurrent admin request exceeded its native deadline") pure+ join workers = do+ forM_ workers (\(_, thread, _) -> killThread thread)+ forM_ workers (\(_, _, done) -> joinResult done)+ flip finally (mapM_ (removeIfPresent producer) topics) $ withNativeTracking $ do+ bracket (mapM spawn topics) join $ \workers ->+ forM_ workers $ \(topic, _, done) -> do+ result <- joinResult done+ either throwIO (\value -> value @?= Right topic) result+ counts NativeNewTopic >>= (@?= (20, 20))+ peak NativeQueue >>= \high -> assertBool ("no native queue overlap observed: " <> show high) (high > 1)+ metadata <- allTopicsMetadata producer (Timeout 5000)+ (sort . map (\t -> (tmTopicName t, map pmPartitionId (tmPartitions t))) . filter ((`elem` topics) . tmTopicName) . kmTopics) <$> metadata+ @?= Right (sort [(topic, [PartitionId 0]) | topic <- topics])+ assertBalanced,+ testCase "unresponsive deletion preserves the native timeout error" $+ withUnresponsiveBroker $ \address connected ->+ bracket+ (newProducer (brokersList [address] <> extraProps (Map.fromList [("socket.timeout.ms", "100"), ("log_level", "0")])) >>= either throwIO pure)+ releaseProducer+ $ \producer -> do+ connected+ withNativeTracking $ do+ let topic = TopicName (prefixedName env "config-delete-unresponsive")+ bounded (deleteTopic producer topic) >>= (@?= Left (KafkaResponseError RdKafkaRespErrTimedOut))+ counts NativeDeleteTopic >>= (@?= (1, 1))+ counts NativeEvent >>= (@?= (1, 1))+ assertBalanced+ ]+ <> [ testCase name $+ bracket (shortRequestProducer env) releaseProducer $ \producer -> do+ let topic = TopicName (prefixedName env suffix)+ bracket+ (createTopic producer (NewTopic topic (PartitionCount 1) (ReplicationFactor 1) mempty) >>= either throwIO pure)+ (removeIfPresent producer)+ $ \created -> withNativeTracking $ do+ responseMode mode+ deleteTopic producer created >>= (@?= Left expected)+ counts NativeDeleteTopic >>= (@?= (1, 1))+ counts NativeEvent >>= (@?= (1, 1))+ awaitAbsent producer topic+ assertBalanced+ | (name, suffix, mode, expected) <-+ [ ("deletion rejects a wrong event type and releases it", "config-delete-wrong-event", WrongEvent, KafkaInvalidReturnValue),+ ("deletion rejects an empty result and releases its event", "config-delete-empty-result", EmptyResult, KafkaInvalidReturnValue),+ ("deletion rejects a mismatched topic result", "config-delete-wrong-topic", WrongTopic, KafkaInvalidReturnValue),+ ("deletion reports a missing response as a timeout", "config-delete-missing-event", MissingPoll, KafkaResponseError RdKafkaRespErrTimedOut)+ ]+ ]++shortRequestProducer :: TestEnv -> IO KafkaProducer+shortRequestProducer env =+ newProducer (producerProps env <> extraProps (Map.singleton "socket.timeout.ms" "1000")) >>= either throwIO pure++-- Native configuration is immutable and validated, but malformed/error replies+-- from its getter still return a defined error before acquiring admin handles.+timeoutDecodeTests :: TestEnv -> [TestTree]+timeoutDecodeTests env =+ [ testCase name $+ bracket (mkProducer env) releaseProducer $ \producer -> withNativeTracking $ do+ let topic = TopicName (prefixedName env ("config-timeout-decode-" <> Text.pack (show mode)))+ timeoutFault mode+ createTopic producer (NewTopic topic (PartitionCount 1) (ReplicationFactor 1) mempty)+ >>= (@?= Left (KafkaError reason))+ timeoutReads >>= (@?= 1)+ counts NativeNewTopic >>= (@?= (0, 0))+ counts NativeQueue >>= (@?= (0, 0))+ submissions >>= (@?= 0)+ assertAbsent producer topic+ assertBalanced+ | (name, mode, reason) <-+ [ ("missing native timeout configuration returns an error", 1, "could not read socket.timeout.ms from the native client"),+ ("malformed native timeout configuration returns an error", 2, "invalid socket.timeout.ms value from the native client"),+ ("zero native timeout configuration returns an error", 3, "invalid socket.timeout.ms value from the native client"),+ ("negative native timeout configuration returns an error", 4, "invalid socket.timeout.ms value from the native client"),+ ("overflowing native timeout configuration returns an error", 5, "invalid socket.timeout.ms value from the native client"),+ ("oversized native timeout configuration never reads a truncated buffer", 6, "could not read socket.timeout.ms from the native client")+ ]+ ]
+ test-integration/Kafka/Integration/TopicTest.hs view
@@ -0,0 +1,56 @@+-- | Topic administration. Only topics carrying this run's prefix are ever+-- deleted.+module Kafka.Integration.TopicTest+ ( tests,+ )+where++import Control.Monad (forM_, replicateM)+import Data.Either (isRight)+import Data.IORef (newIORef, readIORef, writeIORef)+import Data.Text qualified as Text+import Kafka.Consumer+import Kafka.Metadata+import Kafka.TestEnv+import Kafka.Topic+import System.Random (randomRIO)+import Test.Tasty (DependencyType (AllSucceed), TestTree, dependentTestGroup, withResource)+import Test.Tasty.HUnit (assertBool, testCase, (@?=))++tests :: TestEnv -> TestTree+tests env =+ withResource (newIORef []) (const (pure ())) $ \getTopicsRef ->+ withConsumer env (consumerProps env) $ \getConsumer ->+ dependentTestGroup+ "Read all topics"+ AllSucceed+ [ testCase "should create a topic" $ do+ consumer <- getConsumer+ suffix <- replicateM 5 (randomRIO ('a', 'z'))+ let newTopic = mkNewTopic (TopicName (prefixedName env ("admin.topic.created." <> Text.pack suffix)))+ result <- createTopic consumer newTopic+ assertBool (show result) (isRight result),+ testCase "should return all the topics" $ do+ consumer <- getConsumer+ res <- allTopicsMetadata consumer (Timeout 1000)+ assertBool (show res) (isRight res)+ let filterUserTopics m = m {kmTopics = filter (\t -> topicType (tmTopicName t) == User) (kmTopics m)}+ let res' = fmap filterUserTopics res+ length . kmBrokers <$> res' @?= Right 1++ let runTopics = filter (isTestTopic env) (either (const []) (map tmTopicName . kmTopics) res')+ getTopicsRef >>= \ref -> writeIORef ref runTopics++ let hasTopic = teTopic env `elem` runTopics+ assertBool "expected this run's topics" (not (null runTopics))+ hasTopic @?= True,+ testCase "should delete this run's topics" $ do+ consumer <- getConsumer+ runTopics <- getTopicsRef >>= readIORef+ forM_ runTopics $ \topic -> do+ result <- deleteTopic consumer topic+ assertBool (show (topic, result)) (isRight result)+ ]++mkNewTopic :: TopicName -> NewTopic+mkNewTopic name = NewTopic name (PartitionCount 1) (ReplicationFactor 1) mempty
+ test-integration/Kafka/Integration/TransactionErrorTest.hs view
@@ -0,0 +1,305 @@+module Kafka.Integration.TransactionErrorTest (tests) where++import Control.Concurrent (forkFinally, forkIOWithUnmask, killThread, threadDelay)+import Control.Concurrent.MVar (newEmptyMVar, putMVar, readMVar, tryReadMVar)+import Control.Exception (AsyncException (ThreadKilled), SomeException, allowInterrupt, bracket, bracket_, finally, fromException, throwIO, try)+import Control.Monad (forM_, replicateM_, void, when)+import Data.ByteString qualified as BS+import Data.Either (isLeft)+import Data.Int (Int64)+import Data.Map.Strict qualified as M+import Data.Text qualified as Text+import GHC.Conc (BlockReason (BlockedOnException), ThreadStatus (ThreadBlocked), threadStatus)+import Kafka.Consumer qualified as C+import Kafka.Producer qualified as P+import Kafka.TestEnv hiding (withProducer)+import Kafka.Topic qualified as Topic+import Kafka.Transaction qualified as T+import Kafka.TransactionTestSupport+import System.Timeout (timeout)+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.HUnit (assertBool, assertFailure, testCase, (@?=))++tests :: TestEnv -> TestTree+tests testEnv =+ testGroup "transaction-errors" $+ [ testCase "transaction-error-leak-probe releases 300 immediate native errors" $+ withClients testEnv "leaks" $ \producer consumer -> withTxFault 0 $ do+ replicateM_ 100 $ forM_ ["init", "begin", "abort"] $ \operation ->+ runOperation operation producer consumer >>= (@?= notConfigured)+ txStat 0 >>= (@?= 300)+ balanced 300,+ testCase "native allocation control detects the inherited three-error leak" $+ withClients testEnv "control" $ \producer _ -> withTxFault 0 $ do+ T.beginTransaction producer >>= (@?= notConfigured)+ balanced 1+ nativeLeakControl+ txStat 0 >>= (@?= 4)+ txStat 1 >>= (@?= 1),+ testCase "initialization timeout destroys its native error on each retry" $+ withProducer testEnv "timeout" True ["127.0.0.1:1"] $ \producer -> withTxFault 0 $ do+ replicateM_ 3 $ T.initTransactions producer (C.Timeout 10) >>= (@?= Just (C.KafkaResponseError C.RdKafkaRespErrTimedOut))+ txStat 0 >>= (@?= 3)+ balanced 3,+ testCase "zero-timeout initialization resumes successfully against the broker" $+ withProducer testEnv "resume" True (teBrokers testEnv) $ \producer -> withTxFault 0 $ do+ T.initTransactions producer (C.Timeout 0) >>= (@?= Just (C.KafkaResponseError C.RdKafkaRespErrTimedOut))+ T.initTransactions producer (C.Timeout 10000) >>= (@?= Nothing)+ T.beginTransaction producer >>= (@?= Nothing)+ T.commitTransaction producer (C.Timeout 10000) >>= noTxError+ balanced 1,+ testCase "transaction state errors preserve empty commit and abort recovery" $+ withProducer testEnv "states" True (teBrokers testEnv) $ \producer -> withTxFault 0 $ do+ T.beginTransaction producer >>= (@?= stateError)+ T.initTransactions producer (C.Timeout 10000) >>= (@?= Nothing)+ T.beginTransaction producer >>= (@?= Nothing)+ T.beginTransaction producer >>= (@?= stateError)+ T.abortTransaction producer (C.Timeout 10000) >>= (@?= Nothing)+ T.abortTransaction producer (C.Timeout 1000) >>= (@?= stateError)+ T.commitTransaction producer (C.Timeout 1000) >>= checkTx C.RdKafkaRespErrState (False, False, False)+ T.beginTransaction producer >>= (@?= Nothing)+ T.commitTransaction producer (C.Timeout 10000) >>= noTxError+ T.initTransactions producer (C.Timeout 1000) >>= (@?= stateError)+ txStat 0 >>= (@?= 5)+ balanced 5,+ testCase "duplicate transactional IDs report a real fatal fencing error" $ fencing testEnv,+ testCase "broker-rejected delivery requires abort and permits a successful new transaction" $ abortRecovery testEnv+ ]+ <> [ testCase (operation <> " without transactional ID preserves native code and destroys error") $+ withClients testEnv operation $ \producer consumer -> withTxFault 0 $ do+ runOperation operation producer consumer >>= (@?= notConfigured)+ balanced 1+ if operation == "offset" then metadataBalanced else pure ()+ | operation <- operations+ ]+ <> [ testCase (operation <> " NULL return remains success") $+ withClients testEnv ("null-" <> operation) $ \producer consumer -> withTxFault 201 $ do+ runOperation operation producer consumer >>= (@?= Nothing)+ txStat 0 >>= (@?= 0)+ balanced 0+ | operation <- operations+ ]+ <> [ testCase (operation <> " invalid native code still destroys acquired error") $+ withClients testEnv ("decode-" <> operation) $ \producer consumer -> withTxFault 200 $ do+ result <- try @SomeException (runOperation operation producer consumer)+ assertBool (show result) (isLeft result)+ balanced 1+ if operation == "offset" then metadataBalanced else pure ()+ | operation <- operations+ ]+ <> [ testCase (operation <> " copies native flag combination " <> show bits <> " before destruction") $ do+ when (bits /= 0) requireNativeFlagDiagnostics+ withClients testEnv ("flags-" <> operation <> show bits) $ \producer consumer -> withTxFault (100 + bits) $ do+ result <- if operation == "commit" then T.commitTransaction producer (C.Timeout 1000) else T.commitOffsetMessageTransaction producer consumer dummy (C.Timeout 1000)+ checkTx C.RdKafkaRespErrState (odd bits, odd (bits `div` 2), odd (bits `div` 4)) result+ balanced 1+ forM_ [2 .. 5] $ \index -> txStat index >>= (@?= 1)+ if operation == "offset" then metadataBalanced >> (txStat 12 >>= (@?= 8)) else pure ()+ | operation <- ["commit", "offset"],+ bits <- [0 .. 7]+ ]+ <> [ testCase (operation <> " cancellation at decoder stage " <> show stage <> " releases once") $+ withClients testEnv ("cancel-" <> operation <> show stage) $ \producer consumer ->+ withTxFault stage (cancelDecoder operation producer consumer)+ | operation <- operations,+ stage <- if operation `elem` ["commit", "offset"] then [20 .. 23] else [20]+ ]+ <> [ testCase (label <> " commit publishes output and source next offset atomically; abort publishes neither") $+ atomicOffsets testEnv label mode+ | (label, mode) <- [("async", C.CallbackPollModeAsync), ("sync", C.CallbackPollModeSync)]+ ]++operations :: [String]+operations = ["init", "begin", "abort", "commit", "offset"]++notConfigured, stateError :: Maybe C.KafkaError+notConfigured = Just (C.KafkaResponseError C.RdKafkaRespErrNotConfigured)+stateError = Just (C.KafkaResponseError C.RdKafkaRespErrState)++dummy :: C.ConsumerRecord (Maybe BS.ByteString) (Maybe BS.ByteString)+dummy = C.ConsumerRecord (C.TopicName "transaction-source-fixture") (C.PartitionId 0) (C.Offset 7) C.NoTimestamp mempty Nothing Nothing++runOperation :: String -> P.KafkaProducer -> C.KafkaConsumer -> IO (Maybe C.KafkaError)+runOperation operation producer consumer = case operation of+ "init" -> T.initTransactions producer (C.Timeout 1000)+ "begin" -> T.beginTransaction producer+ "abort" -> T.abortTransaction producer (C.Timeout 1000)+ "commit" -> fmap T.getKafkaError <$> T.commitTransaction producer (C.Timeout 1000)+ _ -> fmap T.getKafkaError <$> T.commitOffsetMessageTransaction producer consumer dummy (C.Timeout 1000)++withProducer :: TestEnv -> String -> Bool -> [C.BrokerAddress] -> (P.KafkaProducer -> IO a) -> IO a+withProducer testEnv label transactional brokers = bracket acquire cleanup+ where+ cleanup producer =+ when transactional (void (T.abortTransaction producer (C.Timeout 5000))) `finally` releaseProducer producer+ acquire =+ P.newProducer+ ( P.brokersList brokers+ <> P.extraProp "log_level" "0"+ <> if transactional then P.extraProp "transactional.id" (prefixedName testEnv (Text.pack ("tx-" <> label))) else mempty+ )+ >>= either throwIO pure++withClients :: TestEnv -> String -> (P.KafkaProducer -> C.KafkaConsumer -> IO a) -> IO a+withClients testEnv label action = withProducer testEnv label False (teBrokers testEnv) $ \producer ->+ bracket+ (C.newAssignedConsumer (C.brokersList (teBrokers testEnv) <> C.groupId (makeGroupId testEnv (Text.pack ("tx-" <> label))) <> C.noAutoCommit) >>= either throwIO pure)+ releaseConsumer+ (action producer)++balanced :: Int64 -> IO ()+balanced count = do+ txStat 0 >>= (@?= count)+ txStat 1 >>= (@?= count)+ txStat 8 >>= (@?= 0)++metadataBalanced :: IO ()+metadataBalanced = do+ txStat 6 >>= (@?= 1)+ txStat 7 >>= (@?= 1)++checkTx :: C.RdKafkaRespErrT -> (Bool, Bool, Bool) -> Maybe T.TxError -> IO ()+checkTx code flags = \case+ Nothing -> assertFailure "expected a native transaction error"+ Just result -> do+ T.getKafkaError result @?= C.KafkaResponseError code+ (T.kafkaErrorIsFatal result, T.kafkaErrorIsRetriable result, T.kafkaErrorTxnRequiresAbort result) @?= flags++noTxError :: Maybe T.TxError -> IO ()+noTxError = maybe (pure ()) (assertFailure . show . T.getKafkaError)++bounded :: IO a -> IO a+bounded action = timeout 10000000 action >>= maybe (assertFailure "transaction stage timed out") pure++cancelDecoder :: String -> P.KafkaProducer -> C.KafkaConsumer -> IO ()+cancelDecoder operation producer consumer = do+ done <- newEmptyMVar+ worker <- forkIOWithUnmask $ \unmask -> try @SomeException (unmask (runOperation operation producer consumer <* allowInterrupt)) >>= putMVar done+ flip finally (releaseTxBoundary >> bounded (readMVar done)) $ do+ awaitTxBoundary+ txStat 0 >>= (@?= 1)+ txStat 1 >>= (@?= 0)+ killed <- newEmptyMVar+ killer <- forkFinally (killThread worker) (putMVar killed)+ let awaitPending =+ threadStatus killer >>= \status ->+ if status == ThreadBlocked BlockedOnException then pure () else threadDelay 1000 >> awaitPending+ bounded awaitPending+ tryReadMVar done >>= maybe (pure ()) (const (assertFailure "decoder returned before observed cancellation"))+ releaseTxBoundary+ bounded (readMVar done) >>= \case+ Left exception -> (fromException exception :: Maybe AsyncException) @?= Just ThreadKilled+ Right _ -> assertFailure "pending decoder cancellation was not delivered"+ bounded (readMVar killed) >>= either throwIO pure+ balanced 1+ if operation == "offset" then metadataBalanced else pure ()++atomicOffsets :: TestEnv -> String -> C.CallbackPollMode -> IO ()+atomicOffsets testEnv label mode =+ withTopic testEnv (Text.pack ("tx-source-" <> label)) 1 $ \source ordinary ->+ withTopic testEnv (Text.pack ("tx-output-" <> label)) 1 $ \output _ ->+ withProducer testEnv ("atomic-" <> label) True (teBrokers testEnv) $ \producer -> do+ produceTo ordinary source 0 "first-input"+ produceTo ordinary source 0 "second-input"+ let props = C.brokersList (teBrokers testEnv) <> C.groupId (makeGroupId testEnv (Text.pack ("tx-source-" <> label))) <> C.noAutoCommit <> C.noAutoOffsetStore <> C.callbackPollMode mode+ bracket (C.newConsumer props (C.topics [source] <> C.offsetReset C.Earliest) >>= either throwIO pure) releaseConsumer $ \consumer -> do+ first <- C.pollMessage consumer (C.Timeout 10000) >>= either throwIO pure+ C.crOffset first @?= C.Offset 0+ committedOffset consumer source >>= (@?= C.PartitionOffsetInvalid)+ T.initTransactions producer (C.Timeout 10000) >>= (@?= Nothing)+ T.beginTransaction producer >>= (@?= Nothing)+ produceTo producer output 0 "aborted-output"+ T.commitOffsetMessageTransaction producer consumer first (C.Timeout 10000) >>= noTxError+ T.abortTransaction producer (C.Timeout 10000) >>= (@?= Nothing)+ committedOffset consumer source >>= (@?= C.PartitionOffsetInvalid)+ T.beginTransaction producer >>= (@?= Nothing)+ produceTo producer output 0 "committed-output"+ T.commitOffsetMessageTransaction producer consumer first (C.Timeout 10000) >>= noTxError+ T.commitTransaction producer (C.Timeout 10000) >>= noTxError+ committedOffset consumer source >>= (@?= C.PartitionOffset 1)+ second <- C.pollMessage consumer (C.Timeout 10000) >>= either throwIO pure+ C.crOffset second @?= C.Offset 1+ T.beginTransaction producer >>= (@?= Nothing)+ produceTo producer output 0 "next-output"+ T.commitOffsetMessageTransaction producer consumer second (C.Timeout 10000) >>= noTxError+ T.commitTransaction producer (C.Timeout 10000) >>= noTxError+ committedOffset consumer source >>= (@?= C.PartitionOffset 2)+ visible testEnv mode (label <> "-committed") output "read_committed" ["committed-output", "next-output"]+ visible testEnv mode (label <> "-uncommitted") output "read_uncommitted" ["aborted-output", "committed-output", "next-output"]++committedOffset :: C.KafkaConsumer -> C.TopicName -> IO C.PartitionOffset+committedOffset consumer topic =+ C.committed consumer (C.Timeout 10000) [(topic, C.PartitionId 0)] >>= \case+ Right [C.TopicPartition actual (C.PartitionId 0) offset] | actual == topic -> pure offset+ other -> assertFailure (show other)++visible :: TestEnv -> C.CallbackPollMode -> String -> C.TopicName -> Text.Text -> [BS.ByteString] -> IO ()+visible testEnv mode label topic level expected = bracket acquire releaseConsumer $ \consumer -> do+ C.assign consumer [C.TopicPartition topic (C.PartitionId 0) C.PartitionOffsetBeginning] >>= (@?= Nothing)+ records <- receiveMessages consumer (length expected) >>= either throwIO pure+ map C.crValue records @?= map Just expected+ where+ acquire =+ C.newAssignedConsumer+ (C.brokersList (teBrokers testEnv) <> C.groupId (makeGroupId testEnv (Text.pack ("tx-visible-" <> label))) <> C.noAutoCommit <> C.callbackPollMode mode <> C.extraProps (M.singleton "isolation.level" level))+ >>= either throwIO pure++fencing :: TestEnv -> IO ()+fencing testEnv = withTopic testEnv "tx-fencing" 1 $ \topic _ ->+ withProducer testEnv "fenced" True (teBrokers testEnv) $ \first -> do+ T.initTransactions first (C.Timeout 10000) >>= (@?= Nothing)+ T.beginTransaction first >>= (@?= Nothing)+ produceTo first topic 0 "fenced-output"+ withProducer testEnv "fenced" True (teBrokers testEnv) $ \replacement -> do+ T.initTransactions replacement (C.Timeout 10000) >>= (@?= Nothing)+ withTxFault 0 $ do+ T.commitTransaction first (C.Timeout 10000) >>= checkTx C.RdKafkaRespErrFenced (True, False, False)+ balanced 1+ T.beginTransaction replacement >>= (@?= Nothing)+ produceTo replacement topic 0 "replacement-output"+ T.commitTransaction replacement (C.Timeout 10000) >>= noTxError+ visible testEnv C.CallbackPollModeSync "fencing" topic "read_committed" ["replacement-output"]++abortRecovery :: TestEnv -> IO ()+abortRecovery testEnv = withProducer testEnv "small-admin" False (teBrokers testEnv) $ \admin -> do+ let topic = C.TopicName (prefixedName testEnv "tx-small-records")+ request = Topic.NewTopic topic (Topic.PartitionCount 1) (Topic.ReplicationFactor 1) (M.singleton "max.message.bytes" "1024")+ bracket_+ (Topic.createTopic admin request >>= either throwIO (const (pure ())))+ (void (Topic.deleteTopic admin topic))+ $ withProducer testEnv "abort-recovery" True (teBrokers testEnv)+ $ \producer -> do+ T.initTransactions producer (C.Timeout 10000) >>= (@?= Nothing)+ T.beginTransaction producer >>= (@?= Nothing)+ report <- newEmptyMVar+ let record = P.ProducerRecord topic (P.SpecifiedPartition 0) Nothing (Just (BS.replicate 4096 97)) mempty+ P.produceMessage' producer record (putMVar report) >>= (@?= Right ())+ P.flushProducerTimeout producer (C.Timeout 10000) >>= (@?= Nothing)+ bounded (readMVar report) >>= (@?= P.DeliveryFailure record (C.KafkaResponseError C.RdKafkaRespErrMsgSizeTooLarge))+ withTxFault 0 $ do+ T.commitTransaction producer (C.Timeout 10000) >>= checkTx C.RdKafkaRespErrMsgSizeTooLarge (False, False, True)+ balanced 1+ T.abortTransaction producer (C.Timeout 10000) >>= (@?= Nothing)+ T.beginTransaction producer >>= (@?= Nothing)+ let recovered = P.ProducerRecord topic (P.SpecifiedPartition 0) Nothing (Just "recovered-output") mempty+ recovery <- newEmptyMVar+ P.produceMessage' producer recovered (putMVar recovery) >>= (@?= Right ())+ P.flushProducerTimeout producer (C.Timeout 10000) >>= (@?= Nothing)+ bounded (readMVar recovery) >>= \case+ P.DeliverySuccess actual _ -> actual @?= recovered+ P.DeliveryFailure actual (C.KafkaResponseError C.RdKafkaRespErrPurgeQueue) -> do+ actual @?= recovered+ -- Apache 4.4/native 2.16 can reject this first recovery with a+ -- sequence error. An independent C probe reproduces the exact+ -- purge/abort-required sequence. Honor that native decision once;+ -- no arbitrary delivery error or unbounded retry is accepted.+ withTxFault 0 $ do+ T.commitTransaction producer (C.Timeout 10000) >>= checkTx C.RdKafkaRespErrOutOfOrderSequenceNumber (False, False, True)+ balanced 1+ T.abortTransaction producer (C.Timeout 10000) >>= (@?= Nothing)+ T.beginTransaction producer >>= (@?= Nothing)+ produceTo producer topic 0 "recovered-output"+ putStrLn "[transaction-recovery] observed purge and abort-required sequence error; next transaction delivered"+ other -> assertFailure (show other)+ T.commitTransaction producer (C.Timeout 10000) >>= noTxError+ visible testEnv C.CallbackPollModeSync "abort-recovery" topic "read_committed" ["recovered-output"]
+ test-integration/Kafka/MessageTestSupport.hs view
@@ -0,0 +1,26 @@+module Kafka.MessageTestSupport (withMessageFault, messageStat, awaitMessageBoundary, releaseMessageBoundary) where++import Control.Concurrent (threadDelay)+import Control.Exception (bracket_)+import Foreign.C.Types (CInt (..))+import System.Timeout (timeout)+import Test.Tasty.HUnit (assertFailure)++foreign import ccall unsafe "rdkafka_hs_test_messages_begin" begin :: CInt -> IO ()++foreign import ccall safe "rdkafka_hs_test_messages_end" end :: IO ()++foreign import ccall unsafe "rdkafka_hs_test_messages_release" releaseMessageBoundary :: IO ()++foreign import ccall unsafe "rdkafka_hs_test_messages_stat" stat :: CInt -> IO CInt++withMessageFault :: Int -> IO a -> IO a+withMessageFault mode = bracket_ (begin (fromIntegral mode)) end++messageStat :: Int -> IO Int+messageStat index = fromIntegral <$> stat (fromIntegral index)++awaitMessageBoundary :: IO ()+awaitMessageBoundary = timeout 5000000 loop >>= maybe (assertFailure "message ownership boundary not reached") pure+ where+ loop = messageStat 4 >>= \value -> if value > 0 then pure () else threadDelay 1000 >> loop
+ test-integration/Kafka/MetadataTestSupport.hs view
@@ -0,0 +1,36 @@+module Kafka.MetadataTestSupport (withMetadataFault, metadataStat, awaitMetadataBoundary, releaseMetadataBoundary, metadataLeakControl) where++import Control.Concurrent (threadDelay)+import Control.Exception (bracket_)+import Data.Text qualified as Text+import Foreign.C.String (CString, withCString)+import Foreign.C.Types (CInt (..))+import Kafka.Types (BrokerAddress (..))+import System.Timeout (timeout)+import Test.Tasty.HUnit (assertFailure)++foreign import ccall unsafe "rdkafka_hs_test_metadata_begin" begin :: CInt -> IO ()++foreign import ccall unsafe "rdkafka_hs_test_metadata_end" end :: IO ()++foreign import ccall unsafe "rdkafka_hs_test_metadata_stat" stat :: CInt -> IO CInt++foreign import ccall unsafe "rdkafka_hs_test_metadata_entered" entered :: IO CInt++foreign import ccall unsafe "rdkafka_hs_test_metadata_release" releaseMetadataBoundary :: IO ()++foreign import ccall safe "rdkafka_hs_test_metadata_control" control :: CString -> IO ()++withMetadataFault :: Int -> IO a -> IO a+withMetadataFault value = bracket_ (begin (fromIntegral value)) end++metadataStat :: Int -> IO Int+metadataStat index = fromIntegral <$> stat (fromIntegral index)++awaitMetadataBoundary :: IO ()+awaitMetadataBoundary = timeout 10000000 loop >>= maybe (assertFailure "metadata acquisition boundary was not reached") pure+ where+ loop = entered >>= \n -> if n == 1 then pure () else threadDelay 1000 >> loop++metadataLeakControl :: [BrokerAddress] -> IO ()+metadataLeakControl brokers = withCString (Text.unpack (Text.intercalate "," [address | BrokerAddress address <- brokers])) control
+ test-integration/Kafka/ProducerTestSupport.hs view
@@ -0,0 +1,70 @@+module Kafka.ProducerTestSupport (withProducerTracking, awaitEnqueueBoundary, releaseEnqueueBoundary, nativeProducerProperty, triggerNullDelivery, enqueueWithoutOpaque, ProducerMock, withProducerMock, delayMockProduce, mockReceivedProduce) where++import Control.Concurrent (threadDelay)+import Control.Exception (bracket, bracket_)+import Data.Text qualified as T+import Foreign.C.String (CString, peekCString, withCString)+import Foreign.C.Types (CInt (..))+import Foreign.Ptr (Ptr, nullPtr)+import Kafka.TestEnv (resolveBrokers)+import Kafka.Types (BrokerAddress, TopicName (..))+import System.Timeout (timeout)+import Test.Tasty.HUnit (assertFailure, (@?=))++foreign import ccall unsafe "rdkafka_hs_test_producer_begin" begin :: CInt -> IO ()++foreign import ccall unsafe "rdkafka_hs_test_producer_end" end :: IO ()++foreign import ccall unsafe "rdkafka_hs_test_producer_entered" entered :: IO CInt++foreign import ccall unsafe "rdkafka_hs_test_producer_release" releaseEnqueueBoundary :: IO ()++foreign import ccall unsafe "rdkafka_hs_test_producer_property" property :: CInt -> IO CString++withProducerTracking :: Int -> IO a -> IO a+withProducerTracking mode = bracket_ (begin (fromIntegral mode)) end++awaitEnqueueBoundary :: IO ()+awaitEnqueueBoundary = timeout 5000000 loop >>= maybe (assertFailure "native enqueue boundary was not reached") pure+ where+ loop = entered >>= \n -> if n == 1 then pure () else threadDelay 1000 >> loop++nativeProducerProperty :: Int -> IO (Maybe String)+nativeProducerProperty index =+ property (fromIntegral index) >>= \ptr ->+ if ptr == nullPtr then pure Nothing else Just <$> peekCString ptr++foreign import ccall safe "rdkafka_hs_test_producer_null_delivery" nullDelivery :: IO CInt++foreign import ccall safe "rdkafka_hs_test_producer_without_opaque" withoutOpaque :: CString -> IO CInt++triggerNullDelivery :: IO Int+triggerNullDelivery = fromIntegral <$> nullDelivery++enqueueWithoutOpaque :: TopicName -> IO ()+enqueueWithoutOpaque (TopicName topic) = withCString (T.unpack topic) withoutOpaque >>= (@?= 0)++data ProducerMock++foreign import ccall safe "rdkafka_hs_test_producer_mock_new" newMock :: IO (Ptr ProducerMock)++foreign import ccall safe "rdkafka_hs_test_producer_mock_destroy" destroyMock :: Ptr ProducerMock -> IO ()++foreign import ccall unsafe "rdkafka_hs_test_producer_mock_brokers" mockBrokers :: Ptr ProducerMock -> IO CString++foreign import ccall safe "rdkafka_hs_test_producer_mock_delay" mockDelay :: Ptr ProducerMock -> CInt -> IO CInt++foreign import ccall safe "rdkafka_hs_test_producer_mock_received" received :: Ptr ProducerMock -> IO CInt++withProducerMock :: (Ptr ProducerMock -> [BrokerAddress] -> IO a) -> IO a+withProducerMock action = bracket acquire destroyMock $ \mock -> do+ addresses <- mockBrokers mock >>= peekCString >>= either assertFailure pure . resolveBrokers . Just+ action mock addresses+ where+ acquire = newMock >>= \ptr -> if ptr == nullPtr then assertFailure "native mock cluster creation failed" else pure ptr++delayMockProduce :: Ptr ProducerMock -> Int -> IO ()+delayMockProduce mock milliseconds = mockDelay mock (fromIntegral milliseconds) >>= (@?= 0)++mockReceivedProduce :: Ptr ProducerMock -> IO Int+mockReceivedProduce mock = fromIntegral <$> received mock
+ test-integration/Kafka/SeekTestSupport.hs view
@@ -0,0 +1,26 @@+module Kafka.SeekTestSupport (withSeekFault, seekStat, awaitCommittedBoundary, releaseCommittedBoundary) where++import Control.Concurrent (threadDelay)+import Control.Exception (bracket_)+import Foreign.C.Types (CInt (..))+import System.Timeout (timeout)+import Test.Tasty.HUnit (assertFailure)++foreign import ccall unsafe "rdkafka_hs_test_seek_begin" begin :: CInt -> IO ()++foreign import ccall unsafe "rdkafka_hs_test_seek_end" end :: IO ()++foreign import ccall unsafe "rdkafka_hs_test_seek_release" releaseCommittedBoundary :: IO ()++foreign import ccall unsafe "rdkafka_hs_test_seek_stat" stat :: CInt -> IO CInt++withSeekFault :: Int -> IO a -> IO a+withSeekFault mode = bracket_ (begin (fromIntegral mode)) end++seekStat :: Int -> IO Int+seekStat index = fromIntegral <$> stat (fromIntegral index)++awaitCommittedBoundary :: IO ()+awaitCommittedBoundary = timeout 5000000 loop >>= maybe (assertFailure "committed lookup barrier not reached") pure+ where+ loop = seekStat 0 >>= \n -> if n == 1 then pure () else threadDelay 1000 >> loop
+ test-integration/Kafka/TestEnv.hs view
@@ -0,0 +1,321 @@+-- | The integration suite's environment: which broker to use, the per-run name+-- prefix that isolates one run from another, client properties, and tasty+-- fixtures that create and release clients.+--+-- The suite only ever talks to the project's private Redpanda broker. The+-- broker comes from @RDKAFKA_TEST_BROKER@ (default 'defaultBroker'), and+-- 'resolveBrokers' rejects the machine-global broker on loopback port 9092+-- before any client is created, because the suite creates and deletes topics.+module Kafka.TestEnv+ ( -- * Environment+ TestEnv (..),+ defaultBroker,+ resolveBrokers,+ newTestEnv,+ checkBrokerReachable,++ -- * Prefixed names+ prefixedName,+ testGroupId,+ makeGroupId,+ isTestGroupId,+ isTestTopic,++ -- * Client properties+ consumerProps,+ consumerPropsNoStore,+ producerProps,+ testSubscription,++ -- * Fixtures+ mkProducer,+ mkConsumerWith,+ mkConsumerFor,+ withProducer,+ withConsumer,+ withKafka,+ withTopic,+ produceTo,++ -- * Messages+ receiveMessages,+ receiveTestMessages,+ releaseConsumer,+ releaseProducer,+ testMessages,+ sendMessages,+ sendMessagesWithHeaders,+ )+where++import Control.Concurrent (threadDelay)+import Control.Concurrent.MVar (newEmptyMVar, tryPutMVar, tryReadMVar)+import Control.Exception (bracket, bracketOnError, finally, throwIO)+import Control.Monad (void)+import Data.ByteString qualified as BS+import Data.Char (isDigit)+import Data.Text (Text)+import Data.Text qualified as Text+import GHC.Clock (getMonotonicTimeNSec)+import Kafka.Consumer as C+import Kafka.FixtureSupport (acquirePair, collectExactly, sendAndConfirm)+import Kafka.Metadata (allTopicsMetadata)+import Kafka.Producer as P+import Kafka.Topic (NewTopic (..), PartitionCount (..), ReplicationFactor (..), createTopic, deleteTopic)+import System.IO (hPutStrLn, stderr)+import System.Random qualified as Rnd+import System.Timeout (timeout)+import Test.Tasty (TestTree, withResource)++-- | Everything a test group needs to know about this run.+data TestEnv = TestEnv+ { -- | the private broker's bootstrap addresses+ teBrokers :: [BrokerAddress],+ -- | a random prefix carried by every topic and consumer group of this run+ tePrefix :: Text,+ -- | the run's main topic, @<prefix>-topic@+ teTopic :: TopicName+ }++-- | The private broker's Kafka listener: @redpanda.kafka-port@ in+-- @.seihou/manifest.json@.+defaultBroker :: Text+defaultBroker = "127.0.0.1:39092"++-- | Turn the value of @RDKAFKA_TEST_BROKER@ (a comma-separated list of+-- @host:port@ addresses, or nothing for 'defaultBroker') into broker+-- addresses, refusing the machine-global broker.+--+-- An address on a loopback host whose port is 9092, or that has no port (which+-- librdkafka treats as 9092), is rejected.+resolveBrokers :: Maybe String -> Either String [BrokerAddress]+resolveBrokers raw = do+ let value = maybe defaultBroker (Text.strip . Text.pack) raw+ addrs = filter (not . Text.null) (Text.strip <$> Text.splitOn "," value)+ if null addrs+ then Left "RDKAFKA_TEST_BROKER is empty; unset it to use the private broker at 127.0.0.1:39092."+ else traverse checkAddress addrs+ where+ checkAddress addr+ | isSharedBroker addr =+ Left $+ "RDKAFKA_TEST_BROKER names "+ <> Text.unpack addr+ <> ", the machine-global broker. The integration suite creates and deletes topics,"+ <> " so it only runs against the project's private broker; start it with"+ <> " `just redpanda-up` and unset RDKAFKA_TEST_BROKER (default 127.0.0.1:39092)."+ | otherwise = Right (BrokerAddress addr)++isSharedBroker :: Text -> Bool+isSharedBroker addr =+ let (host, port) = splitHostPort addr+ in isLoopback (Text.toLower host) && maybe True (== 9092) port++-- | Split @host:port@, @[v6]:port@, @host@ or @[v6]@. A bare IPv6 literal+-- without brackets has no port.+splitHostPort :: Text -> (Text, Maybe Int)+splitHostPort addr+ | Just rest <- Text.stripPrefix "[" addr =+ let (host, after) = Text.breakOn "]" rest+ in (host, Text.stripPrefix "]:" after >>= readPort)+ | Text.count ":" addr == 1 =+ let (host, port) = Text.breakOn ":" addr+ in (host, readPort (Text.drop 1 port))+ | otherwise = (addr, Nothing)+ where+ readPort p+ | not (Text.null p) && Text.all isDigit p = Just (read (Text.unpack p))+ | otherwise = Nothing++isLoopback :: Text -> Bool+isLoopback host =+ host `elem` ["localhost", "localhost.localdomain", "::1", "0:0:0:0:0:0:0:1", "0.0.0.0", "::"]+ || "127." `Text.isPrefixOf` host++-- | An environment for one run, with a fresh random ten-letter prefix.+newTestEnv :: [BrokerAddress] -> IO TestEnv+newTestEnv brokers = do+ prefix <- Text.pack . take 10 . Rnd.randomRs ('a', 'z') <$> Rnd.newStdGen+ hPutStrLn stderr ("[fixture] run-prefix=" <> Text.unpack prefix)+ pure+ TestEnv+ { teBrokers = brokers,+ tePrefix = prefix,+ teTopic = TopicName (prefix <> "-topic")+ }++-- | Ask the broker for metadata, giving up after ten seconds.+checkBrokerReachable :: TestEnv -> IO (Either String ())+checkBrokerReachable env = do+ res <- newProducer (P.brokersList (teBrokers env))+ case res of+ Left err -> pure (Left ("could not create a probe client: " <> show err))+ Right prod -> do+ meta <- allTopicsMetadata prod (Timeout 10000) `finally` releaseProducer prod+ pure $ case meta of+ Right _ -> Right ()+ Left err ->+ Left $+ "the Kafka broker at "+ <> Text.unpack (Text.intercalate "," (unBrokerAddress <$> teBrokers env))+ <> " did not answer a metadata request within 10 seconds ("+ <> show err+ <> "). Start the private broker with `just redpanda-up`."++-- | @<prefix>-<suffix>@.+prefixedName :: TestEnv -> Text -> Text+prefixedName env suffix = tePrefix env <> "-" <> suffix++-- | The run's shared consumer group, named after the prefix alone.+testGroupId :: TestEnv -> ConsumerGroupId+testGroupId env = ConsumerGroupId (tePrefix env)++makeGroupId :: TestEnv -> Text -> ConsumerGroupId+makeGroupId env = ConsumerGroupId . prefixedName env++isTestGroupId :: TestEnv -> ConsumerGroupId -> Bool+isTestGroupId env (ConsumerGroupId group) = tePrefix env `Text.isPrefixOf` group++isTestTopic :: TestEnv -> TopicName -> Bool+isTestTopic env (TopicName name) = (tePrefix env <> "-") `Text.isPrefixOf` name++consumerProps :: TestEnv -> ConsumerProperties+consumerProps env =+ C.brokersList (teBrokers env)+ <> groupId (testGroupId env)+ <> C.setCallback (logCallback (\l s1 s2 -> print $ "[Consumer] " <> show l <> ": " <> s1 <> ", " <> s2))+ <> C.setCallback (errorCallback (\e r -> print $ "[Consumer] " <> show e <> ": " <> r))+ <> noAutoCommit++consumerPropsNoStore :: TestEnv -> ConsumerProperties+consumerPropsNoStore env = consumerProps env <> noAutoOffsetStore++producerProps :: TestEnv -> ProducerProperties+producerProps env =+ P.brokersList (teBrokers env)+ <> P.setCallback (logCallback (\l s1 s2 -> print $ "[Producer] " <> show l <> ": " <> s1 <> ", " <> s2))+ <> P.setCallback (errorCallback (\e r -> print $ "[Producer] " <> show e <> ": " <> r))++testSubscription :: TopicName -> Subscription+testSubscription t =+ topics [t]+ <> offsetReset Earliest++mkProducer :: TestEnv -> IO KafkaProducer+mkProducer env =+ newProducer (producerProps env) >>= either (throwIO . userError . ("newProducer: " <>) . show) pure++-- | Subscribe a consumer to the run's topic and return once its first+-- partition assignment has been delivered, or fail after thirty seconds.+--+-- In 'CallbackPollModeSync' librdkafka only serves the rebalance callback from+-- inside a poll, so this keeps polling for events (without blocking, so no+-- record can be fetched and discarded) while it waits. In+-- 'CallbackPollModeAsync' the consumer's background loop serves it, and+-- polling here could discard a record that races the partition-queue redirect.+mkConsumerWith :: TestEnv -> ConsumerProperties -> IO KafkaConsumer+mkConsumerWith env = mkConsumerFor (teTopic env)++-- | Like 'mkConsumerWith', subscribed to the given topic.+mkConsumerFor :: TopicName -> ConsumerProperties -> IO KafkaConsumer+mkConsumerFor topic props = do+ assigned <- newEmptyMVar+ let props' = C.setCallback (rebalanceCallback (\_ evt -> onRebalance assigned evt)) <> props+ driveCallbacks c = case effectiveCallbackPollMode props' of+ CallbackPollModeSync -> pollConsumerEvents c Nothing+ CallbackPollModeAsync -> pure ()+ let acquire =+ newConsumer props' (testSubscription topic)+ >>= either (throwIO . userError . ("newConsumer: " <>) . show) pure+ bracketOnError acquire destroyConsumer $ \consumer -> do+ let awaitAssignment =+ tryReadMVar assigned >>= \case+ Just () -> pure ()+ Nothing -> do+ driveCallbacks consumer+ threadDelay 50000+ awaitAssignment+ timeout 30000000 awaitAssignment >>= \case+ Just () -> pure consumer+ Nothing -> throwIO (userError "consumer was not assigned a partition within 30 seconds")+ where+ onRebalance var = \case+ RebalanceAssign _ -> void (tryPutMVar var ())+ _ -> pure ()++withProducer :: TestEnv -> (IO KafkaProducer -> TestTree) -> TestTree+withProducer env = withResource (mkProducer env) releaseProducer++withConsumer :: TestEnv -> ConsumerProperties -> (IO KafkaConsumer -> TestTree) -> TestTree+withConsumer env props = withResource (mkConsumerWith env props) releaseConsumer++withKafka :: TestEnv -> ConsumerProperties -> (IO (KafkaConsumer, KafkaProducer) -> TestTree) -> TestTree+withKafka env props =+ withResource+ (acquirePair (mkConsumerWith env props) releaseConsumer (mkProducer env))+ (\(consumer, producer) -> releaseProducer producer `finally` releaseConsumer consumer)++-- | Create a topic named @<prefix>-<suffix>@ with the given number of+-- partitions, run the action with it and a producer, then delete the topic.+withTopic :: TestEnv -> Text -> Int -> (TopicName -> KafkaProducer -> IO a) -> IO a+withTopic env suffix partitions action =+ bracket (mkProducer env) releaseProducer $ \producer -> do+ let topic = TopicName (prefixedName env suffix)+ create =+ createTopic producer (NewTopic topic (PartitionCount partitions) (ReplicationFactor 1) mempty)+ >>= either (throwIO . userError . ("createTopic: " <>) . show) (checkTopic topic)+ remove =+ deleteTopic producer topic+ >>= either (throwIO . userError . ("deleteTopic: " <>) . show) (checkTopic topic)+ bracket create (const remove) (const (action topic producer))+ where+ checkTopic expected actual+ | expected == actual = pure ()+ | otherwise = throwIO (userError ("admin response topic mismatch: " <> show (expected, actual)))++releaseConsumer :: KafkaConsumer -> IO ()+releaseConsumer consumer =+ (closeConsumer consumer >>= mapM_ throwIO) `finally` destroyConsumer consumer++-- | Cleanup must not wait forever for an unreachable broker. Purge first;+-- this fixture is cleanup, delivery success is checked by sendMessages.+releaseProducer :: KafkaProducer -> IO ()+releaseProducer producer = do+ purgeProducer producer [PurgeQueue, PurgeInFlight] >>= mapM_ throwIO+ flushProducerTimeout producer (Timeout 5000) >>= mapM_ throwIO++-- | Produce one record and verify the matching successful delivery report.+produceTo :: KafkaProducer -> TopicName -> Int -> BS.ByteString -> IO ()+produceTo producer topic partition value =+ sendMessages [ProducerRecord topic (SpecifiedPartition partition) Nothing (Just value) mempty] producer+ >>= either throwIO pure++receiveMessages :: KafkaConsumer -> Int -> IO (Either KafkaError [ConsumerRecord (Maybe BS.ByteString) (Maybe BS.ByteString)])+receiveMessages kafka count = collectExactly getMonotonicTimeNSec 30000000000 count (pollMessage kafka (Timeout 200))++-- | Validate the inherited scenario's complete payload/key/header identities+-- and contiguous offsets, not just its count. Every send uses testMessages.+receiveTestMessages :: TestEnv -> KafkaConsumer -> Int -> Int -> IO (Either KafkaError [ConsumerRecord (Maybe BS.ByteString) (Maybe BS.ByteString)])+receiveTestMessages env consumer count start = do+ result <- receiveMessages consumer count+ pure $ do+ records <- result+ let expected = take count (cycle (testMessages (teTopic env)))+ actual = [ProducerRecord (crTopic r) UnassignedPartition (crKey r) (crValue r) (crHeaders r) | r <- records]+ if actual == expected+ && map crPartition records == replicate count (PartitionId 0)+ && map crOffset records == map (Offset . fromIntegral) [start .. start + count - 1]+ then Right records+ else Left (KafkaError ("unexpected record identities/offsets: " <> Text.pack (show records)))++testMessages :: TopicName -> [ProducerRecord]+testMessages t =+ [ ProducerRecord t UnassignedPartition Nothing (Just "test from producer") mempty,+ ProducerRecord t UnassignedPartition (Just "key") (Just "test from producer (with key)") mempty+ ]++sendMessages :: [ProducerRecord] -> KafkaProducer -> IO (Either KafkaError ())+sendMessages msgs prod = sendAndConfirm 10000000 (produceMessage' prod) (flushProducerTimeout prod) msgs++sendMessagesWithHeaders :: [ProducerRecord] -> Headers -> KafkaProducer -> IO (Either KafkaError ())+sendMessagesWithHeaders msgs hdrs = sendMessages [msg {prHeaders = hdrs} | msg <- msgs]
+ test-integration/Kafka/TransactionTestSupport.hs view
@@ -0,0 +1,34 @@+module Kafka.TransactionTestSupport (withTxFault, txStat, awaitTxBoundary, releaseTxBoundary, nativeLeakControl, requireNativeFlagDiagnostics) where++import Control.Concurrent (threadDelay)+import Control.Exception (bracket_)+import Data.Int (Int64)+import Foreign.C.Types (CInt (..))+import System.Timeout (timeout)+import Test.Tasty.HUnit (assertBool, assertFailure)++foreign import ccall unsafe "rdkafka_hs_test_tx_begin" begin :: CInt -> IO ()++foreign import ccall unsafe "rdkafka_hs_test_tx_end" end :: IO ()++foreign import ccall unsafe "rdkafka_hs_test_tx_release" releaseTxBoundary :: IO ()++foreign import ccall unsafe "rdkafka_hs_test_tx_stat" stat :: CInt -> IO Int64++foreign import ccall safe "rdkafka_hs_test_tx_leak_control" nativeLeakControl :: IO ()++foreign import ccall unsafe "rdkafka_hs_test_tx_flag_diagnostics_available" flagDiagnosticsAvailable :: IO CInt++requireNativeFlagDiagnostics :: IO ()+requireNativeFlagDiagnostics = flagDiagnosticsAvailable >>= assertBool "Native flag controls require the diagnostic librdkafka build exposing its three private error-flag setters; see docs/testing/coverage.md." . (/= 0)++withTxFault :: Int -> IO a -> IO a+withTxFault value = bracket_ (begin (fromIntegral value)) end++txStat :: Int -> IO Int64+txStat = stat . fromIntegral++awaitTxBoundary :: IO ()+awaitTxBoundary = timeout 5000000 loop >>= maybe (assertFailure "transaction decoder boundary not reached") pure+ where+ loop = txStat 9 >>= \n -> if n == 1 then pure () else threadDelay 1000 >> loop
+ test-integration/Main.hs view
@@ -0,0 +1,120 @@+module Main (main) where++import Control.Concurrent (threadDelay)+import Control.Exception (finally)+import Foreign.C.Types (CInt (..))+import Kafka.Compatibility.KafkaFixture qualified as KafkaFixture+import Kafka.Compatibility.SecurityFixture qualified as SecurityFixture+import Kafka.FixtureSupportTest qualified as FixtureSupportTest+import Kafka.Integration.AssignOnlyTest qualified as AssignOnlyTest+import Kafka.Integration.AttributedErrorTest qualified as AttributedErrorTest+import Kafka.Integration.AuthenticationTest qualified as AuthenticationTest+import Kafka.Integration.BatchTest qualified as BatchTest+import Kafka.Integration.BrokerFailureTest qualified as BrokerFailureTest+import Kafka.Integration.CallbackLifetimeTest qualified as CallbackLifetimeTest+import Kafka.Integration.ConfigurationTest qualified as ConfigurationTest+import Kafka.Integration.ConsumerPropertyTest qualified as ConsumerPropertyTest+import Kafka.Integration.ConsumerTest qualified as ConsumerTest+import Kafka.Integration.DestroyTest qualified as DestroyTest+import Kafka.Integration.HeadersTest qualified as HeadersTest+import Kafka.Integration.LifecycleTest qualified as LifecycleTest+import Kafka.Integration.MetadataContractTest qualified as MetadataContractTest+import Kafka.Integration.ObserverTest qualified as ObserverTest+import Kafka.Integration.PerMessageCommitTest qualified as PerMessageCommitTest+import Kafka.Integration.ProducerPropertyTest qualified as ProducerPropertyTest+import Kafka.Integration.ProducerRegressionTest qualified as ProducerRegressionTest+import Kafka.Integration.PublicConsumerContractTest qualified as PublicConsumerContractTest+import Kafka.Integration.ReadCommittedTest qualified as ReadCommittedTest+import Kafka.Integration.SeekPartitionsTest qualified as SeekPartitionsTest+import Kafka.Integration.StoreOffsetsTest qualified as StoreOffsetsTest+import Kafka.Integration.TopicConfigurationTest qualified as TopicConfigurationTest+import Kafka.Integration.TopicTest qualified as TopicTest+import Kafka.Integration.TransactionErrorTest qualified as TransactionErrorTest+import Kafka.TestEnv (checkBrokerReachable, newTestEnv, resolveBrokers)+import System.Environment (getArgs, lookupEnv, setEnv, withArgs)+import System.Exit (die)+import System.Mem (performGC)+import System.Timeout (timeout)+import Test.Tasty (DependencyType (AllFinish), defaultMain, dependentTestGroup, localOption, mkTimeout, testGroup, withResource)+import Test.Tasty.Runners (NumThreads (..))++main :: IO ()+main = do+ nativeLifetime <- lookupEnv "RDKAFKA_TEST_NATIVE_LIFETIME"+ if nativeLifetime == Just "1" then dispatch `finally` quiesceNativeClients else dispatch++dispatch :: IO ()+dispatch =+ getArgs >>= \case+ ["--producer-callback-probe", mode] -> ProducerRegressionTest.runCallbackProbe mode+ ["--lifetime-callback-probe", kind, label] -> CallbackLifetimeTest.runThrowingProbe kind label+ ["--rebalance-error-probe", protocol, operation, poll, failure] -> PublicConsumerContractTest.runRebalanceProbe protocol operation poll failure+ ["--metadata-cancellation-probe", kind] -> MetadataContractTest.runCancellationProbe kind+ ["--callback-lifetime-native-control"] -> CallbackLifetimeTest.runInvalidAccessControl+ "--native-lifetime" : args -> setEnv "RDKAFKA_TEST_NATIVE_LIFETIME" "1" >> withArgs args main+ "--broker-qualification" : args -> withArgs args brokerMain+ "--authentication-qualification" : args -> withArgs args authenticationMain+ _ -> integrationMain++brokerMain :: IO ()+brokerMain =+ defaultMain . localOption (NumThreads 1) . localOption (mkTimeout 120000000) $+ withResource KafkaFixture.createKafkaFixture KafkaFixture.destroyKafkaFixture BrokerFailureTest.tests++authenticationMain :: IO ()+authenticationMain =+ defaultMain . localOption (NumThreads 1) . localOption (mkTimeout 120000000) $+ withResource SecurityFixture.createSecurityFixture SecurityFixture.destroySecurityFixture AuthenticationTest.tests++integrationMain :: IO ()+integrationMain = do+ brokers <- lookupEnv "RDKAFKA_TEST_BROKER" >>= either die pure . resolveBrokers+ env <- newTestEnv brokers+ checkBrokerReachable env >>= either (die . ("rdkafka-hs-integration: " <>)) pure+ defaultMain+ . localOption (NumThreads 1)+ . localOption (mkTimeout 60000000)+ $ testGroup+ "rdkafka-hs-integration"+ [ FixtureSupportTest.tests,+ ConfigurationTest.tests,+ CallbackLifetimeTest.tests env,+ TransactionErrorTest.tests env,+ LifecycleTest.tests env,+ TopicConfigurationTest.tests env,+ ProducerRegressionTest.tests env,+ ProducerPropertyTest.tests,+ ConsumerPropertyTest.tests env,+ PublicConsumerContractTest.tests env,+ SeekPartitionsTest.tests env,+ -- The groups share the run's topic and consumer group, so later groups+ -- depend on the records and offsets earlier ones leave behind.+ dependentTestGroup+ "broker"+ AllFinish+ [ PerMessageCommitTest.tests env,+ StoreOffsetsTest.tests env,+ ConsumerTest.tests env,+ BatchTest.tests env,+ HeadersTest.tests env,+ AssignOnlyTest.tests env,+ AttributedErrorTest.tests env,+ DestroyTest.tests env,+ ReadCommittedTest.tests env,+ ObserverTest.tests env,+ TopicTest.tests env+ ]+ ]++foreign import ccall safe "rd_kafka_wait_destroyed" waitDestroyed :: CInt -> IO CInt++-- Heap diagnostics must observe completed native destruction, including clients+-- whose managed Haskell wrappers became unreachable at the end of a test.+-- This mode never suppresses findings or treats a shutdown timeout as success.+quiesceNativeClients :: IO ()+quiesceNativeClients = do+ let drain = do+ performGC+ result <- waitDestroyed 100+ if result == 0 then pure () else threadDelay 10000 >> drain+ timeout 10000000 drain >>= maybe (die "native clients did not quiesce before heap diagnostics") pure
+ test-integration/cbits/admin_ownership.c view
@@ -0,0 +1,297 @@+/* Test executable only: observe real public-library allocations and inject+ * failures at native ownership transitions. Production artifacts never link+ * these symbols. RTLD_NEXT dispatches each ordinary call to librdkafka. */+#define _GNU_SOURCE+#include <dlfcn.h>+#include <errno.h>+#include <time.h>+#include <pthread.h>+#include <stdio.h>+#include <stdlib.h>+#include <string.h>+#include <librdkafka/rdkafka.h>++#define REAL(name) \+ __typeof__(&name) real = (__typeof__(&name))dlsym(RTLD_NEXT, #name); \+ if (!real) { fprintf(stderr, "admin ownership: %s: %s\n", #name, dlerror()); abort(); }++enum { NEW_TOPIC, DELETE_TOPIC, QUEUE, OPTIONS, EVENT, KINDS };+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;+static pthread_cond_t resumed = PTHREAD_COND_INITIALIZER;+static struct { void *pointer; int kind; } live[4096];+static int allocations[KINDS], releases[KINDS], peaks[KINDS];+static char *last_key, *last_value;+static int enabled, fail_config, block_config, config_entered, submissions, config_calls, response_mode, timeout_fault, timeout_reads;++/* ELF may preempt calls made inside librdkafka itself. Count application-owned+ * references, not the library's internal copies and reference increments. */+static int application_call(void *caller) {+ Dl_info image;+ if (!dladdr(caller, &image) || !image.dli_fname) abort();+ const char *name = strrchr(image.dli_fname, '/');+ name = name ? name + 1 : image.dli_fname;+ return strncmp(name, "librdkafka.", 11) != 0;+}+#define APPLICATION_CALL application_call(__builtin_extract_return_addr(__builtin_return_address(0)))++static void acquired(void *pointer, int kind) {+ if (!pointer) return;+ pthread_mutex_lock(&lock);+ if (enabled) {+ size_t slot;+ for (slot = 0; slot < 4096 && live[slot].pointer; ++slot) {}+ if (slot == 4096) abort();+ live[slot].pointer = pointer;+ live[slot].kind = kind;+ ++allocations[kind];+ if (allocations[kind] - releases[kind] > peaks[kind]) peaks[kind] = allocations[kind] - releases[kind];+ }+ pthread_mutex_unlock(&lock);+}++static void released(void *pointer, int kind) {+ pthread_mutex_lock(&lock);+ for (size_t slot = 0; slot < 4096; ++slot) {+ if (live[slot].pointer == pointer && live[slot].kind == kind) {+ live[slot].pointer = NULL;+ ++releases[kind];+ break;+ }+ }+ pthread_mutex_unlock(&lock);+}++int rdkafka_hs_test_admin_begin(void) {+ int outstanding = 0;+ pthread_mutex_lock(&lock);+ for (int kind = 0; kind < KINDS; ++kind)+ outstanding += allocations[kind] - releases[kind];+ if (!outstanding) {+ memset(allocations, 0, sizeof allocations);+ memset(releases, 0, sizeof releases);+ memset(peaks, 0, sizeof peaks);+ free(last_key); free(last_value); last_key = last_value = NULL;+ enabled = 1;+ fail_config = block_config = config_entered = submissions = config_calls = response_mode = timeout_fault = timeout_reads = 0;+ }+ pthread_mutex_unlock(&lock);+ return outstanding;+}++void rdkafka_hs_test_admin_end(void) {+ pthread_mutex_lock(&lock);+ enabled = fail_config = block_config = response_mode = timeout_fault = 0;+ free(last_key); free(last_value); last_key = last_value = NULL;+ pthread_cond_broadcast(&resumed);+ pthread_mutex_unlock(&lock);+}++int rdkafka_hs_test_admin_count(int kind, int field) {+ int result;+ pthread_mutex_lock(&lock);+ result = field == 0 ? allocations[kind] : field == 1 ? releases[kind] : field == 3 ? peaks[kind] : allocations[kind] - releases[kind];+ pthread_mutex_unlock(&lock);+ return result;+}++void rdkafka_hs_test_admin_fail_config(int flag) {+ pthread_mutex_lock(&lock); fail_config = flag; pthread_mutex_unlock(&lock);+}+void rdkafka_hs_test_admin_block_config(int flag) {+ pthread_mutex_lock(&lock);+ block_config = flag;+ if (!flag) pthread_cond_broadcast(&resumed);+ pthread_mutex_unlock(&lock);+}+int rdkafka_hs_test_admin_config_entered(void) {+ int result;+ pthread_mutex_lock(&lock); result = config_entered; pthread_mutex_unlock(&lock);+ return result;+}++rd_kafka_NewTopic_t *rd_kafka_NewTopic_new(const char *name, int partitions, int replication, char *error, size_t size) {+ REAL(rd_kafka_NewTopic_new);+ rd_kafka_NewTopic_t *result = real(name, partitions, replication, error, size);+ if (APPLICATION_CALL) acquired(result, NEW_TOPIC);+ return result;+}+void rd_kafka_NewTopic_destroy(rd_kafka_NewTopic_t *topic) {+ REAL(rd_kafka_NewTopic_destroy);+ if (APPLICATION_CALL) released(topic, NEW_TOPIC); real(topic);+}+rd_kafka_resp_err_t rd_kafka_NewTopic_set_config(rd_kafka_NewTopic_t *topic, const char *name, const char *value) {+ REAL(rd_kafka_NewTopic_set_config);+ int reject;+ if (!APPLICATION_CALL) return real(topic, name, value);+ pthread_mutex_lock(&lock);+ if (!enabled) { pthread_mutex_unlock(&lock); return real(topic, name, value); }+ free(last_key); free(last_value);+ last_key = strdup(name ? name : "(null)");+ last_value = strdup(value ? value : "(null)");+ if (!last_key || !last_value) abort();+ config_entered = 1;+ while (block_config) pthread_cond_wait(&resumed, &lock);+ ++config_calls;+ reject = fail_config > 0 && config_calls >= fail_config;+ pthread_mutex_unlock(&lock);+ return reject ? RD_KAFKA_RESP_ERR__INVALID_ARG : real(topic, name, value);+}+rd_kafka_DeleteTopic_t *rd_kafka_DeleteTopic_new(const char *name) {+ REAL(rd_kafka_DeleteTopic_new);+ rd_kafka_DeleteTopic_t *result = real(name);+ if (APPLICATION_CALL) acquired(result, DELETE_TOPIC); return result;+}+void rd_kafka_DeleteTopic_destroy(rd_kafka_DeleteTopic_t *topic) {+ REAL(rd_kafka_DeleteTopic_destroy);+ if (APPLICATION_CALL) released(topic, DELETE_TOPIC); real(topic);+}+/* Share queue interception with callback lifetime fixtures, so each ordinary+ * native call still has exactly one interposer and one real dispatch. */+void rdkafka_hs_callbacks_queue_created(rd_kafka_t *, rd_kafka_queue_t *);+void rdkafka_hs_callbacks_queue_destroying(rd_kafka_queue_t *);++rd_kafka_queue_t *rd_kafka_queue_new(rd_kafka_t *client) {+ REAL(rd_kafka_queue_new);+ rd_kafka_queue_t *result = real(client);+ if (APPLICATION_CALL) {+ acquired(result, QUEUE);+ rdkafka_hs_callbacks_queue_created(client, result);+ } return result;+}+void rd_kafka_queue_destroy(rd_kafka_queue_t *queue) {+ REAL(rd_kafka_queue_destroy);+ if (APPLICATION_CALL) {+ released(queue, QUEUE);+ rdkafka_hs_callbacks_queue_destroying(queue);+ } real(queue);+}+rd_kafka_AdminOptions_t *rd_kafka_AdminOptions_new(rd_kafka_t *client, rd_kafka_admin_op_t operation) {+ REAL(rd_kafka_AdminOptions_new);+ rd_kafka_AdminOptions_t *result = real(client, operation);+ if (APPLICATION_CALL) acquired(result, OPTIONS); return result;+}+void rd_kafka_AdminOptions_destroy(rd_kafka_AdminOptions_t *options) {+ REAL(rd_kafka_AdminOptions_destroy);+ if (APPLICATION_CALL) released(options, OPTIONS); real(options);+}+rd_kafka_event_t *rd_kafka_queue_poll(rd_kafka_queue_t *queue, int timeout) {+ REAL(rd_kafka_queue_poll);+ int application = APPLICATION_CALL;+ int mode = 0;+ pthread_mutex_lock(&lock); if (application) mode = response_mode; pthread_mutex_unlock(&lock);+ if (mode == 5) {+ struct timespec delay = {0, 150000000};+ while (nanosleep(&delay, &delay) && errno == EINTR) {}+ }+ rd_kafka_event_t *result = real(queue, timeout);+ if (application) acquired(result, EVENT);+ if (mode == 4 && result) {+ rd_kafka_event_destroy(result);+ return NULL;+ }+ return result;+}+void rd_kafka_event_destroy(rd_kafka_event_t *event) {+ REAL(rd_kafka_event_destroy);+ if (APPLICATION_CALL) released(event, EVENT); real(event);+}++/* Deliberately retain one real native request to prove the counter sees a+ * leak. The control's caller must release it; it never submits to a broker. */+rd_kafka_NewTopic_t *rdkafka_hs_test_admin_positive_control(void) {+ char error[512];+ return rd_kafka_NewTopic_new("ownership-positive-control", 1, 1, error, sizeof error);+}+void rdkafka_hs_test_admin_release_control(rd_kafka_NewTopic_t *topic) {+ rd_kafka_NewTopic_destroy(topic);+}++int rdkafka_hs_test_admin_submissions(void) {+ int result;+ pthread_mutex_lock(&lock); result = submissions; pthread_mutex_unlock(&lock);+ return result;+}+void rd_kafka_CreateTopics(rd_kafka_t *client, rd_kafka_NewTopic_t **topics, size_t count, const rd_kafka_AdminOptions_t *options, rd_kafka_queue_t *queue) {+ REAL(rd_kafka_CreateTopics);+ pthread_mutex_lock(&lock); if (enabled && APPLICATION_CALL) ++submissions; pthread_mutex_unlock(&lock);+ real(client, topics, count, options, queue);+}++int rdkafka_hs_test_admin_reject_control(rd_kafka_NewTopic_t *topic) {+ return rd_kafka_NewTopic_set_config(topic, "cleanup.policy", "compact");+}++int rdkafka_hs_test_admin_configuration_calls(void) {+ int result;+ pthread_mutex_lock(&lock); result = config_calls; pthread_mutex_unlock(&lock);+ return result;+}+void rdkafka_hs_test_admin_response_mode(int mode) {+ pthread_mutex_lock(&lock); response_mode = mode; pthread_mutex_unlock(&lock);+}+static int current_response_mode(void) {+ int mode;+ pthread_mutex_lock(&lock); mode = response_mode; pthread_mutex_unlock(&lock);+ return mode;+}+const rd_kafka_CreateTopics_result_t *rd_kafka_event_CreateTopics_result(rd_kafka_event_t *event) {+ REAL(rd_kafka_event_CreateTopics_result);+ if (APPLICATION_CALL && current_response_mode() == 1) return NULL;+ return real(event);+}+const rd_kafka_topic_result_t **rd_kafka_CreateTopics_result_topics(const rd_kafka_CreateTopics_result_t *result, size_t *count) {+ REAL(rd_kafka_CreateTopics_result_topics);+ if (APPLICATION_CALL && current_response_mode() == 2) { *count = 0; return NULL; }+ return real(result, count);+}+const char *rd_kafka_topic_result_name(const rd_kafka_topic_result_t *result) {+ REAL(rd_kafka_topic_result_name);+ if (APPLICATION_CALL && current_response_mode() == 3) return "unrelated-result";+ return real(result);+}++const char *rdkafka_hs_test_admin_last_key(void) { return last_key ? last_key : ""; }+const char *rdkafka_hs_test_admin_last_value(void) { return last_value ? last_value : ""; }++const rd_kafka_DeleteTopics_result_t *rd_kafka_event_DeleteTopics_result(rd_kafka_event_t *event) {+ REAL(rd_kafka_event_DeleteTopics_result);+ if (APPLICATION_CALL && current_response_mode() == 1) return NULL;+ return real(event);+}+const rd_kafka_topic_result_t **rd_kafka_DeleteTopics_result_topics(const rd_kafka_DeleteTopics_result_t *result, size_t *count) {+ REAL(rd_kafka_DeleteTopics_result_topics);+ if (APPLICATION_CALL && current_response_mode() == 2) { *count = 0; return NULL; }+ return real(result, count);+}++void rdkafka_hs_test_admin_timeout_fault(int mode) {+ pthread_mutex_lock(&lock); timeout_fault = mode; pthread_mutex_unlock(&lock);+}+int rdkafka_hs_test_admin_timeout_reads(void) {+ int reads;+ pthread_mutex_lock(&lock); reads = timeout_reads; pthread_mutex_unlock(&lock);+ return reads;+}+rd_kafka_conf_res_t rd_kafka_conf_get(const rd_kafka_conf_t *conf, const char *name, char *destination, size_t *size) {+ REAL(rd_kafka_conf_get);+ int mode = 0;+ if (APPLICATION_CALL && strcmp(name, "socket.timeout.ms") == 0) {+ pthread_mutex_lock(&lock);+ if (enabled) { ++timeout_reads; mode = timeout_fault; }+ pthread_mutex_unlock(&lock);+ }+ if (mode == 1) return RD_KAFKA_CONF_UNKNOWN;+ if (mode == 6) {+ if (destination && *size) destination[0] = 0;+ *size = 100;+ return RD_KAFKA_CONF_OK;+ }+ if (mode) {+ const char *value = mode == 2 ? "not-an-integer" : mode == 3 ? "0" : mode == 4 ? "-1" : "2147483648";+ size_t capacity = *size;+ *size = strlen(value) + 1;+ if (destination && capacity) snprintf(destination, capacity, "%s", value);+ return RD_KAFKA_CONF_OK;+ }+ return real(conf, name, destination, size);+}
+ test-integration/cbits/callback_lifetime.c view
@@ -0,0 +1,173 @@+/* Integration executable only: observed constructor/destructor stages. The+ * log barrier is reached by an actual native DESTROY log callback. Every+ * ordinary operation, including shutdown, still reaches librdkafka. */+#define _GNU_SOURCE+#include <dlfcn.h>+#include <pthread.h>+#include <stdio.h>+#include <stdlib.h>+#include <string.h>+#include <librdkafka/rdkafka.h>++typedef void (*log_callback)(const rd_kafka_t *, int, const char *, const char *);+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;+static pthread_cond_t resume = PTHREAD_COND_INITIALIZER;+static int enabled, mode, released, counters[10];+static rd_kafka_t *client;+static rd_kafka_queue_t *message_queue;+static rd_kafka_conf_t *duplicate;+static log_callback user_log;+extern void rdkafka_hs_state_client_created(rd_kafka_type_t, rd_kafka_t *);+extern void rdkafka_hs_producer_client_created(rd_kafka_type_t, rd_kafka_t *);++#define REAL(name) __typeof__(&name) real = (__typeof__(&name))dlsym(RTLD_NEXT, #name); \+ if (!real) { fprintf(stderr, "callback lifetime: %s\n", dlerror()); abort(); }++/* Called with the lock held. Native/Haskell cancellation cannot release this+ * barrier; the controller must observe it and release it explicitly. */+static void boundary(void) {+ counters[0]++;+ while (!released) pthread_cond_wait(&resume, &lock);+}+void rdkafka_hs_test_callbacks_begin(int value) {+ pthread_mutex_lock(&lock);+ enabled = 1; mode = value; released = 0;+ memset(counters, 0, sizeof counters);+ client = NULL; message_queue = NULL; duplicate = NULL; user_log = NULL;+ pthread_mutex_unlock(&lock);+}+void rdkafka_hs_test_callbacks_release(void) {+ pthread_mutex_lock(&lock);+ released = 1;+ pthread_cond_broadcast(&resume);+ pthread_mutex_unlock(&lock);+}+void rdkafka_hs_test_callbacks_end(void) {+ pthread_mutex_lock(&lock);+ enabled = 0; released = 1;+ /* Do not keep dead native addresses reachable for heap diagnostics. */+ client = NULL; message_queue = NULL; duplicate = NULL; user_log = NULL;+ pthread_cond_broadcast(&resume);+ pthread_mutex_unlock(&lock);+}+int rdkafka_hs_test_callbacks_stat(int index) {+ int value;+ pthread_mutex_lock(&lock);+ value = index >= 0 && index < 10 ? counters[index] : -1;+ pthread_mutex_unlock(&lock);+ return value;+}++/* Explicit diagnostic negative control, never called by ordinary tests. An+ * instrumented native library must diagnose the read in conf_get. */+int rdkafka_hs_test_callbacks_invalid_access(void) {+ rd_kafka_conf_t *conf = rd_kafka_conf_new();+ rd_kafka_conf_destroy(conf);+ size_t size = 0;+ return (int)rd_kafka_conf_get(conf, "client.id", NULL, &size);+}++static void forward_log(const rd_kafka_t *rk, int level, const char *facility, const char *message) {+ pthread_mutex_lock(&lock);+ log_callback callback = user_log;+ int shutting_down = enabled && rk == client && counters[2] > counters[3];+ if (enabled) counters[9]++;+ pthread_mutex_unlock(&lock);+ if (callback) callback(rk, level, facility, message);+ pthread_mutex_lock(&lock);+ if (shutting_down && strcmp(facility, "DESTROY") == 0) {+ counters[4]++;+ if (mode == 6 && counters[0] == 0) boundary();+ }+ pthread_mutex_unlock(&lock);+}++void rd_kafka_conf_set_log_cb(rd_kafka_conf_t *conf, log_callback callback) {+ REAL(rd_kafka_conf_set_log_cb);+ pthread_mutex_lock(&lock);+ int tracking = enabled;+ if (tracking) user_log = callback;+ pthread_mutex_unlock(&lock);+ real(conf, tracking ? forward_log : callback);+}++void rd_kafka_conf_set_stats_cb(rd_kafka_conf_t *conf,+ int (*callback)(rd_kafka_t *, char *, size_t, void *)) {+ REAL(rd_kafka_conf_set_stats_cb);+ real(conf, callback);+ pthread_mutex_lock(&lock);+ if (enabled) {+ counters[6]++;+ if (mode == 1) boundary();+ }+ pthread_mutex_unlock(&lock);+}++rd_kafka_conf_t *rd_kafka_conf_dup(const rd_kafka_conf_t *conf) {+ REAL(rd_kafka_conf_dup);+ rd_kafka_conf_t *result = real(conf);+ pthread_mutex_lock(&lock);+ if (enabled) { duplicate = result; counters[7]++; }+ pthread_mutex_unlock(&lock);+ return result;+}+void rd_kafka_conf_destroy(rd_kafka_conf_t *conf) {+ REAL(rd_kafka_conf_destroy);+ pthread_mutex_lock(&lock);+ if (enabled && conf == duplicate) { duplicate = NULL; counters[5]++; }+ pthread_mutex_unlock(&lock);+ real(conf);+}+rd_kafka_t *rd_kafka_new(rd_kafka_type_t type, rd_kafka_conf_t *conf, char *error, size_t capacity) {+ REAL(rd_kafka_new);+ rd_kafka_t *result = real(type, conf, error, capacity);+ rdkafka_hs_state_client_created(type, result);+ rdkafka_hs_producer_client_created(type, result);+ pthread_mutex_lock(&lock);+ if (enabled && result) {+ if (client) abort(); /* Each fixture owns one client. */+ client = result;+ duplicate = NULL; /* Consumed by successful native creation. */+ counters[1]++;+ if (mode == 2) boundary();+ }+ pthread_mutex_unlock(&lock);+ return result;+}+void rdkafka_hs_callbacks_queue_created(rd_kafka_t *rk, rd_kafka_queue_t *queue) {+ pthread_mutex_lock(&lock);+ if (enabled && rk == client && !message_queue) message_queue = queue;+ pthread_mutex_unlock(&lock);+}+void rdkafka_hs_callbacks_queue_destroying(rd_kafka_queue_t *queue) {+ pthread_mutex_lock(&lock);+ if (enabled && queue == message_queue) {+ counters[8]++;+ if (mode == 4) boundary();+ message_queue = NULL;+ }+ pthread_mutex_unlock(&lock);+}+void rd_kafka_destroy_flags(rd_kafka_t *rk, int flags) {+ REAL(rd_kafka_destroy_flags);+ pthread_mutex_lock(&lock);+ int tracking = enabled && rk == client;+ if (tracking) {+ counters[2]++;+ const char *probe = getenv("RDKAFKA_TEST_CALLBACK_SAFETY_PROBE");+ if (probe) {+ fprintf(stderr, "callback safety probe: native destructor entered (%s)\n", probe);+ fflush(stderr);+ }+ if (mode == 3) boundary();+ }+ pthread_mutex_unlock(&lock);+ real(rk, flags);+ pthread_mutex_lock(&lock);+ if (tracking) {+ counters[3]++;+ if (mode == 5) boundary();+ client = NULL;+ }+ pthread_mutex_unlock(&lock);+}
+ test-integration/cbits/consumer_state.c view
@@ -0,0 +1,191 @@+/* Integration executable only. Invoke the installed native callback with an+ * owned native partition list and controlled, actually allocated error objects.+ * Mode zero only observes native commit arguments without changing results.+ * Real cooperative group handoffs remain separate broker scenarios. */+#define _GNU_SOURCE+#include <dlfcn.h>+#include <pthread.h>+#include <stdio.h>+#include <stdlib.h>+#include <string.h>+#include <librdkafka/rdkafka.h>++typedef void (*rebalance_callback)(rd_kafka_t *, rd_kafka_resp_err_t,+ rd_kafka_topic_partition_list_t *, void *);+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;+static int enabled, mode, stats[7];+static rd_kafka_t *client;+static int commit_calls, commit_async;+static rebalance_callback installed;+static rd_kafka_error_t *owned_error;++#define REAL(name) __typeof__(&name) real = (__typeof__(&name))dlsym(RTLD_NEXT, #name); \+ if (!real) { fprintf(stderr, "consumer state: %s\n", dlerror()); abort(); }++void rdkafka_hs_test_state_begin(int value) {+ pthread_mutex_lock(&lock);+ if (owned_error) abort();+ enabled = 1; mode = value; client = NULL; installed = NULL;+ commit_calls = 0; commit_async = -1;+ for (int i = 0; i < 7; ++i) stats[i] = 0;+ pthread_mutex_unlock(&lock);+}+void rdkafka_hs_test_state_end(void) {+ REAL(rd_kafka_error_destroy);+ pthread_mutex_lock(&lock);+ rd_kafka_error_t *retained = owned_error;+ enabled = 0; client = NULL; installed = NULL; owned_error = NULL;+ pthread_mutex_unlock(&lock);+ if (retained) real(retained);+}+int rdkafka_hs_test_state_stat(int index) {+ pthread_mutex_lock(&lock);+ int value = index >= 0 && index < 7 ? stats[index] : -1;+ pthread_mutex_unlock(&lock);+ return value;+}+void rdkafka_hs_state_client_created(rd_kafka_type_t type, rd_kafka_t *created) {+ pthread_mutex_lock(&lock);+ if (enabled && type == RD_KAFKA_CONSUMER && created) client = created;+ pthread_mutex_unlock(&lock);+}+void rdkafka_hs_state_error_destroyed(rd_kafka_error_t *error) {+ pthread_mutex_lock(&lock);+ if (enabled && error && error == owned_error) { stats[1]++; owned_error = NULL; }+ pthread_mutex_unlock(&lock);+}+void rd_kafka_conf_set_rebalance_cb(rd_kafka_conf_t *conf, rebalance_callback callback) {+ REAL(rd_kafka_conf_set_rebalance_cb);+ real(conf, callback);+ pthread_mutex_lock(&lock);+ if (enabled) installed = callback;+ pthread_mutex_unlock(&lock);+}+const char *rd_kafka_rebalance_protocol(rd_kafka_t *rk) {+ REAL(rd_kafka_rebalance_protocol);+ pthread_mutex_lock(&lock);+ int controlled = enabled && rk == client && mode >= 1 && mode <= 6;+ int eager = mode >= 5;+ if (controlled) stats[4]++;+ pthread_mutex_unlock(&lock);+ return controlled ? (eager ? "EAGER" : "COOPERATIVE") : real(rk);+}+static rd_kafka_error_t *failure_locked(int index) {+ if (owned_error) abort();+ stats[index]++;+ owned_error = rd_kafka_error_new(mode == 3 || mode == 4 ? (rd_kafka_resp_err_t)32767 : RD_KAFKA_RESP_ERR__STATE,+ "%s", "controlled rebalance failure");+ stats[0]++;+ return owned_error;+}+rd_kafka_error_t *rd_kafka_incremental_assign(rd_kafka_t *rk, const rd_kafka_topic_partition_list_t *partitions) {+ REAL(rd_kafka_incremental_assign);+ pthread_mutex_lock(&lock);+ if (enabled && rk == client && mode >= 1 && mode <= 6) {+ rd_kafka_error_t *error = failure_locked(2);+ pthread_mutex_unlock(&lock); return error;+ }+ pthread_mutex_unlock(&lock);+ return real(rk, partitions);+}+rd_kafka_error_t *rd_kafka_incremental_unassign(rd_kafka_t *rk, const rd_kafka_topic_partition_list_t *partitions) {+ REAL(rd_kafka_incremental_unassign);+ pthread_mutex_lock(&lock);+ if (enabled && rk == client && mode >= 1 && mode <= 6) {+ rd_kafka_error_t *error = failure_locked(3);+ pthread_mutex_unlock(&lock); return error;+ }+ pthread_mutex_unlock(&lock);+ return real(rk, partitions);+}+rd_kafka_resp_err_t rd_kafka_assign(rd_kafka_t *rk, const rd_kafka_topic_partition_list_t *partitions) {+ REAL(rd_kafka_assign);+ pthread_mutex_lock(&lock);+ int observed = enabled && rk == client && mode >= 5 && mode <= 8;+ int controlled = observed && (mode == 5 || mode == 6 || (mode == 8 && !partitions));+ if (observed) stats[5]++;+ pthread_mutex_unlock(&lock);+ return controlled ? RD_KAFKA_RESP_ERR__STATE : real(rk, partitions);+}+void rdkafka_hs_test_state_trigger(const char *topic) {+ pthread_mutex_lock(&lock);+ rd_kafka_t *target = client; rebalance_callback callback = installed;+ int revoke = mode == 2 || mode == 4 || mode == 6;+ int unexpected = mode == 7 || mode == 8;+ if (!enabled || !target || !callback) abort();+ stats[6]++;+ pthread_mutex_unlock(&lock);+ rd_kafka_topic_partition_list_t *partitions = rd_kafka_topic_partition_list_new(1);+ rd_kafka_topic_partition_list_add(partitions, topic, 0);+ callback(target, unexpected ? RD_KAFKA_RESP_ERR_GROUP_AUTHORIZATION_FAILED : revoke ? RD_KAFKA_RESP_ERR__REVOKE_PARTITIONS : RD_KAFKA_RESP_ERR__ASSIGN_PARTITIONS, partitions, NULL);+ rd_kafka_topic_partition_list_destroy(partitions);+}+void rdkafka_hs_test_state_trigger_cooperative(const char *topic, int revoke) {+ pthread_mutex_lock(&lock);+ rd_kafka_t *target = client; rebalance_callback callback = installed;+ if (!enabled || mode != 9 || !target || !callback) abort();+ pthread_mutex_unlock(&lock);+ /* No protocol or action is replaced: the client must have negotiated+ * COOPERATIVE and the installed bridge calls real incremental APIs. */+ rd_kafka_topic_partition_list_t *partitions = rd_kafka_topic_partition_list_new(1);+ rd_kafka_topic_partition_t *partition = rd_kafka_topic_partition_list_add(partitions, topic, 0);+ if (!revoke) partition->offset = RD_KAFKA_OFFSET_END;+ callback(target, revoke ? RD_KAFKA_RESP_ERR__REVOKE_PARTITIONS : RD_KAFKA_RESP_ERR__ASSIGN_PARTITIONS, partitions, NULL);+ rd_kafka_topic_partition_list_destroy(partitions);+}+void rdkafka_hs_test_state_leak_control(void) {+ pthread_mutex_lock(&lock);+ failure_locked(2);+ pthread_mutex_unlock(&lock);+}++int rdkafka_hs_test_state_commit_count(void) {+ pthread_mutex_lock(&lock); int value = commit_calls; pthread_mutex_unlock(&lock); return value;+}+int rdkafka_hs_test_state_commit_async(void) {+ pthread_mutex_lock(&lock); int value = commit_async; pthread_mutex_unlock(&lock); return value;+}+rd_kafka_resp_err_t rd_kafka_commit(rd_kafka_t *rk, const rd_kafka_topic_partition_list_t *offsets, int async) {+ REAL(rd_kafka_commit);+ pthread_mutex_lock(&lock);+ if (enabled && mode == 0 && rk == client) { commit_calls++; commit_async = async; }+ pthread_mutex_unlock(&lock);+ return real(rk, offsets, async);+}++/* A sync queue handle is a temporary wrapper. Observe its length within the+ * call that borrows it; retain only scalar observations after that call. */+static int queue_tracking, queue_calls, notification_length;+static int queue_application_call(void *caller) {+ Dl_info image;+ if (!dladdr(caller, &image) || !image.dli_fname) abort();+ const char *name = strrchr(image.dli_fname, '/');+ name = name ? name + 1 : image.dli_fname;+ return strncmp(name, "librdkafka.", 11) != 0;+}+void rdkafka_hs_test_queue_begin(void) {+ pthread_mutex_lock(&lock);+ if (queue_tracking) abort();+ queue_tracking = 1; queue_calls = 0; notification_length = -1;+ pthread_mutex_unlock(&lock);+}+void rdkafka_hs_test_queue_end(void) {+ pthread_mutex_lock(&lock);+ queue_tracking = 0; notification_length = -1;+ pthread_mutex_unlock(&lock);+}+void rd_kafka_queue_io_event_enable(rd_kafka_queue_t *queue, int fd, const void *payload, size_t size) {+ REAL(rd_kafka_queue_io_event_enable);+ real(queue, fd, payload, size);+ if (!queue_application_call(__builtin_return_address(0))) return;+ pthread_mutex_lock(&lock);+ if (queue_tracking) { notification_length = (int)rd_kafka_queue_length(queue); queue_calls++; }+ pthread_mutex_unlock(&lock);+}+int rdkafka_hs_test_queue_stat(int index) {+ pthread_mutex_lock(&lock);+ int result = index == 0 ? queue_calls :+ index == 1 && queue_tracking ? notification_length : -1;+ pthread_mutex_unlock(&lock);+ return result;+}
+ test-integration/cbits/diagnostics.c view
@@ -0,0 +1,113 @@+/* Test-only ownership observation. Faults retain genuine native dump arrays+ * until after assertions, then release any deliberately abandoned objects. */+#define _GNU_SOURCE+#include <dlfcn.h>+#include <errno.h>+#include <fcntl.h>+#include <librdkafka/rdkafka.h>+#include <pthread.h>+#include <stdio.h>+#include <stdlib.h>++#define REAL(name) __typeof__(&name) real = (__typeof__(&name))dlsym(RTLD_NEXT, #name); \+ if (!real) { fprintf(stderr, "diagnostics: %s\n", dlerror()); abort(); }+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;+static pthread_cond_t condition = PTHREAD_COND_INITIALIZER;+static int enabled, mode, entered, released, stats[4], last_descriptor;+static const char **arrays[256];+static size_t sizes[256];+static FILE *files[256];++void rdkafka_hs_test_diagnostic_begin(int value) {+ pthread_mutex_lock(&lock);+ enabled = 1; mode = value; entered = released = 0; last_descriptor = -1;+ for (int i = 0; i < 4; ++i) stats[i] = 0;+ for (int i = 0; i < 256; ++i) { arrays[i] = NULL; files[i] = NULL; }+ pthread_mutex_unlock(&lock);+}+int rdkafka_hs_test_diagnostic_stat(int index) {+ pthread_mutex_lock(&lock);+ int result = index >= 0 && index < 4 ? stats[index] : index == 4 ? (last_descriptor >= 0 && fcntl(last_descriptor, F_GETFD) >= 0) : -1;+ pthread_mutex_unlock(&lock); return result;+}+int rdkafka_hs_test_diagnostic_entered(void) {+ pthread_mutex_lock(&lock); int result = entered;+ pthread_mutex_unlock(&lock); return result;+}+void rdkafka_hs_test_diagnostic_release(void) {+ pthread_mutex_lock(&lock); released = 1;+ pthread_cond_broadcast(&condition); pthread_mutex_unlock(&lock);+}+static void acquired(const char **array, size_t size, int kind) {+ pthread_mutex_lock(&lock);+ if (enabled) {+ int i; for (i = 0; i < 256 && arrays[i]; ++i) {}+ if (i == 256) abort();+ arrays[i] = array; sizes[i] = size; stats[0]++;+ if (mode == kind) {+ entered = 1;+ while (!released) pthread_cond_wait(&condition, &lock);+ }+ }+ pthread_mutex_unlock(&lock);+}+const char **rd_kafka_conf_dump(rd_kafka_conf_t *conf, size_t *size) {+ REAL(rd_kafka_conf_dump);+ const char **array = real(conf, size); acquired(array, *size, 1); return array;+}+const char **rd_kafka_topic_conf_dump(rd_kafka_topic_conf_t *conf, size_t *size) {+ REAL(rd_kafka_topic_conf_dump);+ const char **array = real(conf, size); acquired(array, *size, 2); return array;+}+void rd_kafka_conf_dump_free(const char **array, size_t size) {+ REAL(rd_kafka_conf_dump_free);+ pthread_mutex_lock(&lock);+ if (enabled) for (int i = 0; i < 256; ++i) if (array == arrays[i]) {+ arrays[i] = NULL; stats[1]++; break;+ }+ pthread_mutex_unlock(&lock); real(array, size);+}+FILE *fdopen(int fd, const char *mode_string) {+ REAL(fdopen);+ pthread_mutex_lock(&lock);+ int reject = enabled && mode == 3;+ if (enabled) last_descriptor = fd;+ pthread_mutex_unlock(&lock);+ if (reject) { errno = EMFILE; return NULL; }+ FILE *file = real(fd, mode_string);+ pthread_mutex_lock(&lock);+ if (enabled && file) {+ int i; for (i = 0; i < 256 && files[i]; ++i) {}+ if (i == 256) abort(); files[i] = file; stats[2]++;+ }+ pthread_mutex_unlock(&lock); return file;+}+int fclose(FILE *file) {+ REAL(fclose);+ pthread_mutex_lock(&lock);+ if (enabled) for (int i = 0; i < 256; ++i) if (file == files[i]) {+ files[i] = NULL; stats[3]++; break;+ }+ int reject = enabled && mode == 4;+ pthread_mutex_unlock(&lock);+ int result = real(file);+ if (reject) { errno = EIO; return EOF; }+ return result;+}+void rdkafka_hs_test_diagnostic_end(void) {+ __typeof__(&rd_kafka_conf_dump_free) free_array = (__typeof__(&rd_kafka_conf_dump_free))dlsym(RTLD_NEXT, "rd_kafka_conf_dump_free");+ __typeof__(&fclose) close_file = (__typeof__(&fclose))dlsym(RTLD_NEXT, "fclose");+ if (!free_array || !close_file) abort();+ pthread_mutex_lock(&lock); enabled = 0; released = 1;+ pthread_cond_broadcast(&condition); pthread_mutex_unlock(&lock);+ for (int i = 0; i < 256; ++i) {+ if (arrays[i]) { free_array(arrays[i], sizes[i]); arrays[i] = NULL; }+ if (files[i]) { close_file(files[i]); files[i] = NULL; }+ }+}+void rdkafka_hs_test_diagnostic_leak_control(void) {+ rd_kafka_conf_t *conf = rd_kafka_conf_new();+ size_t size;+ rd_kafka_conf_dump(conf, &size);+ rd_kafka_conf_destroy(conf);+}
+ test-integration/cbits/message_ownership.c view
@@ -0,0 +1,215 @@+/* Test executable only: actual polled messages, owned return boundaries and+ * decoder failures. Native calls remain real except declared fault results. */+#define _GNU_SOURCE+#include <dlfcn.h>+#include <errno.h>+#include <pthread.h>+#include <stdio.h>+#include <stdlib.h>+#include <string.h>+#include <time.h>+#include <librdkafka/rdkafka.h>++static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;+static pthread_cond_t resume = PTHREAD_COND_INITIALIZER;+static int enabled, mode, released, count, stats[8];+static rd_kafka_message_t *messages[8];+static int live[8];+static int32_t original_partition[8];+static int64_t original_offset[8];+static rd_kafka_topic_t *original_topic[8];+static rd_kafka_resp_err_t original_error[8];++#define REAL(name) __typeof__(&name) real = (__typeof__(&name))dlsym(RTLD_NEXT, #name); \+ if (!real) { fprintf(stderr, "message ownership: %s\n", dlerror()); abort(); }++static int application_call(void *caller) {+ Dl_info image;+ if (!dladdr(caller, &image) || !image.dli_fname) abort();+ const char *name = strrchr(image.dli_fname, '/');+ name = name ? name + 1 : image.dli_fname;+ return strncmp(name, "librdkafka.", 11) != 0;+}+#define APPLICATION_CALL application_call(__builtin_extract_return_addr(__builtin_return_address(0)))++void rdkafka_hs_test_messages_begin(int value) {+ pthread_mutex_lock(&lock);+ enabled = 1; mode = value; released = count = 0;+ memset(stats, 0, sizeof stats); memset(messages, 0, sizeof messages); memset(live, 0, sizeof live);+ pthread_mutex_unlock(&lock);+}+void rdkafka_hs_test_messages_release(void) {+ pthread_mutex_lock(&lock);+ released = 1; pthread_cond_broadcast(&resume);+ pthread_mutex_unlock(&lock);+}+void rdkafka_hs_test_messages_end(void) {+ REAL(rd_kafka_message_destroy);+ rd_kafka_message_t *retained[8]; int remaining = 0;+ pthread_mutex_lock(&lock);+ for (int i = 0; i < count; ++i) if (live[i]) {+ messages[i]->partition = original_partition[i];+ messages[i]->offset = original_offset[i];+ messages[i]->rkt = original_topic[i];+ messages[i]->err = original_error[i];+ retained[remaining++] = messages[i];+ }+ enabled = 0; released = 1; count = 0;+ memset(messages, 0, sizeof messages); memset(live, 0, sizeof live);+ pthread_cond_broadcast(&resume);+ pthread_mutex_unlock(&lock);+ /* Release the deliberate control, or messages retained by a failing test. */+ for (int i = 0; i < remaining; ++i) real(retained[i]);+}+int rdkafka_hs_test_messages_stat(int index) {+ pthread_mutex_lock(&lock);+ int result = index >= 0 && index < 8 ? stats[index] : -1;+ pthread_mutex_unlock(&lock);+ return result;+}+static void boundary(void) {+ stats[4]++;+ while (!released) pthread_cond_wait(&resume, &lock);+}+static void acquired(rd_kafka_message_t *message) {+ if (count == 8 || !message) abort();+ original_partition[count] = message->partition;+ original_offset[count] = message->offset;+ original_topic[count] = message->rkt;+ original_error[count] = message->err;+ messages[count] = message; live[count++] = 1; stats[1]++;+}+static long long now_ms(void) {+ struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now);+ return (long long)now.tv_sec * 1000 + now.tv_nsec / 1000000;+}++ssize_t rd_kafka_consume_batch_queue(rd_kafka_queue_t *queue, int timeout,+ rd_kafka_message_t **output, size_t capacity) {+ REAL(rd_kafka_consume_batch_queue);+ pthread_mutex_lock(&lock);+ int tracking = enabled && APPLICATION_CALL;+ int current = mode;+ if (tracking) stats[0]++;+ pthread_mutex_unlock(&lock);+ if (!tracking) return real(queue, timeout, output, capacity);+ if (current == 4) { errno = ETIMEDOUT; return -1; }++ /* Ownership faults require three actual records at one native boundary.+ * Collect from the real queue up to that bound; ordinary observation mode+ * 20 preserves the requested timeout/capacity exactly. */+ ssize_t received = 0;+ if (current <= 6) {+ size_t target = capacity < 3 ? capacity : 3;+ long long deadline = now_ms() + 3000;+ while ((size_t)received < target && now_ms() < deadline) {+ int remaining = (int)(deadline - now_ms());+ int wait = timeout < 0 || timeout > remaining ? remaining : timeout;+ ssize_t next = real(queue, wait, output + received, target - (size_t)received);+ if (next < 0) {+ int saved = errno;+ __typeof__(&rd_kafka_message_destroy) destroy = (__typeof__(&rd_kafka_message_destroy))dlsym(RTLD_NEXT, "rd_kafka_message_destroy");+ if (!destroy) abort();+ for (ssize_t i = 0; i < received; ++i) destroy(output[i]);+ errno = saved; return next;+ }+ received += next;+ }+ } else received = real(queue, timeout, output, capacity);+ pthread_mutex_lock(&lock);+ for (ssize_t i = 0; i < received; ++i) acquired(output[i]);+ if (current == 2 && received > 0) boundary();+ pthread_mutex_unlock(&lock);+ return received;+}++static rd_kafka_message_t *single(rd_kafka_message_t *message, int app, int queue) {+ pthread_mutex_lock(&lock);+ int selected = (queue ? mode >= 10 && mode <= 12 : mode >= 13 && mode <= 19) || (mode >= 21 && mode <= 25);+ if (enabled && app && selected && message && message->err == RD_KAFKA_RESP_ERR_NO_ERROR) {+ acquired(message);+ /* Native error frames can lack a partition or offset independently.+ * Retain the real allocation and restore its fields before destruction. */+ if (mode == 21 || mode == 23) message->partition = RD_KAFKA_PARTITION_UA;+ if (mode == 21 || mode == 22) message->offset = RD_KAFKA_OFFSET_INVALID;+ if (mode == 24 || mode == 25) {+ /* Only documented public message fields change; restore them before+ * native destruction, so the original allocation/ownership stays real. */+ message->rkt = NULL; message->partition = RD_KAFKA_PARTITION_UA;+ message->offset = RD_KAFKA_OFFSET_INVALID;+ message->err = mode == 24 ? RD_KAFKA_RESP_ERR__BAD_MSG : RD_KAFKA_RESP_ERR__FATAL;+ }+ if (mode == 10 || mode == 13) boundary();+ }+ pthread_mutex_unlock(&lock);+ return message;+}+rd_kafka_message_t *rd_kafka_consumer_poll(rd_kafka_t *client, int timeout) {+ REAL(rd_kafka_consumer_poll);+ int app = APPLICATION_CALL;+ return single(real(client, timeout), app, 0);+}+rd_kafka_message_t *rd_kafka_consume_queue(rd_kafka_queue_t *queue, int timeout) {+ REAL(rd_kafka_consume_queue);+ int app = APPLICATION_CALL;+ return single(real(queue, timeout), app, 1);+}+rd_kafka_resp_err_t rd_kafka_message_headers(const rd_kafka_message_t *message,+ rd_kafka_headers_t **headers) {+ REAL(rd_kafka_message_headers);+ extern int rdkafka_hs_test_producer_header_failure(void);+ if (rdkafka_hs_test_producer_header_failure()) { *headers = NULL; return RD_KAFKA_RESP_ERR__BAD_MSG; }+ pthread_mutex_lock(&lock);+ int index;+ for (index = 0; index < count && messages[index] != message; ++index) {}+ if (enabled && index < count && live[index]) {+ stats[3]++;+ if (mode >= 21 && mode <= 23) {+ *headers = NULL;+ pthread_mutex_unlock(&lock);+ return RD_KAFKA_RESP_ERR__BAD_MSG;+ }+ if (index == 1 && mode == 3) boundary();+ if (index == 0 && (mode == 11 || mode == 14)) boundary();+ if ((index == 1 && (mode == 1 || mode == 6)) || (index == 0 && (mode == 12 || mode == 15))) {+ *headers = NULL;+ int current = mode;+ pthread_mutex_unlock(&lock);+ return current == 1 ? (rd_kafka_resp_err_t)32767 : RD_KAFKA_RESP_ERR__BAD_MSG;+ }+ }+ pthread_mutex_unlock(&lock);+ return real(message, headers);+}+int64_t rd_kafka_message_timestamp(const rd_kafka_message_t *message, rd_kafka_timestamp_type_t *type) {+ REAL(rd_kafka_message_timestamp);+ pthread_mutex_lock(&lock);+ int selected = 0;+ for (int i = 0; i < count; ++i) if (messages[i] == message && live[i]) selected = 1;+ int current = enabled && selected ? mode : 0;+ pthread_mutex_unlock(&lock);+ if (current == 17) { if (type) *type = RD_KAFKA_TIMESTAMP_NOT_AVAILABLE; return -1; }+ if (current == 18) { if (type) *type = RD_KAFKA_TIMESTAMP_LOG_APPEND_TIME; return 123456789; }+ if (current == 19) { if (type) *type = RD_KAFKA_TIMESTAMP_CREATE_TIME; return 987654321; }+ return real(message, type);+}+void rd_kafka_message_destroy(rd_kafka_message_t *message) {+ REAL(rd_kafka_message_destroy);+ int skip = 0;+ pthread_mutex_lock(&lock);+ if (enabled && APPLICATION_CALL) for (int i = 0; i < count; ++i) if (messages[i] == message) {+ stats[6]++;+ if (!live[i]) { stats[5]++; skip = 1; }+ else if (mode == 5 && i == count - 1) { stats[7]++; skip = 1; }+ else {+ message->partition = original_partition[i];+ message->offset = original_offset[i];+ message->rkt = original_topic[i];+ message->err = original_error[i];+ live[i] = 0; stats[2]++;+ }+ break;+ }+ pthread_mutex_unlock(&lock);+ if (!skip) real(message);+}
+ test-integration/cbits/metadata.c view
@@ -0,0 +1,151 @@+/* Test-only observations of real native metadata/group-list ownership. */+#define _GNU_SOURCE+#include <dlfcn.h>+#include <librdkafka/rdkafka.h>+#include <pthread.h>+#include <stdio.h>+#include <stdlib.h>+#include <string.h>+#define REAL(name) __typeof__(&name) real = (__typeof__(&name))dlsym(RTLD_NEXT, #name); \+ if (!real) { fprintf(stderr, "metadata: %s\n", dlerror()); abort(); }+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;+static pthread_cond_t condition = PTHREAD_COND_INITIALIZER;+static int enabled, mode, entered, released, stats[5];+static const struct rd_kafka_metadata *metadata, *control_metadata;+static const struct rd_kafka_group_list *groups;+static const char *states[] = {"PreparingRebalance", "AwaitingSync", "CompletingRebalance", "Stable", "Dead", "Empty", "FutureState"};+void rdkafka_hs_test_metadata_begin(int value) {+ pthread_mutex_lock(&lock); enabled = 1; mode = value; entered = released = 0;+ metadata = control_metadata = NULL; groups = NULL;+ for (int i = 0; i < 5; ++i) stats[i] = 0;+ pthread_mutex_unlock(&lock);+}+int rdkafka_hs_test_metadata_stat(int index) {+ pthread_mutex_lock(&lock); int result = index >= 0 && index < 5 ? stats[index] : -1;+ pthread_mutex_unlock(&lock); return result;+}+int rdkafka_hs_test_metadata_entered(void) {+ pthread_mutex_lock(&lock); int result = entered;+ pthread_mutex_unlock(&lock); return result;+}+void rdkafka_hs_test_metadata_release(void) {+ pthread_mutex_lock(&lock); released = 1;+ pthread_cond_broadcast(&condition); pthread_mutex_unlock(&lock);+}+static void boundary(int kind) {+ if (mode == kind) {+ entered = 1;+ while (!released) pthread_cond_wait(&condition, &lock);+ }+}+rd_kafka_resp_err_t rd_kafka_metadata(rd_kafka_t *rk, int all_topics, rd_kafka_topic_t *only_topic,+ const struct rd_kafka_metadata **result, int timeout_ms) {+ REAL(rd_kafka_metadata);+ rd_kafka_resp_err_t error = real(rk, all_topics, only_topic, result, timeout_ms);+ pthread_mutex_lock(&lock);+ if (enabled && error == RD_KAFKA_RESP_ERR_NO_ERROR) {+ metadata = *result; stats[0]++;+ if (mode == 3) {+ if (metadata->topic_cnt != 1 || metadata->topics[0].partition_cnt != 2) abort();+ metadata->topics[0].partitions[0].err = RD_KAFKA_RESP_ERR_TOPIC_AUTHORIZATION_FAILED;+ }+ if (mode == 19) {+ struct rd_kafka_metadata *frame = (struct rd_kafka_metadata *)(void *)metadata;+ if (frame->broker_cnt < 1 || frame->topic_cnt != 1 || frame->topics[0].partition_cnt != 1 || strlen(frame->brokers[0].host) < 2) abort();+ /* Select one broker from the real, single-allocation native frame. The+ * decoder control must work on both single-node and distributed brokers;+ * metadata_destroy still owns and frees the complete allocation. */+ frame->broker_cnt = 1;+ frame->brokers[0].id = 7; frame->brokers[0].port = 19092;+ strcpy(frame->brokers[0].host, "λ");+ frame->orig_broker_id = 19;+ frame->topics[0].err = RD_KAFKA_RESP_ERR_UNKNOWN_TOPIC_OR_PART;+ struct rd_kafka_metadata_partition *partition = &frame->topics[0].partitions[0];+ if (partition->replica_cnt != 1 || partition->isr_cnt != 1) abort();+ partition->id = 42; partition->leader = 11;+ partition->err = RD_KAFKA_RESP_ERR_TOPIC_AUTHORIZATION_FAILED;+ partition->replicas[0] = 13; partition->isrs[0] = 17;+ }+ if (mode == 20) {+ /* Metadata is one native allocation; destroy frees the entire frame. */+ ((struct rd_kafka_metadata *)(void *)metadata)->topic_cnt = 0;+ }+ boundary(1);+ }+ pthread_mutex_unlock(&lock); return error;+}+rd_kafka_resp_err_t rd_kafka_offsets_for_times(rd_kafka_t *rk, rd_kafka_topic_partition_list_t *partitions, int timeout_ms) {+ REAL(rd_kafka_offsets_for_times);+ pthread_mutex_lock(&lock);+ int controlled = enabled && mode == 21;+ if (controlled) stats[4]++;+ pthread_mutex_unlock(&lock);+ return controlled ? RD_KAFKA_RESP_ERR__TIMED_OUT : real(rk, partitions, timeout_ms);+}+void rd_kafka_metadata_destroy(const struct rd_kafka_metadata *value) {+ REAL(rd_kafka_metadata_destroy);+ pthread_mutex_lock(&lock);+ if (enabled && value == metadata) { stats[1]++; metadata = NULL; }+ pthread_mutex_unlock(&lock); real(value);+}+rd_kafka_resp_err_t rd_kafka_list_groups(rd_kafka_t *rk, const char *group,+ const struct rd_kafka_group_list **result, int timeout_ms) {+ REAL(rd_kafka_list_groups);+ rd_kafka_resp_err_t error = real(rk, group, result, timeout_ms);+ pthread_mutex_lock(&lock);+ if (enabled && error == RD_KAFKA_RESP_ERR_NO_ERROR) {+ groups = *result; stats[2]++;+ if (mode >= 10 && mode <= 16) {+ if (groups->group_cnt != 1) abort();+ struct rd_kafka_group_info *info = &groups->groups[0];+ free(info->state); info->state = strdup(states[mode - 10]);+ }+ if (mode == 18) {+ if (groups->group_cnt != 1) abort();+ groups->groups[0].err = RD_KAFKA_RESP_ERR_GROUP_AUTHORIZATION_FAILED;+ }+ if (mode == 17) {+ if (groups->group_cnt != 1 || groups->groups[0].member_cnt != 1) abort();+ struct rd_kafka_group_member_info *member = &groups->groups[0].members[0];+ free(member->member_id); member->member_id = strdup("member-field-λ-配置");+ free(member->client_id); member->client_id = strdup("client-field-λ-配置");+ free(member->client_host); member->client_host = strdup("host-field-λ-配置");+ const unsigned char metadata_bytes[] = {0, 1, 0, 255};+ const unsigned char assignment_bytes[] = {255, 0, 2, 0, 3};+ free(member->member_metadata); member->member_metadata = malloc(sizeof(metadata_bytes));+ member->member_metadata_size = sizeof(metadata_bytes);+ memcpy(member->member_metadata, metadata_bytes, sizeof(metadata_bytes));+ free(member->member_assignment); member->member_assignment = malloc(sizeof(assignment_bytes));+ member->member_assignment_size = sizeof(assignment_bytes);+ memcpy(member->member_assignment, assignment_bytes, sizeof(assignment_bytes));+ }+ boundary(2);+ }+ pthread_mutex_unlock(&lock); return error;+}+void rd_kafka_group_list_destroy(const struct rd_kafka_group_list *value) {+ REAL(rd_kafka_group_list_destroy);+ pthread_mutex_lock(&lock);+ if (enabled && value == groups) { stats[3]++; groups = NULL; }+ pthread_mutex_unlock(&lock); real(value);+}+void rdkafka_hs_test_metadata_control(const char *brokers) {+ rd_kafka_conf_t *conf = rd_kafka_conf_new(); char error[512];+ if (rd_kafka_conf_set(conf, "bootstrap.servers", brokers, error, sizeof(error)) != RD_KAFKA_CONF_OK) abort();+ rd_kafka_t *client = rd_kafka_new(RD_KAFKA_PRODUCER, conf, error, sizeof(error));+ if (!client) abort();+ const struct rd_kafka_metadata *value;+ if (rd_kafka_metadata(client, 1, NULL, &value, 5000) != RD_KAFKA_RESP_ERR_NO_ERROR) abort();+ control_metadata = value; rd_kafka_destroy(client);+}+void rdkafka_hs_test_metadata_end(void) {+ REAL(rd_kafka_metadata_destroy);+ pthread_mutex_lock(&lock);+ const struct rd_kafka_metadata *control = control_metadata;+ enabled = 0; released = 1; metadata = control_metadata = NULL; groups = NULL;+ pthread_cond_broadcast(&condition); pthread_mutex_unlock(&lock);+ if (control) real(control);+ /* Ordinary results have Haskell ForeignPtr owners: never compete with their+ * finalizers. A failing pre-owner cancellation probe terminates its process+ * with the demonstrated native allocation still outstanding. */+}
+ test-integration/cbits/partition_lists.c view
@@ -0,0 +1,112 @@+/* Integration executable only: count application-owned lists, including+ * native-returned outputs. Internal native copies remain unobserved. */+#define _GNU_SOURCE+#include <dlfcn.h>+#include <pthread.h>+#include <stdio.h>+#include <stdlib.h>+#include <string.h>+#include <librdkafka/rdkafka.h>+static pthread_mutex_t list_lock = PTHREAD_MUTEX_INITIALIZER;+static pthread_cond_t list_resume = PTHREAD_COND_INITIALIZER;+static int tracking, fault, allocated, destroyed, live, entered, released, queue_attempts;+static rd_kafka_topic_partition_list_t *lists[64], *control;+#define REAL(name) __typeof__(&name) real = (__typeof__(&name))dlsym(RTLD_NEXT, #name); \+ if (!real) { fprintf(stderr,"partition lists: %s\n",dlerror()); abort(); }+static int application(void *caller) {+ Dl_info info;+ if (!dladdr(caller,&info) || !info.dli_fname) abort();+ const char *name=strrchr(info.dli_fname,'/');+ return strncmp(name ? name+1 : info.dli_fname,"librdkafka.",11)!=0;+}+static void observe(rd_kafka_topic_partition_list_t *list, int output) {+ pthread_mutex_lock(&list_lock);+ if (tracking && list) {+ int slot;+ for(slot=0;slot<64 && lists[slot];slot++) if(lists[slot]==list) abort();+ if(slot==64) abort();+ lists[slot]=list; allocated++; live++;+ if ((fault==2 && output==1) || (fault==3 && output==2)) {+ if(list->cnt<1 || strlen(list->elems[0].topic)<2) abort();+ list->elems[0].topic[0]=(char)0xff; list->elems[0].topic[1]=0;+ }+ if ((fault==4 && output==0) || (fault==5 && output==1)) {+ entered=1;+ while(!released) pthread_cond_wait(&list_resume,&list_lock);+ }+ }+ pthread_mutex_unlock(&list_lock);+}+void rdkafka_hs_test_lists_begin(int value) {+ pthread_mutex_lock(&list_lock);+ if(tracking || control) abort();+ memset(lists,0,sizeof(lists)); fault=value; tracking=1;+ allocated=destroyed=live=entered=released=queue_attempts=0;+ pthread_mutex_unlock(&list_lock);+}+void rdkafka_hs_test_lists_release(void) {+ pthread_mutex_lock(&list_lock); released=1;+ pthread_cond_broadcast(&list_resume); pthread_mutex_unlock(&list_lock);+}+void rdkafka_hs_test_lists_end(void) {+ rdkafka_hs_test_lists_release();+ pthread_mutex_lock(&list_lock); tracking=0;+ memset(lists,0,sizeof(lists)); pthread_mutex_unlock(&list_lock);+}+int rdkafka_hs_test_lists_stat(int index) {+ pthread_mutex_lock(&list_lock);+ int value=index==0?allocated:index==1?destroyed:index==2?live:index==4?queue_attempts:entered;+ pthread_mutex_unlock(&list_lock); return value;+}+rd_kafka_topic_partition_list_t *rd_kafka_topic_partition_list_new(int size) {+ REAL(rd_kafka_topic_partition_list_new);+ rd_kafka_topic_partition_list_t *list=real(size);+ if(application(__builtin_return_address(0))) observe(list,0);+ return list;+}+void rd_kafka_topic_partition_list_destroy(rd_kafka_topic_partition_list_t *list) {+ REAL(rd_kafka_topic_partition_list_destroy);+ pthread_mutex_lock(&list_lock);+ if(tracking) for(int i=0;i<64;i++) if(lists[i]==list) {+ lists[i]=NULL; destroyed++; live--; break;+ }+ pthread_mutex_unlock(&list_lock);+ /* Destruction can release native partition references and invoke logging. */+ real(list);+}+void rdkafka_hs_test_lists_assignment(rd_kafka_topic_partition_list_t *list) { observe(list,1); }+rd_kafka_resp_err_t rd_kafka_subscription(rd_kafka_t *client, rd_kafka_topic_partition_list_t **list) {+ REAL(rd_kafka_subscription);+ pthread_mutex_lock(&list_lock);+ int selected = tracking && fault == 7 && application(__builtin_return_address(0));+ pthread_mutex_unlock(&list_lock);+ if (selected) { *list = NULL; return RD_KAFKA_RESP_ERR__UNKNOWN_GROUP; }+ rd_kafka_resp_err_t result=real(client,list);+ if(result==RD_KAFKA_RESP_ERR_NO_ERROR && application(__builtin_return_address(0))) observe(*list,2);+ return result;+}+rd_kafka_queue_t *rd_kafka_queue_get_partition(rd_kafka_t *client, const char *topic, int32_t partition) {+ REAL(rd_kafka_queue_get_partition);+ pthread_mutex_lock(&list_lock);+ int selected = tracking && fault == 8 && application(__builtin_return_address(0));+ if (selected) queue_attempts++;+ pthread_mutex_unlock(&list_lock);+ return selected ? NULL : real(client, topic, partition);+}+rd_kafka_resp_err_t rd_kafka_position(rd_kafka_t *client, rd_kafka_topic_partition_list_t *list) {+ REAL(rd_kafka_position);+ rd_kafka_resp_err_t result = real(client, list);+ pthread_mutex_lock(&list_lock);+ if (tracking && fault == 6 && application(__builtin_return_address(0))) {+ const int64_t offsets[] = {RD_KAFKA_OFFSET_BEGINNING, RD_KAFKA_OFFSET_END,+ RD_KAFKA_OFFSET_STORED, RD_KAFKA_OFFSET_INVALID, -17, 0, INT64_MAX};+ if (list->cnt != 7 || result != RD_KAFKA_RESP_ERR_NO_ERROR) abort();+ for (int i = 0; i < 7; ++i) list->elems[i].offset = offsets[i];+ }+ pthread_mutex_unlock(&list_lock);+ return result;+}+void rdkafka_hs_test_lists_control(int release) {+ if(release) { rd_kafka_topic_partition_list_destroy(control); control=NULL; }+ else { REAL(rd_kafka_topic_partition_list_new); if(control) abort(); control=real(1); observe(control,0); }+}
+ test-integration/cbits/producer_ownership.c view
@@ -0,0 +1,207 @@+/* Test executable only: observe the actual client used by produceva and+ * pause at the enqueue ownership boundary. Ordinary calls go to librdkafka. */+#define _GNU_SOURCE+#include <dlfcn.h>+#include <errno.h>+#include <pthread.h>+#include <stdio.h>+#include <stdlib.h>+#include <string.h>+#include <librdkafka/rdkafka.h>+#include <librdkafka/rdkafka_mock.h>++static pthread_mutex_t producer_lock = PTHREAD_MUTEX_INITIALIZER;+static pthread_cond_t producer_resume = PTHREAD_COND_INITIALIZER;+static int producer_enabled, producer_mode, producer_entered, producer_released;+static const char *property_names[] = {+ "client.id", "message.timeout.ms", "compression.codec", "acks", "queue.buffering.max.messages", "log_level"+};+#define PROPERTY_COUNT (sizeof property_names / sizeof property_names[0])+static char *property_values[PROPERTY_COUNT];+typedef void (*delivery_callback)(rd_kafka_t *, const rd_kafka_message_t *, void *);+static delivery_callback observed_delivery;+static rd_kafka_t *observed_client;++void rdkafka_hs_producer_client_created(rd_kafka_type_t type, rd_kafka_t *client) {+ pthread_mutex_lock(&producer_lock);+ if (producer_enabled && type == RD_KAFKA_PRODUCER) observed_client = client;+ pthread_mutex_unlock(&producer_lock);+}+void rd_kafka_conf_set_dr_msg_cb(rd_kafka_conf_t *conf, delivery_callback callback) {+ __typeof__(&rd_kafka_conf_set_dr_msg_cb) real = (__typeof__(&rd_kafka_conf_set_dr_msg_cb))dlsym(RTLD_NEXT, "rd_kafka_conf_set_dr_msg_cb");+ if (!real) abort();+ real(conf, callback);+ pthread_mutex_lock(&producer_lock);+ if (producer_enabled) observed_delivery = callback;+ pthread_mutex_unlock(&producer_lock);+}+int rdkafka_hs_test_producer_null_delivery(void) {+ pthread_mutex_lock(&producer_lock);+ rd_kafka_t *client = observed_client; delivery_callback callback = observed_delivery;+ int valid = producer_enabled && producer_mode == 6 && client && callback;+ pthread_mutex_unlock(&producer_lock);+ if (!valid) abort();+ /* A callback entry can change thread-local errno; zero exercises the+ * native generic-failure fallback without assuming errno survives RTS entry. */+ errno = 0;+ callback(client, NULL, NULL);+ return RD_KAFKA_RESP_ERR__FAIL;+}+int rdkafka_hs_test_producer_without_opaque(const char *topic) {+ pthread_mutex_lock(&producer_lock);+ rd_kafka_t *client = observed_client;+ int valid = producer_enabled && producer_mode == 6 && client;+ pthread_mutex_unlock(&producer_lock);+ if (!valid) abort();+ /* Real native enqueue intentionally has no Haskell per-message opaque root. */+ return rd_kafka_producev(client, RD_KAFKA_V_TOPIC(topic), RD_KAFKA_V_PARTITION(0),+ RD_KAFKA_V_MSGFLAGS(RD_KAFKA_MSG_F_COPY), RD_KAFKA_V_KEY("native-key", 10),+ RD_KAFKA_V_VALUE("native-without-opaque", 21), RD_KAFKA_V_END);+}+int rdkafka_hs_test_producer_header_failure(void) {+ pthread_mutex_lock(&producer_lock);+ int result = producer_enabled && producer_mode == 7;+ pthread_mutex_unlock(&producer_lock);+ return result;+}++static void clear_properties(void) {+ for (size_t i = 0; i < PROPERTY_COUNT; ++i) {+ free(property_values[i]);+ property_values[i] = NULL;+ }+}+void rdkafka_hs_test_producer_begin(int mode) {+ pthread_mutex_lock(&producer_lock);+ clear_properties();+ producer_enabled = 1;+ producer_mode = mode;+ producer_entered = producer_released = 0;+ observed_delivery = NULL; observed_client = NULL;+ pthread_mutex_unlock(&producer_lock);+}+void rdkafka_hs_test_producer_end(void) {+ pthread_mutex_lock(&producer_lock);+ producer_enabled = 0;+ producer_released = 1;+ observed_delivery = NULL; observed_client = NULL;+ clear_properties();+ pthread_cond_broadcast(&producer_resume);+ pthread_mutex_unlock(&producer_lock);+}+void rdkafka_hs_test_producer_release(void) {+ pthread_mutex_lock(&producer_lock);+ producer_released = 1;+ pthread_cond_broadcast(&producer_resume);+ pthread_mutex_unlock(&producer_lock);+}+int rdkafka_hs_test_producer_entered(void) {+ int result;+ pthread_mutex_lock(&producer_lock);+ result = producer_entered;+ pthread_mutex_unlock(&producer_lock);+ return result;+}+const char *rdkafka_hs_test_producer_property(int index) {+ return index >= 0 && (size_t)index < PROPERTY_COUNT ? property_values[index] : NULL;+}++rd_kafka_error_t *rd_kafka_produceva(rd_kafka_t *client, const rd_kafka_vu_t *values, size_t count) {+ __typeof__(&rd_kafka_produceva) real = (__typeof__(&rd_kafka_produceva))dlsym(RTLD_NEXT, "rd_kafka_produceva");+ if (!real) { fprintf(stderr, "producer ownership: %s\n", dlerror()); abort(); }+ pthread_mutex_lock(&producer_lock);+ int enabled = producer_enabled, mode = producer_mode;+ if (enabled) {+ clear_properties();+ const rd_kafka_conf_t *conf = rd_kafka_conf(client);+ rd_kafka_topic_conf_t *topic_conf = rd_kafka_default_topic_conf_dup(client);+ for (size_t i = 0; i < PROPERTY_COUNT; ++i) {+ size_t length = 0;+ int topic_property = rd_kafka_conf_get(conf, property_names[i], NULL, &length) != RD_KAFKA_CONF_OK;+ /* An untouched client need not have an allocated default-topic config.+ * The native duplication API supplies the same native topic defaults. */+ if (topic_property && rd_kafka_topic_conf_get(topic_conf, property_names[i], NULL, &length) != RD_KAFKA_CONF_OK) continue;+ property_values[i] = calloc(length + 1, 1);+ if (!property_values[i]) abort();+ size_t capacity = length;+ rd_kafka_conf_res_t result = topic_property+ ? rd_kafka_topic_conf_get(topic_conf, property_names[i], property_values[i], &capacity)+ : rd_kafka_conf_get(conf, property_names[i], property_values[i], &capacity);+ if (result != RD_KAFKA_CONF_OK || capacity > length) abort();+ }+ rd_kafka_topic_conf_destroy(topic_conf);+ }+ if (enabled && mode == 1) {+ /* The Haskell StablePtr exists; the native client has not accepted it. */+ producer_entered = 1;+ while (!producer_released) pthread_cond_wait(&producer_resume, &producer_lock);+ pthread_mutex_unlock(&producer_lock);+ return rd_kafka_error_new(RD_KAFKA_RESP_ERR__QUEUE_FULL, "%s", "controlled enqueue rejection");+ }+ if (enabled && mode >= 3 && mode <= 5) {+ /* These calls reject before native transfer. Exercise a decoder failure,+ * a contradictory non-null success-code object, and a valid UNKNOWN code+ * with an unrelated errno. No message or delivery report is created. */+ rd_kafka_resp_err_t code = mode == 3 ? (rd_kafka_resp_err_t)32767+ : mode == 4 ? RD_KAFKA_RESP_ERR_NO_ERROR : RD_KAFKA_RESP_ERR_UNKNOWN;+ producer_entered = 1;+ pthread_mutex_unlock(&producer_lock);+ rd_kafka_error_t *error = rd_kafka_error_new(code, "%s", "controlled native error object");+ if (mode == 5) errno = EINVAL;+ return error;+ }+ pthread_mutex_unlock(&producer_lock);+ rd_kafka_error_t *result = real(client, values, count);+ const char *safety_probe = getenv("RDKAFKA_TEST_PRODUCER_SAFETY_PROBE");+ if (!result && safety_probe)+ fprintf(stderr, "producer safety probe: native enqueue accepted (%s)\n", safety_probe);+ if (enabled && mode == 2 && !result) {+ /* Native ownership has passed, but the caller has not seen the result.+ * Another Haskell thread may now serve the real delivery report. */+ pthread_mutex_lock(&producer_lock);+ producer_entered = 1;+ while (!producer_released) pthread_cond_wait(&producer_resume, &producer_lock);+ pthread_mutex_unlock(&producer_lock);+ }+ return result;+}++/* Native protocol fixture: delay only Produce responses and observe actual+ * received Produce requests before testing in-flight purge behavior. This+ * does not replace the real-broker configuration and record round trips. */+struct producer_mock { rd_kafka_t *anchor; rd_kafka_mock_cluster_t *cluster; };+struct producer_mock *rdkafka_hs_test_producer_mock_new(void) {+ char error[512];+ struct producer_mock *mock = calloc(1, sizeof *mock);+ if (!mock) abort();+ rd_kafka_conf_t *conf = rd_kafka_conf_new();+ rd_kafka_conf_set(conf, "log_level", "0", error, sizeof error);+ mock->anchor = rd_kafka_new(RD_KAFKA_PRODUCER, conf, error, sizeof error);+ if (!mock->anchor) { rd_kafka_conf_destroy(conf); free(mock); return NULL; }+ mock->cluster = rd_kafka_mock_cluster_new(mock->anchor, 1);+ if (!mock->cluster) { rd_kafka_destroy(mock->anchor); free(mock); return NULL; }+ if (rd_kafka_mock_topic_create(mock->cluster, "producer-inflight", 1, 1)) abort();+ rd_kafka_mock_start_request_tracking(mock->cluster);+ return mock;+}+void rdkafka_hs_test_producer_mock_destroy(struct producer_mock *mock) {+ rd_kafka_mock_cluster_destroy(mock->cluster);+ rd_kafka_destroy(mock->anchor);+ free(mock);+}+const char *rdkafka_hs_test_producer_mock_brokers(struct producer_mock *mock) {+ return rd_kafka_mock_cluster_bootstraps(mock->cluster);+}+int rdkafka_hs_test_producer_mock_delay(struct producer_mock *mock, int milliseconds) {+ return rd_kafka_mock_broker_push_request_error_rtts(mock->cluster, 1, 0, 1,+ RD_KAFKA_RESP_ERR_NO_ERROR, milliseconds);+}+int rdkafka_hs_test_producer_mock_received(struct producer_mock *mock) {+ size_t count;+ int result = 0;+ rd_kafka_mock_request_t **requests = rd_kafka_mock_get_requests(mock->cluster, &count);+ for (size_t i = 0; i < count; ++i)+ if (rd_kafka_mock_request_api_key(requests[i]) == 0) ++result;+ rd_kafka_mock_request_destroy_array(requests, count);+ return result;+}
+ test-integration/cbits/seek_faults.c view
@@ -0,0 +1,108 @@+/* Test executable only. Ordinary calls always reach the real native client.+ * Fault modes expose native result boundaries; the committed barrier lets an+ * actual assignment change occur between lookup and seek. */+#define _GNU_SOURCE+#include <dlfcn.h>+#include <pthread.h>+#include <stdio.h>+#include <stdlib.h>+#include <librdkafka/rdkafka.h>++static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;+static pthread_cond_t resume = PTHREAD_COND_INITIALIZER;+static int mode, entered, released, seek_calls, created, destroyed;+static rd_kafka_error_t *owned_error;+extern void rdkafka_hs_tx_error_destroyed(rd_kafka_error_t *error);+extern void rdkafka_hs_state_error_destroyed(rd_kafka_error_t *error);+extern void rdkafka_hs_test_lists_assignment(rd_kafka_topic_partition_list_t *list);++#define REAL(name) __typeof__(&name) real = (__typeof__(&name))dlsym(RTLD_NEXT, #name); \+ if (!real) { fprintf(stderr, "seek seam: %s\n", dlerror()); abort(); }++void rdkafka_hs_test_seek_begin(int value) {+ pthread_mutex_lock(&lock);+ if (owned_error) abort();+ mode = value; entered = released = seek_calls = created = destroyed = 0;+ pthread_mutex_unlock(&lock);+}+void rdkafka_hs_test_seek_release(void) {+ pthread_mutex_lock(&lock);+ released = 1;+ pthread_cond_broadcast(&resume);+ pthread_mutex_unlock(&lock);+}+void rdkafka_hs_test_seek_end(void) {+ pthread_mutex_lock(&lock);+ mode = 0; released = 1;+ pthread_cond_broadcast(&resume);+ pthread_mutex_unlock(&lock);+}+int rdkafka_hs_test_seek_stat(int which) {+ int value;+ pthread_mutex_lock(&lock);+ value = which == 0 ? entered : which == 1 ? seek_calls : which == 2 ? created : destroyed;+ pthread_mutex_unlock(&lock);+ return value;+}++rd_kafka_resp_err_t rd_kafka_committed(rd_kafka_t *client, rd_kafka_topic_partition_list_t *parts, int timeout) {+ REAL(rd_kafka_committed);+ pthread_mutex_lock(&lock);+ int current = mode;+ pthread_mutex_unlock(&lock);+ if (current == 11) return RD_KAFKA_RESP_ERR__TIMED_OUT;+ rd_kafka_resp_err_t result = real(client, parts, timeout);+ if (current == 10) {+ pthread_mutex_lock(&lock);+ entered = 1;+ while (!released) pthread_cond_wait(&resume, &lock);+ pthread_mutex_unlock(&lock);+ }+ return result;+}++rd_kafka_resp_err_t rd_kafka_assignment(rd_kafka_t *client, rd_kafka_topic_partition_list_t **parts) {+ REAL(rd_kafka_assignment);+ pthread_mutex_lock(&lock);+ int current = mode;+ pthread_mutex_unlock(&lock);+ if (current == 12) { *parts = NULL; return RD_KAFKA_RESP_ERR__STATE; }+ rd_kafka_resp_err_t result = real(client, parts);+ if (result == RD_KAFKA_RESP_ERR_NO_ERROR) rdkafka_hs_test_lists_assignment(*parts);+ return result;+}++rd_kafka_error_t *rd_kafka_seek_partitions(rd_kafka_t *client, rd_kafka_topic_partition_list_t *parts, int timeout) {+ REAL(rd_kafka_seek_partitions);+ pthread_mutex_lock(&lock);+ int current = mode;+ if (current) seek_calls++;+ if (current >= 3 && current <= 7) {+ for (int i = 0; i < parts->cnt; ++i) {+ parts->elems[i].err = current == 5+ ? (parts->elems[i].partition == 42 ? RD_KAFKA_RESP_ERR__INVALID_ARG : RD_KAFKA_RESP_ERR__UNKNOWN_PARTITION)+ : (i == 0 || current == 6 ? RD_KAFKA_RESP_ERR__IN_PROGRESS : RD_KAFKA_RESP_ERR__UNKNOWN_PARTITION);+ }+ rd_kafka_error_t *result = NULL;+ if (current == 3 || current == 7) {+ result = rd_kafka_error_new(current == 3 ? RD_KAFKA_RESP_ERR__TIMED_OUT : (rd_kafka_resp_err_t)32767,+ "%s", "controlled seek top-level failure");+ owned_error = result;+ created++;+ }+ pthread_mutex_unlock(&lock);+ return result;+ }+ pthread_mutex_unlock(&lock);+ return real(client, parts, timeout);+}++void rd_kafka_error_destroy(rd_kafka_error_t *error) {+ REAL(rd_kafka_error_destroy);+ rdkafka_hs_tx_error_destroyed(error);+ rdkafka_hs_state_error_destroyed(error);+ pthread_mutex_lock(&lock);+ if (error && error == owned_error) { destroyed++; owned_error = NULL; }+ pthread_mutex_unlock(&lock);+ real(error);+}
+ test-integration/cbits/transaction_ownership.c view
@@ -0,0 +1,186 @@+/* Integration executable only. Count returned native transaction errors, not+ * background allocations. Ordinary calls reach the native library. */+#define _GNU_SOURCE+#include <dlfcn.h>+#include <pthread.h>+#include <stdint.h>+#include <stdio.h>+#include <stdlib.h>+#include <librdkafka/rdkafka.h>++static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;+static pthread_cond_t resume = PTHREAD_COND_INITIALIZER;+static int enabled, mode, released;+static int64_t counts[13];+static struct { rd_kafka_error_t *pointer; int live; } errors[4096];+static rd_kafka_t *last_client;++#define REAL(name) __typeof__(&name) real = (__typeof__(&name))dlsym(RTLD_NEXT, #name); \+ if (!real) { fprintf(stderr, "transaction seam: %s\n", dlerror()); abort(); }++void rdkafka_hs_test_tx_begin(int value) {+ pthread_mutex_lock(&lock);+ enabled = 1; mode = value; released = 0; last_client = NULL;+ for (int i = 0; i < 13; ++i) counts[i] = 0;+ for (int i = 0; i < 4096; ++i) { errors[i].pointer = NULL; errors[i].live = 0; }+ pthread_mutex_unlock(&lock);+}+void rdkafka_hs_test_tx_release(void) {+ pthread_mutex_lock(&lock);+ released = 1; pthread_cond_broadcast(&resume);+ pthread_mutex_unlock(&lock);+}+void rdkafka_hs_test_tx_end(void) {+ REAL(rd_kafka_error_destroy);+ pthread_mutex_lock(&lock);+ enabled = 0; released = 1; last_client = NULL;+ /* Clean up the deliberately leaking control, or a failed assertion. */+ for (int i = 0; i < 4096; ++i) {+ if (errors[i].live) real(errors[i].pointer);+ errors[i].pointer = NULL; errors[i].live = 0;+ }+ pthread_cond_broadcast(&resume);+ pthread_mutex_unlock(&lock);+}+int64_t rdkafka_hs_test_tx_stat(int index) {+ pthread_mutex_lock(&lock);+ int64_t result = index >= 0 && index < 13 ? counts[index] : -1;+ pthread_mutex_unlock(&lock);+ return result;+}+static rd_kafka_error_t *track(rd_kafka_t *client, rd_kafka_error_t *error) {+ pthread_mutex_lock(&lock);+ if (enabled) {+ last_client = client; counts[10]++;+ if (error) {+ int i;+ for (i = 0; i < 4096 && errors[i].live; ++i) {}+ if (i == 4096) abort();+ errors[i].pointer = error; errors[i].live = 1; counts[0]++;+ }+ }+ pthread_mutex_unlock(&lock);+ return error;+}+/* Called by the one shared error-destroy interposer in seek_faults.c. */+void rdkafka_hs_tx_error_destroyed(rd_kafka_error_t *error) {+ pthread_mutex_lock(&lock);+ if (enabled && error) for (int i = 0; i < 4096; ++i) {+ if (errors[i].pointer == error && errors[i].live) {+ errors[i].live = 0; counts[1]++; break;+ }+ }+ pthread_mutex_unlock(&lock);+}+static void reading(const rd_kafka_error_t *error, int index) {+ pthread_mutex_lock(&lock);+ int known = 0, live = 0;+ if (enabled && error) for (int i = 0; i < 4096; ++i) {+ if (errors[i].pointer == error) { known = 1; live |= errors[i].live; }+ }+ if (known) {+ counts[index]++;+ if (!live) counts[8]++;+ if (mode == 18 + index && counts[9] == 0) {+ counts[9]++;+ while (!released) pthread_cond_wait(&resume, &lock);+ }+ }+ pthread_mutex_unlock(&lock);+}+static int current_mode(void) {+ pthread_mutex_lock(&lock);+ int value = enabled ? mode : 0;+ pthread_mutex_unlock(&lock);+ return value;+}+static const char *flag_setter_names[] = {"rd_kafka_error_set_fatal", "rd_kafka_error_set_retriable", "rd_kafka_error_set_txn_requires_abort"};+int rdkafka_hs_test_tx_flag_diagnostics_available(void) {+ for (int bit = 0; bit < 3; ++bit) if (!dlsym(RTLD_NEXT, flag_setter_names[bit])) return 0;+ return 1;+}+static rd_kafka_error_t *fixture(int value) {+ rd_kafka_error_t *error = rd_kafka_error_new(value == 200 ? (rd_kafka_resp_err_t)32767 : RD_KAFKA_RESP_ERR__STATE,+ "%s", "native transaction fixture");+ /* These actual native setters are private diagnostic symbols. No opaque+ * structure layout is copied. Ordinary/compatibility paths do not use them. */+ for (int bit = 0; bit < 3; ++bit) if (value >= 100 && value < 108 && ((value - 100) & (1 << bit))) {+ void (*set)(rd_kafka_error_t *) = (void (*)(rd_kafka_error_t *))dlsym(RTLD_NEXT, flag_setter_names[bit]);+ if (!set) { fprintf(stderr, "transaction native fixture: %s\n", dlerror()); abort(); }+ set(error);+ }+ return error;+}+static int overridden(int value) { return (value >= 100 && value < 108) || value == 200 || value == 201; }++rd_kafka_error_t *rd_kafka_init_transactions(rd_kafka_t *client, int timeout) {+ REAL(rd_kafka_init_transactions); int value = current_mode();+ return track(client, overridden(value) ? (value == 201 ? NULL : fixture(value)) : real(client, timeout));+}+rd_kafka_error_t *rd_kafka_begin_transaction(rd_kafka_t *client) {+ REAL(rd_kafka_begin_transaction); int value = current_mode();+ return track(client, overridden(value) ? (value == 201 ? NULL : fixture(value)) : real(client));+}+rd_kafka_error_t *rd_kafka_abort_transaction(rd_kafka_t *client, int timeout) {+ REAL(rd_kafka_abort_transaction); int value = current_mode();+ return track(client, overridden(value) ? (value == 201 ? NULL : fixture(value)) : real(client, timeout));+}+rd_kafka_error_t *rd_kafka_commit_transaction(rd_kafka_t *client, int timeout) {+ REAL(rd_kafka_commit_transaction); int value = current_mode();+ return track(client, overridden(value) ? (value == 201 ? NULL : fixture(value)) : real(client, timeout));+}+rd_kafka_error_t *rd_kafka_send_offsets_to_transaction(rd_kafka_t *client,+ const rd_kafka_topic_partition_list_t *offsets,+ const rd_kafka_consumer_group_metadata_t *metadata, int timeout) {+ REAL(rd_kafka_send_offsets_to_transaction); int value = current_mode();+ pthread_mutex_lock(&lock);+ if (enabled && offsets && offsets->cnt == 1) counts[12] = offsets->elems[0].offset;+ pthread_mutex_unlock(&lock);+ return track(client, overridden(value) ? (value == 201 ? NULL : fixture(value)) : real(client, offsets, metadata, timeout));+}+rd_kafka_error_t *rd_kafka_sasl_set_credentials(rd_kafka_t *client,+ const char *username, const char *password) {+ REAL(rd_kafka_sasl_set_credentials); int value = current_mode();+ /* The public Haskell arguments are non-NULL. Ask the real native function+ * for its actual invalid-argument object to exercise the owned error path. */+ rd_kafka_error_t *error = track(client, value == 300 || value == 301 || value == 20 ? real(client, NULL, NULL) : real(client, username, password));+ if (value == 301) {+ pthread_mutex_lock(&lock); counts[9]++;+ while (!released) pthread_cond_wait(&resume, &lock);+ pthread_mutex_unlock(&lock);+ }+ return error;+}+rd_kafka_resp_err_t rd_kafka_error_code(const rd_kafka_error_t *error) {+ REAL(rd_kafka_error_code); reading(error, 2); return real(error);+}+int rd_kafka_error_is_fatal(const rd_kafka_error_t *error) {+ REAL(rd_kafka_error_is_fatal); reading(error, 3); return real(error);+}+int rd_kafka_error_is_retriable(const rd_kafka_error_t *error) {+ REAL(rd_kafka_error_is_retriable); reading(error, 4); return real(error);+}+int rd_kafka_error_txn_requires_abort(const rd_kafka_error_t *error) {+ REAL(rd_kafka_error_txn_requires_abort); reading(error, 5); return real(error);+}+rd_kafka_consumer_group_metadata_t *rd_kafka_consumer_group_metadata(rd_kafka_t *client) {+ REAL(rd_kafka_consumer_group_metadata);+ rd_kafka_consumer_group_metadata_t *result = real(client);+ pthread_mutex_lock(&lock); if (enabled && result) counts[6]++; pthread_mutex_unlock(&lock);+ return result;+}+void rd_kafka_consumer_group_metadata_destroy(rd_kafka_consumer_group_metadata_t *metadata) {+ REAL(rd_kafka_consumer_group_metadata_destroy);+ pthread_mutex_lock(&lock); if (enabled && metadata) counts[7]++; pthread_mutex_unlock(&lock);+ real(metadata);+}++/* Reproduce the inherited decode-without-destroy sequence on the same live,+ * nontransactional producer. The enclosing fixture later releases all three. */+void rdkafka_hs_test_tx_leak_control(void) {+ pthread_mutex_lock(&lock); rd_kafka_t *client = last_client; pthread_mutex_unlock(&lock);+ if (!client) abort();+ { REAL(rd_kafka_init_transactions); rd_kafka_error_code(track(client, real(client, 0))); }+ { REAL(rd_kafka_begin_transaction); rd_kafka_error_code(track(client, real(client))); }+ { REAL(rd_kafka_abort_transaction); rd_kafka_error_code(track(client, real(client, 0))); }+}
+ test-support/Kafka/PropertySupport.hs view
@@ -0,0 +1,22 @@+module Kafka.PropertySupport (generatedGroup, boundedList, smallText, shrinkText) where++import Data.Text (Text)+import Data.Text qualified as Text+import Test.Tasty (TestTree, localOption, testGroup)+import Test.Tasty.QuickCheck qualified as QC++-- Keep the adapter's case-count and replay options while printing replay+-- tokens for every generated suite, including successful runs.+generatedGroup :: String -> [TestTree] -> TestTree+generatedGroup name = localOption (QC.QuickCheckShowReplay True) . testGroup name++boundedList :: Int -> QC.Gen a -> QC.Gen [a]+boundedList limit element = QC.sized $ \size -> do+ count <- QC.choose (0, min limit size)+ QC.vectorOf count element++smallText :: QC.Gen Text+smallText = QC.elements ["", "shared", "other", "0", "1", "gzip", "λ", "a\0b"]++shrinkText :: Text -> [Text]+shrinkText = map Text.pack . QC.shrink . Text.unpack
+ test/Kafka/Consumer/ConsumerPropertiesSpec.hs view
@@ -0,0 +1,27 @@+module Kafka.Consumer.ConsumerPropertiesSpec+ ( tests,+ )+where++import Test.Tasty (TestTree, testGroup)+import Test.Tasty.HUnit (testCase, (@?=))+import "rdkafka-hs" Kafka.Consumer.ConsumerProperties+import "rdkafka-hs" Kafka.Consumer.Types (ConsumerGroupId (..))++tests :: TestTree+tests =+ testGroup+ "Kafka.Consumer.ConsumerProperties"+ [ testCase "the poll mode defaults to async" $+ effectiveCallbackPollMode (groupId (ConsumerGroupId "g")) @?= CallbackPollModeAsync,+ testCase "properties composed after the poll mode keep it" $+ effectiveCallbackPollMode+ (callbackPollMode CallbackPollModeSync <> groupId (ConsumerGroupId "g") <> noAutoCommit)+ @?= CallbackPollModeSync,+ testCase "properties composed before the poll mode keep it" $+ effectiveCallbackPollMode (groupId (ConsumerGroupId "g") <> callbackPollMode CallbackPollModeSync)+ @?= CallbackPollModeSync,+ testCase "a later poll mode overrides an earlier one" $+ effectiveCallbackPollMode (callbackPollMode CallbackPollModeSync <> callbackPollMode CallbackPollModeAsync)+ @?= CallbackPollModeAsync+ ]
+ test/Kafka/Consumer/ConsumerRecordMapSpec.hs view
@@ -0,0 +1,42 @@+-- These tests cover the deprecated crMapKey, crMapValue and crMapKV.+{-# OPTIONS_GHC -Wno-deprecations #-}++module Kafka.Consumer.ConsumerRecordMapSpec+ ( tests,+ )+where++import Data.Bitraversable+import Data.Text+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.HUnit (testCase, (@?=))+import "rdkafka-hs" Kafka.Consumer.Types+import "rdkafka-hs" Kafka.Types++testKey, testValue :: Text+testKey = "some-key"+testValue = "some-value"++testRecord :: ConsumerRecord (Maybe Text) (Maybe Text)+testRecord =+ ConsumerRecord+ { crTopic = "some-topic",+ crPartition = PartitionId 0,+ crOffset = Offset 5,+ crTimestamp = NoTimestamp,+ crHeaders = mempty,+ crKey = Just testKey,+ crValue = Just testValue+ }++tests :: TestTree+tests =+ testGroup+ "Kafka.Consumer.ConsumerRecordMapSpec"+ [ testCase "should extract key" $+ bitraverse id pure testRecord @?= Just (crMapKey (const testKey) testRecord),+ testCase "should extract value" $+ sequence testRecord @?= Just (crMapValue (const testValue) testRecord),+ testCase "should extract both key and value" $+ bisequence testRecord @?= Just (crMapKV (const testKey) (const testValue) testRecord)+ ]
+ test/Kafka/Consumer/ConsumerRecordTraverseSpec.hs view
@@ -0,0 +1,58 @@+module Kafka.Consumer.ConsumerRecordTraverseSpec+ ( tests,+ )+where++import Data.Bifunctor+import Data.Bitraversable+import Data.Text+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.HUnit (testCase, (@?=))+import "rdkafka-hs" Kafka.Consumer.Types+import "rdkafka-hs" Kafka.Types++testKey, testValue :: Text+testKey = "some-key"+testValue = "some-value"++testRecord :: ConsumerRecord Text Text+testRecord =+ ConsumerRecord+ { crTopic = "some-topic",+ crPartition = PartitionId 0,+ crOffset = Offset 5,+ crTimestamp = NoTimestamp,+ crHeaders = mempty,+ crKey = testKey,+ crValue = testValue+ }++liftValue :: a -> Maybe a+liftValue = Just++liftNothing :: a -> Maybe a+liftNothing _ = Nothing++tests :: TestTree+tests =+ testGroup+ "Kafka.Consumer.ConsumerRecordTraverseSpec"+ [ testCase "should sequence" $ do+ sequence (liftValue <$> testRecord) @?= Just testRecord+ sequenceA (liftValue <$> testRecord) @?= Just testRecord+ sequence (liftNothing <$> testRecord) @?= Nothing,+ testCase "should traverse" $ do+ traverse liftValue testRecord @?= Just testRecord+ traverse liftNothing testRecord @?= Nothing,+ testCase "should bisequence" $ do+ bisequence (bimap liftValue liftValue testRecord) @?= Just testRecord+ bisequence (bimap liftNothing liftValue testRecord) @?= Nothing+ bisequence (bimap liftValue liftNothing testRecord) @?= Nothing+ bisequenceA (bimap liftValue liftValue testRecord) @?= Just testRecord+ bisequenceA (bimap liftNothing liftValue testRecord) @?= Nothing+ bisequenceA (bimap liftValue liftNothing testRecord) @?= Nothing,+ testCase "should bitraverse" $ do+ bitraverse liftValue liftValue testRecord @?= Just testRecord+ bitraverse liftNothing liftValue testRecord @?= Nothing+ bitraverse liftValue liftNothing testRecord @?= Nothing+ ]
+ test/Kafka/Internal/CallbackOwnerSpec.hs view
@@ -0,0 +1,145 @@+{-# LANGUAGE ForeignFunctionInterface #-}++module Kafka.Internal.CallbackOwnerSpec (tests) where++import Control.Concurrent (forkFinally, forkIOWithUnmask, threadDelay)+import Control.Concurrent.MVar (newEmptyMVar, putMVar, readMVar, tryReadMVar)+import Control.Exception (MaskingState (MaskedInterruptible), SomeException, finally, getMaskingState, throwIO, try)+import Control.Monad (void)+import Data.Either (isLeft)+import Data.IORef (IORef, atomicModifyIORef', modifyIORef', newIORef, readIORef)+import Data.Map.Strict qualified as M+import Foreign.Ptr (FunPtr, castFunPtr, freeHaskellFunPtr)+import GHC.Conc (BlockReason (BlockedOnMVar), ThreadStatus (ThreadBlocked), threadStatus)+import Kafka.Internal.CallbackOwner+import System.Timeout (timeout)+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.HUnit (assertBool, assertFailure, testCase, (@?=))++foreign import ccall "wrapper" wrap :: IO () -> IO (FunPtr (IO ()))++foreign import ccall "dynamic" invoke :: FunPtr (IO ()) -> IO ()++tests :: TestTree+tests =+ testGroup+ "Callback owner"+ [ testCase "bridge allocation executes masked before ownership is recorded" $ do+ freed <- newIORef M.empty+ owner <- newCallbackOwnerWith (countFree freed)+ observed <- newEmptyMVar+ done <- newEmptyMVar+ void $ forkIOWithUnmask $ \unmask -> do+ result <-+ try @SomeException $+ unmask $+ installCallback+ owner+ (getMaskingState >>= putMVar observed >> wrap (pure ()))+ (const (pure ()))+ putMVar done result+ bounded (readMVar done) >>= either throwIO pure+ bounded (readMVar observed) >>= (@?= MaskedInterruptible)+ releaseCallbackOwner owner+ counts <- readIORef freed+ M.size counts @?= 1+ sum counts @?= 1,+ testCase "installed and replaced bridges release exactly once" $ do+ freed <- newIORef M.empty+ owner <- newCallbackOwnerWith (countFree freed)+ a <- wrap (pure ())+ b <- wrap (pure ())+ installCallback owner (pure a) (const (pure ()))+ installCallback owner (pure b) (const (pure ()))+ releaseUnattachedCallbacks owner+ releaseCallbackOwner owner+ readIORef freed >>= (@?= M.fromList [(castFunPtr a, 1), (castFunPtr b, 1)]),+ testCase "failed native install still owns its allocated bridge" $ do+ freed <- newIORef M.empty+ owner <- newCallbackOwnerWith (countFree freed)+ pointer <- wrap (pure ())+ result <- try @SomeException $ installCallback owner (pure pointer) (const (throwIO (userError "install")))+ assertBool (show result) (isLeft result)+ releaseUnattachedCallbacks owner+ readIORef freed >>= (@?= M.singleton (castFunPtr pointer) 1),+ testCase "failed allocation has no release" $ do+ freed <- newIORef M.empty+ owner <- newCallbackOwnerWith (countFree freed)+ result <- try @SomeException $ installCallback owner (throwIO (userError "allocate") :: IO (FunPtr (IO ()))) (const (pure ()))+ assertBool (show result) (isLeft result)+ releaseUnattachedCallbacks owner+ readIORef freed >>= (@?= M.empty),+ testCase "transfer preserves a callable bridge until client release" $ do+ freed <- newIORef M.empty+ called <- newIORef (0 :: Int)+ owner <- newCallbackOwnerWith (countFree freed)+ pointer <- wrap (modifyIORef' called (+ 1))+ installCallback owner (pure pointer) (const (pure ()))+ attachCallbackOwner owner+ releaseUnattachedCallbacks owner+ readIORef freed >>= (@?= M.empty)+ invoke pointer+ readIORef called >>= (@?= 1)+ releaseCallbackOwner owner+ releaseCallbackOwner owner+ readIORef freed >>= (@?= M.singleton (castFunPtr pointer) 1),+ testCase "transferred and released owners reject reuse before allocating" $ do+ owner <- newCallbackOwner+ allocated <- newIORef (0 :: Int)+ attachCallbackOwner owner+ let reject = do+ result <- try @SomeException $ installCallback owner (modifyIORef' allocated (+ 1) >> wrap (pure ())) (const (pure ()))+ assertBool (show result) (isLeft result)+ checked <- try @SomeException (checkCallbackOwner owner)+ assertBool (show checked) (isLeft checked)+ transferred <- try @SomeException (attachCallbackOwner owner)+ assertBool (show transferred) (isLeft transferred)+ reject+ releaseCallbackOwner owner+ reject+ readIORef allocated >>= (@?= 0),+ testCase "release retry does not repeat completed releases" $ do+ freed <- newIORef M.empty+ attempts <- newIORef (0 :: Int)+ owner <- newCallbackOwnerWith $ \pointer -> do+ attempt <- atomicModifyIORef' attempts (\n -> (n + 1, n + 1))+ if attempt == 2 then throwIO (userError "before free") else countFree freed pointer+ a <- wrap (pure ())+ b <- wrap (pure ())+ installCallback owner (pure a) (const (pure ()))+ installCallback owner (pure b) (const (pure ()))+ result <- try @SomeException (releaseCallbackOwner owner)+ assertBool (show result) (isLeft result)+ releaseCallbackOwner owner+ readIORef freed >>= (@?= M.fromList [(castFunPtr a, 1), (castFunPtr b, 1)]),+ testCase "concurrent releases join before returning" $ do+ entered <- newEmptyMVar+ resume <- newEmptyMVar+ freed <- newIORef M.empty+ owner <- newCallbackOwnerWith $ \pointer -> putMVar entered () >> bounded (readMVar resume) >> countFree freed pointer+ pointer <- wrap (pure ())+ installCallback owner (pure pointer) (const (pure ()))+ doneA <- newEmptyMVar+ doneB <- newEmptyMVar+ void $ forkFinally (releaseCallbackOwner owner) (putMVar doneA)+ bounded (readMVar entered)+ flip finally (putMVar resume ()) $ do+ second <- forkFinally (releaseCallbackOwner owner) (putMVar doneB)+ let awaitBlocked =+ threadStatus second >>= \status ->+ if status == ThreadBlocked BlockedOnMVar then pure () else threadDelay 1000 >> awaitBlocked+ bounded awaitBlocked+ tryReadMVar doneA >>= maybe (pure ()) (const (assertFailure "first release returned before free"))+ tryReadMVar doneB >>= maybe (pure ()) (const (assertFailure "second release returned before free"))+ bounded (readMVar doneA) >>= either throwIO pure+ bounded (readMVar doneB) >>= either throwIO pure+ readIORef freed >>= (@?= M.singleton (castFunPtr pointer) 1)+ ]++countFree :: IORef (M.Map (FunPtr ()) Int) -> FunPtr () -> IO ()+countFree counts pointer = do+ modifyIORef' counts (M.insertWith (+) pointer 1)+ freeHaskellFunPtr pointer++bounded :: IO a -> IO a+bounded action = timeout 5000000 action >>= maybe (assertFailure "owner stage timed out") pure
+ test/Kafka/Producer/ProducerPropertiesSpec.hs view
@@ -0,0 +1,93 @@+module Kafka.Producer.ProducerPropertiesSpec (tests) where++import Data.Map.Strict (Map)+import Data.Map.Strict qualified as Map+import Data.Text (Text)+import Kafka.PropertySupport+import Test.Tasty (TestTree)+import Test.Tasty.HUnit (testCase, (@?=))+import Test.Tasty.QuickCheck qualified as QC+import "rdkafka-hs" Kafka.Producer qualified as P++data Edit = Global Text Text | Topic Text Text | Level P.KafkaLogLevel+ deriving stock (Eq, Show)++tests :: TestTree+tests =+ generatedGroup+ "Producer properties generated"+ [ QC.testProperty "program follows last-write semantics" $+ QC.forAllShrink program shrinkProgram $ \edits ->+ view (assemble edits) QC.=== model edits,+ QC.testProperty "configuration has left and right identity" $+ QC.forAllShrink program shrinkProgram $ \edits ->+ let props = assemble edits+ in QC.conjoin [view (mempty <> props) QC.=== view props, view (props <> mempty) QC.=== view props],+ QC.testProperty "configuration composition is associative" $+ QC.forAllShrink triple shrinkTriple $ \(a, b, c) ->+ view ((assemble a <> assemble b) <> assemble c) QC.=== view (assemble a <> (assemble b <> assemble c)),+ QC.testProperty "composition appends writes in order" $+ QC.forAllShrink pair shrinkPair $ \(a, b) ->+ view (assemble a <> assemble b) QC.=== model (a <> b),+ QC.testProperty "unrelated keys survive a conflicting write" $+ QC.forAllShrink ((,) <$> smallText <*> smallText) shrinkValues $ \(before, after) ->+ let left =+ P.extraProps (Map.fromList [("left", before), ("shared", before)])+ <> P.extraTopicProps (Map.fromList [("left", before), ("shared", before)])+ right = P.extraProp "shared" after <> P.extraTopicProps (Map.singleton "shared" after)+ expected = Map.fromList [("left", before), ("shared", after)]+ in view (left <> right) QC.=== (expected, expected, Nothing),+ QC.testProperty "last explicit log level wins" $+ QC.forAll ((,) <$> logLevel <*> logLevel) $ \(a, b) ->+ P.ppLogLevel (P.logLevel a <> P.logLevel b) QC.=== Just b,+ testCase "fixed empty duplicate and binary text values" $ do+ let edits = [Global "" "", Global "shared" "before", Global "shared" "after", Topic "empty" "", Topic "binary" "a\0b", Level P.KafkaLogDebug, Level P.KafkaLogEmerg]+ view (assemble edits) @?= (Map.fromList [("", ""), ("shared", "after")], Map.fromList [("empty", ""), ("binary", "a\0b")], Just P.KafkaLogEmerg)+ ]++program :: QC.Gen [Edit]+program = boundedList 30 $ QC.oneof [Global <$> smallText <*> smallText, Topic <$> smallText <*> smallText, Level <$> logLevel]++logLevel :: QC.Gen P.KafkaLogLevel+logLevel = QC.elements [P.KafkaLogEmerg, P.KafkaLogAlert, P.KafkaLogCrit, P.KafkaLogErr, P.KafkaLogWarning, P.KafkaLogNotice, P.KafkaLogInfo, P.KafkaLogDebug]++shrinkProgram :: [Edit] -> [[Edit]]+shrinkProgram = QC.shrinkList shrinkEdit+ where+ shrinkEdit (Global key value) = [Global key' value | key' <- shrinkText key] <> [Global key value' | value' <- shrinkText value]+ shrinkEdit (Topic key value) = [Topic key' value | key' <- shrinkText key] <> [Topic key value' | value' <- shrinkText value]+ shrinkEdit (Level _) = []++pair :: QC.Gen ([Edit], [Edit])+pair = (,) <$> program <*> program++triple :: QC.Gen ([Edit], [Edit], [Edit])+triple = (,,) <$> program <*> program <*> program++shrinkPair :: ([Edit], [Edit]) -> [([Edit], [Edit])]+shrinkPair (a, b) = [(a', b) | a' <- shrinkProgram a] <> [(a, b') | b' <- shrinkProgram b]++shrinkTriple :: ([Edit], [Edit], [Edit]) -> [([Edit], [Edit], [Edit])]+shrinkTriple (a, b, c) = [(a', b, c) | a' <- shrinkProgram a] <> [(a, b', c) | b' <- shrinkProgram b] <> [(a, b, c') | c' <- shrinkProgram c]++shrinkValues :: (Text, Text) -> [(Text, Text)]+shrinkValues (a, b) = [(a', b) | a' <- shrinkText a] <> [(a, b') | b' <- shrinkText b]++assemble :: [Edit] -> P.ProducerProperties+assemble = foldMap $ \case+ Global key value -> P.extraProp key value+ Topic key value -> P.extraTopicProps (Map.singleton key value)+ Level level -> P.logLevel level++view :: P.ProducerProperties -> (Map Text Text, Map Text Text, Maybe P.KafkaLogLevel)+view props = (P.ppKafkaProps props, P.ppTopicProps props, P.ppLogLevel props)++-- Independent state-machine model: each edit writes one field/key. It does+-- not use producer composition or map union to derive expected results.+model :: [Edit] -> (Map Text Text, Map Text Text, Maybe P.KafkaLogLevel)+model = foldl' step (Map.empty, Map.empty, Nothing)+ where+ step (global, topic, level) = \case+ Global key value -> (Map.insert key value global, topic, level)+ Topic key value -> (global, Map.insert key value topic, level)+ Level newLevel -> (global, topic, Just newLevel)
+ test/Kafka/PublicDataContractSpec.hs view
@@ -0,0 +1,274 @@+module Kafka.PublicDataContractSpec (tests) where++import Control.Exception (displayException, fromException, toException)+import Control.Monad (forM_)+import Data.ByteString qualified as BS+import Data.Int (Int64)+import Data.List (intercalate)+import Data.List.NonEmpty (NonEmpty (..))+import Data.Map.Strict qualified as M+import Data.Semigroup (sconcat, stimes)+import Data.Set qualified as Set+import Data.String (fromString)+import Data.Text qualified as Text+import Foreign.C.String (CString, peekCString)+import Foreign.C.Types (CInt (..))+import GHC.Generics qualified as G+import Kafka.PropertySupport+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.HUnit (assertBool, testCase, (@?=))+import Test.Tasty.QuickCheck qualified as QC+import "rdkafka-hs" Kafka.Consumer qualified as C+import "rdkafka-hs" Kafka.Metadata qualified as D+import "rdkafka-hs" Kafka.Producer qualified as P+import "rdkafka-hs" Kafka.Topic.Types qualified as T+import "rdkafka-hs" Kafka.Types qualified as K++foreign import ccall unsafe "rdkafka_hs_test_error_count" errorCount :: IO CInt++foreign import ccall unsafe "rdkafka_hs_test_error_code" errorCode :: CInt -> IO CInt++foreign import ccall unsafe "rdkafka_hs_test_error_name" errorName :: CInt -> IO CString++foreign import ccall unsafe "rdkafka_hs_test_error_description" errorDescription :: CInt -> IO CString++foreign import ccall unsafe "rdkafka_hs_test_error_sentinel" sentinel :: CInt -> IO CInt++tests :: TestTree+tests =+ testGroup+ "Public data contracts"+ [ generatedGroup+ "builders"+ [ QC.testProperty "semigroup defaults retain writes callbacks and subscription union" $+ QC.forAll ((,,) <$> text <*> text <*> QC.choose (1, 5 :: Int)) $ \(key, value, copies) ->+ let cp = C.extraProp key value <> C.setCallback (C.logCallback (\_ _ _ -> pure ()))+ pp = P.extraProp key value <> P.setCallback (P.deliveryCallback (\_ -> pure ()))+ sub = C.topics [K.TopicName key] <> C.extraSubscriptionProps (M.singleton key value)+ subView (C.Subscription names properties) = (Set.toAscList names, properties)+ in QC.conjoin+ [ consumer (sconcat (cp :| [cp])) QC.=== (M.singleton key value, Nothing, Nothing, 2),+ consumer (stimes copies cp) QC.=== (M.singleton key value, Nothing, Nothing, copies),+ producer (sconcat (pp :| [pp])) QC.=== (M.singleton key value, M.empty, Nothing, 2),+ producer (stimes copies pp) QC.=== (M.singleton key value, M.empty, Nothing, copies),+ subView (sconcat (sub :| [sub])) QC.=== ([K.TopicName key], M.singleton key value),+ subView (stimes copies sub) QC.=== ([K.TopicName key], M.singleton key value)+ ],+ QC.testProperty "consumer builders preserve exact settings and leave other fields unset" $+ QC.forAll ((,,,,) <$> strings <*> text <*> text <*> signed <*> signed64) $ \(addresses, group, client, amount, millis) ->+ let property pairs = (M.fromList pairs, Nothing, Nothing, 0)+ decimal value = Text.pack (show value)+ in QC.conjoin+ [ consumer (C.brokersList (map K.BrokerAddress addresses)) QC.=== property [("bootstrap.servers", Text.pack (intercalate "," (map Text.unpack addresses)))],+ consumer (C.groupId (C.ConsumerGroupId group)) QC.=== property [("group.id", group)],+ consumer (C.clientId (K.ClientId client)) QC.=== property [("client.id", client)],+ consumer (C.autoCommit (K.Millis millis)) QC.=== property [("enable.auto.commit", "true"), ("auto.commit.interval.ms", decimal millis)],+ consumer C.noAutoCommit QC.=== property [("enable.auto.commit", "false")],+ consumer C.noAutoOffsetStore QC.=== property [("enable.auto.offset.store", "false")],+ consumer C.suppressDisconnectLogs QC.=== property [("log.connection.close", "false")],+ consumer (C.statisticsInterval (K.Millis millis)) QC.=== property [("statistics.interval.ms", decimal millis)],+ consumer (C.queuedMaxMessagesKBytes amount) QC.=== property [("queued.max.messages.kbytes", decimal amount)],+ consumer (C.extraProps (M.fromList [(group, client), (client, group)])) QC.=== property [(group, client), (client, group)]+ ],+ QC.testProperty "producer builders preserve global versus explicit topic placement" $+ QC.forAll ((,,) <$> strings <*> signed <*> signed64) $ \(addresses, amount, millis) ->+ let global pairs = (M.fromList pairs, M.empty, Nothing, 0)+ topic pairs = (M.empty, M.fromList pairs, Nothing, 0)+ in QC.conjoin+ [ producer (P.brokersList (map K.BrokerAddress addresses)) QC.=== global [("bootstrap.servers", Text.pack (intercalate "," (map Text.unpack addresses)))],+ producer P.suppressDisconnectLogs QC.=== global [("log.connection.close", "false")],+ producer (P.statisticsInterval (K.Millis millis)) QC.=== global [("statistics.interval.ms", Text.pack (show millis))],+ producer (P.sendTimeout (K.Timeout amount)) QC.=== topic [("message.timeout.ms", Text.pack (show amount))]+ ],+ QC.testProperty "all codecs have independently specified builder spellings" $+ QC.forAll (QC.elements codecs) $ \(codec, spelling) ->+ QC.conjoin+ [ consumer (C.compression codec) QC.=== (M.singleton "compression.codec" spelling, Nothing, Nothing, 0),+ producer (P.compression codec) QC.=== (M.singleton "compression.codec" spelling, M.empty, Nothing, 0),+ producer (P.topicCompression codec) QC.=== (M.empty, M.singleton "compression.codec" spelling, Nothing, 0)+ ],+ QC.testProperty "debug contexts preserve order duplicates and the empty-list identity" $+ QC.forAll (boundedList 15 (QC.elements contexts)) $ \entries ->+ let settings = if null entries then M.empty else M.singleton "debug" (Text.pack (intercalate "," (map snd entries)))+ in QC.conjoin [consumer (C.debugOptions (map fst entries)) QC.=== (settings, Nothing, Nothing, 0), producer (P.debugOptions (map fst entries)) QC.=== (settings, M.empty, Nothing, 0)]+ ],+ generatedGroup+ "representations"+ [ QC.testProperty "numeric ordering and reads agree with represented signed values" $+ QC.forAll ((,,,) <$> signed <*> signed <*> signed64 <*> signed64) $ \(a, b, x, y) ->+ QC.conjoin+ [ compare (K.BrokerId a) (K.BrokerId b) QC.=== compare a b,+ compare (K.PartitionId a) (K.PartitionId b) QC.=== compare a b,+ compare (K.BatchSize a) (K.BatchSize b) QC.=== compare a b,+ compare (C.Offset x) (C.Offset y) QC.=== compare x y,+ compare (K.Millis x) (K.Millis y) QC.=== compare x y,+ readShow (K.BrokerId a),+ readShow (K.PartitionId a),+ readShow (K.BatchSize a),+ readShow (K.Timeout a),+ readShow (C.Offset x),+ readShow (K.Millis x),+ fromEnum (K.PartitionId a) QC.=== a,+ (toEnum a :: K.PartitionId) QC.=== K.PartitionId a+ ],+ QC.testProperty "numeric instances preserve primitive arithmetic including boundaries" $+ QC.forAll ((,,,) <$> signed <*> signed <*> signed64 <*> signed64) $ \(a, b, x, y) ->+ QC.conjoin+ [ map K.unBatchSize [K.BatchSize a + K.BatchSize b, K.BatchSize a - K.BatchSize b, K.BatchSize a * K.BatchSize b, negate (K.BatchSize a), abs (K.BatchSize a), signum (K.BatchSize a), fromInteger (toInteger a)] QC.=== [a + b, a - b, a * b, negate a, abs a, signum a, a],+ map K.unMillis [K.Millis x + K.Millis y, K.Millis x - K.Millis y, K.Millis x * K.Millis y, negate (K.Millis x), abs (K.Millis x), signum (K.Millis x), fromInteger (toInteger x)] QC.=== [x + y, x - y, x * y, negate x, abs x, signum x, x]+ ],+ QC.testProperty "text ordering string conversion reads and generic representations round-trip" $+ QC.forAll ((,) <$> text <*> text) $ \(a, b) ->+ QC.conjoin+ [ compare (K.TopicName a) (K.TopicName b) QC.=== compare a b,+ compare (K.ClientId a) (K.ClientId b) QC.=== compare a b,+ compare (C.ConsumerGroupId a) (C.ConsumerGroupId b) QC.=== compare a b,+ compare (D.GroupMemberId a) (D.GroupMemberId b) QC.=== compare a b,+ compare (D.GroupProtocol a) (D.GroupProtocol b) QC.=== compare a b,+ compare (D.GroupProtocolType a) (D.GroupProtocolType b) QC.=== compare a b,+ (fromString (Text.unpack a) :: K.TopicName) QC.=== K.TopicName a,+ (fromString (Text.unpack a) :: K.ClientId) QC.=== K.ClientId a,+ (fromString (Text.unpack a) :: K.BrokerAddress) QC.=== K.BrokerAddress a,+ (fromString (Text.unpack a) :: C.ConsumerGroupId) QC.=== C.ConsumerGroupId a,+ readShow (K.TopicName a),+ readShow (D.GroupMemberId a),+ readShow (D.GroupProtocol a),+ readShow (D.GroupProtocolType a),+ generic (K.TopicName a),+ generic (K.ClientId a),+ generic (K.BrokerAddress a),+ generic (C.ConsumerGroupId a)+ ],+ QC.testProperty "consumer variants retain fields and distinguish constructors" $+ QC.forAll ((,,,) <$> text <*> signed <*> signed64 <*> bytes) $ \(name, partition, offset, value) ->+ let topic = K.TopicName name+ partitions = [(topic, K.PartitionId partition)]+ offsets = [C.PartitionOffsetBeginning, C.PartitionOffsetEnd, C.PartitionOffset offset, C.PartitionOffsetStored, C.PartitionOffsetInvalid]+ events = [C.RebalanceBeforeAssign partitions, C.RebalanceAssign partitions, C.RebalanceBeforeRevoke partitions, C.RebalanceRevoke partitions]+ headers = K.headersFromList [(value, value), (value, "")]+ message = C.ConsumerRecord topic (K.PartitionId partition) (C.Offset offset) (C.CreateTime (K.Millis offset)) headers value value+ failure = C.ConsumerMessageError K.KafkaInvalidReturnValue (Just topic) (Just (K.PartitionId partition)) (Just (C.Offset offset))+ stores = [C.OffsetStoreBroker, C.OffsetStoreFile (Text.unpack name) C.OffsetSyncDisable, C.OffsetStoreFile (Text.unpack name) C.OffsetSyncImmediate, C.OffsetStoreFile (Text.unpack name) (C.OffsetSyncInterval partition)]+ in QC.conjoin+ [ allDistinct offsets,+ allDistinct events,+ allDistinct stores,+ QC.conjoin (map generic offsets),+ QC.conjoin (map generic events),+ QC.conjoin (map generic stores),+ generic C.OffsetCommit,+ generic C.OffsetCommitAsync,+ generic C.Earliest,+ generic C.Latest,+ generic (C.SubscribedPartitions (map snd partitions)),+ generic C.SubscribedPartitionsAll,+ readShow message,+ readShow headers,+ generic message,+ generic failure,+ (C.cmeError failure, C.cmeTopic failure, C.cmePartition failure, C.cmeOffset failure) QC.=== (K.KafkaInvalidReturnValue, Just topic, Just (K.PartitionId partition), Just (C.Offset offset))+ ],+ QC.testProperty "producer records delivery variants and topic requests retain exact fields" $+ QC.forAll ((,,,,) <$> text <*> signed <*> signed64 <*> bytes <*> bytes) $ \(name, partition, offset, key, value) ->+ let topic = K.TopicName name+ headers = K.headersFromList [(key, value)]+ message = P.ProducerRecord topic (P.SpecifiedPartition partition) (Just key) (Just value) headers+ reports = [P.DeliverySuccess message (C.Offset offset), P.DeliveryFailure message K.KafkaBadConfiguration, P.NoMessageError K.KafkaInvalidReturnValue]+ request = T.NewTopic topic (T.PartitionCount partition) (T.ReplicationFactor partition) (M.singleton (Text.unpack name) (Text.unpack name))+ in QC.conjoin+ [ (P.prTopic message, P.prPartition message, P.prKey message, P.prValue message, P.prHeaders message) QC.=== (topic, P.SpecifiedPartition partition, Just key, Just value, headers),+ allDistinct reports,+ QC.conjoin (map generic reports),+ generic message,+ QC.conjoin+ [ (P.ImmediateError (K.KafkaError name) == P.ImmediateError (K.KafkaError (name <> "x"))) QC.=== False,+ show (P.ImmediateError (K.KafkaError name)) QC.=== show (K.KafkaError name),+ (case P.ImmediateError (K.KafkaError name) of P.ImmediateError err -> err) QC.=== K.KafkaError name+ ],+ QC.property (P.SpecifiedPartition partition /= P.UnassignedPartition),+ map fromEnum [P.PurgeQueue, P.PurgeInFlight, P.PurgeNonBlocking] QC.=== [0, 1, 2],+ [minBound .. maxBound :: P.PurgeFlag] QC.=== [P.PurgeQueue, P.PurgeInFlight, P.PurgeNonBlocking],+ (T.topicName request, T.unPartitionCount (T.topicPartitionCount request), T.unReplicationFactor (T.topicReplicationFactor request), T.topicConfig request) QC.=== (topic, partition, partition, M.singleton (Text.unpack name) (Text.unpack name))+ ],+ QC.testProperty "metadata structures retain identities states members and binary data" $+ QC.forAll ((,,,,,) <$> text <*> signed <*> signed <*> signed64 <*> bytes <*> bytes) $ \(name, n, port, offset, binary, assignment) ->+ let topic = K.TopicName name+ brokerId = K.BrokerId n+ broker = D.BrokerMetadata brokerId name port+ partition = D.PartitionMetadata (K.PartitionId n) Nothing brokerId [brokerId] [brokerId]+ topicInfo = D.TopicMetadata topic [partition] Nothing+ metadata = D.KafkaMetadata [broker] [topicInfo] brokerId+ watermark = D.WatermarkOffsets topic (K.PartitionId n) (C.Offset offset) (C.Offset offset)+ member = D.GroupMemberInfo (D.GroupMemberId name) (K.ClientId name) name binary assignment+ states = [D.GroupPreparingRebalance, D.GroupEmpty, D.GroupAwaitingSync, D.GroupStable, D.GroupDead]+ group state = D.GroupInfo (C.ConsumerGroupId name) Nothing state (D.GroupProtocolType name) (D.GroupProtocol name) [member]+ in QC.conjoin+ [ generic broker,+ generic partition,+ generic topicInfo,+ generic metadata,+ generic watermark,+ generic member,+ (D.bmBrokerId broker, D.bmBrokerHost broker, D.bmBrokerPort broker) QC.=== (brokerId, name, port),+ (D.kmBrokers metadata, D.kmTopics metadata, D.kmOrigBroker metadata) QC.=== ([broker], [topicInfo], brokerId),+ (D.gmiMemberId member, D.gmiClientId member, D.gmiClientHost member, D.gmiMetadata member, D.gmiAssignment member) QC.=== (D.GroupMemberId name, K.ClientId name, name, binary, assignment),+ QC.conjoin (map (generic . group) states),+ QC.conjoin (map readShow states),+ allDistinct (map group states)+ ],+ QC.testProperty "every Kafka error preserves its Exception identity and generic form" $+ QC.forAll text $ \message ->+ let errors = [K.KafkaError message, K.KafkaInvalidReturnValue, K.KafkaBadSpecification message, K.KafkaResponseError C.RdKafkaRespErrTimedOut, K.KafkaInvalidConfigurationValue message, K.KafkaUnknownConfigurationKey message, K.KafkaBadConfiguration]+ in QC.conjoin [QC.conjoin [fromException (toException error) QC.=== Just error, generic error, case error of K.KafkaResponseError _ -> QC.property True; _ -> displayException error QC.=== show error] | error <- errors]+ ],+ testCase "all linked native errors retain sparse numeric codes names and descriptions" $ do+ count <- errorCount+ assertBool "native error descriptor table is empty" (count > 0)+ forM_ [0 .. count - 1] $ \index -> do+ code <- fromIntegral <$> errorCode index+ name <- errorName index >>= peekCString+ description <- errorDescription index >>= peekCString+ let value = toEnum code :: C.RdKafkaRespErrT+ fromEnum value @?= code+ displayException (K.KafkaResponseError value) @?= "[" <> name <> "] " <> description+ forM_ (zip [0 .. 2] [C.RdKafkaRespErrBegin, C.RdKafkaRespErrEnd, C.RdKafkaRespErrEndAll]) $ \(index, value) -> do+ code <- fromIntegral <$> sentinel index+ fromEnum value @?= code+ (toEnum code :: C.RdKafkaRespErrT) @?= value+ ]++consumer :: C.ConsumerProperties -> (M.Map Text.Text Text.Text, Maybe K.KafkaLogLevel, Maybe C.CallbackPollMode, Int)+consumer p = (C.cpProps p, C.cpLogLevel p, C.cpCallbackPollMode p, length (C.cpCallbacks p))++producer :: P.ProducerProperties -> (M.Map Text.Text Text.Text, M.Map Text.Text Text.Text, Maybe K.KafkaLogLevel, Int)+producer p = (P.ppKafkaProps p, P.ppTopicProps p, P.ppLogLevel p, length (P.ppCallbacks p))++readShow :: (Eq a, Show a, Read a) => a -> QC.Property+readShow value = QC.conjoin [read (show value) QC.=== value, read (show [value]) QC.=== [value]]++generic :: (Eq a, Show a, G.Generic a) => a -> QC.Property+generic value = G.to (G.from value) QC.=== value++allDistinct :: (Eq a, Show a) => [a] -> QC.Property+allDistinct values = QC.conjoin [QC.counterexample (show (a, b)) (QC.property (a /= b)) | (i, a) <- zip [0 :: Int ..] values, (j, b) <- zip [0 :: Int ..] values, i /= j]++text :: QC.Gen Text.Text+text = QC.frequency [(2, smallText), (5, Text.pack <$> boundedList 30 QC.arbitrary)]++strings :: QC.Gen [Text.Text]+strings = boundedList 8 text++bytes :: QC.Gen BS.ByteString+bytes = BS.pack <$> boundedList 30 QC.arbitrary++signed :: QC.Gen Int+signed = QC.frequency [(1, QC.elements [minBound, -1, 0, 1, maxBound]), (4, QC.arbitrary)] :: QC.Gen Int++signed64 :: QC.Gen Int64+signed64 = QC.frequency [(1, QC.elements [minBound, -1, 0, 1, maxBound]), (4, QC.arbitrary)] :: QC.Gen Int64++codecs :: [(K.KafkaCompressionCodec, Text.Text)]+codecs = [(K.NoCompression, "none"), (K.Gzip, "gzip"), (K.Snappy, "snappy"), (K.Lz4, "lz4"), (K.Zstd, "zstd")]++contexts :: [(K.KafkaDebug, String)]+contexts = [(K.DebugGeneric, "generic"), (K.DebugBroker, "broker"), (K.DebugTopic, "topic"), (K.DebugMetadata, "metadata"), (K.DebugQueue, "queue"), (K.DebugMsg, "msg"), (K.DebugProtocol, "protocol"), (K.DebugCgrp, "cgrp"), (K.DebugSecurity, "security"), (K.DebugFetch, "fetch"), (K.DebugFeature, "feature"), (K.DebugAll, "all")]
+ test/Kafka/PublicPropertiesSpec.hs view
@@ -0,0 +1,283 @@+{-# OPTIONS_GHC -Wno-deprecations #-}++module Kafka.PublicPropertiesSpec (tests) where++import Control.Monad (forM_)+import Data.Bifoldable (bifoldMap)+import Data.Bifunctor (bimap, first, second)+import Data.Bitraversable (bitraverse)+import Data.ByteString qualified as BS+import Data.Functor.Compose (Compose (..))+import Data.Functor.Const (Const (..))+import Data.Functor.Identity (Identity (..))+import Data.Int (Int64)+import Data.List (nub, sort)+import Data.Map.Strict qualified as M+import Data.Set qualified as Set+import Data.Text (Text)+import Data.Text qualified as Text+import Data.Word (Word32, Word8)+import Kafka.PropertySupport+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.HUnit (testCase, (@?=))+import Test.Tasty.QuickCheck qualified as QC+import "rdkafka-hs" Kafka.Consumer qualified as C+import "rdkafka-hs" Kafka.Types qualified as K+import "rdkafka-hs" Kafka.Version qualified as V++data Edit = Property Text Text | Level K.KafkaLogLevel | Mode C.CallbackPollMode+ deriving stock (Eq, Show)++data SubEdit = SubTopic Text | SubProperty Text Text | Reset C.OffsetReset+ deriving stock (Eq, Show)++tests :: TestTree+tests =+ testGroup+ "Public properties"+ [ generatedGroup+ "consumer composition"+ [ QC.testProperty "consumer program follows independent last-write model" $+ QC.forAllShrink program shrinkProgram $+ \edits -> view (assemble edits) QC.=== model edits,+ QC.testProperty "consumer identity preserves every observable field" $+ QC.forAllShrink program shrinkProgram $ \edits ->+ let p = assemble edits in QC.conjoin [view (mempty <> p) QC.=== view p, view (p <> mempty) QC.=== view p],+ QC.testProperty "consumer association preserves writes and poll mode" $+ QC.forAll ((,,) <$> program <*> program <*> program) $ \(a, b, c) ->+ view ((assemble a <> assemble b) <> assemble c) QC.=== view (assemble a <> (assemble b <> assemble c)),+ QC.testProperty "consumer composition appends programs" $+ QC.forAll ((,) <$> program <*> program) $+ \(a, b) -> view (assemble a <> assemble b) QC.=== model (a <> b),+ QC.testProperty "unset poll mode preserves a prior explicit mode" $+ QC.forAll ((,,) <$> mode <*> smallText <*> smallText) $ \(poll, key, value) ->+ C.effectiveCallbackPollMode (C.callbackPollMode poll <> C.extraProp key value) QC.=== poll,+ QC.testProperty "consumer helpers write exact native property names" $+ QC.forAll ((,,) <$> smallText <*> smallText <*> QC.arbitrary) $ \(group, client, millis :: Int64) ->+ C.cpProps (C.groupId (C.ConsumerGroupId group) <> C.clientId (K.ClientId client) <> C.autoCommit (K.Millis millis) <> C.noAutoOffsetStore)+ QC.=== M.fromList [("group.id", group), ("client.id", client), ("enable.auto.commit", "true"), ("auto.commit.interval.ms", Text.pack (show millis)), ("enable.auto.offset.store", "false")]+ ],+ generatedGroup+ "subscription"+ [ QC.testProperty "subscription follows last-write properties and topic union" $+ QC.forAllShrink subscriptionProgram shrinkSubscription $+ \edits -> subscriptionView (subscription edits) QC.=== subscriptionModel edits,+ QC.testProperty "subscription identity and association retain topics and properties" $+ QC.forAll ((,,) <$> subscriptionProgram <*> subscriptionProgram <*> subscriptionProgram) $ \(a, b, c) ->+ let x = subscription a; y = subscription b; z = subscription c+ in QC.conjoin [subscriptionView (mempty <> x) QC.=== subscriptionView x, subscriptionView (x <> mempty) QC.=== subscriptionView x, subscriptionView ((x <> y) <> z) QC.=== subscriptionView (x <> (y <> z))],+ QC.testProperty "subscription composition appends property writes" $+ QC.forAll ((,) <$> subscriptionProgram <*> subscriptionProgram) $+ \(a, b) -> subscriptionView (subscription a <> subscription b) QC.=== subscriptionModel (a <> b),+ testCase "later subscription reset and explicit properties win" $ do+ subscriptionView (C.offsetReset C.Latest <> C.offsetReset C.Earliest) @?= ([], M.singleton "auto.offset.reset" "earliest")+ subscriptionView (C.extraSubscriptionProps (M.singleton "shared" "before") <> C.extraSubscriptionProps (M.singleton "shared" "after")) @?= ([], M.singleton "shared" "after")+ subscriptionView (C.topics ["a", "b"] <> C.topics ["b", "c"]) @?= (["a", "b", "c"], M.empty)+ ],+ generatedGroup+ "headers"+ [ QC.testProperty "header list round-trip preserves duplicates and binary bytes" $+ QC.forAllShrink headerPairs shrinkPairs $+ \pairs -> K.headersToList (K.headersFromList pairs) QC.=== pairs,+ QC.testProperty "header concatenation follows list order" $+ QC.forAll ((,) <$> headerPairs <*> headerPairs) $ \(a, b) ->+ K.headersToList (K.headersFromList a <> K.headersFromList b) QC.=== (a <> b),+ QC.testProperty "headers have two identities and associative concatenation" $+ QC.forAll ((,,) <$> headerPairs <*> headerPairs <*> headerPairs) $ \(a, b, c) ->+ let x = K.headersFromList a; y = K.headersFromList b; z = K.headersFromList c+ in QC.conjoin [mempty <> x QC.=== x, x <> mempty QC.=== x, (x <> y) <> z QC.=== x <> (y <> z)],+ testCase "fixed duplicate empty and binary header values" $ do+ let pairs = [("same", ""), ("same", BS.pack [0, 255]), ("", ""), ("same", "last")]+ K.headersToList (K.headersFromList pairs) @?= pairs+ ],+ generatedGroup+ "records"+ [ law "record functor identity" $ \r -> fmap id r QC.=== r,+ law "record functor composition" $ \r -> fmap ((+ 1) . (* 3)) r QC.=== (fmap (+ 1) . fmap (* 3)) r,+ law "record bifunctor identity and composition" $ \r ->+ QC.conjoin+ [ bimap id id r QC.=== r,+ bimap ((+ 1) . (* 2)) (subtract 1 . (* 3)) r QC.=== (bimap (+ 1) (subtract 1) . bimap (* 2) (* 3)) r+ ],+ law "record mapping preserves origin timestamp and headers" $ \r ->+ let mapped = bimap (+ 1) (* 3) r+ in (C.crTopic mapped, C.crPartition mapped, C.crOffset mapped, C.crTimestamp mapped, C.crHeaders mapped, C.crKey mapped, C.crValue mapped)+ QC.=== (C.crTopic r, C.crPartition r, C.crOffset r, C.crTimestamp r, C.crHeaders r, C.crKey r + 1, C.crValue r * 3),+ law "record traversal identity and failure preserve the applicative contract" $ \r ->+ QC.conjoin+ [ runIdentity (traverse Identity r) QC.=== r,+ traverse Just r QC.=== Just r,+ traverse (const (Nothing :: Maybe Int)) r QC.=== Nothing,+ getConst (traverse (const (Const ["value" :: String])) r) QC.=== ["value"]+ ],+ law "record traversal composition preserves nested effects" $ \r ->+ let f value = if value `mod` 3 == 0 then Nothing else Just (value + 1)+ g value = [value, value * 2]+ in getCompose (traverse (Compose . fmap g . f) r) QC.=== fmap (traverse g) (traverse f r),+ law "record bitraversal visits key before value" $ \r ->+ QC.conjoin+ [ runIdentity (bitraverse Identity Identity r) QC.=== r,+ bitraverse Just Just r QC.=== Just r,+ bitraverse (const (Nothing :: Maybe Int)) Just r QC.=== Nothing,+ bitraverse Just (const (Nothing :: Maybe Int)) r QC.=== Nothing,+ getConst (bitraverse (const (Const ["key" :: String])) (const (Const ["value"])) r) QC.=== ["key", "value"]+ ],+ law "record bitraversal composition preserves nested effects" $ \r ->+ let f value = if value `mod` 3 == 0 then Nothing else Just (value + 1)+ g value = [value, value * 2]+ h value = [value - 1, value]+ in getCompose (bitraverse (Compose . fmap g . f) (Compose . fmap h . f) r) QC.=== fmap (bitraverse g h) (bitraverse f f r),+ law "record folds retain key and value order" $ \r ->+ QC.conjoin+ [ foldMap (: []) r QC.=== [C.crValue r],+ bifoldMap (\x -> [("key" :: String, x)]) (\x -> [("value", x)]) r QC.=== [("key", C.crKey r), ("value", C.crValue r)]+ ],+ law "deprecated record mapping remains equivalent" $ \r ->+ QC.conjoin+ [ C.crMapKey (+ 1) r QC.=== first (+ 1) r,+ C.crMapValue (* 3) r QC.=== second (* 3) r,+ C.crMapKV (+ 1) (* 3) r QC.=== bimap (+ 1) (* 3) r+ ],+ law "deprecated traversal helpers preserve successful effects" $ \r ->+ QC.conjoin+ [ C.sequenceFirst (first Just r) QC.=== Just r,+ C.traverseFirst Just r QC.=== Just r,+ runIdentity (C.traverseFirstM (Identity . Just) r) QC.=== Just r,+ runIdentity (C.traverseM (Identity . Just) r) QC.=== Just r,+ runIdentity (C.bitraverseM (Identity . Just) (Identity . Just) r) QC.=== Just r+ ],+ law "deprecated traversal helpers preserve failed effects" $ \r ->+ QC.conjoin+ [ C.traverseFirst (const (Nothing :: Maybe Int)) r QC.=== Nothing,+ runIdentity (C.traverseFirstM (const (Identity (Nothing :: Maybe Int))) r) QC.=== Nothing,+ runIdentity (C.traverseM (const (Identity (Nothing :: Maybe Int))) r) QC.=== Nothing,+ runIdentity (C.bitraverseM (Identity . Just) (const (Identity (Nothing :: Maybe Int))) r) QC.=== Nothing+ ]+ ],+ generatedGroup+ "representations"+ [ QC.testProperty "text newtypes preserve arbitrary represented text" $+ QC.forAll smallText $ \text ->+ QC.conjoin+ [K.unTopicName (K.TopicName text) QC.=== text, K.unClientId (K.ClientId text) QC.=== text, K.unBrokerAddress (K.BrokerAddress text) QC.=== text, C.unConsumerGroupId (C.ConsumerGroupId text) QC.=== text],+ QC.testProperty "integer newtypes preserve signed machine boundaries" $ \(n :: Int) ->+ QC.conjoin+ [K.unBrokerId (K.BrokerId n) QC.=== n, K.unPartitionId (K.PartitionId n) QC.=== n, K.unBatchSize (K.BatchSize n) QC.=== n, K.unTimeout (K.Timeout n) QC.=== n],+ QC.testProperty "offset and milliseconds preserve signed 64-bit boundaries" $ \(n :: Int64) ->+ QC.conjoin+ [C.unOffset (C.Offset n) QC.=== n, K.unMillis (K.Millis n) QC.=== n, read (show (C.Offset n)) QC.=== C.Offset n, read (show (K.Millis n)) QC.=== K.Millis n],+ QC.testProperty "timestamp constructors retain their represented boundary" $+ QC.forAll timestamp $+ \value -> (read (show value) :: C.Timestamp) QC.=== value,+ QC.testProperty "system topic classification requires two initial underscores" $+ QC.forAll smallText $+ \text -> K.topicType (K.TopicName text) QC.=== (case Text.unpack text of '_' : '_' : _ -> K.System; _ -> K.User),+ testCase "fixed empty underscore and signed numeric boundaries" $ do+ map (K.topicType . K.TopicName) ["", "_", "__", "___", "x__", "__λ"] @?= [K.User, K.User, K.System, K.System, K.User, K.System]+ forM_ [minBound, 0, maxBound :: Int64] $ \n -> do+ C.unOffset (C.Offset n) @?= n+ (read (show (C.CreateTime (K.Millis n))) :: C.Timestamp) @?= C.CreateTime (K.Millis n)+ ],+ generatedGroup+ "version"+ [ QC.testProperty "version bytes decode independently of prerelease byte" $ \(major :: Word8) (minor :: Word8) (revision :: Word8) (pre :: Word8) ->+ let packed = (((fromIntegral major * 256 + fromIntegral minor) * 256 + fromIntegral revision) * 256 + fromIntegral pre) :: Word32+ in V.decodeLibrdkafkaVersion (fromIntegral packed) QC.=== V.LibrdkafkaVersion (fromIntegral major) (fromIntegral minor) (fromIntegral revision),+ QC.testProperty "version extraction agrees with arithmetic for every Int" $ \(n :: Int) ->+ V.decodeLibrdkafkaVersion n QC.=== V.LibrdkafkaVersion ((n `div` 16777216) `mod` 256) ((n `div` 65536) `mod` 256) ((n `div` 256) `mod` 256),+ testCase "fixed zero and full version byte boundaries" $ do+ V.decodeLibrdkafkaVersion 0 @?= V.LibrdkafkaVersion 0 0 0+ V.decodeLibrdkafkaVersion (fromIntegral (maxBound :: Word32)) @?= V.LibrdkafkaVersion 255 255 255+ ],+ testCase "every compression debug and log enumeration has its native spelling" $ do+ map K.kafkaCompressionCodecToText [K.NoCompression, K.Gzip, K.Snappy, K.Lz4, K.Zstd] @?= ["none", "gzip", "snappy", "lz4", "zstd"]+ map K.kafkaDebugToText [K.DebugGeneric, K.DebugBroker, K.DebugTopic, K.DebugMetadata, K.DebugQueue, K.DebugMsg, K.DebugProtocol, K.DebugCgrp, K.DebugSecurity, K.DebugFetch, K.DebugFeature, K.DebugAll]+ @?= ["generic", "broker", "topic", "metadata", "queue", "msg", "protocol", "cgrp", "security", "fetch", "feature", "all"]+ map fromEnum [K.KafkaLogEmerg .. K.KafkaLogDebug] @?= [0 .. 7]+ ]++program :: QC.Gen [Edit]+program = boundedList 30 (QC.oneof [Property <$> smallText <*> smallText, Level <$> QC.elements [K.KafkaLogEmerg .. K.KafkaLogDebug], Mode <$> mode])++mode :: QC.Gen C.CallbackPollMode+mode = QC.elements [C.CallbackPollModeAsync, C.CallbackPollModeSync]++shrinkProgram :: [Edit] -> [[Edit]]+shrinkProgram = QC.shrinkList $ \case+ Property key value -> [Property key' value | key' <- shrinkText key] <> [Property key value' | value' <- shrinkText value]+ _ -> []++assemble :: [Edit] -> C.ConsumerProperties+assemble = foldMap $ \case+ Property key value -> C.extraProp key value+ Level level -> C.logLevel level+ Mode poll -> C.callbackPollMode poll++view :: C.ConsumerProperties -> (M.Map Text Text, Maybe K.KafkaLogLevel, Maybe C.CallbackPollMode, C.CallbackPollMode)+view p = (C.cpProps p, C.cpLogLevel p, C.cpCallbackPollMode p, C.effectiveCallbackPollMode p)++model :: [Edit] -> (M.Map Text Text, Maybe K.KafkaLogLevel, Maybe C.CallbackPollMode, C.CallbackPollMode)+model edits =+ let (props, level, poll) = foldl' step (M.empty, Nothing, Nothing) edits+ in (props, level, poll, maybe C.CallbackPollModeAsync id poll)+ where+ step (props, level, poll) = \case+ Property key value -> (M.insert key value props, level, poll)+ Level value -> (props, Just value, poll)+ Mode value -> (props, level, Just value)++bytes :: QC.Gen BS.ByteString+bytes = BS.pack <$> boundedList 20 QC.arbitrary++headerPairs :: QC.Gen [(BS.ByteString, BS.ByteString)]+headerPairs = boundedList 15 ((,) <$> QC.oneof [pure "same", bytes] <*> bytes)++shrinkPairs :: [(BS.ByteString, BS.ByteString)] -> [[(BS.ByteString, BS.ByteString)]]+shrinkPairs = QC.shrinkList $ \(key, value) -> [(BS.pack k, value) | k <- QC.shrink (BS.unpack key)] <> [(key, BS.pack v) | v <- QC.shrink (BS.unpack value)]++signed64 :: QC.Gen Int64+signed64 = QC.frequency [(1, QC.elements [minBound, -2002, -1001, -2, -1, 0, 1, maxBound]), (4, QC.arbitrary)]++timestamp :: QC.Gen C.Timestamp+timestamp = QC.oneof [pure C.NoTimestamp, C.CreateTime . K.Millis <$> signed64, C.LogAppendTime . K.Millis <$> signed64]++record :: QC.Gen (C.ConsumerRecord Int Int)+record = C.ConsumerRecord <$> (K.TopicName <$> smallText) <*> (K.PartitionId <$> QC.arbitrary) <*> (C.Offset <$> signed64) <*> timestamp <*> (K.headersFromList <$> headerPairs) <*> QC.arbitrary <*> QC.arbitrary++law :: String -> (C.ConsumerRecord Int Int -> QC.Property) -> TestTree+law name = QC.testProperty name . QC.forAllShrink record shrinkRecord+ where+ shrinkRecord r =+ [r {C.crKey = k} | k <- QC.shrink (C.crKey r)]+ <> [r {C.crValue = v} | v <- QC.shrink (C.crValue r)]+ <> [r {C.crHeaders = K.headersFromList pairs} | pairs <- shrinkPairs (K.headersToList (C.crHeaders r))]+ <> [r {C.crOffset = C.Offset n} | n <- QC.shrink (C.unOffset (C.crOffset r))]+ <> [r {C.crTopic = K.TopicName text} | text <- shrinkText (K.unTopicName (C.crTopic r))]+ <> [r {C.crPartition = K.PartitionId n} | n <- QC.shrink (K.unPartitionId (C.crPartition r))]+ <> [r {C.crTimestamp = C.NoTimestamp} | C.crTimestamp r /= C.NoTimestamp]++subscriptionProgram :: QC.Gen [SubEdit]+subscriptionProgram = boundedList 30 (QC.oneof [SubTopic <$> smallText, SubProperty <$> smallText <*> smallText, Reset <$> QC.elements [C.Earliest, C.Latest]])++shrinkSubscription :: [SubEdit] -> [[SubEdit]]+shrinkSubscription = QC.shrinkList $ \case+ SubTopic topic -> [SubTopic value | value <- shrinkText topic]+ SubProperty key value -> [SubProperty key' value | key' <- shrinkText key] <> [SubProperty key value' | value' <- shrinkText value]+ Reset _ -> []++subscription :: [SubEdit] -> C.Subscription+subscription = foldMap $ \case+ SubTopic value -> C.topics [K.TopicName value]+ SubProperty key value -> C.extraSubscriptionProps (M.singleton key value)+ Reset value -> C.offsetReset value++subscriptionView :: C.Subscription -> ([K.TopicName], M.Map Text Text)+subscriptionView (C.Subscription topics props) = (Set.toAscList topics, props)++subscriptionModel :: [SubEdit] -> ([K.TopicName], M.Map Text Text)+subscriptionModel edits = let (topics, props) = foldl' step ([], M.empty) edits in (sort (nub topics), props)+ where+ step (topics, props) = \case+ SubTopic value -> (topics <> [K.TopicName value], props)+ SubProperty key value -> (topics, M.insert key value props)+ Reset value -> (topics, M.insert "auto.offset.reset" (case value of C.Earliest -> "earliest"; C.Latest -> "latest") props)
+ test/Kafka/VersionTest.hs view
@@ -0,0 +1,24 @@+module Kafka.VersionTest+ ( tests,+ )+where++import Data.Text qualified as Text+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.HUnit (assertBool, testCase, (@?=))+import "rdkafka-hs" Kafka.Version++tests :: TestTree+tests =+ testGroup+ "Kafka.Version"+ [ testCase "linked librdkafka is at least 2.15.0" $+ assertBool+ ("linked librdkafka " <> show librdkafkaVersionNumber <> " is older than 2.15")+ (librdkafkaVersionNumber >= 0x020f0000),+ testCase "version string agrees with the version number" $ do+ let LibrdkafkaVersion {versionMajor, versionMinor} = librdkafkaVersionParts+ take 2 (Text.splitOn "." librdkafkaVersion) @?= [Text.pack (show versionMajor), Text.pack (show versionMinor)],+ testCase "decodes the hex version encoding" $+ decodeLibrdkafkaVersion 0x020f01ff @?= LibrdkafkaVersion {versionMajor = 2, versionMinor = 15, versionRevision = 1}+ ]
+ test/Main.hs view
@@ -0,0 +1,35 @@+module Main (main) where++import Kafka.Consumer.ConsumerPropertiesSpec qualified as ConsumerPropertiesSpec+import Kafka.Consumer.ConsumerRecordMapSpec qualified as ConsumerRecordMapSpec+import Kafka.Consumer.ConsumerRecordTraverseSpec qualified as ConsumerRecordTraverseSpec+import Kafka.Internal.CallbackOwnerSpec qualified as CallbackOwnerSpec+import Kafka.Producer.ProducerPropertiesSpec qualified as ProducerPropertiesSpec+import Kafka.PublicDataContractSpec qualified as PublicDataContractSpec+import Kafka.PublicPropertiesSpec qualified as PublicPropertiesSpec+import Kafka.VersionTest qualified as VersionTest+import System.Environment (getArgs)+import Test.Tasty (defaultMain, testGroup)+import "rdkafka-hs" Kafka.Version (librdkafkaVersion, librdkafkaVersionNumber)++main :: IO ()+main = do+ args <- getArgs+ case args of+ ["--native-version"] -> print (librdkafkaVersion, librdkafkaVersionNumber)+ _ -> runTests++runTests :: IO ()+runTests =+ defaultMain $+ testGroup+ "rdkafka-hs"+ [ CallbackOwnerSpec.tests,+ ConsumerPropertiesSpec.tests,+ ConsumerRecordMapSpec.tests,+ ConsumerRecordTraverseSpec.tests,+ VersionTest.tests,+ ProducerPropertiesSpec.tests,+ PublicPropertiesSpec.tests,+ PublicDataContractSpec.tests+ ]
+ test/cbits/error_constants.c view
@@ -0,0 +1,22 @@+/* Compare the Haskell error enum and exception rendering with the linked+ * library's public descriptor table, including its deliberately sparse codes. */+#include <librdkafka/rdkafka.h>+#include <stddef.h>+int rdkafka_hs_test_error_count(void) {+ const struct rd_kafka_err_desc *descriptors; size_t size; int count = 0;+ rd_kafka_get_err_descs(&descriptors, &size);+ for (size_t i = 0; i < size; ++i) if (descriptors[i].name && descriptors[i].desc) count++;+ return count;+}+static const struct rd_kafka_err_desc *at(int index) {+ const struct rd_kafka_err_desc *descriptors; size_t size;+ rd_kafka_get_err_descs(&descriptors, &size);+ for (size_t i = 0; i < size; ++i) if (descriptors[i].name && descriptors[i].desc && index-- == 0) return &descriptors[i];+ return NULL;+}+int rdkafka_hs_test_error_code(int index) { return at(index)->code; }+const char *rdkafka_hs_test_error_name(int index) { return at(index)->name; }+const char *rdkafka_hs_test_error_description(int index) { return at(index)->desc; }+int rdkafka_hs_test_error_sentinel(int index) {+ return index == 0 ? RD_KAFKA_RESP_ERR__BEGIN : index == 1 ? RD_KAFKA_RESP_ERR__END : RD_KAFKA_RESP_ERR_END_ALL;+}