fluentd 0.12.40 → 0.14.0

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 (252) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE.md +6 -0
  3. data/.gitignore +2 -0
  4. data/.travis.yml +33 -21
  5. data/CONTRIBUTING.md +1 -0
  6. data/ChangeLog +810 -237
  7. data/README.md +0 -25
  8. data/Rakefile +2 -1
  9. data/Vagrantfile +17 -0
  10. data/appveyor.yml +35 -0
  11. data/example/filter_stdout.conf +5 -5
  12. data/example/in_forward.conf +2 -2
  13. data/example/in_http.conf +2 -2
  14. data/example/in_out_forward.conf +17 -0
  15. data/example/in_syslog.conf +2 -2
  16. data/example/in_tail.conf +2 -2
  17. data/example/in_tcp.conf +2 -2
  18. data/example/in_udp.conf +2 -2
  19. data/example/out_copy.conf +4 -4
  20. data/example/out_file.conf +2 -2
  21. data/example/out_forward.conf +2 -2
  22. data/example/out_forward_buf_file.conf +23 -0
  23. data/example/v0_12_filter.conf +8 -8
  24. data/fluent.conf +29 -0
  25. data/fluentd.gemspec +18 -11
  26. data/lib/fluent/agent.rb +60 -58
  27. data/lib/fluent/command/cat.rb +1 -1
  28. data/lib/fluent/command/debug.rb +7 -5
  29. data/lib/fluent/command/fluentd.rb +97 -2
  30. data/lib/fluent/compat/call_super_mixin.rb +67 -0
  31. data/lib/fluent/compat/filter.rb +50 -0
  32. data/lib/fluent/compat/formatter.rb +109 -0
  33. data/lib/fluent/compat/input.rb +50 -0
  34. data/lib/fluent/compat/output.rb +617 -0
  35. data/lib/fluent/compat/output_chain.rb +60 -0
  36. data/lib/fluent/compat/parser.rb +163 -0
  37. data/lib/fluent/compat/propagate_default.rb +62 -0
  38. data/lib/fluent/config.rb +23 -20
  39. data/lib/fluent/config/configure_proxy.rb +119 -70
  40. data/lib/fluent/config/dsl.rb +5 -18
  41. data/lib/fluent/config/element.rb +72 -8
  42. data/lib/fluent/config/error.rb +0 -3
  43. data/lib/fluent/config/literal_parser.rb +0 -2
  44. data/lib/fluent/config/parser.rb +4 -4
  45. data/lib/fluent/config/section.rb +39 -28
  46. data/lib/fluent/config/types.rb +2 -13
  47. data/lib/fluent/config/v1_parser.rb +1 -3
  48. data/lib/fluent/configurable.rb +48 -16
  49. data/lib/fluent/daemon.rb +15 -0
  50. data/lib/fluent/engine.rb +26 -52
  51. data/lib/fluent/env.rb +6 -4
  52. data/lib/fluent/event.rb +58 -11
  53. data/lib/fluent/event_router.rb +5 -5
  54. data/lib/fluent/filter.rb +2 -50
  55. data/lib/fluent/formatter.rb +4 -293
  56. data/lib/fluent/input.rb +2 -32
  57. data/lib/fluent/label.rb +2 -2
  58. data/lib/fluent/load.rb +3 -2
  59. data/lib/fluent/log.rb +107 -38
  60. data/lib/fluent/match.rb +0 -36
  61. data/lib/fluent/mixin.rb +117 -7
  62. data/lib/fluent/msgpack_factory.rb +62 -0
  63. data/lib/fluent/output.rb +7 -612
  64. data/lib/fluent/output_chain.rb +23 -0
  65. data/lib/fluent/parser.rb +4 -800
  66. data/lib/fluent/plugin.rb +100 -121
  67. data/lib/fluent/plugin/bare_output.rb +63 -0
  68. data/lib/fluent/plugin/base.rb +121 -0
  69. data/lib/fluent/plugin/buf_file.rb +101 -182
  70. data/lib/fluent/plugin/buf_memory.rb +9 -92
  71. data/lib/fluent/plugin/buffer.rb +473 -0
  72. data/lib/fluent/plugin/buffer/chunk.rb +135 -0
  73. data/lib/fluent/plugin/buffer/file_chunk.rb +339 -0
  74. data/lib/fluent/plugin/buffer/memory_chunk.rb +100 -0
  75. data/lib/fluent/plugin/exec_util.rb +80 -75
  76. data/lib/fluent/plugin/file_util.rb +33 -28
  77. data/lib/fluent/plugin/file_wrapper.rb +120 -0
  78. data/lib/fluent/plugin/filter.rb +51 -0
  79. data/lib/fluent/plugin/filter_grep.rb +13 -40
  80. data/lib/fluent/plugin/filter_record_transformer.rb +22 -18
  81. data/lib/fluent/plugin/formatter.rb +93 -0
  82. data/lib/fluent/plugin/formatter_csv.rb +48 -0
  83. data/lib/fluent/plugin/formatter_hash.rb +32 -0
  84. data/lib/fluent/plugin/formatter_json.rb +47 -0
  85. data/lib/fluent/plugin/formatter_ltsv.rb +42 -0
  86. data/lib/fluent/plugin/formatter_msgpack.rb +32 -0
  87. data/lib/fluent/plugin/formatter_out_file.rb +45 -0
  88. data/lib/fluent/plugin/formatter_single_value.rb +34 -0
  89. data/lib/fluent/plugin/formatter_stdout.rb +39 -0
  90. data/lib/fluent/plugin/in_debug_agent.rb +4 -0
  91. data/lib/fluent/plugin/in_dummy.rb +22 -18
  92. data/lib/fluent/plugin/in_exec.rb +18 -8
  93. data/lib/fluent/plugin/in_forward.rb +36 -79
  94. data/lib/fluent/plugin/in_gc_stat.rb +4 -0
  95. data/lib/fluent/plugin/in_http.rb +21 -18
  96. data/lib/fluent/plugin/in_monitor_agent.rb +15 -48
  97. data/lib/fluent/plugin/in_object_space.rb +6 -1
  98. data/lib/fluent/plugin/in_stream.rb +7 -3
  99. data/lib/fluent/plugin/in_syslog.rb +46 -95
  100. data/lib/fluent/plugin/in_tail.rb +51 -595
  101. data/lib/fluent/plugin/in_tcp.rb +8 -1
  102. data/lib/fluent/plugin/in_udp.rb +8 -14
  103. data/lib/fluent/plugin/input.rb +33 -0
  104. data/lib/fluent/plugin/multi_output.rb +95 -0
  105. data/lib/fluent/plugin/out_buffered_null.rb +59 -0
  106. data/lib/fluent/plugin/out_copy.rb +11 -7
  107. data/lib/fluent/plugin/out_exec.rb +15 -11
  108. data/lib/fluent/plugin/out_exec_filter.rb +18 -10
  109. data/lib/fluent/plugin/out_file.rb +34 -5
  110. data/lib/fluent/plugin/out_forward.rb +19 -9
  111. data/lib/fluent/plugin/out_null.rb +0 -14
  112. data/lib/fluent/plugin/out_roundrobin.rb +11 -7
  113. data/lib/fluent/plugin/out_stdout.rb +5 -7
  114. data/lib/fluent/plugin/out_stream.rb +3 -1
  115. data/lib/fluent/plugin/output.rb +979 -0
  116. data/lib/fluent/plugin/owned_by_mixin.rb +42 -0
  117. data/lib/fluent/plugin/parser.rb +244 -0
  118. data/lib/fluent/plugin/parser_apache.rb +24 -0
  119. data/lib/fluent/plugin/parser_apache2.rb +84 -0
  120. data/lib/fluent/plugin/parser_apache_error.rb +21 -0
  121. data/lib/fluent/plugin/parser_csv.rb +31 -0
  122. data/lib/fluent/plugin/parser_json.rb +79 -0
  123. data/lib/fluent/plugin/parser_ltsv.rb +50 -0
  124. data/lib/fluent/plugin/parser_multiline.rb +102 -0
  125. data/lib/fluent/plugin/parser_nginx.rb +24 -0
  126. data/lib/fluent/plugin/parser_none.rb +36 -0
  127. data/lib/fluent/plugin/parser_syslog.rb +82 -0
  128. data/lib/fluent/plugin/parser_tsv.rb +37 -0
  129. data/lib/fluent/plugin/socket_util.rb +120 -114
  130. data/lib/fluent/plugin/storage.rb +84 -0
  131. data/lib/fluent/plugin/storage_local.rb +116 -0
  132. data/lib/fluent/plugin/string_util.rb +16 -13
  133. data/lib/fluent/plugin_helper.rb +39 -0
  134. data/lib/fluent/plugin_helper/child_process.rb +298 -0
  135. data/lib/fluent/plugin_helper/compat_parameters.rb +99 -0
  136. data/lib/fluent/plugin_helper/event_emitter.rb +80 -0
  137. data/lib/fluent/plugin_helper/event_loop.rb +118 -0
  138. data/lib/fluent/plugin_helper/retry_state.rb +177 -0
  139. data/lib/fluent/plugin_helper/storage.rb +308 -0
  140. data/lib/fluent/plugin_helper/thread.rb +147 -0
  141. data/lib/fluent/plugin_helper/timer.rb +85 -0
  142. data/lib/fluent/plugin_id.rb +63 -0
  143. data/lib/fluent/process.rb +21 -30
  144. data/lib/fluent/registry.rb +21 -9
  145. data/lib/fluent/root_agent.rb +115 -40
  146. data/lib/fluent/supervisor.rb +330 -320
  147. data/lib/fluent/system_config.rb +42 -18
  148. data/lib/fluent/test.rb +6 -1
  149. data/lib/fluent/test/base.rb +23 -3
  150. data/lib/fluent/test/driver/base.rb +247 -0
  151. data/lib/fluent/test/driver/event_feeder.rb +98 -0
  152. data/lib/fluent/test/driver/filter.rb +35 -0
  153. data/lib/fluent/test/driver/input.rb +31 -0
  154. data/lib/fluent/test/driver/output.rb +78 -0
  155. data/lib/fluent/test/driver/test_event_router.rb +45 -0
  156. data/lib/fluent/test/filter_test.rb +0 -1
  157. data/lib/fluent/test/formatter_test.rb +2 -1
  158. data/lib/fluent/test/input_test.rb +23 -17
  159. data/lib/fluent/test/output_test.rb +28 -39
  160. data/lib/fluent/test/parser_test.rb +1 -1
  161. data/lib/fluent/time.rb +104 -1
  162. data/lib/fluent/{status.rb → unique_id.rb} +15 -24
  163. data/lib/fluent/version.rb +1 -1
  164. data/lib/fluent/winsvc.rb +72 -0
  165. data/test/compat/test_calls_super.rb +164 -0
  166. data/test/config/test_config_parser.rb +83 -0
  167. data/test/config/test_configurable.rb +547 -274
  168. data/test/config/test_configure_proxy.rb +146 -29
  169. data/test/config/test_dsl.rb +3 -181
  170. data/test/config/test_element.rb +274 -0
  171. data/test/config/test_literal_parser.rb +1 -1
  172. data/test/config/test_section.rb +79 -7
  173. data/test/config/test_system_config.rb +21 -0
  174. data/test/config/test_types.rb +3 -26
  175. data/test/helper.rb +78 -8
  176. data/test/plugin/test_bare_output.rb +118 -0
  177. data/test/plugin/test_base.rb +75 -0
  178. data/test/plugin/test_buf_file.rb +420 -521
  179. data/test/plugin/test_buf_memory.rb +32 -194
  180. data/test/plugin/test_buffer.rb +981 -0
  181. data/test/plugin/test_buffer_chunk.rb +110 -0
  182. data/test/plugin/test_buffer_file_chunk.rb +770 -0
  183. data/test/plugin/test_buffer_memory_chunk.rb +265 -0
  184. data/test/plugin/test_filter.rb +255 -0
  185. data/test/plugin/test_filter_grep.rb +2 -73
  186. data/test/plugin/test_filter_record_transformer.rb +24 -68
  187. data/test/plugin/test_filter_stdout.rb +6 -6
  188. data/test/plugin/test_in_debug_agent.rb +2 -0
  189. data/test/plugin/test_in_dummy.rb +11 -17
  190. data/test/plugin/test_in_exec.rb +6 -25
  191. data/test/plugin/test_in_forward.rb +112 -151
  192. data/test/plugin/test_in_gc_stat.rb +2 -0
  193. data/test/plugin/test_in_http.rb +106 -157
  194. data/test/plugin/test_in_object_space.rb +21 -5
  195. data/test/plugin/test_in_stream.rb +14 -13
  196. data/test/plugin/test_in_syslog.rb +30 -275
  197. data/test/plugin/test_in_tail.rb +95 -234
  198. data/test/plugin/test_in_tcp.rb +14 -0
  199. data/test/plugin/test_in_udp.rb +21 -13
  200. data/test/plugin/test_input.rb +122 -0
  201. data/test/plugin/test_multi_output.rb +180 -0
  202. data/test/plugin/test_out_buffered_null.rb +79 -0
  203. data/test/plugin/test_out_copy.rb +15 -2
  204. data/test/plugin/test_out_exec.rb +75 -25
  205. data/test/plugin/test_out_exec_filter.rb +74 -8
  206. data/test/plugin/test_out_file.rb +61 -7
  207. data/test/plugin/test_out_forward.rb +92 -15
  208. data/test/plugin/test_out_roundrobin.rb +1 -0
  209. data/test/plugin/test_out_stdout.rb +22 -13
  210. data/test/plugin/test_out_stream.rb +18 -0
  211. data/test/plugin/test_output.rb +515 -0
  212. data/test/plugin/test_output_as_buffered.rb +1540 -0
  213. data/test/plugin/test_output_as_buffered_overflow.rb +247 -0
  214. data/test/plugin/test_output_as_buffered_retries.rb +808 -0
  215. data/test/plugin/test_output_as_buffered_secondary.rb +776 -0
  216. data/test/plugin/test_output_as_standard.rb +362 -0
  217. data/test/plugin/test_owned_by.rb +35 -0
  218. data/test/plugin/test_storage.rb +167 -0
  219. data/test/plugin/test_storage_local.rb +8 -0
  220. data/test/plugin_helper/test_child_process.rb +599 -0
  221. data/test/plugin_helper/test_compat_parameters.rb +175 -0
  222. data/test/plugin_helper/test_event_emitter.rb +51 -0
  223. data/test/plugin_helper/test_event_loop.rb +52 -0
  224. data/test/plugin_helper/test_retry_state.rb +399 -0
  225. data/test/plugin_helper/test_storage.rb +411 -0
  226. data/test/plugin_helper/test_thread.rb +164 -0
  227. data/test/plugin_helper/test_timer.rb +100 -0
  228. data/test/scripts/exec_script.rb +0 -6
  229. data/test/scripts/fluent/plugin/out_test.rb +3 -0
  230. data/test/test_config.rb +13 -4
  231. data/test/test_event.rb +24 -13
  232. data/test/test_event_router.rb +8 -7
  233. data/test/test_event_time.rb +187 -0
  234. data/test/test_formatter.rb +13 -51
  235. data/test/test_input.rb +1 -1
  236. data/test/test_log.rb +239 -16
  237. data/test/test_mixin.rb +1 -1
  238. data/test/test_output.rb +53 -66
  239. data/test/test_parser.rb +105 -323
  240. data/test/test_plugin_helper.rb +81 -0
  241. data/test/test_root_agent.rb +4 -52
  242. data/test/test_supervisor.rb +272 -0
  243. data/test/test_unique_id.rb +47 -0
  244. metadata +180 -54
  245. data/lib/fluent/buffer.rb +0 -365
  246. data/lib/fluent/plugin/filter_parser.rb +0 -107
  247. data/lib/fluent/plugin/in_status.rb +0 -76
  248. data/lib/fluent/test/helpers.rb +0 -86
  249. data/test/plugin/data/log/foo/bar2 +0 -0
  250. data/test/plugin/test_filter_parser.rb +0 -744
  251. data/test/plugin/test_in_status.rb +0 -38
  252. data/test/test_buffer.rb +0 -624
