fluentd 1.14.6 → 1.15.0

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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/linux-test.yaml +1 -1
  3. data/.github/workflows/windows-test.yaml +4 -1
  4. data/CHANGELOG.md +53 -1
  5. data/fluentd.gemspec +2 -1
  6. data/lib/fluent/command/ctl.rb +4 -1
  7. data/lib/fluent/command/fluentd.rb +10 -0
  8. data/lib/fluent/config/literal_parser.rb +2 -2
  9. data/lib/fluent/config/yaml_parser/fluent_value.rb +47 -0
  10. data/lib/fluent/config/yaml_parser/loader.rb +91 -0
  11. data/lib/fluent/config/yaml_parser/parser.rb +166 -0
  12. data/lib/fluent/config/yaml_parser/section_builder.rb +107 -0
  13. data/lib/fluent/config/yaml_parser.rb +56 -0
  14. data/lib/fluent/config.rb +14 -1
  15. data/lib/fluent/plugin/file_wrapper.rb +52 -107
  16. data/lib/fluent/plugin/in_tail/group_watch.rb +204 -0
  17. data/lib/fluent/plugin/in_tail/position_file.rb +1 -15
  18. data/lib/fluent/plugin/in_tail.rb +66 -47
  19. data/lib/fluent/plugin/out_forward/socket_cache.rb +2 -0
  20. data/lib/fluent/plugin/output.rb +2 -1
  21. data/lib/fluent/plugin/parser_syslog.rb +1 -1
  22. data/lib/fluent/plugin_helper/server.rb +3 -1
  23. data/lib/fluent/plugin_helper/service_discovery.rb +2 -2
  24. data/lib/fluent/supervisor.rb +109 -25
  25. data/lib/fluent/system_config.rb +2 -1
  26. data/lib/fluent/version.rb +1 -1
  27. data/lib/fluent/winsvc.rb +2 -0
  28. data/test/command/test_ctl.rb +0 -1
  29. data/test/command/test_fluentd.rb +33 -0
  30. data/test/config/test_system_config.rb +3 -1
  31. data/test/config/test_types.rb +1 -1
  32. data/test/plugin/in_tail/test_io_handler.rb +14 -4
  33. data/test/plugin/in_tail/test_position_file.rb +0 -63
  34. data/test/plugin/out_forward/test_socket_cache.rb +26 -1
  35. data/test/plugin/test_file_wrapper.rb +0 -68
  36. data/test/plugin/test_in_object_space.rb +9 -3
  37. data/test/plugin/test_in_syslog.rb +1 -1
  38. data/test/plugin/test_in_tail.rb +629 -353
  39. data/test/plugin/test_out_forward.rb +30 -20
  40. data/test/plugin/test_parser_syslog.rb +1 -1
  41. data/test/plugin_helper/test_cert_option.rb +1 -1
  42. data/test/plugin_helper/test_child_process.rb +16 -4
  43. data/test/test_config.rb +135 -4
  44. data/test/test_supervisor.rb +155 -0
  45. metadata +11 -5
@@ -235,6 +235,7 @@ module Fluent
235
235
  @dequeued_chunks_mutex = nil
236
236
  @output_enqueue_thread = nil
237
237
  @output_flush_threads = nil
238
+ @output_flush_thread_current_position = 0
238
239
 
239
240
  @simple_chunking = nil
240
241
  @chunk_keys = @chunk_key_accessors = @chunk_key_time = @chunk_key_tag = nil
@@ -492,6 +493,7 @@ module Fluent
492
493
  @dequeued_chunks = []
493
494
  @dequeued_chunks_mutex = Mutex.new
494
495
 
496
+ @output_flush_thread_current_position = 0
495
497
  @buffer_config.flush_thread_count.times do |i|
496
498
  thread_title = "flush_thread_#{i}".to_sym
497
499
  thread_state = FlushThreadState.new(nil, nil, Mutex.new, ConditionVariable.new)
@@ -503,7 +505,6 @@ module Fluent
503
505
  @output_flush_threads << thread_state
