fluentd 0.10.62 → 0.12.0.pre.1

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 (140) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -2
  3. data/.travis.yml +0 -4
  4. data/ChangeLog +0 -72
  5. data/Gemfile +0 -6
  6. data/Rakefile +12 -3
  7. data/example/in_http.conf +14 -0
  8. data/example/in_syslog.conf +15 -0
  9. data/example/in_tail.conf +14 -0
  10. data/example/in_tcp.conf +13 -0
  11. data/example/in_udp.conf +13 -0
  12. data/example/out_copy.conf +20 -0
  13. data/example/out_file.conf +13 -0
  14. data/example/out_forward.conf +30 -0
  15. data/fluent.conf +2 -12
  16. data/fluentd.gemspec +8 -11
  17. data/lib/fluent/agent.rb +180 -0
  18. data/lib/fluent/buffer.rb +6 -12
  19. data/lib/fluent/command/cat.rb +1 -3
  20. data/lib/fluent/command/debug.rb +1 -3
  21. data/lib/fluent/command/fluentd.rb +0 -10
  22. data/lib/fluent/config.rb +9 -3
  23. data/lib/fluent/config/basic_parser.rb +1 -6
  24. data/lib/fluent/config/configure_proxy.rb +25 -61
  25. data/lib/fluent/config/dsl.rb +16 -0
  26. data/lib/fluent/config/element.rb +21 -2
  27. data/lib/fluent/config/error.rb +16 -0
  28. data/lib/fluent/config/literal_parser.rb +9 -27
  29. data/lib/fluent/config/parser.rb +16 -0
  30. data/lib/fluent/config/section.rb +16 -2
  31. data/lib/fluent/config/types.rb +16 -1
  32. data/lib/fluent/config/v1_parser.rb +4 -12
  33. data/lib/fluent/configurable.rb +16 -0
  34. data/lib/fluent/engine.rb +43 -163
  35. data/lib/fluent/env.rb +16 -1
  36. data/lib/fluent/event.rb +20 -48
  37. data/lib/fluent/event_router.rb +187 -0
  38. data/lib/fluent/filter.rb +32 -0
  39. data/lib/fluent/formatter.rb +29 -101
  40. data/lib/fluent/input.rb +6 -4
  41. data/lib/fluent/label.rb +18 -0
  42. data/lib/fluent/load.rb +1 -3
  43. data/lib/fluent/log.rb +1 -3
  44. data/lib/fluent/match.rb +12 -19
  45. data/lib/fluent/mixin.rb +9 -25
  46. data/lib/fluent/output.rb +27 -45
  47. data/lib/fluent/parser.rb +93 -99
  48. data/lib/fluent/plugin.rb +22 -48
  49. data/lib/fluent/plugin/buf_file.rb +10 -7
  50. data/lib/fluent/plugin/buf_memory.rb +2 -3
  51. data/lib/fluent/plugin/buf_zfile.rb +75 -0
  52. data/lib/fluent/plugin/exec_util.rb +16 -0
  53. data/lib/fluent/plugin/in_debug_agent.rb +2 -3
  54. data/lib/fluent/plugin/in_exec.rb +2 -9
  55. data/lib/fluent/plugin/in_forward.rb +4 -22
  56. data/lib/fluent/plugin/in_gc_stat.rb +2 -3
  57. data/lib/fluent/plugin/in_http.rb +19 -59
  58. data/lib/fluent/plugin/in_monitor_agent.rb +21 -47
  59. data/lib/fluent/plugin/in_object_space.rb +2 -3
  60. data/lib/fluent/plugin/in_status.rb +2 -3
  61. data/lib/fluent/plugin/in_stream.rb +6 -16
  62. data/lib/fluent/plugin/in_syslog.rb +8 -17
  63. data/lib/fluent/plugin/in_tail.rb +17 -24
  64. data/lib/fluent/plugin/in_tcp.rb +16 -0
  65. data/lib/fluent/plugin/in_udp.rb +16 -0
  66. data/lib/fluent/plugin/out_copy.rb +3 -4
  67. data/lib/fluent/plugin/out_exec.rb +2 -4
  68. data/lib/fluent/plugin/out_exec_filter.rb +2 -13
  69. data/lib/fluent/plugin/out_file.rb +5 -6
  70. data/lib/fluent/plugin/out_forward.rb +4 -5
  71. data/lib/fluent/plugin/out_null.rb +2 -3
  72. data/lib/fluent/plugin/out_relabel.rb +26 -0
  73. data/lib/fluent/plugin/out_roundrobin.rb +3 -4
  74. data/lib/fluent/plugin/out_stdout.rb +2 -3
  75. data/lib/fluent/plugin/out_stream.rb +2 -3
  76. data/{test/scripts → lib}/fluent/plugin/out_test.rb +2 -3
  77. data/lib/fluent/plugin/socket_util.rb +19 -10
  78. data/lib/fluent/process.rb +4 -6
  79. data/lib/fluent/registry.rb +16 -0
  80. data/lib/fluent/root_agent.rb +212 -0
  81. data/lib/fluent/status.rb +2 -3
  82. data/lib/fluent/supervisor.rb +33 -54
  83. data/lib/fluent/test.rb +16 -0
  84. data/lib/fluent/test/base.rb +3 -17
  85. data/lib/fluent/test/input_test.rb +52 -7
  86. data/lib/fluent/test/output_test.rb +4 -20
  87. data/lib/fluent/version.rb +17 -1
  88. data/spec/config/config_parser_spec.rb +314 -0
  89. data/spec/config/configurable_spec.rb +524 -0
  90. data/spec/config/configure_proxy_spec.rb +96 -0
  91. data/spec/config/dsl_spec.rb +239 -0
  92. data/spec/config/helper.rb +49 -0
  93. data/spec/config/literal_parser_spec.rb +222 -0
  94. data/spec/config/section_spec.rb +97 -0
  95. data/spec/config/system_config_spec.rb +49 -0
  96. data/test/helper.rb +0 -25
  97. data/test/plugin/test_in_exec.rb +1 -1
  98. data/test/plugin/test_in_forward.rb +2 -1
  99. data/test/plugin/test_in_gc_stat.rb +1 -1
  100. data/test/plugin/test_in_http.rb +3 -78
  101. data/test/plugin/test_in_object_space.rb +1 -1
  102. data/test/plugin/test_in_status.rb +1 -1
  103. data/test/plugin/test_in_stream.rb +2 -1
  104. data/test/plugin/test_in_syslog.rb +2 -1
  105. data/test/plugin/test_in_tail.rb +6 -11
  106. data/test/plugin/test_in_tcp.rb +2 -1
  107. data/test/plugin/test_in_udp.rb +2 -1
  108. data/test/plugin/test_out_copy.rb +1 -12
  109. data/test/plugin/test_out_exec.rb +1 -1
  110. data/test/plugin/test_out_exec_filter.rb +1 -1
  111. data/test/plugin/test_out_file.rb +7 -96
  112. data/test/plugin/test_out_forward.rb +2 -1
  113. data/test/plugin/test_out_roundrobin.rb +1 -12
  114. data/test/plugin/test_out_stdout.rb +1 -1
  115. data/test/plugin/test_out_stream.rb +2 -1
  116. data/test/scripts/fluent/plugin/formatter_known.rb +1 -4
  117. data/test/scripts/fluent/plugin/parser_known.rb +1 -2
  118. data/test/test_config.rb +1 -1
  119. data/test/test_configdsl.rb +2 -1
  120. data/test/test_formatter.rb +3 -395
  121. data/test/test_match.rb +2 -1
  122. data/test/test_mixin.rb +3 -75
  123. data/test/test_output.rb +1 -112
  124. data/test/test_parser.rb +85 -152
  125. metadata +58 -167
  126. data/example/v1_literal_example.conf +0 -36
  127. data/lib/fluent/plugin/in_dummy.rb +0 -103
  128. data/lib/fluent/timezone.rb +0 -131
  129. data/test/config/assertions.rb +0 -42
  130. data/test/config/test_config_parser.rb +0 -389
  131. data/test/config/test_configurable.rb +0 -652
  132. data/test/config/test_configure_proxy.rb +0 -99
  133. data/test/config/test_dsl.rb +0 -237
  134. data/test/config/test_literal_parser.rb +0 -295
  135. data/test/config/test_section.rb +0 -112
  136. data/test/config/test_system_config.rb +0 -99
  137. data/test/config/test_types.rb +0 -63
  138. data/test/plugin/test_in_dummy.rb +0 -95
  139. data/test/test_event.rb +0 -168
  140. data/test/test_input.rb +0 -21
