fluentd 0.12.43 → 0.14.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of fluentd might be problematic. Click here for more details.

Files changed (253) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE.md +6 -0
  3. data/.gitignore +2 -0
  4. data/.travis.yml +33 -21
  5. data/CONTRIBUTING.md +1 -0
  6. data/ChangeLog +1239 -0
  7. data/README.md +0 -25
  8. data/Rakefile +2 -1
  9. data/Vagrantfile +17 -0
  10. data/appveyor.yml +35 -0
  11. data/example/filter_stdout.conf +5 -5
  12. data/example/in_forward.conf +2 -2
  13. data/example/in_http.conf +2 -2
  14. data/example/in_out_forward.conf +17 -0
  15. data/example/in_syslog.conf +2 -2
  16. data/example/in_tail.conf +2 -2
  17. data/example/in_tcp.conf +2 -2
  18. data/example/in_udp.conf +2 -2
  19. data/example/out_copy.conf +4 -4
  20. data/example/out_file.conf +2 -2
  21. data/example/out_forward.conf +2 -2
  22. data/example/out_forward_buf_file.conf +23 -0
  23. data/example/v0_12_filter.conf +8 -8
  24. data/fluent.conf +29 -0
  25. data/fluentd.gemspec +18 -11
  26. data/lib/fluent/agent.rb +60 -58
  27. data/lib/fluent/command/cat.rb +1 -1
  28. data/lib/fluent/command/debug.rb +7 -5
  29. data/lib/fluent/command/fluentd.rb +97 -2
  30. data/lib/fluent/compat/call_super_mixin.rb +67 -0
  31. data/lib/fluent/compat/filter.rb +50 -0
  32. data/lib/fluent/compat/formatter.rb +109 -0
  33. data/lib/fluent/compat/input.rb +50 -0
  34. data/lib/fluent/compat/output.rb +617 -0
  35. data/lib/fluent/compat/output_chain.rb +60 -0
  36. data/lib/fluent/compat/parser.rb +163 -0
  37. data/lib/fluent/compat/propagate_default.rb +62 -0
  38. data/lib/fluent/config.rb +23 -20
  39. data/lib/fluent/config/configure_proxy.rb +119 -70
  40. data/lib/fluent/config/dsl.rb +5 -18
  41. data/lib/fluent/config/element.rb +72 -8
  42. data/lib/fluent/config/error.rb +0 -3
  43. data/lib/fluent/config/literal_parser.rb +0 -2
  44. data/lib/fluent/config/parser.rb +4 -4
  45. data/lib/fluent/config/section.rb +39 -28
  46. data/lib/fluent/config/types.rb +2 -13
  47. data/lib/fluent/config/v1_parser.rb +1 -3
  48. data/lib/fluent/configurable.rb +48 -16
  49. data/lib/fluent/daemon.rb +15 -0
  50. data/lib/fluent/engine.rb +26 -52
  51. data/lib/fluent/env.rb +6 -4
  52. data/lib/fluent/event.rb +58 -11
  53. data/lib/fluent/event_router.rb +5 -5
  54. data/lib/fluent/filter.rb +2 -50
  55. data/lib/fluent/formatter.rb +4 -293
  56. data/lib/fluent/input.rb +2 -32
  57. data/lib/fluent/label.rb +2 -2
  58. data/lib/fluent/load.rb +3 -2
  59. data/lib/fluent/log.rb +107 -38
  60. data/lib/fluent/match.rb +0 -36
  61. data/lib/fluent/mixin.rb +117 -7
  62. data/lib/fluent/msgpack_factory.rb +62 -0
  63. data/lib/fluent/output.rb +7 -612
  64. data/lib/fluent/output_chain.rb +23 -0
  65. data/lib/fluent/parser.rb +4 -800
  66. data/lib/fluent/plugin.rb +100 -121
  67. data/lib/fluent/plugin/bare_output.rb +63 -0
  68. data/lib/fluent/plugin/base.rb +121 -0
  69. data/lib/fluent/plugin/buf_file.rb +101 -182
  70. data/lib/fluent/plugin/buf_memory.rb +9 -92
  71. data/lib/fluent/plugin/buffer.rb +473 -0
  72. data/lib/fluent/plugin/buffer/chunk.rb +135 -0
  73. data/lib/fluent/plugin/buffer/file_chunk.rb +339 -0
  74. data/lib/fluent/plugin/buffer/memory_chunk.rb +100 -0
  75. data/lib/fluent/plugin/exec_util.rb +80 -75
  76. data/lib/fluent/plugin/file_util.rb +33 -28
  77. data/lib/fluent/plugin/file_wrapper.rb +120 -0
  78. data/lib/fluent/plugin/filter.rb +51 -0
  79. data/lib/fluent/plugin/filter_grep.rb +13 -40
  80. data/lib/fluent/plugin/filter_record_transformer.rb +22 -18
  81. data/lib/fluent/plugin/formatter.rb +93 -0
  82. data/lib/fluent/plugin/formatter_csv.rb +48 -0
  83. data/lib/fluent/plugin/formatter_hash.rb +32 -0
  84. data/lib/fluent/plugin/formatter_json.rb +47 -0
  85. data/lib/fluent/plugin/formatter_ltsv.rb +42 -0
  86. data/lib/fluent/plugin/formatter_msgpack.rb +32 -0
  87. data/lib/fluent/plugin/formatter_out_file.rb +45 -0
  88. data/lib/fluent/plugin/formatter_single_value.rb +34 -0
  89. data/lib/fluent/plugin/formatter_stdout.rb +39 -0
  90. data/lib/fluent/plugin/in_debug_agent.rb +4 -0
  91. data/lib/fluent/plugin/in_dummy.rb +22 -18
  92. data/lib/fluent/plugin/in_exec.rb +18 -8
  93. data/lib/fluent/plugin/in_forward.rb +36 -79
  94. data/lib/fluent/plugin/in_gc_stat.rb +4 -0
  95. data/lib/fluent/plugin/in_http.rb +21 -18
  96. data/lib/fluent/plugin/in_monitor_agent.rb +15 -48
  97. data/lib/fluent/plugin/in_object_space.rb +6 -1
  98. data/lib/fluent/plugin/in_stream.rb +7 -3
  99. data/lib/fluent/plugin/in_syslog.rb +46 -95
  100. data/lib/fluent/plugin/in_tail.rb +58 -640
  101. data/lib/fluent/plugin/in_tcp.rb +8 -1
  102. data/lib/fluent/plugin/in_udp.rb +8 -18
  103. data/lib/fluent/plugin/input.rb +33 -0
  104. data/lib/fluent/plugin/multi_output.rb +95 -0
  105. data/lib/fluent/plugin/out_buffered_null.rb +59 -0
  106. data/lib/fluent/plugin/out_copy.rb +11 -7
  107. data/lib/fluent/plugin/out_exec.rb +15 -11
  108. data/lib/fluent/plugin/out_exec_filter.rb +18 -10
  109. data/lib/fluent/plugin/out_file.rb +34 -5
  110. data/lib/fluent/plugin/out_forward.rb +25 -19
  111. data/lib/fluent/plugin/out_null.rb +0 -14
  112. data/lib/fluent/plugin/out_roundrobin.rb +11 -7
  113. data/lib/fluent/plugin/out_stdout.rb +5 -7
  114. data/lib/fluent/plugin/out_stream.rb +3 -1
  115. data/lib/fluent/plugin/output.rb +979 -0
  116. data/lib/fluent/plugin/owned_by_mixin.rb +42 -0
  117. data/lib/fluent/plugin/parser.rb +244 -0
  118. data/lib/fluent/plugin/parser_apache.rb +24 -0
  119. data/lib/fluent/plugin/parser_apache2.rb +84 -0
  120. data/lib/fluent/plugin/parser_apache_error.rb +21 -0
  121. data/lib/fluent/plugin/parser_csv.rb +31 -0
  122. data/lib/fluent/plugin/parser_json.rb +79 -0
  123. data/lib/fluent/plugin/parser_ltsv.rb +50 -0
  124. data/lib/fluent/plugin/parser_multiline.rb +102 -0
  125. data/lib/fluent/plugin/parser_nginx.rb +24 -0
  126. data/lib/fluent/plugin/parser_none.rb +36 -0
  127. data/lib/fluent/plugin/parser_syslog.rb +82 -0
  128. data/lib/fluent/plugin/parser_tsv.rb +37 -0
  129. data/lib/fluent/plugin/socket_util.rb +119 -117
  130. data/lib/fluent/plugin/storage.rb +84 -0
  131. data/lib/fluent/plugin/storage_local.rb +116 -0
  132. data/lib/fluent/plugin/string_util.rb +16 -13
  133. data/lib/fluent/plugin_helper.rb +39 -0
  134. data/lib/fluent/plugin_helper/child_process.rb +298 -0
  135. data/lib/fluent/plugin_helper/compat_parameters.rb +99 -0
  136. data/lib/fluent/plugin_helper/event_emitter.rb +80 -0
  137. data/lib/fluent/plugin_helper/event_loop.rb +118 -0
  138. data/lib/fluent/plugin_helper/retry_state.rb +177 -0
  139. data/lib/fluent/plugin_helper/storage.rb +308 -0
  140. data/lib/fluent/plugin_helper/thread.rb +147 -0
  141. data/lib/fluent/plugin_helper/timer.rb +85 -0
  142. data/lib/fluent/plugin_id.rb +63 -0
  143. data/lib/fluent/process.rb +21 -30
  144. data/lib/fluent/registry.rb +21 -9
  145. data/lib/fluent/root_agent.rb +115 -40
  146. data/lib/fluent/supervisor.rb +330 -320
  147. data/lib/fluent/system_config.rb +42 -18
  148. data/lib/fluent/test.rb +6 -1
  149. data/lib/fluent/test/base.rb +23 -3
  150. data/lib/fluent/test/driver/base.rb +247 -0
  151. data/lib/fluent/test/driver/event_feeder.rb +98 -0
  152. data/lib/fluent/test/driver/filter.rb +35 -0
  153. data/lib/fluent/test/driver/input.rb +31 -0
  154. data/lib/fluent/test/driver/output.rb +78 -0
  155. data/lib/fluent/test/driver/test_event_router.rb +45 -0
  156. data/lib/fluent/test/filter_test.rb +0 -1
  157. data/lib/fluent/test/formatter_test.rb +2 -1
  158. data/lib/fluent/test/input_test.rb +23 -17
  159. data/lib/fluent/test/output_test.rb +28 -39
  160. data/lib/fluent/test/parser_test.rb +1 -1
  161. data/lib/fluent/time.rb +104 -1
  162. data/lib/fluent/{status.rb → unique_id.rb} +15 -24
  163. data/lib/fluent/version.rb +1 -1
  164. data/lib/fluent/winsvc.rb +72 -0
  165. data/test/compat/test_calls_super.rb +164 -0
  166. data/test/config/test_config_parser.rb +83 -0
  167. data/test/config/test_configurable.rb +547 -274
  168. data/test/config/test_configure_proxy.rb +146 -29
  169. data/test/config/test_dsl.rb +3 -181
  170. data/test/config/test_element.rb +274 -0
  171. data/test/config/test_literal_parser.rb +1 -1
  172. data/test/config/test_section.rb +79 -7
  173. data/test/config/test_system_config.rb +21 -0
  174. data/test/config/test_types.rb +3 -26
  175. data/test/helper.rb +78 -8
  176. data/test/plugin/test_bare_output.rb +118 -0
  177. data/test/plugin/test_base.rb +75 -0
  178. data/test/plugin/test_buf_file.rb +420 -521
  179. data/test/plugin/test_buf_memory.rb +32 -194
  180. data/test/plugin/test_buffer.rb +981 -0
  181. data/test/plugin/test_buffer_chunk.rb +110 -0
  182. data/test/plugin/test_buffer_file_chunk.rb +770 -0
  183. data/test/plugin/test_buffer_memory_chunk.rb +265 -0
  184. data/test/plugin/test_filter.rb +255 -0
  185. data/test/plugin/test_filter_grep.rb +2 -73
  186. data/test/plugin/test_filter_record_transformer.rb +24 -68
  187. data/test/plugin/test_filter_stdout.rb +6 -6
  188. data/test/plugin/test_in_debug_agent.rb +2 -0
  189. data/test/plugin/test_in_dummy.rb +11 -17
  190. data/test/plugin/test_in_exec.rb +6 -25
  191. data/test/plugin/test_in_forward.rb +112 -151
  192. data/test/plugin/test_in_gc_stat.rb +2 -0
  193. data/test/plugin/test_in_http.rb +106 -157
  194. data/test/plugin/test_in_object_space.rb +21 -5
  195. data/test/plugin/test_in_stream.rb +14 -13
  196. data/test/plugin/test_in_syslog.rb +30 -275
  197. data/test/plugin/test_in_tail.rb +95 -282
  198. data/test/plugin/test_in_tcp.rb +14 -0
  199. data/test/plugin/test_in_udp.rb +21 -67
  200. data/test/plugin/test_input.rb +122 -0
  201. data/test/plugin/test_multi_output.rb +180 -0
  202. data/test/plugin/test_out_buffered_null.rb +79 -0
  203. data/test/plugin/test_out_copy.rb +15 -2
  204. data/test/plugin/test_out_exec.rb +75 -25
  205. data/test/plugin/test_out_exec_filter.rb +74 -8
  206. data/test/plugin/test_out_file.rb +61 -7
  207. data/test/plugin/test_out_forward.rb +92 -15
  208. data/test/plugin/test_out_roundrobin.rb +1 -0
  209. data/test/plugin/test_out_stdout.rb +22 -13
  210. data/test/plugin/test_out_stream.rb +18 -0
  211. data/test/plugin/test_output.rb +515 -0
  212. data/test/plugin/test_output_as_buffered.rb +1540 -0
  213. data/test/plugin/test_output_as_buffered_overflow.rb +247 -0
  214. data/test/plugin/test_output_as_buffered_retries.rb +808 -0
  215. data/test/plugin/test_output_as_buffered_secondary.rb +776 -0
  216. data/test/plugin/test_output_as_standard.rb +362 -0
  217. data/test/plugin/test_owned_by.rb +35 -0
  218. data/test/plugin/test_storage.rb +167 -0
  219. data/test/plugin/test_storage_local.rb +8 -0
  220. data/test/plugin_helper/test_child_process.rb +599 -0
  221. data/test/plugin_helper/test_compat_parameters.rb +175 -0
  222. data/test/plugin_helper/test_event_emitter.rb +51 -0
  223. data/test/plugin_helper/test_event_loop.rb +52 -0
  224. data/test/plugin_helper/test_retry_state.rb +399 -0
  225. data/test/plugin_helper/test_storage.rb +411 -0
  226. data/test/plugin_helper/test_thread.rb +164 -0
  227. data/test/plugin_helper/test_timer.rb +100 -0
  228. data/test/scripts/exec_script.rb +0 -6
  229. data/test/scripts/fluent/plugin/out_test.rb +3 -0
  230. data/test/test_config.rb +13 -4
  231. data/test/test_event.rb +24 -13
  232. data/test/test_event_router.rb +8 -7
  233. data/test/test_event_time.rb +187 -0
  234. data/test/test_formatter.rb +13 -51
  235. data/test/test_input.rb +1 -1
  236. data/test/test_log.rb +239 -16
  237. data/test/test_mixin.rb +1 -1
  238. data/test/test_output.rb +53 -66
  239. data/test/test_parser.rb +105 -323
  240. data/test/test_plugin_helper.rb +81 -0
  241. data/test/test_root_agent.rb +4 -52
  242. data/test/test_supervisor.rb +272 -0
  243. data/test/test_unique_id.rb +47 -0
  244. metadata +181 -55
  245. data/CHANGELOG.md +0 -710
  246. data/lib/fluent/buffer.rb +0 -365
  247. data/lib/fluent/plugin/filter_parser.rb +0 -107
  248. data/lib/fluent/plugin/in_status.rb +0 -76
  249. data/lib/fluent/test/helpers.rb +0 -86
  250. data/test/plugin/data/log/foo/bar2 +0 -0
  251. data/test/plugin/test_filter_parser.rb +0 -744
  252. data/test/plugin/test_in_status.rb +0 -38
  253. data/test/test_buffer.rb +0 -624
