fluentd 1.6.3 → 1.7.0.rc1

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 (78) hide show
  1. checksums.yaml +4 -4
  2. data/.drone.yml +35 -0
  3. data/.github/ISSUE_TEMPLATE/bug_report.md +2 -0
  4. data/README.md +5 -1
  5. data/fluentd.gemspec +1 -1
  6. data/lib/fluent/clock.rb +4 -0
  7. data/lib/fluent/compat/output.rb +3 -3
  8. data/lib/fluent/compat/socket_util.rb +1 -1
  9. data/lib/fluent/config/element.rb +3 -3
  10. data/lib/fluent/config/literal_parser.rb +1 -1
  11. data/lib/fluent/config/section.rb +4 -1
  12. data/lib/fluent/error.rb +4 -0
  13. data/lib/fluent/event.rb +28 -24
  14. data/lib/fluent/event_router.rb +2 -1
  15. data/lib/fluent/log.rb +1 -1
  16. data/lib/fluent/msgpack_factory.rb +8 -0
  17. data/lib/fluent/plugin/bare_output.rb +4 -4
  18. data/lib/fluent/plugin/buf_file_single.rb +211 -0
  19. data/lib/fluent/plugin/buffer.rb +62 -63
  20. data/lib/fluent/plugin/buffer/chunk.rb +21 -3
  21. data/lib/fluent/plugin/buffer/file_chunk.rb +37 -12
  22. data/lib/fluent/plugin/buffer/file_single_chunk.rb +314 -0
  23. data/lib/fluent/plugin/buffer/memory_chunk.rb +2 -1
  24. data/lib/fluent/plugin/compressable.rb +10 -6
  25. data/lib/fluent/plugin/filter_grep.rb +2 -2
  26. data/lib/fluent/plugin/formatter_csv.rb +10 -6
  27. data/lib/fluent/plugin/in_syslog.rb +10 -3
  28. data/lib/fluent/plugin/in_tail.rb +7 -2
  29. data/lib/fluent/plugin/in_tcp.rb +34 -7
  30. data/lib/fluent/plugin/multi_output.rb +4 -4
  31. data/lib/fluent/plugin/out_exec_filter.rb +1 -0
  32. data/lib/fluent/plugin/out_file.rb +13 -3
  33. data/lib/fluent/plugin/out_forward.rb +126 -588
  34. data/lib/fluent/plugin/out_forward/ack_handler.rb +161 -0
  35. data/lib/fluent/plugin/out_forward/connection_manager.rb +113 -0
  36. data/lib/fluent/plugin/out_forward/error.rb +28 -0
  37. data/lib/fluent/plugin/out_forward/failure_detector.rb +84 -0
  38. data/lib/fluent/plugin/out_forward/handshake_protocol.rb +121 -0
  39. data/lib/fluent/plugin/out_forward/load_balancer.rb +111 -0
  40. data/lib/fluent/plugin/out_forward/socket_cache.rb +138 -0
  41. data/lib/fluent/plugin/out_http.rb +231 -0
  42. data/lib/fluent/plugin/output.rb +29 -35
  43. data/lib/fluent/plugin/parser.rb +77 -0
  44. data/lib/fluent/plugin/parser_csv.rb +75 -0
  45. data/lib/fluent/plugin_helper/server.rb +1 -1
  46. data/lib/fluent/plugin_helper/thread.rb +1 -0
  47. data/lib/fluent/root_agent.rb +1 -1
  48. data/lib/fluent/time.rb +4 -2
  49. data/lib/fluent/timezone.rb +21 -7
  50. data/lib/fluent/version.rb +1 -1
  51. data/test/command/test_fluentd.rb +1 -1
  52. data/test/command/test_plugin_generator.rb +18 -2
  53. data/test/config/test_configurable.rb +78 -40
  54. data/test/counter/test_store.rb +1 -1
  55. data/test/helper.rb +1 -0
  56. data/test/helpers/process_extenstion.rb +33 -0
  57. data/test/plugin/out_forward/test_ack_handler.rb +101 -0
  58. data/test/plugin/out_forward/test_connection_manager.rb +145 -0
  59. data/test/plugin/out_forward/test_handshake_protocol.rb +103 -0
  60. data/test/plugin/out_forward/test_load_balancer.rb +60 -0
  61. data/test/plugin/out_forward/test_socket_cache.rb +139 -0
  62. data/test/plugin/test_buf_file.rb +118 -2
  63. data/test/plugin/test_buf_file_single.rb +734 -0
  64. data/test/plugin/test_buffer.rb +4 -48
  65. data/test/plugin/test_buffer_file_chunk.rb +19 -1
  66. data/test/plugin/test_buffer_file_single_chunk.rb +620 -0
  67. data/test/plugin/test_formatter_csv.rb +16 -0
  68. data/test/plugin/test_in_syslog.rb +56 -6
  69. data/test/plugin/test_in_tail.rb +1 -1
  70. data/test/plugin/test_in_tcp.rb +25 -0
  71. data/test/plugin/test_out_forward.rb +75 -201
  72. data/test/plugin/test_out_http.rb +352 -0
  73. data/test/plugin/test_output_as_buffered.rb +27 -24
  74. data/test/plugin/test_parser.rb +40 -0
  75. data/test/plugin/test_parser_csv.rb +83 -0
  76. data/test/plugin_helper/test_record_accessor.rb +1 -1
  77. data/test/test_time_formatter.rb +140 -121
  78. metadata +35 -6
