hocon 1.2.5 → 1.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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