504
506
  end
505
507
  end
506
- @output_flush_thread_current_position = 0
507
508
 
508
509
  if !@under_plugin_development && (@flush_mode == :interval || @chunk_key_time)
509
510
  @output_enqueue_thread = thread_create(:enqueue_thread, &method(:enqueue_thread_run))
@@ -484,7 +484,7 @@ module Fluent
484
484
 
485
485
  time = begin
486
486
  @time_parser_rfc5424.parse(time_str)
487
- rescue Fluent::TimeParser::TimeParseError => e
487
+ rescue Fluent::TimeParser::TimeParseError
488
488
  @time_parser_rfc5424_without_subseconds.parse(time_str)
489
489
  end
490
490
  record['time'] = time_str if @keep_time_key
@@ -267,7 +267,9 @@ module Fluent
267
267
  ### Socket Params ###
268
268
 
269
269
  # SO_LINGER 0 to send RST rather than FIN to avoid lots of connections sitting in TIME_WAIT at src.
270
- # Set positive value if needing to send FIN on closing.
270
+ # Set positive value if needing to send FIN on closing on non-Windows.
271
+ # (On Windows, Fluentd can send FIN with zero `linger_timeout` since Fluentd doesn't set 0 to SO_LINGER on Windows.
272
+ # See `socket_option.rb`.)
271
273
  # NOTE:
272
274
  # Socket-options can be specified from each plugin as needed, so most of them is not defined here for now.
273
275
  # This is because there is no positive reason to do so.
@@ -44,7 +44,7 @@ module Fluent
44
44
 
45
45
  @discovery_manager.start
46
46
  unless @discovery_manager.static_config?
47
- timer_execute(@_plugin_helper_service_discovery_title, @_plugin_helper_service_discovery_iterval) do
47
+ timer_execute(@_plugin_helper_service_discovery_title, @_plugin_helper_service_discovery_interval) do
48
48
  @discovery_manager.run_once
49
49
  end
50
50
  end
@@ -96,7 +96,7 @@ module Fluent
96
96
  # @param custom_build_method [Proc]
97
97
  def service_discovery_create_manager(title, configurations:, load_balancer: nil, custom_build_method: nil, interval: 3)
98
98
  @_plugin_helper_service_discovery_title = title
99
- @_plugin_helper_service_discovery_iterval = interval
99
+ @_plugin_helper_service_discovery_interval = interval
100
100
 
