4 class BinTest_MrubyBinDebugger
7 def self.test(rubysource, testcase)
8 script, bin = Tempfile.new(['test', '.rb']), Tempfile.new(['test', '.mrb'])
11 script.write rubysource
15 `./bin/mrbc -g -o "#{bin.path}" "#{script.path}"`
18 testcase << {:cmd=>"quit"}
20 stdin_data = testcase.map{|t| t[:cmd]}.join("\n") << "\n"
22 ["bin/mrdb #{script.path}","bin/mrdb -b #{bin.path}"].each do |cmd|
23 o, s = Open3.capture2(cmd, :stdin_data => stdin_data)
25 exp_vals = testcase.map{|t| t.fetch(:exp, nil)}
28 o.split("\n").each_with_index do |i,actual|
32 # compare actual / expected
33 o.split("\n").each do |actual|
38 a = actual.include?(exp) unless exp.nil?
39 p [actual, exp] unless a
41 assert_true actual.include?(exp) unless exp.nil?
45 exp_vals.each do |exp|
47 idx = o.index(exp, idx)
56 assert('mruby-bin-debugger(print) invalid arguments') do
62 tc << {:cmd=>"p", :exp=>"Parameter not specified."}
64 BinTest_MrubyBinDebugger.test(src, tc)
67 assert('mruby-bin-debugger(print) nomal') do
78 tc << {:cmd=>"p (1+2)", :exp=>'$1 = 3'}
79 tc << {:cmd=>"p foo", :exp=>'$2 = "foo"'}
80 tc << {:cmd=>"p foo*=2", :exp=>'$3 = "foofoo"'}
82 tc << {:cmd=>"p bar", :exp=>'$4 = "foofoo"'}
84 BinTest_MrubyBinDebugger.test(src, tc)
87 assert('mruby-bin-debugger(print) error') do
93 tc << {:cmd=>"p (1+2", :exp=>'$1 = SyntaxError'}
94 tc << {:cmd=>"p bar", :exp=>'$2 = (eval):2: undefined method'}
96 BinTest_MrubyBinDebugger.test(src, tc)
99 # Kernel#instance_eval(string) does't work multiple statements.
101 assert('mruby-bin-debugger(print) multiple statements') do
112 tc << {:cmd=>"p x=1;x+=2", :exp=>"3"}
114 tc << {:cmd=>"p x", :exp=>"3"}
116 BinTest_MrubyBinDebugger.test(src, tc)
120 assert('mruby-bin-debugger(print) scope:top') do
121 # ruby source (bp is break point)
126 tc << {:cmd=>"p self", :exp=>'$1 = main'}
128 BinTest_MrubyBinDebugger.test(src, tc)
131 assert('mruby-bin-debugger(print) scope:class') do
132 # ruby source (bp is break point)
142 tc << {:cmd=>"p self", :exp=>'$1 = TestClassScope'}
144 BinTest_MrubyBinDebugger.test(src, tc)
147 assert('mruby-bin-debugger(print) scope:module') do
148 # ruby source (bp is break point)
150 class TestModuleScope
158 tc << {:cmd=>"p self", :exp=>'$1 = TestModuleScope'}
160 BinTest_MrubyBinDebugger.test(src, tc)
163 assert('mruby-bin-debugger(print) scope:instance method') do
164 # ruby source (bp is break point)
166 class TestMethodScope
171 TestMethodScope.new.m
177 tc << {:cmd=>"p self", :exp=>'$1 = #<TestMethodScope:'}
179 BinTest_MrubyBinDebugger.test(src, tc)
182 assert('mruby-bin-debugger(print) scope:class method') do
183 # ruby source (bp is break point)
185 class TestClassMethodScope
190 TestClassMethodScope.cm
196 tc << {:cmd=>"p self", :exp=>'$1 = TestClassMethodScope'}
198 BinTest_MrubyBinDebugger.test(src, tc)
201 assert('mruby-bin-debugger(print) scope:block') do
202 # ruby source (bp is break point)
225 tc << {:cmd=>"p self", :exp=>'$1 = main'}
227 tc << {:cmd=>"p self", :exp=>'$2 = TestBlockScope'}
229 tc << {:cmd=>"p self", :exp=>'$3 = #<TestBlockScope:'}
231 BinTest_MrubyBinDebugger.test(src, tc)
234 assert('mruby-bin-debugger(print) same name:local variabe') do
235 # ruby source (bp is break point)
238 class TestLocalVariableName
241 lv = 'instance method'
246 TestLocalVariableName.new.m
255 tc << {:cmd=>"p lv", :exp=>'$1 = "class"'}
257 tc << {:cmd=>"p lv", :exp=>'$2 = "instance method"'}
259 tc << {:cmd=>"p lv", :exp=>'$3 = "top"'}
261 BinTest_MrubyBinDebugger.test(src, tc)
264 assert('mruby-bin-debugger(print) same name:instance variabe') do
265 # ruby source (bp is break point)
268 class TestInstanceVariableName
276 i1 = TestInstanceVariableName.new('instance1')
277 i2 = TestInstanceVariableName.new('instance2')
287 tc << {:cmd=>"p @iv", :exp=>'$1 = "instance1"'}
289 tc << {:cmd=>"p @iv", :exp=>'$2 = "instance2"'}
291 tc << {:cmd=>"p @iv", :exp=>'$3 = "top"'}
293 BinTest_MrubyBinDebugger.test(src, tc)
296 # Kernel#instance_eval(string) does't work const.
298 assert('mruby-bin-debugger(print) same name:const') do
299 # ruby source (bp is break point)
302 class TestConstNameSuperClass
308 class TestConstNameSubClass < TestConstNameSuperClass
315 TestConstNameSuperClass.new.m()
316 TestConstNameSubClass.new.m()
320 # todo: wait for 'break' to be implemented
322 9.times { tc << {:cmd=>"s"} }
323 tc << {:cmd=>"p CONST", :exp=>"super class"}
324 3.times { tc << {:cmd=>"s"} }
325 tc << {:cmd=>"p CONST", :exp=>"sub class"}
326 1.times { tc << {:cmd=>"s"} }
327 tc << {:cmd=>"p CONST", :exp=>"top"}
329 BinTest_MrubyBinDebugger.test(src, tc)
333 assert('mruby-bin-debugger(print) Literal:Numeric') do
335 src = "foo = 'foo'\n"
339 tc << {:cmd=>"p 100", :exp=>'$1 = 100'}
340 tc << {:cmd=>"p -0b100", :exp=>'$2 = -4'}
341 tc << {:cmd=>"p +0100", :exp=>'$3 = 64'}
342 tc << {:cmd=>"p 0x100", :exp=>'$4 = 256'}
343 tc << {:cmd=>"p 1_234", :exp=>'$5 = 1234'}
344 tc << {:cmd=>"p 0b1000_0000", :exp=>"$6 = #{0b1000_0000}"}
345 tc << {:cmd=>"p 0x1000_0000", :exp=>"$7 = #{0x1000_0000}"}
347 tc << {:cmd=>"p 3.14", :exp=>'$8 = 3.14'}
348 tc << {:cmd=>"p -12.3", :exp=>'$9 = -12.3'}
349 tc << {:cmd=>"p +12.000", :exp=>'$10 = 12'}
350 tc << {:cmd=>"p 1e4", :exp=>'$11 = 10000'}
351 tc << {:cmd=>"p -0.1e-2", :exp=>'$12 = -0.001'}
353 BinTest_MrubyBinDebugger.test(src, tc)
356 assert('mruby-bin-debugger(print) Literal:String') do
369 tc << {:cmd=>'p "str"', :exp=>'$1 = "str"'}
370 tc << {:cmd=>'p "s\tt\rr\n"', :exp=>'$2 = "s\\tt\\rr\\n"'}
371 tc << {:cmd=>'p "\C-a\C-z"', :exp=>'$3 = "\\x01\\x1a"'}
372 tc << {:cmd=>'p "#{foo+bar}"', :exp=>'$4 = "foobar"'}
374 tc << {:cmd=>'p \'str\'', :exp=>'$5 = "str"'}
375 tc << {:cmd=>'p \'s\\tt\\rr\\n\'', :exp=>'$6 = "s\\\\tt\\\\rr\\\\n"'}
376 tc << {:cmd=>'p \'\\C-a\\C-z\'', :exp=>'$7 = "\\\\C-a\\\\C-z"'}
377 tc << {:cmd=>'p \'#{foo+bar}\'', :exp=>'$8 = "\\#{foo+bar}"'}
379 tc << {:cmd=>'p %!str!', :exp=>'$9 = "str"'}
380 tc << {:cmd=>'p %!s\tt\rr\n!', :exp=>'$10 = "s\\tt\\rr\\n"'}
381 tc << {:cmd=>'p %!\C-a\C-z!', :exp=>'$11 = "\\x01\\x1a"'}
382 tc << {:cmd=>'p %!#{foo+bar}!', :exp=>'$12 = "foobar"'}
384 tc << {:cmd=>'p %Q!str!', :exp=>'$13 = "str"'}
385 tc << {:cmd=>'p %Q!s\tt\rr\n!', :exp=>'$14 = "s\\tt\\rr\\n"'}
386 tc << {:cmd=>'p %Q!\C-a\C-z!', :exp=>'$15 = "\\x01\\x1a"'}
387 tc << {:cmd=>'p %Q!#{foo+bar}!', :exp=>'$16 = "foobar"'}
389 tc << {:cmd=>'p %q!str!', :exp=>'$17 = "str"'}
390 tc << {:cmd=>'p %q!s\\tt\\rr\\n!', :exp=>'$18 = "s\\\\tt\\\\rr\\\\n"'}
391 tc << {:cmd=>'p %q!\\C-a\\C-z!', :exp=>'$19 = "\\\\C-a\\\\C-z"'}
392 tc << {:cmd=>'p %q!#{foo+bar}!', :exp=>'$20 = "\\#{foo+bar}"'}
394 BinTest_MrubyBinDebugger.test(src, tc)
397 assert('mruby-bin-debugger(print) Literal:Array') do
410 tc << {:cmd=>'p []', :exp=>'$1 = []'}
411 tc << {:cmd=>'p [ 5, 12, 8, 10, ]', :exp=>'$2 = [5, 12, 8, 10]'}
412 tc << {:cmd=>'p [1,2.5,"#{foo+bar}"]', :exp=>'$3 = [1, 2.5, "foobar"]'}
413 tc << {:cmd=>'p %w[3.14 A\ &\ B #{foo}]', :exp=>'$4 = ["3.14", "A & B", "\#{foo}"]'}
414 tc << {:cmd=>'p %W[3.14 A\ &\ B #{foo}]', :exp=>'$5 = ["3.14", "A & B", "foo"]'}
416 BinTest_MrubyBinDebugger.test(src, tc)
419 assert('mruby-bin-debugger(print) Literal:Hash') do
432 tc << {:cmd=>'p {}', :exp=>'$1 = {}'}
433 tc << {:cmd=>'p {"one"=>1,"two"=>2}', :exp=>'$2 = {"one"=>1, "two"=>2}'}
434 tc << {:cmd=>'p {:eins=>"1", :zwei=>"2", }', :exp=>'$3 = {:eins=>"1", :zwei=>"2"}'}
435 tc << {:cmd=>'p {uno:"one", dos: 2}', :exp=>'$4 = {:uno=>"one", :dos=>2}'}
436 tc << {:cmd=>'p {"one"=>1, :zwei=>2, tres:3}', :exp=>'$5 = {"one"=>1, :zwei=>2, :tres=>3}'}
437 tc << {:cmd=>'p {:foo=>"#{foo}",:bar=>"#{bar}"}', :exp=>'$6 = {:foo=>"foo", :bar=>"bar"}'}
439 BinTest_MrubyBinDebugger.test(src, tc)
442 assert('mruby-bin-debugger(print) Literal:Range') do
444 src = "foo = 'foo'\n"
448 tc << {:cmd=>'p 1..10', :exp=>'$1 = 1..10'}
449 tc << {:cmd=>'p 1...10', :exp=>'$2 = 1...10'}
450 tc << {:cmd=>'p 100..10', :exp=>'$3 = 100..10'}
451 tc << {:cmd=>'p 1 ... 10', :exp=>'$4 = 1...10'}
453 tc << {:cmd=>'p "1" .. "9"', :exp=>'$5 = "1".."9"'}
454 tc << {:cmd=>'p "A" ... "Z"', :exp=>'$6 = "A"..."Z"'}
456 BinTest_MrubyBinDebugger.test(src, tc)
459 assert('mruby-bin-debugger(print) Literal:Symbol') do
472 tc << {:cmd=>'p :sym', :exp=>'$1 = :sym'}
473 tc << {:cmd=>'p :"sd"', :exp=>'$2 = :sd'}
474 tc << {:cmd=>"p :'ss'", :exp=>'$3 = :ss'}
475 tc << {:cmd=>'p :"123"', :exp=>'$4 = :"123"'}
476 tc << {:cmd=>'p :"#{foo} baz"', :exp=>'$5 = :"foo baz"'}
477 tc << {:cmd=>'p %s!symsym!', :exp=>'$6 = :symsym'}
479 BinTest_MrubyBinDebugger.test(src, tc)
482 assert('mruby-bin-debugger(print) Unary operation') do
484 src = "foo = 'foo'\n"
488 tc << {:cmd=>'p +10', :exp=>'$1 = 10'}
489 tc << {:cmd=>'p -100', :exp=>'$2 = -100'}
490 tc << {:cmd=>'p !true', :exp=>'$3 = false'}
491 tc << {:cmd=>'p !false', :exp=>'$4 = true'}
492 tc << {:cmd=>'p !nil', :exp=>'$5 = true'}
493 tc << {:cmd=>'p !1', :exp=>'$6 = false'}
495 BinTest_MrubyBinDebugger.test(src, tc)
498 assert('mruby-bin-debugger(print) Binary operation') do
503 foo,bar,baz = 'foo','bar','baz'
513 tc << {:cmd=>'p a+1', :exp=>'$1 = 2'}
514 tc << {:cmd=>'p 2-b', :exp=>'$2 = -3'}
515 tc << {:cmd=>'p c * 3', :exp=>'$3 = 24'}
516 tc << {:cmd=>'p a/b', :exp=>'$4 = 0.2'}
517 tc << {:cmd=>'p c%b', :exp=>'$5 = 3'}
518 tc << {:cmd=>'p 2**10', :exp=>'$6 = 1024'}
519 tc << {:cmd=>'p ~3', :exp=>'$7 = -4'}
521 tc << {:cmd=>'p 1<<2', :exp=>'$8 = 4'}
522 tc << {:cmd=>'p 64>>5', :exp=>'$9 = 2'}
524 tc << {:cmd=>'p a|c', :exp=>'$10 = 9'}
525 tc << {:cmd=>'p a&b', :exp=>'$11 = 1'}
526 tc << {:cmd=>'p a^b', :exp=>'$12 = 4'}
528 tc << {:cmd=>'p a>b', :exp=>'$13 = false'}
529 tc << {:cmd=>'p a<b', :exp=>'$14 = true'}
530 tc << {:cmd=>'p b>=5', :exp=>'$15 = true'}
531 tc << {:cmd=>'p b<=5', :exp=>'$16 = true'}
533 tc << {:cmd=>'p "A"<=>"B"', :exp=>'$17 = -1'}
534 tc << {:cmd=>'p "A"=="B"', :exp=>'$18 = false'}
535 tc << {:cmd=>'p "A"==="B"', :exp=>'$19 = false'}
536 tc << {:cmd=>'p "A"!="B"', :exp=>'$20 = true'}
538 tc << {:cmd=>'p false || true', :exp=>'$21 = true'}
539 tc << {:cmd=>'p false && true', :exp=>'$22 = false'}
541 tc << {:cmd=>'p not nil', :exp=>'$23 = true'}
542 tc << {:cmd=>'p false or true', :exp=>'$24 = true'}
543 tc << {:cmd=>'p false and true', :exp=>'$25 = false'}
545 BinTest_MrubyBinDebugger.test(src, tc)
548 assert('mruby-bin-debugger(print) Ternary operation') do
553 foo,bar,baz = 'foo','bar','baz'
563 tc << {:cmd=>'p (a < b) ? a : b', :exp=>'$1 = 1'}
564 tc << {:cmd=>'p (a > b) ? a : b', :exp=>'$2 = 5'}
565 tc << {:cmd=>'p true ? "true" : "false"', :exp=>'$3 = "true"'}
566 tc << {:cmd=>'p false ? "true" : "false"', :exp=>'$4 = "false"'}
567 tc << {:cmd=>'p nil ? "true" : "false"', :exp=>'$5 = "false"'}
569 BinTest_MrubyBinDebugger.test(src, tc)
572 assert('mruby-bin-debugger(print) Substitution:simple') do
577 foo,bar,baz = 'foo','bar','baz'
587 tc << {:cmd=>'p a=2', :exp=>'$1 = 2'}
588 tc << {:cmd=>'p foo=[foo,bar,baz]', :exp=>'$2 = ["foo", "bar", "baz"]'}
590 tc << {:cmd=>'p undefined=-1', :exp=>'$3 = -1'}
591 tc << {:cmd=>'p "#{undefined}"', :exp=>'$4 = (eval):2: undefined method'}
593 BinTest_MrubyBinDebugger.test(src, tc)
596 assert('mruby-bin-debugger(print) Substitution:self') do
601 foo,bar,baz = 'foo','bar','baz'
611 tc << {:cmd=>'p a+=9', :exp=>'$1 = 10'}
612 tc << {:cmd=>'p b-=c', :exp=>'$2 = 15'}
613 tc << {:cmd=>'p bar*=2', :exp=>'$3 = "barbar"'}
614 tc << {:cmd=>'p a/=4', :exp=>'$4 = 2.5'}
615 tc << {:cmd=>'p c%=4', :exp=>'$5 = 2'}
617 tc << {:cmd=>'p b&=0b0101', :exp=>'$6 = 5'}
618 tc << {:cmd=>'p c|=0x10', :exp=>'$7 = 18'}
620 tc << {:cmd=>'p "#{a} #{b} #{c}"', :exp=>'$8 = "2.5 5 18"'}
621 tc << {:cmd=>'p "#{foo}#{bar}#{baz}"', :exp=>'$9 = "foobarbarbaz"'}
623 tc << {:cmd=>'p a,b,c=[10,20,30]',:exp=>'$10 = [10, 20, 30]'}
624 tc << {:cmd=>'p [a,b,c]', :exp=>'$11 = [10, 20, 30]'}
625 tc << {:cmd=>'p a,b=b,a', :exp=>'$12 = [20, 10]'}
626 tc << {:cmd=>'p [a,b]', :exp=>'$13 = [20, 10]'}
628 tc << {:cmd=>'p undefined=-1', :exp=>'$14 = -1'}
629 tc << {:cmd=>'p "#{undefined}"', :exp=>'$15 = (eval):2: undefined method'}
631 BinTest_MrubyBinDebugger.test(src, tc)
634 assert('mruby-bin-debugger(print) Substitution:multiple') do
639 foo,bar,baz = 'foo','bar','baz'
649 tc << {:cmd=>'p a,b=[10,20]', :exp=>'$1 = [10, 20]'}
650 tc << {:cmd=>'p [a,b,c]', :exp=>'$2 = [10, 20, -10]'}
652 tc << {:cmd=>'p foo,bar=["FOO","BAR","BAZ"]', :exp=>'$3 = ["FOO", "BAR", "BAZ"]'}
653 tc << {:cmd=>'p [foo,bar,baz]', :exp=>'$4 = ["FOO", "BAR", "baz"]'}
655 tc << {:cmd=>'p a,foo=foo,a', :exp=>'$5 = ["FOO", 10]'}
656 tc << {:cmd=>'p [a,foo]', :exp=>'$6 = ["FOO", 10]'}
658 # tc << {:cmd=>'p a,*b=[123, 456, 789]'}
659 # tc << {:cmd=>'p [a,b]', :exp=>'[123, [456, 789]]'}
661 BinTest_MrubyBinDebugger.test(src, tc)
664 assert('mruby-bin-debugger(print) Substitution:self') do
669 foo,bar,baz = 'foo','bar','baz'
679 tc << {:cmd=>'p a+=9', :exp=>'$1 = 10'}
680 tc << {:cmd=>'p b-=c', :exp=>'$2 = 15'}
681 tc << {:cmd=>'p bar*=2', :exp=>'$3 = "barbar"'}
682 tc << {:cmd=>'p a/=4', :exp=>'$4 = 2.5'}
683 tc << {:cmd=>'p c%=4', :exp=>'$5 = 2'}
685 tc << {:cmd=>'p b&=0b0101', :exp=>'$6 = 5'}
686 tc << {:cmd=>'p c|=0x10', :exp=>'$7 = 18'}
688 tc << {:cmd=>'p "#{a} #{b} #{c}"', :exp=>'$8 = "2.5 5 18"'}
689 tc << {:cmd=>'p "#{foo}#{bar}#{baz}"', :exp=>'$9 = "foobarbarbaz"'}
691 tc << {:cmd=>'p a,b,c=[10,20,30]',:exp=>'$10 = [10, 20, 30]'}
692 tc << {:cmd=>'p [a,b,c]', :exp=>'$11 = [10, 20, 30]'}
693 tc << {:cmd=>'p a,b=b,a', :exp=>'$12 = [20, 10]'}
694 tc << {:cmd=>'p [a,b]', :exp=>'$13 = [20, 10]'}
696 tc << {:cmd=>'p undefined=-1', :exp=>'$14 = -1'}
697 tc << {:cmd=>'p "#{undefined}"', :exp=>'$15 = (eval):2: undefined method'}
699 BinTest_MrubyBinDebugger.test(src, tc)