@@ -0,0 +1,8 @@
1
+ require_relative '../helper'
2
+ require 'fluent/plugin/storage_local'
3
+
4
+ class LocalStorageTest < Test::Unit::TestCase
5
+ test 'syntax' do
6
+ assert true
7
+ end
8
+ end
@@ -0,0 +1,599 @@
1
+ require_relative '../helper'
2
+ require 'fluent/plugin_helper/child_process'
3
+ require 'fluent/plugin/base'
4
+ require 'timeout'
5
+
6
+ class ChildProcessTest < Test::Unit::TestCase
7
+ TEST_DEADLOCK_TIMEOUT = 30
8
+ TEST_WAIT_INTERVAL_FOR_BLOCK_RUNNING = 0.1 # This may be shorter than ruby's threading timer, but work well
9
+ # @nalsh says that ruby's cpu assignments for threads are almost 200ms or so.
10
+ # Loop interval (expected that it work as specified) should be longer than it.
11
+ TEST_WAIT_INTERVAL_FOR_LOOP = 0.5
12
+
13
+ setup do
14
+ @d = Dummy.new
15
+ @d.configure(config_element())
16
+ @d.start
17
+ end
18
+
19
+ teardown do
20
+ if @d
21
+ @d.stop unless @d.stopped?
22
+ @d.shutdown unless @d.shutdown?
23
+ @d.close unless @d.closed?
24
+ @d.terminate unless @d.terminated?
25
+ end
26
+ end
27
+
28
+ class Dummy < Fluent::Plugin::TestBase
29
+ helpers :child_process
30
+ def configure(conf)
31
+ super
32
+ @_child_process_kill_timeout = 1
33
+ end
34
+ end
35
+
36
+ test 'can be instantiated' do
37
+ d1 = Dummy.new
38
+ assert d1.respond_to?(:_child_process_processes)
39
+ end
40
+
41
+ test 'can be configured and started' do
42
+ d1 = Dummy.new
43
+ assert_nothing_raised do
44
+ d1.configure(config_element())
45
+ end
46
+ assert d1.plugin_id
47
+ assert d1.log
48
+
49
+ d1.start
50
+ end
51
+
52
+ test 'can execute external command asyncronously' do
53
+ m = Mutex.new
54
+ m.lock
55
+ ary = []
56
+ Timeout.timeout(TEST_DEADLOCK_TIMEOUT) do
57
+ ran = false
58
+ @d.child_process_execute(:t0, 'echo', arguments: ['foo', 'bar'], mode: [:read]) do |io|
59
+ m.lock
60
+ ran = true
61
+ io.read # discard
62
+ ary << 2
63
+ m.unlock
64
+ end
65
+ ary << 1
66
+ m.unlock
67
+ sleep TEST_WAIT_INTERVAL_FOR_BLOCK_RUNNING until m.locked? || ran
68
+ m.lock
69
+ m.unlock
70
+ end
71
+ assert_equal [1,2], ary
72
+ end
73
+
74
+ test 'can execute external command at just once, which finishes immediately' do
75
+ m = Mutex.new
76
+ t1 = Time.now
77
+ ary = []
78
+ Timeout.timeout(TEST_DEADLOCK_TIMEOUT) do
79
+ ran = false
80
+ @d.child_process_execute(:t1, 'echo', arguments: ['foo', 'bar'], mode: [:read]) do |io|
81
+ m.lock
82
+ ran = true
83
+ ary << io.read
84
+ m.unlock
85
+ end
86
+ sleep TEST_WAIT_INTERVAL_FOR_BLOCK_RUNNING until m.locked? || ran
87
+ m.lock
88
+ m.unlock
89
+ end
90
+ assert{ Time.now - t1 < 4.0 }
91
+ end
92
+
93
+ test 'can execute external command at just once, which can handle both of read and write' do
94
+ m = Mutex.new
95
+ ary = []
96
+ Timeout.timeout(TEST_DEADLOCK_TIMEOUT) do
97
+ ran = false
98
+ cmd = "ruby -e 'while !STDIN.eof? && line = STDIN.readline; puts line.chomp; STDOUT.flush rescue nil; end'"
99
+ @d.child_process_execute(:t2, cmd, mode: [:write, :read]) do |writeio, readio|
100
+ m.lock
101
+ ran = true
102
+
103
+ [[1,2],[3,4],[5,6]].each do |i,j|
104
+ writeio.write "my data#{i}\n"
105
+ writeio.write "my data#{j}\n"
106
+ writeio.flush
107
+ end
108
+ writeio.close
109
+
110
+ while line = readio.readline
111
+ ary << line
112
+ end
113
+ m.unlock
114
+ end
115
+ sleep TEST_WAIT_INTERVAL_FOR_BLOCK_RUNNING until m.locked? || ran
116
+ m.lock
117
+ m.unlock
118
+ end
119
+
120
+ assert_equal [], @d.log.out.logs
121
+ expected = (1..6).map{|i| "my data#{i}\n" }
122
+ assert_equal expected, ary
123
+ end
124
+
125
+ test 'can execute external command at just once, which can handle all of read, write and stderr' do
126
+ m = Mutex.new
127
+ ary1 = []
128
+ ary2 = []
129
+ Timeout.timeout(TEST_DEADLOCK_TIMEOUT) do
130
+ ran = false
131
+ cmd = "ruby -e 'while !STDIN.eof? && line = STDIN.readline; puts line.chomp; STDOUT.flush rescue nil; STDERR.puts line.chomp; STDERR.flush rescue nil; end'"
132
+ @d.child_process_execute(:t2a, cmd, mode: [:write, :read, :stderr]) do |writeio, readio, stderrio|
133
+ m.lock
134
+ ran = true
135
+
136
+ [[1,2],[3,4],[5,6]].each do |i,j|
137
+ writeio.write "my data#{i}\n"
138
+ writeio.write "my data#{j}\n"
139
+ writeio.flush
140
+ end
141
+ writeio.close
142
+
143
+ while (line1 = readio.readline) && (line2 = stderrio.readline)
144
+ ary1 << line1
145
+ ary2 << line2
146
+ end
147
+
148
+ m.unlock
149
+ end
150
+ sleep TEST_WAIT_INTERVAL_FOR_BLOCK_RUNNING until m.locked? || ran
151
+ m.lock
152
+ m.unlock
153
+ end
154
+
155
+ assert_equal [], @d.log.out.logs
156
+ expected = (1..6).map{|i| "my data#{i}\n" }
157
+ assert_equal expected, ary1
158
+ assert_equal expected, ary2
159
+ end
160
+
161
+ test 'can execute external command at just once, which can handle both of write and read (with stderr)' do
162
+ m = Mutex.new
163
+ ary = []
164
+ Timeout.timeout(TEST_DEADLOCK_TIMEOUT) do
165
+ ran = false
166
+ cmd = "ruby"
167
+ args = ['-e', 'while !STDIN.eof? && line = STDIN.readline; puts "[s]" + line.chomp; STDOUT.flush rescue nil; STDERR.puts "[e]" + line.chomp; STDERR.flush rescue nil; end']
168
+ @d.child_process_execute(:t2b, cmd, arguments: args, mode: [:write, :read_with_stderr]) do |writeio, readio|
169
+ m.lock
170
+ ran = true
171
+
172
+ [[1,2],[3,4],[5,6]].each do |i,j|
173
+ writeio.write "my data#{i}\n"
174
+ writeio.write "my data#{j}\n"
175
+ writeio.flush
176
+ end
177
+ writeio.close
178
+
179
+ while line = readio.readline
180
+ ary << line
181
+ end
182
+
183
+ m.unlock
184
+ end
185
+ sleep TEST_WAIT_INTERVAL_FOR_BLOCK_RUNNING until m.locked? || ran
186
+ m.lock
187
+ m.unlock
188
+ end
189
+
190
+ assert_equal [], @d.log.out.logs
191
+ expected = (1..6).map{|i| ["[s]my data#{i}\n", "[e]my data#{i}\n"] }.flatten
192
+ assert_equal expected, ary
193
+ end
194
+
195
+ test 'can execute external command at just once, which runs forever' do
196
+ m = Mutex.new
197
+ ary = []
198
+ Timeout.timeout(TEST_DEADLOCK_TIMEOUT) do
199
+ ran = false
200
+ args = ["-e", "while sleep #{TEST_WAIT_INTERVAL_FOR_LOOP}; puts 1; STDOUT.flush; end"]
201
+ @d.child_process_execute(:t3, "ruby", arguments: args, mode: [:read]) do |io|
202
+ m.lock
203
+ ran = true
204
+ begin
205
+ while @d.child_process_running? && line = io.readline
206
+ ary << line
207
+ end
208
+ rescue
209
+ # ignore
210
+ ensure
211
+ m.unlock
212
+ end
213
+ end
214
+ sleep TEST_WAIT_INTERVAL_FOR_BLOCK_RUNNING until m.locked? || ran
215
+ sleep TEST_WAIT_INTERVAL_FOR_LOOP * 10
216
+ @d.stop # nothing occures
217
+ @d.shutdown
218
+
219
+ assert{ ary.size > 5 }
220
+
221
+ @d.close
222
+
223
+ @d.terminate
224
+ assert @d._child_process_processes.empty?
225
+ end
226
+ end
227
+
228
+ unless Fluent.windows?
229
+ # In windows environment, child_process try KILL at first (because there's no SIGTERM)
230
+ test 'can execute external command just once, and can terminate it forcedly when shutdown/terminate even if it ignore SIGTERM' do
231
+ m = Mutex.new
232
+ ary = []
233
+ Timeout.timeout(TEST_DEADLOCK_TIMEOUT) do
234
+ ran = false
235
+ @d.child_process_execute(:t4, "ruby -e 'Signal.trap(:TERM, nil); while sleep #{TEST_WAIT_INTERVAL_FOR_LOOP}; puts 1; STDOUT.flush rescue nil; end'", mode: [:read]) do |io|
236
+ m.lock
237
+ ran = true
238
+ begin
239
+ while line = io.readline
240
+ ary << line
241
+ end
242
+ rescue
243
+ # ignore
244
+ ensure
245
+ m.unlock
246
+ end
247
+ end
248
+ sleep TEST_WAIT_INTERVAL_FOR_BLOCK_RUNNING until m.locked? || ran
249
+
250
+ assert_equal [], @d.log.out.logs
251
+
252
+ @d.stop # nothing occures
253
+ sleep TEST_WAIT_INTERVAL_FOR_LOOP * 5
254
+ lines1 = ary.size
255
+ assert{ lines1 > 1 }
256
+
257
+ pid = @d._child_process_processes.keys.first
258
+
259
+ @d.shutdown
260
+ sleep TEST_WAIT_INTERVAL_FOR_LOOP * 5
261
+ lines2 = ary.size
262
+ assert{ lines2 > lines1 }
263
+
264
+ @d.close
265
+
266
+ assert_nil((Process.waitpid(pid, Process::WNOHANG) rescue nil))
267
+
268
+ @d.terminate
269
+ assert @d._child_process_processes.empty?
270
+ begin
271
+ Process.waitpid(pid)
272
+ rescue Errno::ECHILD
273
+ end
274
+ # Process successfully KILLed if test reaches here
275
+ assert true
276
+ end
277
+ end
278
+ end
279
+
280
+ test 'can execute external command many times, which finishes immediately' do
281
+ ary = []
282
+ arguments = ["-e", "3.times{ puts 'okay'; STDOUT.flush rescue nil; sleep #{TEST_WAIT_INTERVAL_FOR_LOOP} }"] # 0.5 * 3
283
+ Timeout.timeout(TEST_DEADLOCK_TIMEOUT) do
284
+ @d.child_process_execute(:t5, "ruby", arguments: arguments, interval: 5, mode: [:read]) do |io|
285
+ ary << io.read.split("\n").map(&:chomp).join
286
+ end
287
+ sleep 13 # 5sec * 2 + 3sec
288
+ assert_equal [], @d.log.out.logs
289
+ @d.stop
290
+ assert_equal [], @d.log.out.logs
291
+ @d.shutdown; @d.close; @d.terminate
292
+ assert_equal 2, ary.size
293
+ end
294
+ end
295
+
296
+ test 'can execute external command many times, with leading once executed immediately' do
297
+ ary = []
298
+ arguments = ["-e", "3.times{ puts 'okay'; STDOUT.flush rescue nil; sleep #{TEST_WAIT_INTERVAL_FOR_LOOP} }"]
299
+ Timeout.timeout(TEST_DEADLOCK_TIMEOUT) do
300
+ @d.child_process_execute(:t6, "ruby", arguments: arguments, interval: 5, immediate: true, mode: [:read]) do |io|
301
+ ary << io.read.split("\n").map(&:chomp).join
302
+ end
303
+ sleep 8 # 5sec * 1 + 3sec
304
+ # but expected lines are same with test above
305
+ @d.stop; @d.shutdown; @d.close; @d.terminate
306
+ assert_equal 2, ary.size
307
+ assert_equal [], @d.log.out.logs
308
+ end
309
+ end
310
+
311
+ test 'does not execute long running external command in parallel in default' do
312
+ ary = []
313
+ arguments = ["-e", "10.times{ puts 'okay'; STDOUT.flush rescue nil; sleep #{TEST_WAIT_INTERVAL_FOR_LOOP} }"] # 0.5 * 10
314
+ Timeout.timeout(TEST_DEADLOCK_TIMEOUT) do
315
+ @d.child_process_execute(:t7, "ruby", arguments: arguments, interval: 2, immediate: true, mode: [:read]) do |io|
316
+ ary << io.read.split("\n").map(&:chomp).join
317
+ end
318
+ sleep 4
319
+ assert_equal 1, @d._child_process_processes.size
320
+ @d.stop
321
+ warn_msg = '[warn]: previous child process is still running. skipped. title=:t7 command="ruby" arguments=["-e", "10.times{ puts \'okay\'; STDOUT.flush rescue nil; sleep 0.5 }"] interval=2 parallel=false' + "\n"
322
+ assert{ @d.log.out.logs.first.end_with?(warn_msg) }
323
+ assert{ @d.log.out.logs.all?{|line| line.end_with?(warn_msg) } }
324
+ @d.shutdown; @d.close; @d.terminate
325
+ assert_equal [], @d.log.out.logs
326
+ end
327
+ end
328
+
329
+ test 'can execute long running external command in parallel if specified' do
330
+ ary = []
331
+ arguments = ["-e", "10.times{ puts 'okay'; STDOUT.flush rescue nil; sleep #{TEST_WAIT_INTERVAL_FOR_LOOP} }"] # 0.5 * 10 sec
332
+ Timeout.timeout(TEST_DEADLOCK_TIMEOUT) do
333
+ @d.child_process_execute(:t8, "ruby", arguments: arguments, interval: 1, immediate: true, parallel: true, mode: [:read]) do |io|
334
+ ary << io.read.split("\n").map(&:chomp).join
335
+ end
336
+ sleep 4
337
+ processes = @d._child_process_processes.size
338
+ assert{ processes >= 3 && processes <= 5 }
339
+ @d.stop; @d.shutdown; @d.close; @d.terminate
340
+ assert_equal [], @d.log.out.logs
341
+ end
342
+ end
343
+
344
+ test 'execute external processes only for writing' do
345
+ m = Mutex.new
346
+ unreadable = false
347
+ Timeout.timeout(TEST_DEADLOCK_TIMEOUT) do
348
+ ran = false
349
+ @d.child_process_execute(:t9, "ruby", arguments: ['-e', 'a=""; while b=STDIN.readline; a+=b; end'], mode: [:write]) do |io|
350
+ m.lock
351
+ ran = true
352
+ begin
353
+ io.read
354
+ rescue IOError
355
+ unreadable = true
356
+ end
357
+ 50.times do
358
+ io.write "hahaha\n"
359
+ end
360
+ m.unlock
361
+ end
362
+ sleep TEST_WAIT_INTERVAL_FOR_BLOCK_RUNNING until m.locked? || ran
363
+ m.lock
364
+ m.unlock
365
+ assert unreadable
366
+ @d.stop; @d.shutdown; @d.close; @d.terminate
367
+ assert_equal [], @d.log.out.logs
368
+ end
369
+ end
370
+
371
+ test 'execute external processes only for reading' do
372
+ m = Mutex.new
373
+ unwritable = false
374
+ Timeout.timeout(TEST_DEADLOCK_TIMEOUT) do
375
+ ran = false
376
+ @d.child_process_execute(:t10, "ruby", arguments: ["-e", "while sleep #{TEST_WAIT_INTERVAL_FOR_LOOP}; puts 1; STDOUT.flush rescue nil; end"], mode: [:read]) do |io|
377
+ m.lock
378
+ ran = true
379
+ begin
380
+ io.write "foobar"
381
+ rescue IOError
382
+ unwritable = true
383
+ end
384
+ _data = io.readline
385
+ m.unlock
386
+ end
387
+ sleep TEST_WAIT_INTERVAL_FOR_BLOCK_RUNNING until m.locked? || ran
388
+ m.lock
389
+ m.unlock
390
+ @d.stop; @d.shutdown; @d.close; @d.terminate
391
+ assert unwritable
392
+ assert_equal [], @d.log.out.logs
393
+ end
394
+ end
395
+
396
+ test 'can control external encodings' do
397
+ m = Mutex.new
398
+ encodings = []
399
+ Timeout.timeout(TEST_DEADLOCK_TIMEOUT) do
400
+ ran = false
401
+ @d.child_process_execute(:t11, "ruby -e 'sleep 10'", external_encoding: 'ascii-8bit') do |r, w|
402
+ m.lock
403
+ ran = true
404
+ encodings << r.external_encoding
405
+ encodings << w.external_encoding
406
+ m.unlock
407
+ end
408
+ sleep TEST_WAIT_INTERVAL_FOR_BLOCK_RUNNING until m.locked? || ran
409
+ m.lock
410
+ assert_equal Encoding::ASCII_8BIT, encodings[0]
411
+ assert_equal Encoding::ASCII_8BIT, encodings[1]
412
+ @d.stop; @d.shutdown; @d.close; @d.terminate
413
+ end
414
+ end
415
+
416
+ test 'can control internal encodings' do
417
+ m = Mutex.new
418
+ encodings = []
419
+ Timeout.timeout(TEST_DEADLOCK_TIMEOUT) do
420
+ ran = false
421
+ @d.child_process_execute(:t12, "ruby -e 'sleep 10'", external_encoding: 'utf-8', internal_encoding: 'ascii-8bit') do |r, w|
422
+ m.lock
423
+ ran = true
424
+ encodings << r.internal_encoding
425
+ encodings << w.internal_encoding
426
+ m.unlock
427
+ end
428
+ sleep TEST_WAIT_INTERVAL_FOR_BLOCK_RUNNING until m.locked? || ran
429
+ m.lock
430
+ assert_equal Encoding::ASCII_8BIT, encodings[0]
431
+ assert_equal Encoding::ASCII_8BIT, encodings[1]
432
+ @d.stop; @d.shutdown; @d.close; @d.terminate
433
+ end
434
+ end
435
+
436
+ test 'can convert encodings from ascii-8bit to utf-8' do
437
+ m = Mutex.new
438
+ str = nil
439
+ Timeout.timeout(TEST_DEADLOCK_TIMEOUT) do
440
+ ran = false
441
+ args = ['-e', 'STDOUT.set_encoding("ascii-8bit"); STDOUT.write "\xA4\xB5\xA4\xC8\xA4\xB7"']
442
+ @d.child_process_execute(:t13, "ruby", arguments: args, external_encoding: 'euc-jp', internal_encoding: 'windows-31j', mode: [:read]) do |io|
443
+ m.lock
444
+ ran = true
445
+ str = io.read
446
+ m.unlock
447
+ end
448
+ sleep TEST_WAIT_INTERVAL_FOR_BLOCK_RUNNING until m.locked? || ran
449
+ m.lock
450
+ assert_equal Encoding.find('windows-31j'), str.encoding
451
+ expected = "さとし".encode('windows-31j')
452
+ assert_equal expected, str
453
+ @d.stop; @d.shutdown; @d.close; @d.terminate
454
+ end
455
+ end
456
+
457
+ test 'can scrub characters without exceptions' do
458
+ m = Mutex.new
459
+ str = nil
460
+ Timeout.timeout(TEST_DEADLOCK_TIMEOUT) do
461
+ ran = false
462
+ args = ['-e', 'STDOUT.set_encoding("ascii-8bit"); STDOUT.write "\xFF\xFF\x00\xF0\xF0"']
463
+ @d.child_process_execute(:t13a, "ruby", arguments: args, mode: [:read]) do |io|
464
+ m.lock
465
+ ran = true
466
+ str = io.read
467
+ m.unlock
468
+ end
469
+ sleep TEST_WAIT_INTERVAL_FOR_BLOCK_RUNNING until m.locked? || ran
470
+ m.lock
471
+ assert_equal Encoding.find('utf-8'), str.encoding
472
+ expected = "\xEF\xBF\xBD\xEF\xBF\xBD\x00\xEF\xBF\xBD\xEF\xBF\xBD".force_encoding("utf-8")
473
+ assert_equal expected, str
474
+ @d.stop; @d.shutdown; @d.close; @d.terminate
475
+ end
476
+ end
477
+
478
+ test 'can scrub characters without exceptions and replace specified chars' do
479
+ m = Mutex.new
480
+ str = nil
481
+ Timeout.timeout(TEST_DEADLOCK_TIMEOUT) do
482
+ ran = false
483
+ args = ['-e', 'STDOUT.set_encoding("ascii-8bit"); STDOUT.write "\xFF\xFF\x00\xF0\xF0"']
484
+ @d.child_process_execute(:t13b, "ruby", arguments: args, mode: [:read], scrub: true, replace_string: '?') do |io|
485
+ m.lock
486
+ ran = true
487
+ str = io.read
488
+ m.unlock
489
+ end
490
+ sleep TEST_WAIT_INTERVAL_FOR_BLOCK_RUNNING until m.locked? || ran
491
+ m.lock
492
+ assert_equal Encoding.find('utf-8'), str.encoding
493
+ expected = "??\x00??".force_encoding("utf-8")
494
+ assert_equal expected, str
495
+ @d.stop; @d.shutdown; @d.close; @d.terminate
496
+ end
497
+ end
498
+
499
+ unless Fluent.windows?
500
+ test 'can specify subprocess name' do
501
+ io = IO.popen([["cat", "caaaaaaaaaaat"], '-'])
502
+ process_naming_enabled = (open("|ps"){|_io| _io.readlines }.select{|line| line.include?("caaaaaaaaaaat") }.size > 0)
503
+ Process.kill(:TERM, io.pid) rescue nil
504
+ io.close rescue nil
505
+
506
+ # Does TravisCI prohibit process renaming?
507
+ # This test will be passed in such environment
508
+ pend unless process_naming_enabled
509
+
510
+ m = Mutex.new
511
+ pids = []
512
+ proc_lines = []
513
+ Timeout.timeout(TEST_DEADLOCK_TIMEOUT) do
514
+ ran = false
515
+ @d.child_process_execute(:t14, "ruby", arguments:['-e', 'sleep 10; puts "hello"'], subprocess_name: "sleeeeeeeeeper", mode: [:read]) do |readio|
516
+ m.lock
517
+ ran = true
518
+ pids << @d.child_process_id
519
+ proc_lines += open("|ps"){|_io| _io.readlines }
520
+ m.unlock
521
+ readio.read
522
+ end
523
+ sleep TEST_WAIT_INTERVAL_FOR_BLOCK_RUNNING until m.locked? || ran
524
+ m.lock
525
+ pid = pids.first
526
+ # 51358 ttys001 0:00.00 sleeper -e sleep 10
527
+ assert{ proc_lines.select{|line| line =~ /^\s*#{pid}\s/ }.first.strip.split(/\s+/)[3] == "sleeeeeeeeeper" }
528
+ @d.stop; @d.shutdown; @d.close; @d.terminate
529
+ end
530
+ end
531
+ end
532
+
533
+ test 'can set ENV variables' do
534
+ m = Mutex.new
535
+ str = nil
536
+ Timeout.timeout(TEST_DEADLOCK_TIMEOUT) do
537
+ ran = false
538
+ args = ['-e', 'puts ENV["testing_child_process"]']
539
+ @d.child_process_execute(:t15a, "ruby", arguments: args, mode: [:read], env: {'testing_child_process' => 'Yes! True!'}) do |io|
540
+ m.lock
541
+ ran = true
542
+ str = io.read
543
+ m.unlock
544
+ end
545
+ sleep TEST_WAIT_INTERVAL_FOR_BLOCK_RUNNING until m.locked? || ran
546
+ m.lock
547
+ expected = "Yes! True!\n"
548
+ assert_equal expected, str
549
+ @d.stop; @d.shutdown; @d.close; @d.terminate
550
+ end
551
+ end
552
+
553
+ test 'can unset ENV variables of Fluentd process' do
554
+ m = Mutex.new
555
+ str = nil
556
+ Timeout.timeout(TEST_DEADLOCK_TIMEOUT) do
557
+ current_env_path = ENV['PATH']
558
+ ran = false
559
+ args = ['-e', 'puts ENV["testing_child_process1"].to_s + ENV["testing_child_process2"].to_s']
560
+ ENV['testing_child_process1'] = "No! False!"
561
+ @d.child_process_execute(:t15b, "ruby", arguments: args, mode: [:read], unsetenv: true, env: {'testing_child_process2' => 'Yes! True!', 'PATH' => current_env_path}) do |io|
562
+ m.lock
563
+ ran = true
564
+ str = io.read
565
+ m.unlock
566
+ end
567
+ sleep TEST_WAIT_INTERVAL_FOR_BLOCK_RUNNING until m.locked? || ran
568
+ m.lock
569
+ expected = "Yes! True!\n"
570
+ assert_equal expected, str
571
+ @d.stop; @d.shutdown; @d.close; @d.terminate
572
+ end
573
+ end
574
+
575
+ unless Fluent.windows?
576
+ test 'can change working directory' do
577
+ # check my real /tmp directory (for mac)
578
+ cmd = %[|ruby -e 'Dir.chdir("/tmp"); puts Dir.pwd']
579
+ mytmpdir = open(cmd){|io| io.read.chomp }
580
+
581
+ m = Mutex.new
582
+ str = nil
583
+ Timeout.timeout(TEST_DEADLOCK_TIMEOUT) do
584
+ ran = false
585
+ args = ['-e', 'puts Dir.pwd']
586
+ @d.child_process_execute(:t16, "ruby", arguments: args, mode: [:read], chdir: "/tmp") do |io|
587
+ m.lock
588
+ ran = true
589
+ str = io.read.chomp
590
+ m.unlock
591
+ end
592
+ sleep TEST_WAIT_INTERVAL_FOR_BLOCK_RUNNING until m.locked? || ran
593
+ m.lock
594
+ assert_equal mytmpdir, str
595
+ @d.stop; @d.shutdown; @d.close; @d.terminate
596
+ end
597
+ end
598
+ end
599
+ end