fluentd 0.14.9 → 0.14.10

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 (50) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -0
  3. data/ChangeLog +44 -0
  4. data/appveyor.yml +1 -0
  5. data/code-of-conduct.md +3 -0
  6. data/fluentd.gemspec +1 -1
  7. data/lib/fluent/command/cat.rb +11 -3
  8. data/lib/fluent/compat/output.rb +6 -3
  9. data/lib/fluent/compat/parser.rb +2 -0
  10. data/lib/fluent/config/section.rb +1 -1
  11. data/lib/fluent/env.rb +1 -1
  12. data/lib/fluent/plugin/filter_record_transformer.rb +12 -30
  13. data/lib/fluent/plugin/in_forward.rb +50 -169
  14. data/lib/fluent/plugin/in_monitor_agent.rb +8 -4
  15. data/lib/fluent/plugin/in_syslog.rb +13 -7
  16. data/lib/fluent/plugin/in_tail.rb +29 -14
  17. data/lib/fluent/plugin/in_tcp.rb +54 -14
  18. data/lib/fluent/plugin/in_udp.rb +49 -13
  19. data/lib/fluent/plugin/out_file.rb +30 -14
  20. data/lib/fluent/plugin/out_forward.rb +199 -173
  21. data/lib/fluent/plugin/output.rb +71 -46
  22. data/lib/fluent/plugin/parser_json.rb +1 -1
  23. data/lib/fluent/plugin_helper.rb +2 -0
  24. data/lib/fluent/plugin_helper/event_loop.rb +24 -6
  25. data/lib/fluent/plugin_helper/inject.rb +12 -1
  26. data/lib/fluent/plugin_helper/server.rb +494 -0
  27. data/lib/fluent/plugin_helper/socket.rb +101 -0
  28. data/lib/fluent/plugin_helper/socket_option.rb +84 -0
  29. data/lib/fluent/plugin_helper/timer.rb +1 -0
  30. data/lib/fluent/test/driver/base.rb +45 -13
  31. data/lib/fluent/version.rb +1 -1
  32. data/lib/fluent/winsvc.rb +1 -1
  33. data/test/compat/test_parser.rb +10 -0
  34. data/test/config/test_configurable.rb +20 -0
  35. data/test/helper.rb +36 -1
  36. data/test/plugin/test_filter_record_transformer.rb +31 -103
  37. data/test/plugin/test_in_forward.rb +13 -75
  38. data/test/plugin/test_in_monitor_agent.rb +65 -35
  39. data/test/plugin/test_in_syslog.rb +39 -3
  40. data/test/plugin/test_in_tcp.rb +78 -62
  41. data/test/plugin/test_in_udp.rb +101 -80
  42. data/test/plugin/test_out_file.rb +17 -0
  43. data/test/plugin/test_out_forward.rb +155 -125
  44. data/test/plugin/test_output_as_buffered.rb +4 -2
  45. data/test/plugin_helper/test_inject.rb +21 -0
  46. data/test/plugin_helper/test_server.rb +905 -0
  47. data/test/test_event_time.rb +3 -1
  48. data/test/test_output.rb +30 -1
  49. data/test/test_test_drivers.rb +5 -2
  50. metadata +19 -6
@@ -1,20 +1,8 @@
1
1
  require_relative '../helper'
2
- require 'fluent/test'
2
+ require 'fluent/test/driver/input'
3
3
  require 'fluent/plugin/in_tcp'
4
4
 
5
5
  class TcpInputTest < Test::Unit::TestCase
6
- class << self
7
- def startup
8
- socket_manager_path = ServerEngine::SocketManager::Server.generate_path
9
- @server = ServerEngine::SocketManager::Server.open(socket_manager_path)
10
- ENV['SERVERENGINE_SOCKETMANAGER_PATH'] = socket_manager_path.to_s
11
- end
12
-
13
- def shutdown
14
- @server.close
15
- end
16
- end
17
-
18
6
  def setup
19
7
  Fluent::Test.setup
20
8
  end
@@ -34,69 +22,97 @@ class TcpInputTest < Test::Unit::TestCase
34
22
  ]
35
23
 
36
24
  def create_driver(conf)
37
- Fluent::Test::InputTestDriver.new(Fluent::TcpInput).configure(conf)
25
+ Fluent::Test::Driver::Input.new(Fluent::Plugin::TcpInput).configure(conf)
38
26
  end
39
27
 
40
- def test_configure
41
- configs = {'127.0.0.1' => CONFIG}
42
- configs.merge!('::1' => IPv6_CONFIG) if ipv6_enabled?
28
+ def create_tcp_socket(host, port, &block)
29
+ if block_given?
30
+ TCPSocket.open(host, port, &block)
31
+ else
32
+ TCPSocket.open(host, port)
33
+ end
34
+ end
35
+
36
+
37
+ data(
38
+ 'ipv4' => [CONFIG, '127.0.0.1', :ipv4],
39
+ 'ipv6' => [IPv6_CONFIG, '::1', :ipv6],
40
+ )
41
+ test 'configure' do |data|
42
+ conf, bind, protocol = data
43
+ omit "IPv6 is not supported on this environment" if protocol == :ipv6 && !ipv6_enabled?
43
44
 
44
- configs.each_pair { |k, v|
45
- d = create_driver(v)
46
- assert_equal PORT, d.instance.port
47
- assert_equal k, d.instance.bind
48
- assert_equal "\n", d.instance.delimiter
49
- }
45
+ d = create_driver(conf)
46
+ assert_equal PORT, d.instance.port
47
+ assert_equal bind, d.instance.bind
48
+ assert_equal "\n", d.instance.delimiter
50
49
  end
51
50
 