@@ -0,0 +1,145 @@
1
+ require_relative '../../helper'
2
+ require 'fluent/test/driver/output'
3
+ require 'flexmock/test_unit'
4
+
5
+ require 'fluent/plugin/out_forward'
6
+ require 'fluent/plugin/out_forward/connection_manager'
7
+ require 'fluent/plugin/out_forward/socket_cache'
8
+
9
+ class ConnectionManager < Test::Unit::TestCase
10
+ sub_test_case '#connect' do
11
+ sub_test_case 'when socket_cache is nil' do
12
+ test 'creates socket and does not close when block is not given' do
13
+ cm = Fluent::Plugin::ForwardOutput::ConnectionManager.new(
14
+ log: $log,
15
+ secure: false,
16
+ connection_factory: -> (_, _, _) { sock = 'sock'; mock(sock).close.never; sock },
17
+ socket_cache: nil,
18
+ )
19
+
20
+ mock.proxy(cm).connect_keepalive(anything).never
21
+ sock, ri = cm.connect(host: 'host', port: 1234, hostname: 'hostname', ack: nil)
22
+ assert_equal(sock, 'sock')
23
+ assert_equal(ri.state, :established)
24
+ end
25
+
26
+ test 'creates socket and calls close when block is given' do
27
+ cm = Fluent::Plugin::ForwardOutput::ConnectionManager.new(
28
+ log: $log,
29
+ secure: false,
30
+ connection_factory: -> (_, _, _) {
31
+ sock = 'sock'
32
+ mock(sock).close.once
33
+ mock(sock).close_write.once
34
+ sock
35
+ },
36
+ socket_cache: nil,
37
+ )
38
+
39
+ mock.proxy(cm).connect_keepalive(anything).never
40
+ cm.connect(host: 'host', port: 1234, hostname: 'hostname', ack: nil) do |sock, ri|
41
+ assert_equal(sock, 'sock')
42
+ assert_equal(ri.state, :established)
43
+ end
44
+ end
45
+
46
+ test 'when secure is true, state is helo' do
47
+ cm = Fluent::Plugin::ForwardOutput::ConnectionManager.new(
48
+ log: $log,
49
+ secure: true,
50
+ connection_factory: -> (_, _, _) { sock = 'sock'; mock(sock).close.never; sock },
51
+ socket_cache: nil,
52
+ )
53
+
54
+ mock.proxy(cm).connect_keepalive(anything).never
55
+ sock, ri = cm.connect(host: 'host', port: 1234, hostname: 'hostname', ack: nil)
56
+ assert_equal(sock, 'sock')
57
+ assert_equal(ri.state, :helo)
58
+ end
59
+
60
+ test 'when passed ack' do
61
+ sock = 'sock'
62
+ cm = Fluent::Plugin::ForwardOutput::ConnectionManager.new(
63
+ log: $log,
64
+ secure: false,
65
+ connection_factory: -> (_, _, _) {
66
+ mock(sock).close.never
67
+ mock(sock).close_write.never
68
+ sock
69
+ },
70
+ socket_cache: nil,
71
+ )
72
+
73
+ mock.proxy(cm).connect_keepalive(anything).never
74
+ ack = mock('ack').enqueue(sock).once.subject
75
+ cm.connect(host: 'host', port: 1234, hostname: 'hostname', ack: ack) do |sock, ri|
76
+ assert_equal(sock, 'sock')
77
+ assert_equal(ri.state, :established)
78
+ end
79
+ end
80
+ end
81
+
82
+ sub_test_case 'when socket_cache exists' do
83
+ test 'calls connect_keepalive' do
84
+ cache = Fluent::Plugin::ForwardOutput::SocketCache.new(10, $log)
85
+ mock(cache).checkin('sock').never
86
+
87
+ cm = Fluent::Plugin::ForwardOutput::ConnectionManager.new(
88
+ log: $log,
89
+ secure: false,
90
+ connection_factory: -> (_, _, _) { sock = 'sock'; mock(sock).close.never; sock },
91
+ socket_cache: cache,
92
+ )
93
+
94
+ mock.proxy(cm).connect_keepalive(host: 'host', port: 1234, hostname: 'hostname', ack: nil).once
95
+
96
+ sock, ri = cm.connect(host: 'host', port: 1234, hostname: 'hostname', ack: nil)
97
+ assert_equal(sock, 'sock')
98
+ assert_equal(ri.state, :established)
99
+ end
100
+
101
+ test 'calls connect_keepalive and closes socket with block' do
102
+ cache = Fluent::Plugin::ForwardOutput::SocketCache.new(10, $log)
103
+ mock(cache).checkin('sock').once
104
+
105
+ cm = Fluent::Plugin::ForwardOutput::ConnectionManager.new(
106
+ log: $log,
107
+ secure: false,
108
+ connection_factory: -> (_, _, _) { sock = 'sock'; mock(sock); sock },
109
+ socket_cache: cache,
110
+ )
111
+
112
+ mock.proxy(cm).connect_keepalive(host: 'host', port: 1234, hostname: 'hostname', ack: nil).once
113
+
114
+ cm.connect(host: 'host', port: 1234, hostname: 'hostname', ack: nil) do |sock, ri|
115
+ assert_equal(sock, 'sock')
116
+ assert_equal(ri.state, :established)
117
+ end
118
+ end
119
+
120
+ test 'does not call dec_ref when ack is passed' do
121
+ cache = Fluent::Plugin::ForwardOutput::SocketCache.new(10, $log)
122
+ mock(cache).checkin('sock').never
123
+ sock = 'sock'
124
+ ack = stub('ack').enqueue(sock).once.subject
125
+
126
+ cm = Fluent::Plugin::ForwardOutput::ConnectionManager.new(
127
+ log: $log,
128
+ secure: false,
129
+ connection_factory: -> (_, _, _) {
130
+ mock(sock).close.never
131
+ mock(sock).close_write.never
132
+ sock
133
+ },
134
+ socket_cache: cache,
135
+ )
136
+
137
+ mock.proxy(cm).connect_keepalive(host: 'host', port: 1234, hostname: 'hostname', ack: ack).once
138
+ cm.connect(host: 'host', port: 1234, hostname: 'hostname', ack: ack) do |sock, ri|
139
+ assert_equal(sock, 'sock')
140
+ assert_equal(ri.state, :established)
141
+ end
142
+ end
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,103 @@
1
+ require_relative '../../helper'
2
+ require 'flexmock/test_unit'
3
+
4
+ require 'fluent/plugin/out_forward'
5
+ require 'fluent/plugin/out_forward/handshake_protocol'
6
+ require 'fluent/plugin/out_forward/connection_manager'
7
+
8
+ class HandshakeProtocolTest < Test::Unit::TestCase
9
+ sub_test_case '#invok when helo state' do
10
+ test 'sends PING message and change state to pingpong' do
11
+ hostname = 'hostname'
12
+ handshake = Fluent::Plugin::ForwardOutput::HandshakeProtocol.new(log: $log, hostname: hostname, shared_key: 'shared_key', password: nil, username: nil)
13
+ ri = Fluent::Plugin::ForwardOutput::ConnectionManager::RequestInfo.new(:helo)
14
+
15
+ sock = StringIO.new('')
16
+ handshake.invoke(sock, ri, ['HELO', {}])
17
+
18
+ assert_equal(ri.state, :pingpong)
19
+ Fluent::Engine.msgpack_factory.unpacker.feed_each(sock.string) do |ping|
20
+ assert_equal(ping.size, 6)
21
+ assert_equal(ping[0], 'PING')
22
+ assert_equal(ping[1], hostname)
23
+ assert(ping[2].is_a?(String)) # content is hashed value
24
+ assert(ping[3].is_a?(String)) # content is hashed value
25
+ assert_equal(ping[4], '')
26
+ assert_equal(ping[5], '')
27
+ end
28
+ end
29
+
30
+ test 'returns PING message with username if auth exists' do
31
+ hostname = 'hostname'
32
+ username = 'username'
33
+ pass = 'pass'
34
+ handshake = Fluent::Plugin::ForwardOutput::HandshakeProtocol.new(log: $log, hostname: hostname, shared_key: 'shared_key', password: pass, username: username)
35
+ ri = Fluent::Plugin::ForwardOutput::ConnectionManager::RequestInfo.new(:helo)
36
+
37
+ sock = StringIO.new('')
38
+ handshake.invoke(sock, ri, ['HELO', { 'auth' => 'auth' }])
39
+
40
+ assert_equal(ri.state, :pingpong)
41
+ Fluent::Engine.msgpack_factory.unpacker.feed_each(sock.string) do |ping|
42
+ assert_equal(ping.size, 6)
43
+ assert_equal(ping[0], 'PING')
44
+ assert_equal(ping[1], hostname)
45
+ assert(ping[2].is_a?(String)) # content is hashed value
46
+ assert(ping[3].is_a?(String)) # content is hashed value
47
+ assert_equal(ping[4], username)
48
+ assert_not_equal(ping[5], pass) # should be hashed
49
+ end
50
+ end
51
+
52
+ data(
53
+ lack_of_elem: ['HELO'],
54
+ wrong_message: ['HELLO!', {}],
55
+ )
56
+ test 'raises an error when message is' do |msg|
57
+ handshake = Fluent::Plugin::ForwardOutput::HandshakeProtocol.new(log: $log, hostname: 'hostname', shared_key: 'shared_key', password: nil, username: nil)
58
+ ri = Fluent::Plugin::ForwardOutput::ConnectionManager::RequestInfo.new(:helo)
59
+
60
+ sock = StringIO.new('')
61
+ assert_raise(Fluent::Plugin::ForwardOutput::HeloError) do
62
+ handshake.invoke(sock, ri, msg)
63
+ end
64
+
65
+ assert_equal(ri.state, :helo)
66
+ end
67
+ end
68
+
69
+ sub_test_case '#invok when pingpong state' do
70
+ test 'sends PING message and change state to pingpong' do
71
+ handshake = Fluent::Plugin::ForwardOutput::HandshakeProtocol.new(log: $log, hostname: 'hostname', shared_key: 'shared_key', password: nil, username: nil)
72
+ handshake.instance_variable_set(:@shared_key_salt, 'ce1897b0d3dbd76b90d7fb96010dcac3') # to fix salt
73
+
74
+ ri = Fluent::Plugin::ForwardOutput::ConnectionManager::RequestInfo.new(:pingpong, '', '')
75
+ handshake.invoke(
76
+ '',
77
+ ri,
78
+ # 40a3.... = Digest::SHA512.new.update('ce1897b0d3dbd76b90d7fb96010dcac3').update('client_hostname').update('').update('shared_key').hexdigest
79
+ ['PONG', true, '', 'client_hostname', '40a3c5943cc6256e0c5dcf176e97db3826b0909698c330dc8e53d15af63efb47e030d113130255dd6e7ced5176d2999cc2e02a44852d45152503af317b73b33f']
80
+ )
81
+ assert_equal(ri.state, :established)
82
+ end
83
+
84
+ data(
85
+ lack_of_elem: ['PONG', true, '', 'client_hostname'],
86
+ wrong_message: ['WRONG_PONG', true, '', 'client_hostname', '40a3c5943cc6256e0c5dcf176e97db3826b0909698c330dc8e53d15af63efb47e030d113130255dd6e7ced5176d2999cc2e02a44852d45152503af317b73b33f'],
87
+ error_by_server: ['PONG', false, 'error', 'client_hostname', '40a3c5943cc6256e0c5dcf176e97db3826b0909698c330dc8e53d15af63efb47e030d113130255dd6e7ced5176d2999cc2e02a44852d45152503af317b73b33f'],
88
+ same_hostname_as_server: ['PONG', true, '', 'hostname', '40a3c5943cc6256e0c5dcf176e97db3826b0909698c330dc8e53d15af63efb47e030d113130255dd6e7ced5176d2999cc2e02a44852d45152503af317b73b33f'],
89
+ wrong_key: ['PONG', true, '', 'hostname', 'wrong_key'],
90
+ )
91
+ test 'raises an error when message is' do |msg|
92
+ handshake = Fluent::Plugin::ForwardOutput::HandshakeProtocol.new(log: $log, hostname: 'hostname', shared_key: 'shared_key', password: nil, username: nil)
93
+ handshake.instance_variable_set(:@shared_key_salt, 'ce1897b0d3dbd76b90d7fb96010dcac3') # to fix salt
94
+
95
+ ri = Fluent::Plugin::ForwardOutput::ConnectionManager::RequestInfo.new(:pingpong, '', '')
96
+ assert_raise(Fluent::Plugin::ForwardOutput::PingpongError) do
97
+ handshake.invoke('', ri, msg)
98
+ end
99
+
100
+ assert_equal(ri.state, :pingpong)
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,60 @@
1
+ require_relative '../../helper'
2
+ require 'flexmock/test_unit'
3
+
4
+ require 'fluent/plugin/out_forward/load_balancer'
5
+
6
+ class LoadBalancerTest < Test::Unit::TestCase
7
+ sub_test_case 'select_healthy_node' do
8
+ test 'select healty node' do
9
+ lb = Fluent::Plugin::ForwardOutput::LoadBalancer.new($log)
10
+ n1 = flexmock('node', :'standby?' => false, :'available?' => false, weight: 1)
11
+ n2 = flexmock('node', :'standby?' => false, :'available?' => true, weight: 1)
12
+
13
+ lb.rebuild_weight_array([n1, n2])
14
+ lb.select_healthy_node do |node|
15
+ assert_equal(node, n2)
16
+ end
17
+
18
+ lb.select_healthy_node do |node|
19
+ assert_equal(node, n2)
20
+ end
21
+ end
22
+
23
+ test 'call like round robin' do
24
+ lb = Fluent::Plugin::ForwardOutput::LoadBalancer.new($log)
25
+ n1 = flexmock('node', :'standby?' => false, :'available?' => true, weight: 1)
26
+ n2 = flexmock('node', :'standby?' => false, :'available?' => true, weight: 1)
27
+
28
+ lb.rebuild_weight_array([n1, n2])
29
+
30
+ lb.select_healthy_node do |node|
31
+ # to handle random choice
32
+ if node == n1
33
+ lb.select_healthy_node do |node|
34
+ assert_equal(node, n2)
35
+ end
36
+
37
+ lb.select_healthy_node do |node|
38
+ assert_equal(node, n1)
39
+ end
40
+ else
41
+ lb.select_healthy_node do |node|
42
+ assert_equal(node, n1)
43
+ end
44
+
45
+ lb.select_healthy_node do |node|
46
+ assert_equal(node, n2)
47
+ end
48
+ end
49
+ end
50
+ end
51
+
52
+ test 'raise an error if all node are unavialble' do
53
+ lb = Fluent::Plugin::ForwardOutput::LoadBalancer.new($log)
54
+ lb.rebuild_weight_array([flexmock('node', :'standby?' => false, :'available?' => false, weight: 1)])
55
+ assert_raise(Fluent::Plugin::ForwardOutput::NoNodesAvailable) do
56
+ lb.select_healthy_node
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,139 @@
1
+ require_relative '../../helper'
2
+
3
+ require 'fluent/plugin/out_forward/socket_cache'
4
+ require 'timecop'
5
+
6
+ class SocketCacheTest < Test::Unit::TestCase
7
+ sub_test_case 'checkout_or' do
8
+ test 'when gived key does not exist' do
9
+ c = Fluent::Plugin::ForwardOutput::SocketCache.new(10, $log)
10
+ sock = mock!.open { 'socket' }.subject
11
+ assert_equal('socket', c.checkout_or('key') { sock.open })
12
+ end
13
+
14
+ test 'when given key exists' do
15
+ c = Fluent::Plugin::ForwardOutput::SocketCache.new(10, $log)
16
+ socket = 'socket'
17
+ assert_equal(socket, c.checkout_or('key') { socket })
18
+ c.checkin(socket)
19
+
20
+ sock = dont_allow(mock!).open
21
+ assert_equal(socket, c.checkout_or('key') { sock.open })
22
+ end
23
+
24
+ test 'when given key exists but used by other' do
25
+ c = Fluent::Plugin::ForwardOutput::SocketCache.new(10, $log)
26
+ assert_equal(@sock, c.checkout_or('key') { @sock })
27
+
28
+ new_sock = 'new sock'
29
+ sock = mock!.open { new_sock }.subject
30
+ assert_equal(new_sock, c.checkout_or('key') { sock.open })
31
+ end
32
+
33
+ test "when given key's value was expired" do
34
+ c = Fluent::Plugin::ForwardOutput::SocketCache.new(0, $log)
35
+ assert_equal(@sock, c.checkout_or('key') { @sock })
36
+
37
+ new_sock = 'new sock'
38
+ sock = mock!.open { new_sock }.subject
39
+ assert_equal(new_sock, c.checkout_or('key') { sock.open })
40
+ end
41
+ end
42
+
43
+ sub_test_case 'checkin' do
44
+ test 'when value exists' do
45
+ c = Fluent::Plugin::ForwardOutput::SocketCache.new(10, $log)
46
+ socket = 'socket'
47
+ c.checkout_or('key') { socket }
48
+ c.checkin(socket)
49
+
50
+ assert_equal(socket, c.instance_variable_get(:@available_sockets)['key'].first.sock)
51
+ assert_equal(1, c.instance_variable_get(:@available_sockets)['key'].size)
52
+ assert_equal(0, c.instance_variable_get(:@inflight_sockets).size)
53
+ end
54
+
55
+ test 'when value does not exist' do
56
+ c = Fluent::Plugin::ForwardOutput::SocketCache.new(10, $log)
57
+ c.checkout_or('key') { 'sock' }
58
+ c.checkin('other sock')
59
+
60
+ assert_equal(0, c.instance_variable_get(:@available_sockets)['key'].size)
61
+ assert_equal(1, c.instance_variable_get(:@inflight_sockets).size)
62
+ end
63
+ end
64
+
65
+ test 'revoke' do
66
+ c = Fluent::Plugin::ForwardOutput::SocketCache.new(10, $log)
67
+ socket = 'socket'
68
+ c.checkout_or('key') { socket }
69
+ c.revoke(socket)
70
+
71
+ assert_equal(1, c.instance_variable_get(:@inactive_sockets).size)
72
+ assert_equal(0, c.instance_variable_get(:@inflight_sockets).size)
73
+ assert_equal(0, c.instance_variable_get(:@available_sockets)['key'].size)
74
+
75
+ sock = mock!.open { 1 }.subject
76
+ assert_equal(1, c.checkout_or('key') { sock.open })
77
+ end
78
+
79
+ sub_test_case 'clear' do
80
+ test 'when value is in available_sockets' do
81
+ c = Fluent::Plugin::ForwardOutput::SocketCache.new(10, $log)
82
+ m = mock!.close { 'closed' }.subject
83
+ m2 = mock!.close { 'closed' }.subject
84
+ m3 = mock!.close { 'closed' }.subject
85
+ c.checkout_or('key') { m }
86
+ c.revoke(m)
87
+ c.checkout_or('key') { m2 }
88
+ c.checkin(m2)
89
+ c.checkout_or('key2') { m3 }
90
+
91
+ assert_equal(1, c.instance_variable_get(:@inflight_sockets).size)
92
+ assert_equal(1, c.instance_variable_get(:@available_sockets)['key'].size)
93
+ assert_equal(1, c.instance_variable_get(:@inactive_sockets).size)
94
+
95
+ c.clear
96
+ assert_equal(0, c.instance_variable_get(:@inflight_sockets).size)
97
+ assert_equal(0, c.instance_variable_get(:@available_sockets)['key'].size)
98
+ assert_equal(0, c.instance_variable_get(:@inactive_sockets).size)
99
+ end
100
+ end
101
+
102
+ sub_test_case 'purge_obsolete_socks' do
103
+ test 'delete key in inactive_socks' do
104
+ c = Fluent::Plugin::ForwardOutput::SocketCache.new(10, $log)
105
+ sock = mock!.close { 'closed' }.subject
106
+ c.checkout_or('key') { sock }
107
+ c.revoke(sock)
108
+ assert_false(c.instance_variable_get(:@inactive_sockets).empty?)
109
+
110
+ c.purge_obsolete_socks
111
+ assert_true(c.instance_variable_get(:@inactive_sockets).empty?)
112
+ end
113
+
114
+ test 'move key from available_sockets to inactive_sockets' do
115
+ Timecop.freeze(Time.parse('2016-04-13 14:00:00 +0900'))
116
+
117
+ c = Fluent::Plugin::ForwardOutput::SocketCache.new(10, $log)
118
+ sock = mock!.close { 'closed' }.subject
119
+ sock2 = dont_allow(mock!).close
120
+ stub(sock).inspect
121
+ stub(sock2).inspect
122
+
123
+ c.checkout_or('key') { sock }
124
+ c.checkin(sock)
125
+
126
+ # wait timeout
127
+ Timecop.freeze(Time.parse('2016-04-13 14:20:00 +0900'))
128
+ c.checkout_or('key') { sock2 }
129
+
130
+ assert_equal(1, c.instance_variable_get(:@inflight_sockets).size)
131
+ assert_equal(sock2, c.instance_variable_get(:@inflight_sockets).values.first.sock)
132
+
133
+ c.purge_obsolete_socks
134
+
135
+ assert_equal(1, c.instance_variable_get(:@inflight_sockets).size)
136
+ assert_equal(sock2, c.instance_variable_get(:@inflight_sockets).values.first.sock)
137
+ end
138
+ end
139
+ end