fluentd 1.9.3 → 1.11.1

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 (91) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/issue-auto-closer.yml +12 -0
  3. data/CHANGELOG.md +182 -0
  4. data/CONTRIBUTING.md +1 -1
  5. data/README.md +4 -0
  6. data/docs/SECURITY_AUDIT.pdf +0 -0
  7. data/lib/fluent/command/debug.rb +1 -0
  8. data/lib/fluent/command/fluentd.rb +25 -1
  9. data/lib/fluent/config.rb +1 -0
  10. data/lib/fluent/daemonizer.rb +88 -0
  11. data/lib/fluent/log.rb +45 -6
  12. data/lib/fluent/match.rb +1 -1
  13. data/lib/fluent/msgpack_factory.rb +13 -6
  14. data/lib/fluent/plugin/buffer.rb +2 -2
  15. data/lib/fluent/plugin/in_dummy.rb +3 -3
  16. data/lib/fluent/plugin/in_forward.rb +2 -2
  17. data/lib/fluent/plugin/in_gc_stat.rb +16 -0
  18. data/lib/fluent/plugin/in_http.rb +146 -75
  19. data/lib/fluent/plugin/in_monitor_agent.rb +1 -1
  20. data/lib/fluent/plugin/in_syslog.rb +4 -4
  21. data/lib/fluent/plugin/in_tail.rb +40 -31
  22. data/lib/fluent/plugin/in_tail/position_file.rb +23 -6
  23. data/lib/fluent/plugin/in_unix.rb +77 -77
  24. data/lib/fluent/plugin/out_copy.rb +1 -1
  25. data/lib/fluent/plugin/out_file.rb +1 -1
  26. data/lib/fluent/plugin/out_forward.rb +25 -22
  27. data/lib/fluent/plugin/out_forward/handshake_protocol.rb +4 -0
  28. data/lib/fluent/plugin/out_forward/load_balancer.rb +1 -1
  29. data/lib/fluent/plugin/out_http.rb +15 -2
  30. data/lib/fluent/plugin/parser_multiline.rb +1 -1
  31. data/lib/fluent/plugin/parser_syslog.rb +303 -62
  32. data/lib/fluent/plugin/sd_file.rb +1 -0
  33. data/lib/fluent/plugin/sd_srv.rb +135 -0
  34. data/lib/fluent/plugin_helper/cert_option.rb +15 -2
  35. data/lib/fluent/plugin_helper/child_process.rb +3 -2
  36. data/lib/fluent/plugin_helper/record_accessor.rb +14 -0
  37. data/lib/fluent/plugin_helper/server.rb +3 -1
  38. data/lib/fluent/plugin_helper/service_discovery.rb +7 -0
  39. data/lib/fluent/plugin_helper/service_discovery/manager.rb +8 -0
  40. data/lib/fluent/plugin_helper/socket.rb +20 -2
  41. data/lib/fluent/plugin_helper/socket_option.rb +21 -3
  42. data/lib/fluent/supervisor.rb +21 -9
  43. data/lib/fluent/system_config.rb +2 -1
  44. data/lib/fluent/test/filter_test.rb +2 -2
  45. data/lib/fluent/test/output_test.rb +3 -3
  46. data/lib/fluent/version.rb +1 -1
  47. data/test/command/test_fluentd.rb +71 -12
  48. data/test/config/test_system_config.rb +2 -0
  49. data/test/helper.rb +2 -2
  50. data/test/plugin/in_tail/test_fifo.rb +121 -0
  51. data/test/plugin/in_tail/test_io_handler.rb +132 -0
  52. data/test/plugin/in_tail/test_position_file.rb +25 -1
  53. data/test/plugin/out_forward/test_handshake_protocol.rb +10 -1
  54. data/test/plugin/out_forward/test_load_balancer.rb +46 -0
  55. data/test/plugin/test_buf_file.rb +3 -1
  56. data/test/plugin/test_buffer.rb +20 -0
  57. data/test/plugin/test_compressable.rb +7 -4
  58. data/test/plugin/test_in_dummy.rb +12 -14
  59. data/test/plugin/test_in_forward.rb +2 -2
  60. data/test/plugin/test_in_gc_stat.rb +24 -1
  61. data/test/plugin/test_in_http.rb +57 -0
  62. data/test/plugin/test_in_syslog.rb +16 -1
  63. data/test/plugin/test_in_tail.rb +43 -20
  64. data/test/plugin/test_in_unix.rb +128 -73
  65. data/test/plugin/test_out_forward.rb +39 -3
  66. data/test/plugin/test_out_http.rb +38 -0
  67. data/test/plugin/test_out_null.rb +1 -1
  68. data/test/plugin/test_output_as_buffered_retries.rb +12 -4
  69. data/test/plugin/test_output_as_buffered_secondary.rb +9 -1
  70. data/test/plugin/test_parser_syslog.rb +106 -46
  71. data/test/plugin/test_sd_file.rb +17 -0
  72. data/test/plugin/test_sd_srv.rb +230 -0
  73. data/test/plugin_helper/data/cert/cert-with-CRLF.pem +19 -0
  74. data/test/plugin_helper/data/cert/cert_chains/ca-cert-key.pem +27 -0
  75. data/test/plugin_helper/data/cert/cert_chains/ca-cert.pem +20 -0
  76. data/test/plugin_helper/data/cert/cert_chains/cert-key.pem +27 -0
  77. data/test/plugin_helper/data/cert/cert_chains/cert.pem +40 -0
  78. data/test/plugin_helper/data/cert/generate_cert.rb +38 -0
  79. data/test/plugin_helper/http_server/test_app.rb +1 -1
  80. data/test/plugin_helper/http_server/test_route.rb +1 -1
  81. data/test/plugin_helper/test_cert_option.rb +2 -0
  82. data/test/plugin_helper/test_child_process.rb +20 -3
  83. data/test/plugin_helper/test_http_server_helper.rb +2 -2
  84. data/test/plugin_helper/test_record_accessor.rb +41 -0
  85. data/test/plugin_helper/test_server.rb +1 -1
  86. data/test/plugin_helper/test_service_discovery.rb +37 -4
  87. data/test/plugin_helper/test_socket.rb +131 -0
  88. data/test/test_daemonizer.rb +91 -0
  89. data/test/test_log.rb +44 -0
  90. data/test/test_msgpack_factory.rb +18 -0
  91. metadata +28 -2
