fluentd 1.12.0.rc2 → 1.12.4

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 (74) hide show
  1. checksums.yaml +4 -4
  2. data/.deepsource.toml +13 -0
  3. data/.github/ISSUE_TEMPLATE/config.yml +2 -2
  4. data/.github/workflows/linux-test.yaml +36 -0
  5. data/.github/workflows/macos-test.yaml +30 -0
  6. data/.github/workflows/windows-test.yaml +35 -0
  7. data/.gitlab-ci.yml +41 -19
  8. data/CHANGELOG.md +157 -0
  9. data/MAINTAINERS.md +5 -2
  10. data/README.md +7 -4
  11. data/fluentd.gemspec +5 -4
  12. data/lib/fluent/command/bundler_injection.rb +1 -1
  13. data/lib/fluent/command/ca_generate.rb +6 -3
  14. data/lib/fluent/command/cat.rb +0 -1
  15. data/lib/fluent/command/fluentd.rb +4 -0
  16. data/lib/fluent/command/plugin_config_formatter.rb +16 -1
  17. data/lib/fluent/command/plugin_generator.rb +31 -1
  18. data/lib/fluent/compat/parser.rb +2 -2
  19. data/lib/fluent/config/section.rb +2 -2
  20. data/lib/fluent/config/types.rb +2 -2
  21. data/lib/fluent/event.rb +3 -13
  22. data/lib/fluent/load.rb +0 -1
  23. data/lib/fluent/plugin/file_wrapper.rb +39 -3
  24. data/lib/fluent/plugin/formatter_ltsv.rb +2 -2
  25. data/lib/fluent/plugin/in_http.rb +1 -1
  26. data/lib/fluent/plugin/in_monitor_agent.rb +1 -1
  27. data/lib/fluent/plugin/in_tail.rb +35 -15
  28. data/lib/fluent/plugin/in_tail/position_file.rb +15 -1
  29. data/lib/fluent/plugin/in_tcp.rb +1 -0
  30. data/lib/fluent/plugin/out_copy.rb +18 -5
  31. data/lib/fluent/plugin/out_exec_filter.rb +3 -3
  32. data/lib/fluent/plugin/out_forward.rb +61 -28
  33. data/lib/fluent/plugin/out_http.rb +9 -2
  34. data/lib/fluent/plugin/output.rb +11 -9
  35. data/lib/fluent/plugin/parser_csv.rb +2 -2
  36. data/lib/fluent/plugin/parser_syslog.rb +2 -2
  37. data/lib/fluent/plugin/storage_local.rb +4 -4
  38. data/lib/fluent/plugin_helper/inject.rb +4 -2
  39. data/lib/fluent/plugin_helper/server.rb +4 -2
  40. data/lib/fluent/plugin_helper/socket_option.rb +2 -2
  41. data/lib/fluent/supervisor.rb +13 -5
  42. data/lib/fluent/system_config.rb +2 -1
  43. data/lib/fluent/time.rb +58 -1
  44. data/lib/fluent/version.rb +1 -1
  45. data/templates/new_gem/fluent-plugin.gemspec.erb +3 -3
  46. data/templates/plugin_config_formatter/param.md-table.erb +10 -0
  47. data/test/command/test_fluentd.rb +38 -0
  48. data/test/command/test_plugin_config_formatter.rb +67 -0
  49. data/test/config/test_configurable.rb +1 -1
  50. data/test/plugin/in_tail/test_position_file.rb +59 -5
  51. data/test/plugin/test_file_wrapper.rb +105 -0
  52. data/test/plugin/test_in_exec.rb +1 -1
  53. data/test/plugin/test_in_tail.rb +87 -26
  54. data/test/plugin/test_out_copy.rb +87 -0
  55. data/test/plugin/test_out_forward.rb +94 -6
  56. data/test/plugin/test_out_http.rb +20 -1
  57. data/test/plugin/test_output.rb +15 -3
  58. data/test/plugin/test_output_as_buffered_backup.rb +2 -0
  59. data/test/plugin/test_parser_csv.rb +14 -0
  60. data/test/plugin/test_parser_syslog.rb +16 -2
  61. data/test/plugin/test_sd_file.rb +1 -1
  62. data/test/plugin_helper/service_discovery/test_manager.rb +1 -1
  63. data/test/plugin_helper/test_child_process.rb +5 -2
  64. data/test/plugin_helper/test_http_server_helper.rb +4 -2
  65. data/test/plugin_helper/test_inject.rb +29 -0
  66. data/test/plugin_helper/test_server.rb +26 -7
  67. data/test/test_event.rb +16 -0
  68. data/test/test_formatter.rb +30 -0
  69. data/test/test_output.rb +2 -2
  70. data/test/test_supervisor.rb +31 -0
  71. data/test/test_time_parser.rb +109 -0
  72. metadata +36 -31
  73. data/.travis.yml +0 -77
  74. data/appveyor.yml +0 -31
