@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.
Files changed (628) hide show
  1. package/CHANGELOG.md +457 -0
  2. package/LICENSE.kafkajs +31 -0
  3. package/LICENSE.node-rdkafka +25 -0
  4. package/LICENSE.txt +20 -0
  5. package/README.md +133 -0
  6. package/binding.gyp +184 -0
  7. package/build/Release/confluent-kafka-javascript.node +0 -0
  8. package/build/deps/librdkafka++.so.1 +0 -0
  9. package/build/deps/librdkafka.Makefile +6 -0
  10. package/build/deps/librdkafka.so.1 +0 -0
  11. package/build/deps/librdkafka.target.mk +55 -0
  12. package/deps/librdkafka/.clang-format +136 -0
  13. package/deps/librdkafka/.clang-format-cpp +103 -0
  14. package/deps/librdkafka/.dir-locals.el +10 -0
  15. package/deps/librdkafka/.formatignore +35 -0
  16. package/deps/librdkafka/.gdbmacros +19 -0
  17. package/deps/librdkafka/CHANGELOG.md +2477 -0
  18. package/deps/librdkafka/CMakeLists.txt +291 -0
  19. package/deps/librdkafka/CODE_OF_CONDUCT.md +46 -0
  20. package/deps/librdkafka/CONFIGURATION.md +212 -0
  21. package/deps/librdkafka/CONTRIBUTING.md +431 -0
  22. package/deps/librdkafka/Doxyfile +2375 -0
  23. package/deps/librdkafka/INTRODUCTION.md +2752 -0
  24. package/deps/librdkafka/LICENSE +26 -0
  25. package/deps/librdkafka/LICENSE.cjson +22 -0
  26. package/deps/librdkafka/LICENSE.crc32c +28 -0
  27. package/deps/librdkafka/LICENSE.fnv1a +18 -0
  28. package/deps/librdkafka/LICENSE.hdrhistogram +27 -0
  29. package/deps/librdkafka/LICENSE.lz4 +26 -0
  30. package/deps/librdkafka/LICENSE.murmur2 +25 -0
  31. package/deps/librdkafka/LICENSE.nanopb +22 -0
  32. package/deps/librdkafka/LICENSE.opentelemetry +203 -0
  33. package/deps/librdkafka/LICENSE.pycrc +23 -0
  34. package/deps/librdkafka/LICENSE.queue +31 -0
  35. package/deps/librdkafka/LICENSE.regexp +5 -0
  36. package/deps/librdkafka/LICENSE.snappy +36 -0
  37. package/deps/librdkafka/LICENSE.tinycthread +26 -0
  38. package/deps/librdkafka/LICENSE.wingetopt +49 -0
  39. package/deps/librdkafka/LICENSES.txt +625 -0
  40. package/deps/librdkafka/Makefile +125 -0
  41. package/deps/librdkafka/README.md +201 -0
  42. package/deps/librdkafka/README.win32 +26 -0
  43. package/deps/librdkafka/STATISTICS.md +624 -0
  44. package/deps/librdkafka/configure +214 -0
  45. package/deps/librdkafka/configure.self +341 -0
  46. package/deps/librdkafka/dev-conf.sh +123 -0
  47. package/deps/librdkafka/lds-gen.py +73 -0
  48. package/deps/librdkafka/mainpage.doxy +40 -0
  49. package/deps/librdkafka/mklove/Makefile.base +329 -0
  50. package/deps/librdkafka/mklove/modules/configure.atomics +144 -0
  51. package/deps/librdkafka/mklove/modules/configure.base +2484 -0
  52. package/deps/librdkafka/mklove/modules/configure.builtin +70 -0
  53. package/deps/librdkafka/mklove/modules/configure.cc +186 -0
  54. package/deps/librdkafka/mklove/modules/configure.cxx +8 -0
  55. package/deps/librdkafka/mklove/modules/configure.fileversion +65 -0
  56. package/deps/librdkafka/mklove/modules/configure.gitversion +29 -0
  57. package/deps/librdkafka/mklove/modules/configure.good_cflags +18 -0
  58. package/deps/librdkafka/mklove/modules/configure.host +132 -0
  59. package/deps/librdkafka/mklove/modules/configure.lib +49 -0
  60. package/deps/librdkafka/mklove/modules/configure.libcurl +99 -0
  61. package/deps/librdkafka/mklove/modules/configure.libsasl2 +36 -0
  62. package/deps/librdkafka/mklove/modules/configure.libssl +147 -0
  63. package/deps/librdkafka/mklove/modules/configure.libzstd +58 -0
  64. package/deps/librdkafka/mklove/modules/configure.parseversion +95 -0
  65. package/deps/librdkafka/mklove/modules/configure.pic +16 -0
  66. package/deps/librdkafka/mklove/modules/configure.socket +20 -0
  67. package/deps/librdkafka/mklove/modules/configure.zlib +61 -0
  68. package/deps/librdkafka/mklove/modules/patches/README.md +8 -0
  69. package/deps/librdkafka/mklove/modules/patches/libcurl.0000-no-runtime-linking-check.patch +11 -0
  70. package/deps/librdkafka/mklove/modules/patches/libssl.0000-osx-rand-include-fix-OpenSSL-PR16409.patch +56 -0
  71. package/deps/librdkafka/service.yml +182 -0
  72. package/deps/librdkafka/src/CMakeLists.txt +379 -0
  73. package/deps/librdkafka/src/Makefile +105 -0
  74. package/deps/librdkafka/src/README.lz4.md +30 -0
  75. package/deps/librdkafka/src/cJSON.c +3191 -0
  76. package/deps/librdkafka/src/cJSON.h +306 -0
  77. package/deps/librdkafka/src/crc32c.c +430 -0
  78. package/deps/librdkafka/src/crc32c.h +38 -0
  79. package/deps/librdkafka/src/generate_proto.sh +66 -0
  80. package/deps/librdkafka/src/librdkafka_cgrp_synch.png +0 -0
  81. package/deps/librdkafka/src/lz4.c +2727 -0
  82. package/deps/librdkafka/src/lz4.h +842 -0
  83. package/deps/librdkafka/src/lz4frame.c +2078 -0
  84. package/deps/librdkafka/src/lz4frame.h +692 -0
  85. package/deps/librdkafka/src/lz4frame_static.h +47 -0
  86. package/deps/librdkafka/src/lz4hc.c +1631 -0
  87. package/deps/librdkafka/src/lz4hc.h +413 -0
  88. package/deps/librdkafka/src/nanopb/pb.h +917 -0
  89. package/deps/librdkafka/src/nanopb/pb_common.c +388 -0
  90. package/deps/librdkafka/src/nanopb/pb_common.h +49 -0
  91. package/deps/librdkafka/src/nanopb/pb_decode.c +1727 -0
  92. package/deps/librdkafka/src/nanopb/pb_decode.h +193 -0
  93. package/deps/librdkafka/src/nanopb/pb_encode.c +1000 -0
  94. package/deps/librdkafka/src/nanopb/pb_encode.h +185 -0
  95. package/deps/librdkafka/src/opentelemetry/common.pb.c +32 -0
  96. package/deps/librdkafka/src/opentelemetry/common.pb.h +170 -0
  97. package/deps/librdkafka/src/opentelemetry/metrics.options +2 -0
  98. package/deps/librdkafka/src/opentelemetry/metrics.pb.c +67 -0
  99. package/deps/librdkafka/src/opentelemetry/metrics.pb.h +966 -0
  100. package/deps/librdkafka/src/opentelemetry/resource.pb.c +12 -0
  101. package/deps/librdkafka/src/opentelemetry/resource.pb.h +58 -0
  102. package/deps/librdkafka/src/queue.h +850 -0
  103. package/deps/librdkafka/src/rd.h +592 -0
  104. package/deps/librdkafka/src/rdaddr.c +255 -0
  105. package/deps/librdkafka/src/rdaddr.h +202 -0
  106. package/deps/librdkafka/src/rdatomic.h +262 -0
  107. package/deps/librdkafka/src/rdavg.h +260 -0
  108. package/deps/librdkafka/src/rdavl.c +210 -0
  109. package/deps/librdkafka/src/rdavl.h +250 -0
  110. package/deps/librdkafka/src/rdbase64.c +200 -0
  111. package/deps/librdkafka/src/rdbase64.h +43 -0
  112. package/deps/librdkafka/src/rdbuf.c +1884 -0
  113. package/deps/librdkafka/src/rdbuf.h +375 -0
  114. package/deps/librdkafka/src/rdcrc32.c +114 -0
  115. package/deps/librdkafka/src/rdcrc32.h +170 -0
  116. package/deps/librdkafka/src/rddl.c +179 -0
  117. package/deps/librdkafka/src/rddl.h +43 -0
  118. package/deps/librdkafka/src/rdendian.h +175 -0
  119. package/deps/librdkafka/src/rdfloat.h +67 -0
  120. package/deps/librdkafka/src/rdfnv1a.c +113 -0
  121. package/deps/librdkafka/src/rdfnv1a.h +35 -0
  122. package/deps/librdkafka/src/rdgz.c +120 -0
  123. package/deps/librdkafka/src/rdgz.h +46 -0
  124. package/deps/librdkafka/src/rdhdrhistogram.c +721 -0
  125. package/deps/librdkafka/src/rdhdrhistogram.h +87 -0
  126. package/deps/librdkafka/src/rdhttp.c +831 -0
  127. package/deps/librdkafka/src/rdhttp.h +101 -0
  128. package/deps/librdkafka/src/rdinterval.h +177 -0
  129. package/deps/librdkafka/src/rdkafka.c +7287 -0
  130. package/deps/librdkafka/src/rdkafka.h +11795 -0
  131. package/deps/librdkafka/src/rdkafka_admin.c +10165 -0
  132. package/deps/librdkafka/src/rdkafka_admin.h +658 -0
  133. package/deps/librdkafka/src/rdkafka_assignment.c +1282 -0
  134. package/deps/librdkafka/src/rdkafka_assignment.h +73 -0
  135. package/deps/librdkafka/src/rdkafka_assignor.c +1800 -0
  136. package/deps/librdkafka/src/rdkafka_assignor.h +402 -0
  137. package/deps/librdkafka/src/rdkafka_aux.c +409 -0
  138. package/deps/librdkafka/src/rdkafka_aux.h +174 -0
  139. package/deps/librdkafka/src/rdkafka_background.c +222 -0
  140. package/deps/librdkafka/src/rdkafka_broker.c +6736 -0
  141. package/deps/librdkafka/src/rdkafka_broker.h +851 -0
  142. package/deps/librdkafka/src/rdkafka_buf.c +543 -0
  143. package/deps/librdkafka/src/rdkafka_buf.h +1525 -0
  144. package/deps/librdkafka/src/rdkafka_cert.c +576 -0
  145. package/deps/librdkafka/src/rdkafka_cert.h +62 -0
  146. package/deps/librdkafka/src/rdkafka_cgrp.c +8310 -0
  147. package/deps/librdkafka/src/rdkafka_cgrp.h +589 -0
  148. package/deps/librdkafka/src/rdkafka_conf.c +5177 -0
  149. package/deps/librdkafka/src/rdkafka_conf.h +746 -0
  150. package/deps/librdkafka/src/rdkafka_confval.h +97 -0
  151. package/deps/librdkafka/src/rdkafka_coord.c +623 -0
  152. package/deps/librdkafka/src/rdkafka_coord.h +132 -0
  153. package/deps/librdkafka/src/rdkafka_error.c +228 -0
  154. package/deps/librdkafka/src/rdkafka_error.h +80 -0
  155. package/deps/librdkafka/src/rdkafka_event.c +502 -0
  156. package/deps/librdkafka/src/rdkafka_event.h +126 -0
  157. package/deps/librdkafka/src/rdkafka_feature.c +898 -0
  158. package/deps/librdkafka/src/rdkafka_feature.h +104 -0
  159. package/deps/librdkafka/src/rdkafka_fetcher.c +3820 -0
  160. package/deps/librdkafka/src/rdkafka_fetcher.h +62 -0
  161. package/deps/librdkafka/src/rdkafka_header.c +220 -0
  162. package/deps/librdkafka/src/rdkafka_header.h +76 -0
  163. package/deps/librdkafka/src/rdkafka_idempotence.c +807 -0
  164. package/deps/librdkafka/src/rdkafka_idempotence.h +144 -0
  165. package/deps/librdkafka/src/rdkafka_int.h +1505 -0
  166. package/deps/librdkafka/src/rdkafka_interceptor.c +842 -0
  167. package/deps/librdkafka/src/rdkafka_interceptor.h +104 -0
  168. package/deps/librdkafka/src/rdkafka_lz4.c +450 -0
  169. package/deps/librdkafka/src/rdkafka_lz4.h +49 -0
  170. package/deps/librdkafka/src/rdkafka_metadata.c +2347 -0
  171. package/deps/librdkafka/src/rdkafka_metadata.h +350 -0
  172. package/deps/librdkafka/src/rdkafka_metadata_cache.c +1183 -0
  173. package/deps/librdkafka/src/rdkafka_mock.c +4514 -0
  174. package/deps/librdkafka/src/rdkafka_mock.h +867 -0
  175. package/deps/librdkafka/src/rdkafka_mock_cgrp.c +1877 -0
  176. package/deps/librdkafka/src/rdkafka_mock_handlers.c +5255 -0
  177. package/deps/librdkafka/src/rdkafka_mock_int.h +1005 -0
  178. package/deps/librdkafka/src/rdkafka_mock_sharegrp.c +1207 -0
  179. package/deps/librdkafka/src/rdkafka_msg.c +2619 -0
  180. package/deps/librdkafka/src/rdkafka_msg.h +629 -0
  181. package/deps/librdkafka/src/rdkafka_msgbatch.h +62 -0
  182. package/deps/librdkafka/src/rdkafka_msgset.h +105 -0
  183. package/deps/librdkafka/src/rdkafka_msgset_reader.c +2099 -0
  184. package/deps/librdkafka/src/rdkafka_msgset_writer.c +1474 -0
  185. package/deps/librdkafka/src/rdkafka_offset.c +1565 -0
  186. package/deps/librdkafka/src/rdkafka_offset.h +150 -0
  187. package/deps/librdkafka/src/rdkafka_op.c +1219 -0
  188. package/deps/librdkafka/src/rdkafka_op.h +1065 -0
  189. package/deps/librdkafka/src/rdkafka_partition.c +5109 -0
  190. package/deps/librdkafka/src/rdkafka_partition.h +1215 -0
  191. package/deps/librdkafka/src/rdkafka_pattern.c +228 -0
  192. package/deps/librdkafka/src/rdkafka_pattern.h +70 -0
  193. package/deps/librdkafka/src/rdkafka_plugin.c +213 -0
  194. package/deps/librdkafka/src/rdkafka_plugin.h +41 -0
  195. package/deps/librdkafka/src/rdkafka_proto.h +739 -0
  196. package/deps/librdkafka/src/rdkafka_protocol.h +131 -0
  197. package/deps/librdkafka/src/rdkafka_queue.c +1351 -0
  198. package/deps/librdkafka/src/rdkafka_queue.h +1235 -0
  199. package/deps/librdkafka/src/rdkafka_range_assignor.c +1748 -0
  200. package/deps/librdkafka/src/rdkafka_request.c +7298 -0
  201. package/deps/librdkafka/src/rdkafka_request.h +761 -0
  202. package/deps/librdkafka/src/rdkafka_roundrobin_assignor.c +123 -0
  203. package/deps/librdkafka/src/rdkafka_sasl.c +589 -0
  204. package/deps/librdkafka/src/rdkafka_sasl.h +63 -0
  205. package/deps/librdkafka/src/rdkafka_sasl_cyrus.c +722 -0
  206. package/deps/librdkafka/src/rdkafka_sasl_int.h +89 -0
  207. package/deps/librdkafka/src/rdkafka_sasl_oauthbearer.c +1833 -0
  208. package/deps/librdkafka/src/rdkafka_sasl_oauthbearer.h +52 -0
  209. package/deps/librdkafka/src/rdkafka_sasl_oauthbearer_oidc.c +1827 -0
  210. package/deps/librdkafka/src/rdkafka_sasl_oauthbearer_oidc.h +52 -0
  211. package/deps/librdkafka/src/rdkafka_sasl_plain.c +142 -0
  212. package/deps/librdkafka/src/rdkafka_sasl_scram.c +858 -0
  213. package/deps/librdkafka/src/rdkafka_sasl_win32.c +550 -0
  214. package/deps/librdkafka/src/rdkafka_share_acknowledgement.c +1445 -0
  215. package/deps/librdkafka/src/rdkafka_share_acknowledgement.h +373 -0
  216. package/deps/librdkafka/src/rdkafka_ssl.c +2235 -0
  217. package/deps/librdkafka/src/rdkafka_ssl.h +86 -0
  218. package/deps/librdkafka/src/rdkafka_sticky_assignor.c +4785 -0
  219. package/deps/librdkafka/src/rdkafka_subscription.c +411 -0
  220. package/deps/librdkafka/src/rdkafka_telemetry.c +761 -0
  221. package/deps/librdkafka/src/rdkafka_telemetry.h +52 -0
  222. package/deps/librdkafka/src/rdkafka_telemetry_decode.c +1307 -0
  223. package/deps/librdkafka/src/rdkafka_telemetry_decode.h +59 -0
  224. package/deps/librdkafka/src/rdkafka_telemetry_encode.c +1309 -0
  225. package/deps/librdkafka/src/rdkafka_telemetry_encode.h +459 -0
  226. package/deps/librdkafka/src/rdkafka_timer.c +407 -0
  227. package/deps/librdkafka/src/rdkafka_timer.h +117 -0
  228. package/deps/librdkafka/src/rdkafka_topic.c +2382 -0
  229. package/deps/librdkafka/src/rdkafka_topic.h +369 -0
  230. package/deps/librdkafka/src/rdkafka_transport.c +1309 -0
  231. package/deps/librdkafka/src/rdkafka_transport.h +99 -0
  232. package/deps/librdkafka/src/rdkafka_transport_int.h +100 -0
  233. package/deps/librdkafka/src/rdkafka_txnmgr.c +3256 -0
  234. package/deps/librdkafka/src/rdkafka_txnmgr.h +171 -0
  235. package/deps/librdkafka/src/rdkafka_zstd.c +226 -0
  236. package/deps/librdkafka/src/rdkafka_zstd.h +57 -0
  237. package/deps/librdkafka/src/rdlist.c +593 -0
  238. package/deps/librdkafka/src/rdlist.h +444 -0
  239. package/deps/librdkafka/src/rdlog.c +89 -0
  240. package/deps/librdkafka/src/rdlog.h +41 -0
  241. package/deps/librdkafka/src/rdmap.c +508 -0
  242. package/deps/librdkafka/src/rdmap.h +492 -0
  243. package/deps/librdkafka/src/rdmurmur2.c +167 -0
  244. package/deps/librdkafka/src/rdmurmur2.h +35 -0
  245. package/deps/librdkafka/src/rdports.c +61 -0
  246. package/deps/librdkafka/src/rdports.h +38 -0
  247. package/deps/librdkafka/src/rdposix.h +250 -0
  248. package/deps/librdkafka/src/rdrand.c +151 -0
  249. package/deps/librdkafka/src/rdrand.h +72 -0
  250. package/deps/librdkafka/src/rdregex.c +156 -0
  251. package/deps/librdkafka/src/rdregex.h +43 -0
  252. package/deps/librdkafka/src/rdsignal.h +57 -0
  253. package/deps/librdkafka/src/rdstring.c +645 -0
  254. package/deps/librdkafka/src/rdstring.h +98 -0
  255. package/deps/librdkafka/src/rdsysqueue.h +404 -0
  256. package/deps/librdkafka/src/rdtime.h +356 -0
  257. package/deps/librdkafka/src/rdtypes.h +86 -0
  258. package/deps/librdkafka/src/rdunittest.c +564 -0
  259. package/deps/librdkafka/src/rdunittest.h +232 -0
  260. package/deps/librdkafka/src/rdunittest_acknowledge.c +1177 -0
  261. package/deps/librdkafka/src/rdunittest_fetcher.c +1211 -0
  262. package/deps/librdkafka/src/rdunittest_msgset_errors.c +1521 -0
  263. package/deps/librdkafka/src/rdvarint.c +134 -0
  264. package/deps/librdkafka/src/rdvarint.h +165 -0
  265. package/deps/librdkafka/src/rdwin32.h +382 -0
  266. package/deps/librdkafka/src/rdxxhash.c +1030 -0
  267. package/deps/librdkafka/src/rdxxhash.h +328 -0
  268. package/deps/librdkafka/src/regexp.c +1352 -0
  269. package/deps/librdkafka/src/regexp.h +41 -0
  270. package/deps/librdkafka/src/snappy.c +1866 -0
  271. package/deps/librdkafka/src/snappy.h +62 -0
  272. package/deps/librdkafka/src/snappy_compat.h +138 -0
  273. package/deps/librdkafka/src/statistics_schema.json +444 -0
  274. package/deps/librdkafka/src/tinycthread.c +932 -0
  275. package/deps/librdkafka/src/tinycthread.h +503 -0
  276. package/deps/librdkafka/src/tinycthread_extra.c +210 -0
  277. package/deps/librdkafka/src/tinycthread_extra.h +218 -0
  278. package/deps/librdkafka/src/win32_config.h +58 -0
  279. package/deps/librdkafka/src-cpp/CMakeLists.txt +90 -0
  280. package/deps/librdkafka/src-cpp/ConfImpl.cpp +84 -0
  281. package/deps/librdkafka/src-cpp/ConsumerImpl.cpp +244 -0
  282. package/deps/librdkafka/src-cpp/HandleImpl.cpp +436 -0
  283. package/deps/librdkafka/src-cpp/HeadersImpl.cpp +48 -0
  284. package/deps/librdkafka/src-cpp/KafkaConsumerImpl.cpp +296 -0
  285. package/deps/librdkafka/src-cpp/Makefile +55 -0
  286. package/deps/librdkafka/src-cpp/MessageImpl.cpp +38 -0
  287. package/deps/librdkafka/src-cpp/MetadataImpl.cpp +170 -0
  288. package/deps/librdkafka/src-cpp/ProducerImpl.cpp +197 -0
  289. package/deps/librdkafka/src-cpp/QueueImpl.cpp +70 -0
  290. package/deps/librdkafka/src-cpp/README.md +16 -0
  291. package/deps/librdkafka/src-cpp/RdKafka.cpp +59 -0
  292. package/deps/librdkafka/src-cpp/TopicImpl.cpp +124 -0
  293. package/deps/librdkafka/src-cpp/TopicPartitionImpl.cpp +57 -0
  294. package/deps/librdkafka/src-cpp/rdkafkacpp.h +3797 -0
  295. package/deps/librdkafka/src-cpp/rdkafkacpp_int.h +1641 -0
  296. package/deps/librdkafka/tests/0000-unittests.c +72 -0
  297. package/deps/librdkafka/tests/0001-multiobj.c +102 -0
  298. package/deps/librdkafka/tests/0002-unkpart.c +244 -0
  299. package/deps/librdkafka/tests/0003-msgmaxsize.c +173 -0
  300. package/deps/librdkafka/tests/0004-conf.c +934 -0
  301. package/deps/librdkafka/tests/0005-order.c +133 -0
  302. package/deps/librdkafka/tests/0006-symbols.c +163 -0
  303. package/deps/librdkafka/tests/0007-autotopic.c +136 -0
  304. package/deps/librdkafka/tests/0008-reqacks.c +179 -0
  305. package/deps/librdkafka/tests/0009-mock_cluster.c +272 -0
  306. package/deps/librdkafka/tests/0011-produce_batch.c +753 -0
  307. package/deps/librdkafka/tests/0012-produce_consume.c +537 -0
  308. package/deps/librdkafka/tests/0013-null-msgs.c +473 -0
  309. package/deps/librdkafka/tests/0014-reconsume-191.c +512 -0
  310. package/deps/librdkafka/tests/0015-offset_seeks.c +172 -0
  311. package/deps/librdkafka/tests/0016-client_swname.c +181 -0
  312. package/deps/librdkafka/tests/0017-compression.c +140 -0
  313. package/deps/librdkafka/tests/0018-cgrp_term.c +444 -0
  314. package/deps/librdkafka/tests/0019-list_groups.c +289 -0
  315. package/deps/librdkafka/tests/0020-destroy_hang.c +162 -0
  316. package/deps/librdkafka/tests/0021-rkt_destroy.c +72 -0
  317. package/deps/librdkafka/tests/0022-consume_batch.c +331 -0
  318. package/deps/librdkafka/tests/0025-timers.c +147 -0
  319. package/deps/librdkafka/tests/0026-consume_pause.c +547 -0
  320. package/deps/librdkafka/tests/0028-long_topicnames.c +79 -0
  321. package/deps/librdkafka/tests/0029-assign_offset.c +202 -0
  322. package/deps/librdkafka/tests/0030-offset_commit.c +589 -0
  323. package/deps/librdkafka/tests/0031-get_offsets.c +235 -0
  324. package/deps/librdkafka/tests/0033-regex_subscribe.c +536 -0
  325. package/deps/librdkafka/tests/0034-offset_reset.c +398 -0
  326. package/deps/librdkafka/tests/0035-api_version.c +73 -0
  327. package/deps/librdkafka/tests/0036-partial_fetch.c +87 -0
  328. package/deps/librdkafka/tests/0037-destroy_hang_local.c +85 -0
  329. package/deps/librdkafka/tests/0038-performance.c +121 -0
  330. package/deps/librdkafka/tests/0039-event.c +284 -0
  331. package/deps/librdkafka/tests/0040-io_event.c +257 -0
  332. package/deps/librdkafka/tests/0041-fetch_max_bytes.c +97 -0
  333. package/deps/librdkafka/tests/0042-many_topics.c +252 -0
  334. package/deps/librdkafka/tests/0043-no_connection.c +77 -0
  335. package/deps/librdkafka/tests/0044-partition_cnt.c +94 -0
  336. package/deps/librdkafka/tests/0045-subscribe_update.c +1010 -0
  337. package/deps/librdkafka/tests/0046-rkt_cache.c +65 -0
  338. package/deps/librdkafka/tests/0047-partial_buf_tmout.c +98 -0
  339. package/deps/librdkafka/tests/0048-partitioner.c +283 -0
  340. package/deps/librdkafka/tests/0049-consume_conn_close.c +162 -0
  341. package/deps/librdkafka/tests/0050-subscribe_adds.c +145 -0
  342. package/deps/librdkafka/tests/0051-assign_adds.c +126 -0
  343. package/deps/librdkafka/tests/0052-msg_timestamps.c +238 -0
  344. package/deps/librdkafka/tests/0053-stats_cb.cpp +527 -0
  345. package/deps/librdkafka/tests/0054-offset_time.cpp +236 -0
  346. package/deps/librdkafka/tests/0055-producer_latency.c +539 -0
  347. package/deps/librdkafka/tests/0056-balanced_group_mt.c +315 -0
  348. package/deps/librdkafka/tests/0057-invalid_topic.cpp +112 -0
  349. package/deps/librdkafka/tests/0058-log.cpp +123 -0
  350. package/deps/librdkafka/tests/0059-bsearch.cpp +241 -0
  351. package/deps/librdkafka/tests/0060-op_prio.cpp +163 -0
  352. package/deps/librdkafka/tests/0061-consumer_lag.cpp +295 -0
  353. package/deps/librdkafka/tests/0062-stats_event.c +126 -0
  354. package/deps/librdkafka/tests/0063-clusterid.cpp +180 -0
  355. package/deps/librdkafka/tests/0064-interceptors.c +529 -0
  356. package/deps/librdkafka/tests/0065-yield.cpp +140 -0
  357. package/deps/librdkafka/tests/0066-plugins.cpp +143 -0
  358. package/deps/librdkafka/tests/0067-empty_topic.cpp +151 -0
  359. package/deps/librdkafka/tests/0068-produce_timeout.c +136 -0
  360. package/deps/librdkafka/tests/0069-consumer_add_parts.c +119 -0
  361. package/deps/librdkafka/tests/0070-null_empty.cpp +197 -0
  362. package/deps/librdkafka/tests/0072-headers_ut.c +448 -0
  363. package/deps/librdkafka/tests/0073-headers.c +381 -0
  364. package/deps/librdkafka/tests/0074-producev.c +87 -0
  365. package/deps/librdkafka/tests/0075-retry.c +290 -0
  366. package/deps/librdkafka/tests/0076-produce_retry.c +452 -0
  367. package/deps/librdkafka/tests/0077-compaction.c +366 -0
  368. package/deps/librdkafka/tests/0078-c_from_cpp.cpp +96 -0
  369. package/deps/librdkafka/tests/0079-fork.c +93 -0
  370. package/deps/librdkafka/tests/0080-admin_ut.c +3095 -0
  371. package/deps/librdkafka/tests/0081-admin.c +5633 -0
  372. package/deps/librdkafka/tests/0082-fetch_max_bytes.cpp +137 -0
  373. package/deps/librdkafka/tests/0083-cb_event.c +233 -0
  374. package/deps/librdkafka/tests/0084-destroy_flags.c +208 -0
  375. package/deps/librdkafka/tests/0085-headers.cpp +392 -0
  376. package/deps/librdkafka/tests/0086-purge.c +368 -0
  377. package/deps/librdkafka/tests/0088-produce_metadata_timeout.c +162 -0
  378. package/deps/librdkafka/tests/0089-max_poll_interval.c +511 -0
  379. package/deps/librdkafka/tests/0090-idempotence.c +171 -0
  380. package/deps/librdkafka/tests/0091-max_poll_interval_timeout.c +295 -0
  381. package/deps/librdkafka/tests/0092-mixed_msgver.c +103 -0
  382. package/deps/librdkafka/tests/0093-holb.c +200 -0
  383. package/deps/librdkafka/tests/0094-idempotence_msg_timeout.c +231 -0
  384. package/deps/librdkafka/tests/0095-all_brokers_down.cpp +122 -0
  385. package/deps/librdkafka/tests/0097-ssl_verify.cpp +674 -0
  386. package/deps/librdkafka/tests/0098-consumer-txn.cpp +1218 -0
  387. package/deps/librdkafka/tests/0099-commit_metadata.c +194 -0
  388. package/deps/librdkafka/tests/0100-thread_interceptors.cpp +195 -0
  389. package/deps/librdkafka/tests/0101-fetch-from-follower.cpp +446 -0
  390. package/deps/librdkafka/tests/0102-static_group_rebalance.c +836 -0
  391. package/deps/librdkafka/tests/0103-transactions.c +1383 -0
  392. package/deps/librdkafka/tests/0104-fetch_from_follower_mock.c +625 -0
  393. package/deps/librdkafka/tests/0105-transactions_mock.c +3930 -0
  394. package/deps/librdkafka/tests/0106-cgrp_sess_timeout.c +318 -0
  395. package/deps/librdkafka/tests/0107-topic_recreate.c +259 -0
  396. package/deps/librdkafka/tests/0109-auto_create_topics.cpp +278 -0
  397. package/deps/librdkafka/tests/0110-batch_size.cpp +182 -0
  398. package/deps/librdkafka/tests/0111-delay_create_topics.cpp +127 -0
  399. package/deps/librdkafka/tests/0112-assign_unknown_part.c +87 -0
  400. package/deps/librdkafka/tests/0113-cooperative_rebalance.cpp +3473 -0
  401. package/deps/librdkafka/tests/0114-sticky_partitioning.cpp +176 -0
  402. package/deps/librdkafka/tests/0115-producer_auth.cpp +182 -0
  403. package/deps/librdkafka/tests/0116-kafkaconsumer_close.cpp +216 -0
  404. package/deps/librdkafka/tests/0117-mock_errors.c +331 -0
  405. package/deps/librdkafka/tests/0118-commit_rebalance.c +154 -0
  406. package/deps/librdkafka/tests/0119-consumer_auth.cpp +167 -0
  407. package/deps/librdkafka/tests/0120-asymmetric_subscription.c +185 -0
  408. package/deps/librdkafka/tests/0121-clusterid.c +115 -0
  409. package/deps/librdkafka/tests/0122-buffer_cleaning_after_rebalance.c +227 -0
  410. package/deps/librdkafka/tests/0123-connections_max_idle.c +98 -0
  411. package/deps/librdkafka/tests/0124-openssl_invalid_engine.c +69 -0
  412. package/deps/librdkafka/tests/0125-immediate_flush.c +144 -0
  413. package/deps/librdkafka/tests/0126-oauthbearer_oidc.c +1164 -0
  414. package/deps/librdkafka/tests/0127-fetch_queue_backoff.cpp +165 -0
  415. package/deps/librdkafka/tests/0128-sasl_callback_queue.cpp +217 -0
  416. package/deps/librdkafka/tests/0129-fetch_aborted_msgs.c +79 -0
  417. package/deps/librdkafka/tests/0130-store_offsets.c +178 -0
  418. package/deps/librdkafka/tests/0131-connect_timeout.c +81 -0
  419. package/deps/librdkafka/tests/0132-strategy_ordering.c +179 -0
  420. package/deps/librdkafka/tests/0133-ssl_keys.c +150 -0
  421. package/deps/librdkafka/tests/0134-ssl_provider.c +92 -0
  422. package/deps/librdkafka/tests/0135-sasl_credentials.cpp +279 -0
  423. package/deps/librdkafka/tests/0136-resolve_cb.c +181 -0
  424. package/deps/librdkafka/tests/0137-barrier_batch_consume.c +752 -0
  425. package/deps/librdkafka/tests/0138-admin_mock.c +281 -0
  426. package/deps/librdkafka/tests/0139-offset_validation_mock.c +950 -0
  427. package/deps/librdkafka/tests/0140-commit_metadata.cpp +108 -0
  428. package/deps/librdkafka/tests/0142-reauthentication.c +931 -0
  429. package/deps/librdkafka/tests/0143-exponential_backoff_mock.c +552 -0
  430. package/deps/librdkafka/tests/0144-idempotence_mock.c +373 -0
  431. package/deps/librdkafka/tests/0145-pause_resume_mock.c +119 -0
  432. package/deps/librdkafka/tests/0146-metadata_mock.c +505 -0
  433. package/deps/librdkafka/tests/0147-consumer_group_consumer_mock.c +1210 -0
  434. package/deps/librdkafka/tests/0148-offset_fetch_commit_error_mock.c +569 -0
  435. package/deps/librdkafka/tests/0149-broker-same-host-port.c +140 -0
  436. package/deps/librdkafka/tests/0150-telemetry_mock.c +651 -0
  437. package/deps/librdkafka/tests/0151-purge-brokers.c +566 -0
  438. package/deps/librdkafka/tests/0152-rebootstrap.c +59 -0
  439. package/deps/librdkafka/tests/0153-memberid.c +128 -0
  440. package/deps/librdkafka/tests/0155-share_group_heartbeat_mock.c +2695 -0
  441. package/deps/librdkafka/tests/0156-share_consumer_fetch_mock.c +1551 -0
  442. package/deps/librdkafka/tests/0157-share_consumer_ack_mock.c +1788 -0
  443. package/deps/librdkafka/tests/0158-share_consumer_transactions_mock.c +467 -0
  444. package/deps/librdkafka/tests/0170-share_consumer_subscription.c +2192 -0
  445. package/deps/librdkafka/tests/0171-share_consumer_consume.c +2150 -0
  446. package/deps/librdkafka/tests/0172-share_consumer_acknowledge.c +1919 -0
  447. package/deps/librdkafka/tests/0173-share_consumer_commit_async.c +2735 -0
  448. package/deps/librdkafka/tests/0174-share_consumer_concurrency.c +1434 -0
  449. package/deps/librdkafka/tests/0175-share_consumer_groups.c +574 -0
  450. package/deps/librdkafka/tests/0176-share_consumer_commit_sync.c +2986 -0
  451. package/deps/librdkafka/tests/0177-share_consumer_transactions.c +1815 -0
  452. package/deps/librdkafka/tests/0178-share_consumer_close.c +2102 -0
  453. package/deps/librdkafka/tests/0179-share_consumer_destroy.c +2482 -0
  454. package/deps/librdkafka/tests/0180-share_consumer_config.c +1677 -0
  455. package/deps/librdkafka/tests/0181-share_consumer_topic_delete.c +354 -0
  456. package/deps/librdkafka/tests/0182-share_consumer_error_handling_mock.c +3358 -0
  457. package/deps/librdkafka/tests/0183-share_consumer_leader_change_mock.c +1234 -0
  458. package/deps/librdkafka/tests/0184-share_consumer_topic_recreate.c +1356 -0
  459. package/deps/librdkafka/tests/0185-share_consumer_max_poll_interval.c +557 -0
  460. package/deps/librdkafka/tests/0186-share_consumer_fatal_error.c +360 -0
  461. package/deps/librdkafka/tests/0190-share_consumer_telemetry.c +387 -0
  462. package/deps/librdkafka/tests/1000-unktopic.c +164 -0
  463. package/deps/librdkafka/tests/8000-idle.cpp +60 -0
  464. package/deps/librdkafka/tests/8001-fetch_from_follower_mock_manual.c +113 -0
  465. package/deps/librdkafka/tests/CMakeLists.txt +193 -0
  466. package/deps/librdkafka/tests/LibrdkafkaTestApp.py +291 -0
  467. package/deps/librdkafka/tests/Makefile +182 -0
  468. package/deps/librdkafka/tests/README.md +514 -0
  469. package/deps/librdkafka/tests/autotest.sh +33 -0
  470. package/deps/librdkafka/tests/backtrace.gdb +30 -0
  471. package/deps/librdkafka/tests/broker_version_tests.py +315 -0
  472. package/deps/librdkafka/tests/buildbox.sh +17 -0
  473. package/deps/librdkafka/tests/cleanup-checker-tests.sh +20 -0
  474. package/deps/librdkafka/tests/cluster_testing.py +203 -0
  475. package/deps/librdkafka/tests/delete-test-topics.sh +56 -0
  476. package/deps/librdkafka/tests/fixtures/oauthbearer/jwt_assertion_template.json +10 -0
  477. package/deps/librdkafka/tests/fixtures/ssl/Makefile +8 -0
  478. package/deps/librdkafka/tests/fixtures/ssl/README.md +13 -0
  479. package/deps/librdkafka/tests/fixtures/ssl/client.keystore.intermediate.p12 +0 -0
  480. package/deps/librdkafka/tests/fixtures/ssl/client.keystore.p12 +0 -0
  481. package/deps/librdkafka/tests/fixtures/ssl/client2.certificate.intermediate.pem +72 -0
  482. package/deps/librdkafka/tests/fixtures/ssl/client2.certificate.pem +50 -0
  483. package/deps/librdkafka/tests/fixtures/ssl/client2.intermediate.key +46 -0
  484. package/deps/librdkafka/tests/fixtures/ssl/client2.key +46 -0
  485. package/deps/librdkafka/tests/fixtures/ssl/create_keys.sh +168 -0
  486. package/deps/librdkafka/tests/fuzzers/Makefile +12 -0
  487. package/deps/librdkafka/tests/fuzzers/README.md +31 -0
  488. package/deps/librdkafka/tests/fuzzers/fuzz_regex.c +74 -0
  489. package/deps/librdkafka/tests/fuzzers/helpers.h +90 -0
  490. package/deps/librdkafka/tests/gen-ssl-certs.sh +165 -0
  491. package/deps/librdkafka/tests/interactive_broker_version.py +170 -0
  492. package/deps/librdkafka/tests/interceptor_test/CMakeLists.txt +16 -0
  493. package/deps/librdkafka/tests/interceptor_test/Makefile +22 -0
  494. package/deps/librdkafka/tests/interceptor_test/interceptor_test.c +314 -0
  495. package/deps/librdkafka/tests/interceptor_test/interceptor_test.h +54 -0
  496. package/deps/librdkafka/tests/java/IncrementalRebalanceCli.java +97 -0
  497. package/deps/librdkafka/tests/java/Makefile +13 -0
  498. package/deps/librdkafka/tests/java/Murmur2Cli.java +46 -0
  499. package/deps/librdkafka/tests/java/README.md +14 -0
  500. package/deps/librdkafka/tests/java/TransactionProducerCli.java +162 -0
  501. package/deps/librdkafka/tests/java/run-class.sh +11 -0
  502. package/deps/librdkafka/tests/librdkafka.suppressions +483 -0
  503. package/deps/librdkafka/tests/lz4_manual_test.sh +59 -0
  504. package/deps/librdkafka/tests/multi-broker-version-test.sh +50 -0
  505. package/deps/librdkafka/tests/parse-refcnt.sh +43 -0
  506. package/deps/librdkafka/tests/performance_plot.py +115 -0
  507. package/deps/librdkafka/tests/plugin_test/Makefile +19 -0
  508. package/deps/librdkafka/tests/plugin_test/plugin_test.c +58 -0
  509. package/deps/librdkafka/tests/requirements.txt +2 -0
  510. package/deps/librdkafka/tests/run-all-tests.sh +81 -0
  511. package/deps/librdkafka/tests/run-consumer-tests.sh +16 -0
  512. package/deps/librdkafka/tests/run-producer-tests.sh +16 -0
  513. package/deps/librdkafka/tests/run-test-batches.py +157 -0
  514. package/deps/librdkafka/tests/run-test.sh +141 -0
  515. package/deps/librdkafka/tests/rusage.c +249 -0
  516. package/deps/librdkafka/tests/sasl_test.py +289 -0
  517. package/deps/librdkafka/tests/scenarios/README.md +6 -0
  518. package/deps/librdkafka/tests/scenarios/ak23.json +6 -0
  519. package/deps/librdkafka/tests/scenarios/default.json +5 -0
  520. package/deps/librdkafka/tests/scenarios/noautocreate.json +5 -0
  521. package/deps/librdkafka/tests/share_telemetry_verify/share-otel-collector-config.yaml +28 -0
  522. package/deps/librdkafka/tests/sockem.c +801 -0
  523. package/deps/librdkafka/tests/sockem.h +85 -0
  524. package/deps/librdkafka/tests/sockem_ctrl.c +145 -0
  525. package/deps/librdkafka/tests/sockem_ctrl.h +61 -0
  526. package/deps/librdkafka/tests/test.c +8376 -0
  527. package/deps/librdkafka/tests/test.conf.example +27 -0
  528. package/deps/librdkafka/tests/test.h +1150 -0
  529. package/deps/librdkafka/tests/testcpp.cpp +131 -0
  530. package/deps/librdkafka/tests/testcpp.h +388 -0
  531. package/deps/librdkafka/tests/testshared.h +416 -0
  532. package/deps/librdkafka/tests/tools/README.md +4 -0
  533. package/deps/librdkafka/tests/tools/stats/README.md +21 -0
  534. package/deps/librdkafka/tests/tools/stats/filter.jq +42 -0
  535. package/deps/librdkafka/tests/tools/stats/graph.py +150 -0
  536. package/deps/librdkafka/tests/tools/stats/requirements.txt +3 -0
  537. package/deps/librdkafka/tests/tools/stats/to_csv.py +124 -0
  538. package/deps/librdkafka/tests/trivup/trivup-0.15.0.tar.gz +0 -0
  539. package/deps/librdkafka/tests/until-fail.sh +87 -0
  540. package/deps/librdkafka/tests/xxxx-assign_partition.c +122 -0
  541. package/deps/librdkafka/tests/xxxx-metadata.cpp +159 -0
  542. package/deps/librdkafka/vcpkg.json +23 -0
  543. package/deps/librdkafka/win32/README.md +5 -0
  544. package/deps/librdkafka/win32/build-package.bat +3 -0
  545. package/deps/librdkafka/win32/build.bat +19 -0
  546. package/deps/librdkafka/win32/common.vcxproj +84 -0
  547. package/deps/librdkafka/win32/interceptor_test/interceptor_test.vcxproj +87 -0
  548. package/deps/librdkafka/win32/librdkafka.autopkg.template +54 -0
  549. package/deps/librdkafka/win32/librdkafka.master.testing.targets +13 -0
  550. package/deps/librdkafka/win32/librdkafka.sln +226 -0
  551. package/deps/librdkafka/win32/librdkafka.vcxproj +282 -0
  552. package/deps/librdkafka/win32/librdkafkacpp/librdkafkacpp.vcxproj +104 -0
  553. package/deps/librdkafka/win32/msbuild.ps1 +58 -0
  554. package/deps/librdkafka/win32/openssl_engine_example/openssl_engine_example.vcxproj +132 -0
  555. package/deps/librdkafka/win32/package-zip.ps1 +46 -0
  556. package/deps/librdkafka/win32/packages/repositories.config +4 -0
  557. package/deps/librdkafka/win32/push-package.bat +4 -0
  558. package/deps/librdkafka/win32/rdkafka_complex_consumer_example_cpp/rdkafka_complex_consumer_example_cpp.vcxproj +67 -0
  559. package/deps/librdkafka/win32/rdkafka_example/rdkafka_example.vcxproj +97 -0
  560. package/deps/librdkafka/win32/rdkafka_performance/rdkafka_performance.vcxproj +97 -0
  561. package/deps/librdkafka/win32/setup-msys2.ps1 +47 -0
  562. package/deps/librdkafka/win32/setup-vcpkg.ps1 +34 -0
  563. package/deps/librdkafka/win32/tests/test.conf.example +25 -0
  564. package/deps/librdkafka/win32/tests/tests.vcxproj +278 -0
  565. package/deps/librdkafka/win32/win_ssl_cert_store/win_ssl_cert_store.vcxproj +132 -0
  566. package/deps/librdkafka/win32/wingetopt.c +564 -0
  567. package/deps/librdkafka/win32/wingetopt.h +101 -0
  568. package/deps/librdkafka/win32/wintime.h +33 -0
  569. package/deps/librdkafka.gyp +83 -0
  570. package/deps/windows-install.py +80 -0
  571. package/index.d.ts +3 -0
  572. package/lib/admin.js +732 -0
  573. package/lib/client.js +679 -0
  574. package/lib/error.js +501 -0
  575. package/lib/index.js +8 -0
  576. package/lib/kafka-consumer-stream.js +399 -0
  577. package/lib/kafka-consumer.js +798 -0
  578. package/lib/kafkajs/_admin.js +1052 -0
  579. package/lib/kafkajs/_common.js +887 -0
  580. package/lib/kafkajs/_consumer.js +2156 -0
  581. package/lib/kafkajs/_consumer_cache.js +310 -0
  582. package/lib/kafkajs/_error.js +298 -0
  583. package/lib/kafkajs/_kafka.js +125 -0
  584. package/lib/kafkajs/_linked-list.js +220 -0
  585. package/lib/kafkajs/_producer.js +863 -0
  586. package/lib/kafkajs/index.js +5 -0
  587. package/lib/producer/high-level-producer.js +400 -0
  588. package/lib/producer-stream.js +337 -0
  589. package/lib/producer.js +405 -0
  590. package/lib/rdkafka.js +44 -0
  591. package/lib/tools/ref-counter.js +53 -0
  592. package/lib/topic-partition.js +91 -0
  593. package/lib/topic.js +43 -0
  594. package/lib/util.js +55 -0
  595. package/librdkafka.js +12 -0
  596. package/package.json +85 -0
  597. package/shim/source_location +54 -0
  598. package/src/admin.cc +1597 -0
  599. package/src/admin.h +112 -0
  600. package/src/binding.cc +76 -0
  601. package/src/binding.h +25 -0
  602. package/src/callbacks.cc +676 -0
  603. package/src/callbacks.h +302 -0
  604. package/src/common.cc +1628 -0
  605. package/src/common.h +192 -0
  606. package/src/config.cc +219 -0
  607. package/src/config.h +61 -0
  608. package/src/connection.cc +703 -0
  609. package/src/connection.h +117 -0
  610. package/src/errors.cc +119 -0
  611. package/src/errors.h +60 -0
  612. package/src/kafka-consumer.cc +1539 -0
  613. package/src/kafka-consumer.h +147 -0
  614. package/src/producer.cc +917 -0
  615. package/src/producer.h +124 -0
  616. package/src/topic.cc +173 -0
  617. package/src/topic.h +54 -0
  618. package/src/workers.cc +1714 -0
  619. package/src/workers.h +690 -0
  620. package/types/config.d.ts +1269 -0
  621. package/types/errors.d.ts +373 -0
  622. package/types/kafkajs.d.ts +568 -0
  623. package/types/rdkafka.d.ts +571 -0
  624. package/util/configure.js +32 -0
  625. package/util/generate-docs.sh +18 -0
  626. package/util/get-env.js +6 -0
  627. package/util/test-compile.js +11 -0
  628. package/util/test-producer-delivery.js +100 -0
