fluentd 1.15.3-x64-mingw-ucrt → 1.16.0-x64-mingw-ucrt
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.
- checksums.yaml +4 -4
- data/.github/workflows/linux-test.yaml +2 -2
- data/.github/workflows/macos-test.yaml +2 -2
- data/.github/workflows/windows-test.yaml +2 -2
- data/CHANGELOG.md +77 -0
- data/MAINTAINERS.md +2 -0
- data/README.md +0 -1
- data/fluentd.gemspec +2 -2
- data/lib/fluent/command/fluentd.rb +55 -53
- data/lib/fluent/daemon.rb +2 -4
- data/lib/fluent/log/console_adapter.rb +66 -0
- data/lib/fluent/log.rb +35 -5
- data/lib/fluent/plugin/base.rb +5 -7
- data/lib/fluent/plugin/buf_file.rb +32 -3
- data/lib/fluent/plugin/buf_file_single.rb +32 -3
- data/lib/fluent/plugin/buffer/file_chunk.rb +1 -1
- data/lib/fluent/plugin/buffer.rb +21 -0
- data/lib/fluent/plugin/in_tcp.rb +4 -2
- data/lib/fluent/plugin/out_forward/ack_handler.rb +19 -4
- data/lib/fluent/plugin/out_forward.rb +2 -2
- data/lib/fluent/plugin/out_secondary_file.rb +39 -22
- data/lib/fluent/plugin/output.rb +49 -12
- data/lib/fluent/plugin_helper/http_server/server.rb +2 -1
- data/lib/fluent/supervisor.rb +157 -251
- data/lib/fluent/test/driver/base.rb +11 -5
- data/lib/fluent/test/driver/filter.rb +4 -0
- data/lib/fluent/test/startup_shutdown.rb +6 -8
- data/lib/fluent/version.rb +1 -1
- data/test/command/test_ctl.rb +1 -1
- data/test/command/test_fluentd.rb +137 -6
- data/test/command/test_plugin_config_formatter.rb +0 -1
- data/test/compat/test_parser.rb +5 -5
- data/test/config/test_system_config.rb +0 -8
- data/test/log/test_console_adapter.rb +110 -0
- data/test/plugin/out_forward/test_ack_handler.rb +39 -0
- data/test/plugin/test_base.rb +98 -0
- data/test/plugin/test_buf_file.rb +62 -23
- data/test/plugin/test_buf_file_single.rb +65 -0
- data/test/plugin/test_in_http.rb +2 -3
- data/test/plugin/test_in_monitor_agent.rb +2 -3
- data/test/plugin/test_in_tcp.rb +15 -0
- data/test/plugin/test_out_forward.rb +14 -18
- data/test/plugin/test_out_http.rb +1 -0
- data/test/plugin/test_output.rb +269 -0
- data/test/plugin/test_parser_regexp.rb +1 -6
- data/test/plugin_helper/test_http_server_helper.rb +1 -1
- data/test/plugin_helper/test_server.rb +10 -5
- data/test/test_config.rb +0 -21
- data/test/test_formatter.rb +23 -20
- data/test/test_log.rb +71 -36
- data/test/test_supervisor.rb +277 -282
- metadata +12 -19
- data/.drone.yml +0 -35
- data/.gitlab-ci.yml +0 -103
- data/test/test_logger_initializer.rb +0 -46
@@ -21,9 +21,8 @@ module Fluent
|
|
21
21
|
module Test
|
22
22
|
module StartupShutdown
|
23
23
|
def startup
|
24
|
-
|
25
|
-
|
26
|
-
ENV['SERVERENGINE_SOCKETMANAGER_PATH'] = socket_manager_path.to_s
|
24
|
+
@server = ServerEngine::SocketManager::Server.open
|
25
|
+
ENV['SERVERENGINE_SOCKETMANAGER_PATH'] = @server.path.to_s
|
27
26
|
end
|
28
27
|
|
29
28
|
def shutdown
|
@@ -31,15 +30,14 @@ module Fluent
|
|
31
30
|
end
|
32
31
|
|
33
32
|
def self.setup
|
34
|
-
@
|
35
|
-
|
36
|
-
ENV['SERVERENGINE_SOCKETMANAGER_PATH'] = @socket_manager_path.to_s
|
33
|
+
@server = ServerEngine::SocketManager::Server.open
|
34
|
+
ENV['SERVERENGINE_SOCKETMANAGER_PATH'] = @server.path.to_s
|
37
35
|
end
|
38
36
|
|
39
37
|
def self.teardown
|
40
38
|
@server.close
|
41
|
-
# on Windows,
|
42
|
-
FileUtils.rm_f @
|
39
|
+
# on Windows, the path is a TCP port number
|
40
|
+
FileUtils.rm_f @server.path unless Fluent.windows?
|
43
41
|
end
|
44
42
|
end
|
45
43
|
end
|
data/lib/fluent/version.rb
CHANGED
data/test/command/test_ctl.rb
CHANGED
@@ -71,6 +71,20 @@ class TestFluentdCommand < ::Test::Unit::TestCase
|
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
|
+
def process_kill(pid)
|
75
|
+
if Fluent.windows?
|
76
|
+
Process.kill(:KILL, pid) rescue nil
|
77
|
+
return
|
78
|
+
end
|
79
|
+
|
80
|
+
begin
|
81
|
+
Process.kill(:TERM, pid) rescue nil
|
82
|
+
Timeout.timeout(10){ sleep 0.1 while process_exist?(pid) }
|
83
|
+
rescue Timeout::Error
|
84
|
+
Process.kill(:KILL, pid) rescue nil
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
74
88
|
def execute_command(cmdline, chdir=@tmp_dir, env = {})
|
75
89
|
null_stream = Fluent::FileWrapper.open(File::NULL, 'w')
|
76
90
|
gemfile_path = File.expand_path(File.dirname(__FILE__) + "../../../Gemfile")
|
@@ -85,12 +99,12 @@ class TestFluentdCommand < ::Test::Unit::TestCase
|
|
85
99
|
yield pid, io
|
86
100
|
# p(here: "execute command", pid: pid, worker_pids: @worker_pids)
|
87
101
|
ensure
|
88
|
-
|
102
|
+
process_kill(pid)
|
89
103
|
if @supervisor_pid
|
90
|
-
|
104
|
+
process_kill(@supervisor_pid)
|
91
105
|
end
|
92
106
|
@worker_pids.each do |cpid|
|
93
|
-
|
107
|
+
process_kill(cpid)
|
94
108
|
end
|
95
109
|
# p(here: "execute command", pid: pid, exist: process_exist?(pid), worker_pids: @worker_pids, exists: @worker_pids.map{|i| process_exist?(i) })
|
96
110
|
Timeout.timeout(10){ sleep 0.1 while process_exist?(pid) }
|
@@ -112,7 +126,9 @@ class TestFluentdCommand < ::Test::Unit::TestCase
|
|
112
126
|
end
|
113
127
|
end
|
114
128
|
|
115
|
-
|
129
|
+
# ATTENTION: This stops taking logs when all `pattern_list` match or timeout,
|
130
|
+
# so `patterns_not_match` can test only logs up to that point.
|
131
|
+
def assert_log_matches(cmdline, *pattern_list, patterns_not_match: [], timeout: 20, env: {})
|
116
132
|
matched = false
|
117
133
|
matched_wrongly = false
|
118
134
|
assert_error_msg = ""
|
@@ -121,7 +137,7 @@ class TestFluentdCommand < ::Test::Unit::TestCase
|
|
121
137
|
execute_command(cmdline, @tmp_dir, env) do |pid, stdout|
|
122
138
|
begin
|
123
139
|
waiting(timeout) do
|
124
|
-
while process_exist?(pid)
|
140
|
+
while process_exist?(pid)
|
125
141
|
readables, _, _ = IO.select([stdout], nil, nil, 1)
|
126
142
|
next unless readables
|
127
143
|
break if readables.first.eof?
|
@@ -133,6 +149,18 @@ class TestFluentdCommand < ::Test::Unit::TestCase
|
|
133
149
|
if pattern_list.all?{|ptn| lines.any?{|line| ptn.is_a?(Regexp) ? ptn.match(line) : line.include?(ptn) } }
|
134
150
|
matched = true
|
135
151
|
end
|
152
|
+
|
153
|
+
if Fluent.windows?
|
154
|
+
# https://github.com/fluent/fluentd/issues/4095
|
155
|
+
# On Windows, the initial process is different from the supervisor process,
|
156
|
+
# so we need to wait until `SUPERVISOR_PID_PATTERN` appears in the logs to get the pid.
|
157
|
+
# (Worker processes will be killed by the supervisor process, so we don't need it-)
|
158
|
+
break if matched && SUPERVISOR_PID_PATTERN =~ stdio_buf
|
159
|
+
else
|
160
|
+
# On Non-Windows, the initial process is the supervisor process,
|
161
|
+
# so we don't need to wait `SUPERVISOR_PID_PATTERN`.
|
162
|
+
break if matched
|
163
|
+
end
|
136
164
|
end
|
137
165
|
end
|
138
166
|
ensure
|
@@ -146,6 +174,10 @@ class TestFluentdCommand < ::Test::Unit::TestCase
|
|
146
174
|
end
|
147
175
|
rescue Timeout::Error
|
148
176
|
assert_error_msg = "execution timeout"
|
177
|
+
# https://github.com/fluent/fluentd/issues/4095
|
178
|
+
# On Windows, timeout without `@supervisor_pid` means that the test is invalid,
|
179
|
+
# since the supervisor process will survive without being killed correctly.
|
180
|
+
flunk("Invalid test: The pid of supervisor could not be taken, which is necessary on Windows.") if Fluent.windows? && @supervisor_pid.nil?
|
149
181
|
rescue => e
|
150
182
|
assert_error_msg = "unexpected error in launching fluentd: #{e.inspect}"
|
151
183
|
else
|
@@ -177,7 +209,7 @@ class TestFluentdCommand < ::Test::Unit::TestCase
|
|
177
209
|
assert matched && !matched_wrongly, assert_error_msg
|
178
210
|
end
|
179
211
|
|
180
|
-
def assert_fluentd_fails_to_start(cmdline, *pattern_list, timeout:
|
212
|
+
def assert_fluentd_fails_to_start(cmdline, *pattern_list, timeout: 20)
|
181
213
|
# empty_list.all?{ ... } is always true
|
182
214
|
matched = false
|
183
215
|
running = false
|
@@ -213,6 +245,10 @@ class TestFluentdCommand < ::Test::Unit::TestCase
|
|
213
245
|
end
|
214
246
|
rescue Timeout::Error
|
215
247
|
assert_error_msg = "execution timeout with command out:\n" + stdio_buf
|
248
|
+
# https://github.com/fluent/fluentd/issues/4095
|
249
|
+
# On Windows, timeout without `@supervisor_pid` means that the test is invalid,
|
250
|
+
# since the supervisor process will survive without being killed correctly.
|
251
|
+
flunk("Invalid test: The pid of supervisor could not be taken, which is necessary on Windows.") if Fluent.windows? && @supervisor_pid.nil?
|
216
252
|
rescue => e
|
217
253
|
assert_error_msg = "unexpected error in launching fluentd: #{e.inspect}\n" + stdio_buf
|
218
254
|
assert false, assert_error_msg
|
@@ -1151,4 +1187,99 @@ CONF
|
|
1151
1187
|
"shared socket for multiple workers is disabled",)
|
1152
1188
|
end
|
1153
1189
|
end
|
1190
|
+
|
1191
|
+
# TODO: `patterns_not_match` can test only logs up to `pattern_list`,
|
1192
|
+
# so we need to fix some meaningless `patterns_not_match` conditions.
|
1193
|
+
sub_test_case 'log_level by command line option' do
|
1194
|
+
test 'info' do
|
1195
|
+
conf = ""
|
1196
|
+
conf_path = create_conf_file('empty.conf', conf)
|
1197
|
+
assert File.exist?(conf_path)
|
1198
|
+
assert_log_matches(create_cmdline(conf_path),
|
1199
|
+
"[info]",
|
1200
|
+
patterns_not_match: ["[debug]"])
|
1201
|
+
end
|
1202
|
+
|
1203
|
+
test 'debug' do
|
1204
|
+
conf = ""
|
1205
|
+
conf_path = create_conf_file('empty.conf', conf)
|
1206
|
+
assert File.exist?(conf_path)
|
1207
|
+
assert_log_matches(create_cmdline(conf_path, "-v"),
|
1208
|
+
"[debug]",
|
1209
|
+
patterns_not_match: ["[trace]"])
|
1210
|
+
end
|
1211
|
+
|
1212
|
+
data("Trace" => "-vv")
|
1213
|
+
data("Invalid low level should be treated as Trace level": "-vvv")
|
1214
|
+
test 'trace' do |option|
|
1215
|
+
conf = <<CONF
|
1216
|
+
<source>
|
1217
|
+
@type sample
|
1218
|
+
tag test
|
1219
|
+
</source>
|
1220
|
+
CONF
|
1221
|
+
conf_path = create_conf_file('sample.conf', conf)
|
1222
|
+
assert File.exist?(conf_path)
|
1223
|
+
assert_log_matches(create_cmdline(conf_path, option),
|
1224
|
+
"[trace]",)
|
1225
|
+
end
|
1226
|
+
|
1227
|
+
test 'warn' do
|
1228
|
+
omit "Can't run on Windows since there is no way to take pid of the supervisor." if Fluent.windows?
|
1229
|
+
conf = <<CONF
|
1230
|
+
<source>
|
1231
|
+
@type sample
|
1232
|
+
tag test
|
1233
|
+
</source>
|
1234
|
+
CONF
|
1235
|
+
conf_path = create_conf_file('sample.conf', conf)
|
1236
|
+
assert File.exist?(conf_path)
|
1237
|
+
assert_log_matches(create_cmdline(conf_path, "-q"),
|
1238
|
+
"[warn]",
|
1239
|
+
patterns_not_match: ["[info]"])
|
1240
|
+
end
|
1241
|
+
|
1242
|
+
data("Error" => "-qq")
|
1243
|
+
data("Fatal should be treated as Error level" => "-qqq")
|
1244
|
+
data("Invalid high level should be treated as Error level": "-qqqq")
|
1245
|
+
test 'error' do |option|
|
1246
|
+
# This test can run on Windows correctly,
|
1247
|
+
# since the process will stop automatically with an error.
|
1248
|
+
conf = <<CONF
|
1249
|
+
<source>
|
1250
|
+
@type plugin_not_found
|
1251
|
+
tag test
|
1252
|
+
</source>
|
1253
|
+
CONF
|
1254
|
+
conf_path = create_conf_file('plugin_not_found.conf', conf)
|
1255
|
+
assert File.exist?(conf_path)
|
1256
|
+
assert_log_matches(create_cmdline(conf_path, option),
|
1257
|
+
"[error]",
|
1258
|
+
patterns_not_match: ["[warn]"])
|
1259
|
+
end
|
1260
|
+
|
1261
|
+
test 'system config one should not be overwritten when cmd line one is not specified' do
|
1262
|
+
conf = <<CONF
|
1263
|
+
<system>
|
1264
|
+
log_level debug
|
1265
|
+
</system>
|
1266
|
+
CONF
|
1267
|
+
conf_path = create_conf_file('debug.conf', conf)
|
1268
|
+
assert File.exist?(conf_path)
|
1269
|
+
assert_log_matches(create_cmdline(conf_path),
|
1270
|
+
"[debug]")
|
1271
|
+
end
|
1272
|
+
end
|
1273
|
+
|
1274
|
+
sub_test_case "inline_config" do
|
1275
|
+
test "can change log_level by --inline-config" do
|
1276
|
+
# Since we can't define multiple `<system>` directives, this use-case is not recommended.
|
1277
|
+
# This is just for this test.
|
1278
|
+
inline_conf = '<system>\nlog_level debug\n</system>'
|
1279
|
+
conf_path = create_conf_file('test.conf', "")
|
1280
|
+
assert File.exist?(conf_path)
|
1281
|
+
assert_log_matches(create_cmdline(conf_path, "--inline-config", inline_conf),
|
1282
|
+
"[debug]")
|
1283
|
+
end
|
1284
|
+
end
|
1154
1285
|
end
|
@@ -188,7 +188,6 @@ slow_flush_log_threshold: float: (20.0)
|
|
188
188
|
retry_exponential_backoff_base: float: (2)
|
189
189
|
retry_max_interval: time: (nil)
|
190
190
|
retry_randomize: bool: (true)
|
191
|
-
disable_chunk_backup: bool: (false)
|
192
191
|
<secondary>: optional, single
|
193
192
|
@type: string: (nil)
|
194
193
|
<buffer>: optional, single
|
data/test/compat/test_parser.rb
CHANGED
@@ -38,14 +38,14 @@ class TextParserTest < ::Test::Unit::TestCase
|
|
38
38
|
|
39
39
|
def test_parse_with_return
|
40
40
|
parser = Fluent::TextParser.new
|
41
|
-
parser.configure('format' => 'none')
|
41
|
+
parser.configure(config_element('test', '', 'format' => 'none'))
|
42
42
|
_time, record = parser.parse('log message!')
|
43
43
|
assert_equal({'message' => 'log message!'}, record)
|
44
44
|
end
|
45
45
|
|
46
46
|
def test_parse_with_block
|
47
47
|
parser = Fluent::TextParser.new
|
48
|
-
parser.configure('format' => 'none')
|
48
|
+
parser.configure(config_element('test', '', 'format' => 'none'))
|
49
49
|
parser.parse('log message!') { |time, record|
|
50
50
|
assert_equal({'message' => 'log message!'}, record)
|
51
51
|
}
|
@@ -53,7 +53,7 @@ class TextParserTest < ::Test::Unit::TestCase
|
|
53
53
|
|
54
54
|
def test_multi_event_parser
|
55
55
|
parser = Fluent::TextParser.new
|
56
|
-
parser.configure('format' => 'multi_event_test')
|
56
|
+
parser.configure(config_element('test', '', 'format' => 'multi_event_test'))
|
57
57
|
i = 0
|
58
58
|
parser.parse('log message!') { |time, record|
|
59
59
|
assert_equal('log message!', record['message'])
|
@@ -67,7 +67,7 @@ class TextParserTest < ::Test::Unit::TestCase
|
|
67
67
|
assert_nil p1.estimate_current_event
|
68
68
|
assert_nil p1.parser
|
69
69
|
|
70
|
-
p1.configure('format' => 'none')
|
70
|
+
p1.configure(config_element('test', '', 'format' => 'none'))
|
71
71
|
assert_equal true, p1.parser.estimate_current_event
|
72
72
|
|
73
73
|
p2 = Fluent::TextParser.new
|
@@ -76,7 +76,7 @@ class TextParserTest < ::Test::Unit::TestCase
|
|
76
76
|
|
77
77
|
p2.estimate_current_event = false
|
78
78
|
|
79
|
-
p2.configure('format' => 'none')
|
79
|
+
p2.configure(config_element('test', '', 'format' => 'none'))
|
80
80
|
assert_equal false, p2.parser.estimate_current_event
|
81
81
|
end
|
82
82
|
|
@@ -5,13 +5,6 @@ require 'fluent/config/section'
|
|
5
5
|
require 'fluent/system_config'
|
6
6
|
|
7
7
|
module Fluent::Config
|
8
|
-
class FakeLoggerInitializer
|
9
|
-
attr_accessor :level
|
10
|
-
def initialize
|
11
|
-
@level = nil
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
8
|
class FakeSupervisor
|
16
9
|
attr_writer :log_level
|
17
10
|
|
@@ -21,7 +14,6 @@ module Fluent::Config
|
|
21
14
|
wokers: nil,
|
22
15
|
restart_worker_interval: nil,
|
23
16
|
root_dir: nil,
|
24
|
-
log: FakeLoggerInitializer.new,
|
25
17
|
log_level: Fluent::Log::LEVEL_INFO,
|
26
18
|
suppress_interval: nil,
|
27
19
|
suppress_config_dump: nil,
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require_relative '../helper'
|
2
|
+
|
3
|
+
require 'fluent/log'
|
4
|
+
require 'fluent/log/console_adapter'
|
5
|
+
|
6
|
+
class ConsoleAdapterTest < Test::Unit::TestCase
|
7
|
+
def setup
|
8
|
+
@timestamp = Time.parse("2023-01-01 15:32:41 +0000")
|
9
|
+
@timestamp_str = @timestamp.strftime("%Y-%m-%d %H:%M:%S %z")
|
10
|
+
Timecop.freeze(@timestamp)
|
11
|
+
|
12
|
+
@logdev = Fluent::Test::DummyLogDevice.new
|
13
|
+
@logger = ServerEngine::DaemonLogger.new(@logdev)
|
14
|
+
@fluent_log = Fluent::Log.new(@logger)
|
15
|
+
@console_logger = Fluent::Log::ConsoleAdapter.wrap(@fluent_log)
|
16
|
+
end
|
17
|
+
|
18
|
+
def teardown
|
19
|
+
Timecop.return
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_expected_log_levels
|
23
|
+
assert_equal({debug: 0, info: 1, warn: 2, error: 3, fatal: 4},
|
24
|
+
Console::Logger::LEVELS)
|
25
|
+
end
|
26
|
+
|
27
|
+
data(trace: [Fluent::Log::LEVEL_TRACE, :debug],
|
28
|
+
debug: [Fluent::Log::LEVEL_DEBUG, :debug],
|
29
|
+
info: [Fluent::Log::LEVEL_INFO, :info],
|
30
|
+
warn: [Fluent::Log::LEVEL_WARN, :warn],
|
31
|
+
error: [Fluent::Log::LEVEL_ERROR, :error],
|
32
|
+
fatal: [Fluent::Log::LEVEL_FATAL, :fatal])
|
33
|
+
def test_reflect_log_level(data)
|
34
|
+
level, expected = data
|
35
|
+
@fluent_log.level = level
|
36
|
+
console_logger = Fluent::Log::ConsoleAdapter.wrap(@fluent_log)
|
37
|
+
assert_equal(Console::Logger::LEVELS[expected],
|
38
|
+
console_logger.level)
|
39
|
+
end
|
40
|
+
|
41
|
+
data(debug: :debug,
|
42
|
+
info: :info,
|
43
|
+
warn: :warn,
|
44
|
+
error: :error,
|
45
|
+
fatal: :fatal)
|
46
|
+
def test_string_subject(level)
|
47
|
+
@console_logger.send(level, "subject")
|
48
|
+
assert_equal(["#{@timestamp_str} [#{level}]: 0.0s: subject\n"],
|
49
|
+
@logdev.logs)
|
50
|
+
end
|
51
|
+
|
52
|
+
data(debug: :debug,
|
53
|
+
info: :info,
|
54
|
+
warn: :warn,
|
55
|
+
error: :error,
|
56
|
+
fatal: :fatal)
|
57
|
+
def test_args(level)
|
58
|
+
@console_logger.send(level, "subject", 1, 2, 3)
|
59
|
+
assert_equal([
|
60
|
+
"#{@timestamp_str} [#{level}]: 0.0s: subject\n" +
|
61
|
+
" | 1\n" +
|
62
|
+
" | 2\n" +
|
63
|
+
" | 3\n"
|
64
|
+
],
|
65
|
+
@logdev.logs)
|
66
|
+
end
|
67
|
+
|
68
|
+
data(debug: :debug,
|
69
|
+
info: :info,
|
70
|
+
warn: :warn,
|
71
|
+
error: :error,
|
72
|
+
fatal: :fatal)
|
73
|
+
def test_options(level)
|
74
|
+
@console_logger.send(level, "subject", kwarg1: "opt1", kwarg2: "opt2")
|
75
|
+
assert_equal([
|
76
|
+
"#{@timestamp_str} [#{level}]: 0.0s: subject\n" +
|
77
|
+
" | {\"kwarg1\":\"opt1\",\"kwarg2\":\"opt2\"}\n"
|
78
|
+
],
|
79
|
+
@logdev.logs)
|
80
|
+
end
|
81
|
+
|
82
|
+
data(debug: :debug,
|
83
|
+
info: :info,
|
84
|
+
warn: :warn,
|
85
|
+
error: :error,
|
86
|
+
fatal: :fatal)
|
87
|
+
def test_block(level)
|
88
|
+
@console_logger.send(level, "subject") { "block message" }
|
89
|
+
assert_equal([
|
90
|
+
"#{@timestamp_str} [#{level}]: 0.0s: subject\n" +
|
91
|
+
" | block message\n"
|
92
|
+
],
|
93
|
+
@logdev.logs)
|
94
|
+
end
|
95
|
+
|
96
|
+
data(debug: :debug,
|
97
|
+
info: :info,
|
98
|
+
warn: :warn,
|
99
|
+
error: :error,
|
100
|
+
fatal: :fatal)
|
101
|
+
def test_multiple_entries(level)
|
102
|
+
@console_logger.send(level, "subject1")
|
103
|
+
@console_logger.send(level, "line2")
|
104
|
+
assert_equal([
|
105
|
+
"#{@timestamp_str} [#{level}]: 0.0s: subject1\n",
|
106
|
+
"#{@timestamp_str} [#{level}]: 0.0s: line2\n"
|
107
|
+
],
|
108
|
+
@logdev.logs)
|
109
|
+
end
|
110
|
+
end
|
@@ -98,4 +98,43 @@ class AckHandlerTest < Test::Unit::TestCase
|
|
98
98
|
w.close rescue nil
|
99
99
|
end
|
100
100
|
end
|
101
|
+
|
102
|
+
# ForwardOutput uses AckHandler in multiple threads, so we need to assume this case.
|
103
|
+
# If exclusive control for this case is implemented, this test may not be necessary.
|
104
|
+
test 'raises no error when another thread closes a socket' do
|
105
|
+
ack_handler = Fluent::Plugin::ForwardOutput::AckHandler.new(timeout: 10, log: $log, read_length: 100)
|
106
|
+
|
107
|
+
node = flexmock('node', host: '127.0.0.1', port: '1000') # for log
|
108
|
+
chunk_id = 'chunk_id 111'
|
109
|
+
ack = ack_handler.create_ack(chunk_id, node)
|
110
|
+
|
111
|
+
r, w = IO.pipe
|
112
|
+
begin
|
113
|
+
w.write(chunk_id)
|
114
|
+
stub(r).recv { |_|
|
115
|
+
sleep(1) # To ensure that multiple threads select the socket before closing.
|
116
|
+
raise IOError, 'stream closed in another thread' if r.closed?
|
117
|
+
MessagePack.pack({ 'ack' => Base64.encode64('chunk_id 111') })
|
118
|
+
}
|
119
|
+
ack.enqueue(r)
|
120
|
+
|
121
|
+
threads = []
|
122
|
+
2.times do
|
123
|
+
threads << Thread.new do
|
124
|
+
ack_handler.collect_response(1) do |cid, n, s, ret|
|
125
|
+
s&.close
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
assert_true threads.map{ |t| t.join(10) }.all?
|
131
|
+
assert_false(
|
132
|
+
$log.out.logs.any? { |log| log.include?('[error]') },
|
133
|
+
$log.out.logs.select{ |log| log.include?('[error]') }.join('\n')
|
134
|
+
)
|
135
|
+
ensure
|
136
|
+
r.close rescue nil
|
137
|
+
w.close rescue nil
|
138
|
+
end
|
139
|
+
end
|
101
140
|
end
|
data/test/plugin/test_base.rb
CHANGED
@@ -146,4 +146,102 @@ class BaseTest < Test::Unit::TestCase
|
|
146
146
|
end
|
147
147
|
end
|
148
148
|
end
|
149
|
+
|
150
|
+
test '`ArgumentError` when `conf` is not `Fluent::Config::Element`' do
|
151
|
+
assert_raise ArgumentError.new('BUG: type of conf must be Fluent::Config::Element, but Hash is passed.') do
|
152
|
+
@p.configure({})
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
sub_test_case 'system_config.workers value after configure' do
|
157
|
+
def assert_system_config_workers_value(data)
|
158
|
+
conf = config_element()
|
159
|
+
conf.set_target_worker_ids(data[:target_worker_ids])
|
160
|
+
@p.configure(conf)
|
161
|
+
assert{ @p.system_config.workers == data[:expected] }
|
162
|
+
end
|
163
|
+
|
164
|
+
def stub_supervisor_mode
|
165
|
+
stub(Fluent::Engine).supervisor_mode { true }
|
166
|
+
stub(Fluent::Engine).worker_id { -1 }
|
167
|
+
end
|
168
|
+
|
169
|
+
sub_test_case 'with <system> workers 3 </system>' do
|
170
|
+
setup do
|
171
|
+
system_config = Fluent::SystemConfig.new
|
172
|
+
system_config.workers = 3
|
173
|
+
stub(Fluent::Engine).system_config { system_config }
|
174
|
+
end
|
175
|
+
|
176
|
+
data(
|
177
|
+
'without <worker> directive',
|
178
|
+
{
|
179
|
+
target_worker_ids: [],
|
180
|
+
expected: 3
|
181
|
+
},
|
182
|
+
keep: true
|
183
|
+
)
|
184
|
+
data(
|
185
|
+
'with <worker 0>',
|
186
|
+
{
|
187
|
+
target_worker_ids: [0],
|
188
|
+
expected: 1
|
189
|
+
},
|
190
|
+
keep: true
|
191
|
+
)
|
192
|
+
data(
|
193
|
+
'with <worker 0-1>',
|
194
|
+
{
|
195
|
+
target_worker_ids: [0, 1],
|
196
|
+
expected: 2
|
197
|
+
},
|
198
|
+
keep: true
|
199
|
+
)
|
200
|
+
data(
|
201
|
+
'with <worker 0-2>',
|
202
|
+
{
|
203
|
+
target_worker_ids: [0, 1, 2],
|
204
|
+
expected: 3
|
205
|
+
},
|
206
|
+
keep: true
|
207
|
+
)
|
208
|
+
|
209
|
+
test 'system_config.workers value after configure' do
|
210
|
+
assert_system_config_workers_value(data)
|
211
|
+
end
|
212
|
+
|
213
|
+
test 'system_config.workers value after configure with supervisor_mode' do
|
214
|
+
stub_supervisor_mode
|
215
|
+
assert_system_config_workers_value(data)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
sub_test_case 'without <system> directive' do
|
220
|
+
data(
|
221
|
+
'without <worker> directive',
|
222
|
+
{
|
223
|
+
target_worker_ids: [],
|
224
|
+
expected: 1
|
225
|
+
},
|
226
|
+
keep: true
|
227
|
+
)
|
228
|
+
data(
|
229
|
+
'with <worker 0>',
|
230
|
+
{
|
231
|
+
target_worker_ids: [0],
|
232
|
+
expected: 1
|
233
|
+
},
|
234
|
+
keep: true
|
235
|
+
)
|
236
|
+
|
237
|
+
test 'system_config.workers value after configure' do
|
238
|
+
assert_system_config_workers_value(data)
|
239
|
+
end
|
240
|
+
|
241
|
+
test 'system_config.workers value after configure with supervisor_mode' do
|
242
|
+
stub_supervisor_mode
|
243
|
+
assert_system_config_workers_value(data)
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
149
247
|
end
|