fluentd 0.12.40 → 1.6.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of fluentd might be problematic. Click here for more details.

Files changed (428) hide show
  1. checksums.yaml +5 -5
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +39 -0
  3. data/.github/ISSUE_TEMPLATE/feature_request.md +23 -0
  4. data/.github/ISSUE_TEMPLATE.md +17 -0
  5. data/.github/PULL_REQUEST_TEMPLATE.md +13 -0
  6. data/.gitignore +5 -0
  7. data/.gitlab/cicd-template.yaml +10 -0
  8. data/.gitlab-ci.yml +147 -0
  9. data/.travis.yml +56 -20
  10. data/ADOPTERS.md +5 -0
  11. data/CHANGELOG.md +1369 -0
  12. data/CONTRIBUTING.md +16 -5
  13. data/GOVERNANCE.md +55 -0
  14. data/Gemfile +5 -0
  15. data/GithubWorkflow.md +78 -0
  16. data/LICENSE +202 -0
  17. data/MAINTAINERS.md +7 -0
  18. data/README.md +23 -11
  19. data/Rakefile +48 -2
  20. data/Vagrantfile +17 -0
  21. data/appveyor.yml +37 -0
  22. data/bin/fluent-binlog-reader +7 -0
  23. data/bin/fluent-ca-generate +6 -0
  24. data/bin/fluent-plugin-config-format +5 -0
  25. data/bin/fluent-plugin-generate +5 -0
  26. data/bin/fluentd +3 -0
  27. data/code-of-conduct.md +3 -0
  28. data/example/copy_roundrobin.conf +39 -0
  29. data/example/counter.conf +18 -0
  30. data/example/in_dummy_blocks.conf +17 -0
  31. data/example/in_dummy_with_compression.conf +23 -0
  32. data/example/in_forward.conf +7 -0
  33. data/example/in_forward_client.conf +37 -0
  34. data/example/in_forward_shared_key.conf +15 -0
  35. data/example/in_forward_tls.conf +14 -0
  36. data/example/in_forward_users.conf +24 -0
  37. data/example/in_forward_workers.conf +21 -0
  38. data/example/in_http.conf +3 -1
  39. data/example/in_out_forward.conf +17 -0
  40. data/example/logevents.conf +25 -0
  41. data/example/multi_filters.conf +61 -0
  42. data/example/out_exec_filter.conf +42 -0
  43. data/example/out_forward.conf +13 -13
  44. data/example/out_forward_buf_file.conf +23 -0
  45. data/example/out_forward_client.conf +109 -0
  46. data/example/out_forward_heartbeat_none.conf +16 -0
  47. data/example/out_forward_shared_key.conf +36 -0
  48. data/example/out_forward_tls.conf +18 -0
  49. data/example/out_forward_users.conf +65 -0
  50. data/example/out_null.conf +36 -0
  51. data/example/secondary_file.conf +42 -0
  52. data/example/suppress_config_dump.conf +7 -0
  53. data/example/worker_section.conf +36 -0
  54. data/fluent.conf +29 -0
  55. data/fluentd.gemspec +21 -11
  56. data/lib/fluent/agent.rb +67 -90
  57. data/lib/fluent/clock.rb +62 -0
  58. data/lib/fluent/command/binlog_reader.rb +244 -0
  59. data/lib/fluent/command/ca_generate.rb +181 -0
  60. data/lib/fluent/command/cat.rb +42 -18
  61. data/lib/fluent/command/debug.rb +12 -10
  62. data/lib/fluent/command/fluentd.rb +153 -5
  63. data/lib/fluent/command/plugin_config_formatter.rb +292 -0
  64. data/lib/fluent/command/plugin_generator.rb +324 -0
  65. data/lib/fluent/compat/call_super_mixin.rb +67 -0
  66. data/lib/fluent/compat/detach_process_mixin.rb +33 -0
  67. data/lib/fluent/compat/exec_util.rb +129 -0
  68. data/lib/fluent/compat/file_util.rb +54 -0
  69. data/lib/fluent/compat/filter.rb +68 -0
  70. data/lib/fluent/compat/formatter.rb +111 -0
  71. data/lib/fluent/compat/formatter_utils.rb +85 -0
  72. data/lib/fluent/compat/handle_tag_and_time_mixin.rb +62 -0
  73. data/lib/fluent/compat/handle_tag_name_mixin.rb +53 -0
  74. data/lib/fluent/compat/input.rb +49 -0
  75. data/lib/fluent/compat/output.rb +718 -0
  76. data/lib/fluent/compat/output_chain.rb +60 -0
  77. data/lib/fluent/compat/parser.rb +310 -0
  78. data/lib/fluent/compat/parser_utils.rb +40 -0
  79. data/lib/fluent/compat/propagate_default.rb +62 -0
  80. data/lib/fluent/compat/record_filter_mixin.rb +34 -0
  81. data/lib/fluent/compat/set_tag_key_mixin.rb +50 -0
  82. data/lib/fluent/compat/set_time_key_mixin.rb +69 -0
  83. data/lib/fluent/compat/socket_util.rb +165 -0
  84. data/lib/fluent/compat/string_util.rb +34 -0
  85. data/lib/fluent/compat/structured_format_mixin.rb +26 -0
  86. data/lib/fluent/compat/type_converter.rb +90 -0
  87. data/lib/fluent/config/configure_proxy.rb +210 -62
  88. data/lib/fluent/config/dsl.rb +12 -5
  89. data/lib/fluent/config/element.rb +107 -9
  90. data/lib/fluent/config/literal_parser.rb +9 -3
  91. data/lib/fluent/config/parser.rb +4 -4
  92. data/lib/fluent/config/section.rb +51 -14
  93. data/lib/fluent/config/types.rb +28 -13
  94. data/lib/fluent/config/v1_parser.rb +3 -5
  95. data/lib/fluent/config.rb +23 -20
  96. data/lib/fluent/configurable.rb +79 -21
  97. data/lib/fluent/counter/base_socket.rb +46 -0
  98. data/lib/fluent/counter/client.rb +297 -0
  99. data/lib/fluent/counter/error.rb +86 -0
  100. data/lib/fluent/counter/mutex_hash.rb +163 -0
  101. data/lib/fluent/counter/server.rb +273 -0
  102. data/lib/fluent/counter/store.rb +205 -0
  103. data/lib/fluent/counter/validator.rb +145 -0
  104. data/lib/fluent/counter.rb +23 -0
  105. data/lib/fluent/daemon.rb +15 -0
  106. data/lib/fluent/engine.rb +102 -65
  107. data/lib/fluent/env.rb +7 -3
  108. data/lib/fluent/error.rb +30 -0
  109. data/lib/fluent/event.rb +197 -21
  110. data/lib/fluent/event_router.rb +93 -10
  111. data/lib/fluent/filter.rb +2 -50
  112. data/lib/fluent/formatter.rb +4 -293
  113. data/lib/fluent/input.rb +2 -32
  114. data/lib/fluent/label.rb +10 -2
  115. data/lib/fluent/load.rb +3 -3
  116. data/lib/fluent/log.rb +348 -81
  117. data/lib/fluent/match.rb +37 -36
  118. data/lib/fluent/mixin.rb +12 -176
  119. data/lib/fluent/msgpack_factory.rb +62 -0
  120. data/lib/fluent/output.rb +10 -612
  121. data/lib/fluent/output_chain.rb +23 -0
  122. data/lib/fluent/parser.rb +4 -800
  123. data/lib/fluent/plugin/bare_output.rb +63 -0
  124. data/lib/fluent/plugin/base.rb +192 -0
  125. data/lib/fluent/plugin/buf_file.rb +128 -174
  126. data/lib/fluent/plugin/buf_memory.rb +9 -92
  127. data/lib/fluent/plugin/buffer/chunk.rb +221 -0
  128. data/lib/fluent/plugin/buffer/file_chunk.rb +383 -0
  129. data/lib/fluent/plugin/buffer/memory_chunk.rb +90 -0
  130. data/lib/fluent/plugin/buffer.rb +779 -0
  131. data/lib/fluent/plugin/compressable.rb +92 -0
  132. data/lib/fluent/plugin/exec_util.rb +3 -108
  133. data/lib/fluent/plugin/file_util.rb +4 -34
  134. data/lib/fluent/plugin/file_wrapper.rb +120 -0
  135. data/lib/fluent/plugin/filter.rb +93 -0
  136. data/lib/fluent/plugin/filter_grep.rb +117 -34
  137. data/lib/fluent/plugin/filter_parser.rb +85 -62
  138. data/lib/fluent/plugin/filter_record_transformer.rb +27 -39
  139. data/lib/fluent/plugin/filter_stdout.rb +15 -12
  140. data/lib/fluent/plugin/formatter.rb +50 -0
  141. data/lib/fluent/plugin/formatter_csv.rb +52 -0
  142. data/lib/fluent/plugin/formatter_hash.rb +33 -0
  143. data/lib/fluent/plugin/formatter_json.rb +55 -0
  144. data/lib/fluent/plugin/formatter_ltsv.rb +42 -0
  145. data/lib/fluent/plugin/formatter_msgpack.rb +33 -0
  146. data/lib/fluent/plugin/formatter_out_file.rb +51 -0
  147. data/lib/fluent/plugin/formatter_single_value.rb +34 -0
  148. data/lib/fluent/plugin/formatter_stdout.rb +76 -0
  149. data/lib/fluent/plugin/formatter_tsv.rb +38 -0
  150. data/lib/fluent/plugin/in_debug_agent.rb +17 -6
  151. data/lib/fluent/plugin/in_dummy.rb +47 -20
  152. data/lib/fluent/plugin/in_exec.rb +55 -123
  153. data/lib/fluent/plugin/in_forward.rb +299 -216
  154. data/lib/fluent/plugin/in_gc_stat.rb +14 -36
  155. data/lib/fluent/plugin/in_http.rb +204 -91
  156. data/lib/fluent/plugin/in_monitor_agent.rb +186 -258
  157. data/lib/fluent/plugin/in_object_space.rb +13 -41
  158. data/lib/fluent/plugin/in_syslog.rb +112 -134
  159. data/lib/fluent/plugin/in_tail.rb +408 -745
  160. data/lib/fluent/plugin/in_tcp.rb +66 -9
  161. data/lib/fluent/plugin/in_udp.rb +60 -11
  162. data/lib/fluent/plugin/{in_stream.rb → in_unix.rb} +8 -4
  163. data/lib/fluent/plugin/input.rb +37 -0
  164. data/lib/fluent/plugin/multi_output.rb +158 -0
  165. data/lib/fluent/plugin/out_copy.rb +23 -35
  166. data/lib/fluent/plugin/out_exec.rb +67 -70
  167. data/lib/fluent/plugin/out_exec_filter.rb +204 -271
  168. data/lib/fluent/plugin/out_file.rb +267 -73
  169. data/lib/fluent/plugin/out_forward.rb +854 -325
  170. data/lib/fluent/plugin/out_null.rb +42 -9
  171. data/lib/fluent/plugin/out_relabel.rb +9 -5
  172. data/lib/fluent/plugin/out_roundrobin.rb +18 -37
  173. data/lib/fluent/plugin/out_secondary_file.rb +133 -0
  174. data/lib/fluent/plugin/out_stdout.rb +43 -10
  175. data/lib/fluent/plugin/out_stream.rb +7 -2
  176. data/lib/fluent/plugin/output.rb +1498 -0
  177. data/lib/fluent/plugin/owned_by_mixin.rb +42 -0
  178. data/lib/fluent/plugin/parser.rb +191 -0
  179. data/lib/fluent/plugin/parser_apache.rb +28 -0
  180. data/lib/fluent/plugin/parser_apache2.rb +88 -0
  181. data/lib/fluent/plugin/parser_apache_error.rb +26 -0
  182. data/lib/fluent/plugin/parser_csv.rb +39 -0
  183. data/lib/fluent/plugin/parser_json.rb +94 -0
  184. data/lib/fluent/plugin/parser_ltsv.rb +49 -0
  185. data/lib/fluent/plugin/parser_msgpack.rb +50 -0
  186. data/lib/fluent/plugin/parser_multiline.rb +106 -0
  187. data/lib/fluent/plugin/parser_nginx.rb +28 -0
  188. data/lib/fluent/plugin/parser_none.rb +36 -0
  189. data/lib/fluent/plugin/parser_regexp.rb +68 -0
  190. data/lib/fluent/plugin/parser_syslog.rb +142 -0
  191. data/lib/fluent/plugin/parser_tsv.rb +42 -0
  192. data/lib/fluent/plugin/socket_util.rb +3 -143
  193. data/lib/fluent/plugin/storage.rb +84 -0
  194. data/lib/fluent/plugin/storage_local.rb +164 -0
  195. data/lib/fluent/plugin/string_util.rb +3 -15
  196. data/lib/fluent/plugin.rb +122 -121
  197. data/lib/fluent/plugin_helper/cert_option.rb +178 -0
  198. data/lib/fluent/plugin_helper/child_process.rb +364 -0
  199. data/lib/fluent/plugin_helper/compat_parameters.rb +333 -0
  200. data/lib/fluent/plugin_helper/counter.rb +51 -0
  201. data/lib/fluent/plugin_helper/event_emitter.rb +93 -0
  202. data/lib/fluent/plugin_helper/event_loop.rb +170 -0
  203. data/lib/fluent/plugin_helper/extract.rb +104 -0
  204. data/lib/fluent/plugin_helper/formatter.rb +147 -0
  205. data/lib/fluent/plugin_helper/http_server/app.rb +79 -0
  206. data/lib/fluent/plugin_helper/http_server/compat/server.rb +81 -0
  207. data/lib/fluent/plugin_helper/http_server/compat/webrick_handler.rb +58 -0
  208. data/lib/fluent/plugin_helper/http_server/methods.rb +35 -0
  209. data/lib/fluent/plugin_helper/http_server/request.rb +42 -0
  210. data/lib/fluent/plugin_helper/http_server/router.rb +54 -0
  211. data/lib/fluent/plugin_helper/http_server/server.rb +87 -0
  212. data/lib/fluent/plugin_helper/http_server.rb +76 -0
  213. data/lib/fluent/plugin_helper/inject.rb +151 -0
  214. data/lib/fluent/plugin_helper/parser.rb +147 -0
  215. data/lib/fluent/plugin_helper/record_accessor.rb +210 -0
  216. data/lib/fluent/plugin_helper/retry_state.rb +205 -0
  217. data/lib/fluent/plugin_helper/server.rb +807 -0
  218. data/lib/fluent/plugin_helper/socket.rb +250 -0
  219. data/lib/fluent/plugin_helper/socket_option.rb +80 -0
  220. data/lib/fluent/plugin_helper/storage.rb +349 -0
  221. data/lib/fluent/plugin_helper/thread.rb +179 -0
  222. data/lib/fluent/plugin_helper/timer.rb +92 -0
  223. data/lib/fluent/plugin_helper.rb +73 -0
  224. data/lib/fluent/plugin_id.rb +80 -0
  225. data/lib/fluent/process.rb +3 -489
  226. data/lib/fluent/registry.rb +52 -10
  227. data/lib/fluent/root_agent.rb +204 -42
  228. data/lib/fluent/supervisor.rb +597 -359
  229. data/lib/fluent/system_config.rb +131 -42
  230. data/lib/fluent/test/base.rb +6 -54
  231. data/lib/fluent/test/driver/base.rb +224 -0
  232. data/lib/fluent/test/driver/base_owned.rb +70 -0
  233. data/lib/fluent/test/driver/base_owner.rb +135 -0
  234. data/lib/fluent/test/driver/event_feeder.rb +98 -0
  235. data/lib/fluent/test/driver/filter.rb +57 -0
  236. data/lib/fluent/test/driver/formatter.rb +30 -0
  237. data/lib/fluent/test/driver/input.rb +31 -0
  238. data/lib/fluent/test/driver/multi_output.rb +53 -0
  239. data/lib/fluent/test/driver/output.rb +102 -0
  240. data/lib/fluent/test/driver/parser.rb +30 -0
  241. data/lib/fluent/test/driver/test_event_router.rb +45 -0
  242. data/lib/fluent/test/filter_test.rb +0 -1
  243. data/lib/fluent/test/formatter_test.rb +4 -1
  244. data/lib/fluent/test/helpers.rb +58 -10
  245. data/lib/fluent/test/input_test.rb +27 -19
  246. data/lib/fluent/test/log.rb +79 -0
  247. data/lib/fluent/test/output_test.rb +28 -39
  248. data/lib/fluent/test/parser_test.rb +3 -1
  249. data/lib/fluent/test/startup_shutdown.rb +46 -0
  250. data/lib/fluent/test.rb +33 -1
  251. data/lib/fluent/time.rb +450 -1
  252. data/lib/fluent/timezone.rb +27 -3
  253. data/lib/fluent/{status.rb → unique_id.rb} +15 -24
  254. data/lib/fluent/version.rb +1 -1
  255. data/lib/fluent/winsvc.rb +85 -0
  256. data/templates/new_gem/Gemfile +3 -0
  257. data/templates/new_gem/README.md.erb +43 -0
  258. data/templates/new_gem/Rakefile +13 -0
  259. data/templates/new_gem/fluent-plugin.gemspec.erb +27 -0
  260. data/templates/new_gem/lib/fluent/plugin/filter.rb.erb +14 -0
  261. data/templates/new_gem/lib/fluent/plugin/formatter.rb.erb +14 -0
  262. data/templates/new_gem/lib/fluent/plugin/input.rb.erb +11 -0
  263. data/templates/new_gem/lib/fluent/plugin/output.rb.erb +11 -0
  264. data/templates/new_gem/lib/fluent/plugin/parser.rb.erb +15 -0
  265. data/templates/new_gem/test/helper.rb.erb +8 -0
  266. data/templates/new_gem/test/plugin/test_filter.rb.erb +18 -0
  267. data/templates/new_gem/test/plugin/test_formatter.rb.erb +18 -0
  268. data/templates/new_gem/test/plugin/test_input.rb.erb +18 -0
  269. data/templates/new_gem/test/plugin/test_output.rb.erb +18 -0
  270. data/templates/new_gem/test/plugin/test_parser.rb.erb +18 -0
  271. data/templates/plugin_config_formatter/param.md-compact.erb +25 -0
  272. data/templates/plugin_config_formatter/param.md.erb +34 -0
  273. data/templates/plugin_config_formatter/section.md.erb +12 -0
  274. data/test/command/test_binlog_reader.rb +346 -0
  275. data/test/command/test_ca_generate.rb +70 -0
  276. data/test/command/test_fluentd.rb +901 -0
  277. data/test/command/test_plugin_config_formatter.rb +276 -0
  278. data/test/command/test_plugin_generator.rb +92 -0
  279. data/test/compat/test_calls_super.rb +166 -0
  280. data/test/compat/test_parser.rb +92 -0
  281. data/test/config/test_config_parser.rb +126 -2
  282. data/test/config/test_configurable.rb +946 -187
  283. data/test/config/test_configure_proxy.rb +424 -74
  284. data/test/config/test_dsl.rb +11 -11
  285. data/test/config/test_element.rb +500 -0
  286. data/test/config/test_literal_parser.rb +8 -0
  287. data/test/config/test_plugin_configuration.rb +56 -0
  288. data/test/config/test_section.rb +79 -7
  289. data/test/config/test_system_config.rb +122 -35
  290. data/test/config/test_types.rb +38 -0
  291. data/test/counter/test_client.rb +559 -0
  292. data/test/counter/test_error.rb +44 -0
  293. data/test/counter/test_mutex_hash.rb +179 -0
  294. data/test/counter/test_server.rb +589 -0
  295. data/test/counter/test_store.rb +258 -0
  296. data/test/counter/test_validator.rb +137 -0
  297. data/test/helper.rb +89 -6
  298. data/test/helpers/fuzzy_assert.rb +89 -0
  299. data/test/plugin/test_bare_output.rb +118 -0
  300. data/test/plugin/test_base.rb +115 -0
  301. data/test/plugin/test_buf_file.rb +823 -460
  302. data/test/plugin/test_buf_memory.rb +32 -194
  303. data/test/plugin/test_buffer.rb +1233 -0
  304. data/test/plugin/test_buffer_chunk.rb +198 -0
  305. data/test/plugin/test_buffer_file_chunk.rb +844 -0
  306. data/test/plugin/test_buffer_memory_chunk.rb +338 -0
  307. data/test/plugin/test_compressable.rb +84 -0
  308. data/test/plugin/test_filter.rb +357 -0
  309. data/test/plugin/test_filter_grep.rb +540 -29
  310. data/test/plugin/test_filter_parser.rb +439 -452
  311. data/test/plugin/test_filter_record_transformer.rb +123 -166
  312. data/test/plugin/test_filter_stdout.rb +160 -72
  313. data/test/plugin/test_formatter_csv.rb +111 -0
  314. data/test/plugin/test_formatter_hash.rb +35 -0
  315. data/test/plugin/test_formatter_json.rb +51 -0
  316. data/test/plugin/test_formatter_ltsv.rb +62 -0
  317. data/test/plugin/test_formatter_msgpack.rb +28 -0
  318. data/test/plugin/test_formatter_out_file.rb +95 -0
  319. data/test/plugin/test_formatter_single_value.rb +38 -0
  320. data/test/plugin/test_formatter_tsv.rb +68 -0
  321. data/test/plugin/test_in_debug_agent.rb +24 -1
  322. data/test/plugin/test_in_dummy.rb +111 -18
  323. data/test/plugin/test_in_exec.rb +200 -113
  324. data/test/plugin/test_in_forward.rb +990 -387
  325. data/test/plugin/test_in_gc_stat.rb +10 -8
  326. data/test/plugin/test_in_http.rb +600 -224
  327. data/test/plugin/test_in_monitor_agent.rb +690 -0
  328. data/test/plugin/test_in_object_space.rb +24 -8
  329. data/test/plugin/test_in_syslog.rb +154 -215
  330. data/test/plugin/test_in_tail.rb +1006 -707
  331. data/test/plugin/test_in_tcp.rb +125 -48
  332. data/test/plugin/test_in_udp.rb +204 -63
  333. data/test/plugin/{test_in_stream.rb → test_in_unix.rb} +14 -13
  334. data/test/plugin/test_input.rb +126 -0
  335. data/test/plugin/test_metadata.rb +89 -0
  336. data/test/plugin/test_multi_output.rb +180 -0
  337. data/test/plugin/test_out_copy.rb +117 -112
  338. data/test/plugin/test_out_exec.rb +258 -53
  339. data/test/plugin/test_out_exec_filter.rb +538 -115
  340. data/test/plugin/test_out_file.rb +865 -178
  341. data/test/plugin/test_out_forward.rb +998 -210
  342. data/test/plugin/test_out_null.rb +105 -0
  343. data/test/plugin/test_out_relabel.rb +28 -0
  344. data/test/plugin/test_out_roundrobin.rb +36 -29
  345. data/test/plugin/test_out_secondary_file.rb +458 -0
  346. data/test/plugin/test_out_stdout.rb +135 -37
  347. data/test/plugin/test_out_stream.rb +18 -0
  348. data/test/plugin/test_output.rb +984 -0
  349. data/test/plugin/test_output_as_buffered.rb +2021 -0
  350. data/test/plugin/test_output_as_buffered_backup.rb +312 -0
  351. data/test/plugin/test_output_as_buffered_compress.rb +165 -0
  352. data/test/plugin/test_output_as_buffered_overflow.rb +250 -0
  353. data/test/plugin/test_output_as_buffered_retries.rb +911 -0
  354. data/test/plugin/test_output_as_buffered_secondary.rb +874 -0
  355. data/test/plugin/test_output_as_standard.rb +374 -0
  356. data/test/plugin/test_owned_by.rb +35 -0
  357. data/test/plugin/test_parser.rb +359 -0
  358. data/test/plugin/test_parser_apache.rb +42 -0
  359. data/test/plugin/test_parser_apache2.rb +47 -0
  360. data/test/plugin/test_parser_apache_error.rb +45 -0
  361. data/test/plugin/test_parser_csv.rb +103 -0
  362. data/test/plugin/test_parser_json.rb +138 -0
  363. data/test/plugin/test_parser_labeled_tsv.rb +145 -0
  364. data/test/plugin/test_parser_multiline.rb +100 -0
  365. data/test/plugin/test_parser_nginx.rb +88 -0
  366. data/test/plugin/test_parser_none.rb +52 -0
  367. data/test/plugin/test_parser_regexp.rb +289 -0
  368. data/test/plugin/test_parser_syslog.rb +441 -0
  369. data/test/plugin/test_parser_tsv.rb +122 -0
  370. data/test/plugin/test_storage.rb +167 -0
  371. data/test/plugin/test_storage_local.rb +335 -0
  372. data/test/plugin_helper/data/cert/cert-key.pem +27 -0
  373. data/test/plugin_helper/data/cert/cert-with-no-newline.pem +19 -0
  374. data/test/plugin_helper/data/cert/cert.pem +19 -0
  375. data/test/plugin_helper/http_server/test_app.rb +65 -0
  376. data/test/plugin_helper/http_server/test_route.rb +32 -0
  377. data/test/plugin_helper/test_cert_option.rb +16 -0
  378. data/test/plugin_helper/test_child_process.rb +794 -0
  379. data/test/plugin_helper/test_compat_parameters.rb +353 -0
  380. data/test/plugin_helper/test_event_emitter.rb +51 -0
  381. data/test/plugin_helper/test_event_loop.rb +52 -0
  382. data/test/plugin_helper/test_extract.rb +194 -0
  383. data/test/plugin_helper/test_formatter.rb +255 -0
  384. data/test/plugin_helper/test_http_server_helper.rb +205 -0
  385. data/test/plugin_helper/test_inject.rb +519 -0
  386. data/test/plugin_helper/test_parser.rb +264 -0
  387. data/test/plugin_helper/test_record_accessor.rb +197 -0
  388. data/test/plugin_helper/test_retry_state.rb +442 -0
  389. data/test/plugin_helper/test_server.rb +1714 -0
  390. data/test/plugin_helper/test_storage.rb +542 -0
  391. data/test/plugin_helper/test_thread.rb +164 -0
  392. data/test/plugin_helper/test_timer.rb +132 -0
  393. data/test/scripts/exec_script.rb +0 -6
  394. data/test/scripts/fluent/plugin/formatter1/formatter_test1.rb +7 -0
  395. data/test/scripts/fluent/plugin/formatter2/formatter_test2.rb +7 -0
  396. data/test/scripts/fluent/plugin/out_test.rb +23 -15
  397. data/test/scripts/fluent/plugin/out_test2.rb +80 -0
  398. data/test/test_clock.rb +164 -0
  399. data/test/test_config.rb +16 -7
  400. data/test/test_configdsl.rb +2 -2
  401. data/test/test_event.rb +360 -13
  402. data/test/test_event_router.rb +108 -11
  403. data/test/test_event_time.rb +199 -0
  404. data/test/test_filter.rb +48 -6
  405. data/test/test_formatter.rb +11 -391
  406. data/test/test_input.rb +1 -1
  407. data/test/test_log.rb +591 -31
  408. data/test/test_mixin.rb +1 -1
  409. data/test/test_output.rb +121 -185
  410. data/test/test_plugin.rb +251 -0
  411. data/test/test_plugin_classes.rb +177 -10
  412. data/test/test_plugin_helper.rb +81 -0
  413. data/test/test_plugin_id.rb +101 -0
  414. data/test/test_process.rb +8 -42
  415. data/test/test_root_agent.rb +766 -21
  416. data/test/test_supervisor.rb +481 -0
  417. data/test/test_test_drivers.rb +135 -0
  418. data/test/test_time_formatter.rb +282 -0
  419. data/test/test_time_parser.rb +231 -0
  420. data/test/test_unique_id.rb +47 -0
  421. metadata +454 -60
  422. data/COPYING +0 -14
  423. data/ChangeLog +0 -666
  424. data/lib/fluent/buffer.rb +0 -365
  425. data/lib/fluent/plugin/in_status.rb +0 -76
  426. data/test/plugin/test_in_status.rb +0 -38
  427. data/test/test_buffer.rb +0 -624
  428. data/test/test_parser.rb +0 -1305
