fluentd 0.14.7-x86-mingw32 → 0.14.10-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.

Files changed (120) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.travis.yml +2 -0
  4. data/CONTRIBUTING.md +6 -1
  5. data/ChangeLog +95 -0
  6. data/Rakefile +21 -0
  7. data/appveyor.yml +1 -0
  8. data/code-of-conduct.md +3 -0
  9. data/example/out_exec_filter.conf +42 -0
  10. data/fluentd.gemspec +1 -1
  11. data/lib/fluent/agent.rb +2 -2
  12. data/lib/fluent/command/binlog_reader.rb +1 -1
  13. data/lib/fluent/command/cat.rb +15 -4
  14. data/lib/fluent/compat/output.rb +14 -9
  15. data/lib/fluent/compat/parser.rb +141 -11
  16. data/lib/fluent/config/configure_proxy.rb +2 -11
  17. data/lib/fluent/config/section.rb +8 -1
  18. data/lib/fluent/configurable.rb +1 -3
  19. data/lib/fluent/env.rb +1 -1
  20. data/lib/fluent/log.rb +1 -1
  21. data/lib/fluent/plugin/base.rb +17 -0
  22. data/lib/fluent/plugin/filter_parser.rb +108 -0
  23. data/lib/fluent/plugin/filter_record_transformer.rb +14 -35
  24. data/lib/fluent/plugin/filter_stdout.rb +1 -1
  25. data/lib/fluent/plugin/formatter.rb +5 -0
  26. data/lib/fluent/plugin/formatter_msgpack.rb +4 -0
  27. data/lib/fluent/plugin/formatter_stdout.rb +3 -2
  28. data/lib/fluent/plugin/formatter_tsv.rb +34 -0
  29. data/lib/fluent/plugin/in_exec.rb +48 -93
  30. data/lib/fluent/plugin/in_forward.rb +66 -265
  31. data/lib/fluent/plugin/in_http.rb +68 -65
  32. data/lib/fluent/plugin/in_monitor_agent.rb +8 -4
  33. data/lib/fluent/plugin/in_syslog.rb +42 -58
  34. data/lib/fluent/plugin/in_tail.rb +29 -14
  35. data/lib/fluent/plugin/in_tcp.rb +54 -14
  36. data/lib/fluent/plugin/in_udp.rb +49 -13
  37. data/lib/fluent/plugin/multi_output.rb +1 -3
  38. data/lib/fluent/plugin/out_exec.rb +58 -71
  39. data/lib/fluent/plugin/out_exec_filter.rb +199 -279
  40. data/lib/fluent/plugin/out_file.rb +172 -81
  41. data/lib/fluent/plugin/out_forward.rb +229 -206
  42. data/lib/fluent/plugin/out_stdout.rb +6 -21
  43. data/lib/fluent/plugin/output.rb +90 -59
  44. data/lib/fluent/plugin/parser.rb +121 -61
  45. data/lib/fluent/plugin/parser_csv.rb +9 -3
  46. data/lib/fluent/plugin/parser_json.rb +37 -35
  47. data/lib/fluent/plugin/parser_ltsv.rb +11 -19
  48. data/lib/fluent/plugin/parser_msgpack.rb +50 -0
  49. data/lib/fluent/plugin/parser_regexp.rb +15 -42
  50. data/lib/fluent/plugin/parser_tsv.rb +8 -3
  51. data/lib/fluent/plugin_helper.rb +10 -1
  52. data/lib/fluent/plugin_helper/child_process.rb +139 -73
  53. data/lib/fluent/plugin_helper/compat_parameters.rb +93 -4
  54. data/lib/fluent/plugin_helper/event_emitter.rb +14 -1
  55. data/lib/fluent/plugin_helper/event_loop.rb +24 -6
  56. data/lib/fluent/plugin_helper/extract.rb +16 -4
  57. data/lib/fluent/plugin_helper/formatter.rb +9 -11
  58. data/lib/fluent/plugin_helper/inject.rb +16 -1
  59. data/lib/fluent/plugin_helper/parser.rb +3 -3
  60. data/lib/fluent/plugin_helper/server.rb +494 -0
  61. data/lib/fluent/plugin_helper/socket.rb +101 -0
  62. data/lib/fluent/plugin_helper/socket_option.rb +84 -0
  63. data/lib/fluent/plugin_helper/timer.rb +1 -0
  64. data/lib/fluent/root_agent.rb +1 -1
  65. data/lib/fluent/test/driver/base.rb +95 -49
  66. data/lib/fluent/test/driver/base_owner.rb +18 -8
  67. data/lib/fluent/test/driver/multi_output.rb +2 -1
  68. data/lib/fluent/test/driver/output.rb +29 -6
  69. data/lib/fluent/test/helpers.rb +3 -1
  70. data/lib/fluent/test/log.rb +4 -0
  71. data/lib/fluent/test/startup_shutdown.rb +13 -0
  72. data/lib/fluent/time.rb +14 -8
  73. data/lib/fluent/version.rb +1 -1
  74. data/lib/fluent/winsvc.rb +1 -1
  75. data/test/command/test_binlog_reader.rb +5 -1
  76. data/test/compat/test_parser.rb +10 -0
  77. data/test/config/test_configurable.rb +193 -0
  78. data/test/config/test_configure_proxy.rb +0 -43
  79. data/test/helper.rb +36 -1
  80. data/test/plugin/test_base.rb +16 -0
  81. data/test/plugin/test_filter_parser.rb +665 -0
  82. data/test/plugin/test_filter_record_transformer.rb +36 -100
  83. data/test/plugin/test_filter_stdout.rb +18 -27
  84. data/test/plugin/test_in_dummy.rb +1 -1
  85. data/test/plugin/test_in_exec.rb +206 -94
  86. data/test/plugin/test_in_forward.rb +268 -347
  87. data/test/plugin/test_in_http.rb +310 -186
  88. data/test/plugin/test_in_monitor_agent.rb +65 -35
  89. data/test/plugin/test_in_syslog.rb +39 -3
  90. data/test/plugin/test_in_tcp.rb +78 -62
  91. data/test/plugin/test_in_udp.rb +101 -80
  92. data/test/plugin/test_out_exec.rb +223 -68
  93. data/test/plugin/test_out_exec_filter.rb +520 -169
  94. data/test/plugin/test_out_file.rb +637 -177
  95. data/test/plugin/test_out_forward.rb +242 -234
  96. data/test/plugin/test_out_null.rb +1 -1
  97. data/test/plugin/test_out_secondary_file.rb +4 -2
  98. data/test/plugin/test_out_stdout.rb +14 -35
  99. data/test/plugin/test_output_as_buffered.rb +60 -2
  100. data/test/plugin/test_parser.rb +359 -0
  101. data/test/plugin/test_parser_csv.rb +1 -2
  102. data/test/plugin/test_parser_json.rb +3 -4
  103. data/test/plugin/test_parser_labeled_tsv.rb +1 -2
  104. data/test/plugin/test_parser_none.rb +1 -2
  105. data/test/plugin/test_parser_regexp.rb +8 -4
  106. data/test/plugin/test_parser_tsv.rb +4 -3
  107. data/test/plugin_helper/test_child_process.rb +184 -0
  108. data/test/plugin_helper/test_compat_parameters.rb +88 -1
  109. data/test/plugin_helper/test_extract.rb +0 -1
  110. data/test/plugin_helper/test_formatter.rb +5 -2
  111. data/test/plugin_helper/test_inject.rb +21 -0
  112. data/test/plugin_helper/test_parser.rb +6 -5
  113. data/test/plugin_helper/test_server.rb +905 -0
  114. data/test/test_event_time.rb +3 -1
  115. data/test/test_output.rb +53 -2
  116. data/test/test_plugin_classes.rb +20 -0
  117. data/test/test_root_agent.rb +139 -0
  118. data/test/test_test_drivers.rb +135 -0
  119. metadata +28 -8
  120. data/test/plugin/test_parser_base.rb +0 -32