52
- {
53
- 'none' => [
54
- {'msg' => "tcptest1\n", 'expected' => 'tcptest1'},
55
- {'msg' => "tcptest2\n", 'expected' => 'tcptest2'},
56
- ],
57
- 'json' => [
58
- {'msg' => {'k' => 123, 'message' => 'tcptest1'}.to_json + "\n", 'expected' => 'tcptest1'},
59
- {'msg' => {'k' => 'tcptest2', 'message' => 456}.to_json + "\n", 'expected' => 456},
60
- ]
61
- }.each { |format, test_cases|
62
- define_method("test_msg_size_#{format}") do
63
- d = create_driver(BASE_CONFIG + "format #{format}")
64
- tests = test_cases
51
+ test_case_data = {
52
+ 'none' => {
53
+ 'format' => 'none',
54
+ 'payloads' => [ "tcptest1\n", "tcptest2\n" ],
55
+ 'expecteds' => [
56
+ {'message' => 'tcptest1'},
57
+ {'message' => 'tcptest2'},
58
+ ],
59
+ },
60
+ 'json' => {
61
+ 'format' => 'json',
62
+ 'payloads' => [
63
+ {'k' => 123, 'message' => 'tcptest1'}.to_json + "\n",
64
+ {'k' => 'tcptest2', 'message' => 456}.to_json + "\n",
65
+ ],
66
+ 'expecteds' => [
67
+ {'k' => 123, 'message' => 'tcptest1'},
68
+ {'k' => 'tcptest2', 'message' => 456}
69
+ ],
70
+ },
71
+ }
72
+
73
+ data(test_case_data)
74
+ test 'test_msg_size' do |data|
75
+ format = data['format']
76
+ payloads = data['payloads']
77
+ expecteds = data['expecteds']
65
78
 
66
- d.run do
67
- tests.each {|test|
68
- TCPSocket.open('127.0.0.1', PORT) do |s|
69
- s.send(test['msg'], 0)
70
- end
71
- }
72
- sleep 1
79
+ d = create_driver(BASE_CONFIG + "format #{format}")
80
+ d.run(expect_records: 2) do
81
+ payloads.each do |payload|
82
+ create_tcp_socket('127.0.0.1', PORT) do |sock|
83
+ sock.send(payload, 0)
84
+ end
73
85
  end
86
+ end
74
87
 
75
- compare_test_result(d.emits, tests)
88
+ assert_equal 2, d.events.size
89
+ expecteds.each_with_index do |expected_record, i|
90
+ assert_equal "tcp", d.events[i][0]
91
+ assert d.events[i][1].is_a?(Fluent::EventTime)
92
+ assert_equal expected_record, d.events[i][2]
76
93
  end
94
+ end
77
95
 
78
- define_method("test_msg_size_with_same_connection_#{format}") do
79
- d = create_driver(BASE_CONFIG + "format #{format}")
80
- tests = test_cases
96
+ data(test_case_data)
97
+ test 'test data in a connection' do |data|
98
+ format = data['format']
99
+ payloads = data['payloads']
100
+ expecteds = data['expecteds']
81
101
 
82
- d.run do
83
- TCPSocket.open('127.0.0.1', PORT) do |s|
84
- tests.each {|test|
85
- s.send(test['msg'], 0)
86
- }
102
+ d = create_driver(BASE_CONFIG + "format #{format}")
103
+ d.run(expect_records: 2) do
104
+ create_tcp_socket('127.0.0.1', PORT) do |sock|
105
+ payloads.each do |payload|
106
+ sock.send(payload, 0)
87
107
  end
88
- sleep 1
89
108
  end
90
-
91
- compare_test_result(d.emits, tests)
92
109
  end
93
- }
94
110
 
95
- def compare_test_result(emits, tests)
96
- assert_equal(2, emits.size)
97
- emits.each_index {|i|
98
- assert_equal(tests[i]['expected'], emits[i][2]['message'])
99
- assert(emits[i][1].is_a?(Fluent::EventTime))
100
- }
111
+ assert_equal 2, d.events.size
112
+ expecteds.each_with_index do |expected_record, i|
113
+ assert_equal "tcp", d.events[i][0]
114
+ assert d.events[i][1].is_a?(Fluent::EventTime)
115
+ assert_equal expected_record, d.events[i][2]
116
+ end
101
117
  end
102
118
  end
@@ -1,20 +1,8 @@
1
1
  require_relative '../helper'
2
- require 'fluent/test'
2
+ require 'fluent/test/driver/input'
3
3
  require 'fluent/plugin/in_udp'
4
4
 
5
5
  class UdpInputTest < Test::Unit::TestCase
6
- class << self
7
- def startup
8
- socket_manager_path = ServerEngine::SocketManager::Server.generate_path
9
- @server = ServerEngine::SocketManager::Server.open(socket_manager_path)
10
- ENV['SERVERENGINE_SOCKETMANAGER_PATH'] = socket_manager_path.to_s
11
- end
12
-
13
- def shutdown
14
- @server.close
15
- end
16
- end
17
-
18
6
  def setup
19
7
  Fluent::Test.setup
20
8
  end
@@ -34,88 +22,121 @@ class UdpInputTest < Test::Unit::TestCase
34
22
  !
35
23
 
36
24
  def create_driver(conf)
37
- Fluent::Test::InputTestDriver.new(Fluent::UdpInput).configure(conf)
25
+ Fluent::Test::Driver::Input.new(Fluent::Plugin::UdpInput).configure(conf)
38
26
  end
39
27
 
40
- def test_configure
41
- configs = {'127.0.0.1' => CONFIG}
42
- configs.merge!('::1' => IPv6_CONFIG) if ipv6_enabled?
28
+ def create_udp_socket(host, port)
29
+ u = if IPAddr.new(IPSocket.getaddress(host)).ipv4?
30
+ UDPSocket.new(Socket::AF_INET)
31
+ else
32
+ UDPSocket.new(Socket::AF_INET6)
33
+ end
34
+ u.connect(host, port)
35
+ if block_given?
36
+ begin
37
+ yield u
38
+ ensure
39
+ u.close rescue nil
40
+ end
41
+ else
42
+ u
43
+ end
44
+ end
43
45
 
