fluentd 1.11.3-x86-mingw32 → 1.12.2-x86-mingw32

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 (97) hide show
  1. checksums.yaml +4 -4
  2. data/.deepsource.toml +13 -0
  3. data/.github/ISSUE_TEMPLATE/bug_report.md +1 -1
  4. data/.github/ISSUE_TEMPLATE/config.yml +5 -0
  5. data/.github/workflows/linux-test.yaml +36 -0
  6. data/.github/workflows/macos-test.yaml +30 -0
  7. data/.github/workflows/stale-actions.yml +22 -0
  8. data/.github/workflows/windows-test.yaml +30 -0
  9. data/CHANGELOG.md +138 -0
  10. data/MAINTAINERS.md +5 -2
  11. data/README.md +2 -2
  12. data/bin/fluent-cap-ctl +7 -0
  13. data/bin/fluent-ctl +7 -0
  14. data/fluentd.gemspec +4 -3
  15. data/lib/fluent/capability.rb +87 -0
  16. data/lib/fluent/command/bundler_injection.rb +1 -1
  17. data/lib/fluent/command/ca_generate.rb +6 -3
  18. data/lib/fluent/command/cap_ctl.rb +174 -0
  19. data/lib/fluent/command/cat.rb +0 -1
  20. data/lib/fluent/command/ctl.rb +177 -0
  21. data/lib/fluent/command/fluentd.rb +4 -0
  22. data/lib/fluent/command/plugin_config_formatter.rb +18 -2
  23. data/lib/fluent/compat/parser.rb +2 -2
  24. data/lib/fluent/config/section.rb +2 -2
  25. data/lib/fluent/config/types.rb +2 -2
  26. data/lib/fluent/env.rb +4 -0
  27. data/lib/fluent/event.rb +3 -13
  28. data/lib/fluent/load.rb +0 -1
  29. data/lib/fluent/plugin.rb +5 -0
  30. data/lib/fluent/plugin/buffer.rb +2 -21
  31. data/lib/fluent/plugin/formatter.rb +24 -0
  32. data/lib/fluent/plugin/formatter_csv.rb +1 -1
  33. data/lib/fluent/plugin/formatter_hash.rb +3 -1
  34. data/lib/fluent/plugin/formatter_json.rb +3 -1
  35. data/lib/fluent/plugin/formatter_ltsv.rb +7 -5
  36. data/lib/fluent/plugin/formatter_out_file.rb +6 -4
  37. data/lib/fluent/plugin/formatter_single_value.rb +4 -2
  38. data/lib/fluent/plugin/formatter_tsv.rb +4 -2
  39. data/lib/fluent/plugin/in_http.rb +24 -3
  40. data/lib/fluent/plugin/in_monitor_agent.rb +1 -1
  41. data/lib/fluent/plugin/in_tail.rb +128 -41
  42. data/lib/fluent/plugin/in_tail/position_file.rb +39 -14
  43. data/lib/fluent/plugin/in_tcp.rb +1 -0
  44. data/lib/fluent/plugin/out_copy.rb +18 -5
  45. data/lib/fluent/plugin/out_exec_filter.rb +3 -3
  46. data/lib/fluent/plugin/out_forward.rb +61 -28
  47. data/lib/fluent/plugin/out_http.rb +29 -4
  48. data/lib/fluent/plugin/output.rb +14 -6
  49. data/lib/fluent/plugin/storage_local.rb +3 -3
  50. data/lib/fluent/plugin_helper/http_server/compat/server.rb +1 -1
  51. data/lib/fluent/plugin_helper/inject.rb +4 -1
  52. data/lib/fluent/plugin_helper/retry_state.rb +4 -0
  53. data/lib/fluent/supervisor.rb +153 -48
  54. data/lib/fluent/system_config.rb +2 -1
  55. data/lib/fluent/time.rb +58 -1
  56. data/lib/fluent/version.rb +1 -1
  57. data/lib/fluent/winsvc.rb +22 -4
  58. data/templates/plugin_config_formatter/param.md-table.erb +10 -0
  59. data/test/command/test_binlog_reader.rb +22 -6
  60. data/test/command/test_cap_ctl.rb +100 -0
  61. data/test/command/test_ctl.rb +57 -0
  62. data/test/command/test_fluentd.rb +38 -0
  63. data/test/command/test_plugin_config_formatter.rb +124 -2
  64. data/test/config/test_configurable.rb +1 -1
  65. data/test/plugin/in_tail/test_position_file.rb +46 -26
  66. data/test/plugin/out_forward/test_connection_manager.rb +6 -0
  67. data/test/plugin/test_filter_stdout.rb +6 -1
  68. data/test/plugin/test_formatter_hash.rb +6 -3
  69. data/test/plugin/test_formatter_json.rb +14 -4
  70. data/test/plugin/test_formatter_ltsv.rb +13 -5
  71. data/test/plugin/test_formatter_out_file.rb +35 -14
  72. data/test/plugin/test_formatter_single_value.rb +12 -6
  73. data/test/plugin/test_formatter_tsv.rb +12 -4
  74. data/test/plugin/test_in_exec.rb +1 -1
  75. data/test/plugin/test_in_http.rb +25 -0
  76. data/test/plugin/test_in_tail.rb +470 -32
  77. data/test/plugin/test_out_copy.rb +87 -0
  78. data/test/plugin/test_out_file.rb +23 -18
  79. data/test/plugin/test_out_forward.rb +74 -0
  80. data/test/plugin/test_out_http.rb +20 -1
  81. data/test/plugin/test_output.rb +12 -0
  82. data/test/plugin/test_parser_syslog.rb +2 -2
  83. data/test/plugin/test_sd_file.rb +1 -1
  84. data/test/plugin_helper/test_child_process.rb +5 -2
  85. data/test/plugin_helper/test_compat_parameters.rb +7 -2
  86. data/test/plugin_helper/test_http_server_helper.rb +3 -1
  87. data/test/plugin_helper/test_inject.rb +42 -0
  88. data/test/plugin_helper/test_server.rb +18 -5
  89. data/test/test_capability.rb +74 -0
  90. data/test/test_event.rb +16 -0
  91. data/test/test_formatter.rb +64 -10
  92. data/test/test_output.rb +6 -1
  93. data/test/test_supervisor.rb +150 -1
  94. data/test/test_time_parser.rb +109 -0
  95. metadata +61 -29
  96. data/.travis.yml +0 -57
  97. data/appveyor.yml +0 -28
