mirah 0.1.4-java → 0.2.0-java
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +0 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/History.txt +531 -0
- data/README.md +23 -10
- data/Rakefile +239 -156
- data/TODO.md +71 -10
- data/bin/mirah +1 -1
- data/bin/mirahc +1 -1
- data/dist/mirahc.jar +0 -0
- data/examples/bintrees.mirah +2 -2
- data/examples/construction.mirah +2 -2
- data/examples/fields.mirah +1 -1
- data/examples/fractal.mirah +1 -1
- data/examples/fractal.rb +70 -0
- data/examples/interfaces.mirah +1 -1
- data/examples/java_thing.mirah +1 -1
- data/examples/macros/square.mirah +3 -3
- data/examples/macros/square_int.mirah +3 -3
- data/examples/macros/string_each_char.mirah +6 -6
- data/examples/rosettacode/100-doors.mirah +0 -2
- data/examples/rosettacode/count-occurrences-of-a-substring.mirah +3 -3
- data/examples/rosettacode/empty-string.mirah +1 -1
- data/examples/rosettacode/fizz-buzz.mirah +4 -4
- data/examples/rosettacode/is-string-numeric.mirah +7 -7
- data/examples/rosettacode/palindrome.mirah +2 -2
- data/examples/rosettacode/reverse-a-string.mirah +1 -1
- data/examples/rosettacode/rot-13.mirah +1 -1
- data/examples/{edb.mirah → rosettacode/simple_character_math.mirah} +13 -4
- data/examples/rosettacode/string-case.mirah +2 -2
- data/examples/rosettacode/string-length.mirah +1 -1
- data/examples/swing.mirah +9 -14
- data/extensions_and_macros.md +117 -0
- data/lib/mirah.rb +1 -1
- data/lib/mirah/errors.rb +3 -1
- data/lib/mirah/transform/ast_ext.rb +3 -2
- data/lib/mirah/util/process_errors.rb +1 -2
- data/lib/mirah/version.rb +1 -1
- data/test/A.class +0 -0
- data/test/core/util/jvm_version_test.rb +10 -0
- data/test/core/util/mirah_arguments_test.rb +51 -4
- data/test/fixtures/cp1251_test.mirah +7 -0
- data/test/fixtures/org/foo/AbstractExecutorJava8.java +30 -0
- data/test/fixtures/org/foo/ClassWithSelfReferencingTypeParameter.java +24 -0
- data/test/fixtures/org/foo/InnerInterfaceClass.java +12 -0
- data/test/fixtures/org/foo/IntAnno.class +0 -0
- data/test/fixtures/org/foo/TypeFixtureJava8.java +10 -0
- data/test/fixtures/utf8_test.mirah +7 -0
- data/test/jvm/access_levels_test.rb +31 -0
- data/test/jvm/annotations_test.rb +3 -6
- data/test/jvm/blocks_test.rb +303 -120
- data/test/jvm/cast_test.rb +123 -50
- data/test/jvm/closure_test.rb +242 -0
- data/test/jvm/constructors_test.rb +1 -3
- data/test/jvm/example_test.rb +6 -2
- data/test/jvm/extensions/array_extensions_test.rb +181 -0
- data/test/jvm/extensions/collection_extensions_test.rb +195 -0
- data/test/jvm/{enumerable_test.rb → extensions/enumerable_test.rb} +81 -13
- data/test/jvm/extensions/hash_extensions_test.rb +56 -0
- data/test/jvm/extensions/list_extensions_test.rb +143 -0
- data/test/jvm/extensions/lock_extensions_test.rb +43 -0
- data/test/jvm/{numeric_extensions_test.rb → extensions/numeric_extensions_test.rb} +0 -0
- data/test/jvm/extensions/numeric_operators_test.rb +86 -0
- data/test/jvm/extensions/object_extensions_test.rb +122 -0
- data/test/jvm/{string_builder_extensions_test.rb → extensions/string_builder_extensions_test.rb} +0 -0
- data/test/jvm/{string_extensions_test.rb → extensions/string_extensions_test.rb} +57 -4
- data/test/jvm/generics_test.rb +14 -6
- data/test/jvm/import_test.rb +38 -1
- data/test/jvm/interface_test.rb +17 -0
- data/test/jvm/jvm_commands_test.rb +9 -0
- data/test/jvm/jvm_compiler_test.rb +568 -43
- data/test/jvm/macros_test.rb +343 -19
- data/test/jvm/main_method_test.rb +1 -3
- data/test/jvm/new_backend_test_helper.rb +54 -7
- data/test/jvm/rescue_test.rb +20 -5
- data/test/jvm/static_fields_test.rb +52 -10
- data/test/jvm/{mirror_compilation_test_helper.rb → string_test.rb} +10 -9
- data/test/jvm/varargs_test.rb +6 -16
- data/test/mirrors/base_type_test.rb +20 -7
- data/test/mirrors/bytecode_mirror_test.rb +8 -3
- data/test/mirrors/generics_test.rb +89 -10
- data/test/mirrors/member_test.rb +1 -1
- data/test/mirrors/method_lookup_test.rb +10 -3
- data/test/mirrors/mirrors_test.rb +20 -20
- data/test/mirrors/simple_async_mirror_loader_test.rb +1 -1
- data/test/mirrors/simple_mirror_loader_test.rb +1 -1
- data/test/newMirahClass$Closure2.class +0 -0
- data/test/newMirahClass.class +0 -0
- data/test/test_helper.rb +8 -1
- metadata +31 -16
- data/bin/bundler +0 -16
- data/bin/rake +0 -16
- data/examples/ant/example-build.xml~ +0 -7
- data/examples/test.edb +0 -9
- data/lib/mirah/compiler.rb +0 -67
- data/lib/mirah/parser.rb +0 -224
- data/lib/mirah/util/delegate.rb +0 -65
- data/test/jvm/list_extensions_test.rb +0 -23
data/test/jvm/macros_test.rb
CHANGED
@@ -12,6 +12,7 @@
|
|
12
12
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
13
|
# See the License for the specific language governing permissions and
|
14
14
|
# limitations under the License.
|
15
|
+
require 'test_helper'
|
15
16
|
|
16
17
|
class MacrosTest < Test::Unit::TestCase
|
17
18
|
#TODO perhaps one of these should be an error
|
@@ -29,7 +30,7 @@ class MacrosTest < Test::Unit::TestCase
|
|
29
30
|
foo [2,3] {|x| puts x }
|
30
31
|
EOF
|
31
32
|
|
32
|
-
|
33
|
+
assert_run_output("1\n2\n1\n3\n", cls)
|
33
34
|
end
|
34
35
|
|
35
36
|
def test_block_args_with_pipes_macro
|
@@ -46,7 +47,7 @@ class MacrosTest < Test::Unit::TestCase
|
|
46
47
|
foo [2,3] {|x| puts x }
|
47
48
|
EOF
|
48
49
|
|
49
|
-
|
50
|
+
assert_run_output("1\n2\n1\n3\n", cls)
|
50
51
|
end
|
51
52
|
|
52
53
|
|
@@ -59,7 +60,7 @@ class MacrosTest < Test::Unit::TestCase
|
|
59
60
|
puts(Object(foo))
|
60
61
|
EOF
|
61
62
|
|
62
|
-
|
63
|
+
assert_run_output("null\n", cls)
|
63
64
|
assert(!cls.respond_to?(:foo))
|
64
65
|
end
|
65
66
|
|
@@ -74,7 +75,7 @@ class MacrosTest < Test::Unit::TestCase
|
|
74
75
|
foo
|
75
76
|
EOF
|
76
77
|
|
77
|
-
|
78
|
+
assert_run_output("", cls)
|
78
79
|
assert(!cls.respond_to?(:foo))
|
79
80
|
end
|
80
81
|
|
@@ -87,7 +88,7 @@ class MacrosTest < Test::Unit::TestCase
|
|
87
88
|
puts(Object(foo()))
|
88
89
|
EOF
|
89
90
|
|
90
|
-
|
91
|
+
assert_run_output("null\n", cls)
|
91
92
|
assert(!cls.respond_to?(:foo))
|
92
93
|
end
|
93
94
|
|
@@ -100,7 +101,7 @@ class MacrosTest < Test::Unit::TestCase
|
|
100
101
|
puts(Object(foo))
|
101
102
|
EOF
|
102
103
|
|
103
|
-
|
104
|
+
assert_run_output("null\n", cls)
|
104
105
|
assert(!cls.respond_to?(:foo))
|
105
106
|
end
|
106
107
|
|
@@ -208,6 +209,38 @@ class MacrosTest < Test::Unit::TestCase
|
|
208
209
|
assert_equal("foobar", script.function)
|
209
210
|
end
|
210
211
|
|
212
|
+
def test_static_macro_instance_macro_coexistence_vcall
|
213
|
+
script, cls = compile(%q[
|
214
|
+
class StaticMacrosWithInstanceMacros
|
215
|
+
def foobar
|
216
|
+
"foobar"
|
217
|
+
end
|
218
|
+
|
219
|
+
macro def macro_foobar
|
220
|
+
quote {`@call.target`.foobar}
|
221
|
+
end
|
222
|
+
|
223
|
+
def call_foobar_instance
|
224
|
+
macro_foobar
|
225
|
+
end
|
226
|
+
|
227
|
+
macro def self.macro_foobar
|
228
|
+
quote {`@call.target`.new.foobar}
|
229
|
+
end
|
230
|
+
|
231
|
+
def self.call_foobar_static
|
232
|
+
macro_foobar
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
def function
|
237
|
+
"#{StaticMacrosWithInstanceMacros.call_foobar_static}\n#{StaticMacrosWithInstanceMacros.new.call_foobar_instance}"
|
238
|
+
end
|
239
|
+
])
|
240
|
+
|
241
|
+
assert_equal("foobar\nfoobar", script.function)
|
242
|
+
end
|
243
|
+
|
211
244
|
|
212
245
|
def test_unquote_method_definitions_with_main
|
213
246
|
script, cls = compile(<<-'EOF')
|
@@ -219,7 +252,7 @@ class MacrosTest < Test::Unit::TestCase
|
|
219
252
|
@`name`
|
220
253
|
end
|
221
254
|
def `"#{name}_set"`(`name`: `type`)
|
222
|
-
@`name` = `name`
|
255
|
+
@`name` = `name` # silly parsing `
|
223
256
|
end
|
224
257
|
end
|
225
258
|
end
|
@@ -233,7 +266,7 @@ class MacrosTest < Test::Unit::TestCase
|
|
233
266
|
puts x.foo
|
234
267
|
EOF
|
235
268
|
|
236
|
-
|
269
|
+
assert_run_output("0\n3\n", script)
|
237
270
|
end
|
238
271
|
|
239
272
|
def test_macro_hygene
|
@@ -282,6 +315,10 @@ class MacrosTest < Test::Unit::TestCase
|
|
282
315
|
end
|
283
316
|
|
284
317
|
def test_add_args_in_macro
|
318
|
+
pend "This is poor-man's splat-operator. It should be replaced by a proper splat-operator or abolished entirely."
|
319
|
+
# This unquote is intended to evaluate to more than just exactly one AST node (that is, 2 nodes in this case) and hence
|
320
|
+
# modifies the NodeList higher in the syntax tree, surprisingly.
|
321
|
+
# Hence, the intention of this unquote violates the Principle of Least Surprise.
|
285
322
|
cls, = compile(<<-EOF)
|
286
323
|
macro def foo(a:Array)
|
287
324
|
quote { bar "1", `a.values`, "2"}
|
@@ -294,9 +331,7 @@ class MacrosTest < Test::Unit::TestCase
|
|
294
331
|
foo(["a", "b"])
|
295
332
|
EOF
|
296
333
|
|
297
|
-
|
298
|
-
cls.main(nil)
|
299
|
-
end
|
334
|
+
assert_run_output("1 a b 2\n", cls)
|
300
335
|
end
|
301
336
|
|
302
337
|
def test_block_parameter_uses_outer_scope
|
@@ -310,9 +345,7 @@ class MacrosTest < Test::Unit::TestCase
|
|
310
345
|
end
|
311
346
|
EOF
|
312
347
|
|
313
|
-
|
314
|
-
cls.main(nil)
|
315
|
-
end
|
348
|
+
assert_run_output("3\n", cls)
|
316
349
|
end
|
317
350
|
|
318
351
|
|
@@ -326,9 +359,7 @@ class MacrosTest < Test::Unit::TestCase
|
|
326
359
|
end
|
327
360
|
EOF
|
328
361
|
|
329
|
-
|
330
|
-
cls.main(nil)
|
331
|
-
end
|
362
|
+
assert_run_output("hi\n", cls)
|
332
363
|
end
|
333
364
|
|
334
365
|
def test_method_def_after_macro_def_with_same_name_raises_error
|
@@ -371,7 +402,43 @@ class MacrosTest < Test::Unit::TestCase
|
|
371
402
|
x.foo = 3
|
372
403
|
puts x.foo
|
373
404
|
EOF
|
374
|
-
|
405
|
+
assert_run_output("0\n3\n", script)
|
406
|
+
end
|
407
|
+
|
408
|
+
def test_protected_attr_accessor
|
409
|
+
script, cls = compile(<<-EOF)
|
410
|
+
class ProtectedAttrAccessorTest
|
411
|
+
protected attr_accessor foo:int
|
412
|
+
|
413
|
+
def selfreflect
|
414
|
+
puts self.getClass.getDeclaredMethod("foo").getModifiers
|
415
|
+
puts self.getClass.getDeclaredMethod("foo_set",[int.class].toArray(Class[0])).getModifiers
|
416
|
+
end
|
417
|
+
end
|
418
|
+
|
419
|
+
ProtectedAttrAccessorTest.new.selfreflect
|
420
|
+
EOF
|
421
|
+
assert_run_output("4\n4\n", script)
|
422
|
+
end
|
423
|
+
|
424
|
+
def test_macro_in_abstract_class
|
425
|
+
pend
|
426
|
+
script, cls = compile(%q{
|
427
|
+
interface I1
|
428
|
+
end
|
429
|
+
|
430
|
+
abstract class C2 implements I1
|
431
|
+
macro def self.bar
|
432
|
+
quote do
|
433
|
+
puts "bar"
|
434
|
+
end
|
435
|
+
end
|
436
|
+
end
|
437
|
+
})
|
438
|
+
script, _ =compile(%q{
|
439
|
+
C2.bar
|
440
|
+
})
|
441
|
+
assert_run_output("bar\n", script)
|
375
442
|
end
|
376
443
|
|
377
444
|
def test_separate_compilation
|
@@ -387,6 +454,263 @@ class MacrosTest < Test::Unit::TestCase
|
|
387
454
|
script, _ =compile(<<-CODE)
|
388
455
|
InlineOneSayer.new.say_one
|
389
456
|
CODE
|
390
|
-
|
457
|
+
assert_run_output("one\n", script)
|
458
|
+
end
|
459
|
+
|
460
|
+
def test_separate_compilation_different_macro_dest
|
461
|
+
compile(<<-CODE, separate_macro_dest: true)
|
462
|
+
class InlineTwoSayer
|
463
|
+
macro def say_two
|
464
|
+
quote do
|
465
|
+
puts "two"
|
466
|
+
end
|
467
|
+
end
|
468
|
+
end
|
469
|
+
CODE
|
470
|
+
script, _ =compile(<<-CODE, separate_macro_dest: true)
|
471
|
+
InlineTwoSayer.new.say_two
|
472
|
+
CODE
|
473
|
+
assert_run_output("two\n", script)
|
474
|
+
end
|
475
|
+
|
476
|
+
def test_import_star_with_macro_def
|
477
|
+
cls1, cls2 = compile([<<-EOF1, <<-EOF2])
|
478
|
+
package org.bar.p1
|
479
|
+
import org.bar.p2.*
|
480
|
+
macro def foo1; end
|
481
|
+
puts MultiPackageImplicitRef.class
|
482
|
+
EOF1
|
483
|
+
package org.bar.p2
|
484
|
+
class MultiPackageImplicitRef; end
|
485
|
+
EOF2
|
486
|
+
|
487
|
+
assert_run_output "class org.bar.p2.MultiPackageImplicitRef\n", cls1
|
488
|
+
end
|
489
|
+
|
490
|
+
def test_explicit_import_of_as_yet_unresolved_type_in_file_with_macro
|
491
|
+
cls1, cls2 = compile([<<-EOF1, <<-EOF2])
|
492
|
+
package org.bar.p1
|
493
|
+
import org.bar.p2.MultiPackageExplicitRef
|
494
|
+
|
495
|
+
macro def foo1; end
|
496
|
+
puts MultiPackageExplicitRef.class
|
497
|
+
EOF1
|
498
|
+
package org.bar.p2
|
499
|
+
class MultiPackageExplicitRef; end
|
500
|
+
EOF2
|
501
|
+
|
502
|
+
assert_run_output "class org.bar.p2.MultiPackageExplicitRef\n", cls1
|
503
|
+
end
|
504
|
+
|
505
|
+
def test_macro_using_imported_unresolved_type_fails_to_compile
|
506
|
+
e = assert_raises Mirah::MirahError do
|
507
|
+
compile([<<-EOF1, <<-EOF2])
|
508
|
+
package org.bar.p1
|
509
|
+
import org.bar.p2.UsedInMacro
|
510
|
+
|
511
|
+
macro def foo1; puts UsedInMacro; quote {}; end
|
512
|
+
foo1
|
513
|
+
EOF1
|
514
|
+
package org.bar.p2
|
515
|
+
class MultiPackageExplicitRef2; end
|
516
|
+
EOF2
|
517
|
+
end
|
518
|
+
assert_equal "UsedInMacro;", e.position
|
519
|
+
assert_equal "Cannot find class org.bar.p1.UsedInMacro", e.message
|
520
|
+
end
|
521
|
+
|
522
|
+
def test_macro_changes_body_of_class_second_but_last_element
|
523
|
+
script, cls = compile(%q{
|
524
|
+
class ChangeableClass
|
525
|
+
macro def self.method_adding_macro
|
526
|
+
node = @call
|
527
|
+
node = node.parent until node.nil? || node.kind_of?(ClassDefinition) # cannot call enclosing_class(), currently
|
528
|
+
klass = ClassDefinition(node)
|
529
|
+
|
530
|
+
klass.body.add(quote do
|
531
|
+
def another_method
|
532
|
+
puts "called"
|
533
|
+
end
|
534
|
+
end)
|
535
|
+
nil
|
536
|
+
end
|
537
|
+
|
538
|
+
method_adding_macro
|
539
|
+
|
540
|
+
def last_body_element
|
541
|
+
1
|
542
|
+
end
|
543
|
+
end
|
544
|
+
|
545
|
+
ChangeableClass.new.another_method
|
546
|
+
})
|
547
|
+
assert_run_output("called\n", script)
|
548
|
+
end
|
549
|
+
|
550
|
+
def test_macro_changes_body_of_class_last_element
|
551
|
+
script, cls = compile(%q{
|
552
|
+
class ChangeableClass
|
553
|
+
macro def self.method_adding_macro
|
554
|
+
node = @call
|
555
|
+
node = node.parent until node.nil? || node.kind_of?(ClassDefinition) # cannot call enclosing_class(), currently
|
556
|
+
klass = ClassDefinition(node)
|
557
|
+
|
558
|
+
klass.body.add(quote do
|
559
|
+
def another_method
|
560
|
+
puts "called"
|
561
|
+
end
|
562
|
+
end)
|
563
|
+
nil
|
564
|
+
end
|
565
|
+
|
566
|
+
method_adding_macro
|
567
|
+
end
|
568
|
+
|
569
|
+
ChangeableClass.new.another_method
|
570
|
+
})
|
571
|
+
assert_run_output("called\n", script)
|
572
|
+
end
|
573
|
+
|
574
|
+
def test_macro_in_class_inheriting_from_previously_defined_class_inheriting_from_later_to_be_defined_class
|
575
|
+
script, cls = compile(%q{
|
576
|
+
interface Bar < Baz
|
577
|
+
end
|
578
|
+
|
579
|
+
class Foo
|
580
|
+
implements Bar
|
581
|
+
|
582
|
+
macro def self.generate_foo
|
583
|
+
quote do
|
584
|
+
def foo
|
585
|
+
puts "foo"
|
586
|
+
end
|
587
|
+
end
|
588
|
+
end
|
589
|
+
|
590
|
+
generate_foo
|
591
|
+
end
|
592
|
+
|
593
|
+
interface Baz
|
594
|
+
end
|
595
|
+
|
596
|
+
Foo.new.foo
|
597
|
+
})
|
598
|
+
assert_run_output("foo\n", script)
|
599
|
+
end
|
600
|
+
|
601
|
+
def test_macro_in_class_inheriting_from_previously_defined_class_inheriting_from_later_to_be_defined_class2
|
602
|
+
script, cls = compile(%q{
|
603
|
+
interface Bar < Baz
|
604
|
+
end
|
605
|
+
|
606
|
+
class Foo
|
607
|
+
implements Bar, Baz
|
608
|
+
|
609
|
+
macro def self.generate_foo
|
610
|
+
quote do
|
611
|
+
def foo
|
612
|
+
puts "foo"
|
613
|
+
end
|
614
|
+
end
|
615
|
+
end
|
616
|
+
|
617
|
+
generate_foo
|
618
|
+
end
|
619
|
+
|
620
|
+
interface Baz
|
621
|
+
end
|
622
|
+
|
623
|
+
Foo.new.foo
|
624
|
+
})
|
625
|
+
assert_run_output("foo\n", script)
|
626
|
+
end
|
627
|
+
|
628
|
+
def test_gensym_clash
|
629
|
+
script, cls = compile(%q{
|
630
|
+
result = []
|
631
|
+
c = lambda(Runnable) do
|
632
|
+
5.times do
|
633
|
+
end
|
634
|
+
end
|
635
|
+
result.each do |r:Runnable|
|
636
|
+
end
|
637
|
+
|
638
|
+
puts result
|
639
|
+
})
|
640
|
+
assert_run_output("[]\n", script)
|
641
|
+
end
|
642
|
+
|
643
|
+
def test_optional_args_macro
|
644
|
+
cls, = compile(<<-CODE)
|
645
|
+
class MacroWithBlock
|
646
|
+
macro def self._test(block:Block = nil)
|
647
|
+
if block
|
648
|
+
block.body
|
649
|
+
else
|
650
|
+
quote { puts "self nil" }
|
651
|
+
end
|
652
|
+
end
|
653
|
+
|
654
|
+
macro def test(block:Block = nil)
|
655
|
+
if block
|
656
|
+
block.body
|
657
|
+
else
|
658
|
+
quote { puts "nil" }
|
659
|
+
end
|
660
|
+
end
|
661
|
+
|
662
|
+
def self.main(args: String[]):void
|
663
|
+
mb = MacroWithBlock.new
|
664
|
+
mb.test
|
665
|
+
mb.test do
|
666
|
+
puts "test"
|
667
|
+
end
|
668
|
+
_test
|
669
|
+
_test do
|
670
|
+
puts "self test"
|
671
|
+
end
|
672
|
+
end
|
673
|
+
end
|
674
|
+
CODE
|
675
|
+
|
676
|
+
assert_run_output("nil\ntest\nself nil\nself test\n", cls)
|
677
|
+
end
|
678
|
+
|
679
|
+
def test_macro_varargs
|
680
|
+
cls, = compile(<<-CODE)
|
681
|
+
class MacroWithVarargs
|
682
|
+
macro def self.vararg(first:Node, *args:Node)
|
683
|
+
list = NodeList.new
|
684
|
+
list.add quote do
|
685
|
+
puts `first`
|
686
|
+
end
|
687
|
+
|
688
|
+
args.each do |arg:Node|
|
689
|
+
m = if arg.kind_of? Block
|
690
|
+
body = Block(arg).body
|
691
|
+
quote do
|
692
|
+
puts `body`
|
693
|
+
end
|
694
|
+
else
|
695
|
+
quote do
|
696
|
+
puts `arg`
|
697
|
+
end
|
698
|
+
end
|
699
|
+
list.add m
|
700
|
+
end
|
701
|
+
list
|
702
|
+
end
|
703
|
+
|
704
|
+
def self.main(*args:String):void
|
705
|
+
vararg 1
|
706
|
+
vararg 1, 2
|
707
|
+
vararg 1, 2, 3
|
708
|
+
vararg 1,2 {"test"}
|
709
|
+
end
|
710
|
+
end
|
711
|
+
CODE
|
712
|
+
|
713
|
+
assert_run_output("1\n1\n2\n1\n2\n3\n1\n2\ntest\n", cls)
|
391
714
|
end
|
392
715
|
end
|
716
|
+
|