@@ -390,6 +390,18 @@ class OutputTest < Test::Unit::TestCase
390
390
  assert { logs.none? { |log| log.include?("${chunk_id}") } }
391
391
  end
392
392
 
393
+ test '#extract_placeholders does not log for ${chunk_id} placeholder (with @chunk_keys)' do
394
+ @i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'key1')]))
395
+ tmpl = "/mypath/${chunk_id}/${key1}/tail"
396
+ t = event_time('2016-04-11 20:30:00 +0900')
397
+ v = {key1: "value1", key2: "value2"}
398
+ c = create_chunk(timekey: t, tag: 'fluentd.test.output', variables: v)
399
+ @i.log.out.logs.clear
400
+ @i.extract_placeholders(tmpl, c)
401
+ logs = @i.log.out.logs
402
+ assert { logs.none? { |log| log.include?("${chunk_id}") } }
403
+ end
404
+
393
405
  test '#extract_placeholders logs warn message with not replaced key' do
394
406
  @i.configure(config_element('ROOT', '', {}, [config_element('buffer', '')]))
395
407
  tmpl = "/mypath/${key1}/test"
@@ -868,7 +880,7 @@ class OutputTest < Test::Unit::TestCase
868
880
  test "Warn if primary type is different from secondary type and either primary or secondary has custom_format" do
869
881
  o = create_output(:buffered)
870
882
  mock(o.log).warn("Use different plugin for secondary. Check the plugin works with primary like secondary_file",
871
- { primary: o.class.to_s, secondary: "Fluent::Plugin::TestOutput" })
883
+ primary: o.class.to_s, secondary: "Fluent::Plugin::TestOutput")
872
884
 
873
885
  o.configure(config_element('ROOT','',{},[config_element('secondary','',{'@type'=>'test', 'name' => "cool"})]))
874
886
  assert_not_nil o.instance_variable_get(:@secondary)
@@ -877,7 +889,7 @@ class OutputTest < Test::Unit::TestCase
877
889
  test "don't warn if primary type is the same as secondary type" do
878
890
  o = Fluent::Plugin::TestOutput.new
879
891
  mock(o.log).warn("Use different plugin for secondary. Check the plugin works with primary like secondary_file",
880
- { primary: o.class.to_s, secondary: "Fluent::Plugin::TestOutput" }).never
892
+ primary: o.class.to_s, secondary: "Fluent::Plugin::TestOutput" ).never
881
893
 
