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,15 +1,30 @@
1
1
  require_relative '../helper'
2
- require 'fluent/test'
2
+ require 'fluent/test/driver/output'
3
+ require 'fluent/plugin/out_forward'
4
+ require 'flexmock/test_unit'
5
+
6
+ require 'fluent/test/driver/input'
7
+ require 'fluent/plugin/in_forward'
3
8
 
4
9
  class ForwardOutputTest < Test::Unit::TestCase
5
10
  def setup
6
11
  Fluent::Test.setup
12
+ FileUtils.rm_rf(TMP_DIR)
13
+ FileUtils.mkdir_p(TMP_DIR)
14
+ @d = nil
15
+ end
16
+
17
+ def teardown
18
+ @d.instance_shutdown if @d
7
19
  end
8
20
 
21
+ TMP_DIR = File.join(__dir__, "../tmp/out_forward#{ENV['TEST_ENV_NUMBER']}")
22
+
9
23
  TARGET_HOST = '127.0.0.1'
10
- TARGET_PORT = 13999
24
+ TARGET_PORT = unused_port
11
25
  CONFIG = %[
12
26
  send_timeout 51
27
+ heartbeat_type udp
13
28
  <server>
14
29
  name test
15
30
  host #{TARGET_HOST}
@@ -23,401 +38,1174 @@ class ForwardOutputTest < Test::Unit::TestCase
23
38
  ]
24
39
 
25
40
  def create_driver(conf=CONFIG)