@@ -10,6 +10,11 @@ class CompatParameterTest < Test::Unit::TestCase
10
10
  setup do
11
11
  Fluent::Test.setup
12
12
  @i = nil
13
+ @default_newline = if Fluent.windows?
14
+ "\r\n"
15
+ else
16
+ "\n"
17
+ end
13
18
  end
14
19
 
15
20
  teardown do
@@ -226,7 +231,7 @@ class CompatParameterTest < Test::Unit::TestCase
226
231
  t = event_time('2016-06-24 16:05:01') # localtime
227
232
  iso8601str = Time.at(t.to_i).iso8601
228
233
  formatted = @i.f.format('tag.test', t, @i.inject_values_to_record('tag.test', t, {"value" => 1}))
229
- assert_equal "value%1,tag%tag.test,time%#{iso8601str}\n", formatted
234
+ assert_equal "value%1,tag%tag.test,time%#{iso8601str}#{@default_newline}", formatted
230
235
  end
231
236
 
232
237
  test 'plugin helper setups time injecting as unix time (integer from epoch)' do
@@ -260,7 +265,7 @@ class CompatParameterTest < Test::Unit::TestCase
260
265
  t = event_time('2016-06-24 16:05:01') # localtime
261
266
  iso8601str = Time.at(t.to_i).iso8601
262
267
  formatted = @i.f.format('tag.test', t, @i.inject_values_to_record('tag.test', t, {"value" => 1}))
263
- assert_equal "value%1,tag%tag.test,time%#{iso8601str}\n", formatted
268
+ assert_equal "value%1,tag%tag.test,time%#{iso8601str}#{@default_newline}", formatted
264
269
  end
265
270
  end
266
271
 
@@ -132,7 +132,9 @@ class HttpHelperTest < Test::Unit::TestCase
132
132
  error = e
133
133
  end
134
134
 
135
- resp = Response.new(response.status.to_s, response.body.read, response.headers)
135
+ if response
136
+ resp = Response.new(response.status.to_s, response.body.read, response.headers)
137
+ end
136
138
  end
137
139
 
138
140
  if error
@@ -176,6 +176,48 @@ class InjectHelperTest < Test::Unit::TestCase
176
176
  assert_equal record.merge({"timedata" => float_time}), @d.inject_values_to_record('tag', time, record)
177
177
  end
178
178
 