@@ -24,7 +24,7 @@ module Fluent
24
24
  SYSTEM_CONFIG_PARAMETERS = [
25
25
  :workers, :root_dir, :log_level,
26
26
  :suppress_repeated_stacktrace, :emit_error_log_interval, :suppress_config_dump,
27
- :log_event_verbose,
27
+ :log_event_verbose, :ignore_repeated_log_interval,
28
28
  :without_source, :rpc_endpoint, :enable_get_dump, :process_name,
29
29
  :file_permission, :dir_permission, :counter_server, :counter_client,
30
30
  :strict_config_value, :enable_msgpack_time_support
@@ -34,6 +34,7 @@ module Fluent
34
34
  config_param :root_dir, :string, default: nil
35
35
  config_param :log_level, :enum, list: [:trace, :debug, :info, :warn, :error, :fatal], default: 'info'
36
36
  config_param :suppress_repeated_stacktrace, :bool, default: nil
37
+ config_param :ignore_repeated_log_interval, :time, default: nil
37
38
  config_param :emit_error_log_interval, :time, default: nil
38
39
  config_param :suppress_config_dump, :bool, default: nil
39
40
  config_param :log_event_verbose, :bool, default: nil
@@ -30,12 +30,12 @@ module Fluent
30
30
  attr_reader :filtered
31
31
  attr_accessor :tag
32
32
 
33
- def emit(record, time = Engine.now)
33
+ def emit(record, time = EventTime.now)
34
34
  emit_with_tag(@tag, record, time)
35
35
  end
36
36
  alias_method :filter, :emit
37
37
 
38
- def emit_with_tag(tag, record, time = Engine.now)
38
+ def emit_with_tag(tag, record, time = EventTime.now)
39
39
  @events[tag] ||= MultiEventStream.new
40
40
  @events[tag].add(time, record)
41
41
  end
@@ -41,7 +41,7 @@ module Fluent
41
41
 
42
42
  attr_accessor :tag
43
43
 
44
- def emit(record, time=Engine.now)
44
+ def emit(record, time=EventTime.now)
45
45
  es = OneEventStream.new(time, record)
46
46
  @instance.emit_events(@tag, es)
47
47
  end
@@ -62,7 +62,7 @@ module Fluent
62
62
 
63
63
  attr_accessor :tag
64
64
 
65
- def emit(record, time=Engine.now)
65
+ def emit(record, time=EventTime.now)
66
66
  @entries << [time, record]
67
67
  self
68
68
  end
@@ -110,7 +110,7 @@ module Fluent
110
110
 
111
111
  attr_accessor :tag
112
112
 
113
- def emit(record, time=Engine.now)
113
+ def emit(record, time=EventTime.now)
114
114
  @entries << [time, record]
115
115
  self
116
116
  end
@@ -16,6 +16,6 @@
16
16
 
17
17
  module Fluent
18
18
 
19
- VERSION = '1.9.3'
19
+ VERSION = '1.11.1'
20
20
 
21
21
  end
@@ -16,6 +16,7 @@ class TestFluentdCommand < ::Test::Unit::TestCase
16
16
  FileUtils.mkdir_p(TMP_DIR)
17
17
  @supervisor_pid = nil
18
18
  @worker_pids = []
19
+ ENV["TEST_RUBY_PATH"] = nil
19
20
  end
20
21
 
21
22
  def process_exist?(pid)
@@ -84,9 +85,22 @@ class TestFluentdCommand < ::Test::Unit::TestCase
84
85
  null_stream.close rescue nil
85
86
  end
86
87
 
88
+ def eager_read(io)
89
+ buf = +''
90
+
91
+ loop do
92
+ b = io.read_nonblock(1024, nil, exception: false)
93
+ if b == :wait_readable || b.nil?
94
+ return buf
95
+ end
96
+ buf << b
97
+ end
98
+ end
99
+
87
100
  def assert_log_matches(cmdline, *pattern_list, patterns_not_match: [], timeout: 10, env: {})
88
101
  matched = false
89
- assert_error_msg = "matched correctly"
102
+ matched_wrongly = false
103
+ assert_error_msg = ""
90
104
  stdio_buf = ""
91
105
  begin
92
106
  execute_command(cmdline, TMP_DIR, env) do |pid, stdout|
@@ -97,7 +111,7 @@ class TestFluentdCommand < ::Test::Unit::TestCase
97
111
  next unless readables
98
112
  break if readables.first.eof?
99
113
 
100
- buf = readables.first.readpartial(1024)
114
+ buf = eager_read(readables.first)
101
115
  # puts buf
102
116
  stdio_buf << buf
103
117
  lines = stdio_buf.split("\n")
@@ -116,13 +130,18 @@ class TestFluentdCommand < ::Test::Unit::TestCase
116
130
  end
117
131
  end
118
132
  rescue Timeout::Error
119
- assert_error_msg = "execution timeout with command out:\n" + stdio_buf
133
+ assert_error_msg = "execution timeout"
120
134
  rescue => e
121
- assert_error_msg = "unexpected error in launching fluentd: #{e.inspect}\n" + stdio_buf
135
+ assert_error_msg = "unexpected error in launching fluentd: #{e.inspect}"
136
+ else
137
+ assert_error_msg = "log doesn't match" unless matched
122
138
  end
123
- assert matched, assert_error_msg
124
139
 
125
- unless patterns_not_match.empty?
140
+ if patterns_not_match.empty?
141
+ assert_error_msg = build_message(assert_error_msg,
142
+ "<?>\nwas expected to include:\n<?>",
143
+ stdio_buf, pattern_list)
144
+ else
126
145
  lines = stdio_buf.split("\n")
127
146
  patterns_not_match.each do |ptn|
128
147
  matched_wrongly = if ptn.is_a? Regexp
@@ -130,9 +149,17 @@ class TestFluentdCommand < ::Test::Unit::TestCase
130
149
  else
131
150
  lines.any?{|line| line.include?(ptn) }
132
151
  end
133
- assert_false matched_wrongly, "pattern exists in logs wrongly:\n" + stdio_buf
152
+ if matched_wrongly
153
+ assert_error_msg << "\n" unless assert_error_msg.empty?
154
+ assert_error_msg << "pattern exists in logs wrongly: #{ptn}"
155
+ end
134
156
  end
157
+ assert_error_msg = build_message(assert_error_msg,
158
+ "<?>\nwas expected to include:\n<?>\nand not include:\n<?>",
159
+ stdio_buf, pattern_list, patterns_not_match)
135
160
  end
161
+
162
+ assert matched && !matched_wrongly, assert_error_msg
136
163
  end
137
164
 
138
165
  def assert_fluentd_fails_to_start(cmdline, *pattern_list, timeout: 10)
@@ -150,7 +177,7 @@ class TestFluentdCommand < ::Test::Unit::TestCase
150
177
  next unless readables
151
178
  next if readables.first.eof?
152
179
 
153
- stdio_buf << readables.first.readpartial(1024)
180
+ stdio_buf << eager_read(readables.first)
154
181
  lines = stdio_buf.split("\n")
155
182
  if lines.any?{|line| line.include?("fluentd worker is now running") }
156
183
  running = true
@@ -830,8 +857,7 @@ CONF
830
857
  '-external-encoding' => '--external-encoding=utf-8',
831
858
  '-internal-encoding' => '--internal-encoding=utf-8',
832
859
  )