882
894
  o.configure(config_element('ROOT','',{'name' => "cool2"},
883
895
  [config_element('secondary','',{'@type'=>'test', 'name' => "cool"}),
@@ -889,7 +901,7 @@ class OutputTest < Test::Unit::TestCase
889
901
  test "don't warn if primary type is different from secondary type and both don't have custom_format" do
890
902
  o = create_output(:standard)
891
903
  mock(o.log).warn("Use different plugin for secondary. Check the plugin works with primary like secondary_file",
892
- { primary: o.class.to_s, secondary: "Fluent::Plugin::TestOutput" }).never
904
+ primary: o.class.to_s, secondary: "Fluent::Plugin::TestOutput").never
893
905
 
894
906
  o.configure(config_element('ROOT','',{},[config_element('secondary','',{'@type'=>'test', 'name' => "cool"})]))
895
907
  assert_not_nil o.instance_variable_get(:@secondary)
@@ -173,6 +173,8 @@ class BufferedOutputBackupTest < Test::Unit::TestCase
173
173
  waiting(5) {
174
174
  target_dir = File.join(File.dirname(target_file), "*")
175
175
  while Dir.glob(target_dir).size.zero?
176
+ # Avoid to lose globbed entries on Windows in busy loop
177
+ sleep 0.1 if Fluent.windows?
176
178
  end
177
179
  }
178
180
  end
@@ -183,4 +183,18 @@ class CSVParserTest < ::Test::Unit::TestCase
183
183
  # And more...
184
184
  end
185
185
  end
186
+
187
+ # "parser_type" config shouldn't hide Fluent::Plugin::Parser#plugin_type
188
+ # https://github.com/fluent/fluentd/issues/3296
189
+ data('normal' => :normal, 'fast' => :fast)
190
+ def test_parser_type_method(engine)
191
+ d = create_driver('keys' => '["time"]','time_key' => 'time', 'parser_type' => engine.to_s)
192
+ assert_equal(:text_per_line, d.instance.parser_type)
193
+ end
194
+
195
+ data('normal' => :normal, 'fast' => :fast)
196
+ def test_parser_engine(engine)
197
+ d = create_driver('keys' => '["time"]', 'time_key' => 'time', 'parser_engine' => engine.to_s)
198
+ assert_equal(engine, d.instance.parser_engine)
199
+ end
186
200
  end
@@ -38,7 +38,7 @@ class SyslogParserTest < ::Test::Unit::TestCase
38
38
  data('regexp' => 'regexp', 'string' => 'string')
39
39
  def test_parse_with_time_format2(param)
40
40
  @parser.configure('time_format' => '%Y-%m-%dT%H:%M:%SZ', 'parser_type' => param)
41
- @parser.instance.parse('2020-03-03T10:14:29Z 192.168.0.1 fluentd[11111]: [error] Syslog test') { |time, record|
41
+ @parser.instance.parse("#{Time.now.year}-03-03T10:14:29Z 192.168.0.1 fluentd[11111]: [error] Syslog test") { |time, record|
42
42
  assert_equal(event_time('Mar 03 10:14:29', format: '%b %d %H:%M:%S'), time)
43
43
  assert_equal(@expected, record)
44
44
  }
@@ -47,7 +47,7 @@ class SyslogParserTest < ::Test::Unit::TestCase
47
47
 
48
48
  def test_parse_with_time_format_rfc5424
49
49
  @parser.configure('time_format' => '%Y-%m-%dT%H:%M:%SZ', 'message_format' => 'rfc5424')
50
- @parser.instance.parse('2020-03-03T10:14:29Z 192.168.0.1 fluentd 11111 - - [error] Syslog test') { |time, record|
50
+ @parser.instance.parse("#{Time.now.year}-03-03T10:14:29Z 192.168.0.1 fluentd 11111 - - [error] Syslog test") { |time, record|
51
51
  assert_equal(event_time('Mar 03 10:14:29', format: '%b %d %H:%M:%S'), time)
52
52
  assert_equal(@expected.merge('host' => '192.168.0.1', 'msgid' => '-', 'extradata' => '-'), record)
53
53
  }
@@ -633,4 +633,18 @@ class SyslogParserTest < ::Test::Unit::TestCase
633
633
  end
634
634
  end
635
635
  end
636
+
637
+ # "parser_type" config shouldn't hide Fluent::Plugin::Parser#plugin_type
638
+ # https://github.com/fluent/fluentd/issues/3296
639
+ data('regexp' => :regexp, 'fast' => :string)
640
+ def test_parser_type_method(engine)
641
+ @parser.configure({'parser_type' => engine.to_s})
642
+ assert_equal(:text_per_line, @parser.instance.parser_type)
643
+ end
644
+
645
+ data('regexp' => :regexp, 'string' => :string)
646
+ def test_parser_engine(engine)
647
+ d = @parser.configure({'parser_engine' => engine.to_s})
648
+ assert_equal(engine, @parser.instance.parser_engine)
649
+ end
636
650
  end
@@ -149,7 +149,7 @@ class FileServiceDiscoveryTest < ::Test::Unit::TestCase
149
149
  assert_empty queue
150
150
  end
151
151
 
152
- test 'Skip if error is occured' do
152
+ test 'Skip if error is occurred' do
153
153
  @sd_file.extend(TestStatEventHelperWrapper)
154
154
 
155
155
  create_tmp_config('config.json', JSON.generate([{ port: 1233, host: '127.0.0.1' }]))
@@ -71,7 +71,7 @@ class TestServiceDiscoveryManager < ::Test::Unit::TestCase
71
71
  test 'if new service added and deleted' do
72
72
  sdm = Fluent::PluginHelper::ServiceDiscovery::Manager.new(log: $log)
73
73
  t = TestSdPlugin.new
74
- mock(Fluent::Plugin).new_sd(:sd_test, anything) { t }
74
+ mock(Fluent::Plugin).new_sd(:sd_test, parent: anything) { t }
75
75
  sdm.configure([{ type: :sd_test, conf: config_element('service_discovery', '', {})}])
76
76
  sdm.start
77
77
 
@@ -1,3 +1,4 @@
1
+ # coding: utf-8
1
2
  require_relative '../helper'
2
3
  require 'fluent/plugin_helper/child_process'
3
4
  require 'fluent/plugin/base'
@@ -269,10 +270,12 @@ class ChildProcessTest < Test::Unit::TestCase
269
270
  Timeout.timeout(TEST_DEADLOCK_TIMEOUT) do
270
271
  ran = false
271
272
  @d.child_process_execute(:t4, "ruby -e 'Signal.trap(:TERM, nil); while sleep 0.1; puts 1; STDOUT.flush rescue nil; end'", mode: [:read]) do |io|
272
- m.lock
273
- ran = true
274
273
  begin
275
274
  while line = io.readline
275
+ unless ran
276
+ m.lock
277
+ ran = true
278
+ end
276
279
  ary << line
277
280
  end
278
281
  rescue
@@ -132,7 +132,9 @@ class HttpHelperTest < Test::Unit::TestCase
132
132
  error = e
133
133
  end
134
134
 
135
- resp = Response.new(response.status.to_s, response.body.read, response.headers)
135
+ if response
136
+ resp = Response.new(response.status.to_s, response.body.read, response.headers)
137
+ end
136
138
  end
137
139
 
138
140
  if error
@@ -352,7 +354,7 @@ class HttpHelperTest < Test::Unit::TestCase
352
354
  watcher.should_receive(:stop).once
353
355
  end
354
356
 
355
- stub(Fluent::PluginHelper::HttpServer::Server).new(anything) { server }
357
+ stub(Fluent::PluginHelper::HttpServer::Server).new(addr: anything, port: anything, logger: anything, default_app: anything) { server }
356
358
  driver.http_server_create_http_server(:http_server_helper_test, addr: '127.0.0.1', port: PORT, logger: NULL_LOGGER) do
357
359
  # nothing
358
360
  end
@@ -187,6 +187,35 @@ class InjectHelperTest < Test::Unit::TestCase
187
187
 
188
188
  record = {"key1" => "value1", "key2" => 2}
189
189
  assert_equal record.merge({"timedata" => unixtime_millis}), @d.inject_values_to_record('tag', time, record)
190
+ assert_equal record.merge({"timedata" => time_in_unix * 1_000}), @d.inject_values_to_record('tag', time_in_unix, record)
191
+ end
192
+
193
+ test 'injects time as unix time micros into specified key' do
194
+ time_in_unix = Time.parse("2016-06-21 08:10:11 +0900").to_i
195
+ time_subsecond = 320_101_224
196
+ time = Fluent::EventTime.new(time_in_unix, time_subsecond)
197
+ unixtime_micros = 1466464211320101
198
+
199
+ @d.configure(config_inject_section("time_key" => "timedata", "time_type" => "unixtime_micros"))
200
+ @d.start
201
+
202
+ record = {"key1" => "value1", "key2" => 2}
203
+ assert_equal record.merge({"timedata" => unixtime_micros}), @d.inject_values_to_record('tag', time, record)
204
+ assert_equal record.merge({"timedata" => time_in_unix * 1_000_000}), @d.inject_values_to_record('tag', time_in_unix, record)
205
+ end
206
+
207
+ test 'injects time as unix time nanos into specified key' do
208
+ time_in_unix = Time.parse("2016-06-21 08:10:11 +0900").to_i
209
+ time_subsecond = 320_101_224
210
+ time = Fluent::EventTime.new(time_in_unix, time_subsecond)
211
+ unixtime_nanos = 1466464211320101224
212
+
213
+ @d.configure(config_inject_section("time_key" => "timedata", "time_type" => "unixtime_nanos"))
214
+ @d.start
215
+
216
+ record = {"key1" => "value1", "key2" => 2}
217
+ assert_equal record.merge({"timedata" => unixtime_nanos}), @d.inject_values_to_record('tag', time, record)
218
+ assert_equal record.merge({"timedata" => time_in_unix * 1_000_000_000}), @d.inject_values_to_record('tag', time_in_unix, record)
190
219
  end
191
220
 
192
221
  test 'injects time as unix time into specified key' do
@@ -234,7 +234,13 @@ class ServerPluginHelperTest < Test::Unit::TestCase
234
234
  assert_raise(ArgumentError.new("BUG: backlog is available for tcp/tls")) do
235
235
  @d.__send__(m, :myserver, PORT, proto: proto, backlog: 500){|x| x }
236
236
  end
237
- assert_raise(ArgumentError.new("BUG: send_keepalive_packet is available for tcp")) do
237
+ end
238
+
239
+ data(
240
+ 'server_create udp' => [:server_create, :udp],
241
+ )
242
+ test 'raise error if tcp/tls send_keepalive_packet option is specified for udp' do |(m, proto)|
243
+ assert_raise(ArgumentError.new("BUG: send_keepalive_packet is available for tcp/tls")) do
238
244
  @d.__send__(m, :myserver, PORT, proto: proto, send_keepalive_packet: true){|x| x }
239
245
  end
240
246
  end
@@ -832,8 +838,9 @@ class ServerPluginHelperTest < Test::Unit::TestCase
832
838
  chain_cert.sign(root_key, "sha256")
833
839
 
834
840
  server_cert, server_key, _ = CertUtil.cert_option_generate_pair(create_server_options, chain_cert.subject)
835
- server_cert.add_extension OpenSSL::X509::Extension.new('basicConstraints', OpenSSL::ASN1.Sequence([OpenSSL::ASN1::Boolean(false)]))
836
- server_cert.add_extension OpenSSL::X509::Extension.new('nsCertType', 'server')
841
+ factory = OpenSSL::X509::ExtensionFactory.new
842
+ server_cert.add_extension(factory.create_extension('basicConstraints', 'CA:FALSE'))
843
+ server_cert.add_extension(factory.create_extension('nsCertType', 'server'))
837
844
  server_cert.sign(chain_key, "sha256")
838
845
 
839
846
  # write chained cert
@@ -1299,7 +1306,7 @@ class ServerPluginHelperTest < Test::Unit::TestCase
1299
1306
 
1300
1307
  test 'can accept all keyword arguments valid for tcp/tls server' do
1301
1308
  assert_nothing_raised do
1302
- @d.server_create_tls(:s, PORT, bind: '127.0.0.1', shared: false, resolve_name: true, linger_timeout: 10, backlog: 500, tls_options: @tls_options) do |data, conn|
1309
+ @d.server_create_tls(:s, PORT, bind: '127.0.0.1', shared: false, resolve_name: true, linger_timeout: 10, backlog: 500, tls_options: @tls_options, send_keepalive_packet: true) do |data, conn|
1303
1310
  # ...
1304
1311
  end
1305
1312
  end
@@ -1494,8 +1501,13 @@ class ServerPluginHelperTest < Test::Unit::TestCase
1494
1501
  test "can't connect with different TLS version" do
1495
1502
  @d.server_create_tls(:s, PORT, tls_options: @tls_options) do |data, conn|
1496
1503
  end
1504
+ if defined?(OpenSSL::SSL::TLS1_3_VERSION)
1505
+ version = :'TLS1_3'
1506
+ else
1507
+ version = :'TLS1_1'
1508
+ end
1497
1509
  assert_raise(OpenSSL::SSL::SSLError, Errno::ECONNRESET) {
1498
- open_tls_session('127.0.0.1', PORT, cert_path: @cert_path, version: :'TLS1_1') do |sock|
1510
+ open_tls_session('127.0.0.1', PORT, cert_path: @cert_path, version: version) do |sock|
1499
1511
  end
1500
1512
  }
1501
1513
  end
@@ -1503,14 +1515,21 @@ class ServerPluginHelperTest < Test::Unit::TestCase
1503
1515
  test "can specify multiple TLS versions by min_version/max_version" do
1504
1516
  omit "min_version=/max_version= is not supported" unless Fluent::TLS::MIN_MAX_AVAILABLE
1505
1517
 
1506
- opts = @tls_options.merge(min_version: :'TLS1_1', max_version: :'TLSv1_2')
1518
+ min_version = :'TLS1_2'
1519
+ if defined?(OpenSSL::SSL::TLS1_3_VERSION)
1520
+ max_version = :'TLS1_3'
1521
+ else
1522
+ max_version = :'TLS1_2'
1523
+ end
1524
+
1525
+ opts = @tls_options.merge(min_version: min_version, max_version: max_version)
1507
1526
  @d.server_create_tls(:s, PORT, tls_options: opts) do |data, conn|
1508
1527
  end
1509
1528
  assert_raise(OpenSSL::SSL::SSLError, Errno::ECONNRESET) {
1510
1529
  open_tls_session('127.0.0.1', PORT, cert_path: @cert_path, version: :'TLS1') do |sock|
1511
1530
  end
1512
1531
  }
1513
- [:'TLS1_1', :'TLS1_2'].each { |ver|
1532
+ [min_version, max_version].each { |ver|
1514
1533
  assert_nothing_raised {
1515
1534
  open_tls_session('127.0.0.1', PORT, cert_path: @cert_path, version: ver) do |sock|
1516
1535
  end
data/test/test_event.rb CHANGED
@@ -401,6 +401,22 @@ module EventTest
401
401
  i += 1
402
402
  }
403
403
  end
404
+
405
+ # `any?` represents an Enumerable method which calls `each` internally
406
+ test 'size_after_any' do
407
+ @es.any?
408
+
409
+ assert_equal 2, @es.size
410
+ end
411
+
412
+ # `any?` represents an Enumerable method which calls `each` internally
413
+ test 'each_after_any' do
414
+ @es.any?
415
+
416
+ count = 0
417
+ @es.each { |time, record| count += 1 }
418
+ assert_equal 2, count
419
+ end
404
420
  end
405
421
 
406
422
  class CompressedMessagePackEventStreamTest < ::Test::Unit::TestCase
@@ -184,6 +184,36 @@ module FormatterTest
184
184
 
185
185
  assert_equal("message=awesome,greeting=hello#{@newline}", formatted)
186
186
  end
187
+
188
+ def record_with_tab
189
+ {'message' => "awe\tsome", 'greeting' => "hello\t"}
190
+ end
191
+
192
+ def test_format_suppresses_tab
193
+ @formatter.configure({})
194
+ formatted = @formatter.format(tag, @time, record_with_tab)
195
+
196
+ assert_equal("message:awe some\tgreeting:hello #{@newline}", formatted)
197
+ end
198
+
199
+ def test_format_suppresses_tab_custom_replacement
200
+ @formatter.configure(
201
+ 'replacement' => 'X',
202
+ )
203
+ formatted = @formatter.format(tag, @time, record_with_tab)
204
+
205
+ assert_equal("message:aweXsome\tgreeting:helloX#{@newline}", formatted)
206
+ end
207
+
208
+ def test_format_suppresses_custom_delimiter
209
+ @formatter.configure(
210
+ 'delimiter' => 'w',
211
+ 'label_delimiter' => '=',
212
+ )
213
+ formatted = @formatter.format(tag, @time, record)
214
+
215
+ assert_equal("message=a esomewgreeting=hello#{@newline}", formatted)
216
+ end
187
217
  end
188
218
 
189
219
  class CsvFormatterTest < ::Test::Unit::TestCase
data/test/test_output.rb CHANGED
@@ -117,7 +117,7 @@ module FluentOutputTest
117
117
  end
118
118
 
119
119
  mock(d.instance.log).warn("Use different plugin for secondary. Check the plugin works with primary like secondary_file",
120
- { primary: d.instance.class.to_s, secondary: "Fluent::Plugin::Test2Output" })
120
+ primary: d.instance.class.to_s, secondary: "Fluent::Plugin::Test2Output")
121
121
  d.configure(CONFIG + %[
122
122
  <secondary>
123
123
  type test2
@@ -133,7 +133,7 @@ module FluentOutputTest
133
133
  d = Fluent::Test::BufferedOutputTestDriver.new(Fluent::ObjectBufferedOutput)
134
134
 
135
135
  mock(d.instance.log).warn("Use different plugin for secondary. Check the plugin works with primary like secondary_file",
136
- { primary: d.instance.class.to_s, secondary: "Fluent::Plugin::Test2Output" }).never
136
+ primary: d.instance.class.to_s, secondary: "Fluent::Plugin::Test2Output").never
137
137
  d.configure(CONFIG + %[
138
138
  <secondary>
139
139
  type test2
@@ -517,6 +517,37 @@ class SupervisorTest < ::Test::Unit::TestCase
517
517
  assert_equal Fluent::Log::LEVEL_ERROR, $log.level
518
518
  end
519
519
 
520
+ def test_enable_shared_socket
521
+ server = DummyServer.new
522
+ begin
523
+ ENV.delete('SERVERENGINE_SOCKETMANAGER_PATH')
524
+ server.before_run
525
+ sleep 0.1 if Fluent.windows? # Wait for starting windows event thread
526
+ assert_not_nil(ENV['SERVERENGINE_SOCKETMANAGER_PATH'])
527
+ ensure
528
+ server.after_run
529
+ ENV.delete('SERVERENGINE_SOCKETMANAGER_PATH')
530
+ end
531
+ end
532
+
533
+ def test_disable_shared_socket
534
+ server = DummyServer.new
535
+ def server.config
536
+ {
537
+ :disable_shared_socket => true,
538
+ }
539
+ end
540
+ begin
541
+ ENV.delete('SERVERENGINE_SOCKETMANAGER_PATH')
542
+ server.before_run
543
+ sleep 0.1 if Fluent.windows? # Wait for starting windows event thread
544
+ assert_nil(ENV['SERVERENGINE_SOCKETMANAGER_PATH'])
545
+ ensure
546
+ server.after_run
547
+ ENV.delete('SERVERENGINE_SOCKETMANAGER_PATH')
548
+ end
549
+ end
550
+
520
551
  def create_debug_dummy_logger
521
552
  dl_opts = {}
522
553
  dl_opts[:log_level] = ServerEngine::DaemonLogger::DEBUG
@@ -228,4 +228,113 @@ class TimeParserTest < ::Test::Unit::TestCase
228
228
  assert_equal_event_time(time, parser.parse("#{time.sec}.#{time.nsec}"))
229
229
  end
230
230
  end
231
+
232
+ sub_test_case 'MixedTimeParser fallback' do
233
+ class DummyForTimeParser
234
+ include Fluent::Configurable
235
+ include Fluent::TimeMixin::Parser
236
+ end
237
+
238
+ test 'no time_format_fallbacks failure' do
239
+ i = DummyForTimeParser.new
240
+ assert_raise(Fluent::ConfigError.new("time_type is :mixed but time_format and time_format_fallbacks is empty.")) do
241
+ i.configure(config_element('parse', '', {'time_type' => 'mixed'}))
242
+ end
243
+ end
244
+
245
+ test 'fallback time format failure' do
246
+ i = DummyForTimeParser.new
247
+ i.configure(config_element('parse', '',
248
+ {'time_type' => 'mixed',
249
+ 'time_format_fallbacks' => ['%iso8601']}))
250
+ parser = i.time_parser_create
251
+ assert_raise(Fluent::TimeParser::TimeParseError.new("invalid time format: value = INVALID, even though fallbacks: Fluent::TimeParser")) do
252
+ parser.parse("INVALID")
253
+ end
254
+ end
255
+
256
+ test 'primary format is unixtime, secondary %iso8601 is used' do
257
+ i = DummyForTimeParser.new
258
+ i.configure(config_element('parse', '',
259
+ {'time_type' => 'mixed',
260
+ 'time_format' => 'unixtime',
261
+ 'time_format_fallbacks' => ['%iso8601']}))
262
+ parser = i.time_parser_create
263
+ time = event_time('2021-01-01T12:00:00+0900')
264
+ assert_equal_event_time(time, parser.parse('2021-01-01T12:00:00+0900'))
265
+ end
266
+
267
+ test 'primary format is %iso8601, secondary unixtime is used' do
268
+ i = DummyForTimeParser.new
269
+ i.configure(config_element('parse', '',
270
+ {'time_type' => 'mixed',
271
+ 'time_format' => '%iso8601',
272
+ 'time_format_fallbacks' => ['unixtime']}))
273
+ parser = i.time_parser_create
274
+ time = event_time('2021-01-01T12:00:00+0900')
275
+ assert_equal_event_time(time, parser.parse("#{time.sec}"))
276
+ end
277
+
278
+ test 'primary format is %iso8601, no secondary is used' do
279
+ i = DummyForTimeParser.new
280
+ i.configure(config_element('parse', '',
281
+ {'time_type' => 'mixed',
282
+ 'time_format' => '%iso8601'}))
283
+ parser = i.time_parser_create
284
+ time = event_time('2021-01-01T12:00:00+0900')
285
+ assert_equal_event_time(time, parser.parse("2021-01-01T12:00:00+0900"))
286
+ end
287
+
288
+ test 'primary format is unixtime, no secondary is used' do
289
+ i = DummyForTimeParser.new
290
+ i.configure(config_element('parse', '',
291
+ {'time_type' => 'mixed',
292
+ 'time_format' => 'unixtime'}))
293
+ parser = i.time_parser_create
294
+ time = event_time('2021-01-01T12:00:00+0900')
295
+ assert_equal_event_time(time, parser.parse("#{time.sec}"))
296
+ end
297
+
298
+ test 'primary format is %iso8601, raise error because of no appropriate secondary' do
299
+ i = DummyForTimeParser.new
300
+ i.configure(config_element('parse', '',
301
+ {'time_type' => 'mixed',
302
+ 'time_format' => '%iso8601'}))
303
+ parser = i.time_parser_create
304
+ time = event_time('2021-01-01T12:00:00+0900')
305
+ assert_raise("Fluent::TimeParser::TimeParseError: invalid time format: value = #{time.sec}, even though fallbacks: Fluent::TimeParser") do
306
+ parser.parse("#{time.sec}")
307
+ end
308
+ end
309
+
310
+ test 'primary format is unixtime, raise error because of no appropriate secondary' do
311
+ i = DummyForTimeParser.new
312
+ i.configure(config_element('parse', '',
313
+ {'time_type' => 'mixed',
314
+ 'time_format' => 'unixtime'}))
315
+ parser = i.time_parser_create
316
+ time = event_time('2021-01-01T12:00:00+0900')
317
+ assert_raise("Fluent::TimeParser::TimeParseError: invalid time format: value = #{time}, even though fallbacks: Fluent::NumericTimeParser") do
318
+ parser.parse("2021-01-01T12:00:00+0900")
319
+ end
320
+ end
321
+
322
+ test 'fallback to unixtime' do
323
+ i = DummyForTimeParser.new
324
+ i.configure(config_element('parse', '', {'time_type' => 'mixed',
325
+ 'time_format_fallbacks' => ['%iso8601', 'unixtime']}))
326
+ parser = i.time_parser_create
327
+ time = event_time('2021-01-01T12:00:00+0900')
328
+ assert_equal_event_time(Fluent::EventTime.new(time.to_i), parser.parse("#{time.sec}"))
329
+ end
330
+
331
+ test 'fallback to %iso8601' do
332
+ i = DummyForTimeParser.new
333
+ i.configure(config_element('parse', '', {'time_type' => 'mixed',
334
+ 'time_format_fallbacks' => ['unixtime', '%iso8601']}))
335
+ parser = i.time_parser_create
336
+ time = event_time('2021-01-01T12:00:00+0900')
337
+ assert_equal_event_time(time, parser.parse('2021-01-01T12:00:00+0900'))
338
+ end
339
+ end
231
340
  end