101
101
  @discovery_manager = Fluent::PluginHelper::ServiceDiscovery::Manager.new(
102
102
  log: log,
@@ -16,6 +16,7 @@
16
16
 
17
17
  require 'fileutils'
18
18
  require 'open3'
19
+ require 'pathname'
19
20
 
20
21
  require 'fluent/config'
21
22
  require 'fluent/counter'
@@ -215,44 +216,50 @@ module Fluent
215
216
  Thread.new do
216
217
  ipc = Win32::Ipc.new(nil)
217
218
  events = [
218
- Win32::Event.new("#{@pid_signame}_STOP_EVENT_THREAD"),
219
- Win32::Event.new("#{@pid_signame}"),
220
- Win32::Event.new("#{@pid_signame}_HUP"),
221
- Win32::Event.new("#{@pid_signame}_USR1"),
222
- Win32::Event.new("#{@pid_signame}_USR2"),
219
+ {win32_event: Win32::Event.new("#{@pid_signame}_STOP_EVENT_THREAD"), action: :stop_event_thread},
220
+ {win32_event: Win32::Event.new("#{@pid_signame}"), action: :stop},
221
+ {win32_event: Win32::Event.new("#{@pid_signame}_HUP"), action: :hup},
222
+ {win32_event: Win32::Event.new("#{@pid_signame}_USR1"), action: :usr1},
223
+ {win32_event: Win32::Event.new("#{@pid_signame}_USR2"), action: :usr2},
224
+ {win32_event: Win32::Event.new("#{@pid_signame}_CONT"), action: :cont},
223
225
  ]
224
226
  if @signame
225
227
  signame_events = [
226
- Win32::Event.new("#{@signame}"),
227
- Win32::Event.new("#{@signame}_HUP"),
228
- Win32::Event.new("#{@signame}_USR1"),
229
- Win32::Event.new("#{@signame}_USR2"),
228
+ {win32_event: Win32::Event.new("#{@signame}"), action: :stop},
229
+ {win32_event: Win32::Event.new("#{@signame}_HUP"), action: :hup},
230
+ {win32_event: Win32::Event.new("#{@signame}_USR1"), action: :usr1},
231
+ {win32_event: Win32::Event.new("#{@signame}_USR2"), action: :usr2},
232
+ {win32_event: Win32::Event.new("#{@signame}_CONT"), action: :cont},
230
233
  ]
231
234
  events.concat(signame_events)
232
235
  end
233
236
  begin
234
237
  loop do
235
- idx = ipc.wait_any(events, Windows::Synchronize::INFINITE)
236
- if idx > 0 && idx <= events.length
237
- $log.debug("Got Win32 event \"#{events[idx - 1].name}\"")
238
+ ipc_idx = ipc.wait_any(events.map {|e| e[:win32_event]}, Windows::Synchronize::INFINITE)
239
+ event_idx = ipc_idx - 1
240
+
241
+ if event_idx >= 0 && event_idx < events.length
242
+ $log.debug("Got Win32 event \"#{events[event_idx][:win32_event].name}\"")
238
243
  else
239
- $log.warn("Unexpected reutrn value of Win32::Ipc#wait_any: #{idx}")
244
+ $log.warn("Unexpected return value of Win32::Ipc#wait_any: #{ipc_idx}")
240
245
  end
241
- case idx
242
- when 2, 6
246
+ case events[event_idx][:action]
247
+ when :stop
243
248
  stop(true)
244
- when 3, 7
249
+ when :hup
245
250
  supervisor_sighup_handler
246
- when 4, 8
251
+ when :usr1
247
252
  supervisor_sigusr1_handler
248
- when 5, 9
253
+ when :usr2
249
254
  supervisor_sigusr2_handler
250
- when 1
255
+ when :cont
256
+ supervisor_dump_handler_for_windows
257
+ when :stop_event_thread
251
258
  break
252
259
  end
253
260
  end
254
261
  ensure
255
- events.each { |event| event.close }
262
+ events.each { |event| event[:win32_event].close }
256
263
  end
257
264
  end
258
265
  end
@@ -302,6 +309,26 @@ module Fluent
302
309
  $log.error "Failed to reload config file: #{e}"
303
310
  end
304
311
 
312
+ def supervisor_dump_handler_for_windows
313
+ # As for UNIX-like, SIGCONT signal to each process makes the process output its dump-file,
314
+ # and it is implemented before the implementation of the function for Windows.
315
+ # It is possible to trap SIGCONT and handle it here also on UNIX-like,
316
+ # but for backward compatibility, this handler is currently for a Windows-only.
317
+ raise "[BUG] This function is for Windows ONLY." unless Fluent.windows?
318
+
319
+ Thread.new do
320
+ begin
321
+ FluentSigdump.dump_windows
322
+ rescue => e
323
+ $log.error "failed to dump: #{e}"
324
+ end
325
+ end
326
+
327
+ send_signal_to_workers(:CONT)
328
+ rescue => e
329
+ $log.error "failed to dump: #{e}"
330
+ end
331
+
305
332
  def kill_worker
306
333
  if config[:worker_pid]
307
334
  pids = config[:worker_pid].clone
@@ -358,6 +385,14 @@ module Fluent
358
385
  restart(true)
359
386
  when :USR2
360
387
  reload
388
+ when :CONT
389
+ dump_all_windows_workers
390
+ end
391
+ end
392
+
393
+ def dump_all_windows_workers
394
+ @monitors.each do |m|
395
+ m.send_command("DUMP\n")
361
396
  end
362
397
  end
363
398
  end
@@ -458,7 +493,8 @@ module Fluent
458
493
  config_path: path,
459
494
  main_cmd: params['main_cmd'],
460
495
  signame: params['signame'],
461
- disable_shared_socket: params['disable_shared_socket']
496
+ disable_shared_socket: params['disable_shared_socket'],
497
+ restart_worker_interval: params['restart_worker_interval'],
462
498
  }