833
- test "-E option is set to RUBYOPT3" do |opt|
834
- omit "hard to run correctly on Windows. Need to debug." if Fluent.windows?
860
+ test "-E option is set to RUBYOPT" do |opt|
835
861
  conf = <<CONF
836
862
  <source>
837
863
  @type dummy
@@ -842,6 +868,7 @@ CONF
842
868
  </match>
843
869
  CONF
844
870
  conf_path = create_conf_file('rubyopt_test.conf', conf)
871
+ opt << " #{ENV['RUBYOPT']}" if ENV['RUBYOPT']
845
872
  assert_log_matches(
846
873
  create_cmdline(conf_path),
847
874
  *opt.split(' '),
@@ -850,7 +877,7 @@ CONF
850
877
  )
851
878
  end
852
879
 
853
- test "without RUBYOPT" do
880
+ test "without RUBYOPT" do
854
881
  conf = <<CONF
855
882
  <source>
856
883
  @type dummy
@@ -865,7 +892,7 @@ CONF
865
892
  end
866
893
 
867
894
  test 'invalid values are set to RUBYOPT' do
868
- omit "hard to run correctly on Windows. Need to debug." if Fluent.windows?
895
+ omit "hard to run correctly because RUBYOPT=-r/path/to/bundler/setup is required on Windows while this test set invalid RUBYOPT" if Fluent.windows?
869
896
  conf = <<CONF