44
- configs.each_pair { |k, v|
45
- d = create_driver(v)
46
- assert_equal PORT, d.instance.port
47
- assert_equal k, d.instance.bind
48
- assert_equal 4096, d.instance.body_size_limit
49
- }
46
+ data(
47
+ 'ipv4' => [CONFIG, '127.0.0.1', :ipv4],
48
+ 'ipv6' => [IPv6_CONFIG, '::1', :ipv6],
49
+ )
50
+ test 'configure' do |data|
51
+ conf, bind, protocol = data
52
+ omit "IPv6 is not supported on this environment" if protocol == :ipv6 && !ipv6_enabled?
53
+
54
+ d = create_driver(conf)
55
+ assert_equal PORT, d.instance.port
56
+ assert_equal bind, d.instance.bind
57
+ assert_equal 4096, d.instance.body_size_limit
50
58
  end
51
59
 
52
- def test_time_format
53
- configs = {'127.0.0.1' => CONFIG}
54
- configs.merge!('::1' => IPv6_CONFIG) if ipv6_enabled?
60
+ data(
61
+ 'ipv4' => [CONFIG, '127.0.0.1', :ipv4],
62
+ 'ipv6' => [IPv6_CONFIG, '::1', :ipv6],
63
+ )
64
+ test 'time_format' do |data|
65
+ conf, bind, protocol = data
66
+ omit "IPv6 is not supported on this environment" if protocol == :ipv6 && !ipv6_enabled?
55
67
 
56
- configs.each_pair { |k, v|
57
- d = create_driver(v)
68
+ d = create_driver(conf)
58
69
 
59
- tests = [
60
- {'msg' => '[Sep 11 00:00:00] localhost logger: foo', 'expected' => Fluent::EventTime.from_time(Time.strptime('Sep 11 00:00:00', '%b %d %H:%M:%S'))},
61
- {'msg' => '[Sep 1 00:00:00] localhost logger: foo', 'expected' => Fluent::EventTime.from_time(Time.strptime('Sep 1 00:00:00', '%b %d %H:%M:%S'))},
62
- ]
70
+ tests = [
71
+ {'msg' => '[Sep 11 00:00:00] localhost logger: foo', 'expected' => event_time('Sep 11 00:00:00', format: '%b %d %H:%M:%S')},
72
+ {'msg' => '[Sep 1 00:00:00] localhost logger: foo', 'expected' => event_time('Sep 1 00:00:00', format: '%b %d %H:%M:%S')},
73
+ ]
63
74
 
64
- d.run do
65
- u = Fluent::SocketUtil.create_udp_socket(k)
66
- u.connect(k, PORT)
67
- tests.each {|test|
75
+ d.run(expect_records: 2) do
76
+ create_udp_socket(bind, PORT) do |u|
77
+ tests.each do |test|
68
78
  u.send(test['msg'], 0)
69
- }
70
- u.close
71
- sleep 1
79
+ end
72
80
  end
81
+ end
73
82
 
74
- emits = d.emits
75
- emits.each_index {|i|
76
- assert_equal_event_time(tests[i]['expected'], emits[i][1])
77
- }
78
- }
79
-
83
+ events = d.events
84
+ tests.each_with_index do |t, i|
85
+ assert_equal_event_time(t['expected'], events[i][1])
86
+ end
80
87
  end
81
88
 
82
- {
83
- 'none' => [
84
- {'msg' => "tcptest1\n", 'expected' => 'tcptest1'},
85
- {'msg' => "tcptest2\n", 'expected' => 'tcptest2'},
86
- ],
87
- 'json' => [
88
- {'msg' => {'k' => 123, 'message' => 'tcptest1'}.to_json + "\n", 'expected' => 'tcptest1'},
89
- {'msg' => {'k' => 'tcptest2', 'message' => 456}.to_json + "\n", 'expected' => 456},
90
- ],
91
- '/^\\[(?<time>[^\\]]*)\\] (?<message>.*)/' => [
92
- {'msg' => '[Sep 10 00:00:00] localhost: ' + 'x' * 100 + "\n", 'expected' => 'localhost: ' + 'x' * 100},
93
- {'msg' => '[Sep 10 00:00:00] localhost: ' + 'x' * 1024 + "\n", 'expected' => 'localhost: ' + 'x' * 1024},
94
- ]
95
- }.each { |format, test_cases|
96
- define_method("test_msg_size_#{format[0] == '/' ? 'regexp' : format}") do
97
- d = create_driver(BASE_CONFIG + "format #{format}")
98
- tests = test_cases
99
-
100
- d.run do
101
- u = UDPSocket.new
102
- u.connect('127.0.0.1', PORT)
103
- tests.each { |test|
104
- u.send(test['msg'], 0)
105
- }
106
- u.close
107
- sleep 1
89
+ data(
90
+ 'none' => {
91
+ 'format' => 'none',
92
+ 'payloads' => ["tcptest1\n", "tcptest2\n"],
93
+ 'expecteds' => [
94
+ {"message" => "tcptest1"},
95
+ {"message" => "tcptest2"},
96
+ ],
97
+ },
98
+ 'json' => {
99
+ 'format' => 'json',
100
+ 'payloads' => [
101
+ {'k' => 123, 'message' => 'tcptest1'}.to_json + "\n",
102
+ {'k' => 'tcptest2', 'message' => 456}.to_json + "\n",
103
+ ],
104
+ 'expecteds' => [
105
+ {'k' => 123, 'message' => 'tcptest1'},
106
+ {'k' => 'tcptest2', 'message' => 456},
107
+ ],
108
+ },
109
+ 'regexp' => {
110
+ 'format' => '/^\\[(?<time>[^\\]]*)\\] (?<message>.*)/',
111
+ 'payloads' => [
112
+ '[Sep 10 00:00:00] localhost: ' + 'x' * 100 + "\n",
113
+ '[Sep 10 00:00:00] localhost: ' + 'x' * 1024 + "\n"
114
+ ],
115
+ 'expecteds' => [
116
+ {"message" => 'localhost: ' + 'x' * 100},
117
+ {"message" => 'localhost: ' + 'x' * 1024},
118
+ ],
119
+ },
120
+ )
121
+ test 'message size with format' do |data|
122
+ format = data['format']
123
+ payloads = data['payloads']
124
+ expecteds = data['expecteds']
125
+
126
+ d = create_driver(BASE_CONFIG + "format #{format}")
127
+ d.run(expect_records: 2) do
128
+ create_udp_socket('127.0.0.1', PORT) do |u|
129
+ payloads.each do |payload|
130
+ u.send(payload, 0)
131
+ end
108
132
  end
109
-
110
- compare_test_result(d.emits, tests)
111
133
  end
112
- }
113
134
 