@@ -15,34 +15,25 @@
15
15
  #
16
16
 
17
17
  module Fluent
18
- class StatusClass
19
- def initialize
20
- @entries = {}
21
- @mutex = Mutex.new
18
+ module UniqueId
19
+ def self.generate
20
+ now = Time.now.utc
21
+ u1 = ((now.to_i * 1000 * 1000 + now.usec) << 12 | rand(0xfff))
22
+ [u1 >> 32, u1 & 0xffffffff, rand(0xffffffff), rand(0xffffffff)].pack('NNNN')
22
23
  end
23
24
 
24
- def register(instance, name, &block)
25
- @mutex.synchronize {
26
- (@entries[instance.object_id] ||= {})[name] = block
27
- }
28
- nil
25
+ def self.hex(unique_id)
26
+ unique_id.unpack('H*').first
29
27
  end
30
28
 
31
- def each(&block)
32
- @mutex.synchronize {
33
- @entries.each {|obj_id,hash|
34
- record = {}
35
- hash.each_pair {|name,block|
36
- record[name] = block.call
37
- }
38
- block.call(record)
39
- }
40
- }
29
+ module Mixin
30
+ def generate_unique_id
31
+ Fluent::UniqueId.generate
32
+ end
33
+
34
+ def dump_unique_id_hex(unique_id)
35
+ Fluent::UniqueId.hex(unique_id)
36
+ end
41
37
  end
42
38
  end
43
-
44
- # Don't use this class from plugins.
45
- # The interface may be changed
46
- Status = StatusClass.new
47
39
  end
48
-
@@ -16,6 +16,6 @@
16
16
 
17
17
  module Fluent
18
18
 
19
- VERSION = '0.12.43'
19
+ VERSION = '0.14.0'
20
20
 
21
21
  end