@@ -1,523 +1,1133 @@
1
1
  require_relative '../helper'
2
2
 
3
- require 'fluent/test'
3
+ require 'fluent/test/driver/input'
4
+ require 'fluent/test/startup_shutdown'
4
5
  require 'base64'
5
6
 
6
7
  require 'fluent/env'
8
+ require 'fluent/event'
7
9
  require 'fluent/plugin/in_forward'
10
+ require 'fluent/plugin/compressable'
11
+
12
+ require 'timecop'
8
13
 
9
14
  class ForwardInputTest < Test::Unit::TestCase
15
+ include Fluent::Plugin::Compressable
16
+
10
17
  def setup
11
18
  Fluent::Test.setup
12
19
  @responses = [] # for testing responses after sending data
20
+ @d = nil
21
+ end
22
+
23
+ def teardown
24
+ @d.instance_shutdown if @d
13
25
  end
14
26
 
15
27
  PORT = unused_port
28
+
29
+ SHARED_KEY = 'foobar1'
30
+ USER_NAME = 'tagomoris'
31
+ USER_PASSWORD = 'fluentd'
32
+
16
33
  CONFIG = %[
17
34
  port #{PORT}
18
35
  bind 127.0.0.1
19
36
  ]
20
- PEERADDR = ['?', '0000', '127.0.0.1', '127.0.0.1']
37
+ LOCALHOST_HOSTNAME_GETTER = ->(){sock = UDPSocket.new(::Socket::AF_INET); sock.do_not_reverse_lookup = false; sock.connect("127.0.0.1", 2048); sock.peeraddr[2] }
38
+ LOCALHOST_HOSTNAME = LOCALHOST_HOSTNAME_GETTER.call
39
+ DUMMY_SOCK = Struct.new(:remote_host, :remote_addr, :remote_port).new(LOCALHOST_HOSTNAME, "127.0.0.1", 0)
40
+ CONFIG_AUTH = %[
41
+ port #{PORT}
42
+ bind 127.0.0.1
43
+ <security>
44
+ self_hostname localhost
45
+ shared_key foobar1
46
+ user_auth true
47
+ <user>
48
+ username #{USER_NAME}
49
+ password #{USER_PASSWORD}
50
+ </user>
51
+ <client>
52
+ network 127.0.0.0/8
53
+ shared_key #{SHARED_KEY}
54
+ users ["#{USER_NAME}"]
55
+ </client>
56
+ </security>
57
+ ]
21
58
 