870
897
  <source>
871
898
  @type dummy
@@ -883,6 +910,38 @@ CONF
883
910
  )
884
911
  end
885
912
 
913
+ # https://github.com/fluent/fluentd/issues/2915
914
+ test "ruby path contains spaces" do
915
+ conf = <<CONF
916
+ <source>
917
+ @type dummy
918
+ tag dummy
919
+ </source>
920
+ <match>
921
+ @type null
922
+ </match>
923
+ CONF
924
+ ruby_path = ServerEngine.ruby_bin_path
925
+ tmp_ruby_path = File.join(TMP_DIR, "ruby with spaces")
926
+ if Fluent.windows?
927
+ tmp_ruby_path << ".bat"
928
+ File.open(tmp_ruby_path, "w") do |file|
929
+ file.write "#{ruby_path} %*"
930
+ end
931
+ else
932
+ FileUtils.ln_sf(ruby_path, tmp_ruby_path)
933
+ end
934
+ ENV["TEST_RUBY_PATH"] = tmp_ruby_path
935
+ cmd_path = File.expand_path(File.dirname(__FILE__) + "../../../bin/fluentd")
936
+ conf_path = create_conf_file('space_mixed_ruby_path_test.conf', conf)
937
+ args = ["bundle", "exec", tmp_ruby_path, cmd_path, "-c", conf_path]
938
+ assert_log_matches(
939
+ args,
940
+ 'spawn command to main:',
941
+ '-Eascii-8bit:ascii-8bit'
942
+ )
943
+ end
944
+
886
945
  test 'success to start workers when file buffer is configured in non-workers way only for specific worker' do
887
946
  conf = <<CONF
888
947
  <system>