463
499
  if daemonize
464
500
  se_config[:pid_path] = pid_path
@@ -580,7 +616,8 @@ module Fluent
580
616
  standalone_worker: false,
581
617
  signame: nil,
582
618
  conf_encoding: 'utf-8',
583
- disable_shared_socket: nil
619
+ disable_shared_socket: nil,
620
+ config_file_type: :guess,
584
621
  }
585
622
  end
586
623
 
@@ -593,6 +630,7 @@ module Fluent
593
630
  end
594
631
 
595
632
  def initialize(opt)
633
+ @config_file_type = opt[:config_file_type]
596
634
  @daemonize = opt[:daemonize]
597
635
  @standalone_worker= opt[:standalone_worker]
598
636
  @config_path = opt[:config_path]
@@ -618,7 +656,9 @@ module Fluent
618
656
  @conf = Fluent::Config.build(config_path: @config_path,
619
657
  encoding: @conf_encoding ? @conf_encoding : 'utf-8',
620
658
  additional_config: @inline_config ? @inline_config : nil,
621
- use_v1_config: !!@use_v1_config)
659
+ use_v1_config: !!@use_v1_config,
660
+ type: @config_file_type,
661
+ )
622
662
  @system_config = build_system_config(@conf)
623
663
  if @system_config.log
624
664
  @log_rotate_age ||= @system_config.log.rotate_age
@@ -744,7 +784,13 @@ module Fluent
744
784
  $log.warn('the value "-" for `inline_config` is deprecated. See https://github.com/fluent/fluentd/issues/2711')
745
785
  @inline_config = STDIN.read
746
786
  end
747
- @conf = Fluent::Config.build(config_path: @config_path, encoding: @conf_encoding, additional_config: @inline_config, use_v1_config: @use_v1_config)
787
+ @conf = Fluent::Config.build(
788
+ config_path: @config_path,
789
+ encoding: @conf_encoding,
790
+ additional_config: @inline_config,
791
+ use_v1_config: @use_v1_config,
792
+ type: @config_file_type,
793
+ )
748
794
  @system_config = build_system_config(@conf)
749
795
 
750
796
  @log.level = @system_config.log_level
@@ -822,7 +868,8 @@ module Fluent
822
868
  'counter_server' => @system_config.counter_server,
823
869
  'log_format' => @system_config.log.format,
824
870
  'log_time_format' => @system_config.log.time_format,
825
- 'disable_shared_socket' => @system_config.disable_shared_socket
871
+ 'disable_shared_socket' => @system_config.disable_shared_socket,
872
+ 'restart_worker_interval' => @system_config.restart_worker_interval,
826
873
  }
827
874
 
828
875
  se = ServerEngine.create(ServerModule, WorkerModule){
@@ -896,6 +943,9 @@ module Fluent
896
943
  when "RELOAD"
897
944
  $log.debug "fluentd main process get #{cmd} command"
898
945
  reload_config
946
+ when "DUMP"
947
+ $log.debug "fluentd main process get #{cmd} command"
948
+ dump
899
949
  else
900
950
  $log.warn "fluentd main process get unknown command [#{cmd}]"
901
951
  end
@@ -929,6 +979,7 @@ module Fluent
929
979
  encoding: @conf_encoding,
930
980
  additional_config: @inline_config,
931
981
  use_v1_config: @use_v1_config,
982
+ type: @config_file_type,
932
983
  )
933
984
 
934
985
  Fluent::VariableStore.try_to_reset do
@@ -945,6 +996,16 @@ module Fluent
945
996
  end
946
997
  end
947
998
 
999
+ def dump
1000
+ Thread.new do
1001
+ begin
1002
+ FluentSigdump.dump_windows
1003
+ rescue => e
1004
+ $log.error("failed to dump: #{e}")
1005
+ end
1006
+ end
1007
+ end
1008
+
948
1009
  def logging_with_console_output
