hocon 1.2.5 → 1.2.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +6 -1
  3. data/lib/hocon/version.rb +1 -1
  4. metadata +1 -47
  5. data/spec/fixtures/hocon/by_extension/cat.conf +0 -4
  6. data/spec/fixtures/hocon/by_extension/cat.test +0 -4
  7. data/spec/fixtures/hocon/by_extension/cat.test-json +0 -3
  8. data/spec/fixtures/hocon/with_substitution/subst.conf +0 -2
  9. data/spec/fixtures/parse_render/example1/input.conf +0 -21
  10. data/spec/fixtures/parse_render/example1/output.conf +0 -26
  11. data/spec/fixtures/parse_render/example1/output_nocomments.conf +0 -17
  12. data/spec/fixtures/parse_render/example2/input.conf +0 -10
  13. data/spec/fixtures/parse_render/example2/output.conf +0 -17
  14. data/spec/fixtures/parse_render/example2/output_nocomments.conf +0 -17
  15. data/spec/fixtures/parse_render/example3/input.conf +0 -2
  16. data/spec/fixtures/parse_render/example3/output.conf +0 -2
  17. data/spec/fixtures/parse_render/example4/input.json +0 -6
  18. data/spec/fixtures/parse_render/example4/output.conf +0 -6
  19. data/spec/fixtures/test_utils/resources/bom.conf +0 -2
  20. data/spec/fixtures/test_utils/resources/cycle.conf +0 -1
  21. data/spec/fixtures/test_utils/resources/file-include.conf +0 -5
  22. data/spec/fixtures/test_utils/resources/include-from-list.conf +0 -4
  23. data/spec/fixtures/test_utils/resources/subdir/bar.conf +0 -1
  24. data/spec/fixtures/test_utils/resources/subdir/baz.conf +0 -1
  25. data/spec/fixtures/test_utils/resources/subdir/foo.conf +0 -5
  26. data/spec/fixtures/test_utils/resources/test01.conf +0 -80
  27. data/spec/fixtures/test_utils/resources/test01.json +0 -4
  28. data/spec/fixtures/test_utils/resources/test03.conf +0 -36
  29. data/spec/fixtures/test_utils/resources/utf16.conf +0 -0
  30. data/spec/fixtures/test_utils/resources/utf8.conf +0 -2
  31. data/spec/fixtures/test_utils/resources//341/232/240/341/233/207/341/232/273.conf +0 -2
  32. data/spec/spec_helper.rb +0 -43
  33. data/spec/test_utils.rb +0 -758
  34. data/spec/unit/cli/cli_spec.rb +0 -157
  35. data/spec/unit/hocon/README.md +0 -7
  36. data/spec/unit/hocon/hocon_spec.rb +0 -114
  37. data/spec/unit/typesafe/config/README.md +0 -4
  38. data/spec/unit/typesafe/config/concatenation_spec.rb +0 -417
  39. data/spec/unit/typesafe/config/conf_parser_spec.rb +0 -831
  40. data/spec/unit/typesafe/config/config_document_parser_spec.rb +0 -494
  41. data/spec/unit/typesafe/config/config_document_spec.rb +0 -576
  42. data/spec/unit/typesafe/config/config_factory_spec.rb +0 -120
  43. data/spec/unit/typesafe/config/config_node_spec.rb +0 -552
  44. data/spec/unit/typesafe/config/config_value_factory_spec.rb +0 -85
  45. data/spec/unit/typesafe/config/config_value_spec.rb +0 -959
  46. data/spec/unit/typesafe/config/path_spec.rb +0 -261
  47. data/spec/unit/typesafe/config/public_api_spec.rb +0 -520
  48. data/spec/unit/typesafe/config/simple_config_spec.rb +0 -112
  49. data/spec/unit/typesafe/config/token_spec.rb +0 -188
  50. data/spec/unit/typesafe/config/tokenizer_spec.rb +0 -801
