jsonnet 0.1.0 → 0.4.0

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.
@@ -19,8 +19,10 @@ Gem::Specification.new do |spec|
19
19
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
20
  spec.require_paths = ["lib"]
21
21
 
22
- spec.add_development_dependency "bundler", "~> 1.7"
23
- spec.add_development_dependency "rake", "~> 10.0"
24
- spec.add_development_dependency "test-unit", "~> 3.1.3"
25
- spec.add_development_dependency "rake-compiler", "~> 0.9.5"
22
+ spec.add_runtime_dependency "mini_portile2", ">= 2.2.0"
23
+
24
+ spec.add_development_dependency "bundler", ">= 1.7"
25
+ spec.add_development_dependency "rake", ">= 10.0"
26
+ spec.add_development_dependency "test-unit", ">= 3.1.3"
27
+ spec.add_development_dependency "rake-compiler", ">= 0.9.5"
26
28
  end
@@ -1,7 +1,47 @@
1
1
  require "jsonnet/version"
2
- require "jsonnet/jsonnet_wrap"
3
2
  require "jsonnet/vm"
3
+ require "json"
4
4
 
5
5
  module Jsonnet
6
- # Your code goes here...
6
+ module_function
7
+
8
+ ##
9
+ # Evaluates a string of Jsonnet and returns a hash of the resulting JSON
10
+ #
11
+ # @param [String] jsonnet Jsonnet source string, ideally in UTF-8 encoding
12
+ # @param [Hash] jsonnet_options A hash of options to for Jsonnet::VM.
13
+ # Available options are: filename, multi,
14
+ # import_callback, gc_growth_triger,
15
+ # gc_min_objects, max_stack, max_trace
16
+ # @param [Hash] json_options Options supported by {JSON.parse}[http://www.rubydoc.info/github/flori/json/JSON#parse-class_method]
17
+ # @return [Hash] The JSON representation as a hash
18
+ # @raise [UnsupportedOptionError] Raised when an option passed is unsupported by Jsonnet::VM
19
+ #
20
+ # @note This method runs Jsonnet::VM#evaluate and runs the string
21
+ # output through {JSON.parse}[http://www.rubydoc.info/github/flori/json/JSON#parse-class_method]
22
+ # so those should be looked at for furhter details
23
+ def evaluate(jsonnet, jsonnet_options: {}, json_options: {})
24
+ output = VM.evaluate(jsonnet, jsonnet_options)
25
+ JSON.parse(output, json_options)
26
+ end
27
+
28
+ ##
29
+ # Loads a Jsonnet file and returns a hash of the resulting JSON
30
+ #
31
+ # @param [String] path path to the jsonnet file
32
+ # @param [Hash] jsonnet_options A hash of options to for Jsonnet::VM.
33
+ # Available options are: encoding, multi,
34
+ # import_callback, gc_growth_triger,
35
+ # gc_min_objects, max_stack, max_trace
36
+ # @param [Hash] json_options Options supported by {JSON.parse}[http://www.rubydoc.info/github/flori/json/JSON#parse-class_method]
37
+ # @return [Hash] The JSON representation as a hash
38
+ # @raise [UnsupportedOptionError] Raised when an option passed is unsupported by Jsonnet::VM
39
+ #
40
+ # @note This method runs Jsonnet::VM#evaluate_file and runs the string
41
+ # output through {JSON.parse}[http://www.rubydoc.info/github/flori/json/JSON#parse-class_method]
42
+ # so those should be looked at for furhter details
43
+ def load(path, jsonnet_options: {}, json_options: {})
44
+ output = VM.evaluate_file(path, jsonnet_options)
45
+ JSON.parse(output, json_options)
46
+ end
7
47
  end
@@ -1,3 +1,3 @@
1
1
  module Jsonnet
2
- VERSION = "0.1.0"
2
+ VERSION = "0.4.0"
3
3
  end
@@ -1,5 +1,59 @@
1
+ require "jsonnet/jsonnet_wrap"
2
+
1
3
  module Jsonnet
2
4
  class VM