179
+ test 'injects time as unix time millis into specified key' do
180
+ time_in_unix = Time.parse("2016-06-21 08:10:11 +0900").to_i
181
+ time_subsecond = 320_101_224
182
+ time = Fluent::EventTime.new(time_in_unix, time_subsecond)
183
+ unixtime_millis = 1466464211320
184
+
185
+ @d.configure(config_inject_section("time_key" => "timedata", "time_type" => "unixtime_millis"))
186
+ @d.start
187
+
188
+ record = {"key1" => "value1", "key2" => 2}
189
+ assert_equal record.merge({"timedata" => unixtime_millis}), @d.inject_values_to_record('tag', time, record)
190
+ assert_equal record.merge({"timedata" => time_in_unix * 1_000}), @d.inject_values_to_record('tag', time_in_unix, record)
191
+ end
192
+
193
+ test 'injects time as unix time micros into specified key' do
194
+ time_in_unix = Time.parse("2016-06-21 08:10:11 +0900").to_i
195
+ time_subsecond = 320_101_224
196
+ time = Fluent::EventTime.new(time_in_unix, time_subsecond)
197
+ unixtime_micros = 1466464211320101
198
+
199
+ @d.configure(config_inject_section("time_key" => "timedata", "time_type" => "unixtime_micros"))
200
+ @d.start
201
+
202
+ record = {"key1" => "value1", "key2" => 2}
203
+ assert_equal record.merge({"timedata" => unixtime_micros}), @d.inject_values_to_record('tag', time, record)
204
+ assert_equal record.merge({"timedata" => time_in_unix * 1_000_000}), @d.inject_values_to_record('tag', time_in_unix, record)
205
+ end
206
+
207
+ test 'injects time as unix time nanos into specified key' do
208
+ time_in_unix = Time.parse("2016-06-21 08:10:11 +0900").to_i
209
+ time_subsecond = 320_101_224
210
+ time = Fluent::EventTime.new(time_in_unix, time_subsecond)
211
+ unixtime_nanos = 1466464211320101224
212
+
213
+ @d.configure(config_inject_section("time_key" => "timedata", "time_type" => "unixtime_nanos"))
214
+ @d.start
215
+
216
+ record = {"key1" => "value1", "key2" => 2}
217
+ assert_equal record.merge({"timedata" => unixtime_nanos}), @d.inject_values_to_record('tag', time, record)
218
+ assert_equal record.merge({"timedata" => time_in_unix * 1_000_000_000}), @d.inject_values_to_record('tag', time_in_unix, record)
219
+ end
220
+
179
221
  test 'injects time as unix time into specified key' do
180
222
  time_in_unix = Time.parse("2016-06-21 08:10:11 +0900").to_i
181
223
  time_subsecond = 320_101_224
@@ -832,8 +832,9 @@ class ServerPluginHelperTest < Test::Unit::TestCase
832
832
  chain_cert.sign(root_key, "sha256")
833
833
 
834
834
  server_cert, server_key, _ = CertUtil.cert_option_generate_pair(create_server_options, chain_cert.subject)
835
- server_cert.add_extension OpenSSL::X509::Extension.new('basicConstraints', OpenSSL::ASN1.Sequence([OpenSSL::ASN1::Boolean(false)]))
836
- server_cert.add_extension OpenSSL::X509::Extension.new('nsCertType', 'server')
835
+ factory = OpenSSL::X509::ExtensionFactory.new
836
+ server_cert.add_extension(factory.create_extension('basicConstraints', 'CA:FALSE'))
837
+ server_cert.add_extension(factory.create_extension('nsCertType', 'server'))
837
838
  server_cert.sign(chain_key, "sha256")
838
839
 
839
840
  # write chained cert
@@ -1494,8 +1495,13 @@ class ServerPluginHelperTest < Test::Unit::TestCase
1494
1495
  test "can't connect with different TLS version" do
1495
1496
  @d.server_create_tls(:s, PORT, tls_options: @tls_options) do |data, conn|
1496
1497
  end
1498
+ if defined?(OpenSSL::SSL::TLS1_3_VERSION)
1499
+ version = :'TLS1_3'
1500
+ else
1501
+ version = :'TLS1_1'
1502
+ end
1497
1503
  assert_raise(OpenSSL::SSL::SSLError, Errno::ECONNRESET) {
1498
- open_tls_session('127.0.0.1', PORT, cert_path: @cert_path, version: :'TLS1_1') do |sock|
1504
+ open_tls_session('127.0.0.1', PORT, cert_path: @cert_path, version: version) do |sock|
1499
1505
  end
1500
1506
  }
