fluentd 0.14.3 → 0.14.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of fluentd might be problematic. Click here for more details.

Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog +59 -1131
  3. data/Rakefile +15 -0
  4. data/appveyor.yml +2 -2
  5. data/example/multi_filters.conf +61 -0
  6. data/fluentd.gemspec +19 -16
  7. data/lib/fluent/agent.rb +3 -0
  8. data/lib/fluent/command/debug.rb +4 -4
  9. data/lib/fluent/compat/handle_tag_and_time_mixin.rb +2 -0
  10. data/lib/fluent/compat/output.rb +5 -2
  11. data/lib/fluent/config/configure_proxy.rb +26 -5
  12. data/lib/fluent/config/error.rb +3 -0
  13. data/lib/fluent/config/section.rb +15 -0
  14. data/lib/fluent/event_router.rb +77 -4
  15. data/lib/fluent/plugin/base.rb +12 -3
  16. data/lib/fluent/plugin/filter.rb +48 -6
  17. data/lib/fluent/plugin/filter_record_transformer.rb +3 -1
  18. data/lib/fluent/plugin/filter_stdout.rb +0 -4
  19. data/lib/fluent/plugin/in_debug_agent.rb +5 -5
  20. data/lib/fluent/plugin/in_dummy.rb +9 -1
  21. data/lib/fluent/plugin/in_forward.rb +32 -14
  22. data/lib/fluent/plugin/in_monitor_agent.rb +31 -77
  23. data/lib/fluent/plugin/in_tail.rb +37 -9
  24. data/lib/fluent/plugin/out_forward.rb +2 -13
  25. data/lib/fluent/plugin/output.rb +16 -1
  26. data/lib/fluent/plugin/storage_local.rb +16 -0
  27. data/lib/fluent/plugin_helper/timer.rb +6 -1
  28. data/lib/fluent/root_agent.rb +3 -0
  29. data/lib/fluent/supervisor.rb +62 -9
  30. data/lib/fluent/test/base.rb +3 -0
  31. data/lib/fluent/test/driver/base.rb +5 -0
  32. data/lib/fluent/test/formatter_test.rb +2 -0
  33. data/lib/fluent/test/parser_test.rb +2 -0
  34. data/lib/fluent/version.rb +1 -1
  35. data/lib/fluent/winsvc.rb +1 -2
  36. data/test/compat/test_calls_super.rb +2 -0
  37. data/test/config/test_configurable.rb +88 -0
  38. data/test/config/test_types.rb +7 -3
  39. data/test/plugin/test_filter.rb +121 -23
  40. data/test/plugin/test_filter_record_transformer.rb +22 -6
  41. data/test/plugin/test_in_debug_agent.rb +2 -2
  42. data/test/plugin/test_in_forward.rb +54 -6
  43. data/test/plugin/test_in_monitor_agent.rb +329 -0
  44. data/test/plugin/test_in_tail.rb +73 -0
  45. data/test/plugin/test_out_forward.rb +1 -0
  46. data/test/plugin/test_output.rb +53 -0
  47. data/test/plugin/test_output_as_buffered.rb +13 -0
  48. data/test/plugin/test_output_as_buffered_overflow.rb +3 -0
  49. data/test/plugin/test_output_as_buffered_retries.rb +11 -0
  50. data/test/plugin/test_output_as_buffered_secondary.rb +12 -0
  51. data/test/plugin/test_output_as_standard.rb +12 -0
  52. data/test/plugin_helper/test_compat_parameters.rb +2 -0
  53. data/test/plugin_helper/test_timer.rb +31 -0
  54. data/test/test_event_router.rb +87 -0
  55. data/test/test_filter.rb +48 -6
  56. data/test/test_log.rb +5 -2
  57. data/test/test_output.rb +41 -1
  58. data/test/test_plugin_classes.rb +17 -9
  59. data/test/test_root_agent.rb +146 -0
  60. metadata +51 -67