5
+ class << self
6
+ ##
7
+ # Convenient method to evaluate a Jsonnet snippet.
8
+ #
9
+ # It implicitly instantiates a VM and then evaluate Jsonnet with the VM.
10
+ #
11
+ # @param snippet [String] Jsonnet source string.
12
+ # @param options [Hash] options to {.new} or options to {#evaluate}
13
+ # @return [String]
14
+ # @see #evaluate
15
+ def evaluate(snippet, options = {})
16
+ snippet_check = ->(key, value) { key.to_s.match(/^filename|multi$/) }
17
+ snippet_options = options.select(&snippet_check)
18
+ vm_options = options.reject(&snippet_check)
19
+ new(vm_options).evaluate(snippet, **snippet_options)
20
+ end
21
+
22
+ ##
23
+ # Convenient method to evaluate a Jsonnet file.
24
+ #
25
+ # It implicitly instantiates a VM and then evaluates Jsonnet with the VM.
26
+ #
27
+ # @param filename [String] Jsonnet source file.
28
+ # @param options [Hash] options to {.new} or options to {#evaluate_file}
29
+ # @return [String]
30
+ # @see #evaluate_file
31
+ def evaluate_file(filename, options = {})
32
+ file_check = ->(key, value) { key.to_s.match(/^encoding|multi$/) }
33
+ file_options = options.select(&file_check)
34
+ vm_options = options.reject(&file_check)
35
+ new(vm_options).evaluate_file(filename, **file_options)
36
+ end
37
+ end
38
+
39
+ ##
40
+ # initializes a new VM with the given configuration.
41
+ #
42
+ # @param [Hash] options a mapping from option names to their values.
43
+ # It can have names of writable attributes in VM class as keys.
44
+ # @return [VM] the VM.
45
+ def initialize(options = {})
46
+ options.each do |key, value|
47
+ method = "#{key}="
48
+ if respond_to?(method)
49
+ public_send(method, value)
50
+ else
51
+ raise UnsupportedOptionError.new("Jsonnet VM does not support #{key} option")
52
+ end
53
+ end
54
+ self
55
+ end
56
+
3
57
  ##
4
58
  # Evaluates Jsonnet source.
5
59
  #
@@ -11,9 +65,9 @@ module Jsonnet
11
65
  # @raise [EvaluationError] raised when the evaluation results an error.
12
66
  # @raise [UnsupportedEncodingError] raised when the encoding of jsonnet
13
67
  # is not ASCII-compatible.
14
- # @note It is recommended to encode the source string in UTF-8 because
15
- # Jsonnet expects it is ASCII-compatible, the result JSON string
16
- # shall be UTF-{8,16,32} according to RFC 7159 thus the only
68
+ # @note It is recommended to encode the source string in UTF-8 because
69
+ # Jsonnet expects it is ASCII-compatible, the result JSON string
70
+ # shall be UTF-{8,16,32} according to RFC 7159 thus the only
17
71
  # intersection between the requirements is UTF-8.
18
72
  def evaluate(jsonnet, filename: "(jsonnet)", multi: false)
19
73
  eval_snippet(jsonnet, filename, multi)
@@ -26,23 +80,88 @@ module Jsonnet
26
80
  # @param [Boolean] multi enables multi-mode
27
81
  # @return [String] a JSON representation of the evaluation result
28
82
  # @raise [EvaluationError] raised when the evaluation results an error.
29
- # @note It is recommended to encode the source file in UTF-8 because
30
- # Jsonnet expects it is ASCII-compatible, the result JSON string
31
- # shall be UTF-{8,16,32} according to RFC 7159 thus the only
83
+ # @note It is recommended to encode the source file in UTF-8 because
84
+ # Jsonnet expects it is ASCII-compatible, the result JSON string
85
+ # shall be UTF-{8,16,32} according to RFC 7159 thus the only
32
86
  # intersection between the requirements is UTF-8.
33
87
  def evaluate_file(filename, encoding: Encoding.default_external, multi: false)
34
88
  eval_file(filename, encoding, multi)
35
89
  end
36
90
 