114
- def compare_test_result(emits, tests)
115
- assert_equal(2, emits.size)
116
- emits.each_index {|i|
117
- assert_equal(tests[i]['expected'], emits[i][2]['message'])
118
- assert(emits[i][1].is_a?(Fluent::EventTime))
119
- }
135
+ assert_equal 2, d.events.size
136
+ expecteds.each_with_index do |expected_record, i|
137
+ assert_equal "udp", d.events[i][0]
138
+ assert d.events[i][1].is_a?(Fluent::EventTime)
139
+ assert_equal expected_record, d.events[i][2]
140
+ end
120
141
  end
121
142
  end
@@ -133,6 +133,23 @@ class FileOutputTest < Test::Unit::TestCase
133
133
  create_driver(conf)
134
134
  end
135
135
  end
136
+
137
+ test 'configured as secondary with primary using chunk_key_tag and not using chunk_key_time' do
138
+ require 'fluent/plugin/out_null'
139
+ port = unused_port
140
+ conf = config_element('match', '**', {
141
+ }, [
142
+ config_element('buffer', 'tag', {
143
+ }),
144
+ config_element('secondary', '', {
145
+ '@type' => 'file',
146
+ 'path' => "#{TMP_DIR}/testing_to_dump_by_out_file",
147
+ }),
148
+ ])
149
+ assert_nothing_raised do
150
+ Fluent::Test::Driver::Output.new(Fluent::Plugin::NullOutput).configure(conf)
151
+ end
152
+ end
136
153
  end
137
154
 
138
155
  sub_test_case 'fully configured output' do
@@ -1,6 +1,5 @@
1
1
  require_relative '../helper'
2
2
  require 'fluent/test/driver/output'
3
- require 'fluent/test/startup_shutdown'
4
3
  require 'fluent/plugin/out_forward'
5
4
  require 'flexmock/test_unit'
6
5
 
@@ -8,10 +7,13 @@ require 'fluent/test/driver/input'
8
7
  require 'fluent/plugin/in_forward'
9
8
 
10
9
  class ForwardOutputTest < Test::Unit::TestCase
11
- extend Fluent::Test::StartupShutdown
12
-
13
10
  def setup
14
11
  Fluent::Test.setup
12
+ @d = nil
13
+ end
14
+
15
+ def teardown
16
+ @d.instance_shutdown if @d
15
17
  end
16
18
 
17
19
  TARGET_HOST = '127.0.0.1'
@@ -35,35 +37,23 @@ class ForwardOutputTest < Test::Unit::TestCase
35
37
  Fluent::Test::Driver::Output.new(Fluent::Plugin::ForwardOutput) {
36
38
  attr_reader :responses, :exceptions
37
39
 
38
- def write(chunk)
39
- super
40
- end
41
-
42
40
  def initialize
43
41
  super
44
42
  @responses = []
45
43
  @exceptions = []
46
44
  end
47
45
 
48
- def configure(conf)
49
- super
50
- m = Module.new do
51
- def send_data(tag, chunk)
52
- @sender.responses << super
53
- rescue => e
54
- @sender.exceptions << e
55
- raise e
56
- end
57
- end
58
- @nodes.each do |node|
59
- node.singleton_class.prepend(m)
60
- end
46
+ def read_ack_from_sock(sock, unpacker)
47
+ @responses << super
48
+ rescue => e
49
+ @exceptions << e
50
+ raise e
61
51
  end
62
52
  }.configure(conf)
63
53
  end
64
54
 