949
1010
  yield $log
950
1011
  unless @log.stdout?
@@ -1054,4 +1115,27 @@ module Fluent
1054
1115
  fluentd_spawn_cmd
1055
1116
  end
1056
1117
  end
1118
+
1119
+ module FluentSigdump
1120
+ def self.dump_windows
1121
+ raise "[BUG] WindowsSigdump::dump is for Windows ONLY." unless Fluent.windows?
1122
+
1123
+ # Sigdump outputs under `/tmp` dir without `SIGDUMP_PATH` specified,
1124
+ # but `/tmp` dir may not exist on Windows by default.
1125
+ # So use the systemroot-temp-dir instead.
1126
+ dump_filepath = ENV['SIGDUMP_PATH'].nil? || ENV['SIGDUMP_PATH'].empty? \
1127
+ ? "#{ENV['windir']}/Temp/fluentd-sigdump-#{Process.pid}.log"
1128
+ : get_path_with_pid(ENV['SIGDUMP_PATH'])
1129
+
1130
+ require 'sigdump'
1131
+ Sigdump.dump(dump_filepath)
1132
+
1133
+ $log.info "dump to #{dump_filepath}."
1134
+ end
1135
+
1136
+ def self.get_path_with_pid(raw_path)
1137
+ path = Pathname.new(raw_path)
1138
+ path.sub_ext("-#{Process.pid}#{path.extname}").to_s
1139
+ end
1140
+ end
1057
1141
  end
@@ -22,7 +22,7 @@ module Fluent
22
22
  include Configurable
23
23
 
24
24
  SYSTEM_CONFIG_PARAMETERS = [
25
- :workers, :root_dir, :log_level,
25
+ :workers, :restart_worker_interval, :root_dir, :log_level,
26
26
  :suppress_repeated_stacktrace, :emit_error_log_interval, :suppress_config_dump,
27
27
  :log_event_verbose, :ignore_repeated_log_interval, :ignore_same_log_interval,
28
28
  :without_source, :rpc_endpoint, :enable_get_dump, :process_name,
@@ -32,6 +32,7 @@ module Fluent
32
32
  ]
33
33
 
34
34
  config_param :workers, :integer, default: 1
35
+ config_param :restart_worker_interval, :time, default: 0
35
36
  config_param :root_dir, :string, default: nil
36
37
  config_param :log_level, :enum, list: [:trace, :debug, :info, :warn, :error, :fatal], default: 'info'
37
38
  config_param :suppress_repeated_stacktrace, :bool, default: nil
@@ -16,6 +16,6 @@
16
16
 
17
17
  module Fluent
18
18
 
19
- VERSION = '1.14.6'
19
+ VERSION = '1.15.0'
20
20
 
21
21
  end
data/lib/fluent/winsvc.rb CHANGED
@@ -84,6 +84,8 @@ begin
84
84
  set_event("#{@service_name}_HUP")
85
85
  when 129
86
86
  set_event("#{@service_name}_USR1")
87
+ when 130
88
+ set_event("#{@service_name}_CONT")
87
89
  end
88
90
  end
89
91
 
@@ -7,7 +7,6 @@ require 'fluent/command/ctl'
7
7
 
8
8
  class TestFluentdCtl < ::Test::Unit::TestCase
9
9
  def assert_win32_event(event_name, command, pid_or_svcname)
10
- command, event_suffix = data
11
10
  event = Win32::Event.new(event_name)
12
11
  ipc = Win32::Ipc.new(event.handle)
13
12
  ret = Win32::Ipc::TIMEOUT
@@ -589,6 +589,39 @@ CONF
589
589
  )
590
590
  end
591
591
 