@@ -0,0 +1,72 @@
1
+ #
2
+ # Fluentd
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ INTEVENTOBJ_NAME = "fluentdwinsvc"
18
+
19
+ begin
20
+
21
+ require 'windows/debug'
22
+ require 'Windows/Library'
23
+ require 'win32/daemon'
24
+ require 'win32/event'
25
+
26
+ include Win32
27
+ include Windows::Library
28
+ include Windows::Debug
29
+
30
+ def read_fluentdopt
31
+ require 'win32/Registry'
32
+ Win32::Registry::HKEY_LOCAL_MACHINE.open("SYSTEM\\CurrentControlSet\\Services\\fluentdwinsvc") do |reg|
33
+ reg.read("fluentdopt")[1]
34
+ end
35
+ end
36
+
37
+ def service_main_start
38
+ ruby_path = 0.chr * 260
39
+ GetModuleFileName.call(0, ruby_path,260)
40
+ ruby_path = ruby_path.rstrip.gsub(/\\/, '/')
41
+ rubybin_dir = ruby_path[0, ruby_path.rindex("/")]
42
+ opt = read_fluentdopt
43
+ Process.spawn(rubybin_dir + "/ruby.exe " + rubybin_dir + "/fluentd " + opt + " -x " + INTEVENTOBJ_NAME)
44
+ end
45
+
46
+ class FluentdService < Daemon
47
+ @pid = 0
48
+
49
+ def service_main
50
+ opt = read_fluentdopt
51
+ @pid = service_main_start
52
+ while running?
53
+ sleep 10
54
+ end
55
+ end
56
+
57
+ def service_stop
58
+ ev = Win32::Event.open(INTEVENTOBJ_NAME)
59
+ ev.set
60
+ ev.close
61
+ if @pid > 0
62
+ Porcess.waitpid(@pid)
63
+ end
64
+ end
65
+ end
66
+
67
+ FluentdService.mainloop
68
+
69
+ rescue Exception => err
70
+ raise
71
+ end
72
+
@@ -0,0 +1,164 @@
1
+ require_relative '../helper'
2
+
3
+ # these are Fluent::Compat::* in fact
4
+ require 'fluent/input'
5
+ require 'fluent/output'
6
+ require 'fluent/filter'
7
+
8
+ class CompatCallsSuperTest < Test::Unit::TestCase
9
+ class DummyGoodInput < Fluent::Input
10
+ def configure(conf); super; end
11
+ def start; super; end
12
+ def before_shutdown; super; end
13
+ def shutdown; super; end
14
+ end
15
+ class DummyBadInput < Fluent::Input
16
+ def configure(conf); super; end
17
+ def start; end
18
+ def before_shutdown; end
19
+ def shutdown; end
20
+ end
21
+ class DummyGoodOutput < Fluent::Output
22
+ def configure(conf); super; end
23
+ def start; super; end
24
+ def before_shutdown; super; end
25
+ def shutdown; super; end
26
+ end
27
+ class DummyBadOutput < Fluent::Output
28
+ def configure(conf); super; end
29
+ def start; end
30
+ def before_shutdown; end
31
+ def shutdown; end
32
+ end
33
+ class DummyGoodFilter < Fluent::Filter
34
+ def configure(conf); super; end
35
+ def start; super; end
36
+ def before_shutdown; super; end
37
+ def shutdown; super; end
38
+ end
39
+ class DummyBadFilter < Fluent::Filter
40
+ def configure(conf); super; end
41
+ def start; end
42
+ def before_shutdown; end
43
+ def shutdown; end
44
+ end
45
+
46
+ setup do
47
+ Fluent::Test.setup
48
+ end
49
+
50
+ sub_test_case 'old API plugin which calls super properly' do
51
+ test 'Input#start, #before_shutdown and #shutdown calls all superclass methods properly' do
52
+ i = DummyGoodInput.new
53
+ i.configure(config_element())
54
+ assert i.configured?
55
+
56
+ i.start
57
+ assert i.started?
58
+
59
+ i.before_shutdown
60
+ assert i.before_shutdown?
61
+
62
+ i.shutdown
63
+ assert i.shutdown?
64
+
65
+ assert i.log.out.logs.empty?
66
+ end
67
+
68
+ test 'Output#start, #before_shutdown and #shutdown calls all superclass methods properly' do
69
+ i = DummyGoodOutput.new
70
+ i.configure(config_element())
71
+ assert i.configured?
72
+
73
+ i.start
74
+ assert i.started?
75
+
76
+ i.before_shutdown
77
+ assert i.before_shutdown?
78
+
79
+ i.shutdown
80
+ assert i.shutdown?
81
+
82
+ assert i.log.out.logs.empty?
83
+ end
84
+
85
+ test 'Filter#start, #before_shutdown and #shutdown calls all superclass methods properly' do
86
+ i = DummyGoodFilter.new
87
+ i.configure(config_element())
88
+ assert i.configured?
89
+
90
+ i.start
91
+ assert i.started?
92
+
93
+ i.before_shutdown
94
+ assert i.before_shutdown?
95
+
96
+ i.shutdown
97
+ assert i.shutdown?
98
+
99
+ assert i.log.out.logs.empty?
100
+ end
101
+ end
102
+
103
+ sub_test_case 'old API plugin which does not call super' do
104
+ test 'Input#start, #before_shutdown and #shutdown calls superclass methods forcedly with logs' do
105
+ i = DummyBadInput.new
106
+ i.configure(config_element())
107
+ assert i.configured?
108
+
109
+ i.start
110
+ assert i.started?
111
+
112
+ i.before_shutdown
113
+ assert i.before_shutdown?
114
+
115
+ i.shutdown
116
+ assert i.shutdown?
117
+
118
+ logs = i.log.out.logs
119
+ assert{ logs.any?{|l| l.include?("[warn]: super was not called in #start: called it forcedly plugin=CompatCallsSuperTest::DummyBadInput") } }
120
+ assert{ logs.any?{|l| l.include?("[warn]: super was not called in #before_shutdown: calling it forcedly plugin=CompatCallsSuperTest::DummyBadInput") } }
121
+ assert{ logs.any?{|l| l.include?("[warn]: super was not called in #shutdown: calling it forcedly plugin=CompatCallsSuperTest::DummyBadInput") } }
122
+ end
123
+
124
+ test 'Output#start, #before_shutdown and #shutdown calls superclass methods forcedly with logs' do
125
+ i = DummyBadOutput.new
126
+ i.configure(config_element())
127
+ assert i.configured?
128
+
129
+ i.start
130
+ assert i.started?
131
+
132
+ i.before_shutdown
133
+ assert i.before_shutdown?
134
+
135
+ i.shutdown
136
+ assert i.shutdown?
137
+
138
+ logs = i.log.out.logs
139
+ assert{ logs.any?{|l| l.include?("[warn]: super was not called in #start: called it forcedly plugin=CompatCallsSuperTest::DummyBadOutput") } }
140
+ assert{ logs.any?{|l| l.include?("[warn]: super was not called in #before_shutdown: calling it forcedly plugin=CompatCallsSuperTest::DummyBadOutput") } }
141
+ assert{ logs.any?{|l| l.include?("[warn]: super was not called in #shutdown: calling it forcedly plugin=CompatCallsSuperTest::DummyBadOutput") } }
142
+ end
143
+
144
+ test 'Filter#start, #before_shutdown and #shutdown calls superclass methods forcedly with logs' do
145
+ i = DummyBadFilter.new
146
+ i.configure(config_element())
147
+ assert i.configured?
148
+
149
+ i.start
150
+ assert i.started?
151
+
152
+ i.before_shutdown
153
+ assert i.before_shutdown?
154
+
155
+ i.shutdown
156
+ assert i.shutdown?
157
+
158
+ logs = i.log.out.logs
159
+ assert{ logs.any?{|l| l.include?("[warn]: super was not called in #start: called it forcedly plugin=CompatCallsSuperTest::DummyBadFilter") } }
160
+ assert{ logs.any?{|l| l.include?("[warn]: super was not called in #before_shutdown: calling it forcedly plugin=CompatCallsSuperTest::DummyBadFilter") } }
161
+ assert{ logs.any?{|l| l.include?("[warn]: super was not called in #shutdown: calling it forcedly plugin=CompatCallsSuperTest::DummyBadFilter") } }
162
+ end
163
+ end
164
+ end
@@ -23,6 +23,20 @@ module Fluent::Config
23
23
  end
24
24
  end
25
25
 
26
+ class AllTypes
27
+ include Fluent::Configurable
28
+
29
+ config_param :param_string, :string
30
+ config_param :param_enum, :enum, list: [:foo, :bar, :baz]
31
+ config_param :param_integer, :integer
32
+ config_param :param_float, :float
33
+ config_param :param_size, :size
34
+ config_param :param_bool, :bool
35
+ config_param :param_time, :time
36
+ config_param :param_hash, :hash
37
+ config_param :param_array, :array
38
+ end
39
+
26
40
  class TestV1Parser < ::Test::Unit::TestCase
27
41
  def read_config(path)
28
42
  path = File.expand_path(path)
@@ -419,6 +433,75 @@ module Fluent::Config
419
433
  conf2 = parse_text(conf.to_s) # use dumpped configuration to check unescape
420
434
  assert_equal(expected, conf2.elements.first['k1'])
421
435
  end
436
+
437
+ test 'all types' do
438
+ conf = parse_text(%[
439
+ param_string "value"
440
+ param_enum foo
441
+ param_integer 999
442
+ param_float 55.55
443
+ param_size 4k
444
+ param_bool true
445
+ param_time 10m
446
+ param_hash { "key1": "value1", "key2": 2 }
447
+ param_array ["value1", "value2", 100]
448
+ ])
449
+ target = AllTypes.new.configure(conf)
450
+ assert_equal(conf.to_s, target.config.to_s)
451
+ expected = <<DUMP
452
+ <ROOT>
453
+ param_string "value"
454
+ param_enum foo
455
+ param_integer 999
456
+ param_float 55.55
457
+ param_size 4k
458
+ param_bool true
459
+ param_time 10m
460
+ param_hash {"key1":"value1","key2":2}
461
+ param_array ["value1","value2",100]
462
+ </ROOT>
463
+ DUMP
464
+ assert_equal(expected, conf.to_s)
465
+ end
466
+ end
467
+ end
468
+
469
+ class TestV0Parser < ::Test::Unit::TestCase
470
+ def parse_text(text)
471
+ basepath = File.expand_path(File.dirname(__FILE__) + '/../../')
472
+ Fluent::Config::Parser.parse(StringIO.new(text), '(test)', basepath)
473
+ end
474
+
475
+ sub_test_case "Fluent::Config::Element#to_s" do
476
+ test 'all types' do
477
+ conf = parse_text(%[
478
+ param_string value
479
+ param_enum foo
480
+ param_integer 999
481
+ param_float 55.55
482
+ param_size 4k
483
+ param_bool true
484
+ param_time 10m
485
+ param_hash { "key1": "value1", "key2": 2 }
486
+ param_array ["value1", "value2", 100]
487
+ ])
488
+ target = AllTypes.new.configure(conf)
489
+ assert_equal(conf.to_s, target.config.to_s)
490
+ expected = <<DUMP
491
+ <ROOT>
492
+ param_string value
493
+ param_enum foo
494
+ param_integer 999
495
+ param_float 55.55
496
+ param_size 4k
497
+ param_bool true
498
+ param_time 10m
499
+ param_hash { "key1": "value1", "key2": 2 }
500
+ param_array ["value1", "value2", 100]
501
+ </ROOT>
502
+ DUMP
503
+ assert_equal(expected, conf.to_s)
504
+ end
422
505
  end
423
506
  end
424
507
  end
@@ -89,6 +89,16 @@ module ConfigurableSpec
89
89
  end
90
90
  end
91
91
 
92
+ class Init0
93
+ include Fluent::Configurable
94
+ config_section :sec1, init: true, multi: false do
95
+ config_param :name, :string, default: 'sec1'
96
+ end
97
+ config_section :sec2, init: true, multi: true do
98
+ config_param :name, :string, default: 'sec1'
99
+ end
100
+ end
101
+
92
102
  class Example0
93
103
  include Fluent::Configurable
94
104
 
@@ -116,13 +126,6 @@ module ConfigurableSpec
116
126
  end
117
127
  end