22
59
  def create_driver(conf=CONFIG)
23
- Fluent::Test::InputTestDriver.new(Fluent::ForwardInput).configure(conf)
60
+ Fluent::Test::Driver::Input.new(Fluent::Plugin::ForwardInput).configure(conf)
24
61
  end
25
62
 
26
- def test_configure
27
- d = create_driver
28
- assert_equal PORT, d.instance.port
29
- assert_equal '127.0.0.1', d.instance.bind
30
- assert_equal 0, d.instance.linger_timeout
31
- assert_equal 0.5, d.instance.blocking_timeout
32
- assert !d.instance.backlog
33
- end
63
+ sub_test_case '#configure' do
64
+ test 'simple' do
65
+ @d = d = create_driver
66
+ assert_equal PORT, d.instance.port
67
+ assert_equal '127.0.0.1', d.instance.bind
68
+ assert_equal 0, d.instance.linger_timeout
69
+ assert_equal 0.5, d.instance.blocking_timeout
70
+ assert !d.instance.backlog
71
+ end
34
72
 
35
- # TODO: Will add Loop::run arity check with stub/mock library
73
+ test 'auth' do
74
+ @d = d = create_driver(CONFIG_AUTH)
75
+ assert_equal PORT, d.instance.port
76
+ assert_equal '127.0.0.1', d.instance.bind
77
+ assert_equal 0, d.instance.linger_timeout
78
+ assert !d.instance.backlog
36
79
 
37
- def connect
38
- TCPSocket.new('127.0.0.1', PORT)
39
- end
80
+ assert d.instance.security
81
+ assert_equal 1, d.instance.security.users.size
82
+ assert_equal 1, d.instance.security.clients.size
83
+ end
40
84
 
41
- def test_time
42
- d = create_driver
85
+ data(tag: "tag",
86
+ add_tag_prefix: "add_tag_prefix")
87
+ test 'tag parameters' do |data|
88
+ assert_raise(Fluent::ConfigError.new("'#{data}' parameter must not be empty")) {
89
+ create_driver(CONFIG + "#{data} ''")
90
+ }
91
+ end
43
92
 
44
- time = Time.parse("2011-01-02 13:14:15 UTC").to_i
45
- Fluent::Engine.now = time
93
+ test 'send_keepalive_packet is disabled by default' do
94
+ @d = d = create_driver(CONFIG_AUTH)
95
+ assert_false d.instance.send_keepalive_packet
96
+ end
46
97
 
47
- d.expect_emit "tag1", time, {"a"=>1}
48
- d.expect_emit "tag2", time, {"a"=>2}
98
+ test 'send_keepalive_packet can be enabled' do
99
+ @d = d = create_driver(CONFIG_AUTH + %[
100
+ send_keepalive_packet true
101
+ ])
102
+ assert_true d.instance.send_keepalive_packet
103
+ end
49
104
 