@@ -37,8 +37,7 @@ class CSVParserTest < ::Test::Unit::TestCase
37
37
  }
38
38
 
39
39
  d = Fluent::Test::Driver::Parser.new(Fluent::Plugin::CSVParser)
40
- d.instance.estimate_current_event = false
41
- d.configure('keys' => param)
40
+ d.configure('keys' => param, 'estimate_current_event' => 'no')
42
41
  d.instance.parse("192.168.0.1,111") { |time, record|
43
42
  assert_equal({
44
43
  'c' => '192.168.0.1',
@@ -44,8 +44,7 @@ class JsonParserTest < ::Test::Unit::TestCase
44
44
  }
45
45
 
46
46
  parser = Fluent::Test::Driver::Parser.new(Fluent::Plugin::JSONParser)
47
- parser.instance.estimate_current_event = false
48
- parser.configure('json_parser' => data)
47
+ parser.configure('json_parser' => data, 'estimate_current_event' => 'false')
49
48
  parser.instance.parse('{"host":"192.168.0.1","size":777,"method":"PUT"}') { |time, record|
50
49
  assert_equal({
51
50
  'host' => '192.168.0.1',
@@ -78,8 +77,8 @@ class JsonParserTest < ::Test::Unit::TestCase
78
77
  parser.configure('json_parser' => data)
79
78
  text = "100.1"
80
79
  parser.instance.parse("{\"time\":\"#{text}\"}") do |time, record|
81
- assert_equal Time.at(text.to_f).to_i, time.sec
82
- assert_equal Time.at(text.to_f).nsec, time.nsec
80
+ assert_equal 100, time.sec
81
+ assert_equal 100_000_000, time.nsec
83
82
  end
84
83
  end
85
84
 
@@ -78,8 +78,7 @@ class LabeledTSVParserTest < ::Test::Unit::TestCase
78
78
  }
79
79
 
80
80
  parser = Fluent::Test::Driver::Parser.new(Fluent::Plugin::LabeledTSVParser)
81
- parser.instance.estimate_current_event = false
82
- parser.configure({})
81
+ parser.configure({'estimate_current_event' => 'no'})
83
82
  parser.instance.parse("host:192.168.0.1\treq_id:111") { |time, record|
84
83
  assert_equal({
85
84
  'host' => '192.168.0.1',
@@ -43,8 +43,7 @@ class NoneParserTest < ::Test::Unit::TestCase
43
43
  }
44
44
 
45
45
  parser = Fluent::Test::Driver::Parser.new(Fluent::Plugin.new_parser('none'))
46
- parser.instance.estimate_current_event = false
47
- parser.configure({})
46
+ parser.configure({'estimate_current_event' => 'false'})
48
47
  parser.instance.parse('log message!') { |time, record|
49
48
  assert_equal({'message' => 'log message!'}, record)
50
49
  assert_nil time, "parser returns nil w/o time if configured so"
@@ -28,7 +28,12 @@ class RegexpParserTest < ::Test::Unit::TestCase
28
28
  if initialize_conf
29
29
  Fluent::Test::Driver::Parser.new(Fluent::Compat::TextParser::RegexpParser.new(regexp, conf))
30
30
  else
31
- Fluent::Test::Driver::Parser.new(Fluent::Compat::TextParser::RegexpParser.new(regexp)).configure(conf)
31
+ # Fluent::Test::Driver::Parser.new(Fluent::Compat::TextParser::RegexpParser.new(regexp)).configure(conf)
32
+ instance = Fluent::Compat::TextParser::RegexpParser.new(regexp)
33
+ instance.configure(conf)
34
+ d = Struct.new(:instance).new
35
+ d.instance = instance
36
+ d
32
37
  end
33
38
  end
34
39
 
@@ -188,12 +193,11 @@ class RegexpParserTest < ::Test::Unit::TestCase
188
193
  internal_test_case(d.instance)
189
194
  end
190
195
 
191
- def test_parse_with_typed_and_name_separator
196
+ def test_parse_with_typed_by_json_hash
192
197
  conf = {
193
198
  'expression' => %q!/^(?<host>[^ ]*) [^ ]* (?<user>[^ ]*) \[(?<time>[^\]]*)\] \[(?<date>[^\]]*)\] "(?<flag>\S+)(?: +(?<path>[^ ]*) +\S*)?" (?<code>[^ ]*) (?<size>[^ ]*)$/!,
194
199
  'time_format' => "%d/%b/%Y:%H:%M:%S %z",
195
- 'types' => 'user|string,date|time|%d/%b/%Y:%H:%M:%S %z,flag|bool,path|array,code|float,size|integer',
196
- 'types_label_delimiter' => '|'
200
+ 'types' => '{"user":"string","date":"time:%d/%b/%Y:%H:%M:%S %z","flag":"bool","path":"array","code":"float","size":"integer"}',
197
201
  }
198
202
  d = create_driver(conf)
199
203
  internal_test_case(d.instance)
@@ -13,7 +13,9 @@ class TSVParserTest < ::Test::Unit::TestCase
13
13
 
14
14
  data('array param' => '["a","b"]', 'string param' => 'a,b')
15
15
  def test_config_params(param)
16
- d = create_driver
16
+ d = create_driver(
17
+ 'keys' => param,
18
+ )
17
19
 
18
20
  assert_equal "\t", d.instance.delimiter
19
21
 
@@ -51,8 +53,7 @@ class TSVParserTest < ::Test::Unit::TestCase
51
53
  }
52
54
 
53
55
  d = Fluent::Test::Driver::Parser.new(Fluent::Plugin::TSVParser)
54
- d.instance.estimate_current_event = false
55
- d.configure('keys' => 'a,b', 'time_key' => 'time')
56
+ d.configure('keys' => 'a,b', 'time_key' => 'time', 'estimate_current_event' => 'no')
56
57
  d.instance.parse("192.168.0.1\t111") { |time, record|
57
58
  assert_equal({
58
59
  'a' => '192.168.0.1',
@@ -2,6 +2,7 @@ require_relative '../helper'
2
2
  require 'fluent/plugin_helper/child_process'
3
3
  require 'fluent/plugin/base'
4
4
  require 'timeout'
5
+ require 'tempfile'
5
6
 
6
7
  class ChildProcessTest < Test::Unit::TestCase
7
8
  TEST_DEADLOCK_TIMEOUT = 30
@@ -605,4 +606,187 @@ class ChildProcessTest < Test::Unit::TestCase
605
606
  end
606
607
  end
607
608
  end
609
+
610
+ sub_test_case 'on_exit_callback is specified' do
611
+ setup do
612
+ @temp = Tempfile.create("child_process_wait_with_on_exit_callback")
613
+ @temp_path = @temp.path
614
+ @temp.close
615
+ end
616
+
617
+ teardown do
618
+ File.unlink @temp_path if File.exist?(@temp_path)
619
+ end
620
+
621
+ test 'can return exit status for child process successfully exits using on_exit_callback' do
622
+ assert File.exist?(@temp_path)
623
+
624
+ block_exits = false
625
+ callback_called = false
626
+ exit_status = nil
627
+ args = ['-e', 'sleep ARGV[0].to_i; puts "yay"; File.unlink ARGV[1]', '1', @temp_path]
628
+ cb = ->(status){ exit_status = status; callback_called = true }
629
+
630
+ str = nil
631
+
632
+ Timeout.timeout(TEST_DEADLOCK_TIMEOUT) do
633
+ pid = nil
634
+ @d.child_process_execute(:st1, "ruby", arguments: args, mode: [:read], on_exit_callback: cb) do |readio|
635
+ pid = @d.instance_eval{ child_process_id }
636
+ str = readio.read.chomp
637
+ block_exits = true
638
+ end
639
+ sleep TEST_WAIT_INTERVAL_FOR_BLOCK_RUNNING while @d.child_process_exist?(pid) # to get exit status
640
+ sleep TEST_WAIT_INTERVAL_FOR_BLOCK_RUNNING until block_exits
641
+ sleep TEST_WAIT_INTERVAL_FOR_BLOCK_RUNNING until callback_called
642
+ end
643
+
644
+ assert callback_called
645
+ assert exit_status
646
+ assert_equal 0, exit_status.exitstatus
647
+ assert !File.exist?(@temp_path)
648
+
649
+ assert_equal "yay", str
650
+ end
651
+
652
+ test 'can return exit status with signal code for child process killed by signal using on_exit_callback' do
653
+ omit "SIGQUIT is unsupported on Windows" if Fluent.windows?
654
+
655
+ assert File.exist?(@temp_path)
656
+
657
+ block_exits = false
658
+ callback_called = false
659
+ exit_status = nil
660
+ args = ['-e', 'sleep ARGV[0].to_i; puts "yay"; File.unlink ARGV[1]', '25', @temp_path]
661
+ cb = ->(status){ exit_status = status; callback_called = true }
662
+
663
+ str = nil
664
+
665
+ Timeout.timeout(TEST_DEADLOCK_TIMEOUT) do
666
+ pid = nil
667
+ @d.child_process_execute(:st1, "ruby", arguments: args, mode: [:read], on_exit_callback: cb) do |readio|
668
+ pid = @d.instance_eval{ child_process_id }
669
+ Process.kill(:QUIT, pid)
670
+ Process.kill(:QUIT, pid) rescue nil # once more to kill certainly
671
+ str = readio.read.chomp rescue nil # empty string before EOF
672
+ block_exits = true
673
+ end
674
+ sleep TEST_WAIT_INTERVAL_FOR_BLOCK_RUNNING while @d.child_process_exist?(pid) # to get exit status
675
+ sleep TEST_WAIT_INTERVAL_FOR_BLOCK_RUNNING until block_exits
676
+ sleep TEST_WAIT_INTERVAL_FOR_BLOCK_RUNNING until callback_called
677
+ end
678
+
679
+ assert callback_called
680
+ assert exit_status
681
+
682
+ assert_equal [nil, 3], [exit_status.exitstatus, exit_status.termsig] # SIGQUIT
683
+
684
+ assert File.exist?(@temp_path)
685
+ assert_equal "", str
686
+ end
687
+
688
+ test 'calls on_exit_callback for each process exits for interval call using on_exit_callback' do
689
+ read_data_list = []
690
+ exit_status_list = []
691
+
692
+ args = ['-e', 'puts "yay"', '1']
693
+ cb = ->(status){ exit_status_list << status }
694
+
695
+ Timeout.timeout(TEST_DEADLOCK_TIMEOUT) do
696
+ @d.child_process_execute(:st1, "ruby", arguments: args, immediate: true, interval: 2, mode: [:read], on_exit_callback: cb) do |readio|
697
+ read_data_list << readio.read.chomp
698
+ end
699
+ sleep 10
700
+ end
701
+
702
+ assert{ read_data_list.size >= 3 }
703
+ assert{ exit_status_list.size >= 3 }
704
+ end
705
+
706
+ test 'waits lasting child process until wait_timeout if block is not specified' do
707
+ assert File.exist?(@temp_path)
708
+
709
+ callback_called = false
710
+ exit_status = nil
711
+ args = ['-e', 'sleep ARGV[0].to_i; File.unlink ARGV[1]', '1', @temp_path]
712
+ cb = ->(status){ exit_status = status; callback_called = true }
713
+
714
+ Timeout.timeout(TEST_DEADLOCK_TIMEOUT) do
715
+ @d.child_process_execute(:t17, "ruby", arguments: args, on_exit_callback: cb, wait_timeout: 5)
716
+ sleep TEST_WAIT_INTERVAL_FOR_BLOCK_RUNNING until callback_called
717
+ end
718
+
719
+ assert callback_called
720
+ assert exit_status
721
+ assert_equal 0, exit_status.exitstatus
722
+ assert !File.exist?(@temp_path)
723
+ end
724
+
725
+ test 'waits lasting child process until wait_timeout after block rans if block is specified' do
726
+ assert File.exist?(@temp_path)
727
+
728
+ callback_called = false
729
+ exit_status = nil
730
+ args = ['-e', 'sleep ARGV[0].to_i; File.unlink ARGV[1]', '3', @temp_path]
731
+ cb = ->(status){ exit_status = status; callback_called = true }
732
+
733
+ Timeout.timeout(TEST_DEADLOCK_TIMEOUT) do
734
+ @d.child_process_execute(:t17, "ruby", arguments: args, mode: nil, on_exit_callback: cb, wait_timeout: 10) do
735
+ sleep 1
736
+ end
737
+ sleep TEST_WAIT_INTERVAL_FOR_BLOCK_RUNNING until callback_called
738
+ end
739
+
740
+ assert callback_called
741
+ assert exit_status
742
+ assert_equal 0, exit_status.exitstatus
743
+ assert !File.exist?(@temp_path)
744
+ end
745
+
746
+ test 'kills lasting child process after wait_timeout if block is not specified' do
747
+ assert File.exist?(@temp_path)
748
+
749
+ callback_called = false
750
+ exit_status = nil
751
+ args = ['-e', 'sleep ARGV[0].to_i; File.unlink ARGV[1]', '20', @temp_path]
752
+ cb = ->(status){ exit_status = status; callback_called = true }
753
+
754
+ Timeout.timeout(TEST_DEADLOCK_TIMEOUT) do
755
+ @d.child_process_execute(:t17, "ruby", arguments: args, on_exit_callback: cb, wait_timeout: 3)
756
+ sleep TEST_WAIT_INTERVAL_FOR_BLOCK_RUNNING until callback_called
757
+ end
758
+
759
+ assert callback_called
760
+ assert exit_status
761
+ unless Fluent.windows? # On Windows, exitstatus is always 0 and termsig is nil
762
+ assert_nil exit_status.exitstatus
763
+ assert_equal 9, exit_status.termsig # SIGKILL
764
+ end
765
+ assert File.exist?(@temp_path)
766
+ end
767
+
768
+ test 'kills lasting child process after block ran and wait_timeout expires if block is specified' do
769
+ assert File.exist?(@temp_path)
770
+
771
+ callback_called = false
772
+ exit_status = nil
773
+ args = ['-e', 'sleep ARGV[0].to_i; File.unlink ARGV[1]', '20', @temp_path]
774
+ cb = ->(status){ exit_status = status; callback_called = true }
775
+
776
+ Timeout.timeout(TEST_DEADLOCK_TIMEOUT) do
777
+ @d.child_process_execute(:t17, "ruby", arguments: args, mode: nil, on_exit_callback: cb, wait_timeout: 3) do
778
+ sleep 3
779
+ end
780
+ sleep TEST_WAIT_INTERVAL_FOR_BLOCK_RUNNING until callback_called
781
+ end
782
+
783
+ assert callback_called
784
+ assert exit_status
785
+ unless Fluent.windows? # On Windows, exitstatus is always 0 and termsig is nil
786
+ assert_nil exit_status.exitstatus
787
+ assert_equal 9, exit_status.termsig # SIGKILL
788
+ end
789
+ assert File.exist?(@temp_path)
790
+ end
791
+ end
608
792
  end
@@ -1,6 +1,8 @@
1
1
  require_relative '../helper'
2
2
  require 'fluent/plugin_helper/compat_parameters'
3
- require 'fluent/plugin/base'
3
+ require 'fluent/plugin/input'
4
+ require 'fluent/plugin/output'
5
+ require 'fluent/time'
4
6
 
5
7
  require 'time'
6
8
 
@@ -21,6 +23,26 @@ class CompatParameterTest < Test::Unit::TestCase
21
23
  end
22
24
  end
23
25
 
26
+ class DummyI0 < Fluent::Plugin::Input
27
+ helpers :compat_parameters, :parser, :extract
28
+ attr_reader :parser
29
+ def configure(conf)
30
+ compat_parameters_convert(conf, :extract, :parser)
31
+ super
32
+ end
33
+ def start
34
+ super
35
+ @parser = parser_create
36
+ end
37
+ def produce_events(input_data)
38
+ emit_events = [] # tag, time, record
39
+ @parser.parse(input_data) do |time, record|
40
+ tag = extract_tag_from_record(record) || 'dummy_tag'
41
+ emit_events << [tag, time, record]
42
+ end
43
+ emit_events
44
+ end
45
+ end
24
46
  class DummyO0 < Fluent::Plugin::Output
25
47
  helpers :compat_parameters
26
48
  def configure(conf)
@@ -239,4 +261,69 @@ class CompatParameterTest < Test::Unit::TestCase
239
261
  assert_equal "value%1,tag%tag.test,time%#{iso8601str}\n", formatted
240
262
  end
241
263
  end
264
+
265
+ sub_test_case 'input plugins' do
266
+ test 'plugin helper converts parameters into plugin configuration parameters for extract and parser' do
267
+ hash = {
268
+ 'format' => 'ltsv',
269
+ 'delimiter' => ',',
270
+ 'label_delimiter' => '%',
271
+ 'tag_key' => 't2',
272
+ 'time_key' => 't',
273
+ 'time_format' => '%Y-%m-%d.%H:%M:%S.%N',
274
+ 'utc' => 'yes',
275
+ 'types' => 'A integer|B string|C bool',
276
+ 'types_delimiter' => '|',
277
+ 'types_label_delimiter' => ' ',
278
+ }
279
+ conf = config_element('ROOT', '', hash)
280
+ @i = DummyI0.new
281
+ @i.configure(conf)
282
+ @i.start
283
+ @i.after_start
284
+
285
+ parser = @i.parser
286
+ assert{ parser.is_a? Fluent::Plugin::LabeledTSVParser }
287
+ assert_equal ',', parser.delimiter
288
+ assert_equal '%', parser.label_delimiter
289
+
290
+ events = @i.produce_events("A%1,B%x,C%true,t2%mytag,t%2016-10-20.03:50:11.987654321")
291
+ assert_equal 1, events.size
292
+
293
+ tag, time, record = events.first
294
+ assert_equal 'mytag', tag
295
+ assert_equal_event_time event_time("2016-10-20 03:50:11.987654321 +0000"), time
296
+ assert_equal 3, record.keys.size
297
+ assert_equal ['A','B','C'], record.keys.sort
298
+ assert_equal 1, record['A']
299
+ assert_equal 'x', record['B']
300
+ assert_equal true, record['C']
301
+ end
302
+
303
+ test 'plugin helper converts parameters into plugin configuration parameters for extract and parser, using numeric time' do
304
+ hash = {
305
+ 'format' => 'ltsv',
306
+ 'delimiter' => ',',
307
+ 'label_delimiter' => '%',
308
+ 'tag_key' => 't2',
309
+ 'time_key' => 't',
310
+ 'time_type' => 'float',
311
+ 'localtime' => 'yes',
312
+ }
313
+ conf = config_element('ROOT', '', hash)
314
+ @i = DummyI0.new
315
+ @i.configure(conf)
316
+ @i.start
317
+ @i.after_start
318
+
319
+ parser = @i.parser
320
+ assert{ parser.is_a? Fluent::Plugin::LabeledTSVParser }
321
+ assert_equal ',', parser.delimiter
322
+ assert_equal '%', parser.label_delimiter
323
+ end
324
+
325
+ test 'plugin helper setups time extraction as unix time (integer from epoch)' do
326
+ # TODO:
327
+ end
328
+ end
242
329
  end
@@ -50,7 +50,6 @@ class ExtractHelperTest < Test::Unit::TestCase
50
50
  assert_nil @d.instance_eval{ @_extract_time_key }
51
51
  assert_nil @d.instance_eval{ @_extract_time_parser }
52
52
 
53
- time = event_time()
54
53
  record = {"key1" => "value1", "key2" => 2, "tag" => "yay", "time" => Time.now.to_i}
55
54
 
56
55
  assert_nil @d.extract_tag_from_record(record)
@@ -17,6 +17,9 @@ class FormatterHelperTest < Test::Unit::TestCase
17
17
  end
18
18
  class Dummy < Fluent::Plugin::TestBase
19
19
  helpers :formatter
20
+ config_section :format do
21
+ config_set_default :@type, 'example'
22
+ end
20
23
  end
21
24
 
22
25
  class Dummy2 < Fluent::Plugin::TestBase
@@ -77,12 +80,12 @@ class FormatterHelperTest < Test::Unit::TestCase
77
80
  end
78
81
  end
79
82
 
80
- test 'can be configured without format sections' do
83
+ test 'can be configured with default type without format sections' do
81
84
  d = Dummy.new
82
85
  assert_nothing_raised do
83
86
  d.configure(config_element())
84
87
  end
85
- assert_equal 0, d._formatters.size
88
+ assert_equal 1, d._formatters.size
86
89
  end
87
90
 
88
91
  test 'can be configured with a format section' do
@@ -1,5 +1,6 @@
1
1
  require_relative '../helper'
2
2
  require 'fluent/plugin_helper/inject'
3
+ require 'fluent/plugin/output'
3
4
  require 'fluent/event'
4
5
  require 'time'
5
6
 
@@ -15,6 +16,13 @@ class InjectHelperTest < Test::Unit::TestCase
15
16
  end
16
17
  end
17
18
 
19
+ class Dummy3 < Fluent::Plugin::Output
20
+ helpers :inject
21
+ def write(chunk)
22
+ # dummy
23
+ end
24
+ end
25
+
18
26
  def config_inject_section(hash = {})
19
27
  config_element('ROOT', '', {}, [config_element('inject', '', hash)])
20
28
  end
@@ -27,7 +35,9 @@ class InjectHelperTest < Test::Unit::TestCase
27
35
  teardown do
28
36
  if @d
29
37
  @d.stop unless @d.stopped?
38
+ @d.before_shutdown unless @d.before_shutdown?
30
39
  @d.shutdown unless @d.shutdown?
40
+ @d.after_shutdown unless @d.after_shutdown?
31
41
  @d.close unless @d.closed?
32
42
  @d.terminate unless @d.terminated?
33
43
  end
@@ -93,6 +103,17 @@ class InjectHelperTest < Test::Unit::TestCase
93
103
  assert_not_nil @d.instance_eval{ @_inject_time_formatter }
94
104
  end
95
105
 
106
+ test 'raise an error when injected hostname is used in buffer chunk key too' do
107
+ @d = Dummy3.new
108
+ conf = config_element('ROOT', '', {}, [
109
+ config_element('inject', '', {'hostname_key' => 'h'}),
110
+ config_element('buffer', 'tag,h'),
111
+ ])
112
+ assert_raise Fluent::ConfigError.new("the key specified by 'hostname_key' in <inject> cannot be used in buffering chunk key.") do
113
+ @d.configure(conf)
114
+ end
115
+ end
116
+
96
117
  sub_test_case 'using inject_values_to_record' do
97
118
  test 'injects hostname automatically detected' do
98
119
  detected_hostname = `hostname`.chomp