1501
1507
  end
@@ -1503,14 +1509,21 @@ class ServerPluginHelperTest < Test::Unit::TestCase
1503
1509
  test "can specify multiple TLS versions by min_version/max_version" do
1504
1510
  omit "min_version=/max_version= is not supported" unless Fluent::TLS::MIN_MAX_AVAILABLE
1505
1511
 
1506
- opts = @tls_options.merge(min_version: :'TLS1_1', max_version: :'TLSv1_2')
1512
+ min_version = :'TLS1_2'
1513
+ if defined?(OpenSSL::SSL::TLS1_3_VERSION)
1514
+ max_version = :'TLS1_3'
1515
+ else
1516
+ max_version = :'TLS1_2'
1517
+ end
1518
+
1519
+ opts = @tls_options.merge(min_version: min_version, max_version: max_version)
1507
1520
  @d.server_create_tls(:s, PORT, tls_options: opts) do |data, conn|
1508
1521
  end
1509
1522
  assert_raise(OpenSSL::SSL::SSLError, Errno::ECONNRESET) {
1510
1523
  open_tls_session('127.0.0.1', PORT, cert_path: @cert_path, version: :'TLS1') do |sock|
1511
1524
  end
1512
1525
  }
1513
- [:'TLS1_1', :'TLS1_2'].each { |ver|
1526
+ [min_version, max_version].each { |ver|
1514
1527
  assert_nothing_raised {
1515
1528
  open_tls_session('127.0.0.1', PORT, cert_path: @cert_path, version: ver) do |sock|
1516
1529
  end
@@ -0,0 +1,74 @@
1
+ require_relative 'helper'
2
+ require 'fluent/test'
3
+ require 'fluent/capability'
4
+
5
+ class FluentCapabilityTest < ::Test::Unit::TestCase
6
+ setup do
7
+ @capability = Fluent::Capability.new(:current_process)
8
+ omit "Fluent::Capability class is not usable on this environment" unless @capability.usable?
9
+ end
10
+
11
+ sub_test_case "check capability" do
12
+ test "effective" do
13
+ @capability.clear(:both)
14
+ assert_true @capability.update(:add, :effective, :dac_read_search)
15
+ assert_equal CapNG::Result::PARTIAL, @capability.have_capabilities?(:caps)
16
+ assert_nothing_raised do
17
+ @capability.apply(:caps)
18
+ end
19
+ assert_equal CapNG::Result::NONE, @capability.have_capabilities?(:bounds)
20
+ assert_true @capability.have_capability?(:effective, :dac_read_search)
21
+ assert_false @capability.have_capability?(:inheritable, :dac_read_search)
22
+ assert_false @capability.have_capability?(:permitted, :dac_read_search)
23
+ end
24
+
25
+ test "inheritable" do
26
+ @capability.clear(:both)
27
+ capabilities = [:chown, :dac_override]
28
+ assert_equal [true, true], @capability.update(:add, :inheritable, capabilities)
29
+ assert_equal CapNG::Result::NONE, @capability.have_capabilities?(:caps)
30
+ assert_nothing_raised do
31
+ @capability.apply(:caps)
32
+ end
33
+ assert_equal CapNG::Result::NONE, @capability.have_capabilities?(:bounds)
34
+ capabilities.each do |capability|
35
+ assert_false @capability.have_capability?(:effective, capability)
36
+ assert_true @capability.have_capability?(:inheritable, capability)
37
+ assert_false @capability.have_capability?(:permitted, capability)
38
+ end
39
+ end
40
+
41
+ test "permitted" do
42
+ @capability.clear(:both)
43
+ capabilities = [:fowner, :fsetid, :kill]
44
+ assert_equal [true, true, true], @capability.update(:add, :permitted, capabilities)
45
+ assert_equal CapNG::Result::NONE, @capability.have_capabilities?(:caps)
46
+ assert_nothing_raised do
47
+ @capability.apply(:caps)
48
+ end
49
+ assert_equal CapNG::Result::NONE, @capability.have_capabilities?(:bounds)
50
+ capabilities.each do |capability|
51
+ assert_false @capability.have_capability?(:effective, capability)
52
+ assert_false @capability.have_capability?(:inheritable, capability)
53
+ assert_true @capability.have_capability?(:permitted, capability)
54
+ end
55
+ end
56
+
57
+ test "effective/inheritable/permitted" do
58
+ @capability.clear(:both)
59
+ capabilities = [:setpcap, :net_admin, :net_raw, :sys_boot, :sys_time]
60
+ update_type = CapNG::Type::EFFECTIVE | CapNG::Type::INHERITABLE | CapNG::Type::PERMITTED
61
+ assert_equal [true, true, true, true, true], @capability.update(:add, update_type, capabilities)
62
+ assert_equal CapNG::Result::PARTIAL, @capability.have_capabilities?(:caps)
63
+ assert_nothing_raised do
64
+ @capability.apply(:caps)
65
+ end
66
+ assert_equal CapNG::Result::NONE, @capability.have_capabilities?(:bounds)
67
+ capabilities.each do |capability|
68
+ assert_true @capability.have_capability?(:effective, capability)
69
+ assert_true @capability.have_capability?(:inheritable, capability)
70
+ assert_true @capability.have_capability?(:permitted, capability)
71
+ end
72
+ end
73
+ end
74
+ end
data/test/test_event.rb CHANGED
@@ -401,6 +401,22 @@ module EventTest
401
401
  i += 1
402
402
  }
403
403
  end
404
+
405
+ # `any?` represents an Enumerable method which calls `each` internally
406
+ test 'size_after_any' do
407
+ @es.any?
408
+
409
+ assert_equal 2, @es.size
410
+ end
411
+
412
+ # `any?` represents an Enumerable method which calls `each` internally
413
+ test 'each_after_any' do
414
+ @es.any?
415
+
416
+ count = 0
417
+ @es.each { |time, record| count += 1 }
418
+ assert_equal 2, count
419
+ end
404
420
  end
405
421
 
406
422
  class CompressedMessagePackEventStreamTest < ::Test::Unit::TestCase
@@ -53,6 +53,11 @@ module FormatterTest
53
53
  def setup
54
54
  @formatter = Fluent::Test::FormatterTestDriver.new('out_file')
55
55
  @time = Engine.now
56
+ @newline = if Fluent.windows?
57
+ "\r\n"
58
+ else
59
+ "\n"
60
+ end
56
61
  end
57
62
 
58
63
  def configure(conf)
@@ -63,28 +68,28 @@ module FormatterTest
63
68
  configure({})
64
69
  formatted = @formatter.format(tag, @time, record)
65
70
 
66
- assert_equal("#{time2str(@time)}\t#{tag}\t#{Yajl.dump(record)}\n", formatted)
71
+ assert_equal("#{time2str(@time)}\t#{tag}\t#{Yajl.dump(record)}#{@newline}", formatted)
67
72
  end
68
73
 
69
74
  def test_format_without_time
70
75
  configure('output_time' => 'false')
71
76
  formatted = @formatter.format(tag, @time, record)
72
77
 
73
- assert_equal("#{tag}\t#{Yajl.dump(record)}\n", formatted)
78
+ assert_equal("#{tag}\t#{Yajl.dump(record)}#{@newline}", formatted)
74
79
  end
75
80
 
76
81
  def test_format_without_tag
77
82
  configure('output_tag' => 'false')
78
83
  formatted = @formatter.format(tag, @time, record)
79
84
 
80
- assert_equal("#{time2str(@time)}\t#{Yajl.dump(record)}\n", formatted)
85
+ assert_equal("#{time2str(@time)}\t#{Yajl.dump(record)}#{@newline}", formatted)
81
86
  end
82
87
 
83
88
  def test_format_without_time_and_tag
84
89
  configure('output_tag' => 'false', 'output_time' => 'false')
85
90
  formatted = @formatter.format('tag', @time, record)
86
91
 
87
- assert_equal("#{Yajl.dump(record)}\n", formatted)
92
+ assert_equal("#{Yajl.dump(record)}#{@newline}", formatted)
88
93
  end
89
94
 
90
95
  def test_format_without_time_and_tag_against_string_literal_configure
@@ -95,7 +100,7 @@ module FormatterTest
95
100
  ])
