fluentd 1.12.1-x86-mingw32 → 1.13.1-x86-mingw32
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/.deepsource.toml +13 -0
- data/.github/ISSUE_TEMPLATE/config.yml +2 -2
- data/.github/workflows/linux-test.yaml +36 -0
- data/.github/workflows/{build.yaml → macos-test.yaml} +8 -7
- data/.github/workflows/windows-test.yaml +46 -0
- data/.gitlab-ci.yml +19 -19
- data/CHANGELOG.md +163 -0
- data/CONTRIBUTING.md +2 -2
- data/MAINTAINERS.md +5 -2
- data/README.md +6 -3
- data/example/counter.conf +1 -1
- data/fluentd.gemspec +4 -2
- data/lib/fluent/command/bundler_injection.rb +1 -1
- data/lib/fluent/command/cat.rb +19 -4
- data/lib/fluent/command/fluentd.rb +1 -2
- data/lib/fluent/command/plugin_config_formatter.rb +2 -1
- data/lib/fluent/command/plugin_generator.rb +31 -1
- data/lib/fluent/compat/parser.rb +2 -2
- data/lib/fluent/config/section.rb +6 -1
- data/lib/fluent/config/types.rb +2 -2
- data/lib/fluent/event.rb +3 -13
- data/lib/fluent/load.rb +0 -1
- data/lib/fluent/log.rb +1 -0
- data/lib/fluent/plugin/file_wrapper.rb +49 -4
- data/lib/fluent/plugin/formatter_ltsv.rb +2 -2
- data/lib/fluent/plugin/in_http.rb +11 -1
- data/lib/fluent/plugin/in_monitor_agent.rb +1 -1
- data/lib/fluent/plugin/in_tail.rb +140 -41
- data/lib/fluent/plugin/in_tail/position_file.rb +15 -1
- data/lib/fluent/plugin/out_copy.rb +18 -5
- data/lib/fluent/plugin/out_exec_filter.rb +3 -3
- data/lib/fluent/plugin/out_forward.rb +75 -61
- data/lib/fluent/plugin/output.rb +11 -9
- data/lib/fluent/plugin/parser_csv.rb +2 -2
- data/lib/fluent/plugin/parser_syslog.rb +2 -2
- data/lib/fluent/plugin/service_discovery.rb +0 -15
- data/lib/fluent/plugin/storage_local.rb +4 -4
- data/lib/fluent/plugin_helper/http_server/router.rb +1 -1
- data/lib/fluent/plugin_helper/server.rb +4 -2
- data/lib/fluent/plugin_helper/service_discovery.rb +39 -1
- data/lib/fluent/plugin_helper/service_discovery/manager.rb +11 -5
- data/lib/fluent/plugin_helper/socket_option.rb +2 -2
- data/lib/fluent/supervisor.rb +16 -1
- data/lib/fluent/system_config.rb +14 -0
- data/lib/fluent/time.rb +57 -1
- data/lib/fluent/version.rb +1 -1
- data/templates/new_gem/fluent-plugin.gemspec.erb +3 -3
- data/test/command/test_cat.rb +99 -0
- data/test/command/test_fluentd.rb +8 -0
- data/test/config/test_configurable.rb +1 -1
- data/test/config/test_section.rb +9 -0
- data/test/config/test_system_config.rb +46 -0
- data/test/plugin/in_tail/test_io_handler.rb +4 -4
- data/test/plugin/in_tail/test_position_file.rb +58 -4
- data/test/plugin/test_file_wrapper.rb +115 -0
- data/test/plugin/test_in_exec.rb +1 -1
- data/test/plugin/test_in_forward.rb +59 -83
- data/test/plugin/test_in_http.rb +58 -40
- data/test/plugin/test_in_syslog.rb +66 -56
- data/test/plugin/test_in_tail.rb +298 -26
- data/test/plugin/test_in_tcp.rb +45 -32
- data/test/plugin/test_in_udp.rb +47 -33
- data/test/plugin/test_out_copy.rb +87 -0
- data/test/plugin/test_out_forward.rb +198 -91
- data/test/plugin/test_out_http.rb +1 -1
- data/test/plugin/test_out_stream.rb +18 -8
- data/test/plugin/test_output.rb +15 -3
- data/test/plugin/test_output_as_buffered_backup.rb +2 -0
- data/test/plugin/test_parser_csv.rb +14 -0
- data/test/plugin/test_parser_syslog.rb +14 -0
- data/test/plugin_helper/http_server/test_route.rb +1 -1
- data/test/plugin_helper/service_discovery/test_manager.rb +1 -1
- data/test/plugin_helper/test_child_process.rb +6 -3
- data/test/plugin_helper/test_http_server_helper.rb +34 -27
- data/test/plugin_helper/test_server.rb +144 -139
- data/test/plugin_helper/test_service_discovery.rb +74 -14
- data/test/plugin_helper/test_socket.rb +16 -9
- data/test/test_config.rb +2 -1
- data/test/test_event.rb +16 -0
- data/test/test_formatter.rb +30 -0
- data/test/test_output.rb +2 -2
- data/test/test_supervisor.rb +35 -0
- data/test/test_time_parser.rb +109 -0
- metadata +55 -11
- data/.travis.yml +0 -77
- data/appveyor.yml +0 -31
data/test/plugin/test_in_tail.rb
CHANGED
@@ -6,6 +6,8 @@ require 'fluent/system_config'
|
|
6
6
|
require 'net/http'
|
7
7
|
require 'flexmock/test_unit'
|
8
8
|
require 'timecop'
|
9
|
+
require 'tmpdir'
|
10
|
+
require 'securerandom'
|
9
11
|
|
10
12
|
class TailInputTest < Test::Unit::TestCase
|
11
13
|
include FlexMock::TestCase
|
@@ -22,28 +24,64 @@ class TailInputTest < Test::Unit::TestCase
|
|
22
24
|
end
|
23
25
|
|
24
26
|
def cleanup_directory(path)
|
25
|
-
|
26
|
-
FileUtils.
|
27
|
-
|
28
|
-
FileUtils.rm_f(path) # For Ruby 2.6 or before.
|
27
|
+
unless Dir.exist?(path)
|
28
|
+
FileUtils.mkdir_p(path)
|
29
|
+
return
|
29
30
|
end
|
30
|
-
|
31
|
-
|
31
|
+
|
32
|
+
if Fluent.windows?
|
33
|
+
Dir.glob("*", base: path).each do |name|
|
34
|
+
begin
|
35
|
+
cleanup_file(File.join(path, name))
|
36
|
+
rescue
|
37
|
+
# expect test driver block release already owned file handle.
|
38
|
+
end
|
39
|
+
end
|
40
|
+
else
|
41
|
+
begin
|
42
|
+
FileUtils.rm_f(path, secure:true)
|
43
|
+
rescue ArgumentError
|
44
|
+
FileUtils.rm_f(path) # For Ruby 2.6 or before.
|
45
|
+
end
|
46
|
+
if File.exist?(path)
|
47
|
+
FileUtils.remove_entry_secure(path, true)
|
48
|
+
end
|
32
49
|
end
|
33
50
|
FileUtils.mkdir_p(path)
|
34
51
|
end
|
35
52
|
|
36
53
|
def cleanup_file(path)
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
#
|
44
|
-
#
|
45
|
-
|
46
|
-
|
54
|
+
if Fluent.windows?
|
55
|
+
# On Windows, when the file or directory is removed and created
|
56
|
+
# frequently, there is a case that creating file or directory will
|
57
|
+
# fail. This situation is caused by pending file or directory
|
58
|
+
# deletion which is mentioned on win32 API document [1]
|
59
|
+
# As a workaround, execute rename and remove method.
|
60
|
+
#
|
61
|
+
# [1] https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea#files
|
62
|
+
#
|
63
|
+
file = File.join(Dir.tmpdir, SecureRandom.hex(10))
|
64
|
+
begin
|
65
|
+
FileUtils.mv(path, file)
|
66
|
+
FileUtils.rm_rf(file, secure: true)
|
67
|
+
rescue ArgumentError
|
68
|
+
FileUtils.rm_rf(file) # For Ruby 2.6 or before.
|
69
|
+
end
|
70
|
+
if File.exist?(file)
|
71
|
+
# ensure files are closed for Windows, on which deleted files
|
72
|
+
# are still visible from filesystem
|
73
|
+
GC.start(full_mark: true, immediate_mark: true, immediate_sweep: true)
|
74
|
+
FileUtils.remove_entry_secure(file, true)
|
75
|
+
end
|
76
|
+
else
|
77
|
+
begin
|
78
|
+
FileUtils.rm_f(path, secure: true)
|
79
|
+
rescue ArgumentError
|
80
|
+
FileUtils.rm_f(path) # For Ruby 2.6 or before.
|
81
|
+
end
|
82
|
+
if File.exist?(path)
|
83
|
+
FileUtils.remove_entry_secure(path, true)
|
84
|
+
end
|
47
85
|
end
|
48
86
|
end
|
49
87
|
|
@@ -118,6 +156,7 @@ class TailInputTest < Test::Unit::TestCase
|
|
118
156
|
assert_equal 2, d.instance.rotate_wait
|
119
157
|
assert_equal "#{TMP_DIR}/tail.pos", d.instance.pos_file
|
120
158
|
assert_equal 1000, d.instance.read_lines_limit
|
159
|
+
assert_equal -1, d.instance.read_bytes_limit_per_second
|
121
160
|
assert_equal false, d.instance.ignore_repeated_permission_error
|
122
161
|
assert_nothing_raised do
|
123
162
|
d.instance.have_read_capability?
|
@@ -157,6 +196,22 @@ class TailInputTest < Test::Unit::TestCase
|
|
157
196
|
end
|
158
197
|
end
|
159
198
|
|
199
|
+
sub_test_case "log throttling per file" do
|
200
|
+
test "w/o watcher timer is invalid" do
|
201
|
+
conf = CONFIG_ENABLE_WATCH_TIMER + config_element("ROOT", "", {"read_bytes_limit_per_second" => "8k"})
|
202
|
+
assert_raise(Fluent::ConfigError) do
|
203
|
+
create_driver(conf)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
test "valid" do
|
208
|
+
conf = config_element("ROOT", "", {"read_bytes_limit_per_second" => "8k"})
|
209
|
+
assert_raise(Fluent::ConfigError) do
|
210
|
+
create_driver(conf)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
160
215
|
test "both enable_watch_timer and enable_stat_watcher are false" do
|
161
216
|
assert_raise(Fluent::ConfigError) do
|
162
217
|
create_driver(CONFIG_ENABLE_WATCH_TIMER + CONFIG_DISABLE_STAT_WATCHER + PARSE_SINGLE_LINE_CONFIG)
|
@@ -285,6 +340,124 @@ class TailInputTest < Test::Unit::TestCase
|
|
285
340
|
assert num_events <= d.emit_count
|
286
341
|
end
|
287
342
|
|
343
|
+
sub_test_case "log throttling per file" do
|
344
|
+
teardown do
|
345
|
+
cleanup_file("#{TMP_DIR}/tail.txt")
|
346
|
+
end
|
347
|
+
|
348
|
+
sub_test_case "reads_bytes_per_second w/o throttled" do
|
349
|
+
data("flat 8192 bytes, 2 events" => [:flat, 100, 8192, 2],
|
350
|
+
"flat 8192 bytes, 2 events w/o stat watcher" => [:flat_without_stat, 100, 8192, 2],
|
351
|
+
"flat #{8192*10} bytes, 20 events" => [:flat, 100, (8192 * 10), 20],
|
352
|
+
"flat #{8192*10} bytes, 20 events w/o stat watcher" => [:flat_without_stat, 100, (8192 * 10), 20],
|
353
|
+
"parse #{8192*4} bytes, 8 events" => [:parse, 100, (8192 * 4), 8],
|
354
|
+
"parse #{8192*4} bytes, 8 events w/o stat watcher" => [:parse_without_stat, 100, (8192 * 4), 8],
|
355
|
+
"parse #{8192*10} bytes, 20 events" => [:parse, 100, (8192 * 10), 20],
|
356
|
+
"parse #{8192*10} bytes, 20 events w/o stat watcher" => [:parse_without_stat, 100, (8192 * 10), 20],
|
357
|
+
"flat 8k bytes with unit, 2 events" => [:flat, 100, "8k", 2])
|
358
|
+
def test_emit_with_read_bytes_limit_per_second(data)
|
359
|
+
config_style, limit, limit_bytes, num_events = data
|
360
|
+
case config_style
|
361
|
+
when :flat
|
362
|
+
config = CONFIG_READ_FROM_HEAD + SINGLE_LINE_CONFIG + config_element("", "", { "read_lines_limit" => limit, "read_bytes_limit_per_second" => limit_bytes })
|
363
|
+
when :parse
|
364
|
+
config = CONFIG_READ_FROM_HEAD + config_element("", "", { "read_lines_limit" => limit, "read_bytes_limit_per_second" => limit_bytes }) + PARSE_SINGLE_LINE_CONFIG
|
365
|
+
when :flat_without_stat
|
366
|
+
config = CONFIG_READ_FROM_HEAD + SINGLE_LINE_CONFIG + CONFIG_DISABLE_STAT_WATCHER + config_element("", "", { "read_lines_limit" => limit, "read_bytes_limit_per_second" => limit_bytes })
|
367
|
+
when :parse_without_stat
|
368
|
+
config = CONFIG_READ_FROM_HEAD + CONFIG_DISABLE_STAT_WATCHER + config_element("", "", { "read_lines_limit" => limit, "read_bytes_limit_per_second" => limit_bytes }) + PARSE_SINGLE_LINE_CONFIG
|
369
|
+
end
|
370
|
+
|
371
|
+
msg = 'test' * 2000 # in_tail reads 8192 bytes at once.
|
372
|
+
start_time = Fluent::Clock.now
|
373
|
+
|
374
|
+
d = create_driver(config)
|
375
|
+
d.run(expect_emits: 2) do
|
376
|
+
File.open("#{TMP_DIR}/tail.txt", "ab") {|f|
|
377
|
+
100.times do
|
378
|
+
f.puts msg
|
379
|
+
end
|
380
|
+
}
|
381
|
+
end
|
382
|
+
|
383
|
+
assert_true(Fluent::Clock.now - start_time > 1)
|
384
|
+
assert_equal(num_events.times.map { {"message" => msg} },
|
385
|
+
d.events.collect { |event| event[2] })
|
386
|
+
end
|
387
|
+
|
388
|
+
def test_read_bytes_limit_precede_read_lines_limit
|
389
|
+
config = CONFIG_READ_FROM_HEAD +
|
390
|
+
SINGLE_LINE_CONFIG +
|
391
|
+
config_element("", "", {
|
392
|
+
"read_lines_limit" => 1000,
|
393
|
+
"read_bytes_limit_per_second" => 8192
|
394
|
+
})
|
395
|
+
msg = 'abc'
|
396
|
+
start_time = Fluent::Clock.now
|
397
|
+
d = create_driver(config)
|
398
|
+
d.run(expect_emits: 2) do
|
399
|
+
File.open("#{TMP_DIR}/tail.txt", "ab") {|f|
|
400
|
+
8000.times do
|
401
|
+
f.puts msg
|
402
|
+
end
|
403
|
+
}
|
404
|
+
end
|
405
|
+
|
406
|
+
assert_true(Fluent::Clock.now - start_time > 1)
|
407
|
+
assert_equal(4096.times.map { {"message" => msg} },
|
408
|
+
d.events.collect { |event| event[2] })
|
409
|
+
end
|
410
|
+
end
|
411
|
+
|
412
|
+
sub_test_case "reads_bytes_per_second w/ throttled already" do
|
413
|
+
data("flat 8192 bytes" => [:flat, 100, 8192],
|
414
|
+
"parse 8192 bytes" => [:parse, 100, 8192])
|
415
|
+
def test_emit_with_read_bytes_limit_per_second(data)
|
416
|
+
config_style, limit, limit_bytes = data
|
417
|
+
case config_style
|
418
|
+
when :flat
|
419
|
+
config = CONFIG_READ_FROM_HEAD + SINGLE_LINE_CONFIG + config_element("", "", { "read_lines_limit" => limit, "read_bytes_limit_per_second" => limit_bytes })
|
420
|
+
when :parse
|
421
|
+
config = CONFIG_READ_FROM_HEAD + config_element("", "", { "read_lines_limit" => limit, "read_bytes_limit_per_second" => limit_bytes }) + PARSE_SINGLE_LINE_CONFIG
|
422
|
+
end
|
423
|
+
d = create_driver(config)
|
424
|
+
msg = 'test' * 2000 # in_tail reads 8192 bytes at once.
|
425
|
+
|
426
|
+
mock.proxy(d.instance).io_handler(anything, anything) do |io_handler|
|
427
|
+
require 'fluent/config/types'
|
428
|
+
limit_bytes_value = Fluent::Config.size_value(limit_bytes)
|
429
|
+
io_handler.instance_variable_set(:@number_bytes_read, limit_bytes_value)
|
430
|
+
if Fluent.linux?
|
431
|
+
mock.proxy(io_handler).handle_notify.at_least(5)
|
432
|
+
else
|
433
|
+
mock.proxy(io_handler).handle_notify.twice
|
434
|
+
end
|
435
|
+
io_handler
|
436
|
+
end
|
437
|
+
|
438
|
+
File.open("#{TMP_DIR}/tail.txt", "ab") do |f|
|
439
|
+
100.times do
|
440
|
+
f.puts msg
|
441
|
+
end
|
442
|
+
end
|
443
|
+
|
444
|
+
# We should not do shutdown here due to hard timeout.
|
445
|
+
d.run do
|
446
|
+
start_time = Fluent::Clock.now
|
447
|
+
while Fluent::Clock.now - start_time < 0.8 do
|
448
|
+
File.open("#{TMP_DIR}/tail.txt", "ab") do |f|
|
449
|
+
f.puts msg
|
450
|
+
f.flush
|
451
|
+
end
|
452
|
+
sleep 0.05
|
453
|
+
end
|
454
|
+
end
|
455
|
+
|
456
|
+
assert_equal([], d.events)
|
457
|
+
end
|
458
|
+
end
|
459
|
+
end
|
460
|
+
|
288
461
|
data(flat: CONFIG_READ_FROM_HEAD + SINGLE_LINE_CONFIG,
|
289
462
|
parse: CONFIG_READ_FROM_HEAD + PARSE_SINGLE_LINE_CONFIG)
|
290
463
|
def test_emit_with_read_from_head(data)
|
@@ -551,6 +724,7 @@ class TailInputTest < Test::Unit::TestCase
|
|
551
724
|
File.open("#{TMP_DIR}/tail.txt", "wb") {|f|
|
552
725
|
f.puts "test1"
|
553
726
|
f.puts "test2"
|
727
|
+
f.flush
|
554
728
|
}
|
555
729
|
|
556
730
|
d = create_driver(config)
|
@@ -560,19 +734,23 @@ class TailInputTest < Test::Unit::TestCase
|
|
560
734
|
f.puts "test3\ntest4"
|
561
735
|
f.flush
|
562
736
|
}
|
563
|
-
sleep 1
|
737
|
+
waiting(2) { sleep 0.1 until d.events.length == 2 }
|
564
738
|
File.truncate("#{TMP_DIR}/tail.txt", 6)
|
565
739
|
end
|
566
740
|
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
741
|
+
expected = {
|
742
|
+
emit_count: 2,
|
743
|
+
events: [
|
744
|
+
[Fluent::EventTime, {"message" => "test3"}],
|
745
|
+
[Fluent::EventTime, {"message" => "test4"}],
|
746
|
+
[Fluent::EventTime, {"message" => "test1"}],
|
747
|
+
]
|
748
|
+
}
|
749
|
+
actual = {
|
750
|
+
emit_count: d.emit_count,
|
751
|
+
events: d.events.collect{|event| [event[1].class, event[2]]}
|
752
|
+
}
|
753
|
+
assert_equal(expected, actual)
|
576
754
|
end
|
577
755
|
|
578
756
|
def test_move_truncate_move_back
|
@@ -1876,4 +2054,98 @@ class TailInputTest < Test::Unit::TestCase
|
|
1876
2054
|
waiting(5) { sleep 0.1 until d.instance.instance_variable_get(:@tails).keys.size == 1 }
|
1877
2055
|
d.instance_shutdown
|
1878
2056
|
end
|
2057
|
+
|
2058
|
+
def test_ENOENT_error_after_setup_watcher
|
2059
|
+
path = "#{TMP_DIR}/tail.txt"
|
2060
|
+
FileUtils.touch(path)
|
2061
|
+
config = config_element('', '', {
|
2062
|
+
'format' => 'none',
|
2063
|
+
})
|
2064
|
+
d = create_driver(config)
|
2065
|
+
mock.proxy(d.instance).setup_watcher(anything, anything) do |tw|
|
2066
|
+
cleanup_file(path)
|
2067
|
+
tw
|
2068
|
+
end
|
2069
|
+
assert_nothing_raised do
|
2070
|
+
d.run(shutdown: false) {}
|
2071
|
+
end
|
2072
|
+
d.instance_shutdown
|
2073
|
+
assert($log.out.logs.any?{|log| log.include?("stat() for #{path} failed with Errno::ENOENT. Drop tail watcher for now.\n") })
|
2074
|
+
end
|
2075
|
+
|
2076
|
+
def test_EACCES_error_after_setup_watcher
|
2077
|
+
omit "Cannot test with root user" if Process::UID.eid == 0
|
2078
|
+
path = "#{TMP_DIR}/noaccess/tail.txt"
|
2079
|
+
begin
|
2080
|
+
FileUtils.mkdir_p("#{TMP_DIR}/noaccess")
|
2081
|
+
FileUtils.chmod(0755, "#{TMP_DIR}/noaccess")
|
2082
|
+
FileUtils.touch(path)
|
2083
|
+
config = config_element('', '', {
|
2084
|
+
'tag' => "tail",
|
2085
|
+
'path' => path,
|
2086
|
+
'format' => 'none',
|
2087
|
+
})
|
2088
|
+
d = create_driver(config, false)
|
2089
|
+
mock.proxy(d.instance).setup_watcher(anything, anything) do |tw|
|
2090
|
+
FileUtils.chmod(0000, "#{TMP_DIR}/noaccess")
|
2091
|
+
tw
|
2092
|
+
end
|
2093
|
+
assert_nothing_raised do
|
2094
|
+
d.run(shutdown: false) {}
|
2095
|
+
end
|
2096
|
+
d.instance_shutdown
|
2097
|
+
assert($log.out.logs.any?{|log| log.include?("stat() for #{path} failed with Errno::EACCES. Drop tail watcher for now.\n") })
|
2098
|
+
end
|
2099
|
+
ensure
|
2100
|
+
if File.exist?("#{TMP_DIR}/noaccess")
|
2101
|
+
FileUtils.chmod(0755, "#{TMP_DIR}/noaccess")
|
2102
|
+
FileUtils.rm_rf("#{TMP_DIR}/noaccess")
|
2103
|
+
end
|
2104
|
+
end unless Fluent.windows?
|
2105
|
+
|
2106
|
+
def test_EACCES
|
2107
|
+
path = "#{TMP_DIR}/tail.txt"
|
2108
|
+
FileUtils.touch(path)
|
2109
|
+
config = config_element('', '', {
|
2110
|
+
'format' => 'none',
|
2111
|
+
})
|
2112
|
+
d = create_driver(config)
|
2113
|
+
mock.proxy(Fluent::FileWrapper).stat(path) do |stat|
|
2114
|
+
raise Errno::EACCES
|
2115
|
+
end.at_least(1)
|
2116
|
+
assert_nothing_raised do
|
2117
|
+
d.run(shutdown: false) {}
|
2118
|
+
end
|
2119
|
+
d.instance_shutdown
|
2120
|
+
assert($log.out.logs.any?{|log| log.include?("expand_paths: stat() for #{path} failed with Errno::EACCES. Skip file.\n") })
|
2121
|
+
end
|
2122
|
+
|
2123
|
+
def test_shutdown_timeout
|
2124
|
+
path = "#{TMP_DIR}/tail.txt"
|
2125
|
+
File.open("#{TMP_DIR}/tail.txt", "wb") do |f|
|
2126
|
+
(1024 * 1024 * 5).times do
|
2127
|
+
f.puts "{\"test\":\"fizzbuzz\"}"
|
2128
|
+
end
|
2129
|
+
end
|
2130
|
+
|
2131
|
+
config =
|
2132
|
+
CONFIG_READ_FROM_HEAD +
|
2133
|
+
config_element('', '', {
|
2134
|
+
'format' => 'json',
|
2135
|
+
'skip_refresh_on_startup' => true,
|
2136
|
+
})
|
2137
|
+
d = create_driver(config)
|
2138
|
+
mock.proxy(d.instance).io_handler(anything, anything) do |io_handler|
|
2139
|
+
io_handler.shutdown_timeout = 0.5
|
2140
|
+
io_handler
|
2141
|
+
end
|
2142
|
+
|
2143
|
+
start_time = Fluent::Clock.now
|
2144
|
+
assert_nothing_raised do
|
2145
|
+
d.run(expect_emits: 1)
|
2146
|
+
end
|
2147
|
+
|
2148
|
+
elapsed = Fluent::Clock.now - start_time
|
2149
|
+
assert_true(elapsed > 0.5 && elapsed < 2.5)
|
2150
|
+
end
|
1879
2151
|
end
|
data/test/plugin/test_in_tcp.rb
CHANGED
@@ -5,21 +5,33 @@ require 'fluent/plugin/in_tcp'
|
|
5
5
|
class TcpInputTest < Test::Unit::TestCase
|
6
6
|
def setup
|
7
7
|
Fluent::Test.setup
|
8
|
+
@port = unused_port
|
8
9
|
end
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
11
|
+
def teardown
|
12
|
+
@port = nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def base_config
|
16
|
+
%[
|
17
|
+
port #{@port}
|
18
|
+
tag tcp
|
19
|
+
]
|
20
|
+
end
|
21
|
+
|
22
|
+
def ipv4_config
|
23
|
+
base_config + %[
|
24
|
+
bind 127.0.0.1
|
25
|
+
format none
|
26
|
+
]
|
27
|
+
end
|
28
|
+
|
29
|
+
def ipv6_config
|
30
|
+
base_config + %[
|
31
|
+
bind ::1
|
32
|
+
format none
|
33
|
+
]
|
34
|
+
end
|
23
35
|
|
24
36
|
def create_driver(conf)
|
25
37
|
Fluent::Test::Driver::Input.new(Fluent::Plugin::TcpInput).configure(conf)
|
@@ -35,22 +47,23 @@ class TcpInputTest < Test::Unit::TestCase
|
|
35
47
|
|
36
48
|
|
37
49
|
data(
|
38
|
-
'ipv4' => [
|
39
|
-
'ipv6' => [
|
50
|
+
'ipv4' => ['127.0.0.1', :ipv4],
|
51
|
+
'ipv6' => ['::1', :ipv6],
|
40
52
|
)
|
41
53
|
test 'configure' do |data|
|
42
|
-
|
54
|
+
bind, protocol = data
|
55
|
+
conf = send("#{protocol}_config")
|
43
56
|
omit "IPv6 is not supported on this environment" if protocol == :ipv6 && !ipv6_enabled?
|
44
57
|
|
45
58
|
d = create_driver(conf)
|
46
|
-
assert_equal
|
59
|
+
assert_equal @port, d.instance.port
|
47
60
|
assert_equal bind, d.instance.bind
|
48
61
|
assert_equal "\n", d.instance.delimiter
|
49
62
|
end
|
50
63
|
|
51
64
|
test ' configure w/o parse section' do
|
52
65
|
assert_raise(Fluent::ConfigError.new("<parse> section is required.")) {
|
53
|
-
create_driver(
|
66
|
+
create_driver(base_config)
|
54
67
|
}
|
55
68
|
end
|
56
69
|
|
@@ -82,10 +95,10 @@ class TcpInputTest < Test::Unit::TestCase
|
|
82
95
|
payloads = data['payloads']
|
83
96
|
expecteds = data['expecteds']
|
84
97
|
|
85
|
-
d = create_driver(
|
98
|
+
d = create_driver(base_config + "format #{format}")
|
86
99
|
d.run(expect_records: 2) do
|
87
100
|
payloads.each do |payload|
|
88
|
-
create_tcp_socket('127.0.0.1',
|
101
|
+
create_tcp_socket('127.0.0.1', @port) do |sock|
|
89
102
|
sock.send(payload, 0)
|
90
103
|
end
|
91
104
|
end
|
@@ -105,9 +118,9 @@ class TcpInputTest < Test::Unit::TestCase
|
|
105
118
|
payloads = data['payloads']
|
106
119
|
expecteds = data['expecteds']
|
107
120
|
|
108
|
-
d = create_driver(
|
121
|
+
d = create_driver(base_config + "format #{format}")
|
109
122
|
d.run(expect_records: 2) do
|
110
|
-
create_tcp_socket('127.0.0.1',
|
123
|
+
create_tcp_socket('127.0.0.1', @port) do |sock|
|
111
124
|
payloads.each do |payload|
|
112
125
|
sock.send(payload, 0)
|
113
126
|
end
|
@@ -123,13 +136,13 @@ class TcpInputTest < Test::Unit::TestCase
|
|
123
136
|
end
|
124
137
|
|
125
138
|
test 'source_hostname_key' do
|
126
|
-
d = create_driver(
|
139
|
+
d = create_driver(base_config + %!
|
127
140
|
format none
|
128
141
|
source_hostname_key host
|
129
142
|
!)
|
130
143
|
hostname = nil
|
131
144
|
d.run(expect_records: 1) do
|
132
|
-
create_tcp_socket('127.0.0.1',
|
145
|
+
create_tcp_socket('127.0.0.1', @port) do |sock|
|
133
146
|
sock.do_not_reverse_lookup = false
|
134
147
|
hostname = sock.peeraddr[2]
|
135
148
|
sock.send("test\n", 0)
|
@@ -144,13 +157,13 @@ class TcpInputTest < Test::Unit::TestCase
|
|
144
157
|
end
|
145
158
|
|
146
159
|
test 'source_address_key' do
|
147
|
-
d = create_driver(
|
160
|
+
d = create_driver(base_config + %!
|
148
161
|
format none
|
149
162
|
source_address_key addr
|
150
163
|
!)
|
151
164
|
address = nil
|
152
165
|
d.run(expect_records: 1) do
|
153
|
-
create_tcp_socket('127.0.0.1',
|
166
|
+
create_tcp_socket('127.0.0.1', @port) do |sock|
|
154
167
|
address = sock.peeraddr[3]
|
155
168
|
sock.send("test\n", 0)
|
156
169
|
end
|
@@ -165,7 +178,7 @@ class TcpInputTest < Test::Unit::TestCase
|
|
165
178
|
|
166
179
|
sub_test_case '<security>' do
|
167
180
|
test 'accept from allowed client' do
|
168
|
-
d = create_driver(
|
181
|
+
d = create_driver(ipv4_config + %!
|
169
182
|
<security>
|
170
183
|
<client>
|
171
184
|
network 127.0.0.1
|
@@ -173,7 +186,7 @@ class TcpInputTest < Test::Unit::TestCase
|
|
173
186
|
</security>
|
174
187
|
!)
|
175
188
|
d.run(expect_records: 1) do
|
176
|
-
create_tcp_socket('127.0.0.1',
|
189
|
+
create_tcp_socket('127.0.0.1', @port) do |sock|
|
177
190
|
sock.send("hello\n", 0)
|
178
191
|
end
|
179
192
|
end
|
@@ -185,7 +198,7 @@ class TcpInputTest < Test::Unit::TestCase
|
|
185
198
|
end
|
186
199
|
|
187
200
|
test 'deny from disallowed client' do
|
188
|
-
d = create_driver(
|
201
|
+
d = create_driver(ipv4_config + %!
|
189
202
|
<security>
|
190
203
|
<client>
|
191
204
|
network 200.0.0.0
|
@@ -193,7 +206,7 @@ class TcpInputTest < Test::Unit::TestCase
|
|
193
206
|
</security>
|
194
207
|
!)
|
195
208
|
d.run(shutdown: false, expect_records: 1, timeout: 2) do
|
196
|
-
create_tcp_socket('127.0.0.1',
|
209
|
+
create_tcp_socket('127.0.0.1', @port) do |sock|
|
197
210
|
sock.send("hello\n", 0)
|
198
211
|
end
|
199
212
|
end
|
@@ -205,7 +218,7 @@ class TcpInputTest < Test::Unit::TestCase
|
|
205
218
|
|
206
219
|
sub_test_case '<extract>' do
|
207
220
|
test 'extract tag from record field' do
|
208
|
-
d = create_driver(
|
221
|
+
d = create_driver(base_config + %!
|
209
222
|
<parse>
|
210
223
|
@type json
|
211
224
|
</parse>
|
@@ -214,7 +227,7 @@ class TcpInputTest < Test::Unit::TestCase
|
|
214
227
|
</extract>
|
215
228
|
!)
|
216
229
|
d.run(expect_records: 1) do
|
217
|
-
create_tcp_socket('127.0.0.1',
|
230
|
+
create_tcp_socket('127.0.0.1', @port) do |sock|
|
218
231
|
data = {'msg' => 'hello', 'tag' => 'helper_test'}
|
219
232
|
sock.send("#{data.to_json}\n", 0)
|
220
233
|
end
|