@ohos-ports/confluentinc-kafka-javascript 1.10.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +457 -0
- package/LICENSE.kafkajs +31 -0
- package/LICENSE.node-rdkafka +25 -0
- package/LICENSE.txt +20 -0
- package/README.md +133 -0
- package/binding.gyp +184 -0
- package/build/Release/confluent-kafka-javascript.node +0 -0
- package/build/deps/librdkafka++.so.1 +0 -0
- package/build/deps/librdkafka.Makefile +6 -0
- package/build/deps/librdkafka.so.1 +0 -0
- package/build/deps/librdkafka.target.mk +55 -0
- package/deps/librdkafka/.clang-format +136 -0
- package/deps/librdkafka/.clang-format-cpp +103 -0
- package/deps/librdkafka/.dir-locals.el +10 -0
- package/deps/librdkafka/.formatignore +35 -0
- package/deps/librdkafka/.gdbmacros +19 -0
- package/deps/librdkafka/CHANGELOG.md +2477 -0
- package/deps/librdkafka/CMakeLists.txt +291 -0
- package/deps/librdkafka/CODE_OF_CONDUCT.md +46 -0
- package/deps/librdkafka/CONFIGURATION.md +212 -0
- package/deps/librdkafka/CONTRIBUTING.md +431 -0
- package/deps/librdkafka/Doxyfile +2375 -0
- package/deps/librdkafka/INTRODUCTION.md +2752 -0
- package/deps/librdkafka/LICENSE +26 -0
- package/deps/librdkafka/LICENSE.cjson +22 -0
- package/deps/librdkafka/LICENSE.crc32c +28 -0
- package/deps/librdkafka/LICENSE.fnv1a +18 -0
- package/deps/librdkafka/LICENSE.hdrhistogram +27 -0
- package/deps/librdkafka/LICENSE.lz4 +26 -0
- package/deps/librdkafka/LICENSE.murmur2 +25 -0
- package/deps/librdkafka/LICENSE.nanopb +22 -0
- package/deps/librdkafka/LICENSE.opentelemetry +203 -0
- package/deps/librdkafka/LICENSE.pycrc +23 -0
- package/deps/librdkafka/LICENSE.queue +31 -0
- package/deps/librdkafka/LICENSE.regexp +5 -0
- package/deps/librdkafka/LICENSE.snappy +36 -0
- package/deps/librdkafka/LICENSE.tinycthread +26 -0
- package/deps/librdkafka/LICENSE.wingetopt +49 -0
- package/deps/librdkafka/LICENSES.txt +625 -0
- package/deps/librdkafka/Makefile +125 -0
- package/deps/librdkafka/README.md +201 -0
- package/deps/librdkafka/README.win32 +26 -0
- package/deps/librdkafka/STATISTICS.md +624 -0
- package/deps/librdkafka/configure +214 -0
- package/deps/librdkafka/configure.self +341 -0
- package/deps/librdkafka/dev-conf.sh +123 -0
- package/deps/librdkafka/lds-gen.py +73 -0
- package/deps/librdkafka/mainpage.doxy +40 -0
- package/deps/librdkafka/mklove/Makefile.base +329 -0
- package/deps/librdkafka/mklove/modules/configure.atomics +144 -0
- package/deps/librdkafka/mklove/modules/configure.base +2484 -0
- package/deps/librdkafka/mklove/modules/configure.builtin +70 -0
- package/deps/librdkafka/mklove/modules/configure.cc +186 -0
- package/deps/librdkafka/mklove/modules/configure.cxx +8 -0
- package/deps/librdkafka/mklove/modules/configure.fileversion +65 -0
- package/deps/librdkafka/mklove/modules/configure.gitversion +29 -0
- package/deps/librdkafka/mklove/modules/configure.good_cflags +18 -0
- package/deps/librdkafka/mklove/modules/configure.host +132 -0
- package/deps/librdkafka/mklove/modules/configure.lib +49 -0
- package/deps/librdkafka/mklove/modules/configure.libcurl +99 -0
- package/deps/librdkafka/mklove/modules/configure.libsasl2 +36 -0
- package/deps/librdkafka/mklove/modules/configure.libssl +147 -0
- package/deps/librdkafka/mklove/modules/configure.libzstd +58 -0
- package/deps/librdkafka/mklove/modules/configure.parseversion +95 -0
- package/deps/librdkafka/mklove/modules/configure.pic +16 -0
- package/deps/librdkafka/mklove/modules/configure.socket +20 -0
- package/deps/librdkafka/mklove/modules/configure.zlib +61 -0
- package/deps/librdkafka/mklove/modules/patches/README.md +8 -0
- package/deps/librdkafka/mklove/modules/patches/libcurl.0000-no-runtime-linking-check.patch +11 -0
- package/deps/librdkafka/mklove/modules/patches/libssl.0000-osx-rand-include-fix-OpenSSL-PR16409.patch +56 -0
- package/deps/librdkafka/service.yml +182 -0
- package/deps/librdkafka/src/CMakeLists.txt +379 -0
- package/deps/librdkafka/src/Makefile +105 -0
- package/deps/librdkafka/src/README.lz4.md +30 -0
- package/deps/librdkafka/src/cJSON.c +3191 -0
- package/deps/librdkafka/src/cJSON.h +306 -0
- package/deps/librdkafka/src/crc32c.c +430 -0
- package/deps/librdkafka/src/crc32c.h +38 -0
- package/deps/librdkafka/src/generate_proto.sh +66 -0
- package/deps/librdkafka/src/librdkafka_cgrp_synch.png +0 -0
- package/deps/librdkafka/src/lz4.c +2727 -0
- package/deps/librdkafka/src/lz4.h +842 -0
- package/deps/librdkafka/src/lz4frame.c +2078 -0
- package/deps/librdkafka/src/lz4frame.h +692 -0
- package/deps/librdkafka/src/lz4frame_static.h +47 -0
- package/deps/librdkafka/src/lz4hc.c +1631 -0
- package/deps/librdkafka/src/lz4hc.h +413 -0
- package/deps/librdkafka/src/nanopb/pb.h +917 -0
- package/deps/librdkafka/src/nanopb/pb_common.c +388 -0
- package/deps/librdkafka/src/nanopb/pb_common.h +49 -0
- package/deps/librdkafka/src/nanopb/pb_decode.c +1727 -0
- package/deps/librdkafka/src/nanopb/pb_decode.h +193 -0
- package/deps/librdkafka/src/nanopb/pb_encode.c +1000 -0
- package/deps/librdkafka/src/nanopb/pb_encode.h +185 -0
- package/deps/librdkafka/src/opentelemetry/common.pb.c +32 -0
- package/deps/librdkafka/src/opentelemetry/common.pb.h +170 -0
- package/deps/librdkafka/src/opentelemetry/metrics.options +2 -0
- package/deps/librdkafka/src/opentelemetry/metrics.pb.c +67 -0
- package/deps/librdkafka/src/opentelemetry/metrics.pb.h +966 -0
- package/deps/librdkafka/src/opentelemetry/resource.pb.c +12 -0
- package/deps/librdkafka/src/opentelemetry/resource.pb.h +58 -0
- package/deps/librdkafka/src/queue.h +850 -0
- package/deps/librdkafka/src/rd.h +592 -0
- package/deps/librdkafka/src/rdaddr.c +255 -0
- package/deps/librdkafka/src/rdaddr.h +202 -0
- package/deps/librdkafka/src/rdatomic.h +262 -0
- package/deps/librdkafka/src/rdavg.h +260 -0
- package/deps/librdkafka/src/rdavl.c +210 -0
- package/deps/librdkafka/src/rdavl.h +250 -0
- package/deps/librdkafka/src/rdbase64.c +200 -0
- package/deps/librdkafka/src/rdbase64.h +43 -0
- package/deps/librdkafka/src/rdbuf.c +1884 -0
- package/deps/librdkafka/src/rdbuf.h +375 -0
- package/deps/librdkafka/src/rdcrc32.c +114 -0
- package/deps/librdkafka/src/rdcrc32.h +170 -0
- package/deps/librdkafka/src/rddl.c +179 -0
- package/deps/librdkafka/src/rddl.h +43 -0
- package/deps/librdkafka/src/rdendian.h +175 -0
- package/deps/librdkafka/src/rdfloat.h +67 -0
- package/deps/librdkafka/src/rdfnv1a.c +113 -0
- package/deps/librdkafka/src/rdfnv1a.h +35 -0
- package/deps/librdkafka/src/rdgz.c +120 -0
- package/deps/librdkafka/src/rdgz.h +46 -0
- package/deps/librdkafka/src/rdhdrhistogram.c +721 -0
- package/deps/librdkafka/src/rdhdrhistogram.h +87 -0
- package/deps/librdkafka/src/rdhttp.c +831 -0
- package/deps/librdkafka/src/rdhttp.h +101 -0
- package/deps/librdkafka/src/rdinterval.h +177 -0
- package/deps/librdkafka/src/rdkafka.c +7287 -0
- package/deps/librdkafka/src/rdkafka.h +11795 -0
- package/deps/librdkafka/src/rdkafka_admin.c +10165 -0
- package/deps/librdkafka/src/rdkafka_admin.h +658 -0
- package/deps/librdkafka/src/rdkafka_assignment.c +1282 -0
- package/deps/librdkafka/src/rdkafka_assignment.h +73 -0
- package/deps/librdkafka/src/rdkafka_assignor.c +1800 -0
- package/deps/librdkafka/src/rdkafka_assignor.h +402 -0
- package/deps/librdkafka/src/rdkafka_aux.c +409 -0
- package/deps/librdkafka/src/rdkafka_aux.h +174 -0
- package/deps/librdkafka/src/rdkafka_background.c +222 -0
- package/deps/librdkafka/src/rdkafka_broker.c +6736 -0
- package/deps/librdkafka/src/rdkafka_broker.h +851 -0
- package/deps/librdkafka/src/rdkafka_buf.c +543 -0
- package/deps/librdkafka/src/rdkafka_buf.h +1525 -0
- package/deps/librdkafka/src/rdkafka_cert.c +576 -0
- package/deps/librdkafka/src/rdkafka_cert.h +62 -0
- package/deps/librdkafka/src/rdkafka_cgrp.c +8310 -0
- package/deps/librdkafka/src/rdkafka_cgrp.h +589 -0
- package/deps/librdkafka/src/rdkafka_conf.c +5177 -0
- package/deps/librdkafka/src/rdkafka_conf.h +746 -0
- package/deps/librdkafka/src/rdkafka_confval.h +97 -0
- package/deps/librdkafka/src/rdkafka_coord.c +623 -0
- package/deps/librdkafka/src/rdkafka_coord.h +132 -0
- package/deps/librdkafka/src/rdkafka_error.c +228 -0
- package/deps/librdkafka/src/rdkafka_error.h +80 -0
- package/deps/librdkafka/src/rdkafka_event.c +502 -0
- package/deps/librdkafka/src/rdkafka_event.h +126 -0
- package/deps/librdkafka/src/rdkafka_feature.c +898 -0
- package/deps/librdkafka/src/rdkafka_feature.h +104 -0
- package/deps/librdkafka/src/rdkafka_fetcher.c +3820 -0
- package/deps/librdkafka/src/rdkafka_fetcher.h +62 -0
- package/deps/librdkafka/src/rdkafka_header.c +220 -0
- package/deps/librdkafka/src/rdkafka_header.h +76 -0
- package/deps/librdkafka/src/rdkafka_idempotence.c +807 -0
- package/deps/librdkafka/src/rdkafka_idempotence.h +144 -0
- package/deps/librdkafka/src/rdkafka_int.h +1505 -0
- package/deps/librdkafka/src/rdkafka_interceptor.c +842 -0
- package/deps/librdkafka/src/rdkafka_interceptor.h +104 -0
- package/deps/librdkafka/src/rdkafka_lz4.c +450 -0
- package/deps/librdkafka/src/rdkafka_lz4.h +49 -0
- package/deps/librdkafka/src/rdkafka_metadata.c +2347 -0
- package/deps/librdkafka/src/rdkafka_metadata.h +350 -0
- package/deps/librdkafka/src/rdkafka_metadata_cache.c +1183 -0
- package/deps/librdkafka/src/rdkafka_mock.c +4514 -0
- package/deps/librdkafka/src/rdkafka_mock.h +867 -0
- package/deps/librdkafka/src/rdkafka_mock_cgrp.c +1877 -0
- package/deps/librdkafka/src/rdkafka_mock_handlers.c +5255 -0
- package/deps/librdkafka/src/rdkafka_mock_int.h +1005 -0
- package/deps/librdkafka/src/rdkafka_mock_sharegrp.c +1207 -0
- package/deps/librdkafka/src/rdkafka_msg.c +2619 -0
- package/deps/librdkafka/src/rdkafka_msg.h +629 -0
- package/deps/librdkafka/src/rdkafka_msgbatch.h +62 -0
- package/deps/librdkafka/src/rdkafka_msgset.h +105 -0
- package/deps/librdkafka/src/rdkafka_msgset_reader.c +2099 -0
- package/deps/librdkafka/src/rdkafka_msgset_writer.c +1474 -0
- package/deps/librdkafka/src/rdkafka_offset.c +1565 -0
- package/deps/librdkafka/src/rdkafka_offset.h +150 -0
- package/deps/librdkafka/src/rdkafka_op.c +1219 -0
- package/deps/librdkafka/src/rdkafka_op.h +1065 -0
- package/deps/librdkafka/src/rdkafka_partition.c +5109 -0
- package/deps/librdkafka/src/rdkafka_partition.h +1215 -0
- package/deps/librdkafka/src/rdkafka_pattern.c +228 -0
- package/deps/librdkafka/src/rdkafka_pattern.h +70 -0
- package/deps/librdkafka/src/rdkafka_plugin.c +213 -0
- package/deps/librdkafka/src/rdkafka_plugin.h +41 -0
- package/deps/librdkafka/src/rdkafka_proto.h +739 -0
- package/deps/librdkafka/src/rdkafka_protocol.h +131 -0
- package/deps/librdkafka/src/rdkafka_queue.c +1351 -0
- package/deps/librdkafka/src/rdkafka_queue.h +1235 -0
- package/deps/librdkafka/src/rdkafka_range_assignor.c +1748 -0
- package/deps/librdkafka/src/rdkafka_request.c +7298 -0
- package/deps/librdkafka/src/rdkafka_request.h +761 -0
- package/deps/librdkafka/src/rdkafka_roundrobin_assignor.c +123 -0
- package/deps/librdkafka/src/rdkafka_sasl.c +589 -0
- package/deps/librdkafka/src/rdkafka_sasl.h +63 -0
- package/deps/librdkafka/src/rdkafka_sasl_cyrus.c +722 -0
- package/deps/librdkafka/src/rdkafka_sasl_int.h +89 -0
- package/deps/librdkafka/src/rdkafka_sasl_oauthbearer.c +1833 -0
- package/deps/librdkafka/src/rdkafka_sasl_oauthbearer.h +52 -0
- package/deps/librdkafka/src/rdkafka_sasl_oauthbearer_oidc.c +1827 -0
- package/deps/librdkafka/src/rdkafka_sasl_oauthbearer_oidc.h +52 -0
- package/deps/librdkafka/src/rdkafka_sasl_plain.c +142 -0
- package/deps/librdkafka/src/rdkafka_sasl_scram.c +858 -0
- package/deps/librdkafka/src/rdkafka_sasl_win32.c +550 -0
- package/deps/librdkafka/src/rdkafka_share_acknowledgement.c +1445 -0
- package/deps/librdkafka/src/rdkafka_share_acknowledgement.h +373 -0
- package/deps/librdkafka/src/rdkafka_ssl.c +2235 -0
- package/deps/librdkafka/src/rdkafka_ssl.h +86 -0
- package/deps/librdkafka/src/rdkafka_sticky_assignor.c +4785 -0
- package/deps/librdkafka/src/rdkafka_subscription.c +411 -0
- package/deps/librdkafka/src/rdkafka_telemetry.c +761 -0
- package/deps/librdkafka/src/rdkafka_telemetry.h +52 -0
- package/deps/librdkafka/src/rdkafka_telemetry_decode.c +1307 -0
- package/deps/librdkafka/src/rdkafka_telemetry_decode.h +59 -0
- package/deps/librdkafka/src/rdkafka_telemetry_encode.c +1309 -0
- package/deps/librdkafka/src/rdkafka_telemetry_encode.h +459 -0
- package/deps/librdkafka/src/rdkafka_timer.c +407 -0
- package/deps/librdkafka/src/rdkafka_timer.h +117 -0
- package/deps/librdkafka/src/rdkafka_topic.c +2382 -0
- package/deps/librdkafka/src/rdkafka_topic.h +369 -0
- package/deps/librdkafka/src/rdkafka_transport.c +1309 -0
- package/deps/librdkafka/src/rdkafka_transport.h +99 -0
- package/deps/librdkafka/src/rdkafka_transport_int.h +100 -0
- package/deps/librdkafka/src/rdkafka_txnmgr.c +3256 -0
- package/deps/librdkafka/src/rdkafka_txnmgr.h +171 -0
- package/deps/librdkafka/src/rdkafka_zstd.c +226 -0
- package/deps/librdkafka/src/rdkafka_zstd.h +57 -0
- package/deps/librdkafka/src/rdlist.c +593 -0
- package/deps/librdkafka/src/rdlist.h +444 -0
- package/deps/librdkafka/src/rdlog.c +89 -0
- package/deps/librdkafka/src/rdlog.h +41 -0
- package/deps/librdkafka/src/rdmap.c +508 -0
- package/deps/librdkafka/src/rdmap.h +492 -0
- package/deps/librdkafka/src/rdmurmur2.c +167 -0
- package/deps/librdkafka/src/rdmurmur2.h +35 -0
- package/deps/librdkafka/src/rdports.c +61 -0
- package/deps/librdkafka/src/rdports.h +38 -0
- package/deps/librdkafka/src/rdposix.h +250 -0
- package/deps/librdkafka/src/rdrand.c +151 -0
- package/deps/librdkafka/src/rdrand.h +72 -0
- package/deps/librdkafka/src/rdregex.c +156 -0
- package/deps/librdkafka/src/rdregex.h +43 -0
- package/deps/librdkafka/src/rdsignal.h +57 -0
- package/deps/librdkafka/src/rdstring.c +645 -0
- package/deps/librdkafka/src/rdstring.h +98 -0
- package/deps/librdkafka/src/rdsysqueue.h +404 -0
- package/deps/librdkafka/src/rdtime.h +356 -0
- package/deps/librdkafka/src/rdtypes.h +86 -0
- package/deps/librdkafka/src/rdunittest.c +564 -0
- package/deps/librdkafka/src/rdunittest.h +232 -0
- package/deps/librdkafka/src/rdunittest_acknowledge.c +1177 -0
- package/deps/librdkafka/src/rdunittest_fetcher.c +1211 -0
- package/deps/librdkafka/src/rdunittest_msgset_errors.c +1521 -0
- package/deps/librdkafka/src/rdvarint.c +134 -0
- package/deps/librdkafka/src/rdvarint.h +165 -0
- package/deps/librdkafka/src/rdwin32.h +382 -0
- package/deps/librdkafka/src/rdxxhash.c +1030 -0
- package/deps/librdkafka/src/rdxxhash.h +328 -0
- package/deps/librdkafka/src/regexp.c +1352 -0
- package/deps/librdkafka/src/regexp.h +41 -0
- package/deps/librdkafka/src/snappy.c +1866 -0
- package/deps/librdkafka/src/snappy.h +62 -0
- package/deps/librdkafka/src/snappy_compat.h +138 -0
- package/deps/librdkafka/src/statistics_schema.json +444 -0
- package/deps/librdkafka/src/tinycthread.c +932 -0
- package/deps/librdkafka/src/tinycthread.h +503 -0
- package/deps/librdkafka/src/tinycthread_extra.c +210 -0
- package/deps/librdkafka/src/tinycthread_extra.h +218 -0
- package/deps/librdkafka/src/win32_config.h +58 -0
- package/deps/librdkafka/src-cpp/CMakeLists.txt +90 -0
- package/deps/librdkafka/src-cpp/ConfImpl.cpp +84 -0
- package/deps/librdkafka/src-cpp/ConsumerImpl.cpp +244 -0
- package/deps/librdkafka/src-cpp/HandleImpl.cpp +436 -0
- package/deps/librdkafka/src-cpp/HeadersImpl.cpp +48 -0
- package/deps/librdkafka/src-cpp/KafkaConsumerImpl.cpp +296 -0
- package/deps/librdkafka/src-cpp/Makefile +55 -0
- package/deps/librdkafka/src-cpp/MessageImpl.cpp +38 -0
- package/deps/librdkafka/src-cpp/MetadataImpl.cpp +170 -0
- package/deps/librdkafka/src-cpp/ProducerImpl.cpp +197 -0
- package/deps/librdkafka/src-cpp/QueueImpl.cpp +70 -0
- package/deps/librdkafka/src-cpp/README.md +16 -0
- package/deps/librdkafka/src-cpp/RdKafka.cpp +59 -0
- package/deps/librdkafka/src-cpp/TopicImpl.cpp +124 -0
- package/deps/librdkafka/src-cpp/TopicPartitionImpl.cpp +57 -0
- package/deps/librdkafka/src-cpp/rdkafkacpp.h +3797 -0
- package/deps/librdkafka/src-cpp/rdkafkacpp_int.h +1641 -0
- package/deps/librdkafka/tests/0000-unittests.c +72 -0
- package/deps/librdkafka/tests/0001-multiobj.c +102 -0
- package/deps/librdkafka/tests/0002-unkpart.c +244 -0
- package/deps/librdkafka/tests/0003-msgmaxsize.c +173 -0
- package/deps/librdkafka/tests/0004-conf.c +934 -0
- package/deps/librdkafka/tests/0005-order.c +133 -0
- package/deps/librdkafka/tests/0006-symbols.c +163 -0
- package/deps/librdkafka/tests/0007-autotopic.c +136 -0
- package/deps/librdkafka/tests/0008-reqacks.c +179 -0
- package/deps/librdkafka/tests/0009-mock_cluster.c +272 -0
- package/deps/librdkafka/tests/0011-produce_batch.c +753 -0
- package/deps/librdkafka/tests/0012-produce_consume.c +537 -0
- package/deps/librdkafka/tests/0013-null-msgs.c +473 -0
- package/deps/librdkafka/tests/0014-reconsume-191.c +512 -0
- package/deps/librdkafka/tests/0015-offset_seeks.c +172 -0
- package/deps/librdkafka/tests/0016-client_swname.c +181 -0
- package/deps/librdkafka/tests/0017-compression.c +140 -0
- package/deps/librdkafka/tests/0018-cgrp_term.c +444 -0
- package/deps/librdkafka/tests/0019-list_groups.c +289 -0
- package/deps/librdkafka/tests/0020-destroy_hang.c +162 -0
- package/deps/librdkafka/tests/0021-rkt_destroy.c +72 -0
- package/deps/librdkafka/tests/0022-consume_batch.c +331 -0
- package/deps/librdkafka/tests/0025-timers.c +147 -0
- package/deps/librdkafka/tests/0026-consume_pause.c +547 -0
- package/deps/librdkafka/tests/0028-long_topicnames.c +79 -0
- package/deps/librdkafka/tests/0029-assign_offset.c +202 -0
- package/deps/librdkafka/tests/0030-offset_commit.c +589 -0
- package/deps/librdkafka/tests/0031-get_offsets.c +235 -0
- package/deps/librdkafka/tests/0033-regex_subscribe.c +536 -0
- package/deps/librdkafka/tests/0034-offset_reset.c +398 -0
- package/deps/librdkafka/tests/0035-api_version.c +73 -0
- package/deps/librdkafka/tests/0036-partial_fetch.c +87 -0
- package/deps/librdkafka/tests/0037-destroy_hang_local.c +85 -0
- package/deps/librdkafka/tests/0038-performance.c +121 -0
- package/deps/librdkafka/tests/0039-event.c +284 -0
- package/deps/librdkafka/tests/0040-io_event.c +257 -0
- package/deps/librdkafka/tests/0041-fetch_max_bytes.c +97 -0
- package/deps/librdkafka/tests/0042-many_topics.c +252 -0
- package/deps/librdkafka/tests/0043-no_connection.c +77 -0
- package/deps/librdkafka/tests/0044-partition_cnt.c +94 -0
- package/deps/librdkafka/tests/0045-subscribe_update.c +1010 -0
- package/deps/librdkafka/tests/0046-rkt_cache.c +65 -0
- package/deps/librdkafka/tests/0047-partial_buf_tmout.c +98 -0
- package/deps/librdkafka/tests/0048-partitioner.c +283 -0
- package/deps/librdkafka/tests/0049-consume_conn_close.c +162 -0
- package/deps/librdkafka/tests/0050-subscribe_adds.c +145 -0
- package/deps/librdkafka/tests/0051-assign_adds.c +126 -0
- package/deps/librdkafka/tests/0052-msg_timestamps.c +238 -0
- package/deps/librdkafka/tests/0053-stats_cb.cpp +527 -0
- package/deps/librdkafka/tests/0054-offset_time.cpp +236 -0
- package/deps/librdkafka/tests/0055-producer_latency.c +539 -0
- package/deps/librdkafka/tests/0056-balanced_group_mt.c +315 -0
- package/deps/librdkafka/tests/0057-invalid_topic.cpp +112 -0
- package/deps/librdkafka/tests/0058-log.cpp +123 -0
- package/deps/librdkafka/tests/0059-bsearch.cpp +241 -0
- package/deps/librdkafka/tests/0060-op_prio.cpp +163 -0
- package/deps/librdkafka/tests/0061-consumer_lag.cpp +295 -0
- package/deps/librdkafka/tests/0062-stats_event.c +126 -0
- package/deps/librdkafka/tests/0063-clusterid.cpp +180 -0
- package/deps/librdkafka/tests/0064-interceptors.c +529 -0
- package/deps/librdkafka/tests/0065-yield.cpp +140 -0
- package/deps/librdkafka/tests/0066-plugins.cpp +143 -0
- package/deps/librdkafka/tests/0067-empty_topic.cpp +151 -0
- package/deps/librdkafka/tests/0068-produce_timeout.c +136 -0
- package/deps/librdkafka/tests/0069-consumer_add_parts.c +119 -0
- package/deps/librdkafka/tests/0070-null_empty.cpp +197 -0
- package/deps/librdkafka/tests/0072-headers_ut.c +448 -0
- package/deps/librdkafka/tests/0073-headers.c +381 -0
- package/deps/librdkafka/tests/0074-producev.c +87 -0
- package/deps/librdkafka/tests/0075-retry.c +290 -0
- package/deps/librdkafka/tests/0076-produce_retry.c +452 -0
- package/deps/librdkafka/tests/0077-compaction.c +366 -0
- package/deps/librdkafka/tests/0078-c_from_cpp.cpp +96 -0
- package/deps/librdkafka/tests/0079-fork.c +93 -0
- package/deps/librdkafka/tests/0080-admin_ut.c +3095 -0
- package/deps/librdkafka/tests/0081-admin.c +5633 -0
- package/deps/librdkafka/tests/0082-fetch_max_bytes.cpp +137 -0
- package/deps/librdkafka/tests/0083-cb_event.c +233 -0
- package/deps/librdkafka/tests/0084-destroy_flags.c +208 -0
- package/deps/librdkafka/tests/0085-headers.cpp +392 -0
- package/deps/librdkafka/tests/0086-purge.c +368 -0
- package/deps/librdkafka/tests/0088-produce_metadata_timeout.c +162 -0
- package/deps/librdkafka/tests/0089-max_poll_interval.c +511 -0
- package/deps/librdkafka/tests/0090-idempotence.c +171 -0
- package/deps/librdkafka/tests/0091-max_poll_interval_timeout.c +295 -0
- package/deps/librdkafka/tests/0092-mixed_msgver.c +103 -0
- package/deps/librdkafka/tests/0093-holb.c +200 -0
- package/deps/librdkafka/tests/0094-idempotence_msg_timeout.c +231 -0
- package/deps/librdkafka/tests/0095-all_brokers_down.cpp +122 -0
- package/deps/librdkafka/tests/0097-ssl_verify.cpp +674 -0
- package/deps/librdkafka/tests/0098-consumer-txn.cpp +1218 -0
- package/deps/librdkafka/tests/0099-commit_metadata.c +194 -0
- package/deps/librdkafka/tests/0100-thread_interceptors.cpp +195 -0
- package/deps/librdkafka/tests/0101-fetch-from-follower.cpp +446 -0
- package/deps/librdkafka/tests/0102-static_group_rebalance.c +836 -0
- package/deps/librdkafka/tests/0103-transactions.c +1383 -0
- package/deps/librdkafka/tests/0104-fetch_from_follower_mock.c +625 -0
- package/deps/librdkafka/tests/0105-transactions_mock.c +3930 -0
- package/deps/librdkafka/tests/0106-cgrp_sess_timeout.c +318 -0
- package/deps/librdkafka/tests/0107-topic_recreate.c +259 -0
- package/deps/librdkafka/tests/0109-auto_create_topics.cpp +278 -0
- package/deps/librdkafka/tests/0110-batch_size.cpp +182 -0
- package/deps/librdkafka/tests/0111-delay_create_topics.cpp +127 -0
- package/deps/librdkafka/tests/0112-assign_unknown_part.c +87 -0
- package/deps/librdkafka/tests/0113-cooperative_rebalance.cpp +3473 -0
- package/deps/librdkafka/tests/0114-sticky_partitioning.cpp +176 -0
- package/deps/librdkafka/tests/0115-producer_auth.cpp +182 -0
- package/deps/librdkafka/tests/0116-kafkaconsumer_close.cpp +216 -0
- package/deps/librdkafka/tests/0117-mock_errors.c +331 -0
- package/deps/librdkafka/tests/0118-commit_rebalance.c +154 -0
- package/deps/librdkafka/tests/0119-consumer_auth.cpp +167 -0
- package/deps/librdkafka/tests/0120-asymmetric_subscription.c +185 -0
- package/deps/librdkafka/tests/0121-clusterid.c +115 -0
- package/deps/librdkafka/tests/0122-buffer_cleaning_after_rebalance.c +227 -0
- package/deps/librdkafka/tests/0123-connections_max_idle.c +98 -0
- package/deps/librdkafka/tests/0124-openssl_invalid_engine.c +69 -0
- package/deps/librdkafka/tests/0125-immediate_flush.c +144 -0
- package/deps/librdkafka/tests/0126-oauthbearer_oidc.c +1164 -0
- package/deps/librdkafka/tests/0127-fetch_queue_backoff.cpp +165 -0
- package/deps/librdkafka/tests/0128-sasl_callback_queue.cpp +217 -0
- package/deps/librdkafka/tests/0129-fetch_aborted_msgs.c +79 -0
- package/deps/librdkafka/tests/0130-store_offsets.c +178 -0
- package/deps/librdkafka/tests/0131-connect_timeout.c +81 -0
- package/deps/librdkafka/tests/0132-strategy_ordering.c +179 -0
- package/deps/librdkafka/tests/0133-ssl_keys.c +150 -0
- package/deps/librdkafka/tests/0134-ssl_provider.c +92 -0
- package/deps/librdkafka/tests/0135-sasl_credentials.cpp +279 -0
- package/deps/librdkafka/tests/0136-resolve_cb.c +181 -0
- package/deps/librdkafka/tests/0137-barrier_batch_consume.c +752 -0
- package/deps/librdkafka/tests/0138-admin_mock.c +281 -0
- package/deps/librdkafka/tests/0139-offset_validation_mock.c +950 -0
- package/deps/librdkafka/tests/0140-commit_metadata.cpp +108 -0
- package/deps/librdkafka/tests/0142-reauthentication.c +931 -0
- package/deps/librdkafka/tests/0143-exponential_backoff_mock.c +552 -0
- package/deps/librdkafka/tests/0144-idempotence_mock.c +373 -0
- package/deps/librdkafka/tests/0145-pause_resume_mock.c +119 -0
- package/deps/librdkafka/tests/0146-metadata_mock.c +505 -0
- package/deps/librdkafka/tests/0147-consumer_group_consumer_mock.c +1210 -0
- package/deps/librdkafka/tests/0148-offset_fetch_commit_error_mock.c +569 -0
- package/deps/librdkafka/tests/0149-broker-same-host-port.c +140 -0
- package/deps/librdkafka/tests/0150-telemetry_mock.c +651 -0
- package/deps/librdkafka/tests/0151-purge-brokers.c +566 -0
- package/deps/librdkafka/tests/0152-rebootstrap.c +59 -0
- package/deps/librdkafka/tests/0153-memberid.c +128 -0
- package/deps/librdkafka/tests/0155-share_group_heartbeat_mock.c +2695 -0
- package/deps/librdkafka/tests/0156-share_consumer_fetch_mock.c +1551 -0
- package/deps/librdkafka/tests/0157-share_consumer_ack_mock.c +1788 -0
- package/deps/librdkafka/tests/0158-share_consumer_transactions_mock.c +467 -0
- package/deps/librdkafka/tests/0170-share_consumer_subscription.c +2192 -0
- package/deps/librdkafka/tests/0171-share_consumer_consume.c +2150 -0
- package/deps/librdkafka/tests/0172-share_consumer_acknowledge.c +1919 -0
- package/deps/librdkafka/tests/0173-share_consumer_commit_async.c +2735 -0
- package/deps/librdkafka/tests/0174-share_consumer_concurrency.c +1434 -0
- package/deps/librdkafka/tests/0175-share_consumer_groups.c +574 -0
- package/deps/librdkafka/tests/0176-share_consumer_commit_sync.c +2986 -0
- package/deps/librdkafka/tests/0177-share_consumer_transactions.c +1815 -0
- package/deps/librdkafka/tests/0178-share_consumer_close.c +2102 -0
- package/deps/librdkafka/tests/0179-share_consumer_destroy.c +2482 -0
- package/deps/librdkafka/tests/0180-share_consumer_config.c +1677 -0
- package/deps/librdkafka/tests/0181-share_consumer_topic_delete.c +354 -0
- package/deps/librdkafka/tests/0182-share_consumer_error_handling_mock.c +3358 -0
- package/deps/librdkafka/tests/0183-share_consumer_leader_change_mock.c +1234 -0
- package/deps/librdkafka/tests/0184-share_consumer_topic_recreate.c +1356 -0
- package/deps/librdkafka/tests/0185-share_consumer_max_poll_interval.c +557 -0
- package/deps/librdkafka/tests/0186-share_consumer_fatal_error.c +360 -0
- package/deps/librdkafka/tests/0190-share_consumer_telemetry.c +387 -0
- package/deps/librdkafka/tests/1000-unktopic.c +164 -0
- package/deps/librdkafka/tests/8000-idle.cpp +60 -0
- package/deps/librdkafka/tests/8001-fetch_from_follower_mock_manual.c +113 -0
- package/deps/librdkafka/tests/CMakeLists.txt +193 -0
- package/deps/librdkafka/tests/LibrdkafkaTestApp.py +291 -0
- package/deps/librdkafka/tests/Makefile +182 -0
- package/deps/librdkafka/tests/README.md +514 -0
- package/deps/librdkafka/tests/autotest.sh +33 -0
- package/deps/librdkafka/tests/backtrace.gdb +30 -0
- package/deps/librdkafka/tests/broker_version_tests.py +315 -0
- package/deps/librdkafka/tests/buildbox.sh +17 -0
- package/deps/librdkafka/tests/cleanup-checker-tests.sh +20 -0
- package/deps/librdkafka/tests/cluster_testing.py +203 -0
- package/deps/librdkafka/tests/delete-test-topics.sh +56 -0
- package/deps/librdkafka/tests/fixtures/oauthbearer/jwt_assertion_template.json +10 -0
- package/deps/librdkafka/tests/fixtures/ssl/Makefile +8 -0
- package/deps/librdkafka/tests/fixtures/ssl/README.md +13 -0
- package/deps/librdkafka/tests/fixtures/ssl/client.keystore.intermediate.p12 +0 -0
- package/deps/librdkafka/tests/fixtures/ssl/client.keystore.p12 +0 -0
- package/deps/librdkafka/tests/fixtures/ssl/client2.certificate.intermediate.pem +72 -0
- package/deps/librdkafka/tests/fixtures/ssl/client2.certificate.pem +50 -0
- package/deps/librdkafka/tests/fixtures/ssl/client2.intermediate.key +46 -0
- package/deps/librdkafka/tests/fixtures/ssl/client2.key +46 -0
- package/deps/librdkafka/tests/fixtures/ssl/create_keys.sh +168 -0
- package/deps/librdkafka/tests/fuzzers/Makefile +12 -0
- package/deps/librdkafka/tests/fuzzers/README.md +31 -0
- package/deps/librdkafka/tests/fuzzers/fuzz_regex.c +74 -0
- package/deps/librdkafka/tests/fuzzers/helpers.h +90 -0
- package/deps/librdkafka/tests/gen-ssl-certs.sh +165 -0
- package/deps/librdkafka/tests/interactive_broker_version.py +170 -0
- package/deps/librdkafka/tests/interceptor_test/CMakeLists.txt +16 -0
- package/deps/librdkafka/tests/interceptor_test/Makefile +22 -0
- package/deps/librdkafka/tests/interceptor_test/interceptor_test.c +314 -0
- package/deps/librdkafka/tests/interceptor_test/interceptor_test.h +54 -0
- package/deps/librdkafka/tests/java/IncrementalRebalanceCli.java +97 -0
- package/deps/librdkafka/tests/java/Makefile +13 -0
- package/deps/librdkafka/tests/java/Murmur2Cli.java +46 -0
- package/deps/librdkafka/tests/java/README.md +14 -0
- package/deps/librdkafka/tests/java/TransactionProducerCli.java +162 -0
- package/deps/librdkafka/tests/java/run-class.sh +11 -0
- package/deps/librdkafka/tests/librdkafka.suppressions +483 -0
- package/deps/librdkafka/tests/lz4_manual_test.sh +59 -0
- package/deps/librdkafka/tests/multi-broker-version-test.sh +50 -0
- package/deps/librdkafka/tests/parse-refcnt.sh +43 -0
- package/deps/librdkafka/tests/performance_plot.py +115 -0
- package/deps/librdkafka/tests/plugin_test/Makefile +19 -0
- package/deps/librdkafka/tests/plugin_test/plugin_test.c +58 -0
- package/deps/librdkafka/tests/requirements.txt +2 -0
- package/deps/librdkafka/tests/run-all-tests.sh +81 -0
- package/deps/librdkafka/tests/run-consumer-tests.sh +16 -0
- package/deps/librdkafka/tests/run-producer-tests.sh +16 -0
- package/deps/librdkafka/tests/run-test-batches.py +157 -0
- package/deps/librdkafka/tests/run-test.sh +141 -0
- package/deps/librdkafka/tests/rusage.c +249 -0
- package/deps/librdkafka/tests/sasl_test.py +289 -0
- package/deps/librdkafka/tests/scenarios/README.md +6 -0
- package/deps/librdkafka/tests/scenarios/ak23.json +6 -0
- package/deps/librdkafka/tests/scenarios/default.json +5 -0
- package/deps/librdkafka/tests/scenarios/noautocreate.json +5 -0
- package/deps/librdkafka/tests/share_telemetry_verify/share-otel-collector-config.yaml +28 -0
- package/deps/librdkafka/tests/sockem.c +801 -0
- package/deps/librdkafka/tests/sockem.h +85 -0
- package/deps/librdkafka/tests/sockem_ctrl.c +145 -0
- package/deps/librdkafka/tests/sockem_ctrl.h +61 -0
- package/deps/librdkafka/tests/test.c +8376 -0
- package/deps/librdkafka/tests/test.conf.example +27 -0
- package/deps/librdkafka/tests/test.h +1150 -0
- package/deps/librdkafka/tests/testcpp.cpp +131 -0
- package/deps/librdkafka/tests/testcpp.h +388 -0
- package/deps/librdkafka/tests/testshared.h +416 -0
- package/deps/librdkafka/tests/tools/README.md +4 -0
- package/deps/librdkafka/tests/tools/stats/README.md +21 -0
- package/deps/librdkafka/tests/tools/stats/filter.jq +42 -0
- package/deps/librdkafka/tests/tools/stats/graph.py +150 -0
- package/deps/librdkafka/tests/tools/stats/requirements.txt +3 -0
- package/deps/librdkafka/tests/tools/stats/to_csv.py +124 -0
- package/deps/librdkafka/tests/trivup/trivup-0.15.0.tar.gz +0 -0
- package/deps/librdkafka/tests/until-fail.sh +87 -0
- package/deps/librdkafka/tests/xxxx-assign_partition.c +122 -0
- package/deps/librdkafka/tests/xxxx-metadata.cpp +159 -0
- package/deps/librdkafka/vcpkg.json +23 -0
- package/deps/librdkafka/win32/README.md +5 -0
- package/deps/librdkafka/win32/build-package.bat +3 -0
- package/deps/librdkafka/win32/build.bat +19 -0
- package/deps/librdkafka/win32/common.vcxproj +84 -0
- package/deps/librdkafka/win32/interceptor_test/interceptor_test.vcxproj +87 -0
- package/deps/librdkafka/win32/librdkafka.autopkg.template +54 -0
- package/deps/librdkafka/win32/librdkafka.master.testing.targets +13 -0
- package/deps/librdkafka/win32/librdkafka.sln +226 -0
- package/deps/librdkafka/win32/librdkafka.vcxproj +282 -0
- package/deps/librdkafka/win32/librdkafkacpp/librdkafkacpp.vcxproj +104 -0
- package/deps/librdkafka/win32/msbuild.ps1 +58 -0
- package/deps/librdkafka/win32/openssl_engine_example/openssl_engine_example.vcxproj +132 -0
- package/deps/librdkafka/win32/package-zip.ps1 +46 -0
- package/deps/librdkafka/win32/packages/repositories.config +4 -0
- package/deps/librdkafka/win32/push-package.bat +4 -0
- package/deps/librdkafka/win32/rdkafka_complex_consumer_example_cpp/rdkafka_complex_consumer_example_cpp.vcxproj +67 -0
- package/deps/librdkafka/win32/rdkafka_example/rdkafka_example.vcxproj +97 -0
- package/deps/librdkafka/win32/rdkafka_performance/rdkafka_performance.vcxproj +97 -0
- package/deps/librdkafka/win32/setup-msys2.ps1 +47 -0
- package/deps/librdkafka/win32/setup-vcpkg.ps1 +34 -0
- package/deps/librdkafka/win32/tests/test.conf.example +25 -0
- package/deps/librdkafka/win32/tests/tests.vcxproj +278 -0
- package/deps/librdkafka/win32/win_ssl_cert_store/win_ssl_cert_store.vcxproj +132 -0
- package/deps/librdkafka/win32/wingetopt.c +564 -0
- package/deps/librdkafka/win32/wingetopt.h +101 -0
- package/deps/librdkafka/win32/wintime.h +33 -0
- package/deps/librdkafka.gyp +83 -0
- package/deps/windows-install.py +80 -0
- package/index.d.ts +3 -0
- package/lib/admin.js +732 -0
- package/lib/client.js +679 -0
- package/lib/error.js +501 -0
- package/lib/index.js +8 -0
- package/lib/kafka-consumer-stream.js +399 -0
- package/lib/kafka-consumer.js +798 -0
- package/lib/kafkajs/_admin.js +1052 -0
- package/lib/kafkajs/_common.js +887 -0
- package/lib/kafkajs/_consumer.js +2156 -0
- package/lib/kafkajs/_consumer_cache.js +310 -0
- package/lib/kafkajs/_error.js +298 -0
- package/lib/kafkajs/_kafka.js +125 -0
- package/lib/kafkajs/_linked-list.js +220 -0
- package/lib/kafkajs/_producer.js +863 -0
- package/lib/kafkajs/index.js +5 -0
- package/lib/producer/high-level-producer.js +400 -0
- package/lib/producer-stream.js +337 -0
- package/lib/producer.js +405 -0
- package/lib/rdkafka.js +44 -0
- package/lib/tools/ref-counter.js +53 -0
- package/lib/topic-partition.js +91 -0
- package/lib/topic.js +43 -0
- package/lib/util.js +55 -0
- package/librdkafka.js +12 -0
- package/package.json +85 -0
- package/shim/source_location +54 -0
- package/src/admin.cc +1597 -0
- package/src/admin.h +112 -0
- package/src/binding.cc +76 -0
- package/src/binding.h +25 -0
- package/src/callbacks.cc +676 -0
- package/src/callbacks.h +302 -0
- package/src/common.cc +1628 -0
- package/src/common.h +192 -0
- package/src/config.cc +219 -0
- package/src/config.h +61 -0
- package/src/connection.cc +703 -0
- package/src/connection.h +117 -0
- package/src/errors.cc +119 -0
- package/src/errors.h +60 -0
- package/src/kafka-consumer.cc +1539 -0
- package/src/kafka-consumer.h +147 -0
- package/src/producer.cc +917 -0
- package/src/producer.h +124 -0
- package/src/topic.cc +173 -0
- package/src/topic.h +54 -0
- package/src/workers.cc +1714 -0
- package/src/workers.h +690 -0
- package/types/config.d.ts +1269 -0
- package/types/errors.d.ts +373 -0
- package/types/kafkajs.d.ts +568 -0
- package/types/rdkafka.d.ts +571 -0
- package/util/configure.js +32 -0
- package/util/generate-docs.sh +18 -0
- package/util/get-env.js +6 -0
- package/util/test-compile.js +11 -0
- package/util/test-producer-delivery.js +100 -0
|
@@ -0,0 +1,1551 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* librdkafka - Apache Kafka C library
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2025, Confluent Inc.
|
|
5
|
+
* All rights reserved.
|
|
6
|
+
*
|
|
7
|
+
* Redistribution and use in source and binary forms, with or without
|
|
8
|
+
* modification, are permitted provided that the following conditions are met:
|
|
9
|
+
*
|
|
10
|
+
* 1. Redistributions of source code must retain the above copyright notice,
|
|
11
|
+
* this list of conditions and the following disclaimer.
|
|
12
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
13
|
+
* this list of conditions and the following disclaimer in the documentation
|
|
14
|
+
* and/or other materials provided with the distribution.
|
|
15
|
+
*
|
|
16
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
17
|
+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
18
|
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
19
|
+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
20
|
+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
21
|
+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
22
|
+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
23
|
+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
24
|
+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
25
|
+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
26
|
+
* POSSIBILITY OF SUCH DAMAGE.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
#include "test.h"
|
|
30
|
+
|
|
31
|
+
#include "../src/rdkafka_proto.h"
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @name ShareFetch mock broker tests using the share consumer API.
|
|
35
|
+
*
|
|
36
|
+
* Exercises the ShareFetch path via mock broker. There is no coordinator
|
|
37
|
+
* or ShareAcknowledge support in the mock broker, so group management and
|
|
38
|
+
* ack-based state transitions are not validated here.
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
typedef struct test_ctx_s {
|
|
42
|
+
rd_kafka_t *producer;
|
|
43
|
+
rd_kafka_mock_cluster_t *mcluster;
|
|
44
|
+
const char *bootstraps;
|
|
45
|
+
} test_ctx_t;
|
|
46
|
+
|
|
47
|
+
static test_ctx_t test_ctx_new(void) {
|
|
48
|
+
test_ctx_t ctx;
|
|
49
|
+
rd_kafka_conf_t *conf;
|
|
50
|
+
char errstr[512];
|
|
51
|
+
|
|
52
|
+
memset(&ctx, 0, sizeof(ctx));
|
|
53
|
+
|
|
54
|
+
ctx.mcluster = test_mock_cluster_new(3, &ctx.bootstraps);
|
|
55
|
+
|
|
56
|
+
TEST_ASSERT(rd_kafka_mock_set_apiversion(
|
|
57
|
+
ctx.mcluster, RD_KAFKAP_ShareGroupHeartbeat, 1, 1) ==
|
|
58
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
59
|
+
"Failed to enable ShareGroupHeartbeat");
|
|
60
|
+
TEST_ASSERT(rd_kafka_mock_set_apiversion(ctx.mcluster,
|
|
61
|
+
RD_KAFKAP_ShareFetch, 1, 1) ==
|
|
62
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
63
|
+
"Failed to enable ShareFetch");
|
|
64
|
+
|
|
65
|
+
/* Set auto.offset.reset=earliest so tests that produce
|
|
66
|
+
* before consuming see all records. */
|
|
67
|
+
rd_kafka_mock_sharegroup_set_auto_offset_reset(ctx.mcluster, 1);
|
|
68
|
+
|
|
69
|
+
/* Create a producer targeting the mock cluster */
|
|
70
|
+
test_conf_init(&conf, NULL, 0);
|
|
71
|
+
test_conf_set(conf, "bootstrap.servers", ctx.bootstraps);
|
|
72
|
+
rd_kafka_conf_set_dr_msg_cb(conf, test_dr_msg_cb);
|
|
73
|
+
|
|
74
|
+
ctx.producer =
|
|
75
|
+
rd_kafka_new(RD_KAFKA_PRODUCER, conf, errstr, sizeof(errstr));
|
|
76
|
+
TEST_ASSERT(ctx.producer != NULL, "Failed to create producer: %s",
|
|
77
|
+
errstr);
|
|
78
|
+
|
|
79
|
+
return ctx;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
static void test_ctx_destroy(test_ctx_t *ctx) {
|
|
83
|
+
if (ctx->producer)
|
|
84
|
+
rd_kafka_destroy(ctx->producer);
|
|
85
|
+
if (ctx->mcluster)
|
|
86
|
+
test_mock_cluster_destroy(ctx->mcluster);
|
|
87
|
+
memset(ctx, 0, sizeof(*ctx));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
static rd_kafka_share_t *new_share_consumer(const char *bootstraps,
|
|
91
|
+
const char *group_id) {
|
|
92
|
+
rd_kafka_conf_t *conf;
|
|
93
|
+
rd_kafka_share_t *consumer;
|
|
94
|
+
|
|
95
|
+
test_conf_init(&conf, NULL, 0);
|
|
96
|
+
test_conf_set(conf, "bootstrap.servers", bootstraps);
|
|
97
|
+
test_conf_set(conf, "group.id", group_id);
|
|
98
|
+
|
|
99
|
+
consumer = rd_kafka_share_consumer_new(conf, NULL, 0);
|
|
100
|
+
TEST_ASSERT(consumer != NULL, "Failed to create share consumer");
|
|
101
|
+
return consumer;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
static void subscribe_topics(rd_kafka_share_t *consumer,
|
|
105
|
+
const char **topics,
|
|
106
|
+
int topic_cnt) {
|
|
107
|
+
rd_kafka_topic_partition_list_t *tpl =
|
|
108
|
+
rd_kafka_topic_partition_list_new(topic_cnt);
|
|
109
|
+
for (int i = 0; i < topic_cnt; i++) {
|
|
110
|
+
rd_kafka_topic_partition_list_add(tpl, topics[i],
|
|
111
|
+
RD_KAFKA_PARTITION_UA);
|
|
112
|
+
}
|
|
113
|
+
TEST_ASSERT(!rd_kafka_share_subscribe(consumer, tpl),
|
|
114
|
+
"Subscribe failed");
|
|
115
|
+
rd_kafka_topic_partition_list_destroy(tpl);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
static void do_test_basic_consume(void) {
|
|
119
|
+
const char *topic = "kip932_pos_basic";
|
|
120
|
+
const int msgcnt = 5;
|
|
121
|
+
test_ctx_t ctx = test_ctx_new();
|
|
122
|
+
rd_kafka_share_t *consumer;
|
|
123
|
+
int consumed;
|
|
124
|
+
|
|
125
|
+
SUB_TEST_QUICK();
|
|
126
|
+
|
|
127
|
+
TEST_ASSERT(rd_kafka_mock_topic_create(ctx.mcluster, topic, 1, 1) ==
|
|
128
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
129
|
+
"Failed to create mock topic");
|
|
130
|
+
test_produce_msgs_simple(ctx.producer, topic, RD_KAFKA_PARTITION_UA,
|
|
131
|
+
msgcnt);
|
|
132
|
+
|
|
133
|
+
consumer = new_share_consumer(ctx.bootstraps, "sg-pos-basic");
|
|
134
|
+
subscribe_topics(consumer, &topic, 1);
|
|
135
|
+
consumed = test_share_consume_msgs(consumer, msgcnt, 50, 500, NULL, 0);
|
|
136
|
+
|
|
137
|
+
test_share_consumer_close(consumer);
|
|
138
|
+
test_share_destroy(consumer);
|
|
139
|
+
test_ctx_destroy(&ctx);
|
|
140
|
+
|
|
141
|
+
TEST_ASSERT(consumed == msgcnt, "Expected %d consumed, got %d", msgcnt,
|
|
142
|
+
consumed);
|
|
143
|
+
SUB_TEST_PASS();
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
static void do_test_followup_fetch(void) {
|
|
147
|
+
const char *topic = "kip932_pos_followup";
|
|
148
|
+
test_ctx_t ctx = test_ctx_new();
|
|
149
|
+
rd_kafka_share_t *consumer;
|
|
150
|
+
int consumed;
|
|
151
|
+
|
|
152
|
+
SUB_TEST_QUICK();
|
|
153
|
+
|
|
154
|
+
TEST_ASSERT(rd_kafka_mock_topic_create(ctx.mcluster, topic, 1, 1) ==
|
|
155
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
156
|
+
"Failed to create mock topic");
|
|
157
|
+
test_produce_msgs_simple(ctx.producer, topic, RD_KAFKA_PARTITION_UA, 5);
|
|
158
|
+
|
|
159
|
+
consumer = new_share_consumer(ctx.bootstraps, "sg-pos-followup");
|
|
160
|
+
subscribe_topics(consumer, &topic, 1);
|
|
161
|
+
consumed = test_share_consume_msgs(consumer, 3, 30, 500, NULL, 0);
|
|
162
|
+
consumed += test_share_consume_msgs(consumer, 2, 30, 500, NULL, 0);
|
|
163
|
+
|
|
164
|
+
test_share_consumer_close(consumer);
|
|
165
|
+
test_share_destroy(consumer);
|
|
166
|
+
test_ctx_destroy(&ctx);
|
|
167
|
+
|
|
168
|
+
TEST_ASSERT(consumed == 5, "Expected 5 consumed, got %d", consumed);
|
|
169
|
+
SUB_TEST_PASS();
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
static void do_test_multi_partition(void) {
|
|
173
|
+
const char *topic = "kip932_pos_multi_part";
|
|
174
|
+
const int msgcnt = 6;
|
|
175
|
+
test_ctx_t ctx = test_ctx_new();
|
|
176
|
+
rd_kafka_share_t *consumer;
|
|
177
|
+
int consumed;
|
|
178
|
+
|
|
179
|
+
SUB_TEST_QUICK();
|
|
180
|
+
|
|
181
|
+
TEST_ASSERT(rd_kafka_mock_topic_create(ctx.mcluster, topic, 2, 1) ==
|
|
182
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
183
|
+
"Failed to create mock topic");
|
|
184
|
+
test_produce_msgs_simple(ctx.producer, topic, RD_KAFKA_PARTITION_UA,
|
|
185
|
+
msgcnt);
|
|
186
|
+
|
|
187
|
+
consumer = new_share_consumer(ctx.bootstraps, "sg-pos-multipart");
|
|
188
|
+
subscribe_topics(consumer, &topic, 1);
|
|
189
|
+
consumed = test_share_consume_msgs(consumer, msgcnt, 60, 500, NULL, 0);
|
|
190
|
+
|
|
191
|
+
test_share_consumer_close(consumer);
|
|
192
|
+
test_share_destroy(consumer);
|
|
193
|
+
test_ctx_destroy(&ctx);
|
|
194
|
+
|
|
195
|
+
TEST_ASSERT(consumed == msgcnt, "Expected %d consumed, got %d", msgcnt,
|
|
196
|
+
consumed);
|
|
197
|
+
SUB_TEST_PASS();
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
static void do_test_multi_topic(void) {
|
|
201
|
+
const char *topic_a = "kip932_pos_topic_a";
|
|
202
|
+
const char *topic_b = "kip932_pos_topic_b";
|
|
203
|
+
const char *topics[] = {topic_a, topic_b};
|
|
204
|
+
test_ctx_t ctx = test_ctx_new();
|
|
205
|
+
rd_kafka_share_t *consumer;
|
|
206
|
+
int consumed;
|
|
207
|
+
|
|
208
|
+
SUB_TEST_QUICK();
|
|
209
|
+
|
|
210
|
+
TEST_ASSERT(rd_kafka_mock_topic_create(ctx.mcluster, topic_a, 1, 1) ==
|
|
211
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
212
|
+
"Failed to create mock topic A");
|
|
213
|
+
TEST_ASSERT(rd_kafka_mock_topic_create(ctx.mcluster, topic_b, 1, 1) ==
|
|
214
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
215
|
+
"Failed to create mock topic B");
|
|
216
|
+
|
|
217
|
+
test_produce_msgs_simple(ctx.producer, topic_a, RD_KAFKA_PARTITION_UA,
|
|
218
|
+
2);
|
|
219
|
+
test_produce_msgs_simple(ctx.producer, topic_b, RD_KAFKA_PARTITION_UA,
|
|
220
|
+
2);
|
|
221
|
+
consumer = new_share_consumer(ctx.bootstraps, "sg-pos-multitopic");
|
|
222
|
+
subscribe_topics(consumer, topics, 2);
|
|
223
|
+
consumed = test_share_consume_msgs(consumer, 4, 40, 500, NULL, 0);
|
|
224
|
+
|
|
225
|
+
test_share_consumer_close(consumer);
|
|
226
|
+
test_share_destroy(consumer);
|
|
227
|
+
test_ctx_destroy(&ctx);
|
|
228
|
+
|
|
229
|
+
TEST_ASSERT(consumed == 4, "Expected 4 consumed, got %d", consumed);
|
|
230
|
+
SUB_TEST_PASS();
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
static void do_test_empty_topic_no_records(void) {
|
|
234
|
+
const char *topic = "kip932_pos_empty";
|
|
235
|
+
test_ctx_t ctx = test_ctx_new();
|
|
236
|
+
rd_kafka_share_t *consumer;
|
|
237
|
+
int consumed;
|
|
238
|
+
|
|
239
|
+
SUB_TEST_QUICK();
|
|
240
|
+
|
|
241
|
+
TEST_ASSERT(rd_kafka_mock_topic_create(ctx.mcluster, topic, 1, 1) ==
|
|
242
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
243
|
+
"Failed to create mock topic");
|
|
244
|
+
|
|
245
|
+
consumer = new_share_consumer(ctx.bootstraps, "sg-pos-empty");
|
|
246
|
+
subscribe_topics(consumer, &topic, 1);
|
|
247
|
+
consumed = test_share_consume_msgs(consumer, 1, 5, 500, NULL, 0);
|
|
248
|
+
|
|
249
|
+
test_share_consumer_close(consumer);
|
|
250
|
+
test_share_destroy(consumer);
|
|
251
|
+
test_ctx_destroy(&ctx);
|
|
252
|
+
|
|
253
|
+
TEST_ASSERT(consumed == 0, "Expected 0 consumed, got %d", consumed);
|
|
254
|
+
SUB_TEST_PASS();
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
static int do_test_negative_sharefetch_error(rd_kafka_resp_err_t err) {
|
|
258
|
+
const char *topic = "kip932_neg_sharefetch_error";
|
|
259
|
+
test_ctx_t ctx = test_ctx_new();
|
|
260
|
+
rd_kafka_share_t *consumer;
|
|
261
|
+
int consumed;
|
|
262
|
+
|
|
263
|
+
TEST_ASSERT(rd_kafka_mock_topic_create(ctx.mcluster, topic, 1, 1) ==
|
|
264
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
265
|
+
"Failed to create mock topic");
|
|
266
|
+
test_produce_msgs_simple(ctx.producer, topic, RD_KAFKA_PARTITION_UA, 1);
|
|
267
|
+
|
|
268
|
+
rd_kafka_mock_push_request_errors(ctx.mcluster, RD_KAFKAP_ShareFetch, 1,
|
|
269
|
+
err);
|
|
270
|
+
|
|
271
|
+
consumer = new_share_consumer(ctx.bootstraps, "sg-neg-sharefetch");
|
|
272
|
+
subscribe_topics(consumer, &topic, 1);
|
|
273
|
+
consumed = test_share_consume_msgs(consumer, 1, 30, 500, NULL, 0);
|
|
274
|
+
|
|
275
|
+
test_share_consumer_close(consumer);
|
|
276
|
+
test_share_destroy(consumer);
|
|
277
|
+
test_ctx_destroy(&ctx);
|
|
278
|
+
|
|
279
|
+
return consumed;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
static void do_test_sharefetch_invalid_session_epoch(void) {
|
|
283
|
+
SUB_TEST_QUICK();
|
|
284
|
+
do_test_negative_sharefetch_error(
|
|
285
|
+
RD_KAFKA_RESP_ERR_INVALID_SHARE_SESSION_EPOCH);
|
|
286
|
+
SUB_TEST_PASS();
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
static void do_test_sharefetch_unknown_topic_or_part(void) {
|
|
290
|
+
SUB_TEST_QUICK();
|
|
291
|
+
do_test_negative_sharefetch_error(
|
|
292
|
+
RD_KAFKA_RESP_ERR_UNKNOWN_TOPIC_OR_PART);
|
|
293
|
+
SUB_TEST_PASS();
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
static void do_test_sghb_error(rd_kafka_resp_err_t err, int count) {
|
|
297
|
+
const char *topic = "kip932_neg_sghb";
|
|
298
|
+
test_ctx_t ctx = test_ctx_new();
|
|
299
|
+
rd_kafka_share_t *consumer;
|
|
300
|
+
int consumed;
|
|
301
|
+
rd_kafka_resp_err_t *errs;
|
|
302
|
+
int i;
|
|
303
|
+
|
|
304
|
+
TEST_ASSERT(rd_kafka_mock_topic_create(ctx.mcluster, topic, 1, 1) ==
|
|
305
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
306
|
+
"Failed to create mock topic");
|
|
307
|
+
test_produce_msgs_simple(ctx.producer, topic, RD_KAFKA_PARTITION_UA, 1);
|
|
308
|
+
|
|
309
|
+
/* Build an array of 'count' identical errors and push them all.
|
|
310
|
+
* Using the array variant avoids UB from mismatched varargs count. */
|
|
311
|
+
errs = malloc(sizeof(*errs) * count);
|
|
312
|
+
TEST_ASSERT(errs != NULL, "malloc failed");
|
|
313
|
+
for (i = 0; i < count; i++)
|
|
314
|
+
errs[i] = err;
|
|
315
|
+
rd_kafka_mock_push_request_errors_array(
|
|
316
|
+
ctx.mcluster, RD_KAFKAP_ShareGroupHeartbeat, (size_t)count, errs);
|
|
317
|
+
free(errs);
|
|
318
|
+
|
|
319
|
+
consumer = new_share_consumer(ctx.bootstraps, "sg-neg-sghb");
|
|
320
|
+
subscribe_topics(consumer, &topic, 1);
|
|
321
|
+
consumed = test_share_consume_msgs(consumer, 1, 5, 500, NULL, 0);
|
|
322
|
+
|
|
323
|
+
test_share_consumer_close(consumer);
|
|
324
|
+
test_share_destroy(consumer);
|
|
325
|
+
test_ctx_destroy(&ctx);
|
|
326
|
+
|
|
327
|
+
TEST_ASSERT(consumed == 0, "Expected 0 consumed, got %d", consumed);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
static void do_test_sghb_coord_unavailable(void) {
|
|
331
|
+
SUB_TEST_QUICK();
|
|
332
|
+
do_test_sghb_error(RD_KAFKA_RESP_ERR_COORDINATOR_NOT_AVAILABLE, 50);
|
|
333
|
+
SUB_TEST_PASS();
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
static void do_test_topic_error(rd_kafka_resp_err_t err) {
|
|
337
|
+
const char *topic = "kip932_neg_topic_error";
|
|
338
|
+
test_ctx_t ctx = test_ctx_new();
|
|
339
|
+
rd_kafka_share_t *consumer;
|
|
340
|
+
int consumed;
|
|
341
|
+
|
|
342
|
+
TEST_ASSERT(rd_kafka_mock_topic_create(ctx.mcluster, topic, 1, 1) ==
|
|
343
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
344
|
+
"Failed to create mock topic");
|
|
345
|
+
test_produce_msgs_simple(ctx.producer, topic, RD_KAFKA_PARTITION_UA, 1);
|
|
346
|
+
rd_kafka_mock_topic_set_error(ctx.mcluster, topic, err);
|
|
347
|
+
|
|
348
|
+
consumer = new_share_consumer(ctx.bootstraps, "sg-neg-topicerr");
|
|
349
|
+
subscribe_topics(consumer, &topic, 1);
|
|
350
|
+
consumed = test_share_consume_msgs(consumer, 1, 5, 500, NULL, 0);
|
|
351
|
+
|
|
352
|
+
test_share_consumer_close(consumer);
|
|
353
|
+
test_share_destroy(consumer);
|
|
354
|
+
test_ctx_destroy(&ctx);
|
|
355
|
+
|
|
356
|
+
TEST_ASSERT(consumed == 0, "Expected 0 consumed, got %d", consumed);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
static void do_test_topic_error_unknown_topic_or_part(void) {
|
|
360
|
+
SUB_TEST_QUICK();
|
|
361
|
+
do_test_topic_error(RD_KAFKA_RESP_ERR_UNKNOWN_TOPIC_OR_PART);
|
|
362
|
+
SUB_TEST_PASS();
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
static void do_test_unknown_topic_subscription(void) {
|
|
366
|
+
const char *topic = "kip932_neg_unknown_topic";
|
|
367
|
+
test_ctx_t ctx = test_ctx_new();
|
|
368
|
+
rd_kafka_share_t *consumer;
|
|
369
|
+
int consumed;
|
|
370
|
+
|
|
371
|
+
SUB_TEST_QUICK();
|
|
372
|
+
|
|
373
|
+
consumer = new_share_consumer(ctx.bootstraps, "sg-neg-unknown-topic");
|
|
374
|
+
subscribe_topics(consumer, &topic, 1);
|
|
375
|
+
consumed = test_share_consume_msgs(consumer, 1, 5, 500, NULL, 0);
|
|
376
|
+
|
|
377
|
+
test_share_consumer_close(consumer);
|
|
378
|
+
test_share_destroy(consumer);
|
|
379
|
+
test_ctx_destroy(&ctx);
|
|
380
|
+
|
|
381
|
+
TEST_ASSERT(consumed == 0, "Expected 0 consumed, got %d", consumed);
|
|
382
|
+
SUB_TEST_PASS();
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
static void do_test_empty_fetch_no_records(void) {
|
|
386
|
+
const char *topic = "kip932_neg_empty_fetch";
|
|
387
|
+
test_ctx_t ctx = test_ctx_new();
|
|
388
|
+
rd_kafka_share_t *consumer;
|
|
389
|
+
int consumed;
|
|
390
|
+
|
|
391
|
+
SUB_TEST_QUICK();
|
|
392
|
+
|
|
393
|
+
TEST_ASSERT(rd_kafka_mock_topic_create(ctx.mcluster, topic, 1, 1) ==
|
|
394
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
395
|
+
"Failed to create mock topic");
|
|
396
|
+
|
|
397
|
+
consumer = new_share_consumer(ctx.bootstraps, "sg-neg-empty");
|
|
398
|
+
subscribe_topics(consumer, &topic, 1);
|
|
399
|
+
consumed = test_share_consume_msgs(consumer, 1, 5, 500, NULL, 0);
|
|
400
|
+
|
|
401
|
+
test_share_consumer_close(consumer);
|
|
402
|
+
test_share_destroy(consumer);
|
|
403
|
+
test_ctx_destroy(&ctx);
|
|
404
|
+
|
|
405
|
+
TEST_ASSERT(consumed == 0, "Expected 0 consumed, got %d", consumed);
|
|
406
|
+
SUB_TEST_PASS();
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* @brief Verify that ShareFetch rejects requests from an unregistered member
|
|
411
|
+
* (SHARE_SESSION_NOT_FOUND), and that after the member re-joins it can
|
|
412
|
+
* consume again.
|
|
413
|
+
*
|
|
414
|
+
* Phase 1: Consumer joins normally via SGHB -> consumes messages OK.
|
|
415
|
+
* Phase 2: Push SGHB errors -> heartbeats fail -> member expires -> broker
|
|
416
|
+
* rejects ShareFetch with SHARE_SESSION_NOT_FOUND.
|
|
417
|
+
* Phase 3: SGHB errors drain -> member re-joins -> consumes again.
|
|
418
|
+
*/
|
|
419
|
+
static void do_test_member_validation(void) {
|
|
420
|
+
const char *topic = "kip932_member_validation";
|
|
421
|
+
const int msgcnt = 4;
|
|
422
|
+
test_ctx_t ctx;
|
|
423
|
+
rd_kafka_share_t *consumer;
|
|
424
|
+
int consumed_p1, consumed_p3;
|
|
425
|
+
|
|
426
|
+
SUB_TEST();
|
|
427
|
+
ctx = test_ctx_new();
|
|
428
|
+
|
|
429
|
+
/* Short session timeout so the member is evicted quickly once
|
|
430
|
+
* heartbeats stop succeeding. */
|
|
431
|
+
rd_kafka_mock_sharegroup_set_session_timeout(ctx.mcluster, 500);
|
|
432
|
+
|
|
433
|
+
TEST_ASSERT(rd_kafka_mock_topic_create(ctx.mcluster, topic, 1, 1) ==
|
|
434
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
435
|
+
"Failed to create mock topic");
|
|
436
|
+
test_produce_msgs_simple(ctx.producer, topic, RD_KAFKA_PARTITION_UA,
|
|
437
|
+
msgcnt);
|
|
438
|
+
|
|
439
|
+
consumer = new_share_consumer(ctx.bootstraps, "sg-member-val");
|
|
440
|
+
subscribe_topics(consumer, &topic, 1);
|
|
441
|
+
|
|
442
|
+
/* Phase 1: Consume normally -- member is registered via SGHB. */
|
|
443
|
+
consumed_p1 = test_share_consume_msgs(consumer, 2, 30, 500, NULL, 0);
|
|
444
|
+
TEST_SAY("member_validation: phase1 consumed %d/2\n", consumed_p1);
|
|
445
|
+
|
|
446
|
+
/* Phase 2: Block SGHB so heartbeats fail.
|
|
447
|
+
* Push enough errors to cover the window while we wait for the
|
|
448
|
+
* member to be evicted. */
|
|
449
|
+
rd_kafka_mock_push_request_errors(
|
|
450
|
+
ctx.mcluster, RD_KAFKAP_ShareGroupHeartbeat, 20,
|
|
451
|
+
RD_KAFKA_RESP_ERR_COORDINATOR_NOT_AVAILABLE,
|
|
452
|
+
RD_KAFKA_RESP_ERR_COORDINATOR_NOT_AVAILABLE,
|
|
453
|
+
RD_KAFKA_RESP_ERR_COORDINATOR_NOT_AVAILABLE,
|
|
454
|
+
RD_KAFKA_RESP_ERR_COORDINATOR_NOT_AVAILABLE,
|
|
455
|
+
RD_KAFKA_RESP_ERR_COORDINATOR_NOT_AVAILABLE,
|
|
456
|
+
RD_KAFKA_RESP_ERR_COORDINATOR_NOT_AVAILABLE,
|
|
457
|
+
RD_KAFKA_RESP_ERR_COORDINATOR_NOT_AVAILABLE,
|
|
458
|
+
RD_KAFKA_RESP_ERR_COORDINATOR_NOT_AVAILABLE,
|
|
459
|
+
RD_KAFKA_RESP_ERR_COORDINATOR_NOT_AVAILABLE,
|
|
460
|
+
RD_KAFKA_RESP_ERR_COORDINATOR_NOT_AVAILABLE,
|
|
461
|
+
RD_KAFKA_RESP_ERR_COORDINATOR_NOT_AVAILABLE,
|
|
462
|
+
RD_KAFKA_RESP_ERR_COORDINATOR_NOT_AVAILABLE,
|
|
463
|
+
RD_KAFKA_RESP_ERR_COORDINATOR_NOT_AVAILABLE,
|
|
464
|
+
RD_KAFKA_RESP_ERR_COORDINATOR_NOT_AVAILABLE,
|
|
465
|
+
RD_KAFKA_RESP_ERR_COORDINATOR_NOT_AVAILABLE,
|
|
466
|
+
RD_KAFKA_RESP_ERR_COORDINATOR_NOT_AVAILABLE,
|
|
467
|
+
RD_KAFKA_RESP_ERR_COORDINATOR_NOT_AVAILABLE,
|
|
468
|
+
RD_KAFKA_RESP_ERR_COORDINATOR_NOT_AVAILABLE,
|
|
469
|
+
RD_KAFKA_RESP_ERR_COORDINATOR_NOT_AVAILABLE,
|
|
470
|
+
RD_KAFKA_RESP_ERR_COORDINATOR_NOT_AVAILABLE);
|
|
471
|
+
|
|
472
|
+
/* Wait for the member to be evicted (500ms session timeout + margin).
|
|
473
|
+
*/
|
|
474
|
+
rd_usleep(1500 * 1000, 0);
|
|
475
|
+
|
|
476
|
+
/* Phase 3: SGHB errors will eventually drain. Once a SGHB
|
|
477
|
+
* succeeds, the member re-joins and the remaining records
|
|
478
|
+
* become fetchable again. */
|
|
479
|
+
consumed_p3 = test_share_consume_msgs(consumer, 2, 50, 500, NULL, 0);
|
|
480
|
+
TEST_SAY("member_validation: phase3 consumed %d/2\n", consumed_p3);
|
|
481
|
+
|
|
482
|
+
test_share_consumer_close(consumer);
|
|
483
|
+
test_share_destroy(consumer);
|
|
484
|
+
test_ctx_destroy(&ctx);
|
|
485
|
+
|
|
486
|
+
TEST_ASSERT(consumed_p1 >= 2 && (consumed_p1 + consumed_p3) >= msgcnt,
|
|
487
|
+
"Expected at least 2+2, got %d+%d", consumed_p1,
|
|
488
|
+
consumed_p3);
|
|
489
|
+
SUB_TEST_PASS();
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
static void do_test_sharefetch_session_expiry_rtt(void) {
|
|
493
|
+
const char *topic = "kip932_rtt_expiry";
|
|
494
|
+
test_ctx_t ctx;
|
|
495
|
+
rd_kafka_share_t *consumer;
|
|
496
|
+
int consumed;
|
|
497
|
+
|
|
498
|
+
SUB_TEST();
|
|
499
|
+
ctx = test_ctx_new();
|
|
500
|
+
|
|
501
|
+
/* Session timeout must be long enough for normal requests
|
|
502
|
+
* to complete, but short enough to expire during high RTT. */
|
|
503
|
+
rd_kafka_mock_sharegroup_set_session_timeout(ctx.mcluster, 1000);
|
|
504
|
+
|
|
505
|
+
TEST_ASSERT(rd_kafka_mock_topic_create(ctx.mcluster, topic, 1, 1) ==
|
|
506
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
507
|
+
"Failed to create mock topic");
|
|
508
|
+
/* Produce only 1 message so a single batch cannot over-consume
|
|
509
|
+
* past the requested count in test_share_consume_msgs(). */
|
|
510
|
+
test_produce_msgs_simple(ctx.producer, topic, RD_KAFKA_PARTITION_UA, 1);
|
|
511
|
+
|
|
512
|
+
consumer = new_share_consumer(ctx.bootstraps, "sg-rtt-expiry");
|
|
513
|
+
subscribe_topics(consumer, &topic, 1);
|
|
514
|
+
|
|
515
|
+
/* Phase 1: consume one message with normal RTT (no injection). */
|
|
516
|
+
consumed = test_share_consume_msgs(consumer, 1, 20, 500, NULL, 0);
|
|
517
|
+
TEST_SAY("rtt_expiry: phase1 consumed %d/1\n", consumed);
|
|
518
|
+
|
|
519
|
+
/* Phase 2: inject RTT >> session timeout to force session expiry.
|
|
520
|
+
* All requests to broker 1 now take 3s, but the session
|
|
521
|
+
* expires after 1s of inactivity. The record from phase 1
|
|
522
|
+
* was acquired but not acked, so it becomes available again
|
|
523
|
+
* after the session expires. */
|
|
524
|
+
rd_kafka_mock_broker_set_rtt(ctx.mcluster, 1, 3000);
|
|
525
|
+
rd_usleep(2000 * 1000, 0); /* wait for session to expire */
|
|
526
|
+
|
|
527
|
+
/* Phase 3: clear RTT and let the consumer recover.
|
|
528
|
+
* The same record should be re-delivered after session expiry. */
|
|
529
|
+
rd_kafka_mock_broker_set_rtt(ctx.mcluster, 1, 0);
|
|
530
|
+
consumed += test_share_consume_msgs(consumer, 1, 30, 500, NULL, 0);
|
|
531
|
+
TEST_SAY("rtt_expiry: phase3 consumed %d/2 total\n", consumed);
|
|
532
|
+
|
|
533
|
+
test_share_consumer_close(consumer);
|
|
534
|
+
test_share_destroy(consumer);
|
|
535
|
+
test_ctx_destroy(&ctx);
|
|
536
|
+
|
|
537
|
+
TEST_ASSERT(consumed == 2, "Expected 2 consumed, got %d", consumed);
|
|
538
|
+
SUB_TEST_PASS();
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
static void do_test_forgotten_topics(void) {
|
|
542
|
+
const char *topic_a = "kip932_forgotten_a";
|
|
543
|
+
const char *topic_b = "kip932_forgotten_b";
|
|
544
|
+
const char *both[] = {topic_a, topic_b};
|
|
545
|
+
test_ctx_t ctx = test_ctx_new();
|
|
546
|
+
rd_kafka_share_t *consumer;
|
|
547
|
+
int consumed;
|
|
548
|
+
|
|
549
|
+
SUB_TEST_QUICK();
|
|
550
|
+
|
|
551
|
+
TEST_ASSERT(rd_kafka_mock_topic_create(ctx.mcluster, topic_a, 1, 1) ==
|
|
552
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
553
|
+
"Failed to create mock topic A");
|
|
554
|
+
TEST_ASSERT(rd_kafka_mock_topic_create(ctx.mcluster, topic_b, 1, 1) ==
|
|
555
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
556
|
+
"Failed to create mock topic B");
|
|
557
|
+
|
|
558
|
+
/* Produce 2 messages to each topic */
|
|
559
|
+
test_produce_msgs_simple(ctx.producer, topic_a, RD_KAFKA_PARTITION_UA,
|
|
560
|
+
2);
|
|
561
|
+
test_produce_msgs_simple(ctx.producer, topic_b, RD_KAFKA_PARTITION_UA,
|
|
562
|
+
2);
|
|
563
|
+
|
|
564
|
+
/* Subscribe to both topics and consume all 4 messages */
|
|
565
|
+
consumer = new_share_consumer(ctx.bootstraps, "sg-forgotten");
|
|
566
|
+
subscribe_topics(consumer, both, 2);
|
|
567
|
+
consumed = test_share_consume_msgs(consumer, 4, 40, 500, NULL, 0);
|
|
568
|
+
TEST_SAY("forgotten_topics: consumed %d/4 from both topics\n",
|
|
569
|
+
consumed);
|
|
570
|
+
|
|
571
|
+
/* Re-subscribe to only topic_a (topic_b becomes forgotten) */
|
|
572
|
+
subscribe_topics(consumer, &topic_a, 1);
|
|
573
|
+
|
|
574
|
+
/* Produce 2 more messages to topic_a */
|
|
575
|
+
test_produce_msgs_simple(ctx.producer, topic_a, RD_KAFKA_PARTITION_UA,
|
|
576
|
+
2);
|
|
577
|
+
|
|
578
|
+
/* Consume the 2 new messages -- only topic_a should deliver */
|
|
579
|
+
consumed += test_share_consume_msgs(consumer, 2, 30, 500, NULL, 0);
|
|
580
|
+
TEST_SAY("forgotten_topics: consumed %d/6 total after forget\n",
|
|
581
|
+
consumed);
|
|
582
|
+
|
|
583
|
+
test_share_consumer_close(consumer);
|
|
584
|
+
test_share_destroy(consumer);
|
|
585
|
+
test_ctx_destroy(&ctx);
|
|
586
|
+
|
|
587
|
+
/* We expect at least the 4 initial + 2 from topic_a = 6.
|
|
588
|
+
* Depending on timing the consumer may or may not have already
|
|
589
|
+
* received all messages from the first round, so we accept >= 4. */
|
|
590
|
+
TEST_ASSERT(consumed >= 4, "Expected at least 4 consumed, got %d",
|
|
591
|
+
consumed);
|
|
592
|
+
SUB_TEST_PASS();
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
/**
|
|
596
|
+
* @brief Produce messages one-at-a-time (each flush creates a separate
|
|
597
|
+
* msgset on the mock partition), then consume and verify all are
|
|
598
|
+
* received. This validates that the ShareFetch response includes
|
|
599
|
+
* records from *all* acquired msgsets, not just the first one.
|
|
600
|
+
*/
|
|
601
|
+
static void do_test_multi_batch_consume(void) {
|
|
602
|
+
const char *topic = "kip932_multi_batch";
|
|
603
|
+
const int msgcnt = 5;
|
|
604
|
+
test_ctx_t ctx = test_ctx_new();
|
|
605
|
+
rd_kafka_share_t *consumer;
|
|
606
|
+
int consumed;
|
|
607
|
+
|
|
608
|
+
SUB_TEST_QUICK();
|
|
609
|
+
|
|
610
|
+
TEST_ASSERT(rd_kafka_mock_topic_create(ctx.mcluster, topic, 1, 1) ==
|
|
611
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
612
|
+
"Failed to create mock topic");
|
|
613
|
+
|
|
614
|
+
/* Produce each message individually with a flush in between,
|
|
615
|
+
* guaranteeing separate msgsets on the mock partition. */
|
|
616
|
+
for (int i = 0; i < msgcnt; i++) {
|
|
617
|
+
char payload[64];
|
|
618
|
+
snprintf(payload, sizeof(payload), "batch-%d", i);
|
|
619
|
+
TEST_ASSERT(rd_kafka_producev(
|
|
620
|
+
ctx.producer, RD_KAFKA_V_TOPIC(topic),
|
|
621
|
+
RD_KAFKA_V_VALUE(payload, strlen(payload)),
|
|
622
|
+
RD_KAFKA_V_MSGFLAGS(RD_KAFKA_MSG_F_COPY),
|
|
623
|
+
RD_KAFKA_V_END) == RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
624
|
+
"Produce failed");
|
|
625
|
+
rd_kafka_flush(ctx.producer, 5000);
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
consumer = new_share_consumer(ctx.bootstraps, "sg-multi-batch");
|
|
629
|
+
subscribe_topics(consumer, &topic, 1);
|
|
630
|
+
consumed = test_share_consume_msgs(consumer, msgcnt, 50, 500, NULL, 0);
|
|
631
|
+
TEST_SAY("multi_batch: consumed %d/%d\n", consumed, msgcnt);
|
|
632
|
+
|
|
633
|
+
test_share_consumer_close(consumer);
|
|
634
|
+
test_share_destroy(consumer);
|
|
635
|
+
test_ctx_destroy(&ctx);
|
|
636
|
+
|
|
637
|
+
TEST_ASSERT(consumed == msgcnt, "Expected %d consumed, got %d", msgcnt,
|
|
638
|
+
consumed);
|
|
639
|
+
SUB_TEST_PASS();
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
/**
|
|
643
|
+
* @brief Verify that max_delivery_attempts causes records to be archived
|
|
644
|
+
* after the limit is exceeded. Consumer A acquires all records, then
|
|
645
|
+
* its session times out (releasing locks). Consumer B acquires them
|
|
646
|
+
* again, and its session also times out. After the delivery limit is
|
|
647
|
+
* exhausted, Consumer C should see 0 available records.
|
|
648
|
+
*/
|
|
649
|
+
static void do_test_max_delivery_attempts(void) {
|
|
650
|
+
const char *topic = "kip932_max_delivery";
|
|
651
|
+
const int msgcnt = 3;
|
|
652
|
+
test_ctx_t ctx;
|
|
653
|
+
rd_kafka_share_t *consumer;
|
|
654
|
+
int consumed_a, consumed_b, consumed_c;
|
|
655
|
+
|
|
656
|
+
SUB_TEST();
|
|
657
|
+
ctx = test_ctx_new();
|
|
658
|
+
|
|
659
|
+
/* Set max delivery attempts to 2 and a short session timeout
|
|
660
|
+
* so locks expire quickly after consumer destruction. */
|
|
661
|
+
rd_kafka_mock_sharegroup_set_max_delivery_attempts(ctx.mcluster, 2);
|
|
662
|
+
rd_kafka_mock_sharegroup_set_session_timeout(ctx.mcluster, 500);
|
|
663
|
+
|
|
664
|
+
TEST_ASSERT(rd_kafka_mock_topic_create(ctx.mcluster, topic, 1, 1) ==
|
|
665
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
666
|
+
"Failed to create mock topic");
|
|
667
|
+
test_produce_msgs_simple(ctx.producer, topic, RD_KAFKA_PARTITION_UA,
|
|
668
|
+
msgcnt);
|
|
669
|
+
|
|
670
|
+
/* Delivery 1: Consumer A acquires and "crashes" (no ack). */
|
|
671
|
+
consumer = new_share_consumer(ctx.bootstraps, "sg-max-delivery");
|
|
672
|
+
subscribe_topics(consumer, &topic, 1);
|
|
673
|
+
consumed_a =
|
|
674
|
+
test_share_consume_msgs(consumer, msgcnt, 50, 500, NULL, 0);
|
|
675
|
+
TEST_SAY("max_delivery: A consumed %d/%d (delivery 1)\n", consumed_a,
|
|
676
|
+
msgcnt);
|
|
677
|
+
test_share_destroy(consumer);
|
|
678
|
+
rd_usleep(1500 * 1000, 0); /* wait for lock expiry */
|
|
679
|
+
|
|
680
|
+
/* Delivery 2: Consumer B acquires same records again (delivery_count
|
|
681
|
+
* reaches 2 = limit) and "crashes". */
|
|
682
|
+
consumer = new_share_consumer(ctx.bootstraps, "sg-max-delivery");
|
|
683
|
+
subscribe_topics(consumer, &topic, 1);
|
|
684
|
+
consumed_b =
|
|
685
|
+
test_share_consume_msgs(consumer, msgcnt, 50, 500, NULL, 0);
|
|
686
|
+
TEST_SAY("max_delivery: B consumed %d/%d (delivery 2)\n", consumed_b,
|
|
687
|
+
msgcnt);
|
|
688
|
+
test_share_destroy(consumer);
|
|
689
|
+
rd_usleep(1500 * 1000, 0); /* wait for lock expiry */
|
|
690
|
+
|
|
691
|
+
/* Delivery 3 attempt: Consumer C should get 0 records because
|
|
692
|
+
* all records have been archived (delivery_count >= max). */
|
|
693
|
+
consumer = new_share_consumer(ctx.bootstraps, "sg-max-delivery");
|
|
694
|
+
subscribe_topics(consumer, &topic, 1);
|
|
695
|
+
consumed_c = test_share_consume_msgs(consumer, 1, 10, 500, NULL, 0);
|
|
696
|
+
TEST_SAY("max_delivery: C consumed %d/0 (should be archived)\n",
|
|
697
|
+
consumed_c);
|
|
698
|
+
|
|
699
|
+
test_share_consumer_close(consumer);
|
|
700
|
+
test_share_destroy(consumer);
|
|
701
|
+
test_ctx_destroy(&ctx);
|
|
702
|
+
|
|
703
|
+
TEST_ASSERT(consumed_a == msgcnt && consumed_b == msgcnt &&
|
|
704
|
+
consumed_c == 0,
|
|
705
|
+
"Expected A=%d B=%d C=0, got A=%d B=%d C=%d", msgcnt,
|
|
706
|
+
msgcnt, consumed_a, consumed_b, consumed_c);
|
|
707
|
+
SUB_TEST_PASS();
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
/**
|
|
711
|
+
* @brief Verify that record_lock_duration_ms controls how long acquired
|
|
712
|
+
* records stay locked, independently of session_timeout_ms.
|
|
713
|
+
* Sets a short lock duration (300ms) with a longer session timeout
|
|
714
|
+
* (10s). Consumer A acquires records and "crashes". After the short
|
|
715
|
+
* lock duration expires, Consumer B should be able to acquire them
|
|
716
|
+
* even though A's session hasn't timed out yet.
|
|
717
|
+
*/
|
|
718
|
+
static void do_test_record_lock_duration(void) {
|
|
719
|
+
const char *topic = "kip932_lock_duration";
|
|
720
|
+
const int msgcnt = 3;
|
|
721
|
+
test_ctx_t ctx;
|
|
722
|
+
rd_kafka_share_t *consumer;
|
|
723
|
+
int consumed_a, consumed_b;
|
|
724
|
+
|
|
725
|
+
SUB_TEST();
|
|
726
|
+
ctx = test_ctx_new();
|
|
727
|
+
|
|
728
|
+
/* Long session timeout, short record lock duration. */
|
|
729
|
+
rd_kafka_mock_sharegroup_set_session_timeout(ctx.mcluster, 10000);
|
|
730
|
+
rd_kafka_mock_sharegroup_set_record_lock_duration(ctx.mcluster, 300);
|
|
731
|
+
|
|
732
|
+
TEST_ASSERT(rd_kafka_mock_topic_create(ctx.mcluster, topic, 1, 1) ==
|
|
733
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
734
|
+
"Failed to create mock topic");
|
|
735
|
+
test_produce_msgs_simple(ctx.producer, topic, RD_KAFKA_PARTITION_UA,
|
|
736
|
+
msgcnt);
|
|
737
|
+
|
|
738
|
+
/* Consumer A acquires records, then crashes (no close). */
|
|
739
|
+
consumer = new_share_consumer(ctx.bootstraps, "sg-lock-duration");
|
|
740
|
+
subscribe_topics(consumer, &topic, 1);
|
|
741
|
+
consumed_a =
|
|
742
|
+
test_share_consume_msgs(consumer, msgcnt, 50, 500, NULL, 0);
|
|
743
|
+
TEST_SAY("lock_duration: A consumed %d/%d\n", consumed_a, msgcnt);
|
|
744
|
+
test_share_destroy(consumer);
|
|
745
|
+
|
|
746
|
+
/* Wait for record lock to expire (300ms + margin).
|
|
747
|
+
* test_share_destroy sends SGHB LEAVE which releases
|
|
748
|
+
* locks immediately, but we still need to wait for the
|
|
749
|
+
* client's internal rejoin cycle to settle. */
|
|
750
|
+
rd_usleep(1000 * 1000, 0);
|
|
751
|
+
|
|
752
|
+
/* Consumer B should get the records because locks have expired
|
|
753
|
+
* even though A's session is still technically alive.
|
|
754
|
+
* Use higher max_attempts to account for the mock broker's
|
|
755
|
+
* SGHB LEAVE->rejoin cycle delay. */
|
|
756
|
+
consumer = new_share_consumer(ctx.bootstraps, "sg-lock-duration");
|
|
757
|
+
subscribe_topics(consumer, &topic, 1);
|
|
758
|
+
consumed_b =
|
|
759
|
+
test_share_consume_msgs(consumer, msgcnt, 100, 500, NULL, 0);
|
|
760
|
+
TEST_SAY("lock_duration: B consumed %d/%d\n", consumed_b, msgcnt);
|
|
761
|
+
|
|
762
|
+
test_share_consumer_close(consumer);
|
|
763
|
+
test_share_destroy(consumer);
|
|
764
|
+
test_ctx_destroy(&ctx);
|
|
765
|
+
|
|
766
|
+
TEST_ASSERT(consumed_a == msgcnt && consumed_b == msgcnt,
|
|
767
|
+
"Expected A=%d B=%d, got A=%d B=%d", msgcnt, msgcnt,
|
|
768
|
+
consumed_a, consumed_b);
|
|
769
|
+
SUB_TEST_PASS();
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
/**
|
|
773
|
+
* @brief Multi-consumer lock expiry test.
|
|
774
|
+
*
|
|
775
|
+
* Consumer A acquires records, then crashes (destroyed without close).
|
|
776
|
+
* After the lock expiry timeout, consumer B should be able to pick up
|
|
777
|
+
* the same records because the proactive lock-expiry scan releases them.
|
|
778
|
+
*/
|
|
779
|
+
static void do_test_multi_consumer_lock_expiry(void) {
|
|
780
|
+
const char *topic = "kip932_multi_consumer_lock";
|
|
781
|
+
const int msgcnt = 3;
|
|
782
|
+
test_ctx_t ctx;
|
|
783
|
+
rd_kafka_share_t *consumer_a, *consumer_b;
|
|
784
|
+
int consumed_a, consumed_b;
|
|
785
|
+
|
|
786
|
+
SUB_TEST();
|
|
787
|
+
ctx = test_ctx_new();
|
|
788
|
+
|
|
789
|
+
/* Use a short session/lock timeout so the test runs quickly. */
|
|
790
|
+
rd_kafka_mock_sharegroup_set_session_timeout(ctx.mcluster, 500);
|
|
791
|
+
|
|
792
|
+
TEST_ASSERT(rd_kafka_mock_topic_create(ctx.mcluster, topic, 1, 1) ==
|
|
793
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
794
|
+
"Failed to create mock topic");
|
|
795
|
+
test_produce_msgs_simple(ctx.producer, topic, RD_KAFKA_PARTITION_UA,
|
|
796
|
+
msgcnt);
|
|
797
|
+
|
|
798
|
+
/* Consumer A: subscribe and consume all records (acquires locks). */
|
|
799
|
+
consumer_a =
|
|
800
|
+
new_share_consumer(ctx.bootstraps, "sg-multi-consumer-lock");
|
|
801
|
+
subscribe_topics(consumer_a, &topic, 1);
|
|
802
|
+
consumed_a =
|
|
803
|
+
test_share_consume_msgs(consumer_a, msgcnt, 50, 500, NULL, 0);
|
|
804
|
+
TEST_SAY("multi_consumer: A consumed %d/%d\n", consumed_a, msgcnt);
|
|
805
|
+
|
|
806
|
+
/* Simulate crash: destroy consumer A without calling close.
|
|
807
|
+
* The session will time out and the proactive lock-expiry
|
|
808
|
+
* timer will release A's locks. */
|
|
809
|
+
test_share_destroy(consumer_a);
|
|
810
|
+
|
|
811
|
+
/* Wait for locks to expire (session_timeout=500ms, add margin). */
|
|
812
|
+
rd_usleep(1500 * 1000, 0);
|
|
813
|
+
|
|
814
|
+
/* Consumer B: joins the same share group, should get the same
|
|
815
|
+
* records once the locks have been released.
|
|
816
|
+
* Use higher max_attempts to account for the mock broker's
|
|
817
|
+
* SGHB LEAVE->rejoin cycle delay. */
|
|
818
|
+
consumer_b =
|
|
819
|
+
new_share_consumer(ctx.bootstraps, "sg-multi-consumer-lock");
|
|
820
|
+
subscribe_topics(consumer_b, &topic, 1);
|
|
821
|
+
consumed_b =
|
|
822
|
+
test_share_consume_msgs(consumer_b, msgcnt, 100, 500, NULL, 0);
|
|
823
|
+
TEST_SAY("multi_consumer: B consumed %d/%d\n", consumed_b, msgcnt);
|
|
824
|
+
|
|
825
|
+
test_share_consumer_close(consumer_b);
|
|
826
|
+
test_share_destroy(consumer_b);
|
|
827
|
+
test_ctx_destroy(&ctx);
|
|
828
|
+
|
|
829
|
+
TEST_ASSERT(consumed_a == msgcnt && consumed_b == msgcnt,
|
|
830
|
+
"Expected A=%d B=%d, got A=%d B=%d", msgcnt, msgcnt,
|
|
831
|
+
consumed_a, consumed_b);
|
|
832
|
+
SUB_TEST_PASS();
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
|
|
836
|
+
/*
|
|
837
|
+
* TODO KIP-932: The functions below inject errors using
|
|
838
|
+
* rd_kafka_mock_push_request_errors(), which only sets the top-level
|
|
839
|
+
* ShareFetch error code. The error codes tested here are per-partition
|
|
840
|
+
* errors that the broker never emits at the top level. Re-enable
|
|
841
|
+
* once partition-level mock error injection is available.
|
|
842
|
+
*
|
|
843
|
+
static void do_test_sharefetch_fetch_error(rd_kafka_resp_err_t err) {
|
|
844
|
+
const char *topic = "kip932_fetch_error";
|
|
845
|
+
test_ctx_t ctx = test_ctx_new();
|
|
846
|
+
rd_kafka_share_t *consumer;
|
|
847
|
+
rd_kafka_messages_t *batch = NULL;
|
|
848
|
+
size_t rcvd = 0;
|
|
849
|
+
int consumed = 0;
|
|
850
|
+
size_t i;
|
|
851
|
+
|
|
852
|
+
TEST_ASSERT(rd_kafka_mock_topic_create(ctx.mcluster, topic, 1, 1) ==
|
|
853
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
854
|
+
"Failed to create mock topic");
|
|
855
|
+
test_produce_msgs_simple(ctx.producer, topic, RD_KAFKA_PARTITION_UA, 3);
|
|
856
|
+
|
|
857
|
+
rd_kafka_mock_push_request_errors(ctx.mcluster, RD_KAFKAP_ShareFetch, 1,
|
|
858
|
+
err);
|
|
859
|
+
|
|
860
|
+
consumer = new_share_consumer(ctx.bootstraps, "sg-fetch-error");
|
|
861
|
+
subscribe_topics(consumer, &topic, 1);
|
|
862
|
+
|
|
863
|
+
rd_kafka_share_poll(consumer, 2000, &batch);
|
|
864
|
+
rcvd = rd_kafka_messages_count(batch);
|
|
865
|
+
for (i = 0; i < rcvd; i++) {
|
|
866
|
+
rd_kafka_message_t *msg = rd_kafka_messages_get(batch, i);
|
|
867
|
+
if (!msg->err)
|
|
868
|
+
consumed++;
|
|
869
|
+
}
|
|
870
|
+
rd_kafka_messages_destroy(batch);
|
|
871
|
+
batch = NULL;
|
|
872
|
+
|
|
873
|
+
TEST_SAY("fetch_error(%s): consumed=%d rcvd=%zu\n",
|
|
874
|
+
rd_kafka_err2name(err), consumed, rcvd);
|
|
875
|
+
|
|
876
|
+
test_share_consumer_close(consumer);
|
|
877
|
+
test_share_destroy(consumer);
|
|
878
|
+
test_ctx_destroy(&ctx);
|
|
879
|
+
|
|
880
|
+
TEST_ASSERT(consumed == 0, "Expected 0 consumed with %s, got %d",
|
|
881
|
+
rd_kafka_err2name(err), consumed);
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
static void do_test_sharefetch_fetch_error_not_leader(void) {
|
|
885
|
+
SUB_TEST();
|
|
886
|
+
do_test_sharefetch_fetch_error(
|
|
887
|
+
RD_KAFKA_RESP_ERR_NOT_LEADER_OR_FOLLOWER);
|
|
888
|
+
SUB_TEST_PASS();
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
static void do_test_sharefetch_fetch_error_unknown_topic_or_part(void) {
|
|
892
|
+
SUB_TEST();
|
|
893
|
+
do_test_sharefetch_fetch_error(RD_KAFKA_RESP_ERR_UNKNOWN_TOPIC_OR_PART);
|
|
894
|
+
SUB_TEST_PASS();
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
static void do_test_sharefetch_fetch_error_unknown_topic_id(void) {
|
|
898
|
+
SUB_TEST();
|
|
899
|
+
do_test_sharefetch_fetch_error(RD_KAFKA_RESP_ERR_UNKNOWN_TOPIC_ID);
|
|
900
|
+
SUB_TEST_PASS();
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
static void do_test_sharefetch_fetch_error_fenced_leader_epoch(void) {
|
|
904
|
+
SUB_TEST();
|
|
905
|
+
do_test_sharefetch_fetch_error(RD_KAFKA_RESP_ERR_FENCED_LEADER_EPOCH);
|
|
906
|
+
SUB_TEST_PASS();
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
static void do_test_sharefetch_fetch_error_unknown_leader_epoch(void) {
|
|
910
|
+
SUB_TEST();
|
|
911
|
+
do_test_sharefetch_fetch_error(RD_KAFKA_RESP_ERR_UNKNOWN_LEADER_EPOCH);
|
|
912
|
+
SUB_TEST_PASS();
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
static void do_test_sharefetch_topic_authorization_failed(void) {
|
|
916
|
+
SUB_TEST();
|
|
917
|
+
do_test_sharefetch_fetch_error(
|
|
918
|
+
RD_KAFKA_RESP_ERR_TOPIC_AUTHORIZATION_FAILED);
|
|
919
|
+
SUB_TEST_PASS();
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
static void do_test_sharefetch_corrupt_message(void) {
|
|
923
|
+
SUB_TEST();
|
|
924
|
+
do_test_sharefetch_fetch_error(RD_KAFKA_RESP_ERR_INVALID_MSG);
|
|
925
|
+
SUB_TEST_PASS();
|
|
926
|
+
}
|
|
927
|
+
*/
|
|
928
|
+
|
|
929
|
+
/*
|
|
930
|
+
* TODO KIP-932: This test injects FENCED_LEADER_EPOCH using
|
|
931
|
+
* rd_kafka_mock_push_request_errors(), which only sets the top-level
|
|
932
|
+
* ShareFetch error code. FENCED_LEADER_EPOCH is a per-partition error
|
|
933
|
+
* that the broker never emits at the top level; the top-level handler
|
|
934
|
+
* treats it as transient and retries, so the consumer receives records.
|
|
935
|
+
* Re-enable once partition-level mock error injection is available.
|
|
936
|
+
*
|
|
937
|
+
static void do_test_sharefetch_fetch_disconnected(void) {
|
|
938
|
+
const char *topic = "kip932_disconnect";
|
|
939
|
+
test_ctx_t ctx;
|
|
940
|
+
rd_kafka_share_t *consumer;
|
|
941
|
+
rd_kafka_messages_t *batch = NULL;
|
|
942
|
+
size_t rcvd = 0;
|
|
943
|
+
int consumed = 0;
|
|
944
|
+
size_t i;
|
|
945
|
+
|
|
946
|
+
SUB_TEST();
|
|
947
|
+
ctx = test_ctx_new();
|
|
948
|
+
|
|
949
|
+
TEST_ASSERT(rd_kafka_mock_topic_create(ctx.mcluster, topic, 1, 1) ==
|
|
950
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
951
|
+
"Failed to create mock topic");
|
|
952
|
+
test_produce_msgs_simple(ctx.producer, topic, RD_KAFKA_PARTITION_UA, 3);
|
|
953
|
+
|
|
954
|
+
rd_kafka_mock_push_request_errors(
|
|
955
|
+
ctx.mcluster, RD_KAFKAP_ShareFetch, 1,
|
|
956
|
+
RD_KAFKA_RESP_ERR_FENCED_LEADER_EPOCH);
|
|
957
|
+
|
|
958
|
+
consumer = new_share_consumer(ctx.bootstraps, "sg-disconnect");
|
|
959
|
+
subscribe_topics(consumer, &topic, 1);
|
|
960
|
+
|
|
961
|
+
rd_kafka_share_poll(consumer, 2000, &batch);
|
|
962
|
+
rcvd = rd_kafka_messages_count(batch);
|
|
963
|
+
for (i = 0; i < rcvd; i++) {
|
|
964
|
+
rd_kafka_message_t *msg = rd_kafka_messages_get(batch, i);
|
|
965
|
+
if (!msg->err)
|
|
966
|
+
consumed++;
|
|
967
|
+
}
|
|
968
|
+
rd_kafka_messages_destroy(batch);
|
|
969
|
+
batch = NULL;
|
|
970
|
+
|
|
971
|
+
TEST_SAY("fetch_disconnected: consumed=%d rcvd=%zu\n", consumed, rcvd);
|
|
972
|
+
|
|
973
|
+
test_share_consumer_close(consumer);
|
|
974
|
+
test_share_destroy(consumer);
|
|
975
|
+
test_ctx_destroy(&ctx);
|
|
976
|
+
|
|
977
|
+
TEST_ASSERT(consumed == 0, "Expected 0 consumed on disconnect, got %d",
|
|
978
|
+
consumed);
|
|
979
|
+
SUB_TEST_PASS();
|
|
980
|
+
}
|
|
981
|
+
*/
|
|
982
|
+
|
|
983
|
+
/**
|
|
984
|
+
* @brief Fetch records and close implicitly (no explicit ack).
|
|
985
|
+
*
|
|
986
|
+
* Verifies that a consumer can fetch records and then close successfully.
|
|
987
|
+
* The close sends ShareAcknowledge with epoch=-1 to release the session.
|
|
988
|
+
*/
|
|
989
|
+
static void do_test_sharefetch_fetch_and_close_implicit(void) {
|
|
990
|
+
const char *topic = "kip932_fetch_close";
|
|
991
|
+
const int msgcnt = 2;
|
|
992
|
+
test_ctx_t ctx;
|
|
993
|
+
rd_kafka_share_t *consumer;
|
|
994
|
+
int consumed;
|
|
995
|
+
|
|
996
|
+
SUB_TEST();
|
|
997
|
+
ctx = test_ctx_new();
|
|
998
|
+
|
|
999
|
+
TEST_ASSERT(rd_kafka_mock_topic_create(ctx.mcluster, topic, 1, 1) ==
|
|
1000
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
1001
|
+
"Failed to create mock topic");
|
|
1002
|
+
test_produce_msgs_simple(ctx.producer, topic, RD_KAFKA_PARTITION_UA,
|
|
1003
|
+
msgcnt);
|
|
1004
|
+
|
|
1005
|
+
consumer = new_share_consumer(ctx.bootstraps, "sg-fetch-close");
|
|
1006
|
+
subscribe_topics(consumer, &topic, 1);
|
|
1007
|
+
|
|
1008
|
+
/* Fetch records */
|
|
1009
|
+
consumed = test_share_consume_msgs(consumer, msgcnt, 50, 500, NULL, 0);
|
|
1010
|
+
TEST_SAY("fetch_and_close: consumed %d/%d\n", consumed, msgcnt);
|
|
1011
|
+
|
|
1012
|
+
/* Close — sends ShareAcknowledge/ShareFetch with epoch=-1 */
|
|
1013
|
+
test_share_consumer_close(consumer);
|
|
1014
|
+
test_share_destroy(consumer);
|
|
1015
|
+
test_ctx_destroy(&ctx);
|
|
1016
|
+
|
|
1017
|
+
TEST_ASSERT(consumed == msgcnt, "Expected %d consumed, got %d", msgcnt,
|
|
1018
|
+
consumed);
|
|
1019
|
+
SUB_TEST_PASS();
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
/**
|
|
1023
|
+
* @brief Test that SHARE_SESSION_LIMIT_REACHED is returned when the
|
|
1024
|
+
* session cache is full.
|
|
1025
|
+
*
|
|
1026
|
+
* Set max_fetch_sessions=1, open a session with consumer 1,
|
|
1027
|
+
* then attempt to open a second session with consumer 2.
|
|
1028
|
+
* Consumer 2 should fail to consume any records because every
|
|
1029
|
+
* ShareFetch epoch=0 attempt gets SHARE_SESSION_LIMIT_REACHED.
|
|
1030
|
+
*/
|
|
1031
|
+
static void do_test_session_limit_reached(void) {
|
|
1032
|
+
const char *topic = "kip932_session_limit";
|
|
1033
|
+
const int msgcnt = 5;
|
|
1034
|
+
test_ctx_t ctx;
|
|
1035
|
+
rd_kafka_share_t *consumer1, *consumer2;
|
|
1036
|
+
int consumed1, consumed2;
|
|
1037
|
+
|
|
1038
|
+
SUB_TEST_QUICK();
|
|
1039
|
+
|
|
1040
|
+
ctx = test_ctx_new();
|
|
1041
|
+
|
|
1042
|
+
/* Limit to 1 session */
|
|
1043
|
+
rd_kafka_mock_sharegroup_set_max_fetch_sessions(ctx.mcluster, 1);
|
|
1044
|
+
|
|
1045
|
+
TEST_ASSERT(rd_kafka_mock_topic_create(ctx.mcluster, topic, 1, 1) ==
|
|
1046
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
1047
|
+
"Failed to create mock topic");
|
|
1048
|
+
test_produce_msgs_simple(ctx.producer, topic, RD_KAFKA_PARTITION_UA,
|
|
1049
|
+
msgcnt);
|
|
1050
|
+
|
|
1051
|
+
/* Consumer 1 opens a session successfully */
|
|
1052
|
+
consumer1 = new_share_consumer(ctx.bootstraps, "sg-session-limit");
|
|
1053
|
+
subscribe_topics(consumer1, &topic, 1);
|
|
1054
|
+
consumed1 =
|
|
1055
|
+
test_share_consume_msgs(consumer1, msgcnt, 30, 500, NULL, 0);
|
|
1056
|
+
TEST_ASSERT(consumed1 == msgcnt,
|
|
1057
|
+
"Consumer 1: expected %d consumed, got %d", msgcnt,
|
|
1058
|
+
consumed1);
|
|
1059
|
+
|
|
1060
|
+
/* Consumer 2 tries to open a session — cache is full */
|
|
1061
|
+
consumer2 = new_share_consumer(ctx.bootstraps, "sg-session-limit");
|
|
1062
|
+
subscribe_topics(consumer2, &topic, 1);
|
|
1063
|
+
consumed2 = test_share_consume_msgs(consumer2, 1, 5, 500, NULL, 0);
|
|
1064
|
+
TEST_ASSERT(consumed2 == 0,
|
|
1065
|
+
"Consumer 2: expected 0 consumed (session limit), got %d",
|
|
1066
|
+
consumed2);
|
|
1067
|
+
|
|
1068
|
+
rd_kafka_share_consumer_close(consumer1);
|
|
1069
|
+
rd_kafka_share_destroy(consumer1);
|
|
1070
|
+
rd_kafka_share_consumer_close(consumer2);
|
|
1071
|
+
rd_kafka_share_destroy(consumer2);
|
|
1072
|
+
test_ctx_destroy(&ctx);
|
|
1073
|
+
|
|
1074
|
+
SUB_TEST_PASS();
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
/**
|
|
1078
|
+
* @brief Test that the session limit is enforced per broker, not globally.
|
|
1079
|
+
*
|
|
1080
|
+
* Create two single-partition topics, each with its leader on a
|
|
1081
|
+
* different broker. Set max_fetch_sessions=1 (per broker).
|
|
1082
|
+
*
|
|
1083
|
+
* Consumer 1 subscribes to topic_a (broker 1) and consumer 2 subscribes
|
|
1084
|
+
* to topic_b (broker 2). Both should succeed because each broker only
|
|
1085
|
+
* has 1 session despite there being 2 sessions globally.
|
|
1086
|
+
*
|
|
1087
|
+
* Then consumer 3 subscribes to topic_a — this should fail because
|
|
1088
|
+
* broker 1 already has 1 session (from consumer 1).
|
|
1089
|
+
*/
|
|
1090
|
+
static void do_test_session_limit_per_broker(void) {
|
|
1091
|
+
const char *topic_a = "kip932_session_limit_pb_a";
|
|
1092
|
+
const char *topic_b = "kip932_session_limit_pb_b";
|
|
1093
|
+
const int msgcnt = 5;
|
|
1094
|
+
test_ctx_t ctx;
|
|
1095
|
+
rd_kafka_share_t *consumer1, *consumer2, *consumer3;
|
|
1096
|
+
int consumed1, consumed2, consumed3;
|
|
1097
|
+
|
|
1098
|
+
SUB_TEST();
|
|
1099
|
+
|
|
1100
|
+
ctx = test_ctx_new();
|
|
1101
|
+
|
|
1102
|
+
/* Create two topics, each with 1 partition on a different broker. */
|
|
1103
|
+
TEST_ASSERT(rd_kafka_mock_topic_create(ctx.mcluster, topic_a, 1, 1) ==
|
|
1104
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
1105
|
+
"Failed to create mock topic A");
|
|
1106
|
+
TEST_ASSERT(rd_kafka_mock_topic_create(ctx.mcluster, topic_b, 1, 1) ==
|
|
1107
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
1108
|
+
"Failed to create mock topic B");
|
|
1109
|
+
rd_kafka_mock_partition_set_leader(ctx.mcluster, topic_a, 0, 1);
|
|
1110
|
+
rd_kafka_mock_partition_set_leader(ctx.mcluster, topic_b, 0, 2);
|
|
1111
|
+
|
|
1112
|
+
test_produce_msgs_simple(ctx.producer, topic_a, RD_KAFKA_PARTITION_UA,
|
|
1113
|
+
msgcnt);
|
|
1114
|
+
test_produce_msgs_simple(ctx.producer, topic_b, RD_KAFKA_PARTITION_UA,
|
|
1115
|
+
msgcnt);
|
|
1116
|
+
|
|
1117
|
+
/* Limit to 1 session per broker */
|
|
1118
|
+
rd_kafka_mock_sharegroup_set_max_fetch_sessions(ctx.mcluster, 1);
|
|
1119
|
+
|
|
1120
|
+
/* Consumer 1 subscribes to topic_a -> session on broker 1 */
|
|
1121
|
+
consumer1 = new_share_consumer(ctx.bootstraps, "sg-session-limit-pb");
|
|
1122
|
+
subscribe_topics(consumer1, &topic_a, 1);
|
|
1123
|
+
consumed1 =
|
|
1124
|
+
test_share_consume_msgs(consumer1, msgcnt, 30, 500, NULL, 0);
|
|
1125
|
+
TEST_ASSERT(consumed1 == msgcnt,
|
|
1126
|
+
"Consumer 1: expected %d consumed, got %d", msgcnt,
|
|
1127
|
+
consumed1);
|
|
1128
|
+
|
|
1129
|
+
/* Consumer 2 subscribes to topic_b -> session on broker 2.
|
|
1130
|
+
* If the limit were global, this would fail (2 sessions > limit 1).
|
|
1131
|
+
* Per-broker: broker 2 has 0 sessions, so it succeeds. */
|
|
1132
|
+
consumer2 = new_share_consumer(ctx.bootstraps, "sg-session-limit-pb");
|
|
1133
|
+
subscribe_topics(consumer2, &topic_b, 1);
|
|
1134
|
+
consumed2 =
|
|
1135
|
+
test_share_consume_msgs(consumer2, msgcnt, 30, 500, NULL, 0);
|
|
1136
|
+
TEST_ASSERT(consumed2 == msgcnt,
|
|
1137
|
+
"Consumer 2: expected %d consumed, got %d", msgcnt,
|
|
1138
|
+
consumed2);
|
|
1139
|
+
|
|
1140
|
+
/* Consumer 3 subscribes to topic_a -> broker 1 already has
|
|
1141
|
+
* 1 session (from consumer 1), so this should be rejected. */
|
|
1142
|
+
consumer3 = new_share_consumer(ctx.bootstraps, "sg-session-limit-pb");
|
|
1143
|
+
subscribe_topics(consumer3, &topic_a, 1);
|
|
1144
|
+
consumed3 = test_share_consume_msgs(consumer3, 1, 5, 500, NULL, 0);
|
|
1145
|
+
TEST_ASSERT(consumed3 == 0,
|
|
1146
|
+
"Consumer 3: expected 0 consumed (broker 1 at limit), "
|
|
1147
|
+
"got %d",
|
|
1148
|
+
consumed3);
|
|
1149
|
+
|
|
1150
|
+
rd_kafka_share_consumer_close(consumer1);
|
|
1151
|
+
rd_kafka_share_destroy(consumer1);
|
|
1152
|
+
rd_kafka_share_consumer_close(consumer2);
|
|
1153
|
+
rd_kafka_share_destroy(consumer2);
|
|
1154
|
+
rd_kafka_share_consumer_close(consumer3);
|
|
1155
|
+
rd_kafka_share_destroy(consumer3);
|
|
1156
|
+
test_ctx_destroy(&ctx);
|
|
1157
|
+
|
|
1158
|
+
SUB_TEST_PASS();
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
/**
|
|
1162
|
+
* @brief Test that ShareFetch with epoch=0 and acks is rejected with
|
|
1163
|
+
* INVALID_REQUEST via the mock broker's injected error mechanism.
|
|
1164
|
+
*
|
|
1165
|
+
* Injects SHARE_SESSION_LIMIT_REACHED errors to force the client to
|
|
1166
|
+
* retry with epoch=0. The client never piggybacks acks on epoch=0
|
|
1167
|
+
* (that's a protocol violation), so this test validates that the mock
|
|
1168
|
+
* broker's error injection for SHARE_SESSION_LIMIT_REACHED works and
|
|
1169
|
+
* the client recovers when the error clears.
|
|
1170
|
+
*/
|
|
1171
|
+
static void do_test_session_limit_recovery(void) {
|
|
1172
|
+
const char *topic = "kip932_session_limit_recovery";
|
|
1173
|
+
const int msgcnt = 5;
|
|
1174
|
+
test_ctx_t ctx = test_ctx_new();
|
|
1175
|
+
rd_kafka_share_t *consumer;
|
|
1176
|
+
int consumed;
|
|
1177
|
+
|
|
1178
|
+
SUB_TEST_QUICK();
|
|
1179
|
+
|
|
1180
|
+
TEST_ASSERT(rd_kafka_mock_topic_create(ctx.mcluster, topic, 1, 1) ==
|
|
1181
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
1182
|
+
"Failed to create mock topic");
|
|
1183
|
+
test_produce_msgs_simple(ctx.producer, topic, RD_KAFKA_PARTITION_UA,
|
|
1184
|
+
msgcnt);
|
|
1185
|
+
|
|
1186
|
+
/* Push 3 SHARE_SESSION_LIMIT_REACHED errors, then let it succeed */
|
|
1187
|
+
rd_kafka_mock_push_request_errors(
|
|
1188
|
+
ctx.mcluster, RD_KAFKAP_ShareFetch, 3,
|
|
1189
|
+
RD_KAFKA_RESP_ERR_SHARE_SESSION_LIMIT_REACHED,
|
|
1190
|
+
RD_KAFKA_RESP_ERR_SHARE_SESSION_LIMIT_REACHED,
|
|
1191
|
+
RD_KAFKA_RESP_ERR_SHARE_SESSION_LIMIT_REACHED);
|
|
1192
|
+
|
|
1193
|
+
consumer = new_share_consumer(ctx.bootstraps, "sg-session-recovery");
|
|
1194
|
+
subscribe_topics(consumer, &topic, 1);
|
|
1195
|
+
consumed = test_share_consume_msgs(consumer, msgcnt, 30, 500, NULL, 0);
|
|
1196
|
+
|
|
1197
|
+
rd_kafka_share_consumer_close(consumer);
|
|
1198
|
+
rd_kafka_share_destroy(consumer);
|
|
1199
|
+
test_ctx_destroy(&ctx);
|
|
1200
|
+
|
|
1201
|
+
TEST_ASSERT(consumed == msgcnt,
|
|
1202
|
+
"Expected %d consumed after recovery, got %d", msgcnt,
|
|
1203
|
+
consumed);
|
|
1204
|
+
|
|
1205
|
+
SUB_TEST_PASS();
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
/**
|
|
1209
|
+
* @brief Test that max_record_locks limits the number of in-flight
|
|
1210
|
+
* records per share-partition.
|
|
1211
|
+
*
|
|
1212
|
+
* Produce 10 records, set max_record_locks=3. Consumer A should get
|
|
1213
|
+
* only 3 records on the first fetch round (the rest are blocked by
|
|
1214
|
+
* the lock limit). After A acks (via second poll) and closes,
|
|
1215
|
+
* consumer B should get the next batch. Total consumed across both
|
|
1216
|
+
* should be 10.
|
|
1217
|
+
*/
|
|
1218
|
+
static void do_test_max_record_locks(void) {
|
|
1219
|
+
const char *topic = "kip932_max_record_locks";
|
|
1220
|
+
const int msgcnt = 10;
|
|
1221
|
+
test_ctx_t ctx;
|
|
1222
|
+
rd_kafka_share_t *consumer;
|
|
1223
|
+
int total_consumed = 0;
|
|
1224
|
+
int rounds = 0;
|
|
1225
|
+
|
|
1226
|
+
SUB_TEST_QUICK();
|
|
1227
|
+
ctx = test_ctx_new();
|
|
1228
|
+
|
|
1229
|
+
rd_kafka_mock_sharegroup_set_max_record_locks(ctx.mcluster, 3);
|
|
1230
|
+
|
|
1231
|
+
TEST_ASSERT(rd_kafka_mock_topic_create(ctx.mcluster, topic, 1, 1) ==
|
|
1232
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
1233
|
+
"Failed to create mock topic");
|
|
1234
|
+
test_produce_msgs_simple(ctx.producer, topic, RD_KAFKA_PARTITION_UA,
|
|
1235
|
+
msgcnt);
|
|
1236
|
+
|
|
1237
|
+
/* Consume in rounds. Each round can get at most 3 records
|
|
1238
|
+
* (the lock limit). The implicit ack from the next poll
|
|
1239
|
+
* frees the locks for the next batch. */
|
|
1240
|
+
consumer = new_share_consumer(ctx.bootstraps, "sg-max-locks");
|
|
1241
|
+
subscribe_topics(consumer, &topic, 1);
|
|
1242
|
+
|
|
1243
|
+
while (total_consumed < msgcnt && rounds < 20) {
|
|
1244
|
+
int got =
|
|
1245
|
+
test_share_consume_msgs(consumer, 3, 10, 500, NULL, 0);
|
|
1246
|
+
if (got == 0)
|
|
1247
|
+
break;
|
|
1248
|
+
total_consumed += got;
|
|
1249
|
+
rounds++;
|
|
1250
|
+
TEST_SAY(
|
|
1251
|
+
"max_record_locks: round %d consumed %d (total %d/%d)\n",
|
|
1252
|
+
rounds, got, total_consumed, msgcnt);
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1255
|
+
rd_kafka_share_consumer_close(consumer);
|
|
1256
|
+
rd_kafka_share_destroy(consumer);
|
|
1257
|
+
test_ctx_destroy(&ctx);
|
|
1258
|
+
|
|
1259
|
+
TEST_ASSERT(total_consumed == msgcnt,
|
|
1260
|
+
"Expected %d total consumed, got %d", msgcnt,
|
|
1261
|
+
total_consumed);
|
|
1262
|
+
TEST_ASSERT(rounds > 1,
|
|
1263
|
+
"Expected multiple rounds (lock limit=3, msgs=10), "
|
|
1264
|
+
"got %d rounds",
|
|
1265
|
+
rounds);
|
|
1266
|
+
|
|
1267
|
+
SUB_TEST_PASS();
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
/**
|
|
1271
|
+
* @brief Verify that max_record_locks counts only ACQUIRED records,
|
|
1272
|
+
* not total inflight records (which includes ARCHIVED).
|
|
1273
|
+
*
|
|
1274
|
+
* Produce 6 records. Set max_record_locks=3, max_delivery_attempts=1.
|
|
1275
|
+
*
|
|
1276
|
+
* Consumer A acquires records 0-2 (lock limit), then is destroyed
|
|
1277
|
+
* WITHOUT close (no implicit ack). The connection close releases
|
|
1278
|
+
* the locks; with max_delivery_attempts=1 the released records
|
|
1279
|
+
* transition directly to ARCHIVED (delivery_count >= limit).
|
|
1280
|
+
*
|
|
1281
|
+
* At this point:
|
|
1282
|
+
* - Records 0-2: ARCHIVED, still in the inflight list
|
|
1283
|
+
* - SPSO = 0 (never advanced — ARCHIVED != ACKNOWLEDGED)
|
|
1284
|
+
* - inflight_cnt = 3, acquired_cnt = 0
|
|
1285
|
+
*
|
|
1286
|
+
* Consumer B subscribes. With the correct check (acquired_cnt),
|
|
1287
|
+
* records 3-5 are acquirable because only 0 records are ACQUIRED.
|
|
1288
|
+
* With an inflight_cnt-based check, the limit would block all
|
|
1289
|
+
* acquisition (inflight_cnt=3 >= max_record_locks=3).
|
|
1290
|
+
*/
|
|
1291
|
+
static void do_test_max_record_locks_acquired_only(void) {
|
|
1292
|
+
const char *topic = "kip932_max_locks_acquired_only";
|
|
1293
|
+
const int msgcnt = 6;
|
|
1294
|
+
test_ctx_t ctx;
|
|
1295
|
+
rd_kafka_share_t *consumer;
|
|
1296
|
+
int consumed_a, consumed_b;
|
|
1297
|
+
|
|
1298
|
+
SUB_TEST();
|
|
1299
|
+
ctx = test_ctx_new();
|
|
1300
|
+
|
|
1301
|
+
rd_kafka_mock_sharegroup_set_max_record_locks(ctx.mcluster, 3);
|
|
1302
|
+
rd_kafka_mock_sharegroup_set_max_delivery_attempts(ctx.mcluster, 1);
|
|
1303
|
+
rd_kafka_mock_sharegroup_set_session_timeout(ctx.mcluster, 500);
|
|
1304
|
+
|
|
1305
|
+
TEST_ASSERT(rd_kafka_mock_topic_create(ctx.mcluster, topic, 1, 1) ==
|
|
1306
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
1307
|
+
"Failed to create mock topic");
|
|
1308
|
+
test_produce_msgs_simple(ctx.producer, topic, RD_KAFKA_PARTITION_UA,
|
|
1309
|
+
msgcnt);
|
|
1310
|
+
|
|
1311
|
+
/* Consumer A: acquire first batch (3 records due to lock limit). */
|
|
1312
|
+
consumer = new_share_consumer(ctx.bootstraps, "sg-acq-only");
|
|
1313
|
+
subscribe_topics(consumer, &topic, 1);
|
|
1314
|
+
consumed_a = test_share_consume_msgs(consumer, 3, 30, 500, NULL, 0);
|
|
1315
|
+
TEST_SAY("acquired_only: A consumed %d/3\n", consumed_a);
|
|
1316
|
+
|
|
1317
|
+
/* Destroy WITHOUT close — avoids implicit ack.
|
|
1318
|
+
* The connection close releases locks; with max_delivery_attempts=1
|
|
1319
|
+
* the released records transition to ARCHIVED (not AVAILABLE).
|
|
1320
|
+
* SPSO stays at 0 because ARCHIVED != ACKNOWLEDGED.
|
|
1321
|
+
* inflight_cnt stays 3, but acquired_cnt drops to 0. */
|
|
1322
|
+
rd_kafka_share_destroy(consumer);
|
|
1323
|
+
rd_usleep(1500 * 1000, 0); /* wait for connection close */
|
|
1324
|
+
|
|
1325
|
+
/* Consumer B subscribes. The share-partition now has:
|
|
1326
|
+
* - Records 0-2: ARCHIVED (inflight_cnt=3, acquired_cnt=0)
|
|
1327
|
+
* - Records 3-5: not yet in inflight list
|
|
1328
|
+
* With acquired_cnt check, Consumer B acquires records 3-5.
|
|
1329
|
+
* With inflight_cnt check, the limit would block acquisition. */
|
|
1330
|
+
consumer = new_share_consumer(ctx.bootstraps, "sg-acq-only");
|
|
1331
|
+
subscribe_topics(consumer, &topic, 1);
|
|
1332
|
+
consumed_b = test_share_consume_msgs(consumer, 3, 30, 500, NULL, 0);
|
|
1333
|
+
TEST_SAY("acquired_only: B consumed %d/3\n", consumed_b);
|
|
1334
|
+
|
|
1335
|
+
rd_kafka_share_consumer_close(consumer);
|
|
1336
|
+
rd_kafka_share_destroy(consumer);
|
|
1337
|
+
test_ctx_destroy(&ctx);
|
|
1338
|
+
|
|
1339
|
+
TEST_ASSERT(consumed_a == 3, "A: expected 3, got %d", consumed_a);
|
|
1340
|
+
TEST_ASSERT(consumed_b == 3,
|
|
1341
|
+
"B: expected 3 (max_record_locks should count only "
|
|
1342
|
+
"ACQUIRED, not ARCHIVED), got %d",
|
|
1343
|
+
consumed_b);
|
|
1344
|
+
|
|
1345
|
+
SUB_TEST_PASS();
|
|
1346
|
+
}
|
|
1347
|
+
|
|
1348
|
+
/**
|
|
1349
|
+
* @brief Test that SPSO advances when log retention deletes records
|
|
1350
|
+
* below the current SPSO.
|
|
1351
|
+
*
|
|
1352
|
+
* Produce 10 records (offsets 0-9). Consumer A acquires 0-4.
|
|
1353
|
+
* Then delete records before offset 5 (simulating log retention).
|
|
1354
|
+
* Consumer A closes (acks 0-4, but they're already archived by
|
|
1355
|
+
* retention). Consumer B should get records 5-9 only — SPSO
|
|
1356
|
+
* was advanced to 5 by the retention, and in-flight records
|
|
1357
|
+
* below 5 were archived.
|
|
1358
|
+
*/
|
|
1359
|
+
static void do_test_spso_advances_on_log_retention(void) {
|
|
1360
|
+
const char *topic = "kip932_log_retention_spso";
|
|
1361
|
+
const int msgcnt = 10;
|
|
1362
|
+
test_ctx_t ctx;
|
|
1363
|
+
rd_kafka_share_t *consumer;
|
|
1364
|
+
int consumed_a, consumed_b;
|
|
1365
|
+
|
|
1366
|
+
SUB_TEST_QUICK();
|
|
1367
|
+
ctx = test_ctx_new();
|
|
1368
|
+
|
|
1369
|
+
/* Limit to 5 records per fetch so A gets only 0-4. */
|
|
1370
|
+
rd_kafka_mock_sharegroup_set_max_record_locks(ctx.mcluster, 5);
|
|
1371
|
+
|
|
1372
|
+
TEST_ASSERT(rd_kafka_mock_topic_create(ctx.mcluster, topic, 1, 1) ==
|
|
1373
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
1374
|
+
"Failed to create mock topic");
|
|
1375
|
+
test_produce_msgs_simple(ctx.producer, topic, RD_KAFKA_PARTITION_UA,
|
|
1376
|
+
msgcnt);
|
|
1377
|
+
|
|
1378
|
+
/* Consumer A acquires records 0-4. */
|
|
1379
|
+
consumer = new_share_consumer(ctx.bootstraps, "sg-log-retention");
|
|
1380
|
+
subscribe_topics(consumer, &topic, 1);
|
|
1381
|
+
consumed_a = test_share_consume_msgs(consumer, 5, 30, 500, NULL, 0);
|
|
1382
|
+
TEST_SAY("log_retention: A consumed %d/5\n", consumed_a);
|
|
1383
|
+
|
|
1384
|
+
rd_kafka_share_consumer_close(consumer);
|
|
1385
|
+
rd_kafka_share_destroy(consumer);
|
|
1386
|
+
|
|
1387
|
+
/* Simulate log retention: delete records before offset 5. */
|
|
1388
|
+
TEST_ASSERT(
|
|
1389
|
+
rd_kafka_mock_partition_delete_records(ctx.mcluster, topic, 0, 5) ==
|
|
1390
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
1391
|
+
"Failed to delete records");
|
|
1392
|
+
|
|
1393
|
+
/* Remove lock limit. */
|
|
1394
|
+
rd_kafka_mock_sharegroup_set_max_record_locks(ctx.mcluster, 0);
|
|
1395
|
+
|
|
1396
|
+
/* Consumer B should get records 5-9 (SPSO advanced to 5). */
|
|
1397
|
+
consumer = new_share_consumer(ctx.bootstraps, "sg-log-retention");
|
|
1398
|
+
subscribe_topics(consumer, &topic, 1);
|
|
1399
|
+
consumed_b = test_share_consume_msgs(consumer, 5, 30, 500, NULL, 0);
|
|
1400
|
+
TEST_SAY("log_retention: B consumed %d/5\n", consumed_b);
|
|
1401
|
+
|
|
1402
|
+
rd_kafka_share_consumer_close(consumer);
|
|
1403
|
+
rd_kafka_share_destroy(consumer);
|
|
1404
|
+
test_ctx_destroy(&ctx);
|
|
1405
|
+
|
|
1406
|
+
TEST_ASSERT(consumed_a == 5, "A: expected 5 consumed, got %d",
|
|
1407
|
+
consumed_a);
|
|
1408
|
+
TEST_ASSERT(consumed_b == 5, "B: expected 5 consumed, got %d",
|
|
1409
|
+
consumed_b);
|
|
1410
|
+
|
|
1411
|
+
SUB_TEST_PASS();
|
|
1412
|
+
}
|
|
1413
|
+
|
|
1414
|
+
/**
|
|
1415
|
+
* @brief Test that auto.offset.reset=latest (the default)
|
|
1416
|
+
* causes the consumer to skip records produced before subscription.
|
|
1417
|
+
*
|
|
1418
|
+
* Produce 5 records, then subscribe with auto.offset.reset=latest.
|
|
1419
|
+
* Consumer should get 0 old records but should get new records
|
|
1420
|
+
* produced after subscription.
|
|
1421
|
+
*/
|
|
1422
|
+
static void do_test_auto_offset_reset_latest(void) {
|
|
1423
|
+
const char *topic = "kip932_offset_reset_latest";
|
|
1424
|
+
const int msgcnt = 5;
|
|
1425
|
+
test_ctx_t ctx;
|
|
1426
|
+
rd_kafka_share_t *consumer;
|
|
1427
|
+
rd_kafka_conf_t *conf;
|
|
1428
|
+
char errstr[512];
|
|
1429
|
+
int consumed;
|
|
1430
|
+
|
|
1431
|
+
SUB_TEST_QUICK();
|
|
1432
|
+
|
|
1433
|
+
/* Create a fresh context — do NOT set auto_offset_reset=earliest
|
|
1434
|
+
* (the default is "latest"). */
|
|
1435
|
+
memset(&ctx, 0, sizeof(ctx));
|
|
1436
|
+
ctx.mcluster = test_mock_cluster_new(3, &ctx.bootstraps);
|
|
1437
|
+
TEST_ASSERT(rd_kafka_mock_set_apiversion(
|
|
1438
|
+
ctx.mcluster, RD_KAFKAP_ShareGroupHeartbeat, 1, 1) ==
|
|
1439
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
1440
|
+
"Failed to enable ShareGroupHeartbeat");
|
|
1441
|
+
TEST_ASSERT(rd_kafka_mock_set_apiversion(ctx.mcluster,
|
|
1442
|
+
RD_KAFKAP_ShareFetch, 1, 1) ==
|
|
1443
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
1444
|
+
"Failed to enable ShareFetch");
|
|
1445
|
+
/* Intentionally NOT calling set_auto_offset_reset — default is latest
|
|
1446
|
+
*/
|
|
1447
|
+
test_conf_init(&conf, NULL, 0);
|
|
1448
|
+
test_conf_set(conf, "bootstrap.servers", ctx.bootstraps);
|
|
1449
|
+
rd_kafka_conf_set_dr_msg_cb(conf, test_dr_msg_cb);
|
|
1450
|
+
ctx.producer =
|
|
1451
|
+
rd_kafka_new(RD_KAFKA_PRODUCER, conf, errstr, sizeof(errstr));
|
|
1452
|
+
TEST_ASSERT(ctx.producer != NULL, "Failed to create producer: %s",
|
|
1453
|
+
errstr);
|
|
1454
|
+
|
|
1455
|
+
TEST_ASSERT(rd_kafka_mock_topic_create(ctx.mcluster, topic, 1, 1) ==
|
|
1456
|
+
RD_KAFKA_RESP_ERR_NO_ERROR,
|
|
1457
|
+
"Failed to create mock topic");
|
|
1458
|
+
|
|
1459
|
+
/* Produce records BEFORE subscribing */
|
|
1460
|
+
test_produce_msgs_simple(ctx.producer, topic, RD_KAFKA_PARTITION_UA,
|
|
1461
|
+
msgcnt);
|
|
1462
|
+
|
|
1463
|
+
/* Subscribe — SPSO should start at end of log (latest) */
|
|
1464
|
+
consumer = new_share_consumer(ctx.bootstraps, "sg-offset-latest");
|
|
1465
|
+
subscribe_topics(consumer, &topic, 1);
|
|
1466
|
+
consumed = test_share_consume_msgs(consumer, 1, 5, 500, NULL, 0);
|
|
1467
|
+
TEST_SAY("offset_reset_latest: consumed %d (expected 0)\n", consumed);
|
|
1468
|
+
TEST_ASSERT(consumed == 0,
|
|
1469
|
+
"Expected 0 consumed with latest offset reset, got %d",
|
|
1470
|
+
consumed);
|
|
1471
|
+
|
|
1472
|
+
/* Produce new records AFTER subscription — these should be visible */
|
|
1473
|
+
test_produce_msgs_simple(ctx.producer, topic, RD_KAFKA_PARTITION_UA,
|
|
1474
|
+
msgcnt);
|
|
1475
|
+
consumed = test_share_consume_msgs(consumer, msgcnt, 30, 500, NULL, 0);
|
|
1476
|
+
TEST_SAY("offset_reset_latest: consumed %d new records (expected %d)\n",
|
|
1477
|
+
consumed, msgcnt);
|
|
1478
|
+
|
|
1479
|
+
rd_kafka_share_consumer_close(consumer);
|
|
1480
|
+
rd_kafka_share_destroy(consumer);
|
|
1481
|
+
test_ctx_destroy(&ctx);
|
|
1482
|
+
|
|
1483
|
+
TEST_ASSERT(consumed == msgcnt,
|
|
1484
|
+
"Expected %d new records consumed, got %d", msgcnt,
|
|
1485
|
+
consumed);
|
|
1486
|
+
|
|
1487
|
+
SUB_TEST_PASS();
|
|
1488
|
+
}
|
|
1489
|
+
|
|
1490
|
+
int main_0156_share_consumer_fetch_mock(int argc, char **argv) {
|
|
1491
|
+
TEST_SKIP_MOCK_CLUSTER(0);
|
|
1492
|
+
|
|
1493
|
+
/* This test suite has many subtests; set a generous timeout.
|
|
1494
|
+
* When running in parallel with other test suites (e.g., 0155, 0157)
|
|
1495
|
+
* the mock broker and consumer threads compete for CPU, which can
|
|
1496
|
+
* slow individual subtests by 5x or more. Use 1500s to be safe. */
|
|
1497
|
+
test_timeout_set(1500);
|
|
1498
|
+
|
|
1499
|
+
/* Positive scenarios */
|
|
1500
|
+
do_test_basic_consume();
|
|
1501
|
+
do_test_followup_fetch();
|
|
1502
|
+
do_test_multi_partition();
|
|
1503
|
+
do_test_multi_topic();
|
|
1504
|
+
do_test_empty_topic_no_records();
|
|
1505
|
+
do_test_sharefetch_session_expiry_rtt();
|
|
1506
|
+
do_test_forgotten_topics();
|
|
1507
|
+
do_test_multi_batch_consume();
|
|
1508
|
+
do_test_max_delivery_attempts();
|
|
1509
|
+
do_test_record_lock_duration();
|
|
1510
|
+
do_test_multi_consumer_lock_expiry();
|
|
1511
|
+
|
|
1512
|
+
/* Negative scenarios */
|
|
1513
|
+
do_test_sharefetch_invalid_session_epoch();
|
|
1514
|
+
do_test_sharefetch_unknown_topic_or_part();
|
|
1515
|
+
do_test_sghb_coord_unavailable();
|
|
1516
|
+
do_test_topic_error_unknown_topic_or_part();
|
|
1517
|
+
do_test_unknown_topic_subscription();
|
|
1518
|
+
do_test_empty_fetch_no_records();
|
|
1519
|
+
do_test_member_validation();
|
|
1520
|
+
|
|
1521
|
+
/* TODO KIP-932: These tests inject partition-level errors at the
|
|
1522
|
+
* top-level response field, which the broker never does for these
|
|
1523
|
+
* error codes. Replace with partition-level mock injection once
|
|
1524
|
+
* that API is available. */
|
|
1525
|
+
/* do_test_sharefetch_fetch_error_not_leader(); */
|
|
1526
|
+
/* do_test_sharefetch_fetch_error_unknown_topic_or_part(); */
|
|
1527
|
+
/* do_test_sharefetch_fetch_error_unknown_topic_id(); */
|
|
1528
|
+
/* do_test_sharefetch_fetch_error_fenced_leader_epoch(); */
|
|
1529
|
+
/* do_test_sharefetch_fetch_error_unknown_leader_epoch(); */
|
|
1530
|
+
/* do_test_sharefetch_topic_authorization_failed(); */
|
|
1531
|
+
/* do_test_sharefetch_corrupt_message(); */
|
|
1532
|
+
/* do_test_sharefetch_fetch_disconnected(); */
|
|
1533
|
+
do_test_sharefetch_fetch_and_close_implicit();
|
|
1534
|
+
|
|
1535
|
+
/* Session management */
|
|
1536
|
+
do_test_session_limit_reached();
|
|
1537
|
+
do_test_session_limit_per_broker();
|
|
1538
|
+
do_test_session_limit_recovery();
|
|
1539
|
+
|
|
1540
|
+
/* Record lock limits */
|
|
1541
|
+
do_test_max_record_locks();
|
|
1542
|
+
do_test_max_record_locks_acquired_only();
|
|
1543
|
+
|
|
1544
|
+
/* Offset reset */
|
|
1545
|
+
do_test_auto_offset_reset_latest();
|
|
1546
|
+
|
|
1547
|
+
/* Log retention */
|
|
1548
|
+
do_test_spso_advances_on_log_retention();
|
|
1549
|
+
|
|
1550
|
+
return 0;
|
|
1551
|
+
}
|