@@ -1,758 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require 'hocon'
4
- require 'spec_helper'
5
- require 'rspec'
6
- require 'hocon/impl/config_reference'
7
- require 'hocon/impl/substitution_expression'
8
- require 'hocon/impl/path_parser'
9
- require 'hocon/impl/config_impl_util'
10
- require 'hocon/impl/config_node_simple_value'
11
- require 'hocon/impl/config_node_single_token'
12
- require 'hocon/impl/config_node_object'
13
- require 'hocon/impl/config_node_array'
14
- require 'hocon/impl/config_node_concatenation'
15
- require 'hocon/cli'
16
-
17
- module TestUtils
18
- Tokens = Hocon::Impl::Tokens
19
- ConfigInt = Hocon::Impl::ConfigInt
20
- ConfigDouble = Hocon::Impl::ConfigDouble
21
- ConfigString = Hocon::Impl::ConfigString
22
- ConfigNull = Hocon::Impl::ConfigNull
23
- ConfigBoolean = Hocon::Impl::ConfigBoolean
24
- ConfigReference = Hocon::Impl::ConfigReference
25
- SubstitutionExpression = Hocon::Impl::SubstitutionExpression
26
- ConfigConcatenation = Hocon::Impl::ConfigConcatenation
27
- Path = Hocon::Impl::Path
28
- EOF = Hocon::Impl::TokenType::EOF
29
-
30
- include RSpec::Matchers
31
-
32
- def self.intercept(exception_type, & block)
33
- thrown = nil
34
- result = nil
35
- begin
36
- result = block.call
37
- rescue => e
38
- if e.is_a?(exception_type)
39
- thrown = e
40
- else
41
- raise "Expected exception #{exception_type} was not thrown, got #{e.class}: #{e}\n#{e.backtrace.join("\n")}"
42
- end
43
- end
44
- if thrown.nil?
45
- raise "Expected exception #{exception_type} was not thrown, no exception was thrown and got result #{result}"
46
- end
47
- thrown
48
- end
49
-
50
- class ParseTest
51
-
52
- def self.from_s(test)
53
- ParseTest.new(false, false, test)
54
- end
55
-
56
- def self.from_pair(lift_behavior_unexpected, test)
57
- ParseTest.new(lift_behavior_unexpected, false, test)
58
- end
59
-
60
- def initialize(lift_behavior_unexpected, whitespace_matters, test)
61
- @lift_behavior_unexpected = lift_behavior_unexpected
62
- @whitespace_matters = whitespace_matters
63
- @test = test
64
- end
65
- attr_reader :test
66
-
67
- def lift_behavior_unexpected?
68
- @lift_behavior_unexpected
69
- end
70
-
71
- def whitespace_matters?
72
- @whitespace_matters
73
- end
74
- end
75
-
76
-
77
- # note: it's important to put {} or [] at the root if you
78
- # want to test "invalidity reasons" other than "wrong root"
79
- InvalidJsonInvalidConf = [
80
- ParseTest.from_s("{"),
81
- ParseTest.from_s("}"),
82
- ParseTest.from_s("["),
83
- ParseTest.from_s("]"),
84
- ParseTest.from_s(","),
85
- ParseTest.from_pair(true, "10"), # value not in array or object, lift-json now allows this
86
- ParseTest.from_pair(true, "\"foo\""), # value not in array or object, lift-json allows it
87
- ParseTest.from_s(")\""), # single quote by itself
88
- ParseTest.from_pair(true, "[,]"), # array with just a comma in it; lift is OK with this
89
- ParseTest.from_pair(true, "[,,]"), # array with just two commas in it; lift is cool with this too
90
- ParseTest.from_pair(true, "[1,2,,]"), # array with two trailing commas
91
- ParseTest.from_pair(true, "[,1,2]"), # array with initial comma
92
- ParseTest.from_pair(true, "{ , }"), # object with just a comma in it
93
- ParseTest.from_pair(true, "{ , , }"), # object with just two commas in it
94
- ParseTest.from_s("{ 1,2 }"), # object with single values not key-value pair
95
- ParseTest.from_pair(true, '{ , "foo" : 10 }'), # object starts with comma
96
- ParseTest.from_pair(true, "{ \"foo\" : 10 ,, }"), # object has two trailing commas
97
- ParseTest.from_s(") \"a\" : 10 ,, "), # two trailing commas for braceless root object
98
- ParseTest.from_s("{ \"foo\" : }"), # no value in object
99
- ParseTest.from_s("{ : 10 }"), # no key in object
100
- ParseTest.from_pair(true, " \"foo\" : "), # no value in object with no braces; lift-json thinks this is acceptable
101
- ParseTest.from_pair(true, " : 10 "), # no key in object with no braces; lift-json is cool with this too
102
- ParseTest.from_s(') "foo" : 10 } '), # close brace but no open
103
- ParseTest.from_s(") \"foo\" : 10 } "), # close brace but no open
104
- ParseTest.from_s(") \"foo\" : 10 [ "), # no-braces object with trailing gunk
105
- ParseTest.from_s("{ \"foo\" }"), # no value or colon
106
- ParseTest.from_s("{ \"a\" : [ }"), # [ is not a valid value
107
- ParseTest.from_s("{ \"foo\" : 10, true }"), # non-key after comma
108
- ParseTest.from_s("{ foo \n bar : 10 }"), # newline in the middle of the unquoted key
109
- ParseTest.from_s("[ 1, \\"), # ends with backslash
110
- # these two problems are ignored by the lift tokenizer
111
- ParseTest.from_s("[:\"foo\", \"bar\"]"), # colon in an array; lift doesn't throw (tokenizer erases it)
112
- ParseTest.from_s("[\"foo\" : \"bar\"]"), # colon in an array another way, lift ignores (tokenizer erases it)
113
- ParseTest.from_s("[ \"hello ]"), # unterminated string
114
- ParseTest.from_pair(true, "{ \"foo\" , true }"), # comma instead of colon, lift is fine with this
115
- ParseTest.from_pair(true, "{ \"foo\" : true \"bar\" : false }"), # missing comma between fields, lift fine with this
116
- ParseTest.from_s("[ 10, }]"), # array with } as an element
117
- ParseTest.from_s("[ 10, {]"), # array with { as an element
118
- ParseTest.from_s("{}x"), # trailing invalid token after the root object
119
- ParseTest.from_s("[]x"), # trailing invalid token after the root array
120
- ParseTest.from_pair(true, "{}{}"), # trailing token after the root object - lift OK with it
121
- ParseTest.from_pair(true, "{}true"), # trailing token after the root object; lift ignores the {}
122
- ParseTest.from_pair(true, "[]{}"), # trailing valid token after the root array
123
- ParseTest.from_pair(true, "[]true"), # trailing valid token after the root array, lift ignores the []
124
- ParseTest.from_s("[${]"), # unclosed substitution
125
- ParseTest.from_s("[$]"), # '$' by itself
126
- ParseTest.from_s("[$ ]"), # '$' by itself with spaces after
127
- ParseTest.from_s("[${}]"), # empty substitution (no path)
128
- ParseTest.from_s("[${?}]"), # no path with ? substitution
129
- ParseTest.new(false, true, "[${ ?foo}]"), # space before ? not allowed
130
- ParseTest.from_s(%q|{ "a" : [1,2], "b" : y${a}z }|), # trying to interpolate an array in a string
131
- ParseTest.from_s(%q|{ "a" : { "c" : 2 }, "b" : y${a}z }|), # trying to interpolate an object in a string
132
- ParseTest.from_s(%q|{ "a" : ${a} }|), # simple cycle
133
- ParseTest.from_s(%q|[ { "a" : 2, "b" : ${${a}} } ]|), # nested substitution
134
- ParseTest.from_s("[ = ]"), # = is not a valid token in unquoted text
135
- ParseTest.from_s("[ + ]"),
136
- ParseTest.from_s("[ # ]"),
137
- ParseTest.from_s("[ ` ]"),
138
- ParseTest.from_s("[ ^ ]"),
139
- ParseTest.from_s("[ ? ]"),
140
- ParseTest.from_s("[ ! ]"),
141
- ParseTest.from_s("[ @ ]"),
142
- ParseTest.from_s("[ * ]"),
143
- ParseTest.from_s("[ & ]"),
144
- ParseTest.from_s("[ \\ ]"),
145
- ParseTest.from_s("+="),
146
- ParseTest.from_s("[ += ]"),
147
- ParseTest.from_s("+= 10"),
148
- ParseTest.from_s("10 +="),
149
- ParseTest.from_s("[ 10e+3e ]"), # "+" not allowed in unquoted strings, and not a valid number
150
- ParseTest.from_pair(true, "[ \"foo\nbar\" ]"), # unescaped newline in quoted string, lift doesn't care
151
- ParseTest.from_s("[ # comment ]"),
152
- ParseTest.from_s("${ #comment }"),
153
- ParseTest.from_s("[ // comment ]"),
154
- ParseTest.from_s("${ // comment }"),
155
- # ParseTest.from_s("{ include \"bar\" : 10 }"), # include with a value after it
156
- ParseTest.from_s("{ include foo }"), # include with unquoted string
157
- ParseTest.from_s("{ include : { \"a\" : 1 } }"), # include used as unquoted key
158
- ParseTest.from_s("a="), # no value
159
- ParseTest.from_s("a:"), # no value with colon
160
- ParseTest.from_s("a= "), # no value with whitespace after
161
- ParseTest.from_s("a.b="), # no value with path
162
- ParseTest.from_s("{ a= }"), # no value inside braces
163
- ParseTest.from_s("{ a: }") # no value with colon inside braces
164
- ]
165
-
166
- # We'll automatically try each of these with whitespace modifications
167
- # so no need to add every possible whitespace variation
168
- ValidJson = [
169
- ParseTest.from_s("{}"),
170
- ParseTest.from_s("[]"),
171
- ParseTest.from_s(%q|{ "foo" : "bar" }|),
172
- ParseTest.from_s(%q|["foo", "bar"]|),
173
- ParseTest.from_s(%q|{ "foo" : 42 }|),
174
- ParseTest.from_s("{ \"foo\"\n : 42 }"), # newline after key
175
- ParseTest.from_s("{ \"foo\" : \n 42 }"), # newline after colon
176
- ParseTest.from_s(%q|[10, 11]|),
177
- ParseTest.from_s(%q|[10,"foo"]|),
178
- ParseTest.from_s(%q|{ "foo" : "bar", "baz" : "boo" }|),
179
- ParseTest.from_s(%q|{ "foo" : { "bar" : "baz" }, "baz" : "boo" }|),
180
- ParseTest.from_s(%q|{ "foo" : { "bar" : "baz", "woo" : "w00t" }, "baz" : "boo" }|),
181
- ParseTest.from_s(%q|{ "foo" : [10,11,12], "baz" : "boo" }|),
182
- ParseTest.from_s(%q|[{},{},{},{}]|),
183
- ParseTest.from_s(%q|[[[[[[]]]]]]|),
184
- ParseTest.from_s(%q|[[1], [1,2], [1,2,3], []]|), # nested multiple-valued array
185
- ParseTest.from_s(%q|{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":42}}}}}}}}|),
186
- ParseTest.from_s("[ \"#comment\" ]"), # quoted # comment
187
- ParseTest.from_s("[ \"//comment\" ]"), # quoted // comment
188
- # this long one is mostly to test rendering
189
- ParseTest.from_s(%q|{ "foo" : { "bar" : "baz", "woo" : "w00t" }, "baz" : { "bar" : "baz", "woo" : [1,2,3,4], "w00t" : true, "a" : false, "b" : 3.14, "c" : null } }|),
190
- ParseTest.from_s("{}"),
191
- ParseTest.from_pair(true, "[ 10e+3 ]") # "+" in a number (lift doesn't handle))
192
- ]
193
-
194
- ValidConfInvalidJson = [
195
- ParseTest.from_s(""), # empty document
196
- ParseTest.from_s(" "), # empty document single space
197
- ParseTest.from_s("\n"), # empty document single newline
198
- ParseTest.from_s(" \n \n \n\n\n"), # complicated empty document
199
- ParseTest.from_s("# foo"), # just a comment
200
- ParseTest.from_s("# bar\n"), # just a comment with a newline
201
- ParseTest.from_s("# foo\n//bar"), # comment then another with no newline
202
- ParseTest.from_s(%q|{ "foo" = 42 }|), # equals rather than colon
203
- ParseTest.from_s(%q|{ foo { "bar" : 42 } }|), # omit the colon for object value
204
- ParseTest.from_s(%q|{ foo baz { "bar" : 42 } }|), # omit the colon with unquoted key with spaces
205
- ParseTest.from_s(%q| "foo" : 42 |), # omit braces on root object
206
- ParseTest.from_s(%q|{ "foo" : bar }|), # no quotes on value
207
- ParseTest.from_s(%q|{ "foo" : null bar 42 baz true 3.14 "hi" }|), # bunch of values to concat into a string
208
- ParseTest.from_s("{ foo : \"bar\" }"), # no quotes on key
209
- ParseTest.from_s("{ foo : bar }"), # no quotes on key or value
210
- ParseTest.from_s("{ foo.bar : bar }"), # path expression in key
211
- ParseTest.from_s("{ foo.\"hello world\".baz : bar }"), # partly-quoted path expression in key
212
- ParseTest.from_s("{ foo.bar \n : bar }"), # newline after path expression in key
213
- ParseTest.from_s("{ foo bar : bar }"), # whitespace in the key
214
- ParseTest.from_s("{ true : bar }"), # key is a non-string token
215
- ParseTest.from_pair(true, %q|{ "foo" : "bar", "foo" : "bar2" }|), # dup keys - lift just returns both
216
- ParseTest.from_pair(true, "[ 1, 2, 3, ]"), # single trailing comma (lift fails to throw)
217
- ParseTest.from_pair(true, "[1,2,3 , ]"), # single trailing comma with whitespace
218
- ParseTest.from_pair(true, "[1,2,3\n\n , \n]"), # single trailing comma with newlines
219
- ParseTest.from_pair(true, "[1,]"), # single trailing comma with one-element array
220
- ParseTest.from_pair(true, "{ \"foo\" : 10, }"), # extra trailing comma (lift fails to throw)
221
- ParseTest.from_pair(true, "{ \"a\" : \"b\", }"), # single trailing comma in object
222
- ParseTest.from_s("{ a : b, }"), # single trailing comma in object (unquoted strings)
223
- ParseTest.from_s("{ a : b \n , \n }"), # single trailing comma in object with newlines
224
- ParseTest.from_s("a : b, c : d,"), # single trailing comma in object with no root braces
225
- ParseTest.from_s("{ a : b\nc : d }"), # skip comma if there's a newline
226
- ParseTest.from_s("a : b\nc : d"), # skip comma if there's a newline and no root braces
227
- ParseTest.from_s("a : b\nc : d,"), # skip one comma but still have one at the end
228
- ParseTest.from_s("[ foo ]"), # not a known token in JSON
229
- ParseTest.from_s("[ t ]"), # start of "true" but ends wrong in JSON
230
- ParseTest.from_s("[ tx ]"),
231
- ParseTest.from_s("[ tr ]"),
232
- ParseTest.from_s("[ trx ]"),
233
- ParseTest.from_s("[ tru ]"),
234
- ParseTest.from_s("[ trux ]"),
235
- ParseTest.from_s("[ truex ]"),
236
- ParseTest.from_s("[ 10x ]"), # number token with trailing junk
237
- ParseTest.from_s("[ / ]"), # unquoted string "slash"
238
- ParseTest.from_s("{ include \"foo\" }"), # valid include
239
- ParseTest.from_s("{ include\n\"foo\" }"), # include with just a newline separating from string
240
- ParseTest.from_s("{ include\"foo\" }"), # include with no whitespace after it
241
- ParseTest.from_s("[ include ]"), # include can be a string value in an array
242
- ParseTest.from_s("{ foo : include }"), # include can be a field value also
243
- ParseTest.from_s("{ include \"foo\", \"a\" : \"b\" }"), # valid include followed by comma and field
244
- ParseTest.from_s("{ foo include : 42 }"), # valid to have a key not starting with include
245
- ParseTest.from_s("[ ${foo} ]"),
246
- ParseTest.from_s("[ ${?foo} ]"),
247
- ParseTest.from_s("[ ${\"foo\"} ]"),
248
- ParseTest.from_s("[ ${foo.bar} ]"),
249
- ParseTest.from_s("[ abc xyz ${foo.bar} qrs tuv ]"), # value concatenation
250
- ParseTest.from_s("[ 1, 2, 3, blah ]"),
251
- ParseTest.from_s("[ ${\"foo.bar\"} ]"),
252
- ParseTest.from_s("{} # comment"),
253
- ParseTest.from_s("{} // comment"),
254
- ParseTest.from_s(%q|{ "foo" #comment
255
- : 10 }|),
256
- ParseTest.from_s(%q|{ "foo" // comment
257
- : 10 }|),
258
- ParseTest.from_s(%q|{ "foo" : #comment
259
- 10 }|),
260
- ParseTest.from_s(%q|{ "foo" : // comment
261
- 10 }|),
262
- ParseTest.from_s(%q|{ "foo" : 10 #comment
263
- }|),
264
- ParseTest.from_s(%q|{ "foo" : 10 // comment
265
- }|),
266
- ParseTest.from_s(%q|[ 10, # comment
267
- 11]|),
268
- ParseTest.from_s(%q|[ 10, // comment
269
- 11]|),
270
- ParseTest.from_s(%q|[ 10 # comment
271
- , 11]|),
272
- ParseTest.from_s(%q|[ 10 // comment
273
- , 11]|),
274
- ParseTest.from_s(%q|{ /a/b/c : 10 }|), # key has a slash in it
275
- ParseTest.new(false, true, "[${ foo.bar}]"), # substitution with leading spaces
276
- ParseTest.new(false, true, "[${foo.bar }]"), # substitution with trailing spaces
277
- ParseTest.new(false, true, "[${ \"foo.bar\"}]"), # substitution with leading spaces and quoted
278
- ParseTest.new(false, true, "[${\"foo.bar\" }]"), # substitution with trailing spaces and quoted
279
- ParseTest.from_s(%q|[ ${"foo""bar"} ]|), # multiple strings in substitution
280
- ParseTest.from_s(%q|[ ${foo "bar" baz} ]|), # multiple strings and whitespace in substitution
281
- ParseTest.from_s("[${true}]"), # substitution with unquoted true token
282
- ParseTest.from_s("a = [], a += b"), # += operator with previous init
283
- ParseTest.from_s("{ a = [], a += 10 }"), # += in braces object with previous init
284
- ParseTest.from_s("a += b"), # += operator without previous init
285
- ParseTest.from_s("{ a += 10 }"), # += in braces object without previous init
286
- ParseTest.from_s("[ 10e3e3 ]"), # two exponents. this should parse to a number plus string "e3"
287
- ParseTest.from_s("[ 1-e3 ]"), # malformed number should end up as a string instead
288
- ParseTest.from_s("[ 1.0.0 ]"), # two decimals, should end up as a string
289
- ParseTest.from_s("[ 1.0. ]")
290
- ]
291
-
292
-
293
- InvalidConf = InvalidJsonInvalidConf
294
-
295
- # .conf is a superset of JSON so validJson just goes in here
296
- ValidConf = ValidConfInvalidJson + ValidJson
297
-
298
- def self.add_offending_json_to_exception(parser_name, s, & block)
299
- begin
300
- block.call
301
- rescue => e
302
- tokens =
303
- begin
304
- "tokens: " + TestUtils.tokenize_as_list(s).join("\n")
305
- rescue => tokenize_ex
306
- "tokenizer failed: #{tokenize_ex}\n#{tokenize_ex.backtrace.join("\n")}"
307
- end
308
- raise ArgumentError, "#{parser_name} parser did wrong thing on '#{s}', #{tokens}; error: #{e}\n#{e.backtrace.join("\n")}"
309
- end
310
- end
311
-
312
- def self.whitespace_variations(tests, valid_in_lift)
313
- variations = [
314
- Proc.new { |s| s }, # identity
315
- Proc.new { |s| " " + s },
316
- Proc.new { |s| s + " " },
317
- Proc.new { |s| " " + s + " " },
318
- Proc.new { |s| s.gsub(" ", "") }, # this would break with whitespace in a key or value
319
- Proc.new { |s| s.gsub(":", " : ") }, # could break with : in a key or value
320
- Proc.new { |s| s.gsub(",", " , ") }, # could break with , in a key or value
321
- ]
322
- tests.map { |t|
323
- if t.whitespace_matters?
324
- t
325
- else
326
- with_no_ascii =
327
- if t.test.include?(" ")
328
- [ParseTest.from_pair(valid_in_lift,
329
- t.test.gsub(" ", "\u2003"))] # 2003 = em space, to test non-ascii whitespace
330
- else
331
- []
332
- end
333
-
334
- with_no_ascii << variations.reduce([]) { |acc, v|
335
- acc << ParseTest.from_pair(t.lift_behavior_unexpected?, v.call(t.test))
336
- acc
337
- }
338
- end
339
- }.flatten
340
- end
341
-
342
-
343
- ##################
344
- # Tokenizer Functions
345
- ##################
346
- def self.wrap_tokens(token_list)
347
- # Wraps token_list in START and EOF tokens
348
- [Tokens::START] + token_list + [Tokens::EOF]
349
- end
350
-
351
- def self.tokenize(config_origin, input)
352
- Hocon::Impl::Tokenizer.tokenize(config_origin, input, Hocon::ConfigSyntax::CONF)
353
- end
354
-
355
- def self.tokenize_from_s(s)
356
- tokenize(Hocon::Impl::SimpleConfigOrigin.new_simple("anonymous Reader"),
357
- StringIO.new(s))
358
- end
359
-
360
- def self.tokenize_as_list(input_string)
361
- token_iterator = tokenize_from_s(input_string)
362
-
363
- token_iterator.to_list
364
- end
365
-
366
- def self.tokenize_as_string(input_string)
367
- Hocon::Impl::Tokenizer.render(tokenize_from_s(input_string))
368
- end
369
-
370
- def self.config_node_simple_value(value)
371
- Hocon::Impl::ConfigNodeSimpleValue.new(value)
372
- end
373
-
374
- def self.config_node_key(path)
375
- Hocon::Impl::PathParser.parse_path_node(path)
376
- end
377
-
378
- def self.config_node_single_token(value)
379
- Hocon::Impl::ConfigNodeSingleToken.new(value)
380
- end
381
-
382
- def self.config_node_object(nodes)
383
- Hocon::Impl::ConfigNodeObject.new(nodes)
384
- end
385
-
386
- def self.config_node_array(nodes)
387
- Hocon::Impl::ConfigNodeArray.new(nodes)
388
- end
389
-
390
- def self.config_node_concatenation(nodes)
391
- Hocon::Impl::ConfigNodeConcatenation.new(nodes)
392
- end
393
-
394
- def self.node_colon
395
- Hocon::Impl::ConfigNodeSingleToken.new(Tokens::COLON)
396
- end
397
-
398
- def self.node_space
399
- Hocon::Impl::ConfigNodeSingleToken.new(token_unquoted(" "))
400
- end
401
-
402
- def self.node_open_brace
403
- Hocon::Impl::ConfigNodeSingleToken.new(Tokens::OPEN_CURLY)
404
- end
405
-
406
- def self.node_close_brace
407
- Hocon::Impl::ConfigNodeSingleToken.new(Tokens::CLOSE_CURLY)
408
- end
409
-
410
- def self.node_open_bracket
411
- Hocon::Impl::ConfigNodeSingleToken.new(Tokens::OPEN_SQUARE)
412
- end
413
-
414
- def self.node_close_bracket
415
- Hocon::Impl::ConfigNodeSingleToken.new(Tokens::CLOSE_SQUARE)
416
- end
417
-
418
- def self.node_comma
419
- Hocon::Impl::ConfigNodeSingleToken.new(Tokens::COMMA)
420
- end
421
-
422
- def self.node_line(line)
423
- Hocon::Impl::ConfigNodeSingleToken.new(token_line(line))
424
- end
425
-
426
- def self.node_whitespace(whitespace)
427
- Hocon::Impl::ConfigNodeSingleToken.new(token_whitespace(whitespace))
428
- end
429
-
430
- def self.node_key_value_pair(key, value)
431
- nodes = [key, node_colon, node_space, value]
432
- Hocon::Impl::ConfigNodeField.new(nodes)
433
- end
434
-
435
- def self.node_int(value)
436
- Hocon::Impl::ConfigNodeSimpleValue.new(token_int(value))
437
- end
438
-
439
- def self.node_string(value)
440
- Hocon::Impl::ConfigNodeSimpleValue.new(token_string(value))
441
- end
442
-
443
- def self.node_double(value)
444
- Hocon::Impl::ConfigNodeSimpleValue.new(token_double(value))
445
- end
446
-
447
- def self.node_true
448
- Hocon::Impl::ConfigNodeSimpleValue.new(token_true)
449
- end
450
-
451
- def self.node_false
452
- Hocon::Impl::ConfigNodeSimpleValue.new(token_false)
453
- end
454
-
455
- def self.node_comment_hash(text)
456
- Hocon::Impl::ConfigNodeComment.new(token_comment_hash(text))
457
- end
458
-
459
- def self.node_comment_double_slash(text)
460
- Hocon::Impl::ConfigNodeComment.new(token_comment_double_slash(text))
461
- end
462
-
463
- def self.node_unquoted_text(text)
464
- Hocon::Impl::ConfigNodeSimpleValue.new(token_unquoted(text))
465
- end
466
-
467
- def self.node_null
468
- Hocon::Impl::ConfigNodeSimpleValue.new(token_null)
469
- end
470
-
471
- def self.node_key_substitution(s)
472
- Hocon::Impl::ConfigNodeSimpleValue.new(token_key_substitution(s))
473
- end
474
-
475
- def self.node_optional_substitution(*expression)
476
- Hocon::Impl::ConfigNodeSimpleValue.new(token_optional_substitution(*expression))
477
- end
478
-
479
- def self.node_substitution(*expression)
480
- Hocon::Impl::ConfigNodeSimpleValue.new(token_substitution(*expression))
481
- end
482
-
483
- def self.fake_origin
484
- Hocon::Impl::SimpleConfigOrigin.new_simple("fake origin")
485
- end
486
-
487
- def self.token_line(line_number)
488
- Tokens.new_line(fake_origin.with_line_number(line_number))
489
- end
490
-
491
- def self.token_true
492
- Tokens.new_boolean(fake_origin, true)
493
- end
494
-
495
- def self.token_false
496
- Tokens.new_boolean(fake_origin, false)
497
- end
498
-
499
- def self.token_null
500
- Tokens.new_null(fake_origin)
501
- end
502
-
503
- def self.token_unquoted(value)
504
- Tokens.new_unquoted_text(fake_origin, value)
505
- end
506
-
507
- def self.token_comment_double_slash(value)
508
- Tokens.new_comment_double_slash(fake_origin, value)
509
- end
510
-
511
- def self.token_comment_hash(value)
512
- Tokens.new_comment_hash(fake_origin, value)
513
- end
514
-
515
- def self.token_whitespace(value)
516
- Tokens.new_ignored_whitespace(fake_origin, value)
517
- end
518
-
519
- def self.token_string(value)
520
- Tokens.new_string(fake_origin, value, "\"#{value}\"")
521
- end
522
-
523
- def self.token_double(value)
524
- Tokens.new_double(fake_origin, value, "#{value}")
525
- end
526
-
527
- def self.token_int(value)
528
- Tokens.new_int(fake_origin, value, "#{value}")
529
- end
530
-
531
- def self.token_maybe_optional_substitution(optional, token_list)
532
- Tokens.new_substitution(fake_origin, optional, token_list)
533
- end
534
-
535
- def self.token_substitution(*token_list)
536
- token_maybe_optional_substitution(false, token_list)
537
- end
538
-
539
- def self.token_optional_substitution(*token_list)
540
- token_maybe_optional_substitution(true, token_list)
541
- end
542
-
543
- def self.token_key_substitution(value)
544
- token_substitution(token_string(value))
545
- end
546
-
547
- def self.parse_object(s)
548
- parse_config(s).root
549
- end
550
-
551
- def self.parse_config(s)
552
- options = Hocon::ConfigParseOptions.defaults.
553
- set_origin_description("test string").
554
- set_syntax(Hocon::ConfigSyntax::CONF)
555
- Hocon::ConfigFactory.parse_string(s, options)
556
- end
557
-
558
- ##################
559
- # ConfigValue helpers
560
- ##################
561
- def self.int_value(value)
562
- ConfigInt.new(fake_origin, value, nil)
563
- end
564
-
565
- def self.double_value(value)
566
- ConfigDouble.new(fake_origin, value, nil)
567
- end
568
-
569
- def self.string_value(value)
570
- ConfigString::Quoted.new(fake_origin, value)
571
- end
572
-
573
- def self.null_value
574
- ConfigNull.new(fake_origin)
575
- end
576
-
577
- def self.bool_value(value)
578
- ConfigBoolean.new(fake_origin, value)
579
- end
580
-
581
- def self.config_map(input_map)
582
- # Turns {String: Int} maps into {String: ConfigInt} maps
583
- Hash[ input_map.map { |k, v| [k, int_value(v)] } ]
584
- end
585
-
586
- def self.subst(ref, optional = false)
587
- path = Path.new_path(ref)
588
- ConfigReference.new(fake_origin, SubstitutionExpression.new(path, optional))
589
- end
590
-
591
- def self.subst_in_string(ref, optional = false)
592
- pieces = [string_value("start<"), subst(ref, optional), string_value(">end")]
593
- ConfigConcatenation.new(fake_origin, pieces)
594
- end
595
-
596
- ##################
597
- # Token Functions
598
- ##################
599
- class NotEqualToAnythingElse
600
- def ==(other)
601
- other.is_a? NotEqualToAnythingElse
602
- end
603
-
604
- def hash
605
- 971
606
- end
607
- end
608
-
609
- ##################
610
- # Path Functions
611
- ##################
612
- def self.path(*elements)
613
- # this is importantly NOT using Path.newPath, which relies on
614
- # the parser; in the test suite we are often testing the parser,
615
- # so we don't want to use the parser to build the expected result.
616
- Path.from_string_list(elements)
617
- end
618
-
619
- RESOURCE_DIR = "spec/fixtures/test_utils/resources"
620
-
621
- def self.resource_file(filename)
622
- File.join(RESOURCE_DIR, filename)
623
- end
624
-
625
- def self.json_quoted_resource_file(filename)
626
- quote_json_string(resource_file(filename).to_s)
627
- end
628
-
629
- def self.quote_json_string(s)
630
- Hocon::Impl::ConfigImplUtil.render_json_string(s)
631
- end
632
-
633
- ##################
634
- # RSpec Tests
635
- ##################
636
- def self.check_equal_objects(first_object, second_object)
637
- it "should find the two objects to be equal" do
638
- not_equal_to_anything_else = TestUtils::NotEqualToAnythingElse.new
639
-
640
- # Equality
641
- expect(first_object).to eq(second_object)
642
- expect(second_object).to eq(first_object)
643
-
644
- # Hashes
645
- expect(first_object.hash).to eq(second_object.hash)
646
-
647
- # Other random object
648
- expect(first_object).not_to eq(not_equal_to_anything_else)
649
- expect(not_equal_to_anything_else).not_to eq(first_object)
650
-
651
- expect(second_object).not_to eq(not_equal_to_anything_else)
652
- expect(not_equal_to_anything_else).not_to eq(second_object)
653
- end
654
- end
655
-
656
- def self.check_not_equal_objects(first_object, second_object)
657
-
658
- it "should find the two objects to be not equal" do
659
- not_equal_to_anything_else = TestUtils::NotEqualToAnythingElse.new
660
-
661
- # Equality
662
- expect(first_object).not_to eq(second_object)
663
- expect(second_object).not_to eq(first_object)
664
-
665
- # Hashes
666
- # hashcode inequality isn't guaranteed, but
667
- # as long as it happens to work it might
668
- # detect a bug (if hashcodes are equal,
669
- # check if it's due to a bug or correct
670
- # before you remove this)
671
- expect(first_object.hash).not_to eq(second_object.hash)
672
-
673
- # Other random object
674
- expect(first_object).not_to eq(not_equal_to_anything_else)
675
- expect(not_equal_to_anything_else).not_to eq(first_object)
676
-
677
- expect(second_object).not_to eq(not_equal_to_anything_else)
678
- expect(not_equal_to_anything_else).not_to eq(second_object)
679
- end
680
- end
681
- end
682
-
683
-
684
- ##################
685
- # RSpec Shared Examples
686
- ##################
687
-
688
- # Examples for comparing an object that won't equal anything but itself
689
- # Used in the object_equality examples below
690
- shared_examples_for "not_equal_to_other_random_thing" do
691
- let(:not_equal_to_anything_else) { TestUtils::NotEqualToAnythingElse.new }
692
-
693
- it "should find the first object not equal to a random other thing" do
694
- expect(first_object).not_to eq(not_equal_to_anything_else)
695
- expect(not_equal_to_anything_else).not_to eq(first_object)
696
- end
697
-
698
- it "should find the second object not equal to a random other thing" do
699
- expect(second_object).not_to eq(not_equal_to_anything_else)
700
- expect(not_equal_to_anything_else).not_to eq(second_object)
701
- end
702
- end
703
-
704
- # Examples for making sure two objects are equal
705
- shared_examples_for "object_equality" do
706
-
707
- it "should find the first object to be equal to the second object" do
708
- expect(first_object).to eq(second_object)
709
- end
710
-
711
- it "should find the second object to be equal to the first object" do
712
- expect(second_object).to eq(first_object)
713
- end
714
-
715
- it "should find the hash codes of the two objects to be equal" do
716
- expect(first_object.hash).to eq(second_object.hash)
717
- end
718
-
719
- include_examples "not_equal_to_other_random_thing"
720
- end
721
-
722
- # Examples for making sure two objects are not equal
723
- shared_examples_for "object_inequality" do
724
-
725
- it "should find the first object to not be equal to the second object" do
726
- expect(first_object).not_to eq(second_object)
727
- end
728
-
729
- it "should find the second object to not be equal to the first object" do
730
- expect(second_object).not_to eq(first_object)
731
- end
732
-
733
- it "should find the hash codes of the two objects to not be equal" do
734
- # hashcode inequality isn't guaranteed, but
735
- # as long as it happens to work it might
736
- # detect a bug (if hashcodes are equal,
737
- # check if it's due to a bug or correct
738
- # before you remove this)
739
- expect(first_object.hash).not_to eq(second_object.hash)
740
- end
741
-
742
- include_examples "not_equal_to_other_random_thing"
743
- end
744
-
745
-
746
- shared_examples_for "path_render_test" do
747
- it "should find the expected rendered text equal to the rendered path" do
748
- expect(path.render).to eq(expected)
749
- end
750
-
751
- it "should find the path equal to the parsed expected text" do
752
- expect(Hocon::Impl::PathParser.parse_path(expected)).to eq(path)
753
- end
754
-
755
- it "should find the path equal to the parsed text that came from the rendered path" do
756
- expect(Hocon::Impl::PathParser.parse_path(path.render)).to eq(path)
757
- end
758
- end