50
- d.run do
51
- d.expected_emits.each {|tag,time,record|
52
- send_data [tag, 0, record].to_msgpack
53
- }
105
+ test 'both send_keepalive_packet and deny_keepalive cannot be enabled' do
106
+ assert_raise(Fluent::ConfigError.new("both 'send_keepalive_packet' and 'deny_keepalive' cannot be set to true")) do
107
+ create_driver(CONFIG_AUTH + %[
108
+ send_keepalive_packet true
109
+ deny_keepalive true
110
+ ])
111
+ end
54
112
  end
55
113
  end
56
114
 
57
- def test_message
58
- d = create_driver
115
+ sub_test_case 'message' do
116
+ test 'time' do
117
+ time = event_time("2011-01-02 13:14:15 UTC")
118
+ begin
119
+ Timecop.freeze(Time.at(time))
120
+ @d = d = create_driver
121
+
122
+ records = [
123
+ ["tag1", time, {"a"=>1}],
124
+ ["tag2", time, {"a"=>2}],
125
+ ]
126
+
127
+ d.run(expect_records: records.length, timeout: 5) do
128
+ records.each {|tag, _time, record|
129
+ send_data packer.write([tag, 0, record]).to_s
130
+ }
131
+ end
132
+ assert_equal(records, d.events.sort_by {|a| a[0] })
133
+ ensure
134
+ Timecop.return
135
+ end
136
+ end
59
137
 
60
- time = Time.parse("2011-01-02 13:14:15 UTC").to_i
138
+ test 'plain' do
139
+ @d = d = create_driver
61
140
 
62
- d.expect_emit "tag1", time, {"a"=>1}
63
- d.expect_emit "tag2", time, {"a"=>2}
141
+ time = event_time("2011-01-02 13:14:15 UTC")
64
142
 
65
- d.run do
66
- d.expected_emits.each {|tag,time,record|
67
- send_data Fluent::Engine.msgpack_factory.packer.write([tag, time, record]).to_s
68
- }
143
+ records = [
144
+ ["tag1", time, {"a"=>1}],
145
+ ["tag2", time, {"a"=>2}],
146
+ ]
147
+
148
+ d.run(expect_records: records.length, timeout: 5) do
149
+ records.each {|tag, _time, record|
150
+ send_data packer.write([tag, _time, record]).to_s
151
+ }
152
+ end
153
+ assert_equal(records, d.events)
69
154
  end
70
- end
71
155
 
72
- def test_message_with_skip_invalid_event
73
- d = create_driver(CONFIG + "skip_invalid_event true")
156
+ test 'time_as_integer' do
157
+ @d = d = create_driver
74
158
 
75
- time = Time.parse("2011-01-02 13:14:15 UTC").to_i
159
+ time_i = event_time("2011-01-02 13:14:15 UTC").to_i
76
160
 
77
- d.expect_emit "tag1", time, {"a" => 1}
78
- d.expect_emit "tag2", time, {"a" => 2}
161
+ records = [
162
+ ["tag1", time_i, {"a"=>1}],
163
+ ["tag2", time_i, {"a"=>2}],
164
+ ]
79
165
 
80
- d.run do
81
- entries = d.expected_emits.map { |tag, time, record| [tag, time, record] }
82
- # These entries are skipped
83
- entries << ['tag1', true, {'a' => 3}] << ['tag2', time, 'invalid record']
166
+ d.run(expect_records: records.length, timeout: 5) do
167
+ records.each {|tag, _time, record|
168
+ send_data packer.write([tag, _time, record]).to_s
169
+ }
170
+ end
84
171
 
85
- entries.each { |tag, time, record|
86
- # Without ack, logs are sometimes not saved to logs during test.
87
- send_data Fluent::Engine.msgpack_factory.packer.write([tag, time, record]).to_s, true
88
- }
172
+ assert_equal(records, d.events)
89
173
  end
90
174
 
91
- assert_equal 2, d.instance.log.logs.count { |line| line =~ /got invalid event and drop it/ }
92
- end
175
+ test 'skip_invalid_event' do
176
+ @d = d = create_driver(CONFIG + "skip_invalid_event true")
93
177
 
94
- def test_forward
95
- d = create_driver
178
+ time = event_time("2011-01-02 13:14:15 UTC")
96
179
 
97
- time = Time.parse("2011-01-02 13:14:15 UTC").to_i
180
+ records = [
181
+ ["tag1", time, {"a" => 1}],
182
+ ["tag2", time, {"a" => 2}],
183
+ ]
98
184
 
99
- d.expect_emit "tag1", time, {"a"=>1}
100
- d.expect_emit "tag1", time, {"a"=>2}
185
+ d.run(shutdown: false, expect_records: 2, timeout: 10) do
186
+ entries = []
187
+ # These entries are skipped
188
+ entries << ['tag1', true, {'a' => 3}] << ['tag2', time, 'invalid record']
189
+ entries += records.map { |tag, _time, record| [tag, _time, record] }
101
190
 
102
- d.run do
103
- entries = []
104
- d.expected_emits.each {|tag,time,record|
105
- entries << [time, record]
106
- }
107
- send_data Fluent::Engine.msgpack_factory.packer.write(["tag1", entries]).to_s
191
+ entries.each {|tag, _time, record|
192
+ # Without ack, logs are sometimes not saved to logs during test.
193
+ send_data packer.write([tag, _time, record]).to_s #, try_to_receive_response: true
194
+ }
195
+ end
196
+
197
+ logs = d.instance.log.logs
198
+ assert_equal 2, logs.count { |line| line =~ /got invalid event and drop it/ }
199
+ assert_equal records[0], d.events[0]
200
+ assert_equal records[1], d.events[1]
201
+
202
+ d.instance_shutdown
108
203
  end
109
- end
110
204
 
111
- def test_forward_with_skip_invalid_event
112
- d = create_driver(CONFIG + "skip_invalid_event true")
205
+ test 'json_using_integer_time' do
206
+ @d = d = create_driver
113
207
 
114
- time = Time.parse("2011-01-02 13:14:15 UTC").to_i
208
+ time_i = event_time("2011-01-02 13:14:15 UTC").to_i
115
209
 
116
- d.expect_emit "tag1", time, {"a" => 1}
117
- d.expect_emit "tag1", time, {"a" => 2}
210
+ records = [
211
+ ["tag1", time_i, {"a"=>1}],
212
+ ["tag2", time_i, {"a"=>2}],
213
+ ]
118
214
 
119
- d.run do
120
- entries = d.expected_emits.map { |tag, time, record| [time, record] }
121
- # These entries are skipped
122
- entries << ['invalid time', {'a' => 3}] << [time, 'invalid record']
215
+ d.run(expect_records: records.length, timeout: 20) do
216
+ records.each {|tag, _time, record|
217
+ send_data [tag, _time, record].to_json
218
+ }
219
+ end
123
220
 
124
- send_data Fluent::Engine.msgpack_factory.packer.write(["tag1", entries]).to_s
221
+ assert_equal(records, d.events.sort_by {|a| a[1] })
125
222
  end
126
223
 
127
- assert_equal 2, d.instance.log.logs.count { |line| line =~ /skip invalid event/ }
128
- end
224
+ test 'json_with_newline' do
225
+ @d = d = create_driver
129
226
 
130
- def test_packed_forward
131
- d = create_driver
227
+ time_i = event_time("2011-01-02 13:14:15 UTC").to_i
132
228
 
133
- time = Time.parse("2011-01-02 13:14:15 UTC").to_i
229
+ records = [
230
+ ["tag1", time_i, {"a"=>1}],
231
+ ["tag2", time_i, {"a"=>2}],
232
+ ]
134
233
 
135
- d.expect_emit "tag1", time, {"a"=>1}
136
- d.expect_emit "tag1", time, {"a"=>2}
234
+ d.run(expect_records: records.length, timeout: 20) do
235
+ records.each {|tag, _time, record|
236
+ send_data [tag, _time, record].to_json + "\n"
237
+ sleep 1
238
+ }
239
+ end
137
240
 
138
- d.run do
139
- entries = ''
140
- d.expected_emits.each {|tag,time,record|
141
- Fluent::Engine.msgpack_factory.packer(entries).write([time, record]).flush
142
- }
143
- send_data Fluent::Engine.msgpack_factory.packer.write(["tag1", entries]).to_s
241
+ assert_equal(records, d.events.sort_by {|a| a[1] })
144
242
  end
145
243
  end
146
244
 
147
- def test_packed_forward_with_skip_invalid_event
148
- d = create_driver(CONFIG + "skip_invalid_event true")
245
+ sub_test_case 'forward' do
246
+ data(tcp: {
247
+ config: CONFIG,
248
+ options: {
249
+ auth: false
250
+ }
251
+ },
252
+ auth: {
253
+ config: CONFIG_AUTH,
254
+ options: {
255
+ auth: true
256
+ }
257
+ })
258
+ test 'plain' do |data|
259
+ config = data[:config]
260
+ options = data[:options]
261
+ @d = d = create_driver(config)
262
+
263
+ time = event_time("2011-01-02 13:14:15 UTC")
264
+
265
+ records = [
266
+ ["tag1", time, {"a"=>1}],
267
+ ["tag1", time, {"a"=>2}]
268
+ ]
149
269
 
150
- time = Time.parse("2011-01-02 13:14:15 UTC").to_i
270
+ d.run(expect_records: records.length, timeout: 20) do
271
+ entries = []
272
+ records.each {|tag, _time, record|
273
+ entries << [_time, record]
274
+ }
275
+ send_data packer.write(["tag1", entries]).to_s, **options
276
+ end
277
+ assert_equal(records, d.events)
278
+ end
279
+
280
+ data(tag: {
281
+ param: "tag new_tag",
282
+ result: "new_tag"
283
+ },
284
+ add_tag_prefix: {
285
+ param: "add_tag_prefix new_prefix",
286
+ result: "new_prefix.tag1"
287
+ })
288
+ test 'tag parameters' do |data|
289
+ @d = create_driver(CONFIG + data[:param])
290
+ time = event_time("2011-01-02 13:14:15 UTC")
291
+ options = {auth: false}
292
+
293
+ records = [
294
+ ["tag1", time, {"a"=>1}],
295
+ ["tag1", time, {"a"=>2}],
296
+ ]
151
297
 
152
- d.expect_emit "tag1", time, {"a" => 1}
153
- d.expect_emit "tag1", time, {"a" => 2}
298
+ @d.run(expect_records: records.length, timeout: 20) do
299
+ entries = []
300
+ records.each {|tag, _time, record|
301
+ entries << [_time, record]
302
+ }
303
+ send_data packer.write(["tag1", entries]).to_s, **options
304
+ end
305
+ assert_equal(data[:result], @d.events[0][0])
306
+ end
154
307
 
155
- d.run do
156
- entries = d.expected_emits.map { |tag ,time, record| [time, record] }
157
- # These entries are skipped
158
- entries << ['invalid time', {'a' => 3}] << [time, 'invalid record']
308
+ data(tcp: {
309
+ config: CONFIG,
310
+ options: {
311
+ auth: false
312
+ }
313
+ },
314
+ auth: {
315
+ config: CONFIG_AUTH,
316
+ options: {
317
+ auth: true
318
+ }
319
+ })
320
+ test 'time_as_integer' do |data|
321
+ config = data[:config]
322
+ options = data[:options]
323
+ @d = d = create_driver(config)
324
+
325
+ time_i = event_time("2011-01-02 13:14:15 UTC")
326
+
327
+ records = [
328
+ ["tag1", time_i, {"a"=>1}],
329
+ ["tag1", time_i, {"a"=>2}]
330
+ ]
159
331
 