118
128
 
119
- class Example2 < Example1
120
- config_section :detail, required: true, multi: false, alias: "information2" do
121
- config_param :address, :string, default: "y"
122
- config_param :phone_no, :string
123
- end
124
- end
125
-
126
129
  class Example3
127
130
  include Fluent::Configurable
128
131
 
@@ -138,15 +141,6 @@ module ConfigurableSpec
138
141
  end
139
142
  end
140
143
 
141
- class Example4 < Example3
142
- config_param :age, :integer, default: 20
143
-
144
- config_section :appendix, required: false, multi: false, final: false do
145
- config_param :name, :string, default: "y"
146
- config_param :age, :integer, default: 10
147
- end
148
- end
149
-
150
144
  class Example5
151
145
  include Fluent::Configurable
152
146
 
@@ -159,11 +153,194 @@ module ConfigurableSpec
159
153
  end
160
154
  end
161
155
 
162
- class UnRecommended
156
+ class Example6
163
157
  include Fluent::Configurable
164
- attr_accessor :log
165
- config_param :key1, :string, default: 'deprecated', deprecated: "key1 will be removed."
166
- config_param :key2, :string, default: 'obsoleted', obsoleted: "key2 has been removed."
158
+ config_param :obj1, :hash, default: {}
159
+ config_param :obj2, :array, default: []
160
+ end
161
+
162
+ module Overwrite
163
+ class Base
164
+ include Fluent::Configurable
165
+
166
+ config_param :name, :string, alias: :fullname
167
+ config_param :bool, :bool, alias: :flag
168
+ config_section :detail, required: false, multi: false, alias: "information" do
169
+ config_param :address, :string, default: "x"
170
+ end
171
+ end
172
+
173
+ class Required < Base
174
+ config_section :detail, required: true do
175
+ config_param :address, :string, default: "x"
176
+ end
177
+ end
178
+
179
+ class Multi < Base
180
+ config_section :detail, multi: true do
181
+ config_param :address, :string, default: "x"
182
+ end
183
+ end
184
+
185
+ class Alias < Base
186
+ config_section :detail, alias: "information2" do
187
+ config_param :address, :string, default: "x"
188
+ end
189
+ end
190
+
191
+ class DefaultOptions < Base
192
+ config_section :detail do
193
+ config_param :address, :string, default: "x"
194
+ end
195
+ end
196
+
197
+ class DetailAddressDefault < Base
198
+ config_section :detail do
199
+ config_param :address, :string, default: "y"
200
+ end
201
+ end
202
+
203
+ class AddParam < Base
204
+ config_section :detail do
205
+ config_param :phone_no, :string
206
+ end
207
+ end
208
+
209
+ class AddParamOverwriteAddress < Base
210
+ config_section :detail do
211
+ config_param :address, :string, default: "y"
212
+ config_param :phone_no, :string
213
+ end
214
+ end
215
+ end
216
+
217
+ module Final
218
+ # Show what is allowed in finalized sections
219
+ # InheritsFinalized < Finalized < Base
220
+ class Base
221
+ include Fluent::Configurable
222
+ config_section :appendix, multi: false, final: false do
223
+ config_param :code, :string
224
+ config_param :name, :string
225
+ config_param :address, :string, default: ""
226
+ end
227
+ end
228
+
229
+ class Finalized < Base
230
+ # to non-finalized section
231
+ # subclass can change type (code)
232
+ # add default value (name)
233
+ # change default value (address)
234
+ # add field (age)
235
+ config_section :appendix, final: true do
236
+ config_param :code, :integer
237
+ config_set_default :name, "y"
238
+ config_set_default :address, "-"
239
+ config_param :age, :integer, default: 10
240
+ end
241
+ end
242
+
243
+ class InheritsFinalized < Finalized
244
+ # to finalized section
245
+ # subclass can add default value (code)
246
+ # change default value (age)
247
+ # add field (phone_no)
248
+ config_section :appendix do
249
+ config_set_default :code, 2
250
+ config_set_default :age, 0
251
+ config_param :phone_no, :string
252
+ end
253
+ end
254
+
255
+ # Show what is allowed/prohibited for finalized sections
256
+ class FinalizedBase
257
+ include Fluent::Configurable
258
+ config_section :appendix, param_name: :apd, init: false, required: true, multi: false, alias: "options", final: true do
259
+ config_param :name, :string
260
+ end
261
+ end
262
+
263
+ class FinalizedBase2
264
+ include Fluent::Configurable
265
+ config_section :appendix, param_name: :apd, init: false, required: false, multi: false, alias: "options", final: true do
266
+ config_param :name, :string
267
+ end
268
+ end
269
+
270
+ # subclass can change init with adding default values
271
+ class OverwriteInit < FinalizedBase2
272
+ config_section :appendix, init: true do
273
+ config_set_default :name, "moris"
274
+ config_param :code, :integer, default: 0
275
+ end
276
+ end
277
+
278
+ # subclass cannot change type (name)
279
+ class Subclass < FinalizedBase
280
+ config_section :appendix do
281
+ config_param :name, :integer
282
+ end
283
+ end
284
+
285
+ # subclass cannot change param_name
286
+ class OverwriteParamName < FinalizedBase
287
+ config_section :appendix, param_name: :adx do
288
+ end
289
+ end
290
+
291
+ # subclass cannot change final (section)
292
+ class OverwriteFinal < FinalizedBase
293
+ config_section :appendix, final: false do
294
+ config_param :name, :integer
295
+ end
296
+ end
297
+
298
+ # subclass cannot change required
299
+ class OverwriteRequired < FinalizedBase
300
+ config_section :appendix, required: false do
301
+ end
302
+ end
303
+
304
+ # subclass cannot change multi
305
+ class OverwriteMulti < FinalizedBase
306
+ config_section :appendix, multi: true do
307
+ end
308
+ end
309
+
310
+ # subclass cannot change alias
311
+ class OverwriteAlias < FinalizedBase
312
+ config_section :appendix, alias: "options2" do
313
+ end
314
+ end
315
+ end
316
+
317
+ module OverwriteDefaults
318
+ class Owner
319
+ include Fluent::Configurable
320
+ config_set_default :key1, "V1"
321
+ config_section :buffer do
322
+ config_set_default :size_of_something, 1024
323
+ end
324
+ end
325
+
326
+ class SubOwner < Owner
327
+ config_section :buffer do
328
+ config_set_default :size_of_something, 2048
329
+ end
330
+ end
331
+
332
+ class FlatChild
333
+ include Fluent::Configurable
334
+ attr_accessor :owner
335
+ config_param :key1, :string, default: "v1"
336
+ end
337
+
338
+ class BufferChild
339
+ include Fluent::Configurable
340
+ attr_accessor :owner
341
+ configured_in :buffer
342
+ config_param :size_of_something, :size, default: 128
343
+ end
167
344
  end
168
345
  end
169
346
 
@@ -201,22 +378,18 @@ module Fluent::Config
201
378
  end
202
379
 
203
380
  sub_test_case '#configure' do
204
- def e(attrs)
205
- Fluent::Config::Element.new('', '', attrs, [])
206
- end
207
-
208
381
  test 'returns configurable object itself' do
209
382
  b2 = ConfigurableSpec::Base2.new
210
- assert_instance_of(ConfigurableSpec::Base2, b2.configure(e({"name1" => "t1", "name5" => "t5", "opt3" => "a"})))
383
+ assert_instance_of(ConfigurableSpec::Base2, b2.configure(config_element("", "", {"name1" => "t1", "name5" => "t5", "opt3" => "a"})))
211
384
  end
212
385
 
213
386
  test 'raise errors without any specifications for param without defaults' do
214
387
  b2 = ConfigurableSpec::Base2.new
215
- assert_raise(Fluent::ConfigError) { b2.configure(e({})) }
216
- assert_raise(Fluent::ConfigError) { b2.configure(e({"name1" => "t1"})) }
217
- assert_raise(Fluent::ConfigError) { b2.configure(e({"name5" => "t5"})) }
218
- assert_raise(Fluent::ConfigError) { b2.configure(e({"name1" => "t1", "name5" => "t5"})) }
219
- assert_nothing_raised { b2.configure(e({"name1" => "t1", "name5" => "t5", "opt3" => "a"})) }
388
+ assert_raise(Fluent::ConfigError) { b2.configure(config_element("", "", {})) }
389
+ assert_raise(Fluent::ConfigError) { b2.configure(config_element("", "", {"name1" => "t1"})) }
390
+ assert_raise(Fluent::ConfigError) { b2.configure(config_element("", "", {"name5" => "t5"})) }
391
+ assert_raise(Fluent::ConfigError) { b2.configure(config_element("", "", {"name1" => "t1", "name5" => "t5"})) }
392
+ assert_nothing_raised { b2.configure(config_element("", "", {"name1" => "t1", "name5" => "t5", "opt3" => "a"})) }
220
393
 
221
394
  assert_equal(["node", false, true, "t1", "base2", "base1", "base2", "t5", "base2"], b2.get_all)
222
395
  assert_equal(:a, b2.opt3)
@@ -224,19 +397,19 @@ module Fluent::Config
224
397
 
225
398
  test 'can configure bool values' do
226
399
  b2a = ConfigurableSpec::Base2.new
227
- assert_nothing_raised { b2a.configure(e({"flag1" => "true", "flag2" => "yes", "name1" => "t1", "name5" => "t5", "opt3" => "a"})) }
400
+ assert_nothing_raised { b2a.configure(config_element("", "", {"flag1" => "true", "flag2" => "yes", "name1" => "t1", "name5" => "t5", "opt3" => "a"})) }
228
401
  assert_true(b2a.flag1)
229
402
  assert_true(b2a.flag2)
230
403
 
231
404
  b2b = ConfigurableSpec::Base2.new
232
- assert_nothing_raised { b2b.configure(e({"flag1" => false, "flag2" => "no", "name1" => "t1", "name5" => "t5", "opt3" => "a"})) }
405
+ assert_nothing_raised { b2b.configure(config_element("", "", {"flag1" => false, "flag2" => "no", "name1" => "t1", "name5" => "t5", "opt3" => "a"})) }
233
406
  assert_false(b2b.flag1)