91
+ ##
92
+ # Format Jsonnet file.
93
+ #
94
+ # @param [String] filename filename of a Jsonnet source file.
95
+ # @return [String] a formatted Jsonnet representation
96
+ # @raise [FormatError] raised when the formatting results an error.
97
+ def format_file(filename, encoding: Encoding.default_external)
98
+ fmt_file(filename, encoding)
99
+ end
100
+
101
+ ##
102
+ # Format Jsonnet snippet.
103
+ #
104
+ # @param [String] jsonnet Jsonnet source string. Must be encoded in ASCII-compatible encoding.
105
+ # @param [String] filename filename of the source. Used in stacktrace.
106
+ # @return [String] a formatted Jsonnet representation
107
+ # @raise [FormatError] raised when the formatting results an error.
108
+ # @raise [UnsupportedEncodingError] raised when the encoding of jsonnt is not ASCII-compatible.
109
+ def format(jsonnet, filename: "(jsonnet)")
110
+ fmt_snippet(jsonnet, filename)
111
+ end
112
+
37
113
  ##
38
114
  # Lets the given block handle "import" expression of Jsonnet.
39
115
  # @yieldparam [String] base base path to resolve "rel" from.
40
116
  # @yieldparam [String] rel a relative or absolute path to the file to be imported
41
117
  # @yieldreturn [Array<String>] a pair of the content of the imported file and
42
118
  # its path.
43
- def handle_import
44
- self.import_callback = Proc.new
119
+ def handle_import(&block)
120
+ if block.nil?
121
+ raise ArgumentError, 'handle_import requires a block'
122
+ end
123
+ self.import_callback = to_method(block)
45
124
  nil
46
125
  end
126
+
127
+ ##
128
+ # Define a function (native extension) in the VM and let the given block
129
+ # handle the invocation of the function.
130
+ #
131
+ # @param name [Symbol|String] name of the function.
132
+ # Must be a valid identifier in Jsonnet.
133
+ # @param body [#to_proc] body of the function.
134
+ # @yield calls the given block instead of `body` if `body` is `nil`
135
+ #
136
+ # @note Currently it cannot define keyword or optional paramters in Jsonnet.
137
+ # Also all the positional optional parameters of the body are interpreted
138
+ # as required parameters. And the body cannot have keyword, rest or
139
+ # keyword rest paramters.
140
+ def define_function(name, body = nil, &block)
141
+ body = body ? body.to_proc : block
142
+ if body.nil?
143
+ raise ArgumentError, 'define_function requires a body argument or a block'
144
+ end
145
+ params = body.parameters.map.with_index do |(type, name), i|
146
+ raise ArgumentError, "rest or keyword parameters are not allowed: #{type}" \
147
+ unless [:req, :opt].include? type
148
+
149
+ name || "p#{i}"
150
+ end
151
+
152
+ register_native_callback(name.to_sym, to_method(body), params);
153
+ end
154
+
155
+ private
156
+ # Wraps the function body with a method so that `break` and `return`
157
+ # behave like `return` as they do in a body of Module#define_method.
158
+ def to_method(body)
159
+ mod = Module.new {
160
+ define_method(:dummy, body)
161
+ }
162
+ mod.instance_method(:dummy).bind(body.binding.receiver)
163
+ end
164
+
165
+ class UnsupportedOptionError < RuntimeError; end
47
166
  end
48
167
  end
@@ -0,0 +1,3 @@
1
+ {
2
+ a: 1,
3
+ }
@@ -1,8 +1,51 @@
1
1
  require 'jsonnet'
2
+
3
+ require 'tempfile'
2
4
  require 'test/unit'
3
5
 
4
6
  class TestJsonnet < Test::Unit::TestCase
5
7
  test 'libversion returns a String' do