160
- packed_entries = ''
161
- entries.each { |time, record|
162
- Fluent::Engine.msgpack_factory.packer(packed_entries).write([time, record]).flush
163
- }
164
- send_data Fluent::Engine.msgpack_factory.packer.write(["tag1", packed_entries]).to_s
332
+ d.run(expect_records: records.length, timeout: 20) do
333
+ entries = []
334
+ records.each {|tag, _time, record|
335
+ entries << [_time, record]
336
+ }
337
+ send_data packer.write(["tag1", entries]).to_s, **options
338
+ end
339
+
340
+ assert_equal(records, d.events)
165
341
  end
166
342
 
167
- assert_equal 2, d.instance.log.logs.count { |line| line =~ /skip invalid event/ }
168
- end
343
+ data(tcp: {
344
+ config: CONFIG,
345
+ options: {
346
+ auth: false
347
+ }
348
+ },
349
+ auth: {
350
+ config: CONFIG_AUTH,
351
+ options: {
352
+ auth: true
353
+ }
354
+ })
355
+ test 'skip_invalid_event' do |data|
356
+ config = data[:config]
357
+ options = data[:options]
358
+ @d = d = create_driver(config + "skip_invalid_event true")
359
+
360
+ time = event_time("2011-01-02 13:14:15 UTC")
361
+
362
+ records = [
363
+ ["tag1", time, {"a" => 1}],
364
+ ["tag1", time, {"a" => 2}],
365
+ ]
169
366
 
170
- def test_message_json
171
- d = create_driver
367
+ d.run(shutdown: false, expect_records: records.length, timeout: 20) do
368
+ entries = records.map { |tag, _time, record| [_time, record] }
369
+ # These entries are skipped
370
+ entries << ['invalid time', {'a' => 3}] << [time, 'invalid record']
172
371
 
173
- time = Time.parse("2011-01-02 13:14:15 UTC").to_i
372
+ send_data packer.write(["tag1", entries]).to_s, **options
373
+ end
174
374
 
175
- d.expect_emit "tag1", time, {"a"=>1}
176
- d.expect_emit "tag2", time, {"a"=>2}
375
+ logs = d.instance.log.out.logs
376
+ assert{ logs.select{|line| line =~ /skip invalid event/ }.size == 2 }
177
377
 
178
- d.run do
179
- d.expected_emits.each {|tag,time,record|
180
- send_data [tag, time, record].to_json
181
- }
378
+ d.instance_shutdown
182
379
  end
183
380
  end
184
381
 
185
- def test_send_large_chunk_warning
186
- d = create_driver(CONFIG + %[
187
- chunk_size_warn_limit 16M
188
- chunk_size_limit 32M
189
- ])
382
+ sub_test_case 'packed forward' do
383
+ data(tcp: {
384
+ config: CONFIG,
385
+ options: {
386
+ auth: false
387
+ }
388
+ },
389
+ auth: {
390
+ config: CONFIG_AUTH,
391
+ options: {
392
+ auth: true
393
+ }
394
+ })
395
+ test 'plain' do |data|
396
+ config = data[:config]
397
+ options = data[:options]
398
+ @d = d = create_driver(config)
399
+
400
+ time = event_time("2011-01-02 13:14:15 UTC")
401
+
402
+ records = [
403
+ ["tag1", time, {"a"=>1}],
404
+ ["tag1", time, {"a"=>2}],
405
+ ]
190
406
 
191
- time = Time.parse("2014-04-25 13:14:15 UTC").to_i
407
+ d.run(expect_records: records.length, timeout: 20) do
408
+ entries = ''
409
+ records.each {|_tag, _time, record|
410
+ packer(entries).write([_time, record]).flush
411
+ }
412
+ send_data packer.write(["tag1", entries]).to_s, **options
413
+ end
414
+ assert_equal(records, d.events)
415
+ end
192
416
 
193
- # generate over 16M chunk
194
- str = "X" * 1024 * 1024
195
- chunk = [ "test.tag", (0...16).map{|i| [time + i, {"data" => str}] } ].to_msgpack
196
- assert chunk.size > (16 * 1024 * 1024)
197
- assert chunk.size < (32 * 1024 * 1024)
417
+ data(tag: {
418
+ param: "tag new_tag",
419
+ result: "new_tag"
420
+ },
421
+ add_tag_prefix: {
422
+ param: "add_tag_prefix new_prefix",
423
+ result: "new_prefix.tag1"
424
+ })
425
+ test 'tag parameters' do |data|
426
+ @d = create_driver(CONFIG + data[:param])
427
+ time = event_time("2011-01-02 13:14:15 UTC")
428
+ options = {auth: false}
429
+
430
+ records = [
431
+ ["tag1", time, {"a"=>1}],
432
+ ["tag1", time, {"a"=>2}],
433
+ ]
198
434
 
199
- d.run do
200
- Fluent::Engine.msgpack_factory.unpacker.feed_each(chunk) do |obj|
201
- d.instance.send(:on_message, obj, chunk.size, PEERADDR)
435
+ @d.run(expect_records: records.length, timeout: 20) do
436
+ entries = ''
437
+ records.each {|_tag, _time, record|
438
+ packer(entries).write([_time, record]).flush
439
+ }
440
+ send_data packer.write(["tag1", entries]).to_s, **options
202
441
  end
442
+ assert_equal(data[:result], @d.events[0][0])
203
443
  end
204
444
 
205
- # check emitted data
206
- emits = d.emits
207
- assert_equal 16, emits.size
208
- assert emits.map(&:first).all?{|t| t == "test.tag" }
209
- assert_equal (0...16).to_a, emits.map{|tag, t, record| t - time }
445
+ data(tcp: {
446
+ config: CONFIG,
447
+ options: {
448
+ auth: false
449
+ }
450
+ },
451
+ auth: {
452
+ config: CONFIG_AUTH,
453
+ options: {
454
+ auth: true
455
+ }
456
+ })
457
+ test 'time_as_integer' do |data|
458
+ config = data[:config]
459
+ options = data[:options]
460
+ @d = d = create_driver(config)
461
+
462
+ time_i = event_time("2011-01-02 13:14:15 UTC").to_i
463
+
464
+ records = [
465
+ ["tag1", time_i, {"a"=>1}],
466
+ ["tag1", time_i, {"a"=>2}],
467
+ ]
210
468
 
211
- # check log
212
- assert d.instance.log.logs.select{|line|
213
- line =~ / \[warn\]: Input chunk size is larger than 'chunk_size_warn_limit':/ &&
214
- line =~ / tag="test.tag" source="host: 127.0.0.1, addr: 127.0.0.1, port: \d+" limit=16777216 size=16777501/
215
- }.size == 1, "large chunk warning is not logged"
216
- end
469
+ d.run(expect_records: records.length, timeout: 20) do
470
+ entries = ''
471
+ records.each {|tag, _time, record|
472
+ packer(entries).write([_time, record]).flush
473
+ }
474
+ send_data packer.write(["tag1", entries]).to_s, **options
475
+ end
476
+ assert_equal(records, d.events)
477
+ end
217
478
 
218
- def test_send_large_chunk_only_warning
219
- d = create_driver(CONFIG + %[
220
- chunk_size_warn_limit 16M
221
- ])
222
- time = Time.parse("2014-04-25 13:14:15 UTC").to_i
479
+ data(tcp: {
480
+ config: CONFIG,
481
+ options: {
482
+ auth: false
483
+ }
484
+ },
485
+ auth: {
486
+ config: CONFIG_AUTH,
487
+ options: {
488
+ auth: true
489
+ }
490
+ })
491
+ test 'skip_invalid_event' do |data|
492
+ config = data[:config]
493
+ options = data[:options]
494
+ @d = d = create_driver(config + "skip_invalid_event true")
495
+
496
+ time = event_time("2011-01-02 13:14:15 UTC")
497
+
498
+ records = [
499
+ ["tag1", time, {"a" => 1}],
500
+ ["tag1", time, {"a" => 2}],
501
+ ]
223
502
 
224
- # generate over 16M chunk
225
- str = "X" * 1024 * 1024
226
- chunk = [ "test.tag", (0...16).map{|i| [time + i, {"data" => str}] } ].to_msgpack
503
+ d.run(shutdown: false, expect_records: records.length, timeout: 20) do
504
+ entries = records.map { |tag, _time, record| [_time, record] }
505
+ # These entries are skipped
506
+ entries << ['invalid time', {'a' => 3}] << [time, 'invalid record']
227
507
 
228
- d.run do
229
- Fluent::Engine.msgpack_factory.unpacker.feed_each(chunk) do |obj|
230
- d.instance.send(:on_message, obj, chunk.size, PEERADDR)
508
+ packed_entries = ''
509
+ entries.each { |_time, record|
510
+ packer(packed_entries).write([_time, record]).flush
511
+ }
512
+ send_data packer.write(["tag1", packed_entries]).to_s, **options
231
513
  end
232
- end
233
514
 
234
- # check log
235
- assert d.instance.log.logs.select{ |line|
236
- line =~ / \[warn\]: Input chunk size is larger than 'chunk_size_warn_limit':/ &&
237
- line =~ / tag="test.tag" source="host: 127.0.0.1, addr: 127.0.0.1, port: \d+" limit=16777216 size=16777501/
238
- }.size == 1, "large chunk warning is not logged"
515
+ logs = d.instance.log.logs
516
+ assert_equal 2, logs.count { |line| line =~ /skip invalid event/ }
517
+
518
+ d.instance_shutdown
519
+ end
239
520
  end
240
521
 
241
- def test_send_large_chunk_limit
242
- d = create_driver(CONFIG + %[
243
- chunk_size_warn_limit 16M
244
- chunk_size_limit 32M
245
- ])
522
+ sub_test_case 'compressed packed forward' do
523
+ test 'set_compress_to_option' do
524
+ @d = d = create_driver
246
525
 
247
- time = Time.parse("2014-04-25 13:14:15 UTC").to_i
526
+ time_i = event_time("2011-01-02 13:14:15 UTC").to_i
527
+ events = [
528
+ ["tag1", time_i, {"a"=>1}],
529
+ ["tag1", time_i, {"a"=>2}]
530
+ ]
248
531
 
249
- # generate over 32M chunk
250
- str = "X" * 1024 * 1024
251
- chunk = [ "test.tag", (0...32).map{|i| [time + i, {"data" => str}] } ].to_msgpack
252
- assert chunk.size > (32 * 1024 * 1024)
532
+ # create compressed entries
533
+ entries = ''
534
+ events.each do |_tag, _time, record|
535
+ v = [_time, record].to_msgpack
536
+ entries << compress(v)
537
+ end
538
+ chunk = ["tag1", entries, { 'compressed' => 'gzip' }].to_msgpack
253
539
 