@@ -0,0 +1,1521 @@
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
+ /**
30
+ * @name Unit tests for Share Consumer MessageSet error handling
31
+ * @{
32
+ *
33
+ * Tests cover per-offset error handling for:
34
+ * - CRC errors → REJECT ack_type
35
+ * - Decompression errors → RELEASE ack_type
36
+ * - Unsupported MagicByte → REJECT ack_type
37
+ *
38
+ * These tests craft binary MessageSet v2 buffers with intentional corruption
39
+ * and verify that the msgset reader creates one error op per offset with
40
+ * correct ack_types for share consumers.
41
+ */
42
+
43
+ #include "rd.h"
44
+ #include "rdunittest.h"
45
+ #include "rdkafka_int.h"
46
+ #include "rdkafka_queue.h"
47
+ #include "rdkafka_partition.h"
48
+ #include "rdkafka_share_acknowledgement.h"
49
+ #include "rdkafka_buf.h"
50
+ #include "rdkafka_msgset.h"
51
+ #include "crc32c.h"
52
+
53
+ #if WITH_ZSTD
54
+ #include "rdkafka_zstd.h"
55
+ #endif
56
+
57
+
58
+ /**
59
+ * @brief Alignment-safe big-endian writers.
60
+ *
61
+ * The msgset crafting helpers below write into a char buffer at arbitrary
62
+ * offsets. Casting `char *` to `int{16,32,64}_t *` triggers -Wcast-align
63
+ * on stricter targets (and is undefined behaviour even on x86 strictly
64
+ * speaking). Use memcpy() — the compiler lowers it to a single move on
65
+ * supported architectures.
66
+ */
67
+ static RD_INLINE void ut_put_be16(void *p, int16_t v) {
68
+ int16_t be = htobe16(v);
69
+ memcpy(p, &be, sizeof(be));
70
+ }
71
+ static RD_INLINE void ut_put_be32(void *p, int32_t v) {
72
+ int32_t be = htobe32(v);
73
+ memcpy(p, &be, sizeof(be));
74
+ }
75
+ static RD_INLINE void ut_put_be64(void *p, int64_t v) {
76
+ int64_t be = htobe64(v);
77
+ memcpy(p, &be, sizeof(be));
78
+ }
79
+
80
+
81
+ /**
82
+ * @name Test helpers
83
+ * @{
84
+ */
85
+
86
+ /**
87
+ * @brief Create a minimal share consumer for testing
88
+ */
89
+ static rd_kafka_share_t *ut_create_test_share_consumer(void) {
90
+ rd_kafka_conf_t *conf = rd_kafka_conf_new();
91
+ rd_kafka_share_t *rkshare;
92
+ char errstr[512];
93
+
94
+ if (rd_kafka_conf_set(conf, "group.id", "ut-msgset-errors", errstr,
95
+ sizeof(errstr)) != RD_KAFKA_CONF_OK) {
96
+ rd_kafka_conf_destroy(conf);
97
+ return NULL;
98
+ }
99
+
100
+ /* Enable CRC checking for tests */
101
+ if (rd_kafka_conf_set(conf, "check.crcs", "true", errstr,
102
+ sizeof(errstr)) != RD_KAFKA_CONF_OK) {
103
+ rd_kafka_conf_destroy(conf);
104
+ return NULL;
105
+ }
106
+
107
+ rkshare = rd_kafka_share_consumer_new(conf, errstr, sizeof(errstr));
108
+ return rkshare;
109
+ }
110
+
111
+ static void ut_destroy_share_consumer(rd_kafka_share_t *rkshare) {
112
+ if (!rkshare)
113
+ return;
114
+ rd_kafka_share_consumer_close(rkshare);
115
+ rd_kafka_share_destroy(rkshare);
116
+ }
117
+
118
+ /**
119
+ * @brief Create a mock topic partition
120
+ */
121
+ static rd_kafka_toppar_t *
122
+ ut_create_mock_toppar(rd_kafka_t *rk, const char *topic, int32_t partition) {
123
+ rd_kafka_topic_t *rkt = rd_kafka_topic_new(rk, topic, NULL);
124
+ if (!rkt)
125
+ return NULL;
126
+ return rd_kafka_toppar_new(rkt, partition);
127
+ }
128
+
129
+ /**
130
+ * @brief Helper to write MessageSet v2 header fields in big-endian
131
+ */
132
+ static void ut_write_msgset_v2_header(char *buf,
133
+ int64_t BaseOffset,
134
+ int32_t Length,
135
+ int32_t PartitionLeaderEpoch,
136
+ int8_t MagicByte,
137
+ int32_t Crc,
138
+ int16_t Attributes,
139
+ int32_t LastOffsetDelta,
140
+ int64_t BaseTimestamp,
141
+ int64_t MaxTimestamp,
142
+ int64_t ProducerId,
143
+ int16_t ProducerEpoch,
144
+ int32_t BaseSequence,
145
+ int32_t RecordCount) {
146
+ size_t offset = 0;
147
+
148
+ /* BaseOffset (int64) */
149
+ ut_put_be64(buf + offset, BaseOffset);
150
+ offset += 8;
151
+
152
+ /* Length (int32) */
153
+ ut_put_be32(buf + offset, Length);
154
+ offset += 4;
155
+
156
+ /* PartitionLeaderEpoch (int32) */
157
+ ut_put_be32(buf + offset, PartitionLeaderEpoch);
158
+ offset += 4;
159
+
160
+ /* MagicByte (int8) */
161
+ *(int8_t *)(buf + offset) = MagicByte;
162
+ offset += 1;
163
+
164
+ /* Crc (int32) */
165
+ ut_put_be32(buf + offset, Crc);
166
+ offset += 4;
167
+
168
+ /* Attributes (int16) */
169
+ ut_put_be16(buf + offset, Attributes);
170
+ offset += 2;
171
+
172
+ /* LastOffsetDelta (int32) */
173
+ ut_put_be32(buf + offset, LastOffsetDelta);
174
+ offset += 4;
175
+
176
+ /* BaseTimestamp (int64) */
177
+ ut_put_be64(buf + offset, BaseTimestamp);
178
+ offset += 8;
179
+
180
+ /* MaxTimestamp (int64) */
181
+ ut_put_be64(buf + offset, MaxTimestamp);
182
+ offset += 8;
183
+
184
+ /* ProducerId (int64) */
185
+ ut_put_be64(buf + offset, ProducerId);
186
+ offset += 8;
187
+
188
+ /* ProducerEpoch (int16) */
189
+ ut_put_be16(buf + offset, ProducerEpoch);
190
+ offset += 2;
191
+
192
+ /* BaseSequence (int32) */
193
+ ut_put_be32(buf + offset, BaseSequence);
194
+ offset += 4;
195
+
196
+ /* RecordCount (int32) */
197
+ ut_put_be32(buf + offset, RecordCount);
198
+ offset += 4;
199
+ }
200
+
201
+ #if WITH_ZSTD
202
+ /**
203
+ * @brief Calculate correct CRC32C for MessageSet v2
204
+ * CRC covers from Attributes to end of records
205
+ */
206
+ static uint32_t ut_calc_msgset_crc(const char *buf,
207
+ size_t offset_to_attributes,
208
+ size_t total_len) {
209
+ /* CRC starts after MagicByte and Crc field itself */
210
+ const void *data = buf + offset_to_attributes;
211
+ size_t data_len = total_len - offset_to_attributes;
212
+ return rd_crc32c(0, data, data_len);
213
+ }
214
+ #endif /* WITH_ZSTD */
215
+
216
+ /**
217
+ * @brief Write a varint (used in Record format)
218
+ * @returns number of bytes written
219
+ */
220
+ static size_t ut_write_varint(char *buf, int64_t value) {
221
+ uint64_t uval = (value << 1) ^ (value >> 63); /* Zigzag encoding */
222
+ size_t i = 0;
223
+
224
+ while (uval >= 0x80) {
225
+ buf[i++] = (char)((uval & 0x7F) | 0x80);
226
+ uval >>= 7;
227
+ }
228
+ buf[i++] = (char)(uval & 0x7F);
229
+ return i;
230
+ }
231
+
232
+ /**
233
+ * @brief Build a minimal valid Record v2
234
+ * @returns size of record written
235
+ */
236
+ static size_t ut_build_record_v2(char *buf,
237
+ int32_t offset_delta,
238
+ int64_t timestamp_delta,
239
+ const char *key,
240
+ size_t key_len,
241
+ const char *value,
242
+ size_t value_len) {
243
+ size_t offset = 0;
244
+ size_t len_offset;
245
+ int32_t key_len_varint = key ? (int32_t)key_len : -1;
246
+ int32_t val_len_varint = value ? (int32_t)value_len : -1;
247
+
248
+ /* Reserve space for Length (varint) - we'll fill this in later */
249
+ len_offset = offset;
250
+ offset += 5; /* Max varint size for record length */
251
+
252
+ /* Attributes (int8) */
253
+ buf[offset++] = 0;
254
+
255
+ /* TimestampDelta (varint) */
256
+ offset += ut_write_varint(buf + offset, timestamp_delta);
257
+
258
+ /* OffsetDelta (varint) */
259
+ offset += ut_write_varint(buf + offset, offset_delta);
260
+
261
+ /* KeyLen (varint) */
262
+ offset += ut_write_varint(buf + offset, key_len_varint);
263
+
264
+ /* Key bytes */
265
+ if (key) {
266
+ memcpy(buf + offset, key, key_len);
267
+ offset += key_len;
268
+ }
269
+
270
+ /* ValueLen (varint) */
271
+ offset += ut_write_varint(buf + offset, val_len_varint);
272
+
273
+ /* Value bytes */
274
+ if (value) {
275
+ memcpy(buf + offset, value, value_len);
276
+ offset += value_len;
277
+ }
278
+
279
+ /* Headers count (varint) - 0 headers */
280
+ offset += ut_write_varint(buf + offset, 0);
281
+
282
+ /* Calculate record length (everything after Length field) */
283
+ size_t record_body_len = offset - len_offset - 5;
284
+
285
+ /* Write actual Length at the beginning */
286
+ size_t len_size = ut_write_varint(buf + len_offset, record_body_len);
287
+
288
+ /* Compact the record if varint was smaller than 5 bytes */
289
+ if (len_size < 5) {
290
+ memmove(buf + len_offset + len_size, buf + len_offset + 5,
291
+ record_body_len);
292
+ offset = len_offset + len_size + record_body_len;
293
+ }
294
+
295
+ return offset;
296
+ }
297
+
298
+ /**
299
+ * @brief Build a complete valid MessageSet v2 with records
300
+ * @returns total size of MessageSet
301
+ */
302
+ static size_t ut_build_valid_msgset_v2(char *buf,
303
+ int64_t base_offset,
304
+ int32_t record_count,
305
+ const char **values,
306
+ size_t *value_lens) {
307
+ size_t offset = 0;
308
+ size_t len_offset = 8;
309
+ size_t records_size = 0;
310
+ int32_t i;
311
+ char *records_buf;
312
+ uint32_t crc;
313
+ int32_t last_offset_delta = record_count > 0 ? record_count - 1 : 0;
314
+
315
+ /* Build all records first to know total size */
316
+ records_buf = rd_calloc(1, 8192);
317
+ for (i = 0; i < record_count; i++) {
318
+ records_size += ut_build_record_v2(
319
+ records_buf + records_size, i, /* offsetDelta */
320
+ 0, /* timestampDelta */
321
+ NULL, 0, /* no key */
322
+ values ? values[i] : NULL,
323
+ values && value_lens ? value_lens[i] : 0);
324
+ }
325
+
326
+ /* BaseOffset */
327
+ ut_put_be64(buf + offset, base_offset);
328
+ offset += 8;
329
+
330
+ /* Length - will update later */
331
+ len_offset = offset;
332
+ offset += 4;
333
+
334
+ /* PartitionLeaderEpoch */
335
+ ut_put_be32(buf + offset, -1);
336
+ offset += 4;
337
+
338
+ /* MagicByte */
339
+ buf[offset++] = 2;
340
+
341
+ /* CRC - placeholder, will calculate later */
342
+ size_t crc_offset = offset;
343
+ offset += 4;
344
+
345
+ /* Attributes (no compression) */
346
+ ut_put_be16(buf + offset, 0);
347
+ offset += 2;
348
+
349
+ /* LastOffsetDelta */
350
+ ut_put_be32(buf + offset, last_offset_delta);
351
+ offset += 4;
352
+
353
+ /* BaseTimestamp */
354
+ ut_put_be64(buf + offset, 0);
355
+ offset += 8;
356
+
357
+ /* MaxTimestamp */
358
+ ut_put_be64(buf + offset, 0);
359
+ offset += 8;
360
+
361
+ /* ProducerId */
362
+ ut_put_be64(buf + offset, -1);
363
+ offset += 8;
364
+
365
+ /* ProducerEpoch */
366
+ ut_put_be16(buf + offset, -1);
367
+ offset += 2;
368
+
369
+ /* BaseSequence */
370
+ ut_put_be32(buf + offset, -1);
371
+ offset += 4;
372
+
373
+ /* RecordCount */
374
+ ut_put_be32(buf + offset, record_count);
375
+ offset += 4;
376
+
377
+ /* Copy records */
378
+ memcpy(buf + offset, records_buf, records_size);
379
+ offset += records_size;
380
+ rd_free(records_buf);
381
+
382
+ /* Calculate and write Length */
383
+ int32_t length = (int32_t)(offset - len_offset - 4);
384
+ ut_put_be32(buf + len_offset, length);
385
+
386
+ /* Calculate and write CRC (covers Attributes to end) */
387
+ crc = rd_crc32c(0, buf + crc_offset + 4, offset - crc_offset - 4);
388
+ ut_put_be32(buf + crc_offset, crc);
389
+
390
+ return offset;
391
+ }
392
+
393
+ /**@}*/
394
+
395
+
396
+ /**
397
+ * @brief Test CRC error generates per-offset error ops with REJECT ack_type
398
+ *
399
+ * Creates a MessageSet v2 with intentionally wrong CRC and verifies:
400
+ * - One error op per offset in range [BaseOffset, LastOffset]
401
+ * - Each error op has REJECT ack_type
402
+ * - Error code is RD_KAFKA_RESP_ERR__BAD_MSG
403
+ */
404
+ static int unittest_msgset_crc_error_share_consumer(void) {
405
+ rd_kafka_share_t *rkshare;
406
+ rd_kafka_toppar_t *rktp;
407
+ rd_kafka_buf_t *rkbuf;
408
+ rd_kafka_q_t *response_q;
409
+ char *msgset_data;
410
+ size_t msgset_size;
411
+ int64_t BaseOffset = 100;
412
+ int32_t LastOffsetDelta =
413
+ 4; /* Offsets 100-104 inclusive = 5 messages */
414
+ int expected_err_ops = 5;
415
+ int i;
416
+ struct rd_kafka_toppar_ver tver = {.version = 11};
417
+
418
+ RD_UT_BEGIN();
419
+
420
+ rkshare = ut_create_test_share_consumer();
421
+ RD_UT_ASSERT(rkshare, "Failed to create share consumer");
422
+
423
+ rktp = ut_create_mock_toppar(rkshare->rkshare_rk, "test-topic-crc", 0);
424
+ RD_UT_ASSERT(rktp, "Failed to create toppar");
425
+
426
+ response_q = rd_kafka_q_new(rkshare->rkshare_rk);
427
+
428
+ /* Craft MessageSet v2 with wrong CRC */
429
+ /* MessageSet v2 structure:
430
+ * - BaseOffset (8) + Length (4) = 12 bytes before "Length" data starts
431
+ * - Length field contains size of: PartitionLeaderEpoch (4) + MagicByte
432
+ * (1)
433
+ * + Crc (4) + Attributes (2) + LastOffsetDelta (4) + BaseTimestamp
434
+ * (8)
435
+ * + MaxTimestamp (8) + ProducerId (8) + ProducerEpoch (2)
436
+ * + BaseSequence (4) + RecordCount (4) + Records
437
+ * - Minimum Length = 49 (just the header fields after Length)
438
+ * - For this test, we need enough space for CRC validation
439
+ */
440
+
441
+ /* CRC validation needs: crc_len = Length - 4 - 1 - 4 bytes available
442
+ * after reading up to Crc field (21 bytes read so far) */
443
+ int32_t Length = 61 - 12; /* Minimum: just the header, no records */
444
+ msgset_size = 12 + Length; /* BaseOffset + Length + data */
445
+ msgset_data = rd_calloc(1, msgset_size);
446
+
447
+ ut_write_msgset_v2_header(
448
+ msgset_data, BaseOffset,
449
+ Length, /* Length of data after BaseOffset+Length fields */
450
+ -1, /* PartitionLeaderEpoch */
451
+ 2, /* MagicByte v2 */
452
+ 0xDEADBEEF, /* WRONG CRC - will trigger error */
453
+ 0, /* Attributes: no compression */
454
+ LastOffsetDelta, 0, /* BaseTimestamp */
455
+ 0, /* MaxTimestamp */
456
+ -1, /* ProducerId */
457
+ -1, /* ProducerEpoch */
458
+ -1, /* BaseSequence */
459
+ 5 /* RecordCount */);
460
+
461
+ /* Create shadow buffer from raw data */
462
+ rkbuf = rd_kafka_buf_new_shadow(msgset_data, msgset_size, rd_free);
463
+ rkbuf->rkbuf_rkb = rd_kafka_broker_internal(rkshare->rkshare_rk);
464
+
465
+ /* Parse the MessageSet - should detect CRC error */
466
+ rd_kafka_resp_err_t parse_err =
467
+ rd_kafka_share_msgset_parse(rkbuf, rktp, NULL, &tver, response_q);
468
+
469
+ RD_UT_ASSERT(parse_err == RD_KAFKA_RESP_ERR_NO_ERROR ||
470
+ parse_err == RD_KAFKA_RESP_ERR__BAD_MSG,
471
+ "Unexpected parse error: %s", rd_kafka_err2str(parse_err));
472
+
473
+ /* Verify we got expected number of error ops */
474
+ for (i = 0; i < expected_err_ops; i++) {
475
+ rd_kafka_op_t *rko = rd_kafka_q_pop(response_q, 1000, 0);
476
+ RD_UT_ASSERT(rko != NULL,
477
+ "Expected error op %d of %d, got timeout", i + 1,
478
+ expected_err_ops);
479
+ RD_UT_ASSERT(rko->rko_type == RD_KAFKA_OP_CONSUMER_ERR,
480
+ "Expected CONSUMER_ERR op, got %d", rko->rko_type);
481
+ RD_UT_ASSERT(rko->rko_err == RD_KAFKA_RESP_ERR__BAD_MSG,
482
+ "Expected BAD_MSG error, got %s",
483
+ rd_kafka_err2str(rko->rko_err));
484
+ RD_UT_ASSERT(rko->rko_u.err.offset == BaseOffset + i,
485
+ "Expected offset %" PRId64 ", got %" PRId64,
486
+ BaseOffset + i, rko->rko_u.err.offset);
487
+ RD_UT_ASSERT(rko->rko_u.err.rkm.rkm_u.consumer.ack_type ==
488
+ RD_KAFKA_SHARE_INTERNAL_ACK_REJECT,
489
+ "Expected REJECT ack_type for CRC error, got %d",
490
+ rko->rko_u.err.rkm.rkm_u.consumer.ack_type);
491
+ rd_kafka_op_destroy(rko);
492
+ }
493
+
494
+ /* Verify no extra ops */
495
+ {
496
+ rd_kafka_op_t *rko;
497
+ rko = rd_kafka_q_pop(response_q, 100, 0);
498
+ RD_UT_ASSERT(rko == NULL, "Got unexpected extra op");
499
+ }
500
+
501
+ rd_kafka_buf_destroy(rkbuf);
502
+ rd_kafka_q_destroy_owner(response_q);
503
+ rd_kafka_toppar_destroy(rktp);
504
+ ut_destroy_share_consumer(rkshare);
505
+
506
+ RD_UT_PASS();
507
+ }
508
+
509
+
510
+ #if WITH_ZSTD
511
+ /**
512
+ * @brief Test decompression error generates per-offset error ops with RELEASE
513
+ *
514
+ * Creates a MessageSet v2 with ZSTD compression but corrupted compressed data.
515
+ * Verifies:
516
+ * - One error op per offset in range [BaseOffset, LastOffset]
517
+ * - Each error op has RELEASE ack_type (retryable error)
518
+ * - Error code is RD_KAFKA_RESP_ERR__BAD_COMPRESSION
519
+ */
520
+ static int unittest_msgset_decompression_error_share_consumer(void) {
521
+ rd_kafka_share_t *rkshare;
522
+ rd_kafka_toppar_t *rktp;
523
+ rd_kafka_buf_t *rkbuf;
524
+ rd_kafka_q_t *response_q;
525
+ char *msgset_data;
526
+ size_t msgset_size;
527
+ int64_t BaseOffset = 200;
528
+ int32_t LastOffsetDelta =
529
+ 2; /* Offsets 200-202 inclusive = 3 messages */
530
+ int expected_err_ops = 3;
531
+ int i;
532
+ uint32_t correct_crc;
533
+ size_t crc_offset = 17; /* Offset to CRC field in header */
534
+ size_t attr_offset =
535
+ 21; /* Offset to Attributes field (where CRC starts) */
536
+ struct rd_kafka_toppar_ver tver = {.version = 11};
537
+
538
+ RD_UT_BEGIN();
539
+
540
+ rkshare = ut_create_test_share_consumer();
541
+ RD_UT_ASSERT(rkshare, "Failed to create share consumer");
542
+
543
+ rktp = ut_create_mock_toppar(rkshare->rkshare_rk,
544
+ "test-topic-decompress", 0);
545
+ RD_UT_ASSERT(rktp, "Failed to create toppar");
546
+
547
+ response_q = rd_kafka_q_new(rkshare->rkshare_rk);
548
+
549
+ /* Craft MessageSet v2 with ZSTD compression but corrupted data */
550
+ msgset_size = 200;
551
+ msgset_data = rd_calloc(1, msgset_size);
552
+
553
+ int32_t Length = msgset_size - 12;
554
+
555
+ ut_write_msgset_v2_header(
556
+ msgset_data, BaseOffset,
557
+ Length, /* Length of data after BaseOffset+Length fields */
558
+ -1, /* PartitionLeaderEpoch */
559
+ 2, /* MagicByte v2 */
560
+ 0, /* CRC - will calculate correct one below */
561
+ 4, /* Attributes: ZSTD compression (codec=4) */
562
+ LastOffsetDelta, 0, /* BaseTimestamp */
563
+ 0, /* MaxTimestamp */
564
+ -1, /* ProducerId */
565
+ -1, /* ProducerEpoch */
566
+ -1, /* BaseSequence */
567
+ 3 /* RecordCount */);
568
+
569
+ /* Fill records section with garbage (corrupted ZSTD data) */
570
+ memset(msgset_data + 61, 0xAB, msgset_size - 61);
571
+
572
+ /* Calculate CORRECT CRC so we pass CRC check but fail decompression */
573
+ correct_crc = ut_calc_msgset_crc(msgset_data, attr_offset, msgset_size);
574
+ ut_put_be32(msgset_data + crc_offset, correct_crc);
575
+
576
+ /* Create shadow buffer from raw data */
577
+ rkbuf = rd_kafka_buf_new_shadow(msgset_data, msgset_size, rd_free);
578
+ rkbuf->rkbuf_rkb = rd_kafka_broker_internal(rkshare->rkshare_rk);
579
+
580
+ /* Parse the MessageSet - should detect decompression error */
581
+ rd_kafka_share_msgset_parse(rkbuf, rktp, NULL, &tver, response_q);
582
+
583
+ /* Verify we got expected number of error ops */
584
+ for (i = 0; i < expected_err_ops; i++) {
585
+ rd_kafka_op_t *rko = rd_kafka_q_pop(response_q, 1000, 0);
586
+ RD_UT_ASSERT(rko != NULL,
587
+ "Expected error op %d of %d, got timeout", i + 1,
588
+ expected_err_ops);
589
+ RD_UT_ASSERT(rko->rko_type == RD_KAFKA_OP_CONSUMER_ERR,
590
+ "Expected CONSUMER_ERR op, got %d", rko->rko_type);
591
+ RD_UT_ASSERT(rko->rko_err == RD_KAFKA_RESP_ERR__BAD_COMPRESSION,
592
+ "Expected BAD_COMPRESSION error, got %s",
593
+ rd_kafka_err2str(rko->rko_err));
594
+ RD_UT_ASSERT(rko->rko_u.err.offset == BaseOffset + i,
595
+ "Expected offset %" PRId64 ", got %" PRId64,
596
+ BaseOffset + i, rko->rko_u.err.offset);
597
+ RD_UT_ASSERT(
598
+ rko->rko_u.err.rkm.rkm_u.consumer.ack_type ==
599
+ RD_KAFKA_SHARE_INTERNAL_ACK_RELEASE,
600
+ "Expected RELEASE ack_type for decompression error, got %d",
601
+ rko->rko_u.err.rkm.rkm_u.consumer.ack_type);
602
+ rd_kafka_op_destroy(rko);
603
+ }
604
+
605
+ /* Verify no extra ops */
606
+ {
607
+ rd_kafka_op_t *rko = rd_kafka_q_pop(response_q, 100, 0);
608
+ RD_UT_ASSERT(rko == NULL, "Unexpected extra op");
609
+ }
610
+
611
+ rd_kafka_buf_destroy(rkbuf);
612
+ rd_kafka_q_destroy_owner(response_q);
613
+ rd_kafka_toppar_destroy(rktp);
614
+ ut_destroy_share_consumer(rkshare);
615
+
616
+ RD_UT_PASS();
617
+ }
618
+ #endif /* WITH_ZSTD */
619
+
620
+
621
+ /**
622
+ * @brief Test unsupported MagicByte generates per-offset error ops with REJECT
623
+ *
624
+ * Creates a MessageSet with MagicByte=99 (unsupported future version).
625
+ * Verifies:
626
+ * - One error op per offset in range [BaseOffset, LastOffset]
627
+ * - Each error op has REJECT ack_type (permanent error)
628
+ * - Error code is RD_KAFKA_RESP_ERR__NOT_IMPLEMENTED
629
+ */
630
+ static int unittest_msgset_unsupported_magic_share_consumer(void) {
631
+ rd_kafka_share_t *rkshare;
632
+ rd_kafka_toppar_t *rktp;
633
+ rd_kafka_buf_t *rkbuf;
634
+ rd_kafka_q_t *response_q;
635
+ char *msgset_data;
636
+ size_t msgset_size;
637
+ int64_t BaseOffset = 300;
638
+ int32_t LastOffsetDelta =
639
+ 9; /* Offsets 300-309 inclusive = 10 messages */
640
+ int expected_err_ops = 10;
641
+ int i;
642
+ struct rd_kafka_toppar_ver tver = {.version = 11};
643
+
644
+ RD_UT_BEGIN();
645
+
646
+ rkshare = ut_create_test_share_consumer();
647
+ RD_UT_ASSERT(rkshare, "Failed to create share consumer");
648
+
649
+ rktp =
650
+ ut_create_mock_toppar(rkshare->rkshare_rk, "test-topic-magic", 0);
651
+ RD_UT_ASSERT(rktp, "Failed to create toppar");
652
+
653
+ response_q = rd_kafka_q_new(rkshare->rkshare_rk);
654
+
655
+ /* Craft MessageSet with unsupported MagicByte */
656
+ msgset_size = 200;
657
+ msgset_data = rd_calloc(1, msgset_size);
658
+
659
+ int32_t Length = msgset_size - 12;
660
+
661
+ ut_write_msgset_v2_header(
662
+ msgset_data, BaseOffset,
663
+ Length, /* Length of data after BaseOffset+Length fields */
664
+ -1, /* PartitionLeaderEpoch */
665
+ 99, /* UNSUPPORTED MagicByte - will trigger error */
666
+ 0, /* CRC - doesn't matter, won't get that far */
667
+ 0, /* Attributes */
668
+ LastOffsetDelta, 0, /* BaseTimestamp */
669
+ 0, /* MaxTimestamp */
670
+ -1, /* ProducerId */
671
+ -1, /* ProducerEpoch */
672
+ -1, /* BaseSequence */
673
+ 10 /* RecordCount */);
674
+
675
+ /* Create shadow buffer from raw data */
676
+ rkbuf = rd_kafka_buf_new_shadow(msgset_data, msgset_size, rd_free);
677
+ rkbuf->rkbuf_rkb = rd_kafka_broker_internal(rkshare->rkshare_rk);
678
+
679
+ /* Parse the MessageSet - should detect unsupported MagicByte */
680
+ rd_kafka_share_msgset_parse(rkbuf, rktp, NULL, &tver, response_q);
681
+
682
+ /* Verify we got expected number of error ops */
683
+ for (i = 0; i < expected_err_ops; i++) {
684
+ rd_kafka_op_t *rko = rd_kafka_q_pop(response_q, 1000, 0);
685
+ RD_UT_ASSERT(rko != NULL,
686
+ "Expected error op %d of %d, got timeout", i + 1,
687
+ expected_err_ops);
688
+ RD_UT_ASSERT(rko->rko_type == RD_KAFKA_OP_CONSUMER_ERR,
689
+ "Expected CONSUMER_ERR op, got %d", rko->rko_type);
690
+ RD_UT_ASSERT(rko->rko_err == RD_KAFKA_RESP_ERR__NOT_IMPLEMENTED,
691
+ "Expected NOT_IMPLEMENTED error, got %s",
692
+ rd_kafka_err2str(rko->rko_err));
693
+ RD_UT_ASSERT(rko->rko_u.err.offset == BaseOffset + i,
694
+ "Expected offset %" PRId64 ", got %" PRId64,
695
+ BaseOffset + i, rko->rko_u.err.offset);
696
+ RD_UT_ASSERT(
697
+ rko->rko_u.err.rkm.rkm_u.consumer.ack_type ==
698
+ RD_KAFKA_SHARE_INTERNAL_ACK_REJECT,
699
+ "Expected REJECT ack_type for unsupported MagicByte, got "
700
+ "%d",
701
+ rko->rko_u.err.rkm.rkm_u.consumer.ack_type);
702
+ rd_kafka_op_destroy(rko);
703
+ }
704
+
705
+ /* Verify no extra ops */
706
+ {
707
+ rd_kafka_op_t *rko = rd_kafka_q_pop(response_q, 100, 0);
708
+ RD_UT_ASSERT(rko == NULL, "Unexpected extra op");
709
+ }
710
+
711
+ rd_kafka_buf_destroy(rkbuf);
712
+ rd_kafka_q_destroy_owner(response_q);
713
+ rd_kafka_toppar_destroy(rktp);
714
+ ut_destroy_share_consumer(rkshare);
715
+
716
+ RD_UT_PASS();
717
+ }
718
+
719
+
720
+ /**
721
+ * @brief Test mixed scenario: Success → CRC Error → Success
722
+ *
723
+ * Verifies parser correctly handles:
724
+ * - MessageSet 1: 3 successful messages (offsets 100-102)
725
+ * - MessageSet 2: CRC error covering 5 messages (offsets 103-107)
726
+ * - MessageSet 3: 2 successful messages (offsets 108-109)
727
+ */
728
+ static int unittest_msgset_mixed_success_crc_success(void) {
729
+ rd_kafka_share_t *rkshare;
730
+ rd_kafka_toppar_t *rktp;
731
+ rd_kafka_buf_t *rkbuf;
732
+ rd_kafka_q_t *response_q;
733
+ char *buffer;
734
+ size_t buffer_size = 4096;
735
+ size_t offset = 0;
736
+ struct rd_kafka_toppar_ver tver = {.version = 11};
737
+ const char *values[] = {"msg1", "msg2", "msg3", "msg4", "msg5"};
738
+ size_t value_lens[] = {4, 4, 4, 4, 4};
739
+ int i;
740
+
741
+ RD_UT_BEGIN();
742
+
743
+ rkshare = ut_create_test_share_consumer();
744
+ RD_UT_ASSERT(rkshare, "Failed to create share consumer");
745
+
746
+ rktp =
747
+ ut_create_mock_toppar(rkshare->rkshare_rk, "test-topic-mixed", 0);
748
+ RD_UT_ASSERT(rktp, "Failed to create toppar");
749
+
750
+ response_q = rd_kafka_q_new(rkshare->rkshare_rk);
751
+ buffer = rd_calloc(1, buffer_size);
752
+
753
+ /* MessageSet 1: Valid with 3 messages (offsets 100-102) */
754
+ offset += ut_build_valid_msgset_v2(buffer + offset, 100, 3, values,
755
+ value_lens);
756
+
757
+ /* MessageSet 2: CRC error with 5 messages (offsets 103-107) */
758
+ int64_t BaseOffset2 = 103;
759
+ int32_t LastOffsetDelta2 = 4;
760
+ int32_t Length2 = 61 - 12; /* Just header */
761
+ ut_write_msgset_v2_header(buffer + offset, BaseOffset2, Length2, -1, 2,
762
+ 0xBADC0C, /* Wrong CRC */
763
+ 0, LastOffsetDelta2, 0, 0, -1, -1, -1, 5);
764
+ offset += 12 + Length2;
765
+
766
+ /* MessageSet 3: Valid with 2 messages (offsets 108-109) */
767
+ const char *values3[] = {"msg6", "msg7"};
768
+ size_t value_lens3[] = {4, 4};
769
+ offset += ut_build_valid_msgset_v2(buffer + offset, 108, 2, values3,
770
+ value_lens3);
771
+
772
+ /* Parse all MessageSets */
773
+ rkbuf = rd_kafka_buf_new_shadow(buffer, offset, rd_free);
774
+ rkbuf->rkbuf_rkb = rd_kafka_broker_internal(rkshare->rkshare_rk);
775
+
776
+ rd_kafka_share_msgset_parse(rkbuf, rktp, NULL, &tver, response_q);
777
+
778
+ /* Verify MessageSet 1: 3 FETCH ops with offsets 100-102 */
779
+ for (i = 0; i < 3; i++) {
780
+ rd_kafka_op_t *rko = rd_kafka_q_pop(response_q, 1000, 0);
781
+ RD_UT_ASSERT(rko != NULL, "Expected FETCH op %d, got timeout",
782
+ i);
783
+ RD_UT_ASSERT(rko->rko_type == RD_KAFKA_OP_FETCH,
784
+ "Expected FETCH op, got %d", rko->rko_type);
785
+ RD_UT_ASSERT(rko->rko_u.fetch.rkm.rkm_offset == 100 + i,
786
+ "Expected offset %d, got %" PRId64, 100 + i,
787
+ rko->rko_u.fetch.rkm.rkm_offset);
788
+ rd_kafka_op_destroy(rko);
789
+ }
790
+
791
+ /* Verify MessageSet 2: 5 CONSUMER_ERR ops with offsets 103-107 */
792
+ for (i = 0; i < 5; i++) {
793
+ rd_kafka_op_t *rko = rd_kafka_q_pop(response_q, 1000, 0);
794
+ RD_UT_ASSERT(rko != NULL,
795
+ "Expected CRC error op %d, got timeout", i);
796
+ RD_UT_ASSERT(rko->rko_type == RD_KAFKA_OP_CONSUMER_ERR,
797
+ "Expected CONSUMER_ERR op, got %d", rko->rko_type);
798
+ RD_UT_ASSERT(rko->rko_err == RD_KAFKA_RESP_ERR__BAD_MSG,
799
+ "Expected BAD_MSG error, got %s",
800
+ rd_kafka_err2str(rko->rko_err));
801
+ RD_UT_ASSERT(rko->rko_u.err.offset == 103 + i,
802
+ "Expected offset %d, got %" PRId64, 103 + i,
803
+ rko->rko_u.err.offset);
804
+ RD_UT_ASSERT(rko->rko_u.err.rkm.rkm_u.consumer.ack_type ==
805
+ RD_KAFKA_SHARE_INTERNAL_ACK_REJECT,
806
+ "Expected REJECT ack_type");
807
+ rd_kafka_op_destroy(rko);
808
+ }
809
+
810
+ /* Verify MessageSet 3: 2 FETCH ops with offsets 108-109 */
811
+ for (i = 0; i < 2; i++) {
812
+ rd_kafka_op_t *rko = rd_kafka_q_pop(response_q, 1000, 0);
813
+ RD_UT_ASSERT(rko != NULL, "Expected FETCH op %d, got timeout",
814
+ i + 3);
815
+ RD_UT_ASSERT(rko->rko_type == RD_KAFKA_OP_FETCH,
816
+ "Expected FETCH op, got %d", rko->rko_type);
817
+ RD_UT_ASSERT(rko->rko_u.fetch.rkm.rkm_offset == 108 + i,
818
+ "Expected offset %d, got %" PRId64, 108 + i,
819
+ rko->rko_u.fetch.rkm.rkm_offset);
820
+ rd_kafka_op_destroy(rko);
821
+ }
822
+
823
+ /* Verify no extra ops */
824
+ {
825
+ rd_kafka_op_t *rko = rd_kafka_q_pop(response_q, 100, 0);
826
+ RD_UT_ASSERT(rko == NULL, "Unexpected extra op");
827
+ }
828
+
829
+ rd_kafka_buf_destroy(rkbuf);
830
+ rd_kafka_q_destroy_owner(response_q);
831
+ rd_kafka_toppar_destroy(rktp);
832
+ ut_destroy_share_consumer(rkshare);
833
+
834
+ RD_UT_PASS();
835
+ }
836
+
837
+
838
+ #if WITH_ZSTD
839
+ /**
840
+ * @brief Test mixed scenario: CRC Error → Success → Decompression Error
841
+ *
842
+ * Verifies parser correctly handles:
843
+ * - MessageSet 1: CRC error covering 2 messages (offsets 200-201)
844
+ * - MessageSet 2: 4 successful messages (offsets 202-205)
845
+ * - MessageSet 3: Decompression error covering 3 messages (offsets 206-208)
846
+ */
847
+ static int unittest_msgset_mixed_crc_success_decomp(void) {
848
+ rd_kafka_share_t *rkshare;
849
+ rd_kafka_toppar_t *rktp;
850
+ rd_kafka_buf_t *rkbuf;
851
+ rd_kafka_q_t *response_q;
852
+ char *buffer;
853
+ size_t buffer_size = 4096;
854
+ size_t offset = 0;
855
+ struct rd_kafka_toppar_ver tver = {.version = 11};
856
+ const char *values[] = {"a", "b", "c", "d"};
857
+ size_t value_lens[] = {1, 1, 1, 1};
858
+ int i;
859
+
860
+ RD_UT_BEGIN();
861
+
862
+ rkshare = ut_create_test_share_consumer();
863
+ RD_UT_ASSERT(rkshare, "Failed to create share consumer");
864
+
865
+ rktp =
866
+ ut_create_mock_toppar(rkshare->rkshare_rk, "test-topic-mixed2", 0);
867
+ RD_UT_ASSERT(rktp, "Failed to create toppar");
868
+
869
+ response_q = rd_kafka_q_new(rkshare->rkshare_rk);
870
+ buffer = rd_calloc(1, buffer_size);
871
+
872
+ /* MessageSet 1: CRC error with 2 messages (offsets 200-201) */
873
+ ut_write_msgset_v2_header(buffer + offset, 200, 61 - 12, -1, 2,
874
+ 0xDEADC0C, 0, 1, 0, 0, -1, -1, -1, 2);
875
+ offset += 12 + (61 - 12);
876
+
877
+ /* MessageSet 2: Valid with 4 messages (offsets 202-205) */
878
+ offset += ut_build_valid_msgset_v2(buffer + offset, 202, 4, values,
879
+ value_lens);
880
+
881
+ /* MessageSet 3: Decompression error with 3 messages (offsets 206-208)
882
+ */
883
+ char corrupted_data[16] = {0xDE, 0xAD, 0xBE, 0xEF}; /* Garbage */
884
+ size_t decomp_start = offset;
885
+ ut_write_msgset_v2_header(buffer + offset, 206,
886
+ 49 + sizeof(corrupted_data), -1, 2, 0,
887
+ 4, /* ZSTD compression */
888
+ 2, 0, 0, -1, -1, -1, 3);
889
+ offset += 61;
890
+ memcpy(buffer + offset, corrupted_data, sizeof(corrupted_data));
891
+ offset += sizeof(corrupted_data);
892
+ /* Fix CRC for decompression error (CRC is valid, data is corrupt) */
893
+ uint32_t crc = rd_crc32c(0, buffer + decomp_start + 21,
894
+ 49 + sizeof(corrupted_data) - 4 - 1 - 4);
895
+ ut_put_be32(buffer + decomp_start + 17, crc);
896
+
897
+ /* Parse all MessageSets */
898
+ rkbuf = rd_kafka_buf_new_shadow(buffer, offset, rd_free);
899
+ rkbuf->rkbuf_rkb = rd_kafka_broker_internal(rkshare->rkshare_rk);
900
+
901
+ rd_kafka_share_msgset_parse(rkbuf, rktp, NULL, &tver, response_q);
902
+
903
+ /* Verify MessageSet 1: 2 CRC error ops (offsets 200-201) */
904
+ for (i = 0; i < 2; i++) {
905
+ rd_kafka_op_t *rko = rd_kafka_q_pop(response_q, 1000, 0);
906
+ RD_UT_ASSERT(rko != NULL, "Expected CRC error op %d", i);
907
+ RD_UT_ASSERT(rko->rko_type == RD_KAFKA_OP_CONSUMER_ERR,
908
+ "Expected CONSUMER_ERR");
909
+ RD_UT_ASSERT(rko->rko_err == RD_KAFKA_RESP_ERR__BAD_MSG,
910
+ "Expected BAD_MSG");
911
+ RD_UT_ASSERT(rko->rko_u.err.rkm.rkm_u.consumer.ack_type ==
912
+ RD_KAFKA_SHARE_INTERNAL_ACK_REJECT,
913
+ "Expected REJECT");
914
+ rd_kafka_op_destroy(rko);
915
+ }
916
+
917
+ /* Verify MessageSet 2: 4 successful FETCH ops (offsets 202-205) */
918
+ for (i = 0; i < 4; i++) {
919
+ rd_kafka_op_t *rko = rd_kafka_q_pop(response_q, 1000, 0);
920
+ RD_UT_ASSERT(rko != NULL, "Expected FETCH op %d", i);
921
+ RD_UT_ASSERT(rko->rko_type == RD_KAFKA_OP_FETCH,
922
+ "Expected FETCH op");
923
+ RD_UT_ASSERT(rko->rko_u.fetch.rkm.rkm_offset == 202 + i,
924
+ "Expected offset %d", 202 + i);
925
+ rd_kafka_op_destroy(rko);
926
+ }
927
+
928
+ /* Verify MessageSet 3: 3 decompression error ops (offsets 206-208) */
929
+ for (i = 0; i < 3; i++) {
930
+ rd_kafka_op_t *rko = rd_kafka_q_pop(response_q, 1000, 0);
931
+ RD_UT_ASSERT(rko != NULL, "Expected decomp error op %d", i);
932
+ RD_UT_ASSERT(rko->rko_type == RD_KAFKA_OP_CONSUMER_ERR,
933
+ "Expected CONSUMER_ERR");
934
+ RD_UT_ASSERT(rko->rko_err == RD_KAFKA_RESP_ERR__BAD_COMPRESSION,
935
+ "Expected BAD_COMPRESSION");
936
+ RD_UT_ASSERT(rko->rko_u.err.rkm.rkm_u.consumer.ack_type ==
937
+ RD_KAFKA_SHARE_INTERNAL_ACK_RELEASE,
938
+ "Expected RELEASE");
939
+ rd_kafka_op_destroy(rko);
940
+ }
941
+
942
+ /* Verify no extra ops */
943
+ {
944
+ rd_kafka_op_t *rko = rd_kafka_q_pop(response_q, 100, 0);
945
+ RD_UT_ASSERT(rko == NULL, "Unexpected extra op");
946
+ }
947
+
948
+ rd_kafka_buf_destroy(rkbuf);
949
+ rd_kafka_q_destroy_owner(response_q);
950
+ rd_kafka_toppar_destroy(rktp);
951
+ ut_destroy_share_consumer(rkshare);
952
+
953
+ RD_UT_PASS();
954
+ }
955
+ #endif /* WITH_ZSTD */
956
+
957
+
958
+ /**
959
+ * @brief Test mixed scenario: Unsupported Magic → Success → CRC Error → Success
960
+ *
961
+ * Verifies parser correctly handles:
962
+ * - MessageSet 1: Unsupported MagicByte covering 3 messages (offsets 300-302)
963
+ * - MessageSet 2: 1 successful message (offset 303)
964
+ * - MessageSet 3: CRC error covering 2 messages (offsets 304-305)
965
+ * - MessageSet 4: 5 successful messages (offsets 306-310)
966
+ */
967
+ static int unittest_msgset_mixed_magic_success_crc_success(void) {
968
+ rd_kafka_share_t *rkshare;
969
+ rd_kafka_toppar_t *rktp;
970
+ rd_kafka_buf_t *rkbuf;
971
+ rd_kafka_q_t *response_q;
972
+ char *buffer;
973
+ size_t buffer_size = 4096;
974
+ size_t offset = 0;
975
+ struct rd_kafka_toppar_ver tver = {.version = 11};
976
+ const char *value1 = "x";
977
+ size_t value_len1 = 1;
978
+ const char *values5[] = {"a", "b", "c", "d", "e"};
979
+ size_t value_lens5[] = {1, 1, 1, 1, 1};
980
+ int i;
981
+
982
+ RD_UT_BEGIN();
983
+
984
+ rkshare = ut_create_test_share_consumer();
985
+ RD_UT_ASSERT(rkshare, "Failed to create share consumer");
986
+
987
+ rktp =
988
+ ut_create_mock_toppar(rkshare->rkshare_rk, "test-topic-mixed3", 0);
989
+ RD_UT_ASSERT(rktp, "Failed to create toppar");
990
+
991
+ response_q = rd_kafka_q_new(rkshare->rkshare_rk);
992
+ buffer = rd_calloc(1, buffer_size);
993
+
994
+ /* MessageSet 1: Unsupported MagicByte=99, 3 messages (offsets 300-302)
995
+ */
996
+ ut_write_msgset_v2_header(buffer + offset, 300, 61 - 12, -1,
997
+ 99, /* Unsupported */
998
+ 0, 0, 2, 0, 0, -1, -1, -1, 3);
999
+ offset += 12 + (61 - 12);
1000
+
1001
+ /* MessageSet 2: Valid with 1 message (offset 303) */
1002
+ offset += ut_build_valid_msgset_v2(buffer + offset, 303, 1, &value1,
1003
+ &value_len1);
1004
+
1005
+ /* MessageSet 3: CRC error, 2 messages (offsets 304-305) */
1006
+ ut_write_msgset_v2_header(buffer + offset, 304, 61 - 12, -1, 2,
1007
+ 0xBADBAD, 0, 1, 0, 0, -1, -1, -1, 2);
1008
+ offset += 12 + (61 - 12);
1009
+
1010
+ /* MessageSet 4: Valid with 5 messages (offsets 306-310) */
1011
+ offset += ut_build_valid_msgset_v2(buffer + offset, 306, 5, values5,
1012
+ value_lens5);
1013
+
1014
+ /* Parse all MessageSets */
1015
+ rkbuf = rd_kafka_buf_new_shadow(buffer, offset, rd_free);
1016
+ rkbuf->rkbuf_rkb = rd_kafka_broker_internal(rkshare->rkshare_rk);
1017
+
1018
+ rd_kafka_share_msgset_parse(rkbuf, rktp, NULL, &tver, response_q);
1019
+
1020
+ /* Verify MessageSet 1: 3 unsupported magic error ops (offsets 300-302)
1021
+ */
1022
+ for (i = 0; i < 3; i++) {
1023
+ rd_kafka_op_t *rko = rd_kafka_q_pop(response_q, 1000, 0);
1024
+ RD_UT_ASSERT(rko != NULL, "Expected magic error op %d", i);
1025
+ RD_UT_ASSERT(rko->rko_type == RD_KAFKA_OP_CONSUMER_ERR,
1026
+ "Expected CONSUMER_ERR");
1027
+ RD_UT_ASSERT(rko->rko_err == RD_KAFKA_RESP_ERR__NOT_IMPLEMENTED,
1028
+ "Expected NOT_IMPLEMENTED");
1029
+ RD_UT_ASSERT(rko->rko_u.err.rkm.rkm_u.consumer.ack_type ==
1030
+ RD_KAFKA_SHARE_INTERNAL_ACK_REJECT,
1031
+ "Expected REJECT");
1032
+ rd_kafka_op_destroy(rko);
1033
+ }
1034
+
1035
+ /* Verify MessageSet 2: 1 successful FETCH op (offset 303) */
1036
+ {
1037
+ rd_kafka_op_t *rko = rd_kafka_q_pop(response_q, 1000, 0);
1038
+ RD_UT_ASSERT(rko != NULL, "Expected FETCH op");
1039
+ RD_UT_ASSERT(rko->rko_type == RD_KAFKA_OP_FETCH,
1040
+ "Expected FETCH op");
1041
+ RD_UT_ASSERT(rko->rko_u.fetch.rkm.rkm_offset == 303,
1042
+ "Expected offset 303");
1043
+ rd_kafka_op_destroy(rko);
1044
+ }
1045
+
1046
+ /* Verify MessageSet 3: 2 CRC error ops (offsets 304-305) */
1047
+ for (i = 0; i < 2; i++) {
1048
+ rd_kafka_op_t *rko = rd_kafka_q_pop(response_q, 1000, 0);
1049
+ RD_UT_ASSERT(rko != NULL, "Expected CRC error op %d", i);
1050
+ RD_UT_ASSERT(rko->rko_type == RD_KAFKA_OP_CONSUMER_ERR,
1051
+ "Expected CONSUMER_ERR");
1052
+ RD_UT_ASSERT(rko->rko_err == RD_KAFKA_RESP_ERR__BAD_MSG,
1053
+ "Expected BAD_MSG");
1054
+ RD_UT_ASSERT(rko->rko_u.err.rkm.rkm_u.consumer.ack_type ==
1055
+ RD_KAFKA_SHARE_INTERNAL_ACK_REJECT,
1056
+ "Expected REJECT");
1057
+ rd_kafka_op_destroy(rko);
1058
+ }
1059
+
1060
+ /* Verify MessageSet 4: 5 successful FETCH ops (offsets 306-310) */
1061
+ for (i = 0; i < 5; i++) {
1062
+ rd_kafka_op_t *rko = rd_kafka_q_pop(response_q, 1000, 0);
1063
+ RD_UT_ASSERT(rko != NULL, "Expected FETCH op %d", i);
1064
+ RD_UT_ASSERT(rko->rko_type == RD_KAFKA_OP_FETCH,
1065
+ "Expected FETCH op");
1066
+ RD_UT_ASSERT(rko->rko_u.fetch.rkm.rkm_offset == 306 + i,
1067
+ "Expected offset %d", 306 + i);
1068
+ rd_kafka_op_destroy(rko);
1069
+ }
1070
+
1071
+ /* Verify no extra ops */
1072
+ {
1073
+ rd_kafka_op_t *rko = rd_kafka_q_pop(response_q, 100, 0);
1074
+ RD_UT_ASSERT(rko == NULL, "Unexpected extra op");
1075
+ }
1076
+
1077
+ rd_kafka_buf_destroy(rkbuf);
1078
+ rd_kafka_q_destroy_owner(response_q);
1079
+ rd_kafka_toppar_destroy(rktp);
1080
+ ut_destroy_share_consumer(rkshare);
1081
+
1082
+ RD_UT_PASS();
1083
+ }
1084
+
1085
+
1086
+ /**
1087
+ * @brief Test all successful MessageSets
1088
+ *
1089
+ * Verifies parser correctly handles multiple consecutive successful
1090
+ * MessageSets:
1091
+ * - MessageSet 1: 2 messages (offsets 400-401)
1092
+ * - MessageSet 2: 3 messages (offsets 402-404)
1093
+ * - MessageSet 3: 1 message (offset 405)
1094
+ * - MessageSet 4: 4 messages (offsets 406-409)
1095
+ */
1096
+ static int unittest_msgset_all_success(void) {
1097
+ rd_kafka_share_t *rkshare;
1098
+ rd_kafka_toppar_t *rktp;
1099
+ rd_kafka_buf_t *rkbuf;
1100
+ rd_kafka_q_t *response_q;
1101
+ char *buffer;
1102
+ size_t buffer_size = 4096;
1103
+ size_t offset = 0;
1104
+ struct rd_kafka_toppar_ver tver = {.version = 11};
1105
+ const char *values2[] = {"m1", "m2"};
1106
+ size_t value_lens2[] = {2, 2};
1107
+ const char *values3[] = {"m3", "m4", "m5"};
1108
+ size_t value_lens3[] = {2, 2, 2};
1109
+ const char *value1 = "m6";
1110
+ size_t value_len1 = 2;
1111
+ const char *values4[] = {"m7", "m8", "m9", "m10"};
1112
+ size_t value_lens4[] = {2, 2, 2, 3};
1113
+ int i;
1114
+
1115
+ RD_UT_BEGIN();
1116
+
1117
+ rkshare = ut_create_test_share_consumer();
1118
+ RD_UT_ASSERT(rkshare, "Failed to create share consumer");
1119
+
1120
+ rktp =
1121
+ ut_create_mock_toppar(rkshare->rkshare_rk, "test-topic-success", 0);
1122
+ RD_UT_ASSERT(rktp, "Failed to create toppar");
1123
+
1124
+ response_q = rd_kafka_q_new(rkshare->rkshare_rk);
1125
+ buffer = rd_calloc(1, buffer_size);
1126
+
1127
+ /* Build 4 valid MessageSets */
1128
+ offset += ut_build_valid_msgset_v2(buffer + offset, 400, 2, values2,
1129
+ value_lens2);
1130
+ offset += ut_build_valid_msgset_v2(buffer + offset, 402, 3, values3,
1131
+ value_lens3);
1132
+ offset += ut_build_valid_msgset_v2(buffer + offset, 405, 1, &value1,
1133
+ &value_len1);
1134
+ offset += ut_build_valid_msgset_v2(buffer + offset, 406, 4, values4,
1135
+ value_lens4);
1136
+
1137
+ /* Parse all MessageSets */
1138
+ rkbuf = rd_kafka_buf_new_shadow(buffer, offset, rd_free);
1139
+ rkbuf->rkbuf_rkb = rd_kafka_broker_internal(rkshare->rkshare_rk);
1140
+
1141
+ rd_kafka_share_msgset_parse(rkbuf, rktp, NULL, &tver, response_q);
1142
+
1143
+ /* Verify all 10 messages received successfully (offsets 400-409) */
1144
+ for (i = 0; i < 10; i++) {
1145
+ rd_kafka_op_t *rko = rd_kafka_q_pop(response_q, 1000, 0);
1146
+ RD_UT_ASSERT(rko != NULL, "Expected FETCH op %d, got timeout",
1147
+ i);
1148
+ RD_UT_ASSERT(rko->rko_type == RD_KAFKA_OP_FETCH,
1149
+ "Expected FETCH op, got %d", rko->rko_type);
1150
+ RD_UT_ASSERT(rko->rko_u.fetch.rkm.rkm_offset == 400 + i,
1151
+ "Expected offset %d, got %" PRId64, 400 + i,
1152
+ rko->rko_u.fetch.rkm.rkm_offset);
1153
+ rd_kafka_op_destroy(rko);
1154
+ }
1155
+
1156
+ /* Verify no extra ops */
1157
+ {
1158
+ rd_kafka_op_t *rko = rd_kafka_q_pop(response_q, 100, 0);
1159
+ RD_UT_ASSERT(rko == NULL, "Unexpected extra op");
1160
+ }
1161
+
1162
+ rd_kafka_buf_destroy(rkbuf);
1163
+ rd_kafka_q_destroy_owner(response_q);
1164
+ rd_kafka_toppar_destroy(rktp);
1165
+ ut_destroy_share_consumer(rkshare);
1166
+
1167
+ RD_UT_PASS();
1168
+ }
1169
+
1170
+
1171
+ /**
1172
+ * @brief Test all error MessageSets in sequence
1173
+ *
1174
+ * Verifies parser correctly handles consecutive errors:
1175
+ * - MessageSet 1: CRC error, 2 messages (offsets 500-501)
1176
+ * - MessageSet 2: Unsupported MagicByte, 1 message (offset 502)
1177
+ * - MessageSet 3: CRC error, 3 messages (offsets 503-505)
1178
+ */
1179
+ static int unittest_msgset_all_errors(void) {
1180
+ rd_kafka_share_t *rkshare;
1181
+ rd_kafka_toppar_t *rktp;
1182
+ rd_kafka_buf_t *rkbuf;
1183
+ rd_kafka_q_t *response_q;
1184
+ char *buffer;
1185
+ size_t buffer_size = 4096;
1186
+ size_t offset = 0;
1187
+ struct rd_kafka_toppar_ver tver = {.version = 11};
1188
+ int i;
1189
+
1190
+ RD_UT_BEGIN();
1191
+
1192
+ rkshare = ut_create_test_share_consumer();
1193
+ RD_UT_ASSERT(rkshare, "Failed to create share consumer");
1194
+
1195
+ rktp =
1196
+ ut_create_mock_toppar(rkshare->rkshare_rk, "test-topic-errors", 0);
1197
+ RD_UT_ASSERT(rktp, "Failed to create toppar");
1198
+
1199
+ response_q = rd_kafka_q_new(rkshare->rkshare_rk);
1200
+ buffer = rd_calloc(1, buffer_size);
1201
+
1202
+ /* MessageSet 1: CRC error, 2 messages (offsets 500-501) */
1203
+ ut_write_msgset_v2_header(buffer + offset, 500, 61 - 12, -1, 2,
1204
+ 0xBADC001, 0, 1, 0, 0, -1, -1, -1, 2);
1205
+ offset += 61;
1206
+
1207
+ /* MessageSet 2: Unsupported MagicByte, 1 message (offset 502) */
1208
+ ut_write_msgset_v2_header(buffer + offset, 502, 61 - 12, -1, 99, 0, 0,
1209
+ 0, 0, 0, -1, -1, -1, 1);
1210
+ offset += 61;
1211
+
1212
+ /* MessageSet 3: CRC error, 3 messages (offsets 503-505) */
1213
+ ut_write_msgset_v2_header(buffer + offset, 503, 61 - 12, -1, 2,
1214
+ 0xBADC002, 0, 2, 0, 0, -1, -1, -1, 3);
1215
+ offset += 61;
1216
+
1217
+ RD_UT_SAY("Buffer size: %zu bytes", offset);
1218
+
1219
+ /* Parse all MessageSets */
1220
+ rkbuf = rd_kafka_buf_new_shadow(buffer, offset, rd_free);
1221
+ rkbuf->rkbuf_rkb = rd_kafka_broker_internal(rkshare->rkshare_rk);
1222
+
1223
+ rd_kafka_resp_err_t parse_err =
1224
+ rd_kafka_share_msgset_parse(rkbuf, rktp, NULL, &tver, response_q);
1225
+
1226
+ RD_UT_SAY("Parse returned: %s", rd_kafka_err2str(parse_err));
1227
+
1228
+ /* Verify MessageSet 1: 2 CRC error ops (offsets 500-501) */
1229
+ for (i = 0; i < 2; i++) {
1230
+ rd_kafka_op_t *rko = rd_kafka_q_pop(response_q, 1000, 0);
1231
+ RD_UT_ASSERT(rko != NULL, "Expected CRC error op %d", i);
1232
+ RD_UT_ASSERT(rko->rko_type == RD_KAFKA_OP_CONSUMER_ERR,
1233
+ "Expected CONSUMER_ERR");
1234
+ RD_UT_ASSERT(rko->rko_err == RD_KAFKA_RESP_ERR__BAD_MSG,
1235
+ "Expected BAD_MSG");
1236
+ rd_kafka_op_destroy(rko);
1237
+ }
1238
+
1239
+ /* Verify MessageSet 2: 1 unsupported magic error op (offset 502) */
1240
+ {
1241
+ rd_kafka_op_t *rko = rd_kafka_q_pop(response_q, 1000, 0);
1242
+ RD_UT_ASSERT(rko != NULL, "Expected magic error op");
1243
+ RD_UT_ASSERT(rko->rko_type == RD_KAFKA_OP_CONSUMER_ERR,
1244
+ "Expected CONSUMER_ERR");
1245
+ RD_UT_ASSERT(rko->rko_err == RD_KAFKA_RESP_ERR__NOT_IMPLEMENTED,
1246
+ "Expected NOT_IMPLEMENTED");
1247
+ rd_kafka_op_destroy(rko);
1248
+ }
1249
+
1250
+ /* Verify MessageSet 3: 3 CRC error ops (offsets 503-505) */
1251
+ for (i = 0; i < 3; i++) {
1252
+ rd_kafka_op_t *rko = rd_kafka_q_pop(response_q, 1000, 0);
1253
+ RD_UT_ASSERT(rko != NULL, "Expected CRC error op %d", i);
1254
+ RD_UT_ASSERT(rko->rko_type == RD_KAFKA_OP_CONSUMER_ERR,
1255
+ "Expected CONSUMER_ERR");
1256
+ RD_UT_ASSERT(rko->rko_err == RD_KAFKA_RESP_ERR__BAD_MSG,
1257
+ "Expected BAD_MSG");
1258
+ rd_kafka_op_destroy(rko);
1259
+ }
1260
+
1261
+ /* Verify no extra ops */
1262
+ {
1263
+ rd_kafka_op_t *rko = rd_kafka_q_pop(response_q, 100, 0);
1264
+ RD_UT_ASSERT(rko == NULL, "Unexpected extra op");
1265
+ }
1266
+
1267
+ rd_kafka_buf_destroy(rkbuf);
1268
+ rd_kafka_q_destroy_owner(response_q);
1269
+ rd_kafka_toppar_destroy(rktp);
1270
+ ut_destroy_share_consumer(rkshare);
1271
+
1272
+ RD_UT_PASS();
1273
+ }
1274
+
1275
+
1276
+ #if WITH_ZSTD
1277
+ /**
1278
+ * @brief Test all 3 error types interleaved with valid messages
1279
+ *
1280
+ * Verifies parser continues through all error types:
1281
+ * - MessageSet 1: CRC error (10 messages, offsets 0-9)
1282
+ * - MessageSet 2: Valid (10 messages, offsets 10-19)
1283
+ * - MessageSet 3: Decompression error (10 messages, offsets 20-29)
1284
+ * - MessageSet 4: Valid (10 messages, offsets 30-39)
1285
+ * - MessageSet 5: Unsupported MagicByte (10 messages, offsets 40-49)
1286
+ * - MessageSet 6: Valid (10 messages, offsets 50-59)
1287
+ *
1288
+ * This is the critical test case: all batches must be processed,
1289
+ * with valid messages delivered even after errors.
1290
+ */
1291
+ static int unittest_msgset_all_error_types_with_valid(void) {
1292
+ rd_kafka_share_t *rkshare;
1293
+ rd_kafka_toppar_t *rktp;
1294
+ rd_kafka_buf_t *rkbuf;
1295
+ rd_kafka_q_t *response_q;
1296
+ char *buffer;
1297
+ size_t buffer_size = 8192;
1298
+ size_t offset = 0;
1299
+ struct rd_kafka_toppar_ver tver = {.version = 11};
1300
+ const char *values[] = {"a", "b", "c", "d", "e",
1301
+ "f", "g", "h", "i", "j"};
1302
+ size_t value_lens[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
1303
+ int i;
1304
+
1305
+ RD_UT_BEGIN();
1306
+
1307
+ rkshare = ut_create_test_share_consumer();
1308
+ RD_UT_ASSERT(rkshare, "Failed to create share consumer");
1309
+
1310
+ rktp = ut_create_mock_toppar(rkshare->rkshare_rk,
1311
+ "test-topic-all-errors", 0);
1312
+ RD_UT_ASSERT(rktp, "Failed to create toppar");
1313
+
1314
+ response_q = rd_kafka_q_new(rkshare->rkshare_rk);
1315
+ buffer = rd_calloc(1, buffer_size);
1316
+
1317
+ /* MessageSet 1: CRC error with 10 messages (offsets 0-9) */
1318
+ ut_write_msgset_v2_header(buffer + offset, 0, 100, -1, 2, 0xBADC0001, 0,
1319
+ 9, 0, 0, -1, -1, -1, 10);
1320
+ offset += 112;
1321
+
1322
+ /* MessageSet 2: Valid with 10 messages (offsets 10-19) */
1323
+ offset += ut_build_valid_msgset_v2(buffer + offset, 10, 10, values,
1324
+ value_lens);
1325
+
1326
+ /* MessageSet 3: Decompression error with 10 messages (offsets 20-29) */
1327
+ char corrupted_data[32];
1328
+ memset(corrupted_data, 0xDE, sizeof(corrupted_data));
1329
+ size_t decomp_start = offset;
1330
+ ut_write_msgset_v2_header(buffer + offset, 20,
1331
+ 49 + sizeof(corrupted_data), -1, 2, 0,
1332
+ 4, /* ZSTD compression */
1333
+ 9, 0, 0, -1, -1, -1, 10);
1334
+ offset += 61;
1335
+ memcpy(buffer + offset, corrupted_data, sizeof(corrupted_data));
1336
+ offset += sizeof(corrupted_data);
1337
+ /* Fix CRC for decompression error (CRC valid, data corrupt) */
1338
+ uint32_t crc = rd_crc32c(0, buffer + decomp_start + 21,
1339
+ 49 + sizeof(corrupted_data) - 4 - 1 - 4);
1340
+ ut_put_be32(buffer + decomp_start + 17, crc);
1341
+
1342
+ /* MessageSet 4: Valid with 10 messages (offsets 30-39) */
1343
+ offset += ut_build_valid_msgset_v2(buffer + offset, 30, 10, values,
1344
+ value_lens);
1345
+
1346
+ /* MessageSet 5: Unsupported MagicByte with 10 messages (offsets 40-49)
1347
+ */
1348
+ ut_write_msgset_v2_header(buffer + offset, 40, 100, -1,
1349
+ 99, /* Bad magic */
1350
+ 0, 0, 9, 0, 0, -1, -1, -1, 10);
1351
+ offset += 112;
1352
+
1353
+ /* MessageSet 6: Valid with 10 messages (offsets 50-59) */
1354
+ offset += ut_build_valid_msgset_v2(buffer + offset, 50, 10, values,
1355
+ value_lens);
1356
+
1357
+ RD_UT_SAY("Total buffer size: %zu bytes, 6 MessageSets", offset);
1358
+
1359
+ /* Parse all MessageSets */
1360
+ rkbuf = rd_kafka_buf_new_shadow(buffer, offset, rd_free);
1361
+ rkbuf->rkbuf_rkb = rd_kafka_broker_internal(rkshare->rkshare_rk);
1362
+
1363
+ rd_kafka_share_msgset_parse(rkbuf, rktp, NULL, &tver, response_q);
1364
+
1365
+ /* Verify MessageSet 1: 10 CRC error ops (offsets 0-9) */
1366
+ RD_UT_SAY("Verifying MessageSet 1: CRC errors");
1367
+ for (i = 0; i < 10; i++) {
1368
+ rd_kafka_op_t *rko = rd_kafka_q_pop(response_q, 1000, 0);
1369
+ RD_UT_ASSERT(rko != NULL,
1370
+ "Expected CRC error op %d of 10, got timeout", i);
1371
+ RD_UT_ASSERT(rko->rko_type == RD_KAFKA_OP_CONSUMER_ERR,
1372
+ "Expected CONSUMER_ERR, got %d", rko->rko_type);
1373
+ RD_UT_ASSERT(rko->rko_err == RD_KAFKA_RESP_ERR__BAD_MSG,
1374
+ "Expected BAD_MSG, got %s",
1375
+ rd_kafka_err2str(rko->rko_err));
1376
+ RD_UT_ASSERT(rko->rko_u.err.offset == 0 + i,
1377
+ "Expected offset %d, got %" PRId64, i,
1378
+ rko->rko_u.err.offset);
1379
+ RD_UT_ASSERT(rko->rko_u.err.rkm.rkm_u.consumer.ack_type ==
1380
+ RD_KAFKA_SHARE_INTERNAL_ACK_REJECT,
1381
+ "Expected REJECT ack_type for CRC error");
1382
+ rd_kafka_op_destroy(rko);
1383
+ }
1384
+
1385
+ /* Verify MessageSet 2: 10 successful FETCH ops (offsets 10-19) */
1386
+ RD_UT_SAY("Verifying MessageSet 2: Valid messages");
1387
+ for (i = 0; i < 10; i++) {
1388
+ rd_kafka_op_t *rko = rd_kafka_q_pop(response_q, 1000, 0);
1389
+ RD_UT_ASSERT(rko != NULL, "Expected FETCH op %d of 10", i);
1390
+ RD_UT_ASSERT(rko->rko_type == RD_KAFKA_OP_FETCH,
1391
+ "Expected FETCH op, got %d", rko->rko_type);
1392
+ RD_UT_ASSERT(rko->rko_u.fetch.rkm.rkm_offset == 10 + i,
1393
+ "Expected offset %d, got %" PRId64, 10 + i,
1394
+ rko->rko_u.fetch.rkm.rkm_offset);
1395
+ rd_kafka_op_destroy(rko);
1396
+ }
1397
+
1398
+ /* Verify MessageSet 3: 10 decompression error ops (offsets 20-29) */
1399
+ RD_UT_SAY("Verifying MessageSet 3: Decompression errors");
1400
+ for (i = 0; i < 10; i++) {
1401
+ rd_kafka_op_t *rko = rd_kafka_q_pop(response_q, 1000, 0);
1402
+ RD_UT_ASSERT(rko != NULL, "Expected decomp error op %d of 10",
1403
+ i);
1404
+ RD_UT_ASSERT(rko->rko_type == RD_KAFKA_OP_CONSUMER_ERR,
1405
+ "Expected CONSUMER_ERR, got %d", rko->rko_type);
1406
+ RD_UT_ASSERT(rko->rko_err == RD_KAFKA_RESP_ERR__BAD_COMPRESSION,
1407
+ "Expected BAD_COMPRESSION, got %s",
1408
+ rd_kafka_err2str(rko->rko_err));
1409
+ RD_UT_ASSERT(rko->rko_u.err.offset == 20 + i,
1410
+ "Expected offset %d, got %" PRId64, 20 + i,
1411
+ rko->rko_u.err.offset);
1412
+ RD_UT_ASSERT(
1413
+ rko->rko_u.err.rkm.rkm_u.consumer.ack_type ==
1414
+ RD_KAFKA_SHARE_INTERNAL_ACK_RELEASE,
1415
+ "Expected RELEASE ack_type for decompression error");
1416
+ rd_kafka_op_destroy(rko);
1417
+ }
1418
+
1419
+ /* Verify MessageSet 4: 10 successful FETCH ops (offsets 30-39) */
1420
+ RD_UT_SAY("Verifying MessageSet 4: Valid messages after decomp error");
1421
+ for (i = 0; i < 10; i++) {
1422
+ rd_kafka_op_t *rko = rd_kafka_q_pop(response_q, 1000, 0);
1423
+ RD_UT_ASSERT(rko != NULL,
1424
+ "Expected FETCH op %d of 10 after decomp error, "
1425
+ "got timeout "
1426
+ "(BUG: parser stopped!)",
1427
+ i);
1428
+ RD_UT_ASSERT(rko->rko_type == RD_KAFKA_OP_FETCH,
1429
+ "Expected FETCH op, got %d", rko->rko_type);
1430
+ RD_UT_ASSERT(rko->rko_u.fetch.rkm.rkm_offset == 30 + i,
1431
+ "Expected offset %d, got %" PRId64, 30 + i,
1432
+ rko->rko_u.fetch.rkm.rkm_offset);
1433
+ rd_kafka_op_destroy(rko);
1434
+ }
1435
+
1436
+ /* Verify MessageSet 5: 10 unsupported magic error ops (offsets 40-49)
1437
+ */
1438
+ RD_UT_SAY("Verifying MessageSet 5: Unsupported MagicByte errors");
1439
+ for (i = 0; i < 10; i++) {
1440
+ rd_kafka_op_t *rko = rd_kafka_q_pop(response_q, 1000, 0);
1441
+ RD_UT_ASSERT(rko != NULL, "Expected magic error op %d of 10",
1442
+ i);
1443
+ RD_UT_ASSERT(rko->rko_type == RD_KAFKA_OP_CONSUMER_ERR,
1444
+ "Expected CONSUMER_ERR, got %d", rko->rko_type);
1445
+ RD_UT_ASSERT(rko->rko_err == RD_KAFKA_RESP_ERR__NOT_IMPLEMENTED,
1446
+ "Expected NOT_IMPLEMENTED, got %s",
1447
+ rd_kafka_err2str(rko->rko_err));
1448
+ RD_UT_ASSERT(rko->rko_u.err.offset == 40 + i,
1449
+ "Expected offset %d, got %" PRId64, 40 + i,
1450
+ rko->rko_u.err.offset);
1451
+ RD_UT_ASSERT(rko->rko_u.err.rkm.rkm_u.consumer.ack_type ==
1452
+ RD_KAFKA_SHARE_INTERNAL_ACK_REJECT,
1453
+ "Expected REJECT ack_type for unsupported magic");
1454
+ rd_kafka_op_destroy(rko);
1455
+ }
1456
+
1457
+ /* Verify MessageSet 6: 10 successful FETCH ops (offsets 50-59) */
1458
+ RD_UT_SAY("Verifying MessageSet 6: Valid messages after magic error");
1459
+ for (i = 0; i < 10; i++) {
1460
+ rd_kafka_op_t *rko = rd_kafka_q_pop(response_q, 1000, 0);
1461
+ RD_UT_ASSERT(
1462
+ rko != NULL,
1463
+ "Expected FETCH op %d of 10 after magic error, got timeout "
1464
+ "(BUG: parser stopped!)",
1465
+ i);
1466
+ RD_UT_ASSERT(rko->rko_type == RD_KAFKA_OP_FETCH,
1467
+ "Expected FETCH op, got %d", rko->rko_type);
1468
+ RD_UT_ASSERT(rko->rko_u.fetch.rkm.rkm_offset == 50 + i,
1469
+ "Expected offset %d, got %" PRId64, 50 + i,
1470
+ rko->rko_u.fetch.rkm.rkm_offset);
1471
+ rd_kafka_op_destroy(rko);
1472
+ }
1473
+
1474
+ /* Verify no extra ops */
1475
+ {
1476
+ rd_kafka_op_t *rko = rd_kafka_q_pop(response_q, 100, 0);
1477
+ RD_UT_ASSERT(rko == NULL, "Unexpected extra op");
1478
+ }
1479
+
1480
+ RD_UT_SAY(
1481
+ "SUCCESS: All 6 MessageSets processed correctly (60 ops total)");
1482
+
1483
+ rd_kafka_buf_destroy(rkbuf);
1484
+ rd_kafka_q_destroy_owner(response_q);
1485
+ rd_kafka_toppar_destroy(rktp);
1486
+ ut_destroy_share_consumer(rkshare);
1487
+
1488
+ RD_UT_PASS();
1489
+ }
1490
+ #endif /* WITH_ZSTD */
1491
+
1492
+
1493
+ /**
1494
+ * @brief Run all MessageSet error handling unit tests
1495
+ */
1496
+ int rd_kafka_unittest_msgset_errors(void) {
1497
+ int fails = 0;
1498
+
1499
+ /* Individual error type tests */
1500
+ fails += unittest_msgset_crc_error_share_consumer();
1501
+ #if WITH_ZSTD
1502
+ fails += unittest_msgset_decompression_error_share_consumer();
1503
+ #endif
1504
+ fails += unittest_msgset_unsupported_magic_share_consumer();
1505
+
1506
+ /* Mixed scenario tests */
1507
+ fails += unittest_msgset_mixed_success_crc_success();
1508
+ #if WITH_ZSTD
1509
+ fails += unittest_msgset_mixed_crc_success_decomp();
1510
+ #endif
1511
+ fails += unittest_msgset_mixed_magic_success_crc_success();
1512
+ fails += unittest_msgset_all_success();
1513
+ fails += unittest_msgset_all_errors();
1514
+
1515
+ /* Comprehensive test: all error types with valid messages */
1516
+ #if WITH_ZSTD
1517
+ fails += unittest_msgset_all_error_types_with_valid();
1518
+ #endif
1519
+
1520
+ return fails;
1521
+ }