6
- assert_kind_of String, Jsonnet.libversion
8
+ assert_kind_of String, Jsonnet.libversion
9
+ end
10
+
11
+ test 'Jsonnet.evaluate returns a JSON parsed result' do
12
+ result = Jsonnet.evaluate('{ foo: "bar" }')
13
+ assert_equal result, { "foo" => "bar" }
14
+ end
15
+
16
+ test 'Jsonnet.evaluate can accept options for JSON' do
17
+ result = Jsonnet.evaluate('{ foo: "bar" }', json_options: { symbolize_names: true })
18
+ assert_equal result, { foo: "bar" }
19
+ end
20
+
21
+ test 'Jsonnet.evaluate can accept options for Jsonnet VM' do
22
+ result = Jsonnet.evaluate(
23
+ 'import "imported.jsonnet"',
24
+ jsonnet_options: {
25
+ import_callback: ->(_base, _rel) do
26
+ return ['{ foo: "bar" }', 'imported']
27
+ end
28
+ }
29
+ )
30
+ assert_equal result, { "foo" => "bar" }
31
+ end
32
+
33
+ test 'Jsonnet.load returns a JSON parsed result' do
34
+ result = Jsonnet.load(example_jsonnet_file.path)
35
+ assert_equal result, { "foo1" => 1 }
36
+ end
37
+
38
+ private
39
+
40
+ def example_jsonnet_file
41
+ Tempfile.open("example.jsonnet") do |f|
42
+ f.write %<
43
+ local myvar = 1;
44
+ {
45
+ ["foo" + myvar]: myvar,
46
+ }
47
+ >
48
+ f
49
+ end
7
50
  end
8
51
  end
@@ -47,7 +47,7 @@ class TestVM < Test::Unit::TestCase
47
47
  vm = Jsonnet::VM.new
48
48
  begin