234
407
  assert_false(b2b.flag2)
235
408
  end
236
409
 
237
410
  test 'overwrites values of defaults' do
238
411
  b2 = ConfigurableSpec::Base2.new
239
- b2.configure(e({"name1" => "t1", "name2" => "t2", "name3" => "t3", "name4" => "t4", "name5" => "t5", "opt1" => "foo", "opt3" => "b"}))
412
+ b2.configure(config_element("", "", {"name1" => "t1", "name2" => "t2", "name3" => "t3", "name4" => "t4", "name5" => "t5", "opt1" => "foo", "opt3" => "b"}))
240
413
  assert_equal("t1", b2.name1)
241
414
  assert_equal("t2", b2.name2)
242
415
  assert_equal("t3", b2.name3)
@@ -250,7 +423,7 @@ module Fluent::Config
250
423
  end
251
424
 
252
425
  test 'enum type rejects values which does not exist in list' do
253
- default = e({"name1" => "t1", "name2" => "t2", "name3" => "t3", "name4" => "t4", "name5" => "t5", "opt1" => "foo", "opt3" => "b"})
426
+ default = config_element("", "", {"name1" => "t1", "name2" => "t2", "name3" => "t3", "name4" => "t4", "name5" => "t5", "opt1" => "foo", "opt3" => "b"})
254
427
 
255
428
  b2 = ConfigurableSpec::Base2.new
256
429
  assert_nothing_raised { b2.configure(default) }
@@ -258,6 +431,37 @@ module Fluent::Config
258
431
  assert_raise(Fluent::ConfigError) { b2.configure(default.merge({"opt2" => "fooooooo"})) }
259
432
  assert_raise(Fluent::ConfigError) { b2.configure(default.merge({"opt3" => "c"})) }
260
433
  end
434
+
435
+ sub_test_case 'default values should be duplicated before touched in plugin code' do
436
+ test 'default object should be dupped for cases configured twice' do
437
+ x6a = ConfigurableSpec::Example6.new
438
+ assert_nothing_raised { x6a.configure(config_element("")) }
439
+ assert_equal({}, x6a.obj1)
440
+ assert_equal([], x6a.obj2)
441
+
442
+ x6b = ConfigurableSpec::Example6.new
443
+ assert_nothing_raised { x6b.configure(config_element("")) }
444
+ assert_equal({}, x6b.obj1)
445
+ assert_equal([], x6b.obj2)
446
+
447
+ assert { x6a.obj1.object_id != x6b.obj1.object_id }
448
+ assert { x6a.obj2.object_id != x6b.obj2.object_id }
449
+
450
+ x6c = ConfigurableSpec::Example6.new
451
+ assert_nothing_raised { x6c.configure(config_element("")) }
452
+ assert_equal({}, x6c.obj1)
453
+ assert_equal([], x6c.obj2)
454
+
455
+ x6c.obj1['k'] = 'v'
456
+ x6c.obj2 << 'v'
457
+
458
+ assert_equal({'k' => 'v'}, x6c.obj1)
459
+ assert_equal(['v'], x6c.obj2)
460
+
461
+ assert_equal({}, x6a.obj1)
462
+ assert_equal([], x6a.obj2)
463
+ end
464
+ end
261
465
  end
262
466
  end
263
467
 
@@ -293,12 +497,6 @@ module Fluent::Config
293
497
  end
294
498
 
295
499
  sub_test_case '#configure' do