@@ -73,6 +73,7 @@ module Fluent::Config
73
73
  assert_nil(sc.root_dir)
74
74
  assert_equal(Fluent::Log::LEVEL_INFO, sc.log_level)
75
75
  assert_nil(sc.suppress_repeated_stacktrace)
76
+ assert_nil(sc.ignore_repeated_log_interval)
76
77
  assert_nil(sc.emit_error_log_interval)
77
78
  assert_nil(sc.suppress_config_dump)
78
79
  assert_nil(sc.without_source)
@@ -86,6 +87,7 @@ module Fluent::Config
86
87
  'root_dir' => ['root_dir', File.join(TMP_DIR, 'root')],
87
88
  'log_level' => ['log_level', 'error'],
88
89
  'suppress_repeated_stacktrace' => ['suppress_repeated_stacktrace', true],
90
+ 'ignore_repeated_log_interval' => ['ignore_repeated_log_interval', 10],
89
91
  'log_event_verbose' => ['log_event_verbose', true],
90
92
  'suppress_config_dump' => ['suppress_config_dump', true],
91
93
  'without_source' => ['without_source', true],
@@ -49,8 +49,8 @@ require 'fluent/plugin_helper'
49
49
  require 'fluent/msgpack_factory'
50
50
  require 'fluent/time'
51
51
  require 'serverengine'
52
- require 'helpers/fuzzy_assert'
53
- require 'helpers/process_extenstion'
52
+ require_relative 'helpers/fuzzy_assert'
53
+ require_relative 'helpers/process_extenstion'
54
54
 
55
55
  module Fluent
56
56
  module Plugin
