jsonnet 0.1.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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|