592
+ sub_test_case "YAML config format" do
593
+ test 'success to start the number of workers specified in configuration' do
594
+ conf = <<'CONF'
595
+ system:
596
+ workers: 2
597
+ root_dir: "#{@root_path}"
598
+ config:
599
+ - source:
600
+ $type: dummy
601
+ $id: !fluent/s "dummy.#{worker_id}" # check worker_id works or not with actual command
602
+ $label: '@dummydata'
603
+ tag: dummy
604
+ dummy: !fluent/json {"message": !fluent/s "yay from #{hostname}!"}
605
+
606
+ - label:
607
+ $name: '@dummydata'
608
+ config:
609
+ - match:
610
+ $tag: dummy
611
+ $type: "null"
612
+ $id: blackhole
613
+ CONF
614
+ conf_path = create_conf_file('workers1.yaml', conf)
615
+ assert Dir.exist?(@root_path)
616
+
617
+ assert_log_matches(
618
+ create_cmdline(conf_path),
619
+ "#0 fluentd worker is now running worker=0",
620
+ "#1 fluentd worker is now running worker=1"
621
+ )
622
+ end
623
+ end
624
+
592
625
  test 'success to start the number of workers specified by command line option' do
593
626
  conf = <<CONF
594
627
  <system>
@@ -19,6 +19,7 @@ module Fluent::Config
19
19
  @system_config = nil