@@ -0,0 +1,121 @@
1
+ require_relative '../../helper'
2
+
3
+ require 'fluent/plugin/in_tail'
4
+
5
+ class IntailFIFO < Test::Unit::TestCase
6
+ sub_test_case '#read_line' do
7
+ test 'returns lines spliting per `\n`' do
8
+ fifo = Fluent::Plugin::TailInput::TailWatcher::FIFO.new(Encoding::ASCII_8BIT, Encoding::ASCII_8BIT)
9
+ text = ("test\n" * 3).force_encoding(Encoding::ASCII_8BIT)
10
+ fifo << text
11
+ lines = []
12
+ fifo.read_lines(lines)
13
+ assert_equal Encoding::ASCII_8BIT, lines[0].encoding
14
+ assert_equal ["test\n", "test\n", "test\n"], lines
15
+ end
16
+
17
+ test 'concant line when line is separated' do
18
+ fifo = Fluent::Plugin::TailInput::TailWatcher::FIFO.new(Encoding::ASCII_8BIT, Encoding::ASCII_8BIT)
19
+ text = ("test\n" * 3 + 'test').force_encoding(Encoding::ASCII_8BIT)
20
+ fifo << text
21
+ lines = []
22
+ fifo.read_lines(lines)
23
+ assert_equal Encoding::ASCII_8BIT, lines[0].encoding
24
+ assert_equal ["test\n", "test\n", "test\n"], lines
25
+
26
+ fifo << "2\n"
27
+ fifo.read_lines(lines)
28
+ assert_equal Encoding::ASCII_8BIT, lines[0].encoding
29
+ assert_equal ["test\n", "test\n", "test\n", "test2\n"], lines
30
+ end
31
+
32
+ test 'returns lines which convert encoding' do
33
+ fifo = Fluent::Plugin::TailInput::TailWatcher::FIFO.new(Encoding::ASCII_8BIT, Encoding::UTF_8)
34
+ text = ("test\n" * 3).force_encoding(Encoding::ASCII_8BIT)
35
+ fifo << text
36
+ lines = []
37
+ fifo.read_lines(lines)
38
+ assert_equal Encoding::UTF_8, lines[0].encoding
39
+ assert_equal ["test\n", "test\n", "test\n"], lines
40
+ end
41
+
42
+ test 'reads lines as from_encoding' do
43
+ fifo = Fluent::Plugin::TailInput::TailWatcher::FIFO.new(Encoding::UTF_8, Encoding::ASCII_8BIT)
44
+ text = ("test\n" * 3).force_encoding(Encoding::UTF_8)
45
+ fifo << text
46
+ lines = []
47
+ fifo.read_lines(lines)
48
+ assert_equal Encoding::ASCII_8BIT, lines[0].encoding
49
+ assert_equal ["test\n", "test\n", "test\n"], lines
50
+ end
51
+
52
+ sub_test_case 'when it includes multi byte chars' do
53
+ test 'handles it as ascii_8bit' do
54
+ fifo = Fluent::Plugin::TailInput::TailWatcher::FIFO.new(Encoding::ASCII_8BIT, Encoding::ASCII_8BIT)
55
+ text = ("てすと\n" * 3).force_encoding(Encoding::ASCII_8BIT)
56
+ fifo << text
57
+ lines = []
58
+ fifo.read_lines(lines)
59
+ assert_equal Encoding::ASCII_8BIT, lines[0].encoding
60
+ assert_equal ["てすと\n", "てすと\n", "てすと\n"].map { |e| e.force_encoding(Encoding::ASCII_8BIT) }, lines
61
+ end
62
+
63
+ test 'replaces character with ? when convert error happens' do
64
+ fifo = Fluent::Plugin::TailInput::TailWatcher::FIFO.new(Encoding::UTF_8, Encoding::ASCII_8BIT)
65
+ text = ("てすと\n" * 3).force_encoding(Encoding::UTF_8)
66
+ fifo << text
67
+ lines = []
68
+ fifo.read_lines(lines)
69
+ assert_equal Encoding::ASCII_8BIT, lines[0].encoding
70
+ assert_equal ["???\n", "???\n", "???\n"].map { |e| e.force_encoding(Encoding::ASCII_8BIT) }, lines
71
+ end
72
+ end
73
+
74
+ test 'reutrns nothing when buffer is empty' do
75
+ fifo = Fluent::Plugin::TailInput::TailWatcher::FIFO.new(Encoding::ASCII_8BIT, Encoding::ASCII_8BIT)
76
+ lines = []
77
+ fifo.read_lines(lines)
78
+ assert_equal [], lines
79
+
80
+ text = "test\n" * 3
81
+ fifo << text
82
+ fifo.read_lines(lines)
83
+ assert_equal ["test\n", "test\n", "test\n"], lines
84
+
85
+ lines = []
86
+ fifo.read_lines(lines)
87
+ assert_equal [], lines
88
+ end
89
+ end
90
+
91
+ sub_test_case '#<<' do
92
+ test 'does not make any change about encoding to an argument' do
93
+ fifo = Fluent::Plugin::TailInput::TailWatcher::FIFO.new(Encoding::ASCII_8BIT, Encoding::ASCII_8BIT)
94
+ text = ("test\n" * 3).force_encoding(Encoding::UTF_8)
95
+
96
+ assert_equal Encoding::UTF_8, text.encoding
97
+ fifo << text
98
+ assert_equal Encoding::UTF_8, text.encoding
99
+ end
100
+ end
101
+
102
+ sub_test_case '#bytesize' do
103
+ test 'reutrns buffer size' do
104
+ fifo = Fluent::Plugin::TailInput::TailWatcher::FIFO.new(Encoding::ASCII_8BIT, Encoding::ASCII_8BIT)
105
+ text = "test\n" * 3 + 'test'
106
+ fifo << text
107
+
108
+ assert_equal text.bytesize, fifo.bytesize
109
+ lines = []
110
+ fifo.read_lines(lines)
111
+ assert_equal ["test\n", "test\n", "test\n"], lines
112
+
113
+ assert_equal 'test'.bytesize, fifo.bytesize
114
+ fifo << "2\n"
115
+ fifo.read_lines(lines)
116
+ assert_equal ["test\n", "test\n", "test\n", "test2\n"], lines
117
+
118
+ assert_equal 0, fifo.bytesize
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,132 @@
1
+ require_relative '../../helper'
2
+
3
+ require 'fluent/plugin/in_tail'
4
+ require 'tempfile'
5
+
6
+ class IntailIOHandlerTest < Test::Unit::TestCase
7
+ setup do
8
+ @file = Tempfile.new('intail_io_handler').binmode
9
+ end
10
+
11
+ teardown do
12
+ @file.close rescue nil
13
+ @file.unlink rescue nil
14
+ end
15
+
16
+ test '#on_notify load file content and passed it to receive_lines method' do
17
+ text = "this line is test\ntest line is test\n"
18
+ @file.write(text)
19
+ @file.close
20
+
21
+ watcher = 'watcher'
22
+
23
+ update_pos = 0
24
+
25
+ stub(watcher).pe do
26
+ pe = 'position_file'
27
+ stub(pe).read_pos { 0 }
28
+ stub(pe).update_pos { |val| update_pos = val }
29
+ pe
30
+ end
31
+
32
+ returned_lines = ''
33
+ r = Fluent::Plugin::TailInput::TailWatcher::IOHandler.new(watcher, path: @file.path, read_lines_limit: 100, log: $log, open_on_every_update: false) do |lines, _watcher|
34
+ returned_lines << lines.join
35
+ true
36
+ end
37
+
38
+ r.on_notify
39
+ assert_equal text.bytesize, update_pos
40
+ assert_equal text, returned_lines
41
+
42
+ r.on_notify
43
+
44
+ assert_equal text.bytesize, update_pos
45
+ assert_equal text, returned_lines
46
+ end
47
+
48
+ sub_test_case 'when open_on_every_update is true and read_pos returns always 0' do
49
+ test 'open new IO and change pos to 0 and read it' do
50
+ text = "this line is test\ntest line is test\n"
51
+ @file.write(text)
52
+ @file.close
53
+
54
+ update_pos = 0
55
+
56
+ watcher = 'watcher'
57
+ stub(watcher).pe do
58
+ pe = 'position_file'
59
+ stub(pe).read_pos { 0 }
60
+ stub(pe).update_pos { |val| update_pos = val }
61
+ pe
62
+ end
63
+
64
+ returned_lines = ''
65
+ r = Fluent::Plugin::TailInput::TailWatcher::IOHandler.new(watcher, path: @file.path, read_lines_limit: 100, log: $log, open_on_every_update: true) do |lines, _watcher|
66
+ returned_lines << lines.join
67
+ true
68
+ end
69
+
70
+ r.on_notify
71
+ assert_equal text.bytesize, update_pos
72
+ assert_equal text, returned_lines
73
+
74
+ r.on_notify
75
+ assert_equal text * 2, returned_lines
76
+ end
77
+ end
78
+
79
+ sub_test_case 'when limit is 5' do
80
+ test 'call receive_lines once when short line(less than 8192)' do
81
+ text = "line\n" * 8
82
+ @file.write(text)
83
+ @file.close
84
+
85
+ update_pos = 0
86
+
87
+ watcher = 'watcher'
88
+ stub(watcher).pe do
89
+ pe = 'position_file'
90
+ stub(pe).read_pos { 0 }
91
+ stub(pe).update_pos { |val| update_pos = val }
92
+ pe
93
+ end
94
+
95
+ returned_lines = []
96
+ r = Fluent::Plugin::TailInput::TailWatcher::IOHandler.new(watcher, path: @file.path, read_lines_limit: 5, log: $log, open_on_every_update: false) do |lines, _watcher|
97
+ returned_lines << lines.dup
98
+ true
99
+ end
100
+
101
+ r.on_notify
102
+ assert_equal 8, returned_lines[0].size
103
+ end
104
+
105
+ test 'call receive_lines some times when long line(more than 8192)' do
106
+ t = 'line' * (8192 / 8)
107
+ text = "#{t}\n" * 8
108
+ @file.write(text)
109
+ @file.close
110
+
111
+ update_pos = 0
112
+
113
+ watcher = 'watcher'
114
+ stub(watcher).pe do
115
+ pe = 'position_file'
116
+ stub(pe).read_pos { 0 }
117
+ stub(pe).update_pos { |val| update_pos = val }
118
+ pe
119
+ end
120
+
121
+ returned_lines = []
122
+ r = Fluent::Plugin::TailInput::TailWatcher::IOHandler.new(watcher, path: @file.path, read_lines_limit: 5, log: $log, open_on_every_update: false) do |lines, _watcher|
123
+ returned_lines << lines.dup
124
+ true
125
+ end
126
+
127
+ r.on_notify
128
+ assert_equal 5, returned_lines[0].size
129
+ assert_equal 3, returned_lines[1].size
130
+ end
131
+ end
132
+ end