254
- # d.run => send_data
255
- d.run do
256
- Fluent::Engine.msgpack_factory.unpacker.feed_each(chunk) do |obj|
257
- d.instance.send(:on_message, obj, chunk.size, PEERADDR)
540
+ d.run do
541
+ Fluent::Engine.msgpack_factory.unpacker.feed_each(chunk) do |obj|
542
+ option = d.instance.send(:on_message, obj, chunk.size, DUMMY_SOCK)
543
+ assert_equal 'gzip', option['compressed']
544
+ end
258
545
  end
546
+
547
+ assert_equal events, d.events
259
548
  end
260
549
 
261
- # check emitted data
262
- emits = d.emits
263
- assert_equal 0, emits.size
550
+ test 'create_CompressedMessagePackEventStream_with_gzip_compress_option' do
551
+ @d = d = create_driver
264
552
 
265
- # check log
266
- assert d.instance.log.logs.select{|line|
267
- line =~ / \[warn\]: Input chunk size is larger than 'chunk_size_limit', dropped:/ &&
268
- line =~ / tag="test.tag" source="host: 127.0.0.1, addr: 127.0.0.1, port: \d+" limit=33554432 size=33554989/
269
- }.size == 1, "large chunk warning is not logged"
270
- end
553
+ time_i = event_time("2011-01-02 13:14:15 UTC").to_i
554
+ events = [
555
+ ["tag1", time_i, {"a"=>1}],
556
+ ["tag1", time_i, {"a"=>2}]
557
+ ]
271
558
 
272
- data('string chunk' => 'broken string',
273
- 'integer chunk' => 10)
274
- def test_send_broken_chunk(data)
275
- d = create_driver
559
+ # create compressed entries
560
+ entries = ''
561
+ events.each do |_tag, _time, record|
562
+ v = [_time, record].to_msgpack
563
+ entries << compress(v)
564
+ end
565
+ chunk = ["tag1", entries, { 'compressed' => 'gzip' }].to_msgpack
566
+
567
+ # check CompressedMessagePackEventStream is created
568
+ mock(Fluent::CompressedMessagePackEventStream).new(entries, nil, 0)
276
569
 
277
- # d.run => send_data
278
- d.run do
279
- d.instance.send(:on_message, data, 1000000000, PEERADDR)
570
+ d.run do
571
+ Fluent::Engine.msgpack_factory.unpacker.feed_each(chunk) do |obj|
572
+ option = d.instance.send(:on_message, obj, chunk.size, DUMMY_SOCK)
573
+ assert_equal 'gzip', option['compressed']
574
+ end
575
+ end
280
576
  end
577
+ end
281
578
 
282
- # check emitted data
283
- emits = d.emits
284
- assert_equal 0, emits.size
579
+ sub_test_case 'warning' do
580
+ test 'send_large_chunk_warning' do
581
+ @d = d = create_driver(CONFIG + %[
582
+ chunk_size_warn_limit 16M
583
+ chunk_size_limit 32M
584
+ ])
285
585
 
286
- # check log
287
- assert d.instance.log.logs.select{|line|
288
- line =~ / \[warn\]: incoming chunk is broken: source="host: 127.0.0.1, addr: 127.0.0.1, port: \d+" msg=#{data.inspect}/
289
- }.size == 1, "should not accept broken chunk"
290
- end
586
+ time = event_time("2014-04-25 13:14:15 UTC")
291
587
 
292
- def test_respond_to_message_requiring_ack
293
- d = create_driver
588
+ # generate over 16M chunk
589
+ str = "X" * 1024 * 1024
590
+ chunk = [ "test.tag", (0...16).map{|i| [time + i, {"data" => str}] } ].to_msgpack
591
+ assert chunk.size > (16 * 1024 * 1024)
592
+ assert chunk.size < (32 * 1024 * 1024)
294
593
 
295
- time = Time.parse("2011-01-02 13:14:15 UTC").to_i
594
+ d.run(shutdown: false) do
595
+ Fluent::Engine.msgpack_factory.unpacker.feed_each(chunk) do |obj|
596
+ d.instance.send(:on_message, obj, chunk.size, DUMMY_SOCK)
597
+ end
598
+ end
296
599
 
297
- events = [
298
- ["tag1", time, {"a"=>1}],
299
- ["tag2", time, {"a"=>2}]
300
- ]
301
- d.expected_emits_length = events.length
600
+ # check emitted data
601
+ emits = d.events
602
+ assert_equal 16, emits.size
603
+ assert emits.map(&:first).all?{|t| t == "test.tag" }
604
+ assert_equal (0...16).to_a, emits.map{|_tag, t, _record| t - time }
302
605
 
303
- expected_acks = []
606
+ # check log
607
+ logs = d.instance.log.logs
608
+ assert_equal 1, logs.select{|line|
609
+ line =~ / \[warn\]: Input chunk size is larger than 'chunk_size_warn_limit':/ &&
610
+ line =~ / tag="test.tag" host="#{LOCALHOST_HOSTNAME}" limit=16777216 size=16777501/
611
+ }.size, "large chunk warning is not logged"
304
612
 
305
- d.run do
306
- events.each {|tag,time,record|
307
- op = { 'chunk' => Base64.encode64(record.object_id.to_s) }
308
- expected_acks << op['chunk']
309
- send_data [tag, time, record, op].to_msgpack, true
310
- }
613
+ d.instance_shutdown
311
614
  end
312
615
 
313
- assert_equal events, d.emits
314
- assert_equal expected_acks, @responses.map { |res| MessagePack.unpack(res)['ack'] }
315
- end
316
-
317
- # FIX: response is not pushed into @responses because IO.select has been blocked until InputForward shutdowns
318
- def test_respond_to_forward_requiring_ack
319
- d = create_driver
616
+ test 'send_large_chunk_only_warning' do
617
+ @d = d = create_driver(CONFIG + %[
618
+ chunk_size_warn_limit 16M
619
+ ])
620
+ time = event_time("2014-04-25 13:14:15 UTC")
320
621
 
321
- time = Time.parse("2011-01-02 13:14:15 UTC").to_i
622
+ # generate over 16M chunk
623
+ str = "X" * 1024 * 1024
624
+ chunk = [ "test.tag", (0...16).map{|i| [time + i, {"data" => str}] } ].to_msgpack
322
625
 
323
- events = [
324
- ["tag1", time, {"a"=>1}],
325
- ["tag1", time, {"a"=>2}]
326
- ]
327
- d.expected_emits_length = events.length
626
+ d.run(shutdown: false) do
627
+ Fluent::Engine.msgpack_factory.unpacker.feed_each(chunk) do |obj|
628
+ d.instance.send(:on_message, obj, chunk.size, DUMMY_SOCK)
629
+ end
630
+ end
328
631
 
329
- expected_acks = []
632
+ # check log
633
+ logs = d.instance.log.logs
634
+ assert_equal 1, logs.select{ |line|
635
+ line =~ / \[warn\]: Input chunk size is larger than 'chunk_size_warn_limit':/ &&
636
+ line =~ / tag="test.tag" host="#{LOCALHOST_HOSTNAME}" limit=16777216 size=16777501/
637
+ }.size, "large chunk warning is not logged"
330
638
 
331
- d.run do
332
- entries = []
333
- events.each {|tag,time,record|
334
- entries << [time, record]
335
- }
336
- op = { 'chunk' => Base64.encode64(entries.object_id.to_s) }
337
- expected_acks << op['chunk']
338
- send_data ["tag1", entries, op].to_msgpack, true
639
+ d.instance_shutdown
339
640
  end
340
641
 
341
- assert_equal events, d.emits
342
- assert_equal expected_acks, @responses.map { |res| MessagePack.unpack(res)['ack'] }
343
- end
642
+ test 'send_large_chunk_limit' do
643
+ @d = d = create_driver(CONFIG + %[
644
+ chunk_size_warn_limit 16M
645
+ chunk_size_limit 32M
646
+ ])
344
647
 
345
- def test_respond_to_packed_forward_requiring_ack
346
- d = create_driver
648
+ time = event_time("2014-04-25 13:14:15 UTC")
347
649
 
348
- time = Time.parse("2011-01-02 13:14:15 UTC").to_i
650
+ # generate over 32M chunk
651
+ str = "X" * 1024 * 1024
652
+ chunk = [ "test.tag", (0...32).map{|i| [time + i, {"data" => str}] } ].to_msgpack
653
+ assert chunk.size > (32 * 1024 * 1024)
349
654
 
350
- events = [
351
- ["tag1", time, {"a"=>1}],
352
- ["tag1", time, {"a"=>2}]
353
- ]
354
- d.expected_emits_length = events.length
655
+ # d.run => send_data
656
+ d.run(shutdown: false) do
657
+ Fluent::Engine.msgpack_factory.unpacker.feed_each(chunk) do |obj|
658
+ d.instance.send(:on_message, obj, chunk.size, DUMMY_SOCK)
659
+ end
660
+ end
355
661
 
356
- expected_acks = []
662
+ # check emitted data
663
+ emits = d.events
664
+ assert_equal 0, emits.size
357
665
 
358
- d.run do
359
- entries = ''
360
- events.each {|tag,time,record|
361
- [time, record].to_msgpack(entries)
362
- }
363
- op = { 'chunk' => Base64.encode64(entries.object_id.to_s) }
364
- expected_acks << op['chunk']
365
- send_data ["tag1", entries, op].to_msgpack, true
666
+ # check log
667
+ logs = d.instance.log.logs
668
+ assert_equal 1, logs.select{|line|
669
+ line =~ / \[warn\]: Input chunk size is larger than 'chunk_size_limit', dropped:/ &&
670
+ line =~ / tag="test.tag" host="#{LOCALHOST_HOSTNAME}" limit=33554432 size=33554989/
671
+ }.size, "large chunk warning is not logged"
672
+
673
+ d.instance_shutdown
366
674
  end
367
675
 
368
- assert_equal events, d.emits
369
- assert_equal expected_acks, @responses.map { |res| MessagePack.unpack(res)['ack'] }
676
+ data('string chunk' => 'broken string',
677
+ 'integer chunk' => 10)
678
+ test 'send_broken_chunk' do |data|
679
+ @d = d = create_driver
680
+
681
+ # d.run => send_data
682
+ d.run(shutdown: false) do
683
+ d.instance.send(:on_message, data, 1000000000, DUMMY_SOCK)
684
+ end
685
+
686
+ # check emitted data
687
+ assert_equal 0, d.events.size
688
+
689
+ # check log
690
+ logs = d.instance.log.logs
691
+ assert_equal 1, logs.select{|line|
692
+ line =~ / \[warn\]: incoming chunk is broken: host="#{LOCALHOST_HOSTNAME}" msg=#{data.inspect}/
693
+ }.size, "should not accept broken chunk"
694
+
695
+ d.instance_shutdown
696
+ end
370
697
  end
371
698
 
372
- def test_respond_to_message_json_requiring_ack
373
- d = create_driver
699
+ sub_test_case 'respond to required ack' do
700
+ data(tcp: {
701
+ config: CONFIG,
702
+ options: {
703
+ auth: false
704
+ }
705
+ },
706
+ auth: {
707
+ config: CONFIG_AUTH,
708
+ options: {
709
+ auth: true
710
+ }
711
+ })
712
+ test 'message' do |data|
713
+ config = data[:config]
714
+ options = data[:options]
715
+ @d = d = create_driver(config)
716
+
717
+ time = event_time("2011-01-02 13:14:15 UTC")
374
718
 