@@ -0,0 +1,329 @@
1
+ require_relative '../helper'
2
+ require 'fluent/test/driver/input'
3
+ require 'fluent/plugin/in_monitor_agent'
4
+ require 'fluent/engine'
5
+ require 'fluent/config'
6
+ require 'fluent/event_router'
7
+ require 'fluent/supervisor'
8
+ require 'net/http'
9
+ require 'json'
10
+ require_relative '../test_plugin_classes'
11
+
12
+ class MonitorAgentInputTest < Test::Unit::TestCase
13
+ def setup
14
+ Fluent::Test.setup
15
+ end
16
+
17
+ def create_driver(conf = '')
18
+ Fluent::Test::Driver::Input.new(Fluent::Plugin::MonitorAgentInput).configure(conf)
19
+ end
20
+
21
+ def configure_ra(ra, conf_str)
22
+ conf = Fluent::Config.parse(conf_str, "(test)", "(test_dir)", true)
23
+ ra.configure(conf)
24
+ ra
25
+ end
26
+
27
+ def test_configure
28
+ d = create_driver
29
+ assert_equal("0.0.0.0", d.instance.bind)
30
+ assert_equal(24220, d.instance.port)
31
+ assert_equal(nil, d.instance.tag)
32
+ assert_equal(60, d.instance.emit_interval)
33
+ end
34
+
35
+ sub_test_case "collect plugin information" do
36
+ setup do
37
+ # check @type and type in one configuration
38
+ conf = <<-EOC
39
+ <source>
40
+ @type test_in
41
+ @id test_in
42
+ </source>
43
+ <filter>
44
+ @type test_filter
45
+ @id test_filter
46
+ </filter>
47
+ <match **>
48
+ @type relabel
49
+ @id test_relabel
50
+ @label @test
51
+ </match>
52
+ <label @test>
53
+ <match **>
54
+ @type test_out
55
+ @id test_out
56
+ </match>
57
+ </label>
58
+ <label @ERROR>
59
+ <match>
60
+ @type null
61
+ @id null
62
+ </match>
63
+ </label>
64
+ EOC
65
+ @ra = Fluent::RootAgent.new(log: $log)
66
+ stub(Fluent::Engine).root_agent { @ra }
67
+ @ra = configure_ra(@ra, conf)
68
+ end
69
+
70
+ test "plugin_category" do
71
+ d = create_driver
72
+ test_label = @ra.labels['@test']
73
+ error_label = @ra.labels['@ERROR']
74
+ assert_equal("input", d.instance.plugin_category(@ra.inputs.first))
75
+ assert_equal("filter", d.instance.plugin_category(@ra.filters.first))
76
+ assert_equal("output", d.instance.plugin_category(test_label.outputs.first))
77
+ assert_equal("output", d.instance.plugin_category(error_label.outputs.first))
78
+ end
79
+
80
+ test "get_monitor_info" do
81
+ d = create_driver
82
+ test_label = @ra.labels['@test']
83
+ error_label = @ra.labels['@ERROR']
84
+ input_info = {
85
+ "config" => {
86
+ "@id" => "test_in",
87
+ "@type" => "test_in"
88
+ },
89
+ "output_plugin" => false,
90
+ "plugin_category"=> "input",
91
+ "plugin_id" => "test_in",
92
+ "retry_count" => nil,
93
+ "type" => "test_in"
94
+ }
95
+ filter_info = {
96
+ "config" => {
97
+ "@id" => "test_filter",
98
+ "@type" => "test_filter"
99
+ },
100
+ "output_plugin" => false,
101
+ "plugin_category" => "filter",
102
+ "plugin_id" => "test_filter",
103
+ "retry_count" => nil,
104
+ "type" => "test_filter"
105
+ }
106
+ output_info = {
107
+ "config" => {
108
+ "@id" => "test_out",
109
+ "@type" => "test_out"
110
+ },
111
+ "output_plugin" => true,
112
+ "plugin_category" => "output",
113
+ "plugin_id" => "test_out",
114
+ "retry_count" => 0,
115
+ "type" => "test_out"
116
+ }
117
+ error_label_info = {
118
+ "config" => {
119
+ "@id"=>"null",
120
+ "@type" => "null"
121
+ },
122
+ "output_plugin" => true,
123
+ "plugin_category" => "output",
124
+ "plugin_id" => "null",
125
+ "retry_count" => 0,
126
+ "type" => "null"
127
+ }
128
+ assert_equal(input_info, d.instance.get_monitor_info(@ra.inputs.first))
129
+ assert_equal(filter_info, d.instance.get_monitor_info(@ra.filters.first))
130
+ assert_equal(output_info, d.instance.get_monitor_info(test_label.outputs.first))
131
+ assert_equal(error_label_info, d.instance.get_monitor_info(error_label.outputs.first))
132
+ end
133
+
134
+ test "fluentd opts" do
135
+ d = create_driver
136
+ opts = Fluent::Supervisor.default_options
137
+ Fluent::Supervisor.new(opts)
138
+ expected_opts = {
139
+ "config_path" => "/etc/fluent/fluent.conf",
140
+ "pid_file" => nil,
141
+ "plugin_dirs" => ["/etc/fluent/plugin"],
142
+ "log_path" => nil
143
+ }
144
+ assert_equal(expected_opts, d.instance.fluentd_opts)
145
+ end
146
+
147
+ test "all_plugins" do
148
+ d = create_driver
149
+ plugins = []
150
+ d.instance.all_plugins.each {|plugin| plugins << plugin.class }
151
+ assert_equal([FluentTest::FluentTestInput,
152
+ Fluent::Plugin::RelabelOutput,
153
+ FluentTest::FluentTestFilter,
154
+ FluentTest::FluentTestOutput,
155
+ Fluent::Plugin::NullOutput], plugins)
156
+ end
157
+
158
+ test "emit" do
159
+ port = unused_port
160
+ d = create_driver("
161
+ @type monitor_agent
162
+ bind '127.0.0.1'
163
+ port #{port}
164
+ tag monitor
165
+ emit_interval 1
166
+ ")
167
+ d.instance.start
168
+ d.end_if do
169
+ d.events.size >= 5
170
+ end
171
+ d.run
172
+ expect_relabel_record = {
173
+ "plugin_id" => "test_relabel",
174
+ "plugin_category" => "output",
175
+ "type" => "relabel",
176
+ "output_plugin" => true,
177
+ "retry_count" => 0}
178
+ expect_test_out_record = {
179
+ "plugin_id" => "test_out",
180
+ "plugin_category" => "output",
181
+ "type" => "test_out",
182
+ "output_plugin" => true,
183
+ "retry_count" => 0
184
+ }
185
+ assert_equal(expect_relabel_record, d.events[1][2])
186
+ assert_equal(expect_test_out_record, d.events[3][2])
187
+ end
188
+ end
189
+
190
+ def get(uri, header = {})
191
+ url = URI.parse(uri)
192
+ req = Net::HTTP::Get.new(url.path, header)
193
+ unless header.has_key?('Content-Type')
194
+ header['Content-Type'] = 'application/octet-stream'
195
+ end
196
+ res = Net::HTTP.start(url.host, url.port) {|http|
197
+ http.request(req)
198
+ }
199
+ res.body
200
+ end
201
+
202
+ sub_test_case "servlets" do
203
+ setup do
204
+ @port = unused_port
205
+ # check @type and type in one configuration
206
+ conf = <<-EOC
207
+ <source>
208
+ @type test_in
209
+ @id test_in
210
+ </source>
211
+ <source>
212
+ @type monitor_agent
213
+ bind "127.0.0.1"
214
+ port #{@port}
215
+ tag monitor
216
+ @id monitor_agent
217
+ </source>
218
+ <filter>
219
+ @type test_filter
220
+ @id test_filter
221
+ </filter>
222
+ <match **>
223
+ @type relabel
224
+ @id test_relabel
225
+ @label @test
226
+ </match>
227
+ <label @test>
228
+ <match **>
229
+ @type test_out
230
+ @id test_out
231
+ </match>
232
+ </label>
233
+ <label @ERROR>
234
+ <match>
235
+ @type null
236
+ @id null
237
+ </match>
238
+ </label>
239
+ EOC
240
+ @ra = Fluent::RootAgent.new(log: $log)
241
+ stub(Fluent::Engine).root_agent { @ra }
242
+ @ra = configure_ra(@ra, conf)
243
+ end
244
+
245
+ test "/api/plugins" do
246
+ d = create_driver("
247
+ @type monitor_agent
248
+ bind '127.0.0.1'
249
+ port #{@port}
250
+ tag monitor
251
+ ")
252
+ d.instance.start
253
+ expected_test_in_response = "\
254
+ plugin_id:test_in\tplugin_category:input\ttype:test_in\toutput_plugin:false\tretry_count:"
255
+ expected_test_filter_response = "\
256
+ plugin_id:test_filter\tplugin_category:filter\ttype:test_filter\toutput_plugin:false\tretry_count:"
257
+
258
+ response = get("http://127.0.0.1:#{@port}/api/plugins")
259
+ test_in = response.split("\n")[0]
260
+ test_filter = response.split("\n")[3]
261
+ assert_equal(expected_test_in_response, test_in)
262
+ assert_equal(expected_test_filter_response, test_filter)
263
+ end
264
+
265
+ test "/api/plugins.json" do
266
+ d = create_driver("
267
+ @type monitor_agent
268
+ bind '127.0.0.1'
269
+ port #{@port}
270
+ tag monitor
271
+ ")
272
+ d.instance.start
273
+ expected_test_in_response =
274
+ {"config" => {
275
+ "@id" => "test_in",
276
+ "@type" => "test_in"
277
+ },
278
+ "output_plugin" => false,
279
+ "plugin_category" => "input",
280
+ "plugin_id" => "test_in",
281
+ "retry_count" => nil,
282
+ "type" => "test_in"}
283
+ expected_null_response =
284
+ {"config" => {
285
+ "@id" => "null",
286
+ "@type" => "null"
287
+ },
288
+ "output_plugin" => true,
289
+ "plugin_category" => "output",
290
+ "plugin_id" => "null",
291
+ "retry_count" => 0,
292
+ "type" => "null"}
293
+ response = JSON.parse(get("http://127.0.0.1:#{@port}/api/plugins.json"))
294
+ test_in_response = response["plugins"][0]
295
+ null_response = response["plugins"][5]
296
+ assert_equal(expected_test_in_response, test_in_response)
297
+ assert_equal(expected_null_response, null_response)
298
+ end
299
+
300
+ test "/api/config" do
301
+ d = create_driver("
302
+ @type monitor_agent
303
+ bind '127.0.0.1'
304
+ port #{@port}
305
+ tag monitor
306
+ ")
307
+ d.instance.start
308
+ expected_response_regex = /pid:\d+\tppid:\d+\tconfig_path:\/etc\/fluent\/fluent.conf\tpid_file:\tplugin_dirs:\[\"\/etc\/fluent\/plugin\"\]\tlog_path:/
309
+
310
+ assert_match(expected_response_regex,
311
+ get("http://127.0.0.1:#{@port}/api/config"))
312
+ end
313
+
314
+ test "/api/config.json" do
315
+ d = create_driver("
316
+ @type monitor_agent
317
+ bind '127.0.0.1'
318
+ port #{@port}
319
+ tag monitor
320
+ ")
321
+ d.instance.start
322
+ res = JSON.parse(get("http://127.0.0.1:#{@port}/api/config.json"))
323
+ assert_equal("/etc/fluent/fluent.conf", res["config_path"])
324
+ assert_nil(res["pid_file"])
325
+ assert_equal(["/etc/fluent/plugin"], res["plugin_dirs"])
326
+ assert_nil(res["log_path"])
327
+ end
328
+ end
329
+ end
@@ -71,6 +71,32 @@ class TailInputTest < Test::Unit::TestCase
71
71
  end
72
72
  end
73
73
 
74
+ def test_configure_from_encoding
75
+ # If only specified from_encoding raise ConfigError
76
+ assert_raise(Fluent::ConfigError) do
77
+ create_driver(SINGLE_LINE_CONFIG + 'from_encoding utf-8')
78
+ end
79
+
80
+ # valid setting
81
+ d = create_driver %[
82
+ format /(?<message>.*)/
83
+ read_from_head true
84
+ from_encoding utf-8
85
+ encoding utf-8
86
+ ]
87
+ assert_equal Encoding::UTF_8, d.instance.from_encoding
88
+
89
+ # invalid from_encoding
90
+ assert_raise(Fluent::ConfigError) do
91
+ d = create_driver %[
92
+ format /(?<message>.*)/
93
+ read_from_head true
94
+ from_encoding no-such-encoding
95
+ encoding utf-8
96
+ ]
97
+ end
98
+ end
99
+
74
100
  # TODO: Should using more better approach instead of sleep wait
75
101
 
76
102
  def test_emit
@@ -403,6 +429,28 @@ class TailInputTest < Test::Unit::TestCase
403
429
  assert_equal(encoding, emits[0][2]['message'].encoding)
404
430
  end
405
431
 
432
+ def test_from_encoding
433
+ d = create_driver %[
434
+ format /(?<message>.*)/
435
+ read_from_head true
436
+ from_encoding cp932
437
+ encoding utf-8
438
+ ]
439
+
440
+ d.run do
441
+ sleep 1
442
+
443
+ File.open("#{TMP_DIR}/tail.txt", "w:cp932") {|f|
444
+ f.puts "\x82\xCD\x82\xEB\x81\x5B\x82\xED\x81\x5B\x82\xE9\x82\xC7".force_encoding(Encoding::CP932)
445
+ }
446
+ sleep 1
447
+ end
448
+
449
+ emits = d.emits
450
+ assert_equal("\x82\xCD\x82\xEB\x81\x5B\x82\xED\x81\x5B\x82\xE9\x82\xC7".force_encoding(Encoding::CP932).encode(Encoding::UTF_8), emits[0][2]['message'])
451
+ assert_equal(Encoding::UTF_8, emits[0][2]['message'].encoding)
452
+ end
453
+
406
454
  # multiline mode test
407
455
 
408
456
  def test_multiline
@@ -507,6 +555,31 @@ class TailInputTest < Test::Unit::TestCase
507
555
  end
508
556
  end
509
557
 
558
+ def test_multiline_from_encoding_of_flushed_record
559
+ d = create_driver %[
560
+ format multiline
561
+ format1 /^s (?<message1>[^\\n]+)(\\nf (?<message2>[^\\n]+))?(\\nf (?<message3>.*))?/
562
+ format_firstline /^[s]/
563
+ multiline_flush_interval 2s
564
+ read_from_head true
565
+ from_encoding cp932
566
+ encoding utf-8
567
+ ]
568
+
569
+ d.run do
570
+ sleep 1
571
+ File.open("#{TMP_DIR}/tail.txt", "w:cp932") { |f|
572
+ f.puts "s \x82\xCD\x82\xEB\x81\x5B\x82\xED\x81\x5B\x82\xE9\x82\xC7".force_encoding(Encoding::CP932)
573
+ }
574
+
575
+ sleep 4
576
+ emits = d.emits
577
+ assert_equal(1, emits.length)
578
+ assert_equal("\x82\xCD\x82\xEB\x81\x5B\x82\xED\x81\x5B\x82\xE9\x82\xC7".force_encoding(Encoding::CP932).encode(Encoding::UTF_8), emits[0][2]['message1'])
579
+ assert_equal(Encoding::UTF_8, emits[0][2]['message1'].encoding)
580
+ end
581
+ end
582
+
510
583
  def test_multiline_with_multiple_formats
511
584
  File.open("#{TMP_DIR}/tail.txt", "wb") { |f| }
512
585
 
@@ -454,6 +454,7 @@ class ForwardOutputTest < Test::Unit::TestCase
454
454
  option
455
455
  }
456
456
  @source = nil
457
+ @peeraddr = nil
457
458
  end
458
459
 
459
460
  if do_respond
@@ -98,6 +98,17 @@ module FluentPluginOutputTest
98
98
  end
99
99
 
100
100
  class OutputTest < Test::Unit::TestCase
101
+ class << self
102
+ def startup
103
+ $LOAD_PATH.unshift File.expand_path(File.join(File.dirname(__FILE__), '../scripts'))
104
+ require 'fluent/plugin/out_test'
105
+ end
106
+
107
+ def shutdown
108
+ $LOAD_PATH.shift
109
+ end
110
+ end
111
+
101
112
  def create_output(type=:full)
102
113
  case type
103
114
  when :bare then FluentPluginOutputTest::DummyBareOutput.new
@@ -181,6 +192,9 @@ class OutputTest < Test::Unit::TestCase
181
192
  assert !@i.started?
182
193
  @i.start
183
194
  assert @i.started?
195
+ assert !@i.after_started?
196
+ @i.after_start
197
+ assert @i.after_started?
184
198
  assert !@i.stopped?
185
199
  @i.stop
186
200
  assert @i.stopped?
@@ -318,6 +332,7 @@ class OutputTest < Test::Unit::TestCase
318
332
  i.register(:process){|tag, es| process_called = true }
319
333
  i.configure(config_element())
320
334
  i.start
335
+ i.after_start
321
336
 
322
337
  t = event_time()
323
338
  i.emit_events('tag', Fluent::ArrayEventStream.new([ [t, {"key" => "value1"}], [t, {"key" => "value2"}] ]))
@@ -333,6 +348,7 @@ class OutputTest < Test::Unit::TestCase
333
348
  i.register(:format){|tag, time, record| format_called_times += 1; '' }
334
349
  i.configure(config_element())
335
350
  i.start
351
+ i.after_start
336
352
 
337
353
  t = event_time()
338
354
  i.emit_events('tag', Fluent::ArrayEventStream.new([ [t, {"key" => "value1"}], [t, {"key" => "value2"}] ]))
@@ -353,6 +369,7 @@ class OutputTest < Test::Unit::TestCase
353
369
  i.configure(config_element())
354
370
  i.register(:prefer_buffered_processing){ false } # delayed decision is possible to change after (output's) configure
355
371
  i.start
372
+ i.after_start
356
373
 
357
374
  assert !i.prefer_buffered_processing
358
375
 
@@ -378,6 +395,7 @@ class OutputTest < Test::Unit::TestCase
378
395
  i.configure(config_element())
379
396
  i.register(:prefer_buffered_processing){ true } # delayed decision is possible to change after (output's) configure
380
397
  i.start
398
+ i.after_start
381
399
 
382
400
  assert i.prefer_buffered_processing
383
401
 
@@ -397,6 +415,7 @@ class OutputTest < Test::Unit::TestCase
397
415
 
398
416
  i.configure(config_element('ROOT', '', {}, [config_element('buffer', '', {"flush_mode" => "immediate"})]))
399
417
  i.start
418
+ i.after_start
400
419
 
401
420
  t = event_time()
402
421
  i.emit_events('tag', Fluent::ArrayEventStream.new([ [t, {"key" => "value1"}], [t, {"key" => "value2"}] ]))
@@ -416,6 +435,7 @@ class OutputTest < Test::Unit::TestCase
416
435
 
417
436
  i.configure(config_element('ROOT', '', {}, [config_element('buffer', '', {"flush_mode" => "immediate"})]))
418
437
  i.start
438
+ i.after_start
419
439
 
420
440
  t = event_time()
421
441
  i.emit_events('tag', Fluent::ArrayEventStream.new([ [t, {"key" => "value1"}], [t, {"key" => "value2"}] ]))
@@ -438,6 +458,7 @@ class OutputTest < Test::Unit::TestCase
438
458
  i.configure(config_element('ROOT', '', {}, [config_element('buffer', '', {"flush_mode" => "immediate"})]))
439
459
  i.register(:prefer_delayed_commit){ false } # delayed decision is possible to change after (output's) configure
440
460
  i.start
461
+ i.after_start
441
462
 
442
463
  assert !i.prefer_delayed_commit
443
464
 
@@ -463,6 +484,7 @@ class OutputTest < Test::Unit::TestCase
463
484
  i.configure(config_element('ROOT', '', {}, [config_element('buffer', '', {"flush_mode" => "immediate"})]))
464
485
  i.register(:prefer_delayed_commit){ true } # delayed decision is possible to change after (output's) configure
465
486
  i.start
487
+ i.after_start
466
488
 
467
489
  assert i.prefer_delayed_commit
468
490
 
@@ -477,6 +499,36 @@ class OutputTest < Test::Unit::TestCase
477
499
 
478
500
  i.stop; i.before_shutdown; i.shutdown; i.after_shutdown; i.close; i.terminate
479
501
  end
502
+
503
+ test "Warn if primary type is different from secondary type and either primary or secondary has custom_format" do
504
+ o = create_output(:buffered)
505
+ mock(o.log).warn("secondary type should be same with primary one",
506
+ { primary: o.class.to_s, secondary: "Fluent::Plugin::TestOutput" })
507
+
508
+ o.configure(config_element('ROOT','',{},[config_element('secondary','',{'@type'=>'test', 'name' => "cool"})]))
509
+ assert_not_nil o.instance_variable_get(:@secondary)
510
+ end
511
+
512
+ test "don't warn if primary type is the same as secondary type" do
513
+ o = Fluent::Plugin::TestOutput.new
514
+ mock(o.log).warn("secondary type should be same with primary one",
515
+ { primary: o.class.to_s, secondary: "Fluent::Plugin::TestOutput" }).never
516
+
517
+ o.configure(config_element('ROOT','',{'name' => "cool2"},
518
+ [config_element('secondary','',{'@type'=>'test', 'name' => "cool"}),
519
+ config_element('buffer','',{'@type'=>'memory'})]
520
+ ))
521
+ assert_not_nil o.instance_variable_get(:@secondary)
522
+ end
523
+
524
+ test "don't warn if primary type is different from secondary type and both don't have custom_format" do
525
+ o = create_output(:standard)
526
+ mock(o.log).warn("secondary type should be same with primary one",
527
+ { primary: o.class.to_s, secondary: "Fluent::Plugin::TestOutput" }).never
528
+
529
+ o.configure(config_element('ROOT','',{},[config_element('secondary','',{'@type'=>'test', 'name' => "cool"})]))
530
+ assert_not_nil o.instance_variable_get(:@secondary)
531
+ end
480
532
  end
481
533
 
482
534
  sub_test_case 'sync output feature' do
@@ -501,6 +553,7 @@ class OutputTest < Test::Unit::TestCase
501
553
  @i.register(:process){|tag, es| ary << [tag, es] }
502
554
  @i.configure(config_element())
503
555
  @i.start
556
+ @i.after_start
504
557
 
505
558
  t = event_time()
506
559
  es = Fluent::ArrayEventStream.new([ [t, {"key" => "value1"}], [t, {"key" => "value2"}] ])