@@ -1,103 +0,0 @@
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
- module Fluent
18
- class DummyInput < Input
19
- Fluent::Plugin.register_input('dummy', self)
20
-
21
- BIN_NUM = 10
22
-
23
- config_param :tag, :string
24
- config_param :rate, :integer, :default => 1
25
- config_param :auto_increment_key, :string, :default => nil
26
- config_param :dummy, :default => [{"message"=>"dummy"}] do |val|
27
- begin
28
- parsed = JSON.parse(val)
29
- rescue JSON::ParserError => e
30
- # Fluent::ConfigParseError, "got incomplete JSON" will be raised
31
- # at literal_parser.rb with --use-v1-config, but I had to
32
- # take care at here for the case of --use-v0-config.
33
- raise Fluent::ConfigError, "#{e.class}: #{e.message}"
34
- end
35
- dummy = parsed.is_a?(Array) ? parsed : [parsed]
36
- dummy.each_with_index do |e, i|
37
- raise Fluent::ConfigError, "#{i}th element of dummy, #{e}, is not a hash" unless e.is_a?(Hash)
38
- end
39
- dummy
40
- end
41
-
42
- def configure(conf)
43
- super
44
-
45
- @increment_value = 0
46
- @dummy_index = 0
47
- end
48
-
49
- def start
50
- super
51
- @running = true
52
- @thread = Thread.new(&method(:run))
53
- end
54
-
55
- def shutdown
56
- @running = false
57
- @thread.join
58
- end
59
-
60
- def run
61
- batch_num = (@rate / BIN_NUM).to_i
62
- residual_num = (@rate % BIN_NUM)
63
- while @running
64
- current_time = Time.now.to_i
65
- BIN_NUM.times do
66
- break unless (@running && Time.now.to_i <= current_time)
67
- wait(0.1) { emit(batch_num) }
68
- end
69
- emit(residual_num)
70
- # wait for next second
71
- while @running && Time.now.to_i <= current_time
72
- sleep 0.01
73
- end
74
- end
75
- end
76
-
77
- def emit(num)
78
- num.times { router.emit(@tag, Fluent::Engine.now, generate()) }
79
- end
80
-
81
- def generate
82
- d = @dummy[@dummy_index]
83
- unless d
84
- @dummy_index = 0
85
- d = @dummy[0]
86
- end
87
- @dummy_index += 1
88
- if @auto_increment_key
89
- d = d.dup
90
- d[@auto_increment_key] = @increment_value
91
- @increment_value += 1
92
- end
93
- d
94
- end
95
-
96
- def wait(time)
97
- start_time = Time.now
98
- yield
99
- sleep_time = time - (Time.now - start_time)
100
- sleep sleep_time if sleep_time > 0
101
- end
102
- end
103
- end
@@ -1,131 +0,0 @@
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
- require 'tzinfo'
18
-
19
- module Fluent
20
- class Timezone
21
- # [+-]HH:MM, [+-]HHMM, [+-]HH
22
- NUMERIC_PATTERN = %r{\A[+-]\d\d(:?\d\d)?\z}
23
-
24
- # Region/Zone, Region/Zone/Zone
25
- NAME_PATTERN = %r{\A[^/]+/[^/]+(/[^/]+)?\z}
26
-
27
- # Validate the format of the specified timezone.
28
- #
29
- # Valid formats are as follows. Note that timezone abbreviations
30
- # such as PST and JST are not supported intentionally.
31
- #
32
- # 1. [+-]HH:MM (e.g. "+09:00")
33
- # 2. [+-]HHMM (e.g. "+0900")
34
- # 3. [+-]HH (e.g. "+09")
35
- # 4. Region/Zone (e.g. "Asia/Tokyo")
36
- # 5. Region/Zone/Zone (e.g. "America/Argentina/Buenos_Aires")
37
- #
38
- # In the 4th and 5th cases, it is checked whether the specified
39
- # timezone exists in the timezone database.
40
- #
41
- # When the given timezone is valid, true is returned. Otherwise,
42
- # false is returned. When nil is given, false is returned.
43
- def self.validate(timezone)
44
- # If the specified timezone is nil.
45
- if timezone.nil?
46
- # Invalid.
47
- return false
48
- end
49
-
50
- # [+-]HH:MM, [+-]HHMM, [+-]HH
51
- if NUMERIC_PATTERN === timezone
52
- # Valid. It can be parsed by Time.zone_offset method.
53
- return true
54
- end
55
-
56
- # Region/Zone, Region/Zone/Zone
57
- if NAME_PATTERN === timezone
58
- begin
59
- # Get a Timezone instance for the specified timezone.
60
- TZInfo::Timezone.get(timezone)
61
- rescue
62
- # Invalid. The string does not exist in the timezone database.
63
- return false
64
- else
65
- # Valid. The string was found in the timezone database.
66
- return true
67
- end
68
- else
69
- # Invalid. Timezone abbreviations are not supported.
70
- return false
71
- end
72
- end
73
-
74
- # Validate the format of the specified timezone.
75
- #
76
- # The implementation of this method calls validate(timezone) method
77
- # to check whether the given timezone is valid. When invalid, this
78
- # method raises a ConfigError.
79
- def self.validate!(timezone)
80
- unless validate(timezone)
81
- raise ConfigError, "Unsupported timezone '#{timezone}'"
82
- end
83
- end
84
-
85
- # Create a formatter for a timezone and optionally a format.
86
- #
87
- # An Proc object is returned. If the given timezone is invalid,
88
- # nil is returned.
89
- def self.formatter(timezone, format = nil)
90
- if timezone.nil?
91
- return nil
92
- end
93
-
94
- # [+-]HH:MM, [+-]HHMM, [+-]HH
95
- if NUMERIC_PATTERN === timezone
96
- offset = Time.zone_offset(timezone)
97
-
98
- if format
99
- return Proc.new {|time|
100
- Time.at(time).localtime(offset).strftime(format)
101
- }
102
- else
103
- return Proc.new {|time|
104
- Time.at(time).localtime(offset).iso8601
105
- }
106
- end
107
- end
108
-
109
- # Region/Zone, Region/Zone/Zone
110
- if NAME_PATTERN === timezone
111
- begin
112
- tz = TZInfo::Timezone.get(timezone)
113
- rescue
114
- return nil
115
- end
116
-
117
- if format
118
- return Proc.new {|time|
119
- Time.at(time).localtime(tz.period_for_utc(time).utc_total_offset).strftime(format)
120
- }
121
- else
122
- return Proc.new {|time|
123
- Time.at(time).localtime(tz.period_for_utc(time).utc_total_offset).iso8601
124
- }
125
- end
126
- end
127
-
128
- return nil
129
- end
130
- end
131
- end
@@ -1,42 +0,0 @@
1
- require 'test/unit/assertions'
2
-
3
- module Test::Unit::Assertions
4
- def assert_text_parsed_as(expected, actual)
5
- msg = parse_text(actual).inspect rescue 'failed'
6
- msg = "expected that #{actual.inspect} would be a parsed as #{expected.inspect} but got #{msg}"
7
- assert_block(msg) {
8
- v = parse_text(actual)
9
- if expected.is_a?(Float)
10
- v.is_a?(Float) && (v == obj || (v.nan? && obj.nan?) || (v - obj).abs < 0.000001)
11
- else
12
- v == expected
13
- end
14
- }
15
- end
16
-
17
- def assert_text_parsed_as_json(expected, actual)
18
- msg = parse_text(actual).inspect rescue 'failed'
19
- msg = "expected that #{actual.inspect} would be a parsed as #{expected.inspect} but got #{msg}"
20
- assert_block(msg) {
21
- v = JSON.parse(parse_text(actual))
22
- v == expected
23
- }
24
- end
25
-
26
- def assert_parse_error(actual)
27
- msg = begin
28
- parse_text(actual).inspect
29
- rescue => e
30
- e.inspect
31
- end
32
- msg = "expected that #{actual.inspect} would cause a parse error but got #{msg}"
33
- assert_block(msg) {
34
- begin
35
- parse_text(actual)
36
- false
37
- rescue Fluent::ConfigParseError
38
- true
39
- end
40
- }
41
- end
42
- end
@@ -1,389 +0,0 @@
1
- require_relative '../helper'
2
- require_relative "assertions"
3
- require "json"
4
- require "fluent/config/error"
5
- require "fluent/config/basic_parser"
6
- require "fluent/config/literal_parser"
7
- require "fluent/config/v1_parser"
8
-
9
- module Fluent::Config
10
- module V1TestHelper
11
- def root(*elements)
12
- if elements.first.is_a?(Fluent::Config::Element)
13
- attrs = {}
14
- else
15
- attrs = elements.shift || {}
16
- end
17
- Fluent::Config::Element.new('ROOT', '', attrs, elements)
18
- end
19
-
20
- def e(name, arg='', attrs={}, elements=[])
21
- Fluent::Config::Element.new(name, arg, attrs, elements)
22
- end
23
- end
24
-
25
- class TestV1Parser < ::Test::Unit::TestCase
26
- def read_config(path)
27
- path = File.expand_path(path)
28
- data = File.read(path)
29
- Fluent::Config::V1Parser.parse(data, File.basename(path), File.dirname(path))
30
- end
31
-
32
- def parse_text(text)
33
- basepath = File.expand_path(File.dirname(__FILE__) + '/../../')
34
- Fluent::Config::V1Parser.parse(text, '(test)', basepath, nil)
35
- end
36
-
37
- include V1TestHelper
38
- extend V1TestHelper
39
-
40
- sub_test_case 'attribute parsing' do
41
- test "parses attributes" do
42
- assert_text_parsed_as(e('ROOT', '', {"k1"=>"v1", "k2"=>"v2"}), %[
43
- k1 v1
44
- k2 v2
45
- ])
46
- end
47
-
48
- test "allows attribute without value" do
49
- assert_text_parsed_as(e('ROOT', '', {"k1"=>"", "k2"=>"v2"}), %[
50
- k1
51
- k2 v2
52
- ])
53
- end
54
-
55
- test "parses attribute key always string" do
56
- assert_text_parsed_as(e('ROOT', '', {"1" => "1"}), "1 1")
57
- end
58
-
59
- data("_.%$!," => "_.%$!,",
60
- "/=~-~@\`:?" => "/=~-~@\`:?",
61
- "()*{}.[]" => "()*{}.[]")
62
- test "parses a value with symbols" do |v|
63
- assert_text_parsed_as(e('ROOT', '', {"k" => v}), "k #{v}")
64
- end
65
-
66
- test "ignores spacing around value" do
67
- assert_text_parsed_as(e('ROOT', '', {"k1" => "a"}), " k1 a ")
68
- end
69
-
70
- test "allows spaces in value" do
71
- assert_text_parsed_as(e('ROOT', '', {"k1" => "a b c"}), "k1 a b c")
72
- end
73
-
74
- sub_test_case 'non-quoted string' do
75
- test "remains text starting with '#'" do
76
- assert_text_parsed_as(e('ROOT', '', {"k1" => "#not_comment"}), " k1 #not_comment")
77
- end
78
-
79
- test "remains text just after '#'" do
80
- assert_text_parsed_as(e('ROOT', '', {"k1" => "a#not_comment"}), " k1 a#not_comment")
81
- end
82
-
83
- test "remove text after ` #` (comment)" do
84
- assert_text_parsed_as(e('ROOT', '', {"k1" => "a"}), " k1 a #comment")
85
- end
86
-
87
- test "does not require escaping backslash" do
88
- assert_text_parsed_as(e('ROOT', '', {"k1" => "\\\\"}), " k1 \\\\")
89
- assert_text_parsed_as(e('ROOT', '', {"k1" => "\\"}), " k1 \\")
90
- end
91
-
92
- test "remains backslash in front of a normal character" do
93
- assert_text_parsed_as(e('ROOT', '', {"k1" => '\['}), " k1 \\[")
94
- end
95
-
96
- test "does not accept escape characters" do
97
- assert_text_parsed_as(e('ROOT', '', {"k1" => '\n'}), " k1 \\n")
98
- end
99
- end
100
-
101
- sub_test_case 'double quoted string' do
102
- test "allows # in value" do
103
- assert_text_parsed_as(e('ROOT', '', {"k1" => "a#comment"}), ' k1 "a#comment"')
104
- end
105
-
106
- test "rejects characters after double quoted string" do
107
- assert_parse_error(' k1 "a" 1')
108
- end
109
-
110
- test "requires escaping backslash" do
111
- assert_text_parsed_as(e('ROOT', '', {"k1" => "\\"}), ' k1 "\\\\"')
112
- assert_parse_error(' k1 "\\"')
113
- end
114
-
115
- test "requires escaping double quote" do
116
- assert_text_parsed_as(e('ROOT', '', {"k1" => '"'}), ' k1 "\\""')
117
- assert_parse_error(' k1 """')
118
- end
119
-
120
- test "removes backslash in front of a normal character" do
121
- assert_text_parsed_as(e('ROOT', '', {"k1" => '['}), ' k1 "\\["')
122
- end
123
-
124
- test "accepts escape characters" do
125
- assert_text_parsed_as(e('ROOT', '', {"k1" => "\n"}), ' k1 "\\n"')
126
- end
127
- end
128
-
129
- sub_test_case 'single quoted string' do
130
- test "allows # in value" do
131
- assert_text_parsed_as(e('ROOT', '', {"k1" => "a#comment"}), " k1 'a#comment'")
132
- end
133
-
134
- test "rejects characters after single quoted string" do
135
- assert_parse_error(" k1 'a' 1")
136
- end
137
-
138
- test "requires escaping backslash" do
139
- assert_text_parsed_as(e('ROOT', '', {"k1" => "\\"}), " k1 '\\\\'")
140
- assert_parse_error(" k1 '\\'")
141
- end
142
-
143
- test "requires escaping single quote" do
144
- assert_text_parsed_as(e('ROOT', '', {"k1" => "'"}), " k1 '\\''")
145
- assert_parse_error(" k1 '''")
146
- end
147
-
148
- test "remains backslash in front of a normal character" do
149
- assert_text_parsed_as(e('ROOT', '', {"k1" => '\\['}), " k1 '\\['")
150
- end
151
-
152
- test "does not accept escape characters" do
153
- assert_text_parsed_as(e('ROOT', '', {"k1" => "\\n"}), " k1 '\\n'")
154
- end
155
- end
156
-
157
- data(
158
- "in match" => %[
159
- <match>
160
- @k v
161
- </match>
162
- ],
163
- "in source" => %[
164
- <source>
165
- @k v
166
- </source>
167
- ],
168
- "in filter" => %[
169
- <filter>
170
- @k v
171
- </filter>
172
- ],
173
- "in top-level" => ' @k v '
174
- )
175
- def test_rejects_at_prefix_in_the_parameter_name(data)
176
- assert_parse_error(data)
177
- end
178
-
179
- data(
180
- "in nested" => %[
181
- <match>
182
- <record>
183
- @k v
184
- </record>
185
- </match>
186
- ]
187
- )
188
- def test_not_reject_at_prefix_in_the_parameter_name(data)
189
- assert_nothing_raised { parse_text(data) }
190
- end
191
- end
192
-
193
- sub_test_case 'element parsing' do
194
- data(
195
- 'root' => [root, ""],
196
- "accepts empty element" => [root(e("test")), %[
197
- <test>
198
- </test>
199
- ]],
200
- "accepts argument and attributes" => [root(e("test", 'var', {'key'=>"val"})), %[
201
- <test var>
202
- key val
203
- </test>
204
- ]],
205
- "accepts nested elements" => [root(
206
- e("test", 'var', {'key'=>'1'}, [
207
- e('nested1'),
208
- e('nested2')
209
- ])), %[
210
- <test var>
211
- key 1
212
- <nested1>
213
- </nested1>
214
- <nested2>
215
- </nested2>
216
- </test>
217
- ]],
218
- "accepts multiline json values" => [root(e("test", 'var', {'key'=>"[\"a\",\"b\",\"c\",\"d\"]"})), %[
219
- <test var>
220
- key ["a",
221
- "b", "c",
222
- "d"]
223
- </test>
224
- ]],
225
- "parses empty element argument to nil" => [root(e("test", '')), %[
226
- <test >
227
- </test>
228
- ]],
229
- "ignores spacing around element argument" => [root(e("test", "a")), %[
230
- <test a >
231
- </test>
232
- ]],
233
- "accepts spacing inside element argument (for multiple tags)" => [root(e("test", "a.** b.**")), %[
234
- <test a.** b.** >
235
- </test>
236
- ]])
237
- def test_parse_element(data)
238
- expected, target = data
239
- assert_text_parsed_as(expected, target)
240
- end
241
-
242
- [
243
- "**",
244
- "*.*",
245
- "1",
246
- "_.%$!",
247
- "/",
248
- "()*{}.[]",
249
- ].each do |arg|
250
- test "parses symbol element argument:#{arg}" do
251
- assert_text_parsed_as(root(e("test", arg)), %[
252
- <test #{arg}>
253
- </test>
254
- ])
255
- end
256
- end
257
-
258
- data(
259
- "considers comments in element argument" => %[
260
- <test #a>
261
- </test>
262
- ],
263
- "requires line_end after begin tag" => %[
264
- <test></test>
265
- ],
266
- "requires line_end after end tag" => %[
267
- <test>
268
- </test><test>
269
- </test>
270
- ])
271
- def test_parse_error(data)
272
- assert_parse_error(data)
273
- end
274
- end
275
-
276
- # port from test_config.rb
277
- sub_test_case '@include parsing' do
278
- TMP_DIR = File.dirname(__FILE__) + "/tmp/v1_config#{ENV['TEST_ENV_NUMBER']}"
279
-
280
- def write_config(path, data)
281
- FileUtils.mkdir_p(File.dirname(path))
282
- File.open(path, "w") { |f| f.write data }
283
- end
284
-
285
- def prepare_config
286
- write_config "#{TMP_DIR}/config_test_1.conf", %[
287
- k1 root_config
288
- include dir/config_test_2.conf #
289
- @include #{TMP_DIR}/config_test_4.conf
290
- include file://#{TMP_DIR}/config_test_5.conf
291
- @include config.d/*.conf
292
- ]
293
- write_config "#{TMP_DIR}/dir/config_test_2.conf", %[
294
- k2 relative_path_include
295
- @include ../config_test_3.conf
296
- ]
297
- write_config "#{TMP_DIR}/config_test_3.conf", %[
298
- k3 relative_include_in_included_file
299
- ]
300
- write_config "#{TMP_DIR}/config_test_4.conf", %[
301
- k4 absolute_path_include
302
- ]
303
- write_config "#{TMP_DIR}/config_test_5.conf", %[
304
- k5 uri_include
305
- ]
306
- write_config "#{TMP_DIR}/config.d/config_test_6.conf", %[
307
- k6 wildcard_include_1
308
- <elem1 name>
309
- include normal_parameter
310
- </elem1>
311
- ]
312
- write_config "#{TMP_DIR}/config.d/config_test_7.conf", %[
313
- k7 wildcard_include_2
314
- ]
315
- write_config "#{TMP_DIR}/config.d/config_test_8.conf", %[
316
- <elem2 name>
317
- @include ../dir/config_test_9.conf
318
- </elem2>
319
- ]
320
- write_config "#{TMP_DIR}/dir/config_test_9.conf", %[
321
- k9 embeded
322
- <elem3 name>
323
- nested nested_value
324
- include hoge
325
- </elem3>
326
- ]
327
- write_config "#{TMP_DIR}/config.d/00_config_test_8.conf", %[
328
- k8 wildcard_include_3
329
- <elem4 name>
330
- include normal_parameter
331
- </elem4>
332
- ]
333
- end
334
-
335
- test 'parses @include / include correctly' do
336
- prepare_config
337
- c = read_config("#{TMP_DIR}/config_test_1.conf")
338
- assert_equal('root_config', c['k1'])
339
- assert_equal('relative_path_include', c['k2'])
340
- assert_equal('relative_include_in_included_file', c['k3'])
341
- assert_equal('absolute_path_include', c['k4'])
342
- assert_equal('uri_include', c['k5'])
343
- assert_equal('wildcard_include_1', c['k6'])
344
- assert_equal('wildcard_include_2', c['k7'])
345
- assert_equal('wildcard_include_3', c['k8'])
346
- assert_equal([
347
- 'k1',
348
- 'k2',
349
- 'k3',
350
- 'k4',
351
- 'k5',
352
- 'k8', # Because of the file name this comes first.
353
- 'k6',
354
- 'k7',
355
- ], c.keys)
356
-
357
- elem1 = c.elements.find { |e| e.name == 'elem1' }
358
- assert(elem1)
359
- assert_equal('name', elem1.arg)
360
- assert_equal('normal_parameter', elem1['include'])
361
-
362
- elem2 = c.elements.find { |e| e.name == 'elem2' }
363
- assert(elem2)
364
- assert_equal('name', elem2.arg)
365
- assert_equal('embeded', elem2['k9'])
366
- assert_not_include(elem2, 'include')
367
-
368
- elem3 = elem2.elements.find { |e| e.name == 'elem3' }
369
- assert(elem3)
370
- assert_equal('nested_value', elem3['nested'])
371
- assert_equal('hoge', elem3['include'])
372
- end
373
-
374
- # TODO: Add uri based include spec
375
- end
376
-
377
- sub_test_case '#to_s' do
378
- test 'parses dumpped configuration' do
379
- original = %q!a\\\n\r\f\b'"z!
380
- expected = %q!a\\\n\r\f\b'"z!
381
-
382
- conf = parse_text(%[k1 #{original}])
383
- assert_equal(expected, conf['k1']) # escape check
384
- conf2 = parse_text(conf.to_s) # use dumpped configuration to check unescape
385
- assert_equal(expected, conf2.elements.first['k1'])
386
- end
387
- end
388
- end
389
- end