49
49
  with_example_file(%q{ ["unterminated string }) {|fname|
50
- vm.evaluate_file(fname.encode(Encoding::SJIS))
50
+ vm.evaluate_file(fname.encode(Encoding::SJIS))
51
51
  }
52
52
  rescue Jsonnet::EvaluationError => e
53
53
  assert_equal Encoding::SJIS, e.message.encoding
@@ -104,19 +104,62 @@ class TestVM < Test::Unit::TestCase
104
104
  test "Jsonnet::VM#evaluate raises an error in the encoding of filename" do
105
105
  vm = Jsonnet::VM.new
106
106
  begin
107
- vm.evaluate(%Q{ ["unterminated string }, filename: "テスト.json".encode(Encoding::SJIS))
107
+ vm.evaluate(%Q{ ["unterminated string }, filename: "テスト.json".encode(Encoding::SJIS))
108
108
  rescue Jsonnet::EvaluationError => e
109
109
  assert_equal Encoding::SJIS, e.message.encoding
110
110
  end
111
111
  end
112
112
 
113
- test "Jsonnet::VM#ext_var binds a variable" do
113
+ test "Jsonnet::VM#ext_var binds a variable to a string value" do
114
114
  vm = Jsonnet::VM.new
115
115
  vm.ext_var("var1", "foo")
116
116
  result = vm.evaluate('[std.extVar("var1")]')
117
117
  assert_equal JSON.parse('["foo"]'), JSON.parse(result)
118
118
  end
119
119
 
120
+ test "Jsonnet::VM#ext_code binds a variable to a code fragment" do
121
+ vm = Jsonnet::VM.new
122
+ vm.ext_code("var1", "{a:1}")
123
+ result = vm.evaluate('[std.extVar("var1")]')
124
+ assert_equal JSON.parse(<<-EOS), JSON.parse(result)
125
+ [
126
+ {
127
+ "a": 1
128
+ }
129
+ ]
130
+ EOS
131
+ end
132
+
133
+ test "Jsonnet::VM#tla_var binds a top-level variable to a string value" do
134
+ vm = Jsonnet::VM.new
135
+ vm.tla_var("var1", "foo")
136
+ result = vm.evaluate('function(var1) [var1, var1]')
137
+ assert_equal JSON.parse('["foo", "foo"]'), JSON.parse(result)
138
+ end
139
+
140
+ test "Jsonnet::VM#tla_var binds a top-level argument to a string value" do
141
+ vm = Jsonnet::VM.new
142
+ vm.tla_var("var1", "foo")
143
+ result = vm.evaluate('function(var1) [var1, var1]')
144
+ assert_equal JSON.parse('["foo", "foo"]'), JSON.parse(result)
145
+ end
146
+
147
+ test "Jsonnet::VM#tla_code binds a top-level argument to a code fragment" do
148
+ vm = Jsonnet::VM.new
149
+ vm.tla_code("var1", "{a:1}")
150
+ result = vm.evaluate('function(var1) [var1, var1]')
151
+ assert_equal JSON.parse(<<-EOS), JSON.parse(result)
152
+ [
153
+ {
154
+ "a": 1
155
+ },
156
+ {
157
+ "a": 1
158
+ }
159
+ ]
160
+ EOS
161
+ end
162
+
120
163
  test 'Jsonnet::VM#evaluate returns a JSON per filename on multi mode' do
121
164
  vm = Jsonnet::VM.new
122
165
  [
@@ -211,10 +254,6 @@ class TestVM < Test::Unit::TestCase
211
254
  Jsonnet::VM.new.max_trace = 1
212
255
  end
213
256
 
214
- test "Jsonnet::VM responds to debug_ast=" do
215
- Jsonnet::VM.new.debug_ast = true
216
- end
217
-
218
257
  test "Jsonnet::VM#string_output lets the VM output a raw string" do
219
258
  vm = Jsonnet::VM.new
220
259
  vm.string_output = true
@@ -229,7 +268,7 @@ class TestVM < Test::Unit::TestCase
229
268
  case [base, rel]
230
269
  when ['/path/to/base/', 'imported1.jsonnet']
231
270
  return <<-EOS, '/path/to/imported1/imported1.jsonnet'
232
- import "imported2.jsonnet" {
271
+ (import "imported2.jsonnet") + {
233
272
  b: 2,
234
273
  }
235
274
  EOS
@@ -242,7 +281,7 @@ class TestVM < Test::Unit::TestCase
242
281
  end
243
282
  }
244
283
  result = vm.evaluate(<<-EOS, filename: "/path/to/base/example.jsonnet")
245
- import "imported1.jsonnet" { c: 3 }
284
+ (import "imported1.jsonnet") + { c: 3 }
246
285
  EOS
247
286
 
248
287
  expected = {"a" => 1, "b" => 2, "c" => 3}
@@ -255,12 +294,276 @@ class TestVM < Test::Unit::TestCase
255
294
  vm.import_callback = ->(base, rel) { called = true; raise }
256
295
  assert_raise(Jsonnet::EvaluationError) {
257
296
  vm.evaluate(<<-EOS)
258
- import "a.jsonnet" {}
297
+ (import "a.jsonnet") + {}
259
298
  EOS
260
299
  }
261
300
  assert_true called
262
301
  end
263
302
 
303
+ test "Jsonnet::VM#handle_import treats global escapes as define_method does" do
304
+ num_eval = 0
305
+ begin
306
+ bodies = [
307
+ proc {|rel, base| return 'null', '/x.libsonnet' },
308
+ lambda {|rel, base| return 'null', '/x.libsonnet' },
309
+ proc {|rel, base| next 'null', '/x.libsonnet' },
310
+ lambda {|rel, base| next 'null', '/x.libsonnet' },
311
+ proc {|rel, base| break 'null', '/x.libsonnet' },
312
+ lambda {|rel, base| break 'null', '/x.libsonnet' },
313
+ ]
314
+ bodies.each do |prc|
315
+ vm = Jsonnet::VM.new
316
+ vm.handle_import(&prc)
317
+
318
+ result = vm.evaluate('import "a.jsonnet"')
319
+ assert_nil JSON.load(result)
320
+
321
+ num_eval += 1
322
+ end
323
+ ensure
324
+ assert_equal bodies.size, num_eval
325
+ end
326
+ end
327
+
328
+ test "Jsonnet::VM#handle_import is safe on throw" do
329
+ [
330
+ proc {|rel, base| throw :dummy },
331
+ lambda {|rel, base| throw :dummy },
332
+ ].each do |prc|
333
+ vm = Jsonnet::VM.new
334
+ vm.handle_import(&prc)
335
+
336
+ catch(:dummy) {
337
+ vm.evaluate('import "a.jsonnet"')
338
+ flunk "never reach here"
339
+ }
340
+ end
341
+ end
342
+
343
+ test "Jsonnet::VM#jpath_add adds a library search path" do
344
+ vm = Jsonnet::VM.new
345
+ snippet = "(import 'jpath.libsonnet') {b: 2}"
346
+ assert_raise(Jsonnet::EvaluationError) {
347
+ vm.evaluate(snippet)
348
+ }
349
+
350
+ vm.jpath_add(File.join(__dir__, 'fixtures'))
351
+ result = vm.evaluate(snippet)
352
+ assert_equal JSON.parse(<<-EOS), JSON.parse(result)
353
+ {
354
+ "a": 1,
355
+ "b": 2
356
+ }
357
+ EOS
358
+ end
359
+
360
+ test "Jsonnet::VM#define_function adds a new native extension" do
361
+ vm = Jsonnet::VM.new
362
+ called = false
363
+
364
+ vm.define_function("myPow") do |x, y|
365
+ called = true
366
+ x ** y
367
+ end
368
+
369
+ result = vm.evaluate("std.native('myPow')(3, 4)")
370
+ assert_equal 3**4, JSON.load(result)
371
+ assert_true called
372
+ end
373
+
374
+ test "Jsonnet::VM#define_function passes various types of arguments" do
375
+ [
376
+ [%q(null), nil],
377
+ [%q("abc"), "abc"],
378
+ [%q(1), 1.0],
379
+ [%q(1.25), 1.25],
380
+ [%q(true), true],
381
+ [%q(false), false],
382
+ ].each do |expr, value|
383
+ vm = Jsonnet::VM.new
384
+ vm.define_function("myFunc") do |x|
385
+ assert_equal value, x
386
+ next nil
387
+ end
388
+ vm.evaluate("std.native('myFunc')(#{expr})")
389
+ end
390
+ end
391
+
392
+ test "Jsonnet::VM#define_function returns various types of values" do
393
+ [
394
+ [nil, nil],
395
+ ["abc", "abc"],
396
+ [1, 1.0],
397
+ [1.25, 1.25],
398
+ [true, true],
399
+ [false, false],
400
+ ].each do |retval, expected|
401
+ vm = Jsonnet::VM.new
402
+ vm.define_function("myFunc") { retval }
403
+
404
+ result = vm.evaluate("std.native('myFunc')()")
405
+ assert_equal expected, JSON.load(result)
406
+ end
407
+ end
408
+
409
+ test "Jsonnet::VM#define_function translates an exception in a native function into an error" do
410
+ vm = Jsonnet::VM.new
411
+ vm.define_function("myFunc") do |x|
412
+ raise "something wrong"
413
+ end
414
+ assert_raise(Jsonnet::EvaluationError) {
415
+ vm.evaluate("std.native('myFunc')(1)")
416
+ }
417
+ end
418
+
419
+ test "Jsonnet::VM#define_function let the function return a compound object" do
420
+ vm = Jsonnet::VM.new
421
+ vm.define_function("myCompound") do |x, y|
422
+ {
423
+ x => y,
424
+ y => [x, y, y, x],
425
+ }
426
+ end
427
+
428
+ result = vm.evaluate("std.native('myCompound')('abc', 'def')")
429
+ assert_equal JSON.parse(<<-EOS), JSON.parse(result)
430
+ {
431
+ "abc": "def",
432
+ "def": ["abc", "def", "def", "abc"]
433
+ }
434
+ EOS
435
+ end
436
+
437
+ test "Jsonnet::VM#define_function treats global escapes as define_method does" do
438
+ num_eval = 0
439
+ begin
440
+ bodies = [
441
+ proc {|x| return x },
442
+ lambda {|x| return x },
443
+ proc {|x| next x },
444
+ lambda {|x| next x },
445
+ proc {|x| break x },
446
+ lambda {|x| break x },
447
+ ]
448
+ bodies.each do |prc|
449
+ vm = Jsonnet::VM.new
450
+ vm.define_function(:myFunc, prc)
451
+
452
+ result = vm.evaluate('std.native("myFunc")(1.25) + 0.25')
453
+ assert_equal 1.25 + 0.25, JSON.load(result)
454
+
455
+ num_eval += 1
456
+ end
457
+ ensure
458
+ assert_equal bodies.size, num_eval
459
+ end
460
+ end
461
+
462
+ test "Jsonnet::VM#define_function is safe on throw" do
463
+ [
464
+ proc {|x| throw :dummy },
465
+ lambda {|x| throw :dummy },
466
+ ].each do |prc|
467
+ vm = Jsonnet::VM.new
468
+ vm.define_function(:myFunc, prc)
469
+
470
+ catch(:dummy) {
471
+ vm.evaluate('std.native("myFunc")(1.234)')
472
+ flunk "never reach here"
473
+ }
474
+ end
475
+ end
476
+
477
+ test "Jsonnet::VM#format_file formats Jsonnet file" do
478
+ vm = Jsonnet::VM.new
479
+ vm.fmt_indent = 4
480
+ with_example_file(%<
481
+ local myvar = 1;
482
+ {
483
+ "foo": myvar
484
+ }
485
+ >) {|fname|
486
+ result = vm.format_file(fname)
487
+ assert_equal <<-EOS, result
488
+ local myvar = 1;
489
+ {
490
+ foo: myvar,
491
+ }
492
+ EOS
493
+ }
494
+ end
495
+
496
+ test "Jsonnet::VM#format formats Jsonnet snippet" do
497
+ vm = Jsonnet::VM.new
498
+ vm.fmt_string = 'd'
499
+ result = vm.format(<<-EOS)
500
+ local myvar = 'myvar';
501
+ {
502
+ foo: [myvar,myvar]
503
+ }
504
+ EOS
505
+ assert_equal <<-EOS, result
506
+ local myvar = "myvar";
507
+ {
508
+ foo: [myvar, myvar],
509
+ }
510
+ EOS
511
+ end
512
+
513
+ test "Jsonnet::VM#fmt_string only accepts 'd', 's', or 'l'" do
514
+ vm = Jsonnet::VM.new
515
+ vm.fmt_string = Jsonnet::STRING_STYLE_DOUBLE
516
+ vm.fmt_string = Jsonnet::STRING_STYLE_SINGLE
517
+ vm.fmt_string = Jsonnet::STRING_STYLE_LEAVE
518
+ assert_raise(ArgumentError) do
519
+ vm.fmt_string = ''
520
+ end
521
+ assert_raise(ArgumentError) do
522
+ vm.fmt_string = 'a'
523
+ end
524
+ assert_raise(ArgumentError) do
525
+ vm.fmt_string = 'ds'
526
+ end
527
+ assert_raise(TypeError) do
528
+ vm.fmt_string = 0
529
+ end
530
+ end
531
+
532
+ test "Jsonnet::VM#fmt_comment only accepts 'h', 's', or 'l'" do
533
+ vm = Jsonnet::VM.new
534
+ vm.fmt_comment = Jsonnet::COMMENT_STYLE_HASH
535
+ vm.fmt_comment = Jsonnet::COMMENT_STYLE_SLASH
536
+ vm.fmt_comment = Jsonnet::COMMENT_STYLE_LEAVE
537
+ assert_raise(ArgumentError) do
538
+ vm.fmt_comment = ''
539
+ end
540
+ assert_raise(ArgumentError) do
541
+ vm.fmt_comment = 'a'
542
+ end
543
+ assert_raise(ArgumentError) do
544
+ vm.fmt_comment = 'hs'
545
+ end
546
+ assert_raise(TypeError) do
547
+ vm.fmt_comment = 0
548
+ end
549
+ end
550
+
551
+ test "Jsonnet::VM#fmt_file raises FormatError on error" do
552
+ vm = Jsonnet::VM.new
553
+ with_example_file('{foo: }') do |fname|
554
+ assert_raise(Jsonnet::FormatError) do
555
+ vm.format_file(fname)
556
+ end
557
+ end
558
+ end
559
+
560
+ test "Jsonnet::VM#fmt_snippet raises FormatError on error" do
561
+ vm = Jsonnet::VM.new
562
+ assert_raise(Jsonnet::FormatError) do
563
+ vm.format('{foo: }')
564
+ end
565
+ end
566
+
264
567
  private
265
568
  def with_example_file(content)
266
569
  Tempfile.open("example.jsonnet") {|f|