65
- def test_configure
66
- d = create_driver(%[
55
+ test 'configure' do
56
+ @d = d = create_driver(%[
67
57
  self_hostname localhost
68
58
  <server>
69
59
  name test
@@ -81,44 +71,71 @@ class ForwardOutputTest < Test::Unit::TestCase
81
71
  assert_equal TARGET_PORT, node.port
82
72
  end
83
73
 
84
- def test_configure_udp_heartbeat
85
- d = create_driver(CONFIG + "\nheartbeat_type udp")
74
+ test 'configure_traditional' do
75
+ @d = d = create_driver(<<EOL)
76
+ self_hostname localhost
77
+ <server>
78
+ name test
79
+ host #{TARGET_HOST}
80
+ port #{TARGET_PORT}
81
+ </server>
82
+ buffer_chunk_limit 10m
83
+ EOL
84
+ instance = d.instance
85
+ assert instance.chunk_key_tag
86
+ assert !instance.chunk_key_time
87
+ assert_equal [], instance.chunk_keys
88
+ assert{ instance.buffer.is_a?(Fluent::Plugin::MemoryBuffer) }
89
+ assert_equal( 10*1024*1024, instance.buffer.chunk_limit_size )
90
+ end
91
+
92
+ test 'configure_udp_heartbeat' do
93
+ @d = d = create_driver(CONFIG + "\nheartbeat_type udp")
86
94
  assert_equal :udp, d.instance.heartbeat_type
87
95
  end
88
96
 
89
- def test_configure_none_heartbeat
90
- d = create_driver(CONFIG + "\nheartbeat_type none")
97
+ test 'configure_none_heartbeat' do
98
+ @d = d = create_driver(CONFIG + "\nheartbeat_type none")
91
99
  assert_equal :none, d.instance.heartbeat_type
92
100
  end
93
101
 
94
- def test_configure_dns_round_robin
102
+ test 'configure_expire_dns_cache' do
103
+ @d = d = create_driver(CONFIG + "\nexpire_dns_cache 5")
104
+ assert_equal 5, d.instance.expire_dns_cache
105
+ end
106
+
107
+ test 'configure_dns_round_robin udp' do
95
108
  assert_raise(Fluent::ConfigError) do
96
109
  create_driver(CONFIG + "\nheartbeat_type udp\ndns_round_robin true")
97
110
  end
111
+ end
98
112
 
99
- d = create_driver(CONFIG + "\nheartbeat_type tcp\ndns_round_robin true")
113
+ test 'configure_dns_round_robin tcp' do
114
+ @d = d = create_driver(CONFIG + "\nheartbeat_type tcp\ndns_round_robin true")
100
115
  assert_equal true, d.instance.dns_round_robin
116
+ end
101
117
 
102
- d = create_driver(CONFIG + "\nheartbeat_type none\ndns_round_robin true")
118
+ test 'configure_dns_round_robin none' do
119
+ @d = d = create_driver(CONFIG + "\nheartbeat_type none\ndns_round_robin true")
103
120
  assert_equal true, d.instance.dns_round_robin
104
121
  end
105
122
 
106
- def test_configure_no_server
123
+ test 'configure_no_server' do
107
124
  assert_raise(Fluent::ConfigError, 'forward output plugin requires at least one <server> is required') do
108
125
  create_driver('')
109
126
  end
110
127
  end
111
128
 
112
- def test_compress_default_value
113
- d = create_driver
129
+ test 'compress_default_value' do
130
+ @d = d = create_driver
114
131
  assert_equal :text, d.instance.compress
115
132
 
116
133
  node = d.instance.nodes.first
117
134
  assert_equal :text, node.instance_variable_get(:@compress)
118
135
  end
119
136
 
120
- def test_set_compress_is_gzip
121
- d = create_driver(CONFIG + %[compress gzip])
137
+ test 'set_compress_is_gzip' do
138
+ @d = d = create_driver(CONFIG + %[compress gzip])
122
139
  assert_equal :gzip, d.instance.compress
123
140
  assert_equal :gzip, d.instance.buffer.compress
124
141
 
@@ -126,11 +143,11 @@ class ForwardOutputTest < Test::Unit::TestCase
126
143
  assert_equal :gzip, node.instance_variable_get(:@compress)
127
144
  end
128
145
 
129
- def test_set_compress_is_gzip_in_buffer_section
146
+ test 'set_compress_is_gzip_in_buffer_section' do
130
147
  mock = flexmock($log)
131
148
  mock.should_receive(:log).with("buffer is compressed. If you also want to save the bandwidth of a network, Add `compress` configuration in <match>")
132
149
 
133
- d = create_driver(CONFIG + %[
150
+ @d = d = create_driver(CONFIG + %[
134
151
  <buffer>
135
152
  type memory
136
153
  compress gzip
@@ -143,25 +160,29 @@ class ForwardOutputTest < Test::Unit::TestCase
143
160
  assert_equal :text, node.instance_variable_get(:@compress)
144
161
  end
145
162
 
146
- def test_phi_failure_detector
147
- d = create_driver(CONFIG + %[phi_failure_detector false \n phi_threshold 0])
163
+ test 'phi_failure_detector disabled' do
164
+ @d = d = create_driver(CONFIG + %[phi_failure_detector false \n phi_threshold 0])
148
165
  node = d.instance.nodes.first
149
166
  stub(node.failure).phi { raise 'Should not be called' }
150
167
  node.tick
151
168
  assert_equal node.available, true
169
+ end
152
170
 
153
- d = create_driver(CONFIG + %[phi_failure_detector true \n phi_threshold 0])
171
+ test 'phi_failure_detector enabled' do
172
+ @d = d = create_driver(CONFIG + %[phi_failure_detector true \n phi_threshold 0])
154
173
  node = d.instance.nodes.first
155
174
  node.tick
156
175
  assert_equal node.available, false
157
176
  end
158
177
 
159
- def test_wait_response_timeout_config
160
- d = create_driver(CONFIG)
178
+ test 'require_ack_response is disabled in default' do
179
+ @d = d = create_driver(CONFIG)
161
180
  assert_equal false, d.instance.require_ack_response
162
181
  assert_equal 190, d.instance.ack_response_timeout
182
+ end
163
183
 
164
- d = create_driver(CONFIG + %[
184
+ test 'require_ack_response can be enabled' do
185
+ @d = d = create_driver(CONFIG + %[
165
186
  require_ack_response true
166
187
  ack_response_timeout 2s
167
188
  ])
@@ -169,10 +190,10 @@ class ForwardOutputTest < Test::Unit::TestCase
169
190
  assert_equal 2, d.instance.ack_response_timeout
170
191
  end
171
192
 
172
- def test_send_with_time_as_integer
193
+ test 'send_with_time_as_integer' do
173
194
  target_input_driver = create_target_input_driver
174
195
 
175
- d = create_driver(CONFIG + %[flush_interval 1s])
196
+ @d = d = create_driver(CONFIG + %[flush_interval 1s])
176
197
 
177
198
  time = event_time("2011-01-02 13:14:15 UTC")
178
199
 
@@ -180,8 +201,7 @@ class ForwardOutputTest < Test::Unit::TestCase
180
201
  {"a" => 1},
181
202
  {"a" => 2}
182
203
  ]
183
- target_input_driver.run do
184
- d.end_if{ d.instance.responses.length == 1 }
204
+ target_input_driver.run(expect_records: 2) do
185
205
  d.run(default_tag: 'test') do
186
206
  records.each do |record|
187
207
  d.feed(time, record)
@@ -195,14 +215,13 @@ class ForwardOutputTest < Test::Unit::TestCase
195
215
  assert_equal_event_time(time, events[1][1])
196
216
  assert_equal ['test', time, records[1]], events[1]
197
217
 
198
- assert_equal [nil], d.instance.responses # not attempt to receive responses, so nil is returned
199
218
  assert_empty d.instance.exceptions
200
219
  end
201
220
 
202
- def test_send_without_time_as_integer
221
+ test 'send_without_time_as_integer' do
203
222
  target_input_driver = create_target_input_driver
204
223
 
205
- d = create_driver(CONFIG + %[
224
+ @d = d = create_driver(CONFIG + %[
206
225
  flush_interval 1s
207
226
  time_as_integer false
208
227
  ])
@@ -213,8 +232,7 @@ class ForwardOutputTest < Test::Unit::TestCase
213
232
  {"a" => 1},
214
233
  {"a" => 2}
215
234
  ]
216
- target_input_driver.run do
217
- d.end_if{ d.instance.responses.length == 1 }
235
+ target_input_driver.run(expect_records: 2) do
218
236
  d.run(default_tag: 'test') do
219
237
  records.each do |record|
220
238
  d.feed(time, record)
@@ -228,14 +246,13 @@ class ForwardOutputTest < Test::Unit::TestCase
228
246
  assert_equal_event_time(time, events[1][1])
229
247
  assert_equal ['test', time, records[1]], events[1]
230
248
 
231
- assert_equal [nil], d.instance.responses # not attempt to receive responses, so nil is returned
232
249
  assert_empty d.instance.exceptions
233
250
  end
234
251
 
235
- def test_send_comprssed_message_pack_stream_if_compress_is_gzip
252
+ test 'send_comprssed_message_pack_stream_if_compress_is_gzip' do
236
253
  target_input_driver = create_target_input_driver
237
254
 
238
- d = create_driver(CONFIG + %[
255
+ @d = d = create_driver(CONFIG + %[
239
256
  flush_interval 1s
240
257
  compress gzip
241
258
  ])
@@ -246,8 +263,7 @@ class ForwardOutputTest < Test::Unit::TestCase
246
263
  {"a" => 1},
247
264
  {"a" => 2}
248
265
  ]
249
- target_input_driver.run do
250
- d.end_if{ d.instance.responses.length == 1 }
266
+ target_input_driver.run(expect_records: 2) do
251
267
  d.run(default_tag: 'test') do
252
268
  records.each do |record|
253
269
  d.feed(time, record)
@@ -263,10 +279,10 @@ class ForwardOutputTest < Test::Unit::TestCase
263
279
  assert_equal ['test', time, records[1]], events[1]
264
280
  end
265
281
 
266
- def test_send_to_a_node_supporting_responses
267
- target_input_driver = create_target_input_driver(response_stub: true)
282
+ test 'send_to_a_node_supporting_responses' do
283
+ target_input_driver = create_target_input_driver
268
284
 
269
- d = create_driver(CONFIG + %[flush_interval 1s])
285
+ @d = d = create_driver(CONFIG + %[flush_interval 1s])
270
286
 
271
287
  time = event_time("2011-01-02 13:14:15 UTC")
272
288
 
@@ -274,8 +290,7 @@ class ForwardOutputTest < Test::Unit::TestCase
274
290
  {"a" => 1},
275
291
  {"a" => 2}
276
292
  ]
277
- target_input_driver.run do
278
- d.end_if{ d.instance.responses.length == 1 }
293
+ target_input_driver.run(expect_records: 2) do
279
294
  d.run(default_tag: 'test') do
280
295
  records.each do |record|
281
296
  d.feed(time, record)
@@ -287,14 +302,14 @@ class ForwardOutputTest < Test::Unit::TestCase
287
302
  assert_equal ['test', time, records[0]], events[0]
288
303
  assert_equal ['test', time, records[1]], events[1]
289
304
 
290
- assert_equal [nil], d.instance.responses # not attempt to receive responses, so nil is returned
305
+ assert_empty d.instance.responses # not attempt to receive responses, so it's empty
291
306
  assert_empty d.instance.exceptions
292
307
  end
293
308
 
294
- def test_send_to_a_node_not_supporting_responses
309
+ test 'send_to_a_node_not_supporting_responses' do
295
310
  target_input_driver = create_target_input_driver
296
311
 
297
- d = create_driver(CONFIG + %[flush_interval 1s])
312
+ @d = d = create_driver(CONFIG + %[flush_interval 1s])
298
313
 
299
314
  time = event_time("2011-01-02 13:14:15 UTC")
300
315
 
@@ -302,8 +317,7 @@ class ForwardOutputTest < Test::Unit::TestCase
302
317
  {"a" => 1},
303
318
  {"a" => 2}
304
319
  ]
305
- target_input_driver.run do
306
- d.end_if{ d.instance.responses.length == 1 }
320
+ target_input_driver.run(expect_records: 2) do
307
321
  d.run(default_tag: 'test') do
308
322
  records.each do |record|
309
323
  d.feed(time, record)
@@ -315,17 +329,22 @@ class ForwardOutputTest < Test::Unit::TestCase
315
329
  assert_equal ['test', time, records[0]], events[0]
316
330
  assert_equal ['test', time, records[1]], events[1]
317
331
 
318
- assert_equal [nil], d.instance.responses # not attempt to receive responses, so nil is returned
332
+ assert_empty d.instance.responses # not attempt to receive responses, so it's empty
319
333
  assert_empty d.instance.exceptions
320
334
  end
321
335
 
322
- def test_require_a_node_supporting_responses_to_respond_with_ack
336
+ test 'a node supporting responses' do
323
337
  target_input_driver = create_target_input_driver
324
338
 
325
- d = create_driver(CONFIG + %[
326
- flush_interval 1s
339
+ @d = d = create_driver(CONFIG + %[
327
340
  require_ack_response true
328
341
  ack_response_timeout 1s
342
+ <buffer tag>
343
+ flush_mode immediate
344
+ retry_type periodic
345
+ retry_wait 30s
346
+ flush_at_shutdown false # suppress errors in d.instance_shutdown
347
+ </buffer>
329
348
  ])
330
349
 
331
350
  time = event_time("2011-01-02 13:14:15 UTC")
@@ -334,12 +353,10 @@ class ForwardOutputTest < Test::Unit::TestCase
334
353
  {"a" => 1},
335
354
  {"a" => 2}
336
355
  ]
337
- target_input_driver.run do
338
- d.end_if{ d.instance.responses.length == 1 }
339
- d.run(default_tag: 'test') do
340
- records.each do |record|
341
- d.feed(time, record)
342
- end
356
+ target_input_driver.run(expect_records: 2) do
357
+ d.end_if{ d.instance.responses.length > 0 }
358
+ d.run(default_tag: 'test', wait_flush_completion: false, shutdown: false) do
359
+ d.feed([[time, records[0]], [time,records[1]]])
343
360
  end
344
361
  end
345
362
 
@@ -348,87 +365,100 @@ class ForwardOutputTest < Test::Unit::TestCase
348
365
  assert_equal ['test', time, records[1]], events[1]
349
366
 
350
367
  assert_equal 1, d.instance.responses.length
351
- assert d.instance.responses[0].has_key?('ack')
352
368
  assert_empty d.instance.exceptions
353
369
  end
354
370
 
355
- def test_require_a_node_not_supporting_responses_to_respond_with_ack
356
- target_input_driver = create_target_input_driver(response_stub: ->(_option) { nil }, disconnect: true)
371
+ test 'a destination node not supporting responses by just ignoring' do
372
+ target_input_driver = create_target_input_driver(response_stub: ->(_option) { nil }, disconnect: false)
357
373
 
358
- d = create_driver(CONFIG + %[
359
- flush_interval 1s
374
+ @d = d = create_driver(CONFIG + %[
360
375
  require_ack_response true
361
376
  ack_response_timeout 1s
377
+ <buffer tag>
378
+ flush_mode immediate
379
+ retry_type periodic
380
+ retry_wait 30s
381
+ flush_at_shutdown false # suppress errors in d.instance_shutdown
382
+ </buffer>
362
383
  ])
363
384
 
385
+ node = d.instance.nodes.first
386
+ delayed_commit_timeout_value = nil
387
+
364
388
  time = event_time("2011-01-02 13:14:15 UTC")
365
389
 
366
390
  records = [
367
391
  {"a" => 1},
368
392
  {"a" => 2}
369
393
  ]
370
- assert_raise Fluent::Plugin::ForwardOutput::ACKTimeoutError do
371
- target_input_driver.run do
372
- d.end_if{ d.instance.responses.length == 1 }
373
- d.run(default_tag: 'test', timeout: 2, wait_flush_completion: false) do
374
- records.each do |record|
375
- d.feed(time, record)
376
- end
377
- end
394
+ target_input_driver.end_if{ d.instance.rollback_count > 0 }
395
+ target_input_driver.end_if{ !node.available }
396
+ target_input_driver.run(expect_records: 2, timeout: 25) do
397
+ d.run(default_tag: 'test', timeout: 20, wait_flush_completion: false, shutdown: false) do
398
+ delayed_commit_timeout_value = d.instance.delayed_commit_timeout
399
+ d.feed([[time, records[0]], [time,records[1]]])
378
400
  end
379
401
  end
380
402
 
403
+ assert_equal 1, delayed_commit_timeout_value
404
+
381
405
  events = target_input_driver.events
382
406
  assert_equal ['test', time, records[0]], events[0]
383
407
  assert_equal ['test', time, records[1]], events[1]
384
408
 
385
- node = d.instance.nodes.first
386
- assert_equal false, node.available # node is regarded as unavailable when timeout
409
+ assert{ d.instance.rollback_count > 0 }
387
410
 
388
- assert_empty d.instance.responses # send_data() raises exception, so response is missing
389
- assert_equal 1, d.instance.exceptions.size
411
+ logs = d.instance.log.logs
412
+ assert{ logs.any?{|log| log.include?("failed to flush the buffer chunk, timeout to commit.") } }
413
+ assert{ logs.any?{|log| log.include?("no response from node. regard it as unavailable.") } }
390
414
  end
391
415
 
392
- # bdf1f4f104c00a791aa94dc20087fe2011e1fd83
393
- def test_require_a_node_not_supporting_responses_2_to_respond_with_ack
394
- # in_forward, that doesn't support ack feature, and disconnect immediately
416
+ test 'a destination node not supporting responses by disconnection' do
395
417
  target_input_driver = create_target_input_driver(response_stub: ->(_option) { nil }, disconnect: true)
396
418
 
397
- d = create_driver(CONFIG + %[
398
- flush_interval 1s
419
+ @d = d = create_driver(CONFIG + %[
399
420
  require_ack_response true
400
421
  ack_response_timeout 5s
422
+ <buffer tag>
423
+ flush_mode immediate
424
+ retry_type periodic
425
+ retry_wait 30s
426
+ flush_at_shutdown false # suppress errors in d.instance_shutdown
427
+ </buffer>
401
428
  ])
402
429
 
430
+ node = d.instance.nodes.first
431
+ delayed_commit_timeout_value = nil
432
+
403
433
  time = event_time("2011-01-02 13:14:15 UTC")
404
434
 
405
435
  records = [
406
436
  {"a" => 1},
407
437
  {"a" => 2}
408
438
  ]
409
- assert_raise Fluent::Plugin::ForwardOutput::ACKTimeoutError do
410
- target_input_driver.run do
411
- d.end_if{ d.instance.responses.length == 1 }
412
- d.run(default_tag: 'test', timeout: 2, wait_flush_completion: false) do
413
- records.each do |record|
414
- d.feed(time, record)
415
- end
416
- end
439
+ target_input_driver.end_if{ d.instance.rollback_count > 0 }
440
+ target_input_driver.end_if{ !node.available }
441
+ target_input_driver.run(expect_records: 2, timeout: 25) do
442
+ d.run(default_tag: 'test', timeout: 20, wait_flush_completion: false, shutdown: false) do
443
+ delayed_commit_timeout_value = d.instance.delayed_commit_timeout
444
+ d.feed([[time, records[0]], [time,records[1]]])
417
445
  end
418
446
  end
419
447
 
448
+ assert_equal 5, delayed_commit_timeout_value
449
+
420
450
  events = target_input_driver.events
421
451
  assert_equal ['test', time, records[0]], events[0]
422
452
  assert_equal ['test', time, records[1]], events[1]
423
453
 
424
- assert_equal 0, d.instance.responses.size
425
- assert_equal 1, d.instance.exceptions.size # send_data() fails and to be retried
454
+ assert{ d.instance.rollback_count > 0 }
426
455
 
427
- node = d.instance.nodes.first
428
- assert_equal false, node.available # node is regarded as unavailable when unexpected EOF
456
+ logs = d.instance.log.logs
457
+ assert{ logs.any?{|log| log.include?("failed to flush the buffer chunk, timeout to commit.") } }
458
+ assert{ logs.any?{|log| log.include?("no response from node. regard it as unavailable.") } }
429
459
  end
430
460
 
431
- def test_authentication_with_shared_key
461
+ test 'authentication_with_shared_key' do
432
462
  input_conf = TARGET_CONFIG + %[
433
463
  <security>
434
464
  self_hostname in.localhost
@@ -453,7 +483,7 @@ class ForwardOutputTest < Test::Unit::TestCase
453
483
  shared_key fluentd-sharedkey
454
484
  </server>
455
485
  ]
456
- d = create_driver(output_conf)
486
+ @d = d = create_driver(output_conf)
457
487
 
458
488
  time = event_time("2011-01-02 13:14:15 UTC")
459
489
  records = [
@@ -475,7 +505,7 @@ class ForwardOutputTest < Test::Unit::TestCase
475
505
  assert_equal(['test', time, records[1]], events[1])
476
506
  end
477
507
 
478
- def test_authentication_with_user_auth
508
+ test 'authentication_with_user_auth' do
479
509
  input_conf = TARGET_CONFIG + %[
480
510
  <security>
481
511
  self_hostname in.localhost
@@ -507,7 +537,7 @@ class ForwardOutputTest < Test::Unit::TestCase
507
537
  password fluentd
508
538
  </server>
509
539
  ]
510
- d = create_driver(output_conf)
540
+ @d = d = create_driver(output_conf)
511
541
 
512
542
  time = event_time("2011-01-02 13:14:15 UTC")
513
543
  records = [
@@ -544,8 +574,8 @@ class ForwardOutputTest < Test::Unit::TestCase
544
574
  }.configure(conf)
545
575
  end
546
576
 
547
- def test_heartbeat_type_none
548
- d = create_driver(CONFIG + "\nheartbeat_type none")
577
+ test 'heartbeat_type_none' do
578
+ @d = d = create_driver(CONFIG + "\nheartbeat_type none")
549
579
  node = d.instance.nodes.first
550
580
  assert_equal Fluent::Plugin::ForwardOutput::NoneHeartbeatNode, node.class
551
581
 
@@ -558,23 +588,23 @@ class ForwardOutputTest < Test::Unit::TestCase
558
588
  assert_equal node.available, true
559
589
  end
560
590
 
561
- def test_heartbeat_type_udp
562
- d = create_driver(CONFIG + "\nheartbeat_type udp")
591
+ test 'heartbeat_type_udp' do
592
+ @d = d = create_driver(CONFIG + "\nheartbeat_type udp")
563
593
 
564
594
  d.instance.start
565
595
  usock = d.instance.instance_variable_get(:@usock)
566
- timer = d.instance.instance_variable_get(:@timer)
567
- hb = d.instance.instance_variable_get(:@hb)
596
+ servers = d.instance.instance_variable_get(:@_servers)
597
+ timers = d.instance.instance_variable_get(:@_timers)
568
598
  assert_equal UDPSocket, usock.class
569
- assert_equal Fluent::Plugin::ForwardOutput::HeartbeatRequestTimer, timer.class
570
- assert_equal Fluent::Plugin::ForwardOutput::HeartbeatHandler, hb.class
599
+ assert servers.find{|s| s.title == :out_forward_heartbeat_receiver }
600
+ assert timers.include?(:out_forward_heartbeat_request)
571
601
 
572
602
  mock(usock).send("\0", 0, Socket.pack_sockaddr_in(TARGET_PORT, '127.0.0.1')).once
573
- timer.disable # call send_heartbeat at just once
574
- timer.on_timer
603
+ # timer.disable # call send_heartbeat at just once
604
+ d.instance.send(:on_timer)
575
605
  end
576
606
 
577
- def test_acts_as_secondary
607
+ test 'acts_as_secondary' do
578
608
  i = Fluent::Plugin::ForwardOutput.new
579
609
  conf = config_element(
580
610
  'match',