96
101
  formatted = @formatter.format('tag', @time, record)
97
102
 
98
- assert_equal("#{Yajl.dump(record)}\n", formatted)
103
+ assert_equal("#{Yajl.dump(record)}#{@newline}", formatted)
99
104
  end
100
105
  end
101
106
 
@@ -105,6 +110,11 @@ module FormatterTest
105
110
  def setup
106
111
  @formatter = Fluent::Test::FormatterTestDriver.new(TextFormatter::JSONFormatter)
107
112
  @time = Engine.now
113
+ @newline = if Fluent.windows?
114
+ "\r\n"
115
+ else
116
+ "\n"
117
+ end
108
118
  end
109
119
 
110
120
  data('oj' => 'oj', 'yajl' => 'yajl')
@@ -112,7 +122,7 @@ module FormatterTest
112
122
  @formatter.configure('json_parser' => data)
113
123
  formatted = @formatter.format(tag, @time, record)
114
124
 
115
- assert_equal("#{Yajl.dump(record)}\n", formatted)
125
+ assert_equal("#{Yajl.dump(record)}#{@newline}", formatted)
116
126
  end
117
127
  end
118
128
 
@@ -138,6 +148,11 @@ module FormatterTest
138
148
  def setup
139
149
  @formatter = TextFormatter::LabeledTSVFormatter.new