26
- Fluent::Test::BufferedOutputTestDriver.new(Fluent::ForwardOutput) {
27
- attr_reader :responses, :exceptions
41
+ Fluent::Test::Driver::Output.new(Fluent::Plugin::ForwardOutput) {
42
+ attr_reader :response_chunk_ids, :exceptions, :sent_chunk_ids
28
43
 
29
44
  def initialize
30
45
  super
31
- @responses = []
46
+ @sent_chunk_ids = []
47
+ @response_chunk_ids = []
32
48
  @exceptions = []
33
49
  end
34
50
 
35
- def send_data(node, tag, chunk)
36
- # Original #send_data returns nil when it does not wait for responses or when on response timeout.
37
- @responses << super(node, tag, chunk)
51
+ def try_write(chunk)
52
+ retval = super
53
+ @sent_chunk_ids << chunk.unique_id
54
+ retval
55
+ end
56
+
57
+ def read_ack_from_sock(sock, unpacker)
58
+ retval = super
59
+ @response_chunk_ids << retval
60
+ retval
38
61
  rescue => e
39
62
  @exceptions << e
40
63
  raise e
41
64
  end
42
-
43
- # Fluentd v0.12 BufferedOutputTestDriver calls this method.
44
- # BufferedOutput#format_stream calls format method, but ForwardOutput#format is not defined.
45
- # Because ObjectBufferedOutput#emit calls es.to_msgpack_stream directly.
46
- def format_stream(tag, es)
47
- es.to_msgpack_stream
48
- end
49
65
  }.configure(conf)
50
66
  end
51
67
 
52
- def test_configure
53
- d = create_driver
68
+ test 'configure' do
69
+ @d = d = create_driver(%[
70
+ self_hostname localhost
71
+ <server>
72
+ name test
73
+ host #{TARGET_HOST}
74
+ port #{TARGET_PORT}
75
+ </server>
76
+ ])
54
77
  nodes = d.instance.nodes
55
- assert_equal 51, d.instance.send_timeout
56
- assert_equal :udp, d.instance.heartbeat_type
78
+ assert_equal 60, d.instance.send_timeout
79
+ assert_equal :transport, d.instance.heartbeat_type
57
80
  assert_equal 1, nodes.length
81
+ assert_nil d.instance.connect_timeout
58
82
  node = nodes.first
59
83
  assert_equal "test", node.name
60
84
  assert_equal '127.0.0.1', node.host
61
- assert_equal 13999, node.port
85
+ assert_equal TARGET_PORT, node.port
86
+ end
87
+
88
+ test 'configure_traditional' do
89
+ @d = d = create_driver(<<EOL)
90
+ self_hostname localhost
91
+ <server>
92
+ name test
93
+ host #{TARGET_HOST}
94
+ port #{TARGET_PORT}
95
+ </server>
96
+ buffer_chunk_limit 10m
97
+ EOL
98
+ instance = d.instance
99
+ assert instance.chunk_key_tag
100
+ assert !instance.chunk_key_time
101
+ assert_equal [], instance.chunk_keys
102
+ assert{ instance.buffer.is_a?(Fluent::Plugin::MemoryBuffer) }
103
+ assert_equal( 10*1024*1024, instance.buffer.chunk_limit_size )
104
+ end
105
+
106
+ test 'configure timeouts' do
107
+ @d = d = create_driver(%[
108
+ send_timeout 30
109
+ connect_timeout 10
110
+ hard_timeout 15
111
+ ack_response_timeout 20
112
+ <server>
113
+ host #{TARGET_HOST}
114
+ port #{TARGET_PORT}
115
+ </server>
116
+ ])
117
+ assert_equal 30, d.instance.send_timeout
118
+ assert_equal 10, d.instance.connect_timeout
119
+ assert_equal 15, d.instance.hard_timeout
120
+ assert_equal 20, d.instance.ack_response_timeout
62
121
  end
63
122
 
64
- def test_configure_tcp_heartbeat
65
- d = create_driver(CONFIG + "\nheartbeat_type tcp")
66
- assert_equal :tcp, d.instance.heartbeat_type
123
+ test 'configure_udp_heartbeat' do
124
+ @d = d = create_driver(CONFIG + "\nheartbeat_type udp")
125
+ assert_equal :udp, d.instance.heartbeat_type
67
126
  end
68
127
 
69
- def test_configure_none_heartbeat
70
- d = create_driver(CONFIG + "\nheartbeat_type none")
128
+ test 'configure_none_heartbeat' do
129
+ @d = d = create_driver(CONFIG + "\nheartbeat_type none")
71
130
  assert_equal :none, d.instance.heartbeat_type
72
131
  end
73
132
 
74
- def test_configure_dns_round_robin
133
+ test 'configure_expire_dns_cache' do
134
+ @d = d = create_driver(CONFIG + "\nexpire_dns_cache 5")
135
+ assert_equal 5, d.instance.expire_dns_cache
136
+ end
137
+
138
+ test 'configure_dns_round_robin udp' do
75
139
  assert_raise(Fluent::ConfigError) do
76
140
  create_driver(CONFIG + "\nheartbeat_type udp\ndns_round_robin true")
77
141
  end
142
+ end
78
143
 
79
- d = create_driver(CONFIG + "\nheartbeat_type tcp\ndns_round_robin true")
144
+ test 'configure_dns_round_robin transport' do
145
+ @d = d = create_driver(CONFIG + "\nheartbeat_type transport\ndns_round_robin true")
80
146
  assert_equal true, d.instance.dns_round_robin
81
- assert_equal true, d.instance.nodes.first.conf.dns_round_robin
147
+ end
82
148
 
83
- d = create_driver(CONFIG + "\nheartbeat_type none\ndns_round_robin true")
149
+ test 'configure_dns_round_robin none' do
150
+ @d = d = create_driver(CONFIG + "\nheartbeat_type none\ndns_round_robin true")
84
151
  assert_equal true, d.instance.dns_round_robin
85
- assert_equal true, d.instance.nodes.first.conf.dns_round_robin
86
152
  end
87
153
 
88
- def test_configure_no_server
154
+ test 'configure_no_server' do
89
155
  assert_raise(Fluent::ConfigError, 'forward output plugin requires at least one <server> is required') do
90
156
  create_driver('')
91
157
  end
92
158
  end
93
159
 
94
- def test_phi_failure_detector
95
- d = create_driver(CONFIG + %[phi_failure_detector false \n phi_threshold 0])
160
+ test 'configure with ignore_network_errors_at_startup' do
161
+ normal_conf = config_element('match', '**', {}, [
162
+ config_element('server', '', {'name' => 'test', 'host' => 'unexisting.yaaaaaaaaaaaaaay.host.example.com'})
163
+ ])
164
+ assert_raise SocketError do
165
+ create_driver(normal_conf)
166
+ end
167
+
168
+ conf = config_element('match', '**', {'ignore_network_errors_at_startup' => 'true'}, [
169
+ config_element('server', '', {'name' => 'test', 'host' => 'unexisting.yaaaaaaaaaaaaaay.host.example.com'})
170
+ ])
171
+ @d = d = create_driver(conf)
172
+ expected_log = "failed to resolve node name when configured"
173
+ expected_detail = 'server="test" error_class=SocketError'
174
+ logs = d.logs
175
+ assert{ logs.any?{|log| log.include?(expected_log) && log.include?(expected_detail) } }
176
+ end
177
+
178
+ data('CA cert' => 'tls_ca_cert_path',
179
+ 'non CA cert' => 'tls_cert_path')
180
+ test 'configure tls_cert_path/tls_ca_cert_path' do |param|
181
+ dummy_cert_path = File.join(TMP_DIR, "dummy_cert.pem")
182
+ FileUtils.touch(dummy_cert_path)
183
+ conf = %[
184
+ send_timeout 5
185
+ transport tls
186
+ tls_insecure_mode true
187
+ #{param} #{dummy_cert_path}
188
+ <server>
189
+ host #{TARGET_HOST}
190
+ port #{TARGET_PORT}
191
+ </server>
192
+ ]
193
+
194
+ @d = d = create_driver(conf)
195
+ # In the plugin, tls_ca_cert_path is used for both cases
196
+ assert_equal([dummy_cert_path], d.instance.tls_ca_cert_path)
197
+ end
198
+
199
+ test 'compress_default_value' do
200
+ @d = d = create_driver
201
+ assert_equal :text, d.instance.compress
202
+
203
+ node = d.instance.nodes.first
204
+ assert_equal :text, node.instance_variable_get(:@compress)
205
+ end
206
+
207
+ test 'set_compress_is_gzip' do
208
+ @d = d = create_driver(CONFIG + %[compress gzip])
209
+ assert_equal :gzip, d.instance.compress
210
+ assert_equal :gzip, d.instance.buffer.compress
211
+
212
+ node = d.instance.nodes.first
213
+ assert_equal :gzip, node.instance_variable_get(:@compress)
214
+ end
215
+
216
+ test 'set_compress_is_gzip_in_buffer_section' do
217
+ mock = flexmock($log)
218
+ mock.should_receive(:log).with("buffer is compressed. If you also want to save the bandwidth of a network, Add `compress` configuration in <match>")
219
+
220
+ @d = d = create_driver(CONFIG + %[
221
+ <buffer>
222
+ type memory
223
+ compress gzip
224
+ </buffer>
225
+ ])
226
+ assert_equal :text, d.instance.compress
227
+ assert_equal :gzip, d.instance.buffer.compress
228
+
229
+ node = d.instance.nodes.first
230
+ assert_equal :text, node.instance_variable_get(:@compress)
231
+ end
232
+
233
+ test 'phi_failure_detector disabled' do
234
+ @d = d = create_driver(CONFIG + %[phi_failure_detector false \n phi_threshold 0])
96
235
  node = d.instance.nodes.first
97
236
  stub(node.failure).phi { raise 'Should not be called' }
98
237
  node.tick
99
238
  assert_equal node.available, true
239
+ end
100
240
 
101
- d = create_driver(CONFIG + %[phi_failure_detector true \n phi_threshold 0])
241
+ test 'phi_failure_detector enabled' do
242
+ @d = d = create_driver(CONFIG + %[phi_failure_detector true \n phi_threshold 0])
102
243
  node = d.instance.nodes.first
103
244
  node.tick
104
245
  assert_equal node.available, false
105
246
  end
106
247
 
107
- def test_wait_response_timeout_config
108
- d = create_driver(CONFIG)
109
- assert_equal false, d.instance.extend_internal_protocol
248
+ test 'require_ack_response is disabled in default' do
249
+ @d = d = create_driver(CONFIG)
110
250
  assert_equal false, d.instance.require_ack_response
111
251
  assert_equal 190, d.instance.ack_response_timeout
252
+ end
112
253
 
113
- d = create_driver(CONFIG + %[
254
+ test 'require_ack_response can be enabled' do
255
+ @d = d = create_driver(CONFIG + %[
114
256
  require_ack_response true
115
257
  ack_response_timeout 2s
116
258
  ])
117
- assert d.instance.extend_internal_protocol
118
259
  assert d.instance.require_ack_response
119
260
  assert_equal 2, d.instance.ack_response_timeout
120
261
  end
121
262
 
122
- def test_send_to_a_node_supporting_responses
123
- target_input_driver = create_target_input_driver(true)
263
+ test 'verify_connection_at_startup is disabled in default' do
264
+ @d = d = create_driver(CONFIG)
265
+ assert_false d.instance.verify_connection_at_startup
266
+ end
267
+
268
+ test 'verify_connection_at_startup can be enabled' do
269
+ @d = d = create_driver(CONFIG + %[
270
+ verify_connection_at_startup true
271
+ ])
272
+ assert_true d.instance.verify_connection_at_startup
273
+ end
124
274
 
125
- d = create_driver(CONFIG + %[flush_interval 1s])
275
+ test 'send tags in str (utf-8 strings)' do
276
+ target_input_driver = create_target_input_driver
126
277
 
127
- time = Time.parse("2011-01-02 13:14:15 UTC").to_i
278
+ @d = d = create_driver(CONFIG + %[flush_interval 1s])
128
279
 
129
- records = [
130
- {"a" => 1},
131
- {"a" => 2}
280
+ time = event_time("2011-01-02 13:14:15 UTC")
281
+
282
+ tag_in_utf8 = "test.utf8".encode("utf-8")
283
+ tag_in_ascii = "test.ascii".encode("ascii-8bit")
284
+
285
+ emit_events = [
286
+ [tag_in_utf8, time, {"a" => 1}],
287
+ [tag_in_ascii, time, {"a" => 2}],
132
288
  ]
133
- d.register_run_post_condition do
134
- d.instance.responses.length == 1
135
- end
136
289
 
137
- target_input_driver.run do
290
+ target_input_driver.run(expect_records: 2) do
138
291
  d.run do
139
- records.each do |record|
140
- d.emit record, time
292
+ emit_events.each do |tag, t, record|
293
+ d.feed(tag, t, record)
141
294
  end
142
295
  end
143
296
  end
144
297
 
145
- emits = target_input_driver.emits
146
- assert_equal ['test', time, records[0]], emits[0]
147
- assert_equal ['test', time, records[1]], emits[1]
298
+ events = target_input_driver.events
299
+ assert_equal_event_time(time, events[0][1])
300
+ assert_equal ['test.utf8', time, emit_events[0][2]], events[0]
301
+ assert_equal Encoding::UTF_8, events[0][0].encoding
302
+ assert_equal_event_time(time, events[1][1])
303
+ assert_equal ['test.ascii', time, emit_events[1][2]], events[1]
304
+ assert_equal Encoding::UTF_8, events[1][0].encoding
148
305
 
149
- assert_equal [nil], d.instance.responses # not attempt to receive responses, so nil is returned
150
306
  assert_empty d.instance.exceptions
151
307
  end
152
308
 
153
- def test_send_to_a_node_not_supporting_responses
309
+ test 'send_with_time_as_integer' do
154
310
  target_input_driver = create_target_input_driver
155
311
 
156
- d = create_driver(CONFIG + %[flush_interval 1s])
312
+ @d = d = create_driver(CONFIG + %[flush_interval 1s])
157
313
 
158
- time = Time.parse("2011-01-02 13:14:15 UTC").to_i
314
+ time = event_time("2011-01-02 13:14:15 UTC")
159
315
 
160
316
  records = [
161
317
  {"a" => 1},
162
318
  {"a" => 2}
163
319
  ]
164
- d.register_run_post_condition do
165
- d.instance.responses.length == 1
320
+ target_input_driver.run(expect_records: 2) do
321
+ d.run(default_tag: 'test') do
322
+ records.each do |record|
323
+ d.feed(time, record)
324
+ end
325
+ end
166
326
  end
167
327
 
168
- target_input_driver.run do
169
- d.run do
328
+ events = target_input_driver.events
329
+ assert_equal_event_time(time, events[0][1])
330
+ assert_equal ['test', time, records[0]], events[0]
331
+ assert_equal_event_time(time, events[1][1])
332
+ assert_equal ['test', time, records[1]], events[1]
333
+
334
+ assert_empty d.instance.exceptions
335
+ end
336
+
337
+ test 'send_without_time_as_integer' do
338
+ target_input_driver = create_target_input_driver
339
+
340
+ @d = d = create_driver(CONFIG + %[
341
+ flush_interval 1s
342
+ time_as_integer false
343
+ ])
344
+
345
+ time = event_time("2011-01-02 13:14:15 UTC")
346
+
347
+ records = [
348
+ {"a" => 1},
349
+ {"a" => 2}
350
+ ]
351
+ target_input_driver.run(expect_records: 2) do
352
+ d.run(default_tag: 'test') do
170
353
  records.each do |record|
171
- d.emit record, time
354
+ d.feed(time, record)
172
355
  end
173
356
  end
174
357
  end
175
358
 
176
- emits = target_input_driver.emits
177
- assert_equal ['test', time, records[0]], emits[0]
178
- assert_equal ['test', time, records[1]], emits[1]
359
+ events = target_input_driver.events
360
+ assert_equal_event_time(time, events[0][1])
361
+ assert_equal ['test', time, records[0]], events[0]
362
+ assert_equal_event_time(time, events[1][1])
363
+ assert_equal ['test', time, records[1]], events[1]
179
364
 
180
- assert_equal [nil], d.instance.responses # not attempt to receive responses, so nil is returned
181
365
  assert_empty d.instance.exceptions
182
366
  end
183
367
 
184
- def test_require_a_node_supporting_responses_to_respond_with_ack
185
- target_input_driver = create_target_input_driver(true)
368
+ test 'send_comprssed_message_pack_stream_if_compress_is_gzip' do
369
+ target_input_driver = create_target_input_driver
186
370
 
187
- d = create_driver(CONFIG + %[
371
+ @d = d = create_driver(CONFIG + %[
188
372
  flush_interval 1s
189
- require_ack_response true
190
- ack_response_timeout 1s
373
+ compress gzip
191
374
  ])
192
375
 
193
- time = Time.parse("2011-01-02 13:14:15 UTC").to_i
376
+ time = event_time('2011-01-02 13:14:15 UTC')
194
377
 
195
378
  records = [
196
379
  {"a" => 1},
197
380
  {"a" => 2}
198
381
  ]
199
- d.register_run_post_condition do
200
- d.instance.responses.length == 1
382
+ target_input_driver.run(expect_records: 2) do
383
+ d.run(default_tag: 'test') do
384
+ records.each do |record|
385
+ d.feed(time, record)
386
+ end
387
+ end
201
388
  end
202
389
 
203
- target_input_driver.run do
204
- d.run do
390
+ event_streams = target_input_driver.event_streams
391
+ assert_true event_streams[0][1].is_a?(Fluent::CompressedMessagePackEventStream)
392
+
393
+ events = target_input_driver.events
394
+ assert_equal ['test', time, records[0]], events[0]
395
+ assert_equal ['test', time, records[1]], events[1]
396
+ end
397
+
398
+ test 'send_to_a_node_supporting_responses' do
399
+ target_input_driver = create_target_input_driver
400
+
401
+ @d = d = create_driver(CONFIG + %[flush_interval 1s])
402
+
403
+ time = event_time("2011-01-02 13:14:15 UTC")
404
+
405
+ records = [
406
+ {"a" => 1},
407
+ {"a" => 2}
408
+ ]
409
+ target_input_driver.run(expect_records: 2) do
410
+ d.run(default_tag: 'test') do
205
411
  records.each do |record|
206
- d.emit record, time
412
+ d.feed(time, record)
207
413
  end
208
414
  end
209
415
  end
210
416
 
211
- emits = target_input_driver.emits
212
- assert_equal ['test', time, records[0]], emits[0]
213
- assert_equal ['test', time, records[1]], emits[1]
417
+ events = target_input_driver.events
418
+ assert_equal ['test', time, records[0]], events[0]
419
+ assert_equal ['test', time, records[1]], events[1]
214
420
 
215
- assert_equal 1, d.instance.responses.length
216
- assert d.instance.responses[0].has_key?('ack')
421
+ assert_empty d.instance.response_chunk_ids # not attempt to receive responses, so it's empty
217
422
  assert_empty d.instance.exceptions
218
423
  end
219
424
 
220
- def test_require_a_node_not_supporting_responses_to_respond_with_ack
221
- # in_forward, that doesn't support ack feature, and keep connection alive
425
+ test 'send_to_a_node_not_supporting_responses' do
222
426
  target_input_driver = create_target_input_driver
223
427
 
224
- d = create_driver(CONFIG + %[
225
- flush_interval 1s
428
+ @d = d = create_driver(CONFIG + %[flush_interval 1s])
429
+
430
+ time = event_time("2011-01-02 13:14:15 UTC")
431
+
432
+ records = [
433
+ {"a" => 1},
434
+ {"a" => 2}
435
+ ]
436
+ target_input_driver.run(expect_records: 2) do
437
+ d.run(default_tag: 'test') do
438
+ records.each do |record|
439
+ d.feed(time, record)
440
+ end
441
+ end
442
+ end
443
+
444
+ events = target_input_driver.events
445
+ assert_equal ['test', time, records[0]], events[0]
446
+ assert_equal ['test', time, records[1]], events[1]
447
+
448
+ assert_empty d.instance.response_chunk_ids # not attempt to receive responses, so it's empty
449
+ assert_empty d.instance.exceptions
450
+ end
451
+
452
+ test 'a node supporting responses' do
453
+ target_input_driver = create_target_input_driver
454
+
455
+ @d = d = create_driver(CONFIG + %[
226
456
  require_ack_response true
227
457
  ack_response_timeout 1s
458
+ <buffer tag>
459
+ flush_mode immediate
460
+ retry_type periodic
461
+ retry_wait 30s
462
+ flush_at_shutdown false # suppress errors in d.instance_shutdown
463
+ </buffer>
228
464
  ])
229
465
 
230
- time = Time.parse("2011-01-02 13:14:15 UTC").to_i
466
+ time = event_time("2011-01-02 13:14:15 UTC")
231
467
 
232
468
  records = [
233
469
  {"a" => 1},
234
470
  {"a" => 2}
235
471
  ]
236
- d.register_run_post_condition do
237
- d.instance.responses.length == 1
472
+ target_input_driver.run(expect_records: 2) do
473
+ d.end_if{ d.instance.response_chunk_ids.length > 0 }
474
+ d.run(default_tag: 'test', wait_flush_completion: false, shutdown: false) do
475
+ d.feed([[time, records[0]], [time,records[1]]])
476
+ end
238
477
  end
239
- d.run_timeout = 2
240
478
 
241
- assert_raise Fluent::ForwardOutputACKTimeoutError do
242
- target_input_driver.run do
243
- d.run do
244
- records.each do |record|
245
- d.emit record, time
246
- end
479
+ events = target_input_driver.events
480
+ assert_equal ['test', time, records[0]], events[0]
481
+ assert_equal ['test', time, records[1]], events[1]
482
+
483
+ assert_equal 1, d.instance.response_chunk_ids.size
484
+ assert_equal d.instance.sent_chunk_ids.first, d.instance.response_chunk_ids.first
485
+ assert_empty d.instance.exceptions
486
+ end
487
+
488
+ data('ack true' => true,
489
+ 'ack false' => false)
490
+ test 'TLS transport and ack parameter combination' do |ack|
491
+ omit "TLS and 'ack false' always fails on AppVeyor. Need to debug" if Fluent.windows? && !ack
492
+
493
+ input_conf = TARGET_CONFIG + %[
494
+ <transport tls>
495
+ insecure true
496
+ </transport>
497
+ ]
498
+ target_input_driver = create_target_input_driver(conf: input_conf)
499
+
500
+ output_conf = %[
501
+ send_timeout 5
502
+ require_ack_response #{ack}
503
+ transport tls
504
+ tls_insecure_mode true
505
+ <server>
506
+ host #{TARGET_HOST}
507
+ port #{TARGET_PORT}
508
+ </server>
509
+ <buffer>
510
+ #flush_mode immediate
511
+ flush_interval 0s
512
+ flush_at_shutdown false # suppress errors in d.instance_shutdown
513
+ </buffer>
514
+ ]
515
+ @d = d = create_driver(output_conf)
516
+
517
+ time = event_time("2011-01-02 13:14:15 UTC")
518
+ records = [{"a" => 1}, {"a" => 2}]
519
+ target_input_driver.run(expect_records: 2, timeout: 3) do
520
+ d.run(default_tag: 'test', wait_flush_completion: false, shutdown: false) do
521
+ records.each do |record|
522
+ d.feed(time, record)
247
523
  end
248
524
  end
249
525
  end
250
526
 
251
- emits = target_input_driver.emits
252
- assert_equal ['test', time, records[0]], emits[0]
253
- assert_equal ['test', time, records[1]], emits[1]
527
+ events = target_input_driver.events
528
+ assert{ events != [] }
529
+ assert_equal(['test', time, records[0]], events[0])
530
+ assert_equal(['test', time, records[1]], events[1])
531
+ end
532
+
533
+ test 'a destination node not supporting responses by just ignoring' do
534
+ target_input_driver = create_target_input_driver(response_stub: ->(_option) { nil }, disconnect: false)
535
+
536
+ @d = d = create_driver(CONFIG + %[
537
+ require_ack_response true
538
+ ack_response_timeout 1s
539
+ <buffer tag>
540
+ flush_mode immediate
541
+ retry_type periodic
542
+ retry_wait 30s
543
+ flush_at_shutdown false # suppress errors in d.instance_shutdown
544
+ flush_thread_interval 30s
545
+ </buffer>
546
+ ])
254
547
 
255
548
  node = d.instance.nodes.first
256
- assert_equal false, node.available # node is regarded as unavailable when timeout
549
+ delayed_commit_timeout_value = nil
550
+
551
+ time = event_time("2011-01-02 13:14:15 UTC")
552
+
553
+ records = [
554
+ {"a" => 1},
555
+ {"a" => 2}
556
+ ]
557
+ target_input_driver.end_if{ d.instance.rollback_count > 0 }
558
+ target_input_driver.end_if{ !node.available }
559
+ target_input_driver.run(expect_records: 2, timeout: 25) do
560
+ d.run(default_tag: 'test', timeout: 20, wait_flush_completion: false, shutdown: false, flush: false) do
561
+ delayed_commit_timeout_value = d.instance.delayed_commit_timeout
562
+ d.feed([[time, records[0]], [time,records[1]]])
563
+ end
564
+ end
565
+
566
+ assert_equal (1 + 2), delayed_commit_timeout_value
567
+
568
+ events = target_input_driver.events
569
+ assert_equal ['test', time, records[0]], events[0]
570
+ assert_equal ['test', time, records[1]], events[1]
257
571
 
258
- assert_empty d.instance.responses # send_data() raises exception, so response is missing
259
- assert_equal 1, d.instance.exceptions.size
572
+ assert{ d.instance.rollback_count > 0 }
573
+
574
+ logs = d.instance.log.logs
575
+ assert{ logs.any?{|log| log.include?("no response from node. regard it as unavailable.") } }
260
576
  end
261
577
 
262
- # bdf1f4f104c00a791aa94dc20087fe2011e1fd83
263
- def test_require_a_node_not_supporting_responses_2_to_respond_with_ack
264
- # in_forward, that doesn't support ack feature, and disconnect immediately
265
- target_input_driver = create_target_input_driver(false, true)
578
+ test 'a destination node not supporting responses by disconnection' do
579
+ target_input_driver = create_target_input_driver(response_stub: ->(_option) { nil }, disconnect: true)
266
580
 
267
- d = create_driver(CONFIG + %[
268
- flush_interval 1s
581
+ @d = d = create_driver(CONFIG + %[
269
582
  require_ack_response true
270
583
  ack_response_timeout 5s
584
+ <buffer tag>
585
+ flush_mode immediate
586
+ retry_type periodic
587
+ retry_wait 30s
588
+ flush_at_shutdown false # suppress errors in d.instance_shutdown
589
+ flush_thread_interval 30s
590
+ </buffer>
271
591
  ])
272
592
 
273
- time = Time.parse("2011-01-02 13:14:15 UTC").to_i
593
+ node = d.instance.nodes.first
594
+ delayed_commit_timeout_value = nil
595
+
596
+ time = event_time("2011-01-02 13:14:15 UTC")
274
597
 
275
598
  records = [
276
599
  {"a" => 1},
277
600
  {"a" => 2}
278
601
  ]
279
- d.register_run_post_condition do
280
- d.instance.responses.length == 1
602
+ target_input_driver.end_if{ d.instance.rollback_count > 0 }
603
+ target_input_driver.end_if{ !node.available }
604
+ target_input_driver.run(expect_records: 2, timeout: 25) do
605
+ d.run(default_tag: 'test', timeout: 20, wait_flush_completion: false, shutdown: false, flush: false) do
606
+ delayed_commit_timeout_value = d.instance.delayed_commit_timeout
607
+ d.feed([[time, records[0]], [time,records[1]]])
608
+ end
281
609
  end
282
- d.run_timeout = 2
283
610
 
284
- assert_raise Fluent::ForwardOutputConnectionClosedError do
285
- target_input_driver.run do
286
- d.run do
287
- records.each do |record|
288
- d.emit record, time
289
- end
611
+ assert_equal (5 + 2), delayed_commit_timeout_value
612
+
613
+ events = target_input_driver.events
614
+ assert_equal ['test', time, records[0]], events[0]
615
+ assert_equal ['test', time, records[1]], events[1]
616
+
617
+ assert{ d.instance.rollback_count > 0 }
618
+
619
+ logs = d.instance.log.logs
620
+ assert{ logs.any?{|log| log.include?("no response from node. regard it as unavailable.") } }
621
+ end
622
+
623
+ test 'authentication_with_shared_key' do
624
+ input_conf = TARGET_CONFIG + %[
625
+ <security>
626
+ self_hostname in.localhost
627
+ shared_key fluentd-sharedkey
628
+ <client>
629
+ host 127.0.0.1
630
+ </client>
631
+ </security>
632
+ ]
633
+ target_input_driver = create_target_input_driver(conf: input_conf)
634
+
635
+ output_conf = %[
636
+ send_timeout 51
637
+ <security>
638
+ self_hostname localhost
639
+ shared_key fluentd-sharedkey
640
+ </security>
641
+ <server>
642
+ name test
643
+ host #{TARGET_HOST}
644
+ port #{TARGET_PORT}
645
+ shared_key fluentd-sharedkey
646
+ </server>
647
+ ]
648
+ @d = d = create_driver(output_conf)
649
+
650
+ time = event_time("2011-01-02 13:14:15 UTC")
651
+ records = [
652
+ {"a" => 1},
653
+ {"a" => 2}
654
+ ]
655
+
656
+ target_input_driver.run(expect_records: 2, timeout: 15) do
657
+ d.run(default_tag: 'test') do
658
+ records.each do |record|
659
+ d.feed(time, record)
290
660
  end
291
661
  end
292
662
  end
293
663
 
294
- emits = target_input_driver.emits
295
- assert_equal ['test', time, records[0]], emits[0]
296
- assert_equal ['test', time, records[1]], emits[1]
664
+ events = target_input_driver.events
665
+ assert{ events != [] }
666
+ assert_equal(['test', time, records[0]], events[0])
667
+ assert_equal(['test', time, records[1]], events[1])
668
+ end
297
669
 
298
- assert_equal 0, d.instance.responses.size
299
- assert_equal 1, d.instance.exceptions.size # send_data() fails and to be retried
670
+ test 'keepalive + shared_key' do
671
+ input_conf = TARGET_CONFIG + %[
672
+ <security>
673
+ self_hostname in.localhost
674
+ shared_key fluentd-sharedkey
675
+ </security>
676
+ ]
677
+ target_input_driver = create_target_input_driver(conf: input_conf)
678
+
679
+ output_conf = %[
680
+ send_timeout 51
681
+ keepalive true
682
+ <security>
683
+ self_hostname localhost
684
+ shared_key fluentd-sharedkey
685
+ </security>
686
+ <server>
687
+ name test
688
+ host #{TARGET_HOST}
689
+ port #{TARGET_PORT}
690
+ </server>
691
+ ]
692
+ @d = d = create_driver(output_conf)
300
693
 
301
- node = d.instance.nodes.first
302
- assert_equal false, node.available # node is regarded as unavailable when unexpected EOF
694
+ time = event_time('2011-01-02 13:14:15 UTC')
695
+ records = [{ 'a' => 1 }, { 'a' => 2 }]
696
+ records2 = [{ 'b' => 1}, { 'b' => 2}]
697
+ target_input_driver.run(expect_records: 4, timeout: 15) do
698
+ d.run(default_tag: 'test') do
699
+ records.each do |record|
700
+ d.feed(time, record)
701
+ end
702
+
703
+ d.flush # emit buffer to reuse same socket later
704
+ records2.each do |record|
705
+ d.feed(time, record)
706
+ end
707
+ end
708
+ end
709
+
710
+ events = target_input_driver.events
711
+ assert{ events != [] }
712
+ assert_equal(['test', time, records[0]], events[0])
713
+ assert_equal(['test', time, records[1]], events[1])
714
+ assert_equal(['test', time, records2[0]], events[2])
715
+ assert_equal(['test', time, records2[1]], events[3])
303
716
  end
304
717
 
305
- def create_target_input_driver(do_respond=false, disconnect=false, conf=TARGET_CONFIG)
718
+ test 'authentication_with_user_auth' do
719
+ input_conf = TARGET_CONFIG + %[
720
+ <security>
721
+ self_hostname in.localhost
722
+ shared_key fluentd-sharedkey
723
+ user_auth true
724
+ <user>
725
+ username fluentd
726
+ password fluentd
727
+ </user>
728
+ <client>
729
+ host 127.0.0.1
730
+ </client>
731
+ </security>
732
+ ]
733
+ target_input_driver = create_target_input_driver(conf: input_conf)
734
+
735
+ output_conf = %[
736
+ send_timeout 51
737
+ <security>
738
+ self_hostname localhost
739
+ shared_key fluentd-sharedkey
740
+ </security>
741
+ <server>
742
+ name test
743
+ host #{TARGET_HOST}
744
+ port #{TARGET_PORT}
745
+ shared_key fluentd-sharedkey
746
+ username fluentd
747
+ password fluentd
748
+ </server>
749
+ ]
750
+ @d = d = create_driver(output_conf)
751
+
752
+ time = event_time("2011-01-02 13:14:15 UTC")
753
+ records = [
754
+ {"a" => 1},
755
+ {"a" => 2}
756
+ ]
757
+
758
+ target_input_driver.run(expect_records: 2, timeout: 15) do
759
+ d.run(default_tag: 'test') do
760
+ records.each do |record|
761
+ d.feed(time, record)
762
+ end
763
+ end
764
+ end
765
+
766
+ events = target_input_driver.events
767
+ assert{ events != [] }
768
+ assert_equal(['test', time, records[0]], events[0])
769
+ assert_equal(['test', time, records[1]], events[1])
770
+ end
771
+
772
+ # This test is not 100% but test failed with previous Node implementation which has race condition
773
+ test 'Node with security is thread-safe on multi threads' do
774
+ input_conf = TARGET_CONFIG + %[
775
+ <security>
776
+ self_hostname in.localhost
777
+ shared_key fluentd-sharedkey
778
+ <client>
779
+ host 127.0.0.1
780
+ </client>
781
+ </security>
782
+ ]
783
+ target_input_driver = create_target_input_driver(conf: input_conf)
784
+ output_conf = %[
785
+ send_timeout 51
786
+ <security>
787
+ self_hostname localhost
788
+ shared_key fluentd-sharedkey
789
+ </security>
790
+ <server>
791
+ name test
792
+ host #{TARGET_HOST}
793
+ port #{TARGET_PORT}
794
+ shared_key fluentd-sharedkey
795
+ </server>
796
+ ]
797
+ @d = d = create_driver(output_conf)
798
+
799
+ chunk = Fluent::Plugin::Buffer::MemoryChunk.new(Fluent::Plugin::Buffer::Metadata.new(nil, nil, nil))
800
+ target_input_driver.run(timeout: 15) do
801
+ d.run(shutdown: false) do
802
+ node = d.instance.nodes.first
803
+ arr = []
804
+ 4.times {
805
+ arr << Thread.new {
806
+ node.send_data('test', chunk) rescue nil
807
+ }
808
+ }
809
+ arr.each { |a| a.join }
810
+ end
811
+ end
812
+
813
+ logs = d.logs
814
+ assert_false(logs.any? { |log| log.include?("invalid format for PONG message") || log.include?("shared key mismatch") }, "'#{logs.last.strip}' happens")
815
+ end
816
+
817
+ def create_target_input_driver(response_stub: nil, disconnect: false, conf: TARGET_CONFIG)
306
818
  require 'fluent/plugin/in_forward'
307
819
 
308
- DummyEngineDriver.new(Fluent::ForwardInput) {
309
- handler_class = Class.new(Fluent::ForwardInput::Handler) { |klass|
310
- attr_reader :chunk_counter # for checking if received data is successfully deserialized
820
+ # TODO: Support actual TCP heartbeat test
821
+ Fluent::Test::Driver::Input.new(Fluent::Plugin::ForwardInput) {
822
+ if response_stub.nil?
823
+ # do nothing because in_forward responds for ack option in default
824
+ else
825
+ define_method(:response) do |options|
826
+ return response_stub.(options)
827
+ end
828
+ end
829
+ }.configure(conf)
830
+ end
831
+
832
+ test 'heartbeat_type_none' do
833
+ @d = d = create_driver(CONFIG + "\nheartbeat_type none")
834
+ node = d.instance.nodes.first
835
+ assert_equal Fluent::Plugin::ForwardOutput::NoneHeartbeatNode, node.class
836
+
837
+ d.instance_start
838
+ assert_nil d.instance.instance_variable_get(:@loop) # no HeartbeatHandler, or HeartbeatRequestTimer
839
+ assert_nil d.instance.instance_variable_get(:@thread) # no HeartbeatHandler, or HeartbeatRequestTimer
840
+
841
+ stub(node.failure).phi { raise 'Should not be called' }
842
+ node.tick
843
+ assert_equal node.available, true
844
+ end
845
+
846
+ test 'heartbeat_type_udp' do
847
+ @d = d = create_driver(CONFIG + "\nheartbeat_type udp")
848
+
849
+ d.instance_start
850
+ usock = d.instance.instance_variable_get(:@usock)
851
+ servers = d.instance.instance_variable_get(:@_servers)
852
+ timers = d.instance.instance_variable_get(:@_timers)
853
+ assert_equal Fluent::PluginHelper::Socket::WrappedSocket::UDP, usock.class
854
+ assert_kind_of UDPSocket, usock
855
+ assert servers.find{|s| s.title == :out_forward_heartbeat_receiver }
856
+ assert timers.include?(:out_forward_heartbeat_request)
311
857
 
312
- def initialize(sock, log, on_message)
313
- @sock = sock
314
- @log = log
315
- @chunk_counter = 0
316
- @on_message = on_message
858
+ mock(usock).send("\0", 0, Socket.pack_sockaddr_in(TARGET_PORT, '127.0.0.1')).once
859
+ d.instance.send(:on_timer)
860
+ end
861
+
862
+ test 'acts_as_secondary' do
863
+ i = Fluent::Plugin::ForwardOutput.new
864
+ conf = config_element(
865
+ 'match',
866
+ 'primary.**',
867
+ {'@type' => 'forward'},
868
+ [
869
+ config_element('server', '', {'host' => '127.0.0.1'}),
870
+ config_element('secondary', '', {}, [
871
+ config_element('server', '', {'host' => '192.168.1.2'}),
872
+ config_element('server', '', {'host' => '192.168.1.3'})
873
+ ]),
874
+ ]
875
+ )
876
+ assert_nothing_raised do
877
+ i.configure(conf)
878
+ end
879
+ end
880
+
881
+ sub_test_case 'verify_connection_at_startup' do
882
+ test 'nodes are not available' do
883
+ @d = d = create_driver(CONFIG + %[
884
+ verify_connection_at_startup true
885
+ <buffer tag>
886
+ flush_mode immediate
887
+ retry_type periodic
888
+ retry_wait 30s
889
+ flush_at_shutdown false # suppress errors in d.instance_shutdown
890
+ </buffer>
891
+ ])
892
+ assert_raise Fluent::UnrecoverableError do
893
+ d.instance_start
894
+ end
895
+ d.instance_shutdown
896
+ end
897
+
898
+ test 'nodes_shared_key_miss_match' do
899
+ input_conf = TARGET_CONFIG + %[
900
+ <security>
901
+ self_hostname in.localhost
902
+ shared_key fluentd-sharedkey
903
+ </security>
904
+ ]
905
+ target_input_driver = create_target_input_driver(conf: input_conf)
906
+ output_conf = %[
907
+ send_timeout 30
908
+ heartbeat_type transport
909
+ transport tls
910
+ tls_verify_hostname false
911
+ verify_connection_at_startup true
912
+ require_ack_response true
913
+ ack_response_timeout 5s
914
+ <security>
915
+ self_hostname localhost
916
+ shared_key key_miss_match
917
+ </security>
918
+ <buffer tag>
919
+ flush_mode immediate
920
+ retry_type periodic
921
+ retry_wait 30s
922
+ flush_at_shutdown false # suppress errors in d.instance_shutdown
923
+ flush_thread_interval 31s
924
+ </buffer>
925
+
926
+ <server>
927
+ host #{TARGET_HOST}
928
+ port #{TARGET_PORT}
929
+ </server>
930
+ ]
931
+ @d = d = create_driver(output_conf)
932
+
933
+ target_input_driver.run(expect_records: 1, timeout: 15) do
934
+ assert_raise Fluent::UnrecoverableError do
935
+ d.instance_start
317
936
  end
937
+ d.instance_shutdown
938
+ end
939
+ end
318
940
 
319
- if do_respond
320
- def write(data)
321
- @sock.write data
322
- rescue => e
323
- @sock.close
941
+ test 'nodes_shared_key_match' do
942
+ input_conf = TARGET_CONFIG + %[
943
+ <security>
944
+ self_hostname in.localhost
945
+ shared_key fluentd-sharedkey
946
+ <client>
947
+ host 127.0.0.1
948
+ </client>
949
+ </security>
950
+ ]
951
+ target_input_driver = create_target_input_driver(conf: input_conf)
952
+
953
+ output_conf = %[
954
+ send_timeout 51
955
+ verify_connection_at_startup true
956
+ <security>
957
+ self_hostname localhost
958
+ shared_key fluentd-sharedkey
959
+ </security>
960
+ <server>
961
+ name test
962
+ host #{TARGET_HOST}
963
+ port #{TARGET_PORT}
964
+ shared_key fluentd-sharedkey
965
+ </server>
966
+ ]
967
+ @d = d = create_driver(output_conf)
968
+
969
+ time = event_time("2011-01-02 13:14:15 UTC")
970
+ records = [
971
+ {"a" => 1},
972
+ {"a" => 2}
973
+ ]
974
+
975
+ target_input_driver.run(expect_records: 2, timeout: 15) do
976
+ d.run(default_tag: 'test') do
977
+ records.each do |record|
978
+ d.feed(time, record)
324
979
  end
325
- else
326
- def write(data)
327
- # do nothing
980
+ end
981
+ end
982
+
983
+ events = target_input_driver.events
984
+ assert{ events != [] }
985
+ assert_equal(['test', time, records[0]], events[0])
986
+ assert_equal(['test', time, records[1]], events[1])
987
+ end
988
+ end
989
+
990
+ test 'Create new connection per send_data' do
991
+ target_input_driver = create_target_input_driver(conf: TARGET_CONFIG)
992
+ output_conf = CONFIG
993
+ d = create_driver(output_conf)
994
+ d.instance_start
995
+
996
+ begin
997
+ chunk = Fluent::Plugin::Buffer::MemoryChunk.new(Fluent::Plugin::Buffer::Metadata.new(nil, nil, nil))
998
+ mock.proxy(d.instance).create_transfer_socket(TARGET_HOST, TARGET_PORT, 'test') { |sock| mock(sock).close.once; sock }.twice
999
+
1000
+ target_input_driver.run(timeout: 15) do
1001
+ d.run(shutdown: false) do
1002
+ node = d.instance.nodes.first
1003
+ 2.times do
1004
+ node.send_data('test', chunk) rescue nil
328
1005
  end
329
1006
  end
1007
+ end
1008
+ ensure
1009
+ d.instance_shutdown
1010
+ end
1011
+ end
330
1012
 
331
- def close
332
- unless @sock.closed?
333
- @sock.close_write
334
- @sock.close
1013
+ test 'if no available node' do
1014
+ # do not create output driver
1015
+ d = create_driver(%[
1016
+ <server>
1017
+ name test
1018
+ standby
1019
+ host #{TARGET_HOST}
1020
+ port #{TARGET_PORT}
1021
+ </server>
1022
+ ])
1023
+ d.instance_start
1024
+ assert_nothing_raised { d.run }
1025
+ end
1026
+
1027
+ sub_test_case 'keepalive' do
1028
+ test 'Do not create connection per send_data' do
1029
+ target_input_driver = create_target_input_driver(conf: TARGET_CONFIG)
1030
+ output_conf = CONFIG + %[
1031
+ keepalive true
1032
+ keepalive_timeout 2
1033
+ ]
1034
+ d = create_driver(output_conf)
1035
+ d.instance_start
1036
+
1037
+ begin
1038
+ chunk = Fluent::Plugin::Buffer::MemoryChunk.new(Fluent::Plugin::Buffer::Metadata.new(nil, nil, nil))
1039
+ mock.proxy(d.instance).create_transfer_socket(TARGET_HOST, TARGET_PORT, 'test') { |sock| mock(sock).close.once; sock }.once
1040
+
1041
+ target_input_driver.run(timeout: 15) do
1042
+ d.run(shutdown: false) do
1043
+ node = d.instance.nodes.first
1044
+ 2.times do
1045
+ node.send_data('test', chunk) rescue nil
1046
+ end
335
1047
  end
336
1048
  end
337
- }
338
-
339
- define_method(:start) do
340
- @thread = Thread.new do
341
- Socket.tcp_server_loop(@host, @port) do |sock, client_addrinfo|
342
- begin
343
- handler = handler_class.new(sock, @log, method(:on_message))
344
- loop do
345
- raw_data = sock.recv(1024)
346
- handler.on_read(raw_data)
347
- # chunk_counter is reset to zero only after all the data have been received and successfully deserialized.
348
- break if handler.chunk_counter == 0
349
- break if sock.closed?
350
- end
351
- if disconnect
352
- handler.close
353
- sock = nil
354
- end
355
- sleep # wait for connection to be closed by client
356
- ensure
357
- if sock && !sock.closed?
358
- sock.close_write
359
- sock.close
1049
+ ensure
1050
+ d.instance_shutdown
1051
+ end
1052
+ end
1053
+
1054
+ sub_test_case 'with require_ack_response' do
1055
+ test 'Do not create connection per send_data' do
1056
+ target_input_driver = create_target_input_driver(conf: TARGET_CONFIG)
1057
+ output_conf = CONFIG + %[
1058
+ require_ack_response true
1059
+ keepalive true
1060
+ keepalive_timeout 2
1061
+ ]
1062
+ d = create_driver(output_conf)
1063
+ d.instance_start
1064
+
1065
+ begin
1066
+ chunk = Fluent::Plugin::Buffer::MemoryChunk.new(Fluent::Plugin::Buffer::Metadata.new(nil, nil, nil))
1067
+ mock.proxy(d.instance).create_transfer_socket(TARGET_HOST, TARGET_PORT, 'test') { |sock| mock(sock).close.once; sock }.once
1068
+
1069
+ target_input_driver.run(timeout: 15) do
1070
+ d.run(shutdown: false) do
1071
+ node = d.instance.nodes.first
1072
+ 2.times do
1073
+ node.send_data('test', chunk) rescue nil
360
1074
  end
361
1075
  end
362
1076
  end
1077
+ ensure
1078
+ d.instance_shutdown
363
1079
  end
364
1080
  end
1081
+ end
1082
+ end
365
1083
 
366
- def shutdown
367
- @thread.kill
368
- @thread.join
1084
+ sub_test_case 'SocketCache' do
1085
+ sub_test_case 'fetch_or' do
1086
+ test 'when gived key does not exist' do
1087
+ c = Fluent::Plugin::ForwardOutput::Node::SocketCache.new(10, Logger.new(nil))
1088
+ sock = mock!.open { 1 }.subject
1089
+ assert_equal(1, c.fetch_or { sock.open })
369
1090
  end
370
- }.configure(conf).inject_router()
371
- end
372
1091
 
373
- def test_heartbeat_type_none
374
- d = create_driver(CONFIG + "\nheartbeat_type none")
375
- node = d.instance.nodes.first
376
- assert_equal Fluent::ForwardOutput::NoneHeartbeatNode, node.class
1092
+ test 'when given key exists' do
1093
+ c = Fluent::Plugin::ForwardOutput::Node::SocketCache.new(10, Logger.new(nil))
1094
+ assert_equal(1, c.fetch_or { 1 })
377
1095
 
378
- d.instance.start
379
- assert_nil d.instance.instance_variable_get(:@loop) # no HeartbeatHandler, or HeartbeatRequestTimer
380
- assert_nil d.instance.instance_variable_get(:@thread) # no HeartbeatHandler, or HeartbeatRequestTimer
1096
+ sock = dont_allow(mock!).open
1097
+ assert_equal(1, c.fetch_or { sock.open })
1098
+ end
381
1099
 
382
- stub(node.failure).phi { raise 'Should not be called' }
383
- node.tick
384
- assert_equal node.available, true
385
- end
1100
+ test "when given key's value was expired" do
1101
+ c = Fluent::Plugin::ForwardOutput::Node::SocketCache.new(0, Logger.new(nil))
1102
+ assert_equal(1, c.fetch_or { 1 })
386
1103
 
387
- class DummyEngineDriver < Fluent::Test::TestDriver
388
- def initialize(klass, &block)
389
- super(klass, &block)
390
- @engine = DummyEngineClass.new
1104
+ sock = mock!.open { 1 }.subject
1105
+ assert_equal(1, c.fetch_or { sock.open })
1106
+ end
391
1107
  end
392
1108
 
393
- def inject_router
394
- @instance.router = @engine
395
- self
1109
+ test 'revoke' do
1110
+ c = Fluent::Plugin::ForwardOutput::Node::SocketCache.new(10, Logger.new(nil))
1111
+ c.fetch_or { 1 }
1112
+ c.revoke
1113
+
1114
+ sock = mock!.open { 1 }.subject
1115
+ assert_equal(1, c.fetch_or { sock.open })
396
1116
  end
397
1117
 
398
- def run(&block)
399
- super(&block)
1118
+ test 'revoke_by_value' do
1119
+ c = Fluent::Plugin::ForwardOutput::Node::SocketCache.new(10, Logger.new(nil))
1120
+ c.fetch_or { 1 }
1121
+ c.revoke_by_value(1)
1122
+
1123
+ sock = mock!.open { 1 }.subject
1124
+ assert_equal(1, c.fetch_or { sock.open })
400
1125
  end
401
1126
 
402
- def emits
403
- all = []
404
- @engine.emit_streams.each {|tag,events|
405
- events.each {|time,record|
406
- all << [tag, time, record]
407
- }
408
- }
409
- all
1127
+ sub_test_case 'dec_ref' do
1128
+ test 'when value exists in active_socks' do
1129
+ c = Fluent::Plugin::ForwardOutput::Node::SocketCache.new(10, Logger.new(nil))
1130
+ c.fetch_or { 1 }
1131
+ c.dec_ref
1132
+
1133
+ assert_equal(0, c.instance_variable_get(:@active_socks)[Thread.current.object_id].ref)
1134
+ end
1135
+
1136
+ test 'when value exists in inactive_socks' do
1137
+ c = Fluent::Plugin::ForwardOutput::Node::SocketCache.new(10, Logger.new(nil))
1138
+ c.fetch_or { 1 }
1139
+ c.revoke
1140
+ c.dec_ref
1141
+ assert_equal(-1, c.instance_variable_get(:@inactive_socks)[Thread.current.object_id].ref)
1142
+ end
410
1143
  end
411
1144
 
412
- class DummyEngineClass
413
- attr_reader :emit_streams
1145
+ sub_test_case 'dec_ref_by_value' do
1146
+ test 'when value exists in active_socks' do
1147
+ c = Fluent::Plugin::ForwardOutput::Node::SocketCache.new(10, Logger.new(nil))
1148
+ c.fetch_or { 1 }
1149
+ c.dec_ref_by_value(1)
414
1150
 
415
- def initialize
416
- @emit_streams ||= []
1151
+ assert_equal(0, c.instance_variable_get(:@active_socks)[Thread.current.object_id].ref)
1152
+ end
1153
+
1154
+ test 'when value exists in inactive_socks' do
1155
+ c = Fluent::Plugin::ForwardOutput::Node::SocketCache.new(10, Logger.new(nil))
1156
+ c.fetch_or { 1 }
1157
+ c.revoke
1158
+ c.dec_ref_by_value(1)
1159
+ assert_equal(-1, c.instance_variable_get(:@inactive_socks)[Thread.current.object_id].ref)
1160
+ end
1161
+ end
1162
+
1163
+ sub_test_case 'clear' do
1164
+ test 'when value is in active_socks' do
1165
+ c = Fluent::Plugin::ForwardOutput::Node::SocketCache.new(10, Logger.new(nil))
1166
+ m = mock!.close { 'closed' }.subject
1167
+ c.fetch_or { m }
1168
+ assert_true(!c.instance_variable_get(:@active_socks).empty?)
1169
+
1170
+ c.clear
1171
+ assert_true(c.instance_variable_get(:@active_socks).empty?)
1172
+ end
1173
+
1174
+ test 'when value is in inactive_socks' do
1175
+ c = Fluent::Plugin::ForwardOutput::Node::SocketCache.new(10, Logger.new(nil))
1176
+ m = mock!.close { 'closed' }.subject
1177
+ c.fetch_or { m }
1178
+ c.revoke
1179
+ assert_true(!c.instance_variable_get(:@inactive_socks).empty?)
1180
+
1181
+ c.clear
1182
+ assert_true(c.instance_variable_get(:@active_socks).empty?)
1183
+ end
1184
+ end
1185
+
1186
+ sub_test_case 'purge_obsolete_socks' do
1187
+ test 'delete key in inactive_socks' do
1188
+ c = Fluent::Plugin::ForwardOutput::Node::SocketCache.new(10, Logger.new(nil))
1189
+ m = mock!.close { 'closed' }.subject
1190
+ c.fetch_or { m }
1191
+ c.revoke
1192
+ assert_true(!c.instance_variable_get(:@inactive_socks).empty?)
1193
+
1194
+ c.purge_obsolete_socks
1195
+ assert_true(c.instance_variable_get(:@active_socks).empty?)
417
1196
  end
418
1197
 
419
- def emit_stream(tag, es)
420
- @emit_streams << [tag, es.to_a]
1198
+ test 'move key from active_socks to inactive_socks' do
1199
+ c = Fluent::Plugin::ForwardOutput::Node::SocketCache.new(10, Logger.new(nil))
1200
+ m = dont_allow(mock!).close
1201
+ stub(m).inspect # for log
1202
+ c.fetch_or { m }
1203
+ assert_true(!c.instance_variable_get(:@active_socks).empty?)
1204
+ assert_true(c.instance_variable_get(:@inactive_socks).empty?)
1205
+
1206
+ c.purge_obsolete_socks
1207
+ assert_true(!c.instance_variable_get(:@active_socks).empty?)
1208
+ assert_true(c.instance_variable_get(:@inactive_socks).empty?)
421
1209
  end
422
1210
  end
423
1211
  end