296
- def e(name, arg = '', attrs = {}, elements = [])
297
- attrs_str_keys = {}
298
- attrs.each{|key, value| attrs_str_keys[key.to_s] = value }
299
- config_element(name, arg, attrs_str_keys, elements)
300
- end
301
-
302
500
  BASE_ATTRS = {
303
501
  "name1" => "1", "name2" => "2", "name3" => "3",
304
502
  "name4" => "4", "name5" => "5", "name6" => "6",
@@ -306,68 +504,68 @@ module Fluent::Config
306
504
  test 'checks required subsections' do
307
505
  b3 = ConfigurableSpec::Base3.new
308
506
  # branch sections required
309
- assert_raise(Fluent::ConfigError) { b3.configure(e('ROOT', '', BASE_ATTRS, [])) }
507
+ assert_raise(Fluent::ConfigError) { b3.configure(config_element('ROOT', '', BASE_ATTRS, [])) }
310
508
 
311
509
  # branch argument required
312
510
  msg = "'<branch ARG>' section requires argument, in section branch"
313
511
  #expect{ b3.configure(e('ROOT', '', BASE_ATTRS, [e('branch', '')])) }.to raise_error(Fluent::ConfigError, msg)
314
- assert_raise(Fluent::ConfigError.new(msg)) { b3.configure(e('ROOT', '', BASE_ATTRS, [e('branch', '')])) }
512
+ assert_raise(Fluent::ConfigError.new(msg)) { b3.configure(config_element('ROOT', '', BASE_ATTRS, [config_element('branch', '')])) }
315
513
 
316
514
  # leaf is not required
317
- assert_nothing_raised { b3.configure(e('ROOT', '', BASE_ATTRS, [e('branch', 'branch_name')])) }
515
+ assert_nothing_raised { b3.configure(config_element('ROOT', '', BASE_ATTRS, [config_element('branch', 'branch_name')])) }
318
516
 
319
517
  # leaf weight required
320
518
  msg = "'weight' parameter is required, in section branch > leaf"
321
- branch1 = e('branch', 'branch_name', {size: 1}, [e('leaf', '10', {weight: 1})])
322
- assert_nothing_raised { b3.configure(e('ROOT', '', BASE_ATTRS, [branch1])) }
323
- branch2 = e('branch', 'branch_name', {size: 1}, [e('leaf', '20')])
324
- assert_raise(Fluent::ConfigError.new(msg)) { b3.configure(e('ROOT', '', BASE_ATTRS, [branch1, branch2])) }
325
- branch3 = e('branch', 'branch_name', {size: 1}, [e('leaf', '10', {weight: 3}), e('leaf', '20')])
326
- assert_raise(Fluent::ConfigError.new(msg)) { b3.configure(e('ROOT', '', BASE_ATTRS, [branch3])) }
519
+ branch1 = config_element('branch', 'branch_name', {size: 1}, [config_element('leaf', '10', {"weight" => 1})])
520
+ assert_nothing_raised { b3.configure(config_element('ROOT', '', BASE_ATTRS, [branch1])) }
521
+ branch2 = config_element('branch', 'branch_name', {size: 1}, [config_element('leaf', '20')])
522
+ assert_raise(Fluent::ConfigError.new(msg)) { b3.configure(config_element('ROOT', '', BASE_ATTRS, [branch1, branch2])) }
523
+ branch3 = config_element('branch', 'branch_name', {size: 1}, [config_element('leaf', '10', {"weight" => 3}), config_element('leaf', '20')])
524
+ assert_raise(Fluent::ConfigError.new(msg)) { b3.configure(config_element('ROOT', '', BASE_ATTRS, [branch3])) }
327
525
 
328
526
  ### worm not required
329
527
 
330
528
  b4 = ConfigurableSpec::Base4.new
331
529
 
332
- d1 = e('description1', '', {text:"d1"})
333
- d2 = e('description2', '', {text:"d2"})
334
- d3 = e('description3', '', {text:"d3"})
335
- assert_nothing_raised { b4.configure(e('ROOT', '', BASE_ATTRS, [d1.dup, d2.dup, d3.dup])) }
530
+ d1 = config_element('description1', '', {"text" => "d1"})
531
+ d2 = config_element('description2', '', {"text" => "d2"})
532
+ d3 = config_element('description3', '', {"text" => "d3"})
533
+ assert_nothing_raised { b4.configure(config_element('ROOT', '', BASE_ATTRS, [d1.dup, d2.dup, d3.dup])) }
336
534
 
337
535
  # description1 cannot be specified 2 or more
338
536
  msg = "'<description1>' section cannot be written twice or more"
339
- assert_raise(Fluent::ConfigError.new(msg)) { b4.configure(e('ROOT', '', BASE_ATTRS, [d1.dup, d2.dup, d1.dup, d3.dup])) }
537
+ assert_raise(Fluent::ConfigError.new(msg)) { b4.configure(config_element('ROOT', '', BASE_ATTRS, [d1.dup, d2.dup, d1.dup, d3.dup])) }
340
538
 
341
539
  # description2 cannot be specified 2 or more
342
540
  msg = "'<description2>' section cannot be written twice or more"
343
- assert_raise(Fluent::ConfigError.new(msg)) { b4.configure(e('ROOT', '', BASE_ATTRS, [d1.dup, d2.dup, d3.dup, d2.dup])) }
541
+ assert_raise(Fluent::ConfigError.new(msg)) { b4.configure(config_element('ROOT', '', BASE_ATTRS, [d1.dup, d2.dup, d3.dup, d2.dup])) }
344
542
 
345
543
  # description3 can be specified 2 or more
346
- assert_nothing_raised { b4.configure(e('ROOT', '', BASE_ATTRS, [d1.dup, d2.dup, d3.dup, d3.dup])) }
544
+ assert_nothing_raised { b4.configure(config_element('ROOT', '', BASE_ATTRS, [d1.dup, d2.dup, d3.dup, d3.dup])) }
347
545
  end
348
546
 
349
547
  test 'constructs confuguration object tree for Base3' do
350
- conf = e(
548
+ conf = config_element(
351
549
  'ROOT',
352
550
  '',
353
551
  BASE_ATTRS,
354
552
  [
355
- e('node', '', {type:"1"}), e('node', '', {name:"node2",type:"2"}),
356
- e('branch', 'b1.*', {}, []),
357
- e('branch',
553
+ config_element('node', '', {"type" => "1"}), config_element('node', '', {"name" => "node2","type" => "2"}),
554
+ config_element('branch', 'b1.*', {}, []),
555
+ config_element('branch',
358
556
  'b2.*',
359
- {size: 5},
557
+ {"size" => 5},
360
558
  [
361
- e('leaf', 'THIS IS IGNORED', {weight: 55}, []),
362
- e('leaf', 'THIS IS IGNORED', {weight: 50}, [ e('worm', '', {}) ]),
363
- e('leaf', 'THIS IS IGNORED', {weight: 50}, [ e('worm', '', {type:"w1"}), e('worm', '', {type:"w2"}) ]),
559
+ config_element('leaf', 'THIS IS IGNORED', {"weight" => 55}, []),
560
+ config_element('leaf', 'THIS IS IGNORED', {"weight" => 50}, [ config_element('worm', '', {}) ]),
561
+ config_element('leaf', 'THIS IS IGNORED', {"weight" => 50}, [ config_element('worm', '', {"type" => "w1"}), config_element('worm', '', {"type" => "w2"}) ]),
364
562
  ]
365
563
  ),
366
- e('branch',
564
+ config_element('branch',
367
565
  'b3.*',
368
- {size: "503"},
566
+ {"size" => "503"},
369
567
  [
370
- e('leaf', 'THIS IS IGNORED', {weight: 55}, []),
568
+ config_element('leaf', 'THIS IS IGNORED', {"weight" => 55}, []),
371
569
  ]
372
570
  )
373
571
  ],
@@ -424,18 +622,18 @@ module Fluent::Config
424
622
  end
425
623
 
426
624
  test 'constructs confuguration object tree for Base4' do
427
- conf = e(
625
+ conf = config_element(
428
626
  'ROOT',
429
627
  '',
430
628
  BASE_ATTRS,
431
629
  [
432
- e('node', '1', {type:"1"}), e('node', '2', {name:"node2"}),
433
- e('description3', '', {text:"dddd3-1"}),
434
- e('description2', 'd-2', {text:"dddd2"}),
435
- e('description1', '', {text:"dddd1"}),
436
- e('description3', 'd-3', {text:"dddd3-2"}),
437
- e('description3', 'd-3a', {text:"dddd3-3"}),
438
- e('node', '4', {type:"four"}),
630
+ config_element('node', '1', {"type" => "1"}), config_element('node', '2', {"name" => "node2"}),
631
+ config_element('description3', '', {"text" => "dddd3-1"}),
632
+ config_element('description2', 'd-2', {"text" => "dddd2"}),
633
+ config_element('description1', '', {"text" => "dddd1"}),
634
+ config_element('description3', 'd-3', {"text" => "dddd3-2"}),
635
+ config_element('description3', 'd-3a', {"text" => "dddd3-3"}),
636
+ config_element('node', '4', {"type" => "four"}),
439
637
  ],
440
638
  )
441
639
  b4 = ConfigurableSpec::Base4.new.configure(conf)
@@ -461,9 +659,9 @@ module Fluent::Config
461
659
  assert_equal("node", b4.nodes[2].name)
462
660
  assert_equal("four", b4.nodes[2].type)
463
661
 
464
- # e('description3', '', {text:"dddd3-1"}),
465
- # e('description3', 'd-3', {text:"dddd3-2"}),
466
- # e('description3', 'd-3a', {text:"dddd3-3"}),
662
+ # config_element('description3', '', {"text" => "dddd3-1"}),
663
+ # config_element('description3', 'd-3', {"text" => "dddd3-2"}),
664
+ # config_element('description3', 'd-3a', {"text" => "dddd3-3"}),
467
665
 
468
666
  # NoMethodError: undefined method `class' for <Fluent::Config::Section {...}>:Fluent::Config::Section occurred. Should we add class method to Section?
469
667
  #assert_equal('Fluent::Config::Section', b4.description1.class.name)
@@ -486,11 +684,11 @@ module Fluent::Config
486
684
  end
487
685
 
488
686
  test 'checks missing of specifications' do
489
- conf0 = e('ROOT', '', {}, [])
687
+ conf0 = config_element('ROOT', '', {}, [])
490
688
  ex01 = ConfigurableSpec::Example0.new
491
689
  assert_raise(Fluent::ConfigError) { ex01.configure(conf0) }
492
690
 
493
- complete = e('ROOT', '', {
691
+ complete = config_element('ROOT', '', {
494
692
  "stringvalue" => "s1", "boolvalue" => "yes", "integervalue" => "10",
495
693
  "sizevalue" => "10m", "timevalue" => "100s", "floatvalue" => "1.001",
496
694
  "hashvalue" => '{"foo":1, "bar":2}',
@@ -500,18 +698,27 @@ module Fluent::Config
500
698
  checker = lambda { |conf| ConfigurableSpec::Example0.new.configure(conf) }
501
699
 
502
700
  assert_nothing_raised { checker.call(complete) }
503
- assert_raise(Fluent::ConfigError) { checker.call(complete.reject{|k,v| k == "stringvalue" }) }
504
- assert_raise(Fluent::ConfigError) { checker.call(complete.reject{|k,v| k == "boolvalue" }) }
505
- assert_raise(Fluent::ConfigError) { checker.call(complete.reject{|k,v| k == "integervalue"}) }
506
- assert_raise(Fluent::ConfigError) { checker.call(complete.reject{|k,v| k == "sizevalue" }) }
507
- assert_raise(Fluent::ConfigError) { checker.call(complete.reject{|k,v| k == "timevalue" }) }
508
- assert_raise(Fluent::ConfigError) { checker.call(complete.reject{|k,v| k == "floatvalue" }) }
509
- assert_raise(Fluent::ConfigError) { checker.call(complete.reject{|k,v| k == "hashvalue" }) }
510
- assert_raise(Fluent::ConfigError) { checker.call(complete.reject{|k,v| k == "arrayvalue" }) }
701
+ assert_raise(Fluent::ConfigError) { c = complete.dup; c.delete("stringvalue"); checker.call(c) }
702
+ assert_raise(Fluent::ConfigError) { c = complete.dup; c.delete("boolvalue"); checker.call(c) }
703
+ assert_raise(Fluent::ConfigError) { c = complete.dup; c.delete("integervalue"); checker.call(c) }
704
+ assert_raise(Fluent::ConfigError) { c = complete.dup; c.delete("sizevalue"); checker.call(c) }
705
+ assert_raise(Fluent::ConfigError) { c = complete.dup; c.delete("timevalue"); checker.call(c) }
706
+ assert_raise(Fluent::ConfigError) { c = complete.dup; c.delete("floatvalue"); checker.call(c) }
707
+ assert_raise(Fluent::ConfigError) { c = complete.dup; c.delete("hashvalue"); checker.call(c) }
708
+ assert_raise(Fluent::ConfigError) { c = complete.dup; c.delete("arrayvalue"); checker.call(c) }
709
+ end
710
+
711
+ test 'generates section with default values for init:true sections' do
712
+ conf = config_element('ROOT', '', {}, [])
713
+ init0 = ConfigurableSpec::Init0.new
714
+ assert_nothing_raised { init0.configure(conf) }
715
+ assert init0.sec1
716
+ assert_equal "sec1", init0.sec1.name
717
+ assert_equal [], init0.sec2
511
718
  end
512
719
 
513
720
  test 'accepts configuration values as string representation' do
514
- conf = e('ROOT', '', {
721
+ conf = config_element('ROOT', '', {
515
722
  "stringvalue" => "s1", "boolvalue" => "yes", "integervalue" => "10",
516
723
  "sizevalue" => "10m", "timevalue" => "10m", "floatvalue" => "1.001",
517
724
  "hashvalue" => '{"foo":1, "bar":2}',
@@ -529,7 +736,7 @@ module Fluent::Config
529
736
  end
530
737
 
531
738
  test 'accepts configuration values as ruby value representation (especially for DSL)' do
532
- conf = e('ROOT', '', {
739
+ conf = config_element('ROOT', '', {
533
740
  "stringvalue" => "s1", "boolvalue" => true, "integervalue" => 10,
534
741
  "sizevalue" => 10 * 1024 * 1024, "timevalue" => 10 * 60, "floatvalue" => 1.001,
535
742
  "hashvalue" => {"foo" => 1, "bar" => 2},
@@ -547,7 +754,7 @@ module Fluent::Config
547
754
  end
548
755
 
549
756
  test 'gets both of true(yes) and false(no) for bool value parameter' do
550
- conf = e('ROOT', '', {
757
+ conf = config_element('ROOT', '', {
551
758
  "stringvalue" => "s1", "integervalue" => 10,
552
759
  "sizevalue" => 10 * 1024 * 1024, "timevalue" => 10 * 60, "floatvalue" => 1.001,
553
760
  "hashvalue" => {"foo" => 1, "bar" => 2},
@@ -574,93 +781,212 @@ module Fluent::Config
574
781
  end
575
782
 
576
783
  sub_test_case '.config_section' do
577
- def e(name, arg = '', attrs = {}, elements = [])
578
- attrs_str_keys = {}
579
- attrs.each{|key, value| attrs_str_keys[key.to_s] = value }
580
- config_element(name, arg, attrs_str_keys, elements)
581
- end
582
-
583
- test 'subclass configuration spec can overwrite superclass specs' do
584
- # conf0 = e('ROOT', '', {}, [])
585
-
586
- conf1 = e('ROOT', '', {
587
- 'name' => 'tagomoris',
588
- 'bool' => true,
589
- },
590
- )
591
- # <detail> section is required by overwriting of Example2 config_section spec
592
- assert_nothing_raised { ConfigurableSpec::Example1.new.configure(conf1) }
593
- assert_raise(Fluent::ConfigError.new("'<detail>' sections are required")) { ConfigurableSpec::Example2.new.configure(conf1) }
594
-
595
- conf2 = e('ROOT', '', {
596
- 'name' => 'tagomoris',
597
- 'bool' => true,
598
- },
599
- [e('detail', '', { 'phone_no' => "+81-00-0000-0000" }, [])],
600
- )
601
- # <detail> address </detail> default is overwritten by Example2
602
- assert_nothing_raised { ConfigurableSpec::Example1.new.configure(conf2) }
603
- assert_nothing_raised { ConfigurableSpec::Example2.new.configure(conf2) }
604
- ex1 = ConfigurableSpec::Example1.new.configure(conf2)
605
- assert_equal "x", ex1.detail.address
606
- ex2 = ConfigurableSpec::Example2.new.configure(conf2)
607
- assert_equal "y", ex2.detail.address
608
-
609
- conf3 = e('ROOT', '', {
610
- 'name' => 'tagomoris',
611
- 'bool' => true,
612
- },
613
- [e('detail', '', { 'address' => "Chiyoda Tokyo Japan" }, [])],
614
- )
615
- # <detail> phone_no </detail> is required by Example2 config_param spec
616
- assert_nothing_raised { ConfigurableSpec::Example1.new.configure(conf3) }
617
- assert_raise(Fluent::ConfigError.new("'phone_no' parameter is required, in section detail")) { ConfigurableSpec::Example2.new.configure(conf3) }
618
-
619
- conf4 = e('ROOT', '', {
620
- 'name' => 'tagomoris',
621
- 'bool' => true,
622
- },
623
- [e('detail', '', { 'address' => "Chiyoda Tokyo Japan", 'phone_no' => '+81-00-0000-0000' }, [])],
624
- )
625
- assert_nothing_raised { ConfigurableSpec::Example1.new.configure(conf4) } # phone_no is not used
626
- assert_nothing_raised { ConfigurableSpec::Example2.new.configure(conf4) }
627
-
628
- ex2 = ConfigurableSpec::Example2.new.configure(conf4)
629
- assert_equal "Chiyoda Tokyo Japan", ex2.detail.address
630
- assert_equal "+81-00-0000-0000", ex2.detail.phone_no
631
- end
632
-
633
- test 'adds only config_param definitions into configuration without overwriting existing finalized configuration elements' do
634
-
635
- conf1 = e('ROOT', '', {}, [])
636
- # <appendix> is required by Example3 and its not be overwritten by Example4
637
- assert_raise(Fluent::ConfigError.new("'<appendix>' sections are required")) { ConfigurableSpec::Example3.new.configure(conf1) }
638
- assert_raise(Fluent::ConfigError.new("'<appendix>' sections are required")) { ConfigurableSpec::Example4.new.configure(conf1) }
639
-
640
- conf2 = e('ROOT', '', {
641
- },
642
- [e('appendix', '', {'type' => '1'}, [])],
643
- )
644
- # default value of age is overwritten by Example4, because root proxy is not finalized
645
- ex3 = ConfigurableSpec::Example3.new.configure(conf2)
646
- assert_equal 10, ex3.age
647
- assert_equal '1', ex3.appendix.type
648
- ex4 = ConfigurableSpec::Example4.new.configure(conf2)
649
- assert_equal 20, ex4.age
650
- assert_equal '1', ex4.appendix.type
651
-
652
- conf3 = e('ROOT', '', {},
653
- [e('appendix', '', {'type' => '2'}, [])],
654
- )
655
- # default value of <appendix> name </appendix> cannot be overwritten because it is finalized
656
- ex3 = ConfigurableSpec::Example3.new.configure(conf2)
657
- assert_equal 10, ex3.age
658
- assert_equal '1', ex3.appendix.type
659
- ex4 = ConfigurableSpec::Example4.new.configure(conf2)
660
- assert_equal 20, ex4.age
661
- assert_equal '1', ex4.appendix.type
662
- # <appendix> age </appendix> can be added because it is missing in superclass spec
663
- assert_equal 10, ex4.appendix.age
784
+ CONF1 = config_element('ROOT', '', {
785
+ 'name' => 'tagomoris',
786
+ 'bool' => true,
787
+ })
788
+
789
+ CONF2 = config_element('ROOT', '', {
790
+ 'name' => 'tagomoris',
791
+ 'bool' => true,
792
+ },
793
+ [config_element('detail', '', { 'phone_no' => "+81-00-0000-0000" }, [])])
794
+
795
+ CONF3 = config_element('ROOT', '', {
796
+ 'name' => 'tagomoris',
797
+ 'bool' => true,
798
+ },
799
+ [config_element('detail', '', { 'address' => "Chiyoda Tokyo Japan" }, [])])
800
+
801
+ CONF4 = config_element('ROOT', '', {
802
+ 'name' => 'tagomoris',
803
+ 'bool' => true,
804
+ },
805
+ [
806
+ config_element('detail', '', {
807
+ 'address' => "Chiyoda Tokyo Japan",
808
+ 'phone_no' => '+81-00-0000-0000'
809
+ },
810
+ [])
811
+ ])
812
+
813
+ data(conf1: CONF1,
814
+ conf2: CONF2,
815
+ conf3: CONF3,
816
+ conf4: CONF4,)
817
+ test 'base class' do |data|
818
+ assert_nothing_raised { ConfigurableSpec::Overwrite::Base.new.configure(data) }
819
+ end
820
+
821
+ test 'subclass cannot overwrite required' do
822
+ assert_raise(Fluent::ConfigError.new("BUG: subclass cannot overwrite base class's config_section: required")) do
823
+ ConfigurableSpec::Overwrite::Required.new.configure(CONF1)
824
+ end
825
+ end
826
+
827
+ test 'subclass cannot overwrite multi' do
828
+ assert_raise(Fluent::ConfigError.new("BUG: subclass cannot overwrite base class's config_section: multi")) do
829
+ ConfigurableSpec::Overwrite::Multi.new.configure(CONF1)
830
+ end
831
+ end
832
+
833
+ test 'subclass cannot overwrite alias' do
834
+ assert_raise(Fluent::ConfigError.new("BUG: subclass cannot overwrite base class's config_section: alias")) do
835
+ ConfigurableSpec::Overwrite::Alias.new.configure(CONF1)
836
+ end
837
+ end
838
+
839
+ test 'subclass uses superclass default options' do
840
+ base = ConfigurableSpec::Overwrite::Base.new.configure(CONF2)
841
+ sub = ConfigurableSpec::Overwrite::DefaultOptions.new.configure(CONF2)
842
+ detail_base = base.class.merged_configure_proxy.sections[:detail]
843
+ detail_sub = sub.class.merged_configure_proxy.sections[:detail]
844
+ detail_base_attributes = {
845
+ requried: detail_base.required,
846
+ multi: detail_base.multi,
847
+ alias: detail_base.alias,
848
+ }
849
+ detail_sub_attributes = {
850
+ requried: detail_sub.required,
851
+ multi: detail_sub.multi,
852
+ alias: detail_sub.alias,
853
+ }
854
+ assert_equal(detail_base_attributes, detail_sub_attributes)
855
+ end
856
+
857
+ test 'subclass can overwrite detail.address' do
858
+ base = ConfigurableSpec::Overwrite::Base.new.configure(CONF2)
859
+ target = ConfigurableSpec::Overwrite::DetailAddressDefault.new.configure(CONF2)
860
+ expected_addresses = ["x", "y"]
861
+ actual_addresses = [base.detail.address, target.detail.address]
862
+ assert_equal(expected_addresses, actual_addresses)
863
+ end
864
+
865
+ test 'subclass can add param' do
866
+ assert_raise(Fluent::ConfigError.new("'phone_no' parameter is required, in section detail")) do
867
+ ConfigurableSpec::Overwrite::AddParam.new.configure(CONF3)
868
+ end
869
+ target = ConfigurableSpec::Overwrite::AddParam.new.configure(CONF4)
870
+ expected = {
871
+ address: "Chiyoda Tokyo Japan",
872
+ phone_no: "+81-00-0000-0000"
873
+ }
874
+ actual = {
875
+ address: target.detail.address,
876
+ phone_no: target.detail.phone_no
877
+ }
878
+ assert_equal(expected, actual)
879
+ end
880
+
881
+ test 'subclass can add param with overwriting address' do
882
+ assert_raise(Fluent::ConfigError.new("'phone_no' parameter is required, in section detail")) do
883
+ ConfigurableSpec::Overwrite::AddParamOverwriteAddress.new.configure(CONF3)
884
+ end
885
+ target = ConfigurableSpec::Overwrite::AddParamOverwriteAddress.new.configure(CONF4)
886
+ expected = {
887
+ address: "Chiyoda Tokyo Japan",
888
+ phone_no: "+81-00-0000-0000"
889
+ }
890
+ actual = {
891
+ address: target.detail.address,
892
+ phone_no: target.detail.phone_no
893
+ }
894
+ assert_equal(expected, actual)
895
+ end
896
+
897
+ sub_test_case 'final' do
898
+ test 'base class has designed params and default values' do
899
+ b = ConfigurableSpec::Final::Base.new
900
+ appendix_conf = config_element('appendix', '', {"code" => "b", "name" => "base"})
901
+ b.configure(config_element('ROOT', '', {}, [appendix_conf]))
902
+
903
+ assert_equal "b", b.appendix.code
904
+ assert_equal "base", b.appendix.name
905
+ assert_equal "", b.appendix.address
906
+ end
907
+
908
+ test 'subclass can change type, add default value, change default value of parameters, and add parameters to non-finalized section' do
909
+ f = ConfigurableSpec::Final::Finalized.new
910
+ appendix_conf = config_element('appendix', '', {"code" => 1})
911
+ f.configure(config_element('ROOT', '', {}, [appendix_conf]))
912
+
913
+ assert_equal 1, f.appendix.code
914
+ assert_equal 'y', f.appendix.name
915
+ assert_equal "-", f.appendix.address
916
+ assert_equal 10, f.appendix.age
917
+ end
918
+
919
+ test 'subclass can add default value, change default value of parameters, and add parameters to finalized section' do
920
+ i = ConfigurableSpec::Final::InheritsFinalized.new
921
+ appendix_conf = config_element('appendix', '', {"phone_no" => "00-0000-0000"})
922
+ i.configure(config_element('ROOT', '', {}, [appendix_conf]))
923
+
924
+ assert_equal 2, i.appendix.code
925
+ assert_equal 0, i.appendix.age
926
+ assert_equal "00-0000-0000", i.appendix.phone_no
927
+ end
928
+
929
+ test 'finalized base class works as designed' do
930
+ b = ConfigurableSpec::Final::FinalizedBase.new
931
+ appendix_conf = config_element('options', '', {"name" => "moris"})
932
+
933
+ assert_nothing_raised do
934
+ b.configure(config_element('ROOT', '', {}, [appendix_conf]))
935
+ end
936
+ assert b.apd
937
+ assert_equal "moris", b.apd.name
938
+ end
939
+
940
+ test 'subclass can change init' do
941
+ n = ConfigurableSpec::Final::OverwriteInit.new
942
+
943
+ assert_nothing_raised do
944
+ n.configure(config_element('ROOT', ''))
945
+ end
946
+ assert n.apd
947
+ assert_equal "moris", n.apd.name
948
+ assert_equal 0, n.apd.code
949
+ end
950
+
951
+ test 'subclass cannot change parameter types in finalized sections' do
952
+ s = ConfigurableSpec::Final::Subclass.new
953
+ appendix_conf = config_element('options', '', {"name" => "1"})
954
+
955
+ assert_nothing_raised do
956
+ s.configure(config_element('ROOT', '', {}, [appendix_conf]))
957
+ end
958
+ assert_equal "1", s.apd.name
959
+ end
960
+
961
+ test 'subclass cannot change param_name of finalized section' do
962
+ assert_raise(Fluent::ConfigError.new("BUG: subclass cannot overwrite base class's config_section: param_name")) do
963
+ ConfigurableSpec::Final::OverwriteParamName.new
964
+ end
965
+ end
966
+
967
+ test 'subclass cannot change final of finalized section' do
968
+ assert_raise(Fluent::ConfigError.new("BUG: subclass cannot overwrite finalized base class's config_section")) do
969
+ ConfigurableSpec::Final::OverwriteFinal.new
970
+ end
971
+ end
972
+
973
+ test 'subclass cannot change required of finalized section' do
974
+ assert_raise(Fluent::ConfigError.new("BUG: subclass cannot overwrite base class's config_section: required")) do
975
+ ConfigurableSpec::Final::OverwriteRequired.new
976
+ end
977
+ end
978
+
979
+ test 'subclass cannot change multi of finalized section' do
980
+ assert_raise(Fluent::ConfigError.new("BUG: subclass cannot overwrite base class's config_section: multi")) do
981
+ ConfigurableSpec::Final::OverwriteMulti.new
982
+ end
983
+ end
984
+
985
+ test 'subclass cannot change alias of finalized section' do
986
+ assert_raise(Fluent::ConfigError.new("BUG: subclass cannot overwrite base class's config_section: alias")) do
987
+ ConfigurableSpec::Final::OverwriteAlias.new
988
+ end
989
+ end
664
990
  end
665
991
  end
666
992
  end
@@ -679,15 +1005,14 @@ module Fluent::Config
679
1005
  end
680
1006
 
681
1007
  sub_test_case '#configure' do
682
- def e(name, arg = '', attrs = {}, elements = [])
683
- attrs_str_keys = {}
684
- attrs.each{|key, value| attrs_str_keys[key.to_s] = value }
685
- config_element(name, arg, attrs_str_keys, elements)
686
- end
687
-
688
1008
  test 'provides accessible data for alias attribute keys' do
689
1009
  ex1 = ConfigurableSpec::Example1.new
690
- ex1.configure(e('ROOT', '', {"fullname" => "foo bar", "bool" => false}, [e('information', '', {"address" => "Mountain View 0"})]))
1010
+ conf = config_element('ROOT', '', {
1011
+ "fullname" => "foo bar",
1012
+ "bool" => false
1013
+ },
1014
+ [config_element('information', '', {"address" => "Mountain View 0"})])
1015
+ ex1.configure(conf)
691
1016
  assert_equal("foo bar", ex1.name)
692
1017
  assert_not_nil(ex1.bool)
693
1018
  assert_false(ex1.bool)
@@ -697,15 +1022,40 @@ module Fluent::Config
697
1022
  end
698
1023
  end
699
1024
 
700
- sub_test_case ':secret option' do
701
- def e(name, arg = '', attrs = {}, elements = [])
702
- attrs_str_keys = {}
703
- attrs.each { |key, value| attrs_str_keys[key.to_s] = value }
704
- config_element(name, arg, attrs_str_keys, elements)
1025
+ sub_test_case 'defaults can be overwritten by owner' do
1026
+ test 'for feature plugin which has flat parameters with parent' do
1027
+ owner = ConfigurableSpec::OverwriteDefaults::Owner.new
1028
+ child = ConfigurableSpec::OverwriteDefaults::FlatChild.new
1029
+ child.owner = owner
1030
+ child.configure(config_element('ROOT', '', {}, []))
1031
+ assert_equal "V1", child.key1
1032
+ end
1033
+
1034
+ test 'for feature plugin which has parameters in subsection of parent' do
1035
+ owner = ConfigurableSpec::OverwriteDefaults::Owner.new
1036
+ child = ConfigurableSpec::OverwriteDefaults::BufferChild.new
1037
+ child.owner = owner
1038
+ child.configure(config_element('ROOT', '', {}, []))
1039
+ assert_equal 1024, child.size_of_something
1040
+ end
1041
+
1042
+ test 'even in subclass of owner' do
1043
+ owner = ConfigurableSpec::OverwriteDefaults::SubOwner.new
1044
+ child = ConfigurableSpec::OverwriteDefaults::BufferChild.new
1045
+ child.owner = owner
1046
+ child.configure(config_element('ROOT', '', {}, []))
1047
+ assert_equal 2048, child.size_of_something
705
1048
  end
1049
+ end
706
1050
 
1051
+ sub_test_case ':secret option' do
707
1052
  setup do
708
- @conf = e('ROOT', '', {'normal_param' => 'normal', 'secret_param' => 'secret'}, [e('section', '', {'normal_param2' => 'normal', 'secret_param2' => 'secret'} )])
1053
+ @conf = config_element('ROOT', '',
1054
+ {
1055
+ 'normal_param' => 'normal',
1056
+ 'secret_param' => 'secret'
1057
+ },
1058
+ [config_element('section', '', {'normal_param2' => 'normal', 'secret_param2' => 'secret'} )])
709
1059
  @example = ConfigurableSpec::Example5.new
710
1060
  @example.configure(@conf)
711
1061
  end
@@ -730,7 +1080,12 @@ module Fluent::Config
730
1080
  end
731
1081
 
732
1082
  test 'get plugin name when found unknown section' do
733
- @conf = e('ROOT', '', {'normal_param' => 'normal', 'secret_param' => 'secret'}, [e('unknown', '', {'normal_param2' => 'normal', 'secret_param2' => 'secret'} )])
1083
+ @conf = config_element('ROOT', '',
1084
+ {
1085
+ 'normal_param' => 'normal',
1086
+ 'secret_param' => 'secret'
1087
+ },
1088
+ [config_element('unknown', '', {'normal_param2' => 'normal', 'secret_param2' => 'secret'} )])
734
1089
  @example = ConfigurableSpec::Example5.new
735
1090
  @example.configure(@conf)
736
1091
  @conf.elements.each { |e|
@@ -747,87 +1102,5 @@ module Fluent::Config
747
1102
  end
748
1103
  end
749
1104
  end
750
- sub_test_case 'non-required options for config_param' do
751
- test 'desc must be a string if specified' do
752
- assert_raise ArgumentError.new("key: desc must be a String, but Symbol") do
753
- class InvalidDescClass
754
- include Fluent::Configurable
755
- config_param :key, :string, default: '', desc: :invalid_description
756
- end
757
- end
758
- end
759
- test 'alias must be a symbol if specified' do
760
- assert_raise ArgumentError.new("key: alias must be a Symbol, but String") do
761
- class InvalidAliasClass
762
- include Fluent::Configurable
763
- config_param :key, :string, default: '', alias: 'yay'
764
- end
765
- end
766
- end
767
- test 'deprecated must be a string if specified' do
768
- assert_raise ArgumentError.new("key: deprecated must be a String, but TrueClass") do
769
- class InvalidDeprecatedClass
770
- include Fluent::Configurable
771
- config_param :key, :string, default: '', deprecated: true
772
- end
773
- end
774
- end
775
- test 'obsoleted must be a string if specified' do
776
- assert_raise ArgumentError.new("key: obsoleted must be a String, but TrueClass") do
777
- class InvalidObsoletedClass
778
- include Fluent::Configurable
779
- config_param :key, :string, default: '', obsoleted: true
780
- end
781
- end
782
- end
783
- test 'value_type for hash must be a symbol' do
784
- assert_raise ArgumentError.new("key: value_type must be a Symbol, but String") do
785
- class InvalidValueTypeOfHashClass
786
- include Fluent::Configurable
787
- config_param :key, :hash, value_type: 'yay'
788
- end
789
- end
790
- end
791
- test 'value_type for array must be a symbol' do
792
- assert_raise ArgumentError.new("key: value_type must be a Symbol, but String") do
793
- class InvalidValueTypeOfArrayClass
794
- include Fluent::Configurable
795
- config_param :key, :array, value_type: 'yay'
796
- end
797
- end
798
- end
799
- end
800
- sub_test_case 'enum parameters' do
801
- test 'list must be specified as an array of symbols'
802
- end
803
- sub_test_case 'deprecated/obsoleted parameters' do
804
- test 'both cannot be specified at once' do
805
- assert_raise ArgumentError.new("param1: both of deprecated and obsoleted cannot be specified at once") do
806
- class Buggy1
807
- include Fluent::Configurable
808
- config_param :param1, :string, default: '', deprecated: 'yay', obsoleted: 'foo!'
809
- end
810
- end
811
- end
812
-
813
- test 'warned if deprecated parameter is configured' do
814
- obj = ConfigurableSpec::UnRecommended.new
815
- obj.log = Fluent::Test::TestLogger.new
816
- obj.configure(config_element('ROOT', '', {'key1' => 'yay'}, []))
817
-
818
- assert_equal 'yay', obj.key1
819
- first_log = obj.log.logs.first
820
- assert{ first_log && first_log.include?("[warn]") && first_log.include?("'key1' parameter is deprecated: key1 will be removed.") }
821
- end
822
-
823
- test 'error raised if obsoleted parameter is configured' do
824
- obj = ConfigurableSpec::UnRecommended.new
825
- obj.log = Fluent::Test::TestLogger.new
826
-
827
- assert_raise Fluent::ObsoletedParameterError.new("'key2' parameter is already removed: key2 has been removed.") do
828
- obj.configure(config_element('ROOT', '', {'key2' => 'yay'}, []))
829
- end
830
- end
831
- end
832
1105
  end
833
1106
  end