140
150
  @time = Engine.now
151
+ @newline = if Fluent.windows?
152
+ "\r\n"
153
+ else
154
+ "\n"
155
+ end
141
156
  end
142
157
 
143
158
  def test_config_params
@@ -157,7 +172,7 @@ module FormatterTest
157
172
  @formatter.configure({})
158
173
  formatted = @formatter.format(tag, @time, record)
159
174
 
160
- assert_equal("message:awesome\tgreeting:hello\n", formatted)
175
+ assert_equal("message:awesome\tgreeting:hello#{@newline}", formatted)
161
176
  end
162
177
 
163
178
  def test_format_with_customized_delimiters
@@ -167,7 +182,37 @@ module FormatterTest
167
182
  )
168
183
  formatted = @formatter.format(tag, @time, record)
169
184
 
170
- assert_equal("message=awesome,greeting=hello\n", formatted)
185
+ assert_equal("message=awesome,greeting=hello#{@newline}", formatted)
186
+ end
187
+
188
+ def record_with_tab
189
+ {'message' => "awe\tsome", 'greeting' => "hello\t"}
190
+ end
191
+
192
+ def test_format_suppresses_tab
193
+ @formatter.configure({})
194
+ formatted = @formatter.format(tag, @time, record_with_tab)
195
+
196
+ assert_equal("message:awe some\tgreeting:hello #{@newline}", formatted)
197
+ end
198
+
199
+ def test_format_suppresses_tab_custom_replacement
200
+ @formatter.configure(
201
+ 'replacement' => 'X',
202
+ )
203
+ formatted = @formatter.format(tag, @time, record_with_tab)
204
+
205
+ assert_equal("message:aweXsome\tgreeting:helloX#{@newline}", formatted)
206
+ end
207
+
208
+ def test_format_suppresses_custom_delimiter
209
+ @formatter.configure(
210
+ 'delimiter' => 'w',
211
+ 'label_delimiter' => '=',
212
+ )
213
+ formatted = @formatter.format(tag, @time, record)
214
+
215
+ assert_equal("message=a esomewgreeting=hello#{@newline}", formatted)
171
216
  end
172
217
  end
173
218
 
@@ -260,6 +305,14 @@ module FormatterTest
260
305
 
261
306
  class SingleValueFormatterTest < ::Test::Unit::TestCase
262
307
  include FormatterTest
308
+ def setup
309
+ @newline = if Fluent.windows?
310
+ "\r\n"
311
+ else
312
+ "\n"
313
+ end
314
+ end
315
+
263
316
 
264
317
  def test_config_params
265
318
  formatter = TextFormatter::SingleValueFormatter.new
@@ -271,8 +324,9 @@ module FormatterTest
271
324
 
272
325
  def test_format
273
326
  formatter = Fluent::Plugin.new_formatter('single_value')
327
+ formatter.configure({})
274
328
  formatted = formatter.format('tag', Engine.now, {'message' => 'awesome'})
275
- assert_equal("awesome\n", formatted)
329
+ assert_equal("awesome#{@newline}", formatted)
276
330
  end
277
331
 
278
332
  def test_format_without_newline
@@ -287,7 +341,7 @@ module FormatterTest
287
341
  formatter.configure('message_key' => 'foobar')
288
342
  formatted = formatter.format('tag', Engine.now, {'foobar' => 'foo'})
289
343
 
290
- assert_equal("foo\n", formatted)
344
+ assert_equal("foo#{@newline}", formatted)
291
345
  end
292
346
  end
293
347
 
data/test/test_output.rb CHANGED
@@ -230,6 +230,11 @@ module FluentOutputTest
230
230
  setup do
231
231
  @time = Time.parse("2011-01-02 13:14:15 UTC")
232
232
  Timecop.freeze(@time)