375
- time = Time.parse("2011-01-02 13:14:15 UTC").to_i
719
+ events = [
720
+ ["tag1", time, {"a"=>1}],
721
+ ["tag2", time, {"a"=>2}]
722
+ ]
376
723
 
377
- events = [
378
- ["tag1", time, {"a"=>1}],
379
- ["tag2", time, {"a"=>2}]
380
- ]
381
- d.expected_emits_length = events.length
724
+ expected_acks = []
382
725
 
383
- expected_acks = []
726
+ d.run(expect_records: events.size) do
727
+ events.each {|tag, _time, record|
728
+ op = { 'chunk' => Base64.encode64(record.object_id.to_s) }
729
+ expected_acks << op['chunk']
730
+ send_data [tag, _time, record, op].to_msgpack, try_to_receive_response: true, **options
731
+ }
732
+ end
733
+
734
+ assert_equal events, d.events
735
+ assert_equal expected_acks, @responses.map { |res| MessagePack.unpack(res)['ack'] }
736
+ end
737
+
738
+ # FIX: response is not pushed into @responses because IO.select has been blocked until InputForward shutdowns
739
+ data(tcp: {
740
+ config: CONFIG,
741
+ options: {
742
+ auth: false
743
+ }
744
+ },
745
+ auth: {
746
+ config: CONFIG_AUTH,
747
+ options: {
748
+ auth: true
749
+ }
750
+ })
751
+ test 'forward' do |data|
752
+ config = data[:config]
753
+ options = data[:options]
754
+ @d = d = create_driver(config)
755
+
756
+ time = event_time("2011-01-02 13:14:15 UTC")
757
+
758
+ events = [
759
+ ["tag1", time, {"a"=>1}],
760
+ ["tag1", time, {"a"=>2}]
761
+ ]
384
762
 
385
- d.run do
386
- events.each {|tag,time,record|
387
- op = { 'chunk' => Base64.encode64(record.object_id.to_s) }
763
+ expected_acks = []
764
+
765
+ d.run(expect_records: events.size) do
766
+ entries = []
767
+ events.each {|_tag, _time, record|
768
+ entries << [_time, record]
769
+ }
770
+ op = { 'chunk' => Base64.encode64(entries.object_id.to_s) }
388
771
  expected_acks << op['chunk']
389
- send_data [tag, time, record, op].to_json, true
390
- }
772
+ send_data ["tag1", entries, op].to_msgpack, try_to_receive_response: true, **options
773
+ end
774
+
775
+ assert_equal events, d.events
776
+ assert_equal expected_acks, @responses.map { |res| MessagePack.unpack(res)['ack'] }
391
777
  end
392
778
 
393
- assert_equal events, d.emits
394
- assert_equal expected_acks, @responses.map { |res| JSON.parse(res)['ack'] }
395
- end
779
+ data(tcp: {
780
+ config: CONFIG,
781
+ options: {
782
+ auth: false
783
+ }
784
+ },
785
+ auth: {
786
+ config: CONFIG_AUTH,
787
+ options: {
788
+ auth: true
789
+ }
790
+ })
791
+ test 'packed_forward' do |data|
792
+ config = data[:config]
793
+ options = data[:options]
794
+ @d = d = create_driver(config)
795
+
796
+ time = event_time("2011-01-02 13:14:15 UTC")
396
797
 
397
- def test_not_respond_to_message_not_requiring_ack
398
- d = create_driver
798
+ events = [
799
+ ["tag1", time, {"a"=>1}],
800
+ ["tag1", time, {"a"=>2}]
801
+ ]
399
802
 
400
- time = Time.parse("2011-01-02 13:14:15 UTC").to_i
803
+ expected_acks = []
401
804
 
402
- events = [
403
- ["tag1", time, {"a"=>1}],
404
- ["tag2", time, {"a"=>2}]
405
- ]
406
- d.expected_emits_length = events.length
805
+ d.run(expect_records: events.size) do
806
+ entries = ''
807
+ events.each {|_tag, _time,record|
808
+ [time, record].to_msgpack(entries)
809
+ }
810
+ op = { 'chunk' => Base64.encode64(entries.object_id.to_s) }
811
+ expected_acks << op['chunk']
812
+ send_data ["tag1", entries, op].to_msgpack, try_to_receive_response: true, **options
813
+ end
407
814
 
408
- d.run do
409
- events.each {|tag,time,record|
410
- send_data [tag, time, record].to_msgpack, true
411
- }
815
+ assert_equal events, d.events
816
+ assert_equal expected_acks, @responses.map { |res| MessagePack.unpack(res)['ack'] }
412
817
  end
413
818
 
414
- assert_equal events, d.emits
415
- assert_equal [nil, nil], @responses
819
+ data(
820
+ tcp: {
821
+ config: CONFIG,
822
+ options: {
823
+ auth: false
824
+ }
825
+ },
826
+ ### Auth is not supported with json
827
+ # auth: {
828
+ # config: CONFIG_AUTH,
829
+ # options: {
830
+ # auth: true
831
+ # }
832
+ # },
833
+ )
834
+ test 'message_json' do |data|
835
+ config = data[:config]
836
+ options = data[:options]
837
+ @d = d = create_driver(config)
838
+
839
+ time_i = event_time("2011-01-02 13:14:15 UTC")
840
+
841
+ events = [
842
+ ["tag1", time_i, {"a"=>1}],
843
+ ["tag2", time_i, {"a"=>2}]
844
+ ]
845
+
846
+ expected_acks = []
847
+
848
+ d.run(expect_records: events.size, timeout: 20) do
849
+ events.each {|tag, _time, record|
850
+ op = { 'chunk' => Base64.encode64(record.object_id.to_s) }
851
+ expected_acks << op['chunk']
852
+ send_data [tag, _time, record, op].to_json, try_to_receive_response: true, **options
853
+ }
854
+ end
855
+
856
+ assert_equal events, d.events
857
+ assert_equal expected_acks, @responses.map { |res| JSON.parse(res)['ack'] }
858
+ end
416
859
  end
417
860
 
418
- def test_not_respond_to_forward_not_requiring_ack
419
- d = create_driver
861
+ sub_test_case 'not respond without required ack' do
862
+ data(tcp: {
863
+ config: CONFIG,
864
+ options: {
865
+ auth: false
866
+ }
867
+ },
868
+ auth: {
869
+ config: CONFIG_AUTH,
870
+ options: {
871
+ auth: true
872
+ }
873
+ })
874
+ test 'message' do |data|
875
+ config = data[:config]
876
+ options = data[:options]
877
+ @d = d = create_driver(config)
878
+
879
+ time = event_time("2011-01-02 13:14:15 UTC")
420
880
 
421
- time = Time.parse("2011-01-02 13:14:15 UTC").to_i
881
+ events = [
882
+ ["tag1", time, {"a"=>1}],
883
+ ["tag2", time, {"a"=>2}]
884
+ ]
422
885
 
423
- events = [
424
- ["tag1", time, {"a"=>1}],
425
- ["tag1", time, {"a"=>2}]
426
- ]
427
- d.expected_emits_length = events.length
886
+ d.run(expect_records: events.size, timeout: 20) do
887
+ events.each {|tag, _time, record|
888
+ send_data [tag, _time, record].to_msgpack, try_to_receive_response: true, **options
889
+ }
890
+ end
428
891
 
429
- d.run do
430
- entries = []
431
- events.each {|tag,time,record|
432
- entries << [time, record]
433
- }
434
- send_data ["tag1", entries].to_msgpack, true
892
+ assert_equal events, d.events
893
+ assert_equal [nil, nil], @responses
435
894
  end
436
895
 
437
- assert_equal events, d.emits
438
- assert_equal [nil], @responses
439
- end
896
+ data(tcp: {
897
+ config: CONFIG,
898
+ options: {
899
+ auth: false
900
+ }
901
+ },
902
+ auth: {
903
+ config: CONFIG_AUTH,
904
+ options: {
905
+ auth: true
906
+ }
907
+ })
908
+ test 'forward' do |data|
909
+ config = data[:config]
910
+ options = data[:options]
911
+ @d = d = create_driver(config)
912
+
913
+ time = event_time("2011-01-02 13:14:15 UTC")
440
914
 
441
- def test_not_respond_to_packed_forward_not_requiring_ack
442
- d = create_driver
915
+ events = [
916
+ ["tag1", time, {"a"=>1}],
917
+ ["tag1", time, {"a"=>2}]
918
+ ]
443
919
 
444
- time = Time.parse("2011-01-02 13:14:15 UTC").to_i
920
+ d.run(expect_records: events.size, timeout: 20) do
921
+ entries = []
922
+ events.each {|tag, _time, record|
923
+ entries << [_time, record]
924
+ }
925
+ send_data ["tag1", entries].to_msgpack, try_to_receive_response: true, **options
926
+ end
445
927
 
446
- events = [
447
- ["tag1", time, {"a"=>1}],
448
- ["tag1", time, {"a"=>2}]
449
- ]
450
- d.expected_emits_length = events.length
928
+ assert_equal events, d.events
929
+ assert_equal [nil], @responses
930
+ end
451
931
 
452
- d.run do
453
- entries = ''
454
- events.each {|tag,time,record|
455
- [time, record].to_msgpack(entries)
456
- }
457
- send_data ["tag1", entries].to_msgpack, true
932
+ data(tcp: {
933
+ config: CONFIG,
934
+ options: {
935
+ auth: false
936
+ }
937
+ },
938
+ auth: {
939
+ config: CONFIG_AUTH,
940
+ options: {
941
+ auth: true
942
+ }
943
+ })
944
+ test 'packed_forward' do |data|
945
+ config = data[:config]
946
+ options = data[:options]
947
+ @d = d = create_driver(config)
948
+
949
+ time = event_time("2011-01-02 13:14:15 UTC")
950
+
951
+ events = [
952
+ ["tag1", time, {"a"=>1}],
953
+ ["tag1", time, {"a"=>2}]
954
+ ]
955
+
956
+ d.run(expect_records: events.size, timeout: 20) do
957
+ entries = ''
958
+ events.each {|tag, _time, record|
959
+ [_time, record].to_msgpack(entries)
960
+ }
961
+ send_data ["tag1", entries].to_msgpack, try_to_receive_response: true, **options
962
+ end
963
+
964
+ assert_equal events, d.events
965
+ assert_equal [nil], @responses
458
966
  end
459
967
 
460
- assert_equal events, d.emits
461
- assert_equal [nil], @responses
462
- end
968
+ data(
969
+ tcp: {
970
+ config: CONFIG,
971
+ options: {
972
+ auth: false
973
+ }
974
+ },
975
+ ### Auth is not supported with json
976
+ # auth: {
977
+ # config: CONFIG_AUTH,
978
+ # options: {
979
+ # auth: true
980
+ # }
981
+ # },
982
+ )
983
+ test 'message_json' do |data|
984
+ config = data[:config]
985
+ options = data[:options]
986
+ @d = d = create_driver(config)
463
987
 
464
- def test_not_respond_to_message_json_not_requiring_ack
465
- d = create_driver
988
+ time_i = event_time("2011-01-02 13:14:15 UTC").to_i
466
989
 
467
- time = Time.parse("2011-01-02 13:14:15 UTC").to_i
990
+ events = [
991
+ ["tag1", time_i, {"a"=>1}],
992
+ ["tag2", time_i, {"a"=>2}]
993
+ ]
468
994
 
