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.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE.md +6 -0
- data/.gitignore +2 -0
- data/.travis.yml +33 -21
- data/CONTRIBUTING.md +1 -0
- data/ChangeLog +810 -237
- data/README.md +0 -25
- data/Rakefile +2 -1
- data/Vagrantfile +17 -0
- data/appveyor.yml +35 -0
- data/example/filter_stdout.conf +5 -5
- data/example/in_forward.conf +2 -2
- data/example/in_http.conf +2 -2
- data/example/in_out_forward.conf +17 -0
- data/example/in_syslog.conf +2 -2
- data/example/in_tail.conf +2 -2
- data/example/in_tcp.conf +2 -2
- data/example/in_udp.conf +2 -2
- data/example/out_copy.conf +4 -4
- data/example/out_file.conf +2 -2
- data/example/out_forward.conf +2 -2
- data/example/out_forward_buf_file.conf +23 -0
- data/example/v0_12_filter.conf +8 -8
- data/fluent.conf +29 -0
- data/fluentd.gemspec +18 -11
- data/lib/fluent/agent.rb +60 -58
- data/lib/fluent/command/cat.rb +1 -1
- data/lib/fluent/command/debug.rb +7 -5
- data/lib/fluent/command/fluentd.rb +97 -2
- data/lib/fluent/compat/call_super_mixin.rb +67 -0
- data/lib/fluent/compat/filter.rb +50 -0
- data/lib/fluent/compat/formatter.rb +109 -0
- data/lib/fluent/compat/input.rb +50 -0
- data/lib/fluent/compat/output.rb +617 -0
- data/lib/fluent/compat/output_chain.rb +60 -0
- data/lib/fluent/compat/parser.rb +163 -0
- data/lib/fluent/compat/propagate_default.rb +62 -0
- data/lib/fluent/config.rb +23 -20
- data/lib/fluent/config/configure_proxy.rb +119 -70
- data/lib/fluent/config/dsl.rb +5 -18
- data/lib/fluent/config/element.rb +72 -8
- data/lib/fluent/config/error.rb +0 -3
- data/lib/fluent/config/literal_parser.rb +0 -2
- data/lib/fluent/config/parser.rb +4 -4
- data/lib/fluent/config/section.rb +39 -28
- data/lib/fluent/config/types.rb +2 -13
- data/lib/fluent/config/v1_parser.rb +1 -3
- data/lib/fluent/configurable.rb +48 -16
- data/lib/fluent/daemon.rb +15 -0
- data/lib/fluent/engine.rb +26 -52
- data/lib/fluent/env.rb +6 -4
- data/lib/fluent/event.rb +58 -11
- data/lib/fluent/event_router.rb +5 -5
- data/lib/fluent/filter.rb +2 -50
- data/lib/fluent/formatter.rb +4 -293
- data/lib/fluent/input.rb +2 -32
- data/lib/fluent/label.rb +2 -2
- data/lib/fluent/load.rb +3 -2
- data/lib/fluent/log.rb +107 -38
- data/lib/fluent/match.rb +0 -36
- data/lib/fluent/mixin.rb +117 -7
- data/lib/fluent/msgpack_factory.rb +62 -0
- data/lib/fluent/output.rb +7 -612
- data/lib/fluent/output_chain.rb +23 -0
- data/lib/fluent/parser.rb +4 -800
- data/lib/fluent/plugin.rb +100 -121
- data/lib/fluent/plugin/bare_output.rb +63 -0
- data/lib/fluent/plugin/base.rb +121 -0
- data/lib/fluent/plugin/buf_file.rb +101 -182
- data/lib/fluent/plugin/buf_memory.rb +9 -92
- data/lib/fluent/plugin/buffer.rb +473 -0
- data/lib/fluent/plugin/buffer/chunk.rb +135 -0
- data/lib/fluent/plugin/buffer/file_chunk.rb +339 -0
- data/lib/fluent/plugin/buffer/memory_chunk.rb +100 -0
- data/lib/fluent/plugin/exec_util.rb +80 -75
- data/lib/fluent/plugin/file_util.rb +33 -28
- data/lib/fluent/plugin/file_wrapper.rb +120 -0
- data/lib/fluent/plugin/filter.rb +51 -0
- data/lib/fluent/plugin/filter_grep.rb +13 -40
- data/lib/fluent/plugin/filter_record_transformer.rb +22 -18
- data/lib/fluent/plugin/formatter.rb +93 -0
- data/lib/fluent/plugin/formatter_csv.rb +48 -0
- data/lib/fluent/plugin/formatter_hash.rb +32 -0
- data/lib/fluent/plugin/formatter_json.rb +47 -0
- data/lib/fluent/plugin/formatter_ltsv.rb +42 -0
- data/lib/fluent/plugin/formatter_msgpack.rb +32 -0
- data/lib/fluent/plugin/formatter_out_file.rb +45 -0
- data/lib/fluent/plugin/formatter_single_value.rb +34 -0
- data/lib/fluent/plugin/formatter_stdout.rb +39 -0
- data/lib/fluent/plugin/in_debug_agent.rb +4 -0
- data/lib/fluent/plugin/in_dummy.rb +22 -18
- data/lib/fluent/plugin/in_exec.rb +18 -8
- data/lib/fluent/plugin/in_forward.rb +36 -79
- data/lib/fluent/plugin/in_gc_stat.rb +4 -0
- data/lib/fluent/plugin/in_http.rb +21 -18
- data/lib/fluent/plugin/in_monitor_agent.rb +15 -48
- data/lib/fluent/plugin/in_object_space.rb +6 -1
- data/lib/fluent/plugin/in_stream.rb +7 -3
- data/lib/fluent/plugin/in_syslog.rb +46 -95
- data/lib/fluent/plugin/in_tail.rb +51 -595
- data/lib/fluent/plugin/in_tcp.rb +8 -1
- data/lib/fluent/plugin/in_udp.rb +8 -14
- data/lib/fluent/plugin/input.rb +33 -0
- data/lib/fluent/plugin/multi_output.rb +95 -0
- data/lib/fluent/plugin/out_buffered_null.rb +59 -0
- data/lib/fluent/plugin/out_copy.rb +11 -7
- data/lib/fluent/plugin/out_exec.rb +15 -11
- data/lib/fluent/plugin/out_exec_filter.rb +18 -10
- data/lib/fluent/plugin/out_file.rb +34 -5
- data/lib/fluent/plugin/out_forward.rb +19 -9
- data/lib/fluent/plugin/out_null.rb +0 -14
- data/lib/fluent/plugin/out_roundrobin.rb +11 -7
- data/lib/fluent/plugin/out_stdout.rb +5 -7
- data/lib/fluent/plugin/out_stream.rb +3 -1
- data/lib/fluent/plugin/output.rb +979 -0
- data/lib/fluent/plugin/owned_by_mixin.rb +42 -0
- data/lib/fluent/plugin/parser.rb +244 -0
- data/lib/fluent/plugin/parser_apache.rb +24 -0
- data/lib/fluent/plugin/parser_apache2.rb +84 -0
- data/lib/fluent/plugin/parser_apache_error.rb +21 -0
- data/lib/fluent/plugin/parser_csv.rb +31 -0
- data/lib/fluent/plugin/parser_json.rb +79 -0
- data/lib/fluent/plugin/parser_ltsv.rb +50 -0
- data/lib/fluent/plugin/parser_multiline.rb +102 -0
- data/lib/fluent/plugin/parser_nginx.rb +24 -0
- data/lib/fluent/plugin/parser_none.rb +36 -0
- data/lib/fluent/plugin/parser_syslog.rb +82 -0
- data/lib/fluent/plugin/parser_tsv.rb +37 -0
- data/lib/fluent/plugin/socket_util.rb +120 -114
- data/lib/fluent/plugin/storage.rb +84 -0
- data/lib/fluent/plugin/storage_local.rb +116 -0
- data/lib/fluent/plugin/string_util.rb +16 -13
- data/lib/fluent/plugin_helper.rb +39 -0
- data/lib/fluent/plugin_helper/child_process.rb +298 -0
- data/lib/fluent/plugin_helper/compat_parameters.rb +99 -0
- data/lib/fluent/plugin_helper/event_emitter.rb +80 -0
- data/lib/fluent/plugin_helper/event_loop.rb +118 -0
- data/lib/fluent/plugin_helper/retry_state.rb +177 -0
- data/lib/fluent/plugin_helper/storage.rb +308 -0
- data/lib/fluent/plugin_helper/thread.rb +147 -0
- data/lib/fluent/plugin_helper/timer.rb +85 -0
- data/lib/fluent/plugin_id.rb +63 -0
- data/lib/fluent/process.rb +21 -30
- data/lib/fluent/registry.rb +21 -9
- data/lib/fluent/root_agent.rb +115 -40
- data/lib/fluent/supervisor.rb +330 -320
- data/lib/fluent/system_config.rb +42 -18
- data/lib/fluent/test.rb +6 -1
- data/lib/fluent/test/base.rb +23 -3
- data/lib/fluent/test/driver/base.rb +247 -0
- data/lib/fluent/test/driver/event_feeder.rb +98 -0
- data/lib/fluent/test/driver/filter.rb +35 -0
- data/lib/fluent/test/driver/input.rb +31 -0
- data/lib/fluent/test/driver/output.rb +78 -0
- data/lib/fluent/test/driver/test_event_router.rb +45 -0
- data/lib/fluent/test/filter_test.rb +0 -1
- data/lib/fluent/test/formatter_test.rb +2 -1
- data/lib/fluent/test/input_test.rb +23 -17
- data/lib/fluent/test/output_test.rb +28 -39
- data/lib/fluent/test/parser_test.rb +1 -1
- data/lib/fluent/time.rb +104 -1
- data/lib/fluent/{status.rb → unique_id.rb} +15 -24
- data/lib/fluent/version.rb +1 -1
- data/lib/fluent/winsvc.rb +72 -0
- data/test/compat/test_calls_super.rb +164 -0
- data/test/config/test_config_parser.rb +83 -0
- data/test/config/test_configurable.rb +547 -274
- data/test/config/test_configure_proxy.rb +146 -29
- data/test/config/test_dsl.rb +3 -181
- data/test/config/test_element.rb +274 -0
- data/test/config/test_literal_parser.rb +1 -1
- data/test/config/test_section.rb +79 -7
- data/test/config/test_system_config.rb +21 -0
- data/test/config/test_types.rb +3 -26
- data/test/helper.rb +78 -8
- data/test/plugin/test_bare_output.rb +118 -0
- data/test/plugin/test_base.rb +75 -0
- data/test/plugin/test_buf_file.rb +420 -521
- data/test/plugin/test_buf_memory.rb +32 -194
- data/test/plugin/test_buffer.rb +981 -0
- data/test/plugin/test_buffer_chunk.rb +110 -0
- data/test/plugin/test_buffer_file_chunk.rb +770 -0
- data/test/plugin/test_buffer_memory_chunk.rb +265 -0
- data/test/plugin/test_filter.rb +255 -0
- data/test/plugin/test_filter_grep.rb +2 -73
- data/test/plugin/test_filter_record_transformer.rb +24 -68
- data/test/plugin/test_filter_stdout.rb +6 -6
- data/test/plugin/test_in_debug_agent.rb +2 -0
- data/test/plugin/test_in_dummy.rb +11 -17
- data/test/plugin/test_in_exec.rb +6 -25
- data/test/plugin/test_in_forward.rb +112 -151
- data/test/plugin/test_in_gc_stat.rb +2 -0
- data/test/plugin/test_in_http.rb +106 -157
- data/test/plugin/test_in_object_space.rb +21 -5
- data/test/plugin/test_in_stream.rb +14 -13
- data/test/plugin/test_in_syslog.rb +30 -275
- data/test/plugin/test_in_tail.rb +95 -234
- data/test/plugin/test_in_tcp.rb +14 -0
- data/test/plugin/test_in_udp.rb +21 -13
- data/test/plugin/test_input.rb +122 -0
- data/test/plugin/test_multi_output.rb +180 -0
- data/test/plugin/test_out_buffered_null.rb +79 -0
- data/test/plugin/test_out_copy.rb +15 -2
- data/test/plugin/test_out_exec.rb +75 -25
- data/test/plugin/test_out_exec_filter.rb +74 -8
- data/test/plugin/test_out_file.rb +61 -7
- data/test/plugin/test_out_forward.rb +92 -15
- data/test/plugin/test_out_roundrobin.rb +1 -0
- data/test/plugin/test_out_stdout.rb +22 -13
- data/test/plugin/test_out_stream.rb +18 -0
- data/test/plugin/test_output.rb +515 -0
- data/test/plugin/test_output_as_buffered.rb +1540 -0
- data/test/plugin/test_output_as_buffered_overflow.rb +247 -0
- data/test/plugin/test_output_as_buffered_retries.rb +808 -0
- data/test/plugin/test_output_as_buffered_secondary.rb +776 -0
- data/test/plugin/test_output_as_standard.rb +362 -0
- data/test/plugin/test_owned_by.rb +35 -0
- data/test/plugin/test_storage.rb +167 -0
- data/test/plugin/test_storage_local.rb +8 -0
- data/test/plugin_helper/test_child_process.rb +599 -0
- data/test/plugin_helper/test_compat_parameters.rb +175 -0
- data/test/plugin_helper/test_event_emitter.rb +51 -0
- data/test/plugin_helper/test_event_loop.rb +52 -0
- data/test/plugin_helper/test_retry_state.rb +399 -0
- data/test/plugin_helper/test_storage.rb +411 -0
- data/test/plugin_helper/test_thread.rb +164 -0
- data/test/plugin_helper/test_timer.rb +100 -0
- data/test/scripts/exec_script.rb +0 -6
- data/test/scripts/fluent/plugin/out_test.rb +3 -0
- data/test/test_config.rb +13 -4
- data/test/test_event.rb +24 -13
- data/test/test_event_router.rb +8 -7
- data/test/test_event_time.rb +187 -0
- data/test/test_formatter.rb +13 -51
- data/test/test_input.rb +1 -1
- data/test/test_log.rb +239 -16
- data/test/test_mixin.rb +1 -1
- data/test/test_output.rb +53 -66
- data/test/test_parser.rb +105 -323
- data/test/test_plugin_helper.rb +81 -0
- data/test/test_root_agent.rb +4 -52
- data/test/test_supervisor.rb +272 -0
- data/test/test_unique_id.rb +47 -0
- metadata +180 -54
- data/lib/fluent/buffer.rb +0 -365
- data/lib/fluent/plugin/filter_parser.rb +0 -107
- data/lib/fluent/plugin/in_status.rb +0 -76
- data/lib/fluent/test/helpers.rb +0 -86
- data/test/plugin/data/log/foo/bar2 +0 -0
- data/test/plugin/test_filter_parser.rb +0 -744
- data/test/plugin/test_in_status.rb +0 -38
- data/test/test_buffer.rb +0 -624
@@ -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
|