233
+ @newline = if Fluent.windows?
234
+ "\r\n"
235
+ else
236
+ "\n"
237
+ end
233
238
  end
234
239
 
235
240
  teardown do
@@ -265,7 +270,7 @@ module FluentOutputTest
265
270
  ])
266
271
  time = Time.parse("2016-11-08 12:00:00 UTC").to_i
267
272
  d.emit({"a" => 1}, time)
268
- d.expect_format %[2016-11-08T12:00:00Z\ttest\t{"a":1,"time":"2016-11-08T12:00:00Z"}\n]
273
+ d.expect_format %[2016-11-08T12:00:00Z\ttest\t{"a":1,"time":"2016-11-08T12:00:00Z"}#{@newline}]
269
274
  d.run
270
275
  end
271
276
  end
@@ -8,6 +8,10 @@ require 'net/http'
8
8
  require 'uri'
9
9
  require 'fileutils'
10
10
 
11
+ if Fluent.windows?
12
+ require 'win32/event'
13
+ end
14
+
11
15
  class SupervisorTest < ::Test::Unit::TestCase
12
16
  class DummyServer
13
17
  include Fluent::ServerModule
@@ -107,6 +111,32 @@ class SupervisorTest < ::Test::Unit::TestCase
107
111
  $log.out.reset if $log && $log.out && $log.out.respond_to?(:reset)
108
112
  end
109
113
 
114
+ def test_main_process_command_handlers
115
+ omit "Only for Windows, alternative to UNIX signals" unless Fluent.windows?
116
+
117
+ create_info_dummy_logger
118
+
119
+ opts = Fluent::Supervisor.default_options
120
+ sv = Fluent::Supervisor.new(opts)
121
+ r, w = IO.pipe
122
+ $stdin = r
123
+ sv.send(:install_main_process_signal_handlers)
124
+
125
+ begin
126
+ w.write("GRACEFUL_RESTART\n")
127
+ w.flush
128
+ ensure
129
+ $stdin = STDIN
130
+ end
131
+
132
+ sleep 1
133
+
134
+ info_msg = '[info]: force flushing buffered events' + "\n"
135
+ assert{ $log.out.logs.first.end_with?(info_msg) }
136
+ ensure
137
+ $log.out.reset if $log && $log.out && $log.out.respond_to?(:reset)
138
+ end
139
+
110
140
  def test_supervisor_signal_handler
111
141
  omit "Windows cannot handle signals" if Fluent.windows?
112
142
 
@@ -128,6 +158,60 @@ class SupervisorTest < ::Test::Unit::TestCase
128
158
  $log.out.reset if $log && $log.out && $log.out.respond_to?(:reset)
129
159
  end
130
160
 
161
+ def test_windows_shutdown_event
162
+ omit "Only for Windows platform" unless Fluent.windows?
163
+
164
+ server = DummyServer.new
165
+ def server.config
166
+ {:signame => "TestFluentdEvent"}
167
+ end
168
+
169
+ mock(server).stop(true)
170
+ stub(Process).kill.times(0)
171
+
172
+ server.install_windows_event_handler
173
+ begin
174
+ sleep 0.1 # Wait for starting windows event thread
175
+ event = Win32::Event.open("TestFluentdEvent")
176
+ event.set
177
+ event.close
178
+ ensure
179
+ server.stop_windows_event_thread
180
+ end
181
+
182
+ debug_msg = '[debug]: Got Win32 event "TestFluentdEvent"'
183
+ logs = $log.out.logs
184
+ assert{ logs.any?{|log| log.include?(debug_msg) } }
185
+ ensure
186
+ $log.out.reset if $log && $log.out && $log.out.respond_to?(:reset)
187
+ end
188
+
189
+ def test_supervisor_event_handler
190
+ omit "Only for Windows, alternative to UNIX signals" unless Fluent.windows?
191
+
192
+ create_debug_dummy_logger
193
+
194
+ server = DummyServer.new
195
+ def server.config
196
+ {:signame => "TestFluentdEvent"}
197
+ end
198
+ server.install_windows_event_handler
199
+ begin
200
+ sleep 0.1 # Wait for starting windows event thread
201
+ event = Win32::Event.open("TestFluentdEvent_USR1")
202
+ event.set
203
+ event.close
204
+ ensure
205
+ server.stop_windows_event_thread
206
+ end
207
+
208
+ debug_msg = '[debug]: Got Win32 event "TestFluentdEvent_USR1"'
209
+ logs = $log.out.logs
210
+ assert{ logs.any?{|log| log.include?(debug_msg) } }
211
+ ensure
212
+ $log.out.reset if $log && $log.out && $log.out.respond_to?(:reset)
213
+ end
214
+
131
215
  def test_rpc_server
132
216
  omit "Windows cannot handle signals" if Fluent.windows?
133
217
 
@@ -150,7 +234,7 @@ class SupervisorTest < ::Test::Unit::TestCase
150
234
  server.run_rpc_server
151
235
 
152
236
  sv.send(:install_main_process_signal_handlers)
153
- Net::HTTP.get URI.parse('http://0.0.0.0:24447/api/plugins.flushBuffers')
237
+ response = Net::HTTP.get(URI.parse('http://127.0.0.1:24447/api/plugins.flushBuffers'))
154
238
  info_msg = '[info]: force flushing buffered events' + "\n"
155
239
 
156
240
  server.stop_rpc_server
@@ -159,11 +243,45 @@ class SupervisorTest < ::Test::Unit::TestCase
159
243
  # This test will be passed in such environment.
160
244
  pend unless $log.out.logs.first
161
245
 
246
+ assert_equal('{"ok":true}', response)
162
247
  assert{ $log.out.logs.first.end_with?(info_msg) }
163
248
  ensure
164
249
  $log.out.reset if $log.out.is_a?(Fluent::Test::DummyLogDevice)
165
250
  end
166
251
 
252
+ def test_rpc_server_windows
253
+ omit "Only for windows platform" unless Fluent.windows?
254
+
255
+ create_info_dummy_logger
256
+
257
+ opts = Fluent::Supervisor.default_options
258
+ sv = Fluent::Supervisor.new(opts)
259
+ conf_data = <<-EOC
260
+ <system>
261
+ rpc_endpoint 0.0.0.0:24447
262
+ </system>
263
+ EOC
264
+ conf = Fluent::Config.parse(conf_data, "(test)", "(test_dir)", true)
265
+ sys_conf = sv.__send__(:build_system_config, conf)
266
+
267
+ server = DummyServer.new
268
+ def server.config
269
+ {
270
+ :signame => "TestFluentdEvent",
271
+ :worker_pid => 5963,
272
+ }
273
+ end
274
+ server.rpc_endpoint = sys_conf.rpc_endpoint
275
+
276
+ server.run_rpc_server
277
+
278
+ mock(server).restart(true) { nil }
279
+ response = Net::HTTP.get(URI.parse('http://127.0.0.1:24447/api/plugins.flushBuffers'))
280
+
281
+ server.stop_rpc_server
282
+ assert_equal('{"ok":true}', response)
283
+ end
284
+
167
285
  def test_load_config
168
286
  tmp_dir = "#{TMP_DIR}/dir/test_load_config.conf"
169
287
  conf_info_str = %[
@@ -399,6 +517,37 @@ class SupervisorTest < ::Test::Unit::TestCase
399
517
  assert_equal Fluent::Log::LEVEL_ERROR, $log.level
400
518
  end
401
519
 
520
+ def test_enable_shared_socket
521
+ server = DummyServer.new
522
+ begin
523
+ ENV.delete('SERVERENGINE_SOCKETMANAGER_PATH')
524
+ server.before_run
525
+ sleep 0.1 if Fluent.windows? # Wait for starting windows event thread
526
+ assert_not_nil(ENV['SERVERENGINE_SOCKETMANAGER_PATH'])
527
+ ensure
528
+ server.after_run
529
+ ENV.delete('SERVERENGINE_SOCKETMANAGER_PATH')
530
+ end
531
+ end
532
+
533
+ def test_disable_shared_socket
534
+ server = DummyServer.new
535
+ def server.config
536
+ {
537
+ :disable_shared_socket => true,
538
+ }
539
+ end
540
+ begin
541
+ ENV.delete('SERVERENGINE_SOCKETMANAGER_PATH')
542
+ server.before_run
543
+ sleep 0.1 if Fluent.windows? # Wait for starting windows event thread
544
+ assert_nil(ENV['SERVERENGINE_SOCKETMANAGER_PATH'])
545
+ ensure
546
+ server.after_run
547
+ ENV.delete('SERVERENGINE_SOCKETMANAGER_PATH')
548
+ end
549
+ end
550
+
402
551
  def create_debug_dummy_logger
403
552
  dl_opts = {}
404
553
  dl_opts[:log_level] = ServerEngine::DaemonLogger::DEBUG