469
- events = [
470
- ["tag1", time, {"a"=>1}],
471
- ["tag2", time, {"a"=>2}]
472
- ]
473
- d.expected_emits_length = events.length
995
+ d.run(expect_records: events.size, timeout: 20) do
996
+ events.each {|tag, _time, record|
997
+ send_data [tag, _time, record].to_json, try_to_receive_response: true, **options
998
+ }
999
+ end
474
1000
 
475
- d.run do
476
- events.each {|tag,time,record|
477
- send_data [tag, time, record].to_json, true
478
- }
1001
+ assert_equal events, d.events
1002
+ assert_equal [nil, nil], @responses
479
1003
  end
1004
+ end
480
1005
 
481
- assert_equal events, d.emits
482
- assert_equal [nil, nil], @responses
1006
+ def packer(*args)
1007
+ Fluent::Engine.msgpack_factory.packer(*args)
483
1008
  end
484
1009
 
485
- def send_data(data, try_to_receive_response=false, response_timeout=1)
486
- io = connect
1010
+ def unpacker
1011
+ Fluent::Engine.msgpack_factory.unpacker
1012
+ end
1013
+
1014
+ # res
1015
+ # '' : socket is disconnected without any data
1016
+ # nil: socket read timeout
1017
+ def read_data(io, timeout, &block)
1018
+ res = ''
1019
+ select_timeout = 2
1020
+ clock_id = Process::CLOCK_MONOTONIC_RAW rescue Process::CLOCK_MONOTONIC
1021
+ timeout_at = Process.clock_gettime(clock_id) + timeout
487
1022
  begin
488
- io.write data
489
- if try_to_receive_response
490
- if IO.select([io], nil, nil, response_timeout)
491
- res = io.recv(1024)
1023
+ buf = ''
1024
+ io_activated = false
1025
+ while Process.clock_gettime(clock_id) < timeout_at
1026
+ if IO.select([io], nil, nil, select_timeout)
1027
+ io_activated = true
1028
+ buf = io.readpartial(2048)
1029
+ res ||= ''
1030
+ res << buf
1031
+
1032
+ break if block.call(res)
492
1033
  end
493
- # timeout means no response, so push nil to @responses
494
1034
  end
495
- ensure
496
- io.close
1035
+ res = nil unless io_activated # timeout without no data arrival
1036
+ rescue Errno::EAGAIN
1037
+ sleep 0.01
1038
+ retry if res == ''
1039
+ # if res is not empty, all data in socket buffer are read, so do not retry
1040
+ rescue IOError, EOFError, Errno::ECONNRESET
1041
+ # socket disconnected
497
1042
  end
498
- @responses << res if try_to_receive_response
1043
+ res
499
1044
  end
500
1045
 
501
- LOCALHOST_HOSTNAME_GETTER = ->(){sock = UDPSocket.new(::Socket::AF_INET); sock.do_not_reverse_lookup = false; sock.connect("127.0.0.1", 2048); sock.peeraddr[2] }
502
- LOCALHOST_HOSTNAME = LOCALHOST_HOSTNAME_GETTER.call
503
- DUMMY_SOCK = Struct.new(:remote_host, :remote_addr, :remote_port).new(LOCALHOST_HOSTNAME, "127.0.0.1", 0)
1046
+ def simulate_auth_sequence(io, shared_key=SHARED_KEY, username=USER_NAME, password=USER_PASSWORD)
1047
+ auth_response_timeout = 30
1048
+ shared_key_salt = 'salt'
1049
+
1050
+ # reading helo
1051
+ helo_data = read_data(io, auth_response_timeout){|data| MessagePack.unpack(data) rescue nil }
1052
+ raise "Authentication packet timeout" unless helo_data
1053
+ raise "Authentication connection closed" if helo_data == ''
1054
+ # ['HELO', options(hash)]
1055
+ helo = MessagePack.unpack(helo_data)
1056
+ raise "Invalid HELO header" unless helo[0] == 'HELO'
1057
+ raise "Invalid HELO option object" unless helo[1].is_a?(Hash)
1058
+ @options = helo[1]
1059
+
1060
+ # sending ping
1061
+ ping = [
1062
+ 'PING',
1063
+ 'selfhostname',
1064
+ shared_key_salt,
1065
+ Digest::SHA512.new
1066
+ .update(shared_key_salt)
1067
+ .update('selfhostname')
1068
+ .update(@options['nonce'])
1069
+ .update(shared_key).hexdigest,
1070
+ ]
1071
+ if @options['auth'] # auth enabled -> value is auth salt
1072
+ pass_digest = Digest::SHA512.new.update(@options['auth']).update(username).update(password).hexdigest
1073
+ ping.push(username, pass_digest)
1074
+ else
1075
+ ping.push('', '')
1076
+ end
1077
+ io.write ping.to_msgpack
1078
+ io.flush
1079
+
1080
+ # reading pong
1081
+ pong_data = read_data(io, auth_response_timeout){|data| MessagePack.unpack(data) rescue nil }
1082
+ raise "PONG packet timeout" unless pong_data
1083
+ raise "PONG connection closed" if pong_data == ''
1084
+ # ['PING', bool(auth_result), string(reason_if_failed), self_hostname, shared_key_digest]
1085
+ pong = MessagePack.unpack(pong_data)
1086
+ raise "Invalid PONG header" unless pong[0] == 'PONG'
1087
+ raise "Authentication Failure: #{pong[2]}" unless pong[1]
1088
+ clientside_calculated = Digest::SHA512.new
1089
+ .update(shared_key_salt)
1090
+ .update(pong[3])
1091
+ .update(@options['nonce'])
1092
+ .update(shared_key).hexdigest
1093
+ raise "Shared key digest mismatch" unless clientside_calculated == pong[4]
1094
+
1095
+ # authentication success
1096
+ true
1097
+ end
504
1098
 
505
- sub_test_case 'source_hostname_key and source_address_key features' do
506
- test 'resolve_hostname must be true with source_hostname_key' do
507
- assert_raise(Fluent::ConfigError) {
508
- create_driver(CONFIG + <<EOS)
509
- resolve_hostname false
510
- source_hostname_key hostname
511
- EOS
512
- }
1099
+ def connect
1100
+ TCPSocket.new('127.0.0.1', PORT)
1101
+ end
1102
+
1103
+ # Data ordering is not assured:
1104
+ # Records in different sockets are processed on different thread, so its scheduling make effect
1105
+ # on order of emitted records.
1106
+ # So, we MUST sort emitted records in different `send_data` before assertion.
1107
+ def send_data(data, try_to_receive_response: false, response_timeout: 5, auth: false)
1108
+ io = connect
1109
+
1110
+ if auth
1111
+ simulate_auth_sequence(io)
513
1112
  end
1113
+
1114
+ io.write data
1115
+ io.flush
1116
+ if try_to_receive_response
1117
+ @responses << read_data(io, response_timeout){|d| MessagePack.unpack(d) rescue nil }
1118
+ end
1119
+ ensure
1120
+ io.close rescue nil # SSL socket requires any writes to close sockets
1121
+ end
1122
+
1123
+ sub_test_case 'source_hostname_key and source_address_key features' do
514
1124
  data(
515
1125
  both: [:hostname, :address],
516
1126
  hostname: [:hostname],
517
1127
  address: [:address],
518
1128
  )
519
1129
  test 'message protocol' do |keys|
520
- execute_test(*keys) { |events|
1130
+ execute_test_with_source_hostname_key(*keys) { |events|
521
1131
  events.each { |tag, time, record|
522
1132
  send_data [tag, time, record].to_msgpack
523
1133
  }
@@ -530,7 +1140,7 @@ EOS
530
1140
  address: [:address],
531
1141
  )
532
1142
  test 'forward protocol' do |keys|
533
- execute_test(*keys) { |events|
1143
+ execute_test_with_source_hostname_key(*keys) { |events|
534
1144
  entries = []
535
1145
  events.each {|tag,time,record|
536
1146
  entries << [time, record]
@@ -545,7 +1155,7 @@ EOS
545
1155
  address: [:address],
546
1156
  )
547
1157
  test 'packed forward protocol' do |keys|
548
- execute_test(*keys) { |events|
1158
+ execute_test_with_source_hostname_key(*keys) { |events|
549
1159
  entries = ''
550
1160
  events.each { |tag, time, record|
551
1161
  Fluent::Engine.msgpack_factory.packer(entries).write([time, record]).flush
@@ -553,49 +1163,42 @@ EOS
553
1163
  send_data Fluent::Engine.msgpack_factory.packer.write(["tag1", entries]).to_s
554
1164
  }
555
1165
  end
1166
+ end
556
1167
 
557
- def execute_test(*keys, &block)
558
- conf = CONFIG.dup
559
- if keys.include?(:hostname)
560
- conf << <<EOL
1168
+ def execute_test_with_source_hostname_key(*keys, &block)
1169
+ conf = CONFIG.dup
1170
+ if keys.include?(:hostname)
1171
+ conf << <<EOL
561
1172
  source_hostname_key source_hostname
562
1173
  EOL
563
- end
564
- if keys.include?(:address)
565
- conf << <<EOL
1174
+ end
1175
+ if keys.include?(:address)
1176
+ conf << <<EOL
566
1177
  source_address_key source_address
567
1178
  EOL
568
- end
569
- d = create_driver(conf)
570
-
571
- time = Time.parse("2011-01-02 13:14:15 UTC").to_i
572
- events = [
573
- ["tag1", time, {"a"=>1}],
574
- ["tag1", time, {"a"=>2}]
575
- ]
576
- d.expected_emits_length = events.length
1179
+ end
1180
+ @d = d = create_driver(conf)
577
1181
 
578
- d.run do
579
- block.call(events)
580
- end
1182
+ time = event_time("2011-01-02 13:14:15 UTC")
1183
+ events = [
1184
+ ["tag1", time, {"a"=>1}],
1185
+ ["tag1", time, {"a"=>2}]
1186
+ ]
581
1187
 
582
- d.emits.each { |tag, _time, record|
583
- if keys.include?(:hostname)
584
- assert_true record.has_key?('source_hostname')
585
- assert_equal DUMMY_SOCK.remote_host, record['source_hostname']
586
- unless keys.include?(:address)
587
- assert_false record.has_key?('source_address')
588
- end
589
- end
590
- if keys.include?(:address)
591
- assert_true record.has_key?('source_address')
592
- assert_equal DUMMY_SOCK.remote_addr, record['source_address']
593
- unless keys.include?(:hostname)
594
- assert_false record.has_key?('source_hostname')
595
- end
596
- end
597
- }
1188
+ d.run(expect_records: events.size) do
1189
+ block.call(events)
598
1190
  end
1191
+
1192
+ d.events.each { |tag, _time, record|
1193
+ if keys.include?(:hostname)
1194
+ assert_true record.has_key?('source_hostname')
1195
+ assert_equal DUMMY_SOCK.remote_host, record['source_hostname']
1196
+ end
1197
+ if keys.include?(:address)
1198
+ assert_true record.has_key?('source_address')
1199
+ assert_equal DUMMY_SOCK.remote_addr, record['source_address']
1200
+ end
1201
+ }
599
1202
  end
600
1203
 
601
1204
  # TODO heartbeat