20
20
  @cl_opt = {
21
21
  wokers: nil,
22
+ restart_worker_interval: nil,
22
23
  root_dir: nil,
23
24
  log: FakeLoggerInitializer.new,
24
25
  log_level: Fluent::Log::LEVEL_INFO,
@@ -72,6 +73,7 @@ module Fluent::Config
72
73
  sc = Fluent::SystemConfig.new(conf)
73
74
  sc.overwrite_variables(**s.for_system_config)
74
75
  assert_equal(1, sc.workers)
76
+ assert_equal(0, sc.restart_worker_interval)
75
77
  assert_nil(sc.root_dir)
76
78
  assert_equal(Fluent::Log::LEVEL_INFO, sc.log_level)
77
79
  assert_nil(sc.suppress_repeated_stacktrace)
@@ -88,6 +90,7 @@ module Fluent::Config
88
90
 
89
91
  data(
90
92
  'workers' => ['workers', 3],
93
+ 'restart_worker_interval' => ['restart_worker_interval', 60],
91
94
  'root_dir' => ['root_dir', File.join(TMP_DIR, 'root')],
92
95
  'log_level' => ['log_level', 'error'],
93
96
  'suppress_repeated_stacktrace' => ['suppress_repeated_stacktrace', true],
@@ -174,7 +177,6 @@ module Fluent::Config
174
177
  </log>
175
178
  </system>
176
179
  EOS
177
- s = FakeSupervisor.new
178
180
  sc = Fluent::SystemConfig.new(conf)
179
181
  assert_equal(3, sc.log.rotate_age)
180
182
  end
@@ -190,7 +190,7 @@ class TestConfigTypes < ::Test::Unit::TestCase
190
190
  data("val" => [:val, 'val'],
191
191
  "v" => [:v, 'v'],
192
192
  "value" => [:value, 'value'])
193
- test 'enum' do |(expected, val, list)|
193
+ test 'enum' do |(expected, val)|
194
194
  assert_equal expected, Config::ENUM_TYPE.call(val, {list: [:val, :value, :v]})
195
195
  end
196
196
 
@@ -21,12 +21,20 @@ class IntailIOHandlerTest < Test::Unit::TestCase
21
21
  @file.unlink rescue nil
22
22
  end
23
23
 
24
+ def create_target_info
25
+ Fluent::Plugin::TailInput::TargetInfo.new(@file.path, Fluent::FileWrapper.stat(@file.path).ino)
26
+ end
27
+
28
+ def create_watcher
29
+ Fluent::Plugin::TailInput::TailWatcher.new(create_target_info, nil, nil, nil, nil, nil, nil, nil, nil)
30
+ end
31
+
24
32
  test '#on_notify load file content and passed it to receive_lines method' do
25
33
  text = "this line is test\ntest line is test\n"
26
34
  @file.write(text)
27
35
  @file.close
28
36
 
29
- watcher = 'watcher'
37
+ watcher = create_watcher
30
38
 
31
39
  update_pos = 0
32
40
 
@@ -61,7 +69,7 @@ class IntailIOHandlerTest < Test::Unit::TestCase
61
69
 
62
70
  update_pos = 0
63
71
 
64
- watcher = 'watcher'
72
+ watcher = create_watcher
65
73
  stub(watcher).pe do
66
74
  pe = 'position_file'
67
75
  stub(pe).read_pos { 0 }
@@ -92,7 +100,7 @@ class IntailIOHandlerTest < Test::Unit::TestCase
92
100
 
93
101
  update_pos = 0
94
102
 
95
- watcher = 'watcher'
103
+ watcher = create_watcher
96
104
  stub(watcher).pe do
97
105
  pe = 'position_file'
98
106
  stub(pe).read_pos { 0 }
@@ -107,6 +115,7 @@ class IntailIOHandlerTest < Test::Unit::TestCase
107
115
  end
108
116
 
109
117
  r.on_notify
118
+ assert_equal text.bytesize, update_pos
110
119
  assert_equal 8, returned_lines[0].size
111
120
  end
112
121
 
@@ -118,7 +127,7 @@ class IntailIOHandlerTest < Test::Unit::TestCase
118
127
 
119
128
  update_pos = 0
120
129
 
121
- watcher = 'watcher'
130
+ watcher = create_watcher
122
131
  stub(watcher).pe do
123
132
  pe = 'position_file'
124
133
  stub(pe).read_pos { 0 }
@@ -133,6 +142,7 @@ class IntailIOHandlerTest < Test::Unit::TestCase
133
142
  end
134
143
 
135
144
  r.on_notify
145
+ assert_equal text.bytesize, update_pos
136
146
  assert_equal 5, returned_lines[0].size
137
147
  assert_equal 3, returned_lines[1].size
138
148
  end
@@ -40,10 +40,6 @@ class IntailPositionFileTest < Test::Unit::TestCase
40
40
 
41
41
  test '.load' do
42
42
  write_data(@file, TEST_CONTENT)
43
- paths = {
44
- "valid_path" => Fluent::Plugin::TailInput::TargetInfo.new("valid_path", 1),
45
- "inode23bit" => Fluent::Plugin::TailInput::TargetInfo.new("inode23bit", 2),
46
- }
47
43
  Fluent::Plugin::TailInput::PositionFile.load(@file, false, TEST_CONTENT_PATHS, **{logger: $log})
48
44
 
49
45
  @file.seek(0)
@@ -146,11 +142,6 @@ class IntailPositionFileTest < Test::Unit::TestCase
146
142
  sub_test_case '#load' do
147
143
  test 'compact invalid and convert 32 bit inode value' do
148
144
  write_data(@file, TEST_CONTENT)
149
- invalid_path = "invalidpath100000000000000000000000000000000"
150
- paths = TEST_CONTENT_PATHS.merge({
151
- invalid_path => Fluent::Plugin::TailInput::TargetInfo.new(invalid_path, 0),
152
- "unwatched" => Fluent::Plugin::TailInput::TargetInfo.new("unwatched", 0),
153
- })
154
145
  Fluent::Plugin::TailInput::PositionFile.load(@file, false, TEST_CONTENT_PATHS, **{logger: $log})
155
146
 
156
147
  @file.seek(0)
@@ -322,58 +313,4 @@ class IntailPositionFileTest < Test::Unit::TestCase
322
313
  assert_equal 2, f.read_inode
323
314
  end
324
315
  end
325
-
326
- sub_test_case "TargetInfo equality rules" do
327
- sub_test_case "== operator" do
328
- def test_equal
329
- t1 = Fluent::Plugin::TailInput::TargetInfo.new("test", 1234)
330
- t2 = Fluent::Plugin::TailInput::TargetInfo.new("test", 1235)
331
-
332
- assert_equal t1, t2
333
- end
334
-
335
- def test_not_equal
336
- t1 = Fluent::Plugin::TailInput::TargetInfo.new("test", 1234)
337
- t2 = Fluent::Plugin::TailInput::TargetInfo.new("test2", 1234)
338
-
339
- assert_not_equal t1, t2
340
- end
341
- end
342
-
343
- sub_test_case "eql? method" do
344
- def test_eql?
345
- t1 = Fluent::Plugin::TailInput::TargetInfo.new("test", 1234)
346
- t2 = Fluent::Plugin::TailInput::TargetInfo.new("test", 5321)
347
-
348
- assert do
349
- t1.eql? t2
350
- end
351
- end
352
-
353
- def test_not_eql?
354
- t1 = Fluent::Plugin::TailInput::TargetInfo.new("test2", 1234)
355
- t2 = Fluent::Plugin::TailInput::TargetInfo.new("test3", 1234)
356
-
357
- assert do
358
- !t1.eql? t2
359
- end
360
- end
361
- end
362
-
363
- sub_test_case "hash" do
364
- def test_equal
365
- t1 = Fluent::Plugin::TailInput::TargetInfo.new("test", 1234)
366
- t2 = Fluent::Plugin::TailInput::TargetInfo.new("test", 7321)
367
-
368
- assert_equal t1.hash, t2.hash
369
- end
370
-
371
- def test_not_equal
372
- t1 = Fluent::Plugin::TailInput::TargetInfo.new("test", 1234)
373
- t2 = Fluent::Plugin::TailInput::TargetInfo.new("test2", 1234)
374
-
375
- assert_not_equal t1.hash, t2.hash
376
- end
377
- end
378
- end
379
316
  end
@@ -110,6 +110,10 @@ class SocketCacheTest < Test::Unit::TestCase
110
110
  end
111
111
 
112
112
  sub_test_case 'purge_obsolete_socks' do
113
+ def teardown
114
+ Timecop.return
115
+ end
116
+
113
117
  test 'delete key in inactive_socks' do
114
118
  c = Fluent::Plugin::ForwardOutput::SocketCache.new(10, $log)
115
119
  sock = mock!.close { 'closed' }.subject
@@ -134,7 +138,7 @@ class SocketCacheTest < Test::Unit::TestCase
134
138
  c.checkin(sock)
135
139
 
136
140
  # wait timeout
137
- Timecop.freeze(Time.parse('2016-04-13 14:20:00 +0900'))
141
+ Timecop.freeze(Time.parse('2016-04-13 14:00:11 +0900'))
138
142
  c.checkout_or('key') { sock2 }
139
143
 
140
144
  assert_equal(1, c.instance_variable_get(:@inflight_sockets).size)
@@ -145,5 +149,26 @@ class SocketCacheTest < Test::Unit::TestCase
145
149
  assert_equal(1, c.instance_variable_get(:@inflight_sockets).size)
146
150
  assert_equal(sock2, c.instance_variable_get(:@inflight_sockets).values.first.sock)
147
151
  end
152
+
153
+ test 'should not purge just after checkin and purge after timeout' do
154
+ Timecop.freeze(Time.parse('2016-04-13 14:00:00 +0900'))
155
+
156
+ c = Fluent::Plugin::ForwardOutput::SocketCache.new(10, $log)
157
+ sock = dont_allow(mock!).close
158
+ stub(sock).inspect
159
+ c.checkout_or('key') { sock }
160
+
161
+ Timecop.freeze(Time.parse('2016-04-13 14:00:11 +0900'))
162
+ c.checkin(sock)
163
+
164
+ assert_equal(1, c.instance_variable_get(:@available_sockets).size)
165
+ c.purge_obsolete_socks
166
+ assert_equal(1, c.instance_variable_get(:@available_sockets).size)
167
+
168
+ Timecop.freeze(Time.parse('2016-04-13 14:00:22 +0900'))
169
+ assert_equal(1, c.instance_variable_get(:@available_sockets).size)
170
+ c.purge_obsolete_socks
171
+ assert_equal(0, c.instance_variable_get(:@available_sockets).size)
172
+ end
148
173
  end
149
174
  end