From ba3a0c22a52111da15c9dfea534a68d3fffd78e3 Mon Sep 17 00:00:00 2001 From: cremno Date: Fri, 29 May 2015 12:17:13 +0200 Subject: add multiple assignment with rest tests --- test/t/syntax.rb | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'test') diff --git a/test/t/syntax.rb b/test/t/syntax.rb index 5ce4e0a63..41e49d938 100644 --- a/test/t/syntax.rb +++ b/test/t/syntax.rb @@ -219,6 +219,21 @@ assert('Splat without assignment') do assert_equal 1, a end +assert('multiple assignment (rest)') do + *a = 0 + assert_equal [0], a +end + +assert('multiple assignment (rest+post)') do + *a, b = 0, 1, 2 + *c, d = 3 + + assert_equal [0, 1], a + assert_equal [2], b + assert_equal [], c + assert_equal [3], d +end + assert('Return values of case statements') do a = [] << case 1 when 3 then 2 -- cgit v1.2.3 From 59ea323976557408ba1c5f694213c7a31bbb6e39 Mon Sep 17 00:00:00 2001 From: cremno Date: Fri, 29 May 2015 14:51:48 +0200 Subject: check if outer is a class or module For modules this check didn't exist yet. Also call #inspect. --- src/class.c | 24 +++++++++++++++--------- test/t/class.rb | 5 +++++ test/t/module.rb | 4 ++++ 3 files changed, 24 insertions(+), 9 deletions(-) (limited to 'test') diff --git a/src/class.c b/src/class.c index 3246564ec..35c3aa040 100644 --- a/src/class.c +++ b/src/class.c @@ -131,6 +131,19 @@ mrb_class_outer_module(mrb_state *mrb, struct RClass *c) return mrb_class_ptr(outer); } +static void +check_if_class_or_module(mrb_state *mrb, mrb_value obj) +{ + switch (mrb_type(obj)) { + case MRB_TT_CLASS: + case MRB_TT_SCLASS: + case MRB_TT_MODULE: + return; + default: + mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a class/module", mrb_inspect(mrb, obj)); + } +} + static struct RClass* define_module(mrb_state *mrb, mrb_sym name, struct RClass *outer) { @@ -160,6 +173,7 @@ mrb_define_module(mrb_state *mrb, const char *name) MRB_API struct RClass* mrb_vm_define_module(mrb_state *mrb, mrb_value outer, mrb_sym id) { + check_if_class_or_module(mrb, outer); return define_module(mrb, id, mrb_class_ptr(outer)); } @@ -232,15 +246,7 @@ mrb_vm_define_class(mrb_state *mrb, mrb_value outer, mrb_value super, mrb_sym id else { s = 0; } - switch (mrb_type(outer)) { - case MRB_TT_CLASS: - case MRB_TT_SCLASS: - case MRB_TT_MODULE: - break; - default: - mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a class/module", outer); - break; - } + check_if_class_or_module(mrb, outer); c = define_class(mrb, id, s, mrb_class_ptr(outer)); mrb_class_inherited(mrb, mrb_class_real(c->super), c); diff --git a/test/t/class.rb b/test/t/class.rb index d4ecf99d0..720fd37fa 100644 --- a/test/t/class.rb +++ b/test/t/class.rb @@ -383,3 +383,8 @@ assert('class variable and class << self style class method') do assert_equal("value", ClassVariableTest.class_variable) end + +assert('class with non-class/module outer raises TypeError') do + assert_raise(TypeError) { class 0::C1; end } + assert_raise(TypeError) { class []::C2; end } +end diff --git a/test/t/module.rb b/test/t/module.rb index 9852328ce..ecb969475 100644 --- a/test/t/module.rb +++ b/test/t/module.rb @@ -533,3 +533,7 @@ assert('Module#module_function') do assert_true M.respond_to?(:modfunc) end +assert('module with non-class/module outer raises TypeError') do + assert_raise(TypeError) { module 0::M1 end } + assert_raise(TypeError) { module []::M2 end } +end -- cgit v1.2.3 From 9ef4bbb10d827fb41edc8c2984e0b80fcdbea900 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sun, 31 May 2015 18:29:26 +0900 Subject: update test/t/syntax.rb to success on CRuby --- test/t/syntax.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/test/t/syntax.rb b/test/t/syntax.rb index 41e49d938..070fcbe3b 100644 --- a/test/t/syntax.rb +++ b/test/t/syntax.rb @@ -229,9 +229,9 @@ assert('multiple assignment (rest+post)') do *c, d = 3 assert_equal [0, 1], a - assert_equal [2], b + assert_equal 2, b assert_equal [], c - assert_equal [3], d + assert_equal 3, d end assert('Return values of case statements') do -- cgit v1.2.3 From 5cd877be7f875546dcc03d80aeeddd4bbbcffe3d Mon Sep 17 00:00:00 2001 From: cremno Date: Sun, 31 May 2015 13:30:49 +0200 Subject: fix masgn nosplat array rhs bug The rest lhs variable has to be an empty array if rhs is an array with less elements than pre + post lhs variables. The codegen generated OP_ARRAY with an invalid length (such as 127 for *a, b = []) because rn was negative. --- src/codegen.c | 8 +++++++- test/t/syntax.rb | 14 ++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) (limited to 'test') diff --git a/src/codegen.c b/src/codegen.c index 6f1f75e88..be630b9a8 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -1615,8 +1615,14 @@ codegen(codegen_scope *s, node *tree, int val) } } if (t->car) { /* rest (len - pre - post) */ - int rn = len - post - n; + int rn; + if (len < post + n) { + rn = 0; + } + else { + rn = len - post - n; + } genop(s, MKOP_ABC(OP_ARRAY, cursp(), rhs+n, rn)); gen_assignment(s, t->car, cursp(), NOVAL); n += rn; diff --git a/test/t/syntax.rb b/test/t/syntax.rb index 070fcbe3b..dc1a4a3b9 100644 --- a/test/t/syntax.rb +++ b/test/t/syntax.rb @@ -234,6 +234,20 @@ assert('multiple assignment (rest+post)') do assert_equal 3, d end +assert('multiple assignment (nosplat array rhs)') do + a, *b = [] + *c, d = [0] + e, *f, g = [1, 2] + + assert_nil a + assert_equal [], b + assert_equal [], c + assert_equal 0, d + assert_equal 1, e + assert_equal [], f + assert_equal 2, g +end + assert('Return values of case statements') do a = [] << case 1 when 3 then 2 -- cgit v1.2.3 From 5dd2b8e16f33b84773cdebeec4b6a86a511e8e9c Mon Sep 17 00:00:00 2001 From: Tomoyuki Sahara Date: Mon, 8 Jun 2015 17:32:14 +0900 Subject: gsub/sub supports back references in substitutes. fixes #2816. This implementation is compatible with CRuby's String#gsub/sub except \1 ... \9 and \+. They are useless without Regexp library. --- mrblib/string.rb | 39 +++++++++++++++++++++++++++++++++++++-- test/t/string.rb | 18 ++++++++++++++++++ 2 files changed, 55 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/mrblib/string.rb b/mrblib/string.rb index 90aad5d32..ee097ad6d 100644 --- a/mrblib/string.rb +++ b/mrblib/string.rb @@ -20,6 +20,30 @@ class String self end + # private method for gsub/sub + def __sub_replace(pre, m, post) + s = "" + i = 0 + while j = index("\\", i) + break if j == length-1 + t = case self[j+1] + when "\\" + "\\" + when "`" + pre + when "&", "0" + m + when "'" + post + else + self[j, 2] + end + s += self[i, j-i] + t + i = j + 2 + end + s + self[i, length-i] + end + ## # Replace all matches of +pattern+ with +replacement+. # Call block (if given) for each match and replace @@ -29,7 +53,17 @@ class String # ISO 15.2.10.5.18 def gsub(*args, &block) if args.size == 2 - split(args[0], -1).join(args[1]) + s = "" + i = 0 + while j = index(args[0], i) + seplen = args[0].length + k = j + seplen + pre = self[0, j] + post = self[k, length-k] + s += self[i, j-i] + args[1].__sub_replace(pre, args[0], post) + i = k + end + s + self[i, length-i] elsif args.size == 1 && block split(args[0], -1).join(block.call(args[0])) else @@ -76,7 +110,8 @@ class String # ISO 15.2.10.5.36 def sub(*args, &block) if args.size == 2 - split(args[0], 2).join(args[1]) + pre, post = split(args[0], 2) + pre + args[1].__sub_replace(pre, args[0], post) + post elsif args.size == 1 && block split(args[0], 2).join(block.call(args[0])) else diff --git a/test/t/string.rb b/test/t/string.rb index 63e4af000..ee6fe0848 100644 --- a/test/t/string.rb +++ b/test/t/string.rb @@ -254,6 +254,15 @@ assert('String#gsub', '15.2.10.5.18') do assert_equal('A', 'a'.gsub('a'){|w| w.capitalize }) end +assert('String#gsub with backslash') do + s = 'abXcdXef' + assert_equal 'ab<\\>cd<\\>ef', s.gsub('X', '<\\\\>') + assert_equal 'abcdef', s.gsub('X', '<\\&>') + assert_equal 'abcdef', s.gsub('X', '<\\0>') + assert_equal 'abcdef', s.gsub('X', '<\\`>') + assert_equal 'abcdef', s.gsub('X', '<\\\'>') +end + assert('String#gsub!', '15.2.10.5.19') do a = 'abcabc' a.gsub!('b', 'B') @@ -416,6 +425,15 @@ assert('String#sub', '15.2.10.5.36') do assert_equal 'aa$', 'aa#'.sub('#', '$') end +assert('String#sub with backslash') do + s = 'abXcdXef' + assert_equal 'ab<\\>cdXef', s.sub('X', '<\\\\>') + assert_equal 'abcdXef', s.sub('X', '<\\&>') + assert_equal 'abcdXef', s.sub('X', '<\\0>') + assert_equal 'abcdXef', s.sub('X', '<\\`>') + assert_equal 'abcdXef', s.sub('X', '<\\\'>') +end + assert('String#sub!', '15.2.10.5.37') do a = 'abcabc' a.sub!('b', 'B') -- cgit v1.2.3 From f0eaf9eaf53ce659c44ce6beeedbeb8bfc5b4efa Mon Sep 17 00:00:00 2001 From: cremno Date: Mon, 22 Jun 2015 13:34:24 +0200 Subject: fix arity of lambdas with optional arguments From the CRuby 2.2.2 Proc#arity documentation: If the block has optional arguments, returns -n-1, where n is the number of mandatory arguments, with the exception for blocks that are not lambdas and have only a finite number of optional arguments; in this latter case, returns n. --- src/proc.c | 2 +- test/t/proc.rb | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'test') diff --git a/src/proc.c b/src/proc.c index 4cb9ffe18..61524f00c 100644 --- a/src/proc.c +++ b/src/proc.c @@ -216,7 +216,7 @@ mrb_proc_arity(mrb_state *mrb, mrb_value self) ma = MRB_ASPEC_REQ(aspec); ra = MRB_ASPEC_REST(aspec); pa = MRB_ASPEC_POST(aspec); - arity = ra ? -(ma + pa + 1) : ma + pa; + arity = ra || MRB_PROC_STRICT_P(p) ? -(ma + pa + 1) : ma + pa; return mrb_fixnum_value(arity); } diff --git a/test/t/proc.rb b/test/t/proc.rb index 22ccceb68..888b7d56a 100644 --- a/test/t/proc.rb +++ b/test/t/proc.rb @@ -36,6 +36,14 @@ assert('Proc#arity', '15.2.17.4.2') do assert_equal(-3, b) assert_equal 1, c assert_equal 1, d + + e = ->(x=0, y){}.arity + f = ->((x, y), z=0){}.arity + g = ->(x=0){}.arity + + assert_equal(-2, e) + assert_equal(-2, f) + assert_equal(-1, g) end assert('Proc#call', '15.2.17.4.3') do -- cgit v1.2.3 From f962890a928b566c0f5ca7fdff5ef4ce19207e65 Mon Sep 17 00:00:00 2001 From: Blaž Hrastnik Date: Thu, 9 Jul 2015 23:46:54 +0200 Subject: Implement Module#prepend. --- include/mruby/class.h | 1 + src/class.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++-- test/t/module.rb | 33 +++++++++++++++++++++++++ 3 files changed, 99 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/include/mruby/class.h b/include/mruby/class.h index 9d5260a24..60310ae9d 100644 --- a/include/mruby/class.h +++ b/include/mruby/class.h @@ -16,6 +16,7 @@ struct RClass { struct iv_tbl *iv; struct kh_mt *mt; struct RClass *super; + struct RClass *origin; }; #define mrb_class_ptr(v) ((struct RClass*)(mrb_ptr(v))) diff --git a/src/class.c b/src/class.c index 8a9fdaca6..3b1ea2321 100644 --- a/src/class.c +++ b/src/class.c @@ -194,6 +194,7 @@ define_class(mrb_state *mrb, mrb_sym name, struct RClass *super, struct RClass * if (mrb_const_defined_at(mrb, mrb_obj_value(outer), name)) { c = class_from_sym(mrb, outer, name); + c = c->origin; if (super && mrb_class_real(c->super) != super) { mrb_raisef(mrb, E_TYPE_ERROR, "superclass mismatch for Class %S (%S not %S)", mrb_sym2str(mrb, name), @@ -763,12 +764,13 @@ boot_defclass(mrb_state *mrb, struct RClass *super) else { c->super = mrb->object_class; } + c->origin = c; c->mt = kh_init(mt, mrb); return c; } -MRB_API void -mrb_include_module(mrb_state *mrb, struct RClass *c, struct RClass *m) +MRB_API inline void +include_module_at(mrb_state *mrb, struct RClass *c, struct RClass *m, int search_super) { struct RClass *ins_pos; @@ -782,6 +784,7 @@ mrb_include_module(mrb_state *mrb, struct RClass *c, struct RClass *m) } while (p) { if (c != p && p->tt == MRB_TT_CLASS) { + if (!search_super) break; superclass_seen = 1; } else if (p->mt == m->mt) { @@ -810,6 +813,63 @@ mrb_include_module(mrb_state *mrb, struct RClass *c, struct RClass *m) } } +MRB_API void +mrb_include_module(mrb_state *mrb, struct RClass *c, struct RClass *m) +{ + include_module_at(mrb, c, m, FALSE); +} + +MRB_API void +mrb_prepend_module(mrb_state *mrb, struct RClass *c, struct RClass *m) +{ + struct RClass *origin; + int changed = 0; + + origin = c->origin; + if (origin == c) { + origin = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_ICLASS, c); + //OBJ_WB_UNPROTECT(origin); /* TODO: conservative shading. Need more survey. */ + origin->super = c->super; + c->super = origin; + c->origin = origin; + origin->mt = c->mt; + c->mt = kh_init(mt, mrb); + } + include_module_at(mrb, c, m, FALSE); // changed = + if (changed) { + //rb_vm_check_redefinition_by_prepend(klass); + } +} + +static mrb_value +mrb_mod_prepend_features(mrb_state *mrb, mrb_value mod) +{ + mrb_value klass; + + mrb_check_type(mrb, mod, MRB_TT_MODULE); + mrb_get_args(mrb, "C", &klass); + mrb_prepend_module(mrb, mrb_class_ptr(klass), mrb_class_ptr(mod)); + return mod; +} + +static mrb_value +mrb_mod_prepend(mrb_state *mrb, mrb_value klass) +{ + mrb_value *argv; + mrb_int argc, i; + + mrb_get_args(mrb, "*", &argv, &argc); + for (i=0; i Date: Fri, 10 Jul 2015 20:17:16 +0200 Subject: Rename classes because of conflicts --- test/t/module.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'test') diff --git a/test/t/module.rb b/test/t/module.rb index 9faaf6e2c..3c87c122b 100644 --- a/test/t/module.rb +++ b/test/t/module.rb @@ -491,18 +491,18 @@ assert('Module#prepend') do def m1; [:M4, super, :M4] end end - class C0 + class P0 include M0 prepend M1 def m1; [:C0, super, :C0] end end - class C1 < C0 + class P1 < P0 prepend M2, M3 include M4 def m1; [:C1, super, :C1] end end - obj = C1.new + obj = P1.new expected = [:M2,[:M3,[:C1,[:M4,[:M1,[:C0,[:M0],:C0],:M1],:M4],:C1],:M3],:M2] assert_equal(expected, obj.m1) end -- cgit v1.2.3 From 99aff17075905738a8e45d8b213b92a291588053 Mon Sep 17 00:00:00 2001 From: Corey Powell Date: Sat, 11 Jul 2015 11:09:52 -0500 Subject: Ported a bit more of the MRI Module#prepend tests over Currently kind_of fails miserably, still looking for the reason --- test/t/module.rb | 94 ++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 68 insertions(+), 26 deletions(-) (limited to 'test') diff --git a/test/t/module.rb b/test/t/module.rb index 3c87c122b..6fa22e8b4 100644 --- a/test/t/module.rb +++ b/test/t/module.rb @@ -474,38 +474,80 @@ end # Not ISO specified +# @!group prepend assert('Module#prepend') do - module M0 - def m1; [:M0] end - end - module M1 - def m1; [:M1, super, :M1] end - end - module M2 - def m1; [:M2, super, :M2] end - end - M3 = Module.new do - def m1; [:M3, super, :M3] end - end - module M4 - def m1; [:M4, super, :M4] end - end + assert('test_prepend') do + module M0 + def m1; [:M0] end + end + module M1 + def m1; [:M1, super, :M1] end + end + module M2 + def m1; [:M2, super, :M2] end + end + M3 = Module.new do + def m1; [:M3, super, :M3] end + end + module M4 + def m1; [:M4, super, :M4] end + end - class P0 - include M0 - prepend M1 - def m1; [:C0, super, :C0] end + class P0 + include M0 + prepend M1 + def m1; [:C0, super, :C0] end + end + class P1 < P0 + prepend M2, M3 + include M4 + def m1; [:C1, super, :C1] end + end + + obj = P1.new + expected = [:M2,[:M3,[:C1,[:M4,[:M1,[:C0,[:M0],:C0],:M1],:M4],:C1],:M3],:M2] + assert_equal(expected, obj.m1) end - class P1 < P0 - prepend M2, M3 - include M4 - def m1; [:C1, super, :C1] end + + # mruby shouldn't be affected by this since there is + # no visibility control (yet) + assert('test_public_prepend') do + assert_nothing_raised('ruby/ruby #8846') do + Class.new.prepend(Module.new) + end end - obj = P1.new - expected = [:M2,[:M3,[:C1,[:M4,[:M1,[:C0,[:M0],:C0],:M1],:M4],:C1],:M3],:M2] - assert_equal(expected, obj.m1) + assert('test_prepend_inheritance') do + bug6654 = '[ruby-core:45914]' + a = Module.new + b = Module.new { include a } + c = Module.new { prepend b } + + assert bug6654 do + # the Module#< operator should be used here instead, but we don't have it + assert_include(c.ancestors, a) + assert_include(c.ancestors, b) + end + + bug8357 = '[ruby-core:54736] [Bug #8357]' + b = Module.new { prepend a } + c = Class.new { include b } + + assert bug8357 do + # the Module#< operator should be used here instead, but we don't have it + assert_include(c.ancestors, a) + assert_include(c.ancestors, b) + end + + bug8357 = '[ruby-core:54742] [Bug #8357]' + t_print c.new.kind_of?(b) + t_print "\n" + t_print [b, b.ancestors, c, c.ancestors].inspect + t_print "\n" + assert_kind_of(b, c.new, bug8357) + end end +# @!endgroup prepend assert('Module#to_s') do module Test4to_sModules -- cgit v1.2.3 From 319553f0ef310b4f098773db713e7fcee18f69be Mon Sep 17 00:00:00 2001 From: Corey Powell Date: Sat, 11 Jul 2015 11:11:12 -0500 Subject: Removed some debug prints from the test --- test/t/module.rb | 4 ---- 1 file changed, 4 deletions(-) (limited to 'test') diff --git a/test/t/module.rb b/test/t/module.rb index 6fa22e8b4..5baaadd2e 100644 --- a/test/t/module.rb +++ b/test/t/module.rb @@ -540,10 +540,6 @@ assert('Module#prepend') do end bug8357 = '[ruby-core:54742] [Bug #8357]' - t_print c.new.kind_of?(b) - t_print "\n" - t_print [b, b.ancestors, c, c.ancestors].inspect - t_print "\n" assert_kind_of(b, c.new, bug8357) end end -- cgit v1.2.3 From 47264bf2898fbfa5cae6709074b5e5564dbbe99c Mon Sep 17 00:00:00 2001 From: Corey Powell Date: Sat, 11 Jul 2015 11:32:20 -0500 Subject: Ported all MRI prepend tests And of course, some of them fail miserably --- test/t/module.rb | 231 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 226 insertions(+), 5 deletions(-) (limited to 'test') diff --git a/test/t/module.rb b/test/t/module.rb index 5baaadd2e..7314d140f 100644 --- a/test/t/module.rb +++ b/test/t/module.rb @@ -1,6 +1,26 @@ ## # Module ISO Test +def labeled_module(name, &block) + Module.new do + singleton_class.class_eval do + define_method(:to_s) { name } + alias_method :inspect, :to_s + end + class_eval(&block) if block + end +end + +def labeled_class(name, supklass = Object, &block) + Class.new(supklass) do + singleton_class.class_eval do + define_method(:to_s) { name } + alias_method :inspect, :to_s + end + class_eval(&block) if block + end +end + assert('Module', '15.2.2') do assert_equal Class, Module.class end @@ -519,9 +539,9 @@ assert('Module#prepend') do assert('test_prepend_inheritance') do bug6654 = '[ruby-core:45914]' - a = Module.new - b = Module.new { include a } - c = Module.new { prepend b } + a = labeled_module('a') + b = labeled_module('b') { include a } + c = labeled_module('c') { prepend b } assert bug6654 do # the Module#< operator should be used here instead, but we don't have it @@ -530,8 +550,8 @@ assert('Module#prepend') do end bug8357 = '[ruby-core:54736] [Bug #8357]' - b = Module.new { prepend a } - c = Class.new { include b } + b = labeled_module('b') { prepend a } + c = labeled_class('c') { include b } assert bug8357 do # the Module#< operator should be used here instead, but we don't have it @@ -542,6 +562,207 @@ assert('Module#prepend') do bug8357 = '[ruby-core:54742] [Bug #8357]' assert_kind_of(b, c.new, bug8357) end + + assert('test_prepend_instance_methods') do + bug6655 = '[ruby-core:45915]' + assert_equal(Object.instance_methods, Class.new {prepend Module.new}.instance_methods, bug6655) + end + + assert 'test_prepend_singleton_methods' do + o = Object.new + o.singleton_class.class_eval {prepend Module.new} + assert_equal([], o.singleton_methods) + end + + assert 'test_prepend_remove_method' do + c = Class.new do + prepend Module.new { def foo; end } + end + assert_raise(NameError) do + c.class_eval do + remove_method(:foo) + end + end + c.class_eval do + def foo; end + end + removed = nil + c.singleton_class.class_eval do + define_method(:method_removed) {|id| removed = id} + end + assert_nothing_raised(NoMethodError, NameError, '[Bug #7843]') do + c.class_eval do + remove_method(:foo) + end + end + assert_equal(:foo, removed) + end + + assert 'test_prepend_class_ancestors' do + bug6658 = '[ruby-core:45919]' + m = labeled_module("m") + c = labeled_class("c") {prepend m} + assert_equal([m, c], c.ancestors[0, 2], bug6658) + + bug6662 = '[ruby-dev:45868]' + c2 = labeled_class("c2", c) + anc = c2.ancestors + assert_equal([c2, m, c, Object], anc[0..anc.index(Object)], bug6662) + end + + # this assertion causes the mrbtest to segfault + #assert 'test_prepend_module_ancestors' do + # bug6659 = '[ruby-dev:45861]' + # m0 = labeled_module("m0") { def x; [:m0, *super] end } + # m1 = labeled_module("m1") { def x; [:m1, *super] end; prepend m0 } + # m2 = labeled_module("m2") { def x; [:m2, *super] end; prepend m1 } + # c0 = labeled_class("c0") { def x; [:c0] end } + # c1 = labeled_class("c1") { def x; [:c1] end; prepend m2 } + # c2 = labeled_class("c2", c0) { def x; [:c2, *super] end; include m2 } + # # + # assert_equal([m0, m1], m1.ancestors, bug6659) + # # + # bug6662 = '[ruby-dev:45868]' + # assert_equal([m0, m1, m2], m2.ancestors, bug6662) + # assert_equal([m0, m1, m2, c1], c1.ancestors[0, 4], bug6662) + # assert_equal([:m0, :m1, :m2, :c1], c1.new.x) + # assert_equal([c2, m0, m1, m2, c0], c2.ancestors[0, 5], bug6662) + # assert_equal([:c2, :m0, :m1, :m2, :c0], c2.new.x) + # # + # m3 = labeled_module("m3") { include m1; prepend m1 } + # assert_equal([m3, m0, m1], m3.ancestors) + # m3 = labeled_module("m3") { prepend m1; include m1 } + # assert_equal([m0, m1, m3], m3.ancestors) + # m3 = labeled_module("m3") { prepend m1; prepend m1 } + # assert_equal([m0, m1, m3], m3.ancestors) + # m3 = labeled_module("m3") { include m1; include m1 } + # assert_equal([m3, m0, m1], m3.ancestors) + #end + + assert 'test_prepend_instance_methods_false' do + bug6660 = '[ruby-dev:45863]' + assert_equal([:m1], Class.new{ prepend Module.new; def m1; end }.instance_methods(false), bug6660) + assert_equal([:m1], Class.new(Class.new{def m2;end}){ prepend Module.new; def m1; end }.instance_methods(false), bug6660) + end + + assert 'test_cyclic_prepend' do + bug7841 = '[ruby-core:52205] [Bug #7841]' + m1 = Module.new + m2 = Module.new + m1.instance_eval { prepend(m2) } + assert_raise(ArgumentError, bug7841) do + m2.instance_eval { prepend(m1) } + end + end + + # these assertions will not run without a #assert_seperately method + #assert 'test_prepend_optmethod' do + # bug7983 = '[ruby-dev:47124] [Bug #7983]' + # assert_separately [], %{ + # module M + # def /(other) + # to_f / other + # end + # end + # Fixnum.send(:prepend, M) + # assert_equal(0.5, 1 / 2, "#{bug7983}") + # } + # assert_equal(0, 1 / 2) + #end + + #assert 'test_prepend_visibility' do + # bug8005 = '[ruby-core:53106] [Bug #8005]' + # c = Class.new do + # prepend Module.new {} + # def foo() end + # protected :foo + # end + # a = c.new + # assert_respond_to a, [:foo, true], bug8005 + # assert_nothing_raised(NoMethodError, bug8005) {a.send :foo} + #end + + #assert 'test_prepend_visibility_inherited' do + # bug8238 = '[ruby-core:54105] [Bug #8238]' + # assert_separately [], <<-"end;", timeout: 20 + # class A + # def foo() A; end + # private :foo + # end + # class B < A + # public :foo + # prepend Module.new + # end + # assert_equal(A, B.new.foo, "#{bug8238}") + # end; + #end + + assert 'test_prepend_included_modules' do + bug8025 = '[ruby-core:53158] [Bug #8025]' + mixin = labeled_module("mixin") + c = labeled_module("c") {prepend mixin} + im = c.included_modules + assert_not_include(im, c, bug8025) + assert_include(im, mixin, bug8025) + c1 = labeled_class("c1") {prepend mixin} + c2 = labeled_class("c2", c1) + im = c2.included_modules + assert_not_include(im, c1, bug8025) + assert_not_include(im, c2, bug8025) + assert_include(im, mixin, bug8025) + end + + assert 'test_prepend_super_in_alias' do + bug7842 = '[Bug #7842]' + + p = labeled_module("P") do + def m; "P"+super; end + end + a = labeled_class("A") do + def m; "A"; end + end + b = labeled_class("B", a) do + def m; "B"+super; end + alias m2 m + prepend p + alias m3 m + end + assert_equal("BA", b.new.m2, bug7842) + assert_equal("PBA", b.new.m3, bug7842) + end + + assert 'test_prepend_each_classes' do + m = labeled_module("M") + c1 = labeled_class("C1") {prepend m} + c2 = labeled_class("C2", c1) {prepend m} + assert_equal([m, c2, m, c1], c2.ancestors[0, 4], "should be able to prepend each classes") + end + + assert 'test_prepend_no_duplication' do + m = labeled_module("M") + c = labeled_class("C") {prepend m; prepend m} + assert_equal([m, c], c.ancestors[0, 2], "should never duplicate") + end + + assert 'test_prepend_in_superclass' do + m = labeled_module("M") + c1 = labeled_class("C1") + c2 = labeled_class("C2", c1) {prepend m} + c1.class_eval {prepend m} + assert_equal([m, c2, m, c1], c2.ancestors[0, 4], "should accesisble prepended module in superclass") + end + + # requires #assert_seperately + #assert 'test_prepend_call_super' do + # assert_separately([], <<-'end;') #do + # bug10847 = '[ruby-core:68093] [Bug #10847]' + # module M; end + # Float.prepend M + # assert_nothing_raised(SystemStackError, bug10847) do + # 0.3.numerator + # end + # end; + #end end # @!endgroup prepend -- cgit v1.2.3 From 11dad715784a61174b68fba57f6dc6c5311e22e3 Mon Sep 17 00:00:00 2001 From: Blaž Hrastnik Date: Sun, 12 Jul 2015 22:57:29 +0200 Subject: Enable visibility prepend tests again --- test/t/module.rb | 54 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 26 deletions(-) (limited to 'test') diff --git a/test/t/module.rb b/test/t/module.rb index 7314d140f..89cc257a6 100644 --- a/test/t/module.rb +++ b/test/t/module.rb @@ -670,32 +670,34 @@ assert('Module#prepend') do # assert_equal(0, 1 / 2) #end - #assert 'test_prepend_visibility' do - # bug8005 = '[ruby-core:53106] [Bug #8005]' - # c = Class.new do - # prepend Module.new {} - # def foo() end - # protected :foo - # end - # a = c.new - # assert_respond_to a, [:foo, true], bug8005 - # assert_nothing_raised(NoMethodError, bug8005) {a.send :foo} - #end - - #assert 'test_prepend_visibility_inherited' do - # bug8238 = '[ruby-core:54105] [Bug #8238]' - # assert_separately [], <<-"end;", timeout: 20 - # class A - # def foo() A; end - # private :foo - # end - # class B < A - # public :foo - # prepend Module.new - # end - # assert_equal(A, B.new.foo, "#{bug8238}") - # end; - #end + # mruby has no visibility control + assert 'test_prepend_visibility' do + bug8005 = '[ruby-core:53106] [Bug #8005]' + c = Class.new do + prepend Module.new {} + def foo() end + protected :foo + end + a = c.new + assert_true a.respond_to?(:foo), bug8005 + assert_nothing_raised(NoMethodError, bug8005) {a.send :foo} + end + + # mruby has no visibility control + assert 'test_prepend_visibility_inherited' do + bug8238 = '[ruby-core:54105] [Bug #8238]' + module Test4PrependVisibilityInherited + class A + def foo() A; end + private :foo + end + class B < A + public :foo + prepend Module.new + end + end + assert_equal(Test4PrependVisibilityInherited::A, Test4PrependVisibilityInherited::B.new.foo, "#{bug8238}") + end assert 'test_prepend_included_modules' do bug8025 = '[ruby-core:53158] [Bug #8025]' -- cgit v1.2.3 From 11cb41770dc7b36edac0af1e6784bd40d1c8243c Mon Sep 17 00:00:00 2001 From: Corey Powell Date: Mon, 13 Jul 2015 10:42:33 -0500 Subject: Space out test_prepend_super_in_alias assert Also tried to fix it, however the problem lies with how aliased methods are done and their internal structure. mruby simply aliases methods by grabbing the RProc and giving it a new name, super then determines the original method to call by using the name so a method called m, aliased as m2, will call the m2 super method instead of m --- test/t/module.rb | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/test/t/module.rb b/test/t/module.rb index 89cc257a6..605ca28a7 100644 --- a/test/t/module.rb +++ b/test/t/module.rb @@ -720,17 +720,25 @@ assert('Module#prepend') do p = labeled_module("P") do def m; "P"+super; end end + a = labeled_class("A") do def m; "A"; end end + b = labeled_class("B", a) do def m; "B"+super; end alias m2 m prepend p alias m3 m end - assert_equal("BA", b.new.m2, bug7842) - assert_equal("PBA", b.new.m3, bug7842) + + assert_nothing_raised do + assert_equal("BA", b.new.m2, bug7842) + end + + assert_nothing_raised do + assert_equal("PBA", b.new.m3, bug7842) + end end assert 'test_prepend_each_classes' do -- cgit v1.2.3 From b0fb9ccfd8cb5986ea153142687cfbed1a876d6b Mon Sep 17 00:00:00 2001 From: Blaž Hrastnik Date: Mon, 13 Jul 2015 23:25:01 +0200 Subject: Enable test_prepend_module_ancestors because it seems to pass. --- test/t/module.rb | 54 +++++++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) (limited to 'test') diff --git a/test/t/module.rb b/test/t/module.rb index 605ca28a7..7b4a8fec7 100644 --- a/test/t/module.rb +++ b/test/t/module.rb @@ -611,33 +611,33 @@ assert('Module#prepend') do end # this assertion causes the mrbtest to segfault - #assert 'test_prepend_module_ancestors' do - # bug6659 = '[ruby-dev:45861]' - # m0 = labeled_module("m0") { def x; [:m0, *super] end } - # m1 = labeled_module("m1") { def x; [:m1, *super] end; prepend m0 } - # m2 = labeled_module("m2") { def x; [:m2, *super] end; prepend m1 } - # c0 = labeled_class("c0") { def x; [:c0] end } - # c1 = labeled_class("c1") { def x; [:c1] end; prepend m2 } - # c2 = labeled_class("c2", c0) { def x; [:c2, *super] end; include m2 } - # # - # assert_equal([m0, m1], m1.ancestors, bug6659) - # # - # bug6662 = '[ruby-dev:45868]' - # assert_equal([m0, m1, m2], m2.ancestors, bug6662) - # assert_equal([m0, m1, m2, c1], c1.ancestors[0, 4], bug6662) - # assert_equal([:m0, :m1, :m2, :c1], c1.new.x) - # assert_equal([c2, m0, m1, m2, c0], c2.ancestors[0, 5], bug6662) - # assert_equal([:c2, :m0, :m1, :m2, :c0], c2.new.x) - # # - # m3 = labeled_module("m3") { include m1; prepend m1 } - # assert_equal([m3, m0, m1], m3.ancestors) - # m3 = labeled_module("m3") { prepend m1; include m1 } - # assert_equal([m0, m1, m3], m3.ancestors) - # m3 = labeled_module("m3") { prepend m1; prepend m1 } - # assert_equal([m0, m1, m3], m3.ancestors) - # m3 = labeled_module("m3") { include m1; include m1 } - # assert_equal([m3, m0, m1], m3.ancestors) - #end + assert 'test_prepend_module_ancestors' do + bug6659 = '[ruby-dev:45861]' + m0 = labeled_module("m0") { def x; [:m0, *super] end } + m1 = labeled_module("m1") { def x; [:m1, *super] end; prepend m0 } + m2 = labeled_module("m2") { def x; [:m2, *super] end; prepend m1 } + c0 = labeled_class("c0") { def x; [:c0] end } + c1 = labeled_class("c1") { def x; [:c1] end; prepend m2 } + c2 = labeled_class("c2", c0) { def x; [:c2, *super] end; include m2 } + # + assert_equal([m0, m1], m1.ancestors, bug6659) + # + bug6662 = '[ruby-dev:45868]' + assert_equal([m0, m1, m2], m2.ancestors, bug6662) + assert_equal([m0, m1, m2, c1], c1.ancestors[0, 4], bug6662) + assert_equal([:m0, :m1, :m2, :c1], c1.new.x) + assert_equal([c2, m0, m1, m2, c0], c2.ancestors[0, 5], bug6662) + assert_equal([:c2, :m0, :m1, :m2, :c0], c2.new.x) + # + m3 = labeled_module("m3") { include m1; prepend m1 } + assert_equal([m3, m0, m1], m3.ancestors) + m3 = labeled_module("m3") { prepend m1; include m1 } + assert_equal([m0, m1, m3], m3.ancestors) + m3 = labeled_module("m3") { prepend m1; prepend m1 } + assert_equal([m0, m1, m3], m3.ancestors) + m3 = labeled_module("m3") { include m1; include m1 } + assert_equal([m3, m0, m1], m3.ancestors) + end assert 'test_prepend_instance_methods_false' do bug6660 = '[ruby-dev:45863]' -- cgit v1.2.3 From 8c13e2b7c6e6c1c02771e4f9e5aebda109892503 Mon Sep 17 00:00:00 2001 From: Blaž Hrastnik Date: Mon, 13 Jul 2015 23:35:30 +0200 Subject: Set origin when doing kind_of? comparisons --- src/object.c | 1 + test/t/module.rb | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'test') diff --git a/src/object.c b/src/object.c index f8f41bfe8..c834ee04f 100644 --- a/src/object.c +++ b/src/object.c @@ -487,6 +487,7 @@ mrb_obj_is_kind_of(mrb_state *mrb, mrb_value obj, struct RClass *c) mrb_raise(mrb, E_TYPE_ERROR, "class or module required"); } + c = c->origin; while (cl) { if (cl == c || cl->mt == c->mt) return TRUE; diff --git a/test/t/module.rb b/test/t/module.rb index 7b4a8fec7..a1996f5f6 100644 --- a/test/t/module.rb +++ b/test/t/module.rb @@ -543,21 +543,21 @@ assert('Module#prepend') do b = labeled_module('b') { include a } c = labeled_module('c') { prepend b } - assert bug6654 do + #assert bug6654 do # the Module#< operator should be used here instead, but we don't have it assert_include(c.ancestors, a) assert_include(c.ancestors, b) - end + #end bug8357 = '[ruby-core:54736] [Bug #8357]' b = labeled_module('b') { prepend a } c = labeled_class('c') { include b } - assert bug8357 do + #assert bug8357 do # the Module#< operator should be used here instead, but we don't have it assert_include(c.ancestors, a) assert_include(c.ancestors, b) - end + #end bug8357 = '[ruby-core:54742] [Bug #8357]' assert_kind_of(b, c.new, bug8357) -- cgit v1.2.3 From 8c4da7accd98fb36e3f1f5f9e4ea069244345858 Mon Sep 17 00:00:00 2001 From: Blaž Hrastnik Date: Mon, 13 Jul 2015 23:38:37 +0200 Subject: assert() cannot be nested --- test/t/module.rb | 2 -- 1 file changed, 2 deletions(-) (limited to 'test') diff --git a/test/t/module.rb b/test/t/module.rb index a1996f5f6..5aba53c46 100644 --- a/test/t/module.rb +++ b/test/t/module.rb @@ -495,7 +495,6 @@ end # Not ISO specified # @!group prepend -assert('Module#prepend') do assert('test_prepend') do module M0 def m1; [:M0] end @@ -773,7 +772,6 @@ assert('Module#prepend') do # end # end; #end -end # @!endgroup prepend assert('Module#to_s') do -- cgit v1.2.3 From 78462c9181ccbc92d26a466c5a3f06aec2d2f714 Mon Sep 17 00:00:00 2001 From: Blaž Hrastnik Date: Mon, 13 Jul 2015 23:46:25 +0200 Subject: Clean up tests --- test/t/module.rb | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) (limited to 'test') diff --git a/test/t/module.rb b/test/t/module.rb index 5aba53c46..4bde20fbe 100644 --- a/test/t/module.rb +++ b/test/t/module.rb @@ -495,7 +495,7 @@ end # Not ISO specified # @!group prepend - assert('test_prepend') do + assert('Module#prepend') do module M0 def m1; [:M0] end end @@ -530,13 +530,13 @@ end # mruby shouldn't be affected by this since there is # no visibility control (yet) - assert('test_public_prepend') do + assert('Module#prepend public') do assert_nothing_raised('ruby/ruby #8846') do Class.new.prepend(Module.new) end end - assert('test_prepend_inheritance') do + assert('Module#prepend inheritance') do bug6654 = '[ruby-core:45914]' a = labeled_module('a') b = labeled_module('b') { include a } @@ -562,18 +562,18 @@ end assert_kind_of(b, c.new, bug8357) end - assert('test_prepend_instance_methods') do + assert('Moduler#prepend + #instance_methods') do bug6655 = '[ruby-core:45915]' assert_equal(Object.instance_methods, Class.new {prepend Module.new}.instance_methods, bug6655) end - assert 'test_prepend_singleton_methods' do + assert 'Module#prepend + #singleton_methods' do o = Object.new o.singleton_class.class_eval {prepend Module.new} assert_equal([], o.singleton_methods) end - assert 'test_prepend_remove_method' do + assert 'Module#prepend + #remove_method' do c = Class.new do prepend Module.new { def foo; end } end @@ -597,7 +597,7 @@ end assert_equal(:foo, removed) end - assert 'test_prepend_class_ancestors' do + assert 'Module#prepend + Class#ancestors' do bug6658 = '[ruby-core:45919]' m = labeled_module("m") c = labeled_class("c") {prepend m} @@ -609,8 +609,7 @@ end assert_equal([c2, m, c, Object], anc[0..anc.index(Object)], bug6662) end - # this assertion causes the mrbtest to segfault - assert 'test_prepend_module_ancestors' do + assert 'Module#prepend + Module#ancestors' do bug6659 = '[ruby-dev:45861]' m0 = labeled_module("m0") { def x; [:m0, *super] end } m1 = labeled_module("m1") { def x; [:m1, *super] end; prepend m0 } @@ -638,13 +637,13 @@ end assert_equal([m3, m0, m1], m3.ancestors) end - assert 'test_prepend_instance_methods_false' do + assert 'Module#prepend #instance_methods(false)' do bug6660 = '[ruby-dev:45863]' assert_equal([:m1], Class.new{ prepend Module.new; def m1; end }.instance_methods(false), bug6660) assert_equal([:m1], Class.new(Class.new{def m2;end}){ prepend Module.new; def m1; end }.instance_methods(false), bug6660) end - assert 'test_cyclic_prepend' do + assert 'cyclic Module#prepend' do bug7841 = '[ruby-core:52205] [Bug #7841]' m1 = Module.new m2 = Module.new @@ -670,7 +669,7 @@ end #end # mruby has no visibility control - assert 'test_prepend_visibility' do + assert 'Module#prepend visibility' do bug8005 = '[ruby-core:53106] [Bug #8005]' c = Class.new do prepend Module.new {} @@ -683,7 +682,7 @@ end end # mruby has no visibility control - assert 'test_prepend_visibility_inherited' do + assert 'Module#prepend inherited visibility' do bug8238 = '[ruby-core:54105] [Bug #8238]' module Test4PrependVisibilityInherited class A @@ -698,7 +697,7 @@ end assert_equal(Test4PrependVisibilityInherited::A, Test4PrependVisibilityInherited::B.new.foo, "#{bug8238}") end - assert 'test_prepend_included_modules' do + assert 'Module#prepend + #included_modules' do bug8025 = '[ruby-core:53158] [Bug #8025]' mixin = labeled_module("mixin") c = labeled_module("c") {prepend mixin} @@ -713,7 +712,8 @@ end assert_include(im, mixin, bug8025) end - assert 'test_prepend_super_in_alias' do + assert 'Module#prepend super in alias' do + skip "super does not currently work in aliased methods" bug7842 = '[Bug #7842]' p = labeled_module("P") do @@ -740,20 +740,20 @@ end end end - assert 'test_prepend_each_classes' do + assert 'Module#prepend each class' do m = labeled_module("M") c1 = labeled_class("C1") {prepend m} c2 = labeled_class("C2", c1) {prepend m} - assert_equal([m, c2, m, c1], c2.ancestors[0, 4], "should be able to prepend each classes") + assert_equal([m, c2, m, c1], c2.ancestors[0, 4], "should be able to prepend each class") end - assert 'test_prepend_no_duplication' do + assert 'Module#prepend no duplication' do m = labeled_module("M") c = labeled_class("C") {prepend m; prepend m} assert_equal([m, c], c.ancestors[0, 2], "should never duplicate") end - assert 'test_prepend_in_superclass' do + assert 'Module#prepend in superclass' do m = labeled_module("M") c1 = labeled_class("C1") c2 = labeled_class("C2", c1) {prepend m} @@ -762,7 +762,7 @@ end end # requires #assert_seperately - #assert 'test_prepend_call_super' do + #assert 'Module#prepend call super' do # assert_separately([], <<-'end;') #do # bug10847 = '[ruby-core:68093] [Bug #10847]' # module M; end -- cgit v1.2.3 From 383a7d24d369bbd0e8813d7aabc587fb769e9d9c Mon Sep 17 00:00:00 2001 From: Zachary Scott Date: Sat, 22 Aug 2015 10:18:12 -0400 Subject: Move test source code and rake task to mrbgem --- mrbgems/mruby-test/README.md | 7 ++ mrbgems/mruby-test/driver.c | 166 ++++++++++++++++++++++++++++++++++++++ mrbgems/mruby-test/init_mrbtest.c | 40 +++++++++ mrbgems/mruby-test/mrbgem.rake | 69 ++++++++++++++++ test/README.md | 7 -- test/driver.c | 166 -------------------------------------- test/init_mrbtest.c | 40 --------- test/mrbtest.rake | 69 ---------------- 8 files changed, 282 insertions(+), 282 deletions(-) create mode 100644 mrbgems/mruby-test/README.md create mode 100644 mrbgems/mruby-test/driver.c create mode 100644 mrbgems/mruby-test/init_mrbtest.c create mode 100644 mrbgems/mruby-test/mrbgem.rake delete mode 100644 test/README.md delete mode 100644 test/driver.c delete mode 100644 test/init_mrbtest.c delete mode 100644 test/mrbtest.rake (limited to 'test') diff --git a/mrbgems/mruby-test/README.md b/mrbgems/mruby-test/README.md new file mode 100644 index 000000000..fa4b91e3a --- /dev/null +++ b/mrbgems/mruby-test/README.md @@ -0,0 +1,7 @@ +Running Tests +============= + +To run the tests, execute the following from the project's root directory. + + $ make test + diff --git a/mrbgems/mruby-test/driver.c b/mrbgems/mruby-test/driver.c new file mode 100644 index 000000000..7f0633723 --- /dev/null +++ b/mrbgems/mruby-test/driver.c @@ -0,0 +1,166 @@ +/* +** mrbtest - Test for Embeddable Ruby +** +** This program runs Ruby test programs in test/t directory +** against the current mruby implementation. +*/ + + +#include +#include +#include + +#include "mruby.h" +#include "mruby/proc.h" +#include "mruby/data.h" +#include "mruby/compile.h" +#include "mruby/string.h" +#include "mruby/variable.h" +#include "mruby/array.h" + +void +mrb_init_mrbtest(mrb_state *); + +/* Print a short remark for the user */ +static void +print_hint(void) +{ + printf("mrbtest - Embeddable Ruby Test\n\n"); +} + +static int +check_error(mrb_state *mrb) +{ + /* Error check */ + /* $ko_test and $kill_test should be 0 */ + mrb_value ko_test = mrb_gv_get(mrb, mrb_intern_lit(mrb, "$ko_test")); + mrb_value kill_test = mrb_gv_get(mrb, mrb_intern_lit(mrb, "$kill_test")); + + return mrb_fixnum_p(ko_test) && mrb_fixnum(ko_test) == 0 && mrb_fixnum_p(kill_test) && mrb_fixnum(kill_test) == 0; +} + +static int +eval_test(mrb_state *mrb) +{ + /* evaluate the test */ + mrb_funcall(mrb, mrb_top_self(mrb), "report", 0); + /* did an exception occur? */ + if (mrb->exc) { + mrb_print_error(mrb); + mrb->exc = 0; + return EXIT_FAILURE; + } + else if (!check_error(mrb)) { + return EXIT_FAILURE; + } + return EXIT_SUCCESS; +} + +static void +t_printstr(mrb_state *mrb, mrb_value obj) +{ + char *s; + int len; + + if (mrb_string_p(obj)) { + s = RSTRING_PTR(obj); + len = RSTRING_LEN(obj); + fwrite(s, len, 1, stdout); + } +} + +mrb_value +mrb_t_printstr(mrb_state *mrb, mrb_value self) +{ + mrb_value argv; + + mrb_get_args(mrb, "o", &argv); + t_printstr(mrb, argv); + + return argv; +} + +void +mrb_init_test_driver(mrb_state *mrb, mrb_bool verbose) +{ + struct RClass *krn, *mrbtest; + + krn = mrb->kernel_module; + mrb_define_method(mrb, krn, "__t_printstr__", mrb_t_printstr, MRB_ARGS_REQ(1)); + + mrbtest = mrb_define_module(mrb, "Mrbtest"); + + mrb_define_const(mrb, mrbtest, "FIXNUM_MAX", mrb_fixnum_value(MRB_INT_MAX)); + mrb_define_const(mrb, mrbtest, "FIXNUM_MIN", mrb_fixnum_value(MRB_INT_MIN)); + mrb_define_const(mrb, mrbtest, "FIXNUM_BIT", mrb_fixnum_value(MRB_INT_BIT)); + + if (verbose) { + mrb_gv_set(mrb, mrb_intern_lit(mrb, "$mrbtest_verbose"), mrb_true_value()); + } +} + +void +mrb_t_pass_result(mrb_state *mrb_dst, mrb_state *mrb_src) +{ + mrb_value res_src; + + if (mrb_src->exc) { + mrb_print_error(mrb_src); + exit(EXIT_FAILURE); + } + +#define TEST_COUNT_PASS(name) \ + do { \ + res_src = mrb_gv_get(mrb_src, mrb_intern_lit(mrb_src, "$" #name)); \ + if (mrb_fixnum_p(res_src)) { \ + mrb_value res_dst = mrb_gv_get(mrb_dst, mrb_intern_lit(mrb_dst, "$" #name)); \ + mrb_gv_set(mrb_dst, mrb_intern_lit(mrb_dst, "$" #name), mrb_fixnum_value(mrb_fixnum(res_dst) + mrb_fixnum(res_src))); \ + } \ + } while (FALSE) \ + + TEST_COUNT_PASS(ok_test); + TEST_COUNT_PASS(ko_test); + TEST_COUNT_PASS(kill_test); + +#undef TEST_COUNT_PASS + + res_src = mrb_gv_get(mrb_src, mrb_intern_lit(mrb_src, "$asserts")); + + if (mrb_array_p(res_src)) { + mrb_int i; + mrb_value res_dst = mrb_gv_get(mrb_dst, mrb_intern_lit(mrb_dst, "$asserts")); + for (i = 0; i < RARRAY_LEN(res_src); ++i) { + mrb_value val_src = RARRAY_PTR(res_src)[i]; + mrb_ary_push(mrb_dst, res_dst, mrb_str_new(mrb_dst, RSTRING_PTR(val_src), RSTRING_LEN(val_src))); + } + } +} + +int +main(int argc, char **argv) +{ + mrb_state *mrb; + int ret; + mrb_bool verbose = FALSE; + + print_hint(); + + /* new interpreter instance */ + mrb = mrb_open(); + if (mrb == NULL) { + fprintf(stderr, "Invalid mrb_state, exiting test driver"); + return EXIT_FAILURE; + } + + if (argc == 2 && argv[1][0] == '-' && argv[1][1] == 'v') { + printf("verbose mode: enable\n\n"); + verbose = TRUE; + } + + mrb_init_test_driver(mrb, verbose); + mrb_init_mrbtest(mrb); + ret = eval_test(mrb); + mrb_close(mrb); + + return ret; +} diff --git a/mrbgems/mruby-test/init_mrbtest.c b/mrbgems/mruby-test/init_mrbtest.c new file mode 100644 index 000000000..1e2ba92bd --- /dev/null +++ b/mrbgems/mruby-test/init_mrbtest.c @@ -0,0 +1,40 @@ +#include +#include "mruby.h" +#include "mruby/irep.h" +#include "mruby/variable.h" + +extern const uint8_t mrbtest_assert_irep[]; +extern const uint8_t mrbtest_irep[]; + +void mrbgemtest_init(mrb_state* mrb); +void mrb_init_test_driver(mrb_state* mrb, mrb_bool verbose); +void mrb_t_pass_result(mrb_state *mrb_dst, mrb_state *mrb_src); + +void +mrb_init_mrbtest(mrb_state *mrb) +{ + mrb_state *core_test; + + mrb_load_irep(mrb, mrbtest_assert_irep); + + core_test = mrb_open_core(mrb_default_allocf, NULL); + if (core_test == NULL) { + fprintf(stderr, "Invalid mrb_state, exiting %s", __FUNCTION__); + exit(EXIT_FAILURE); + } + mrb_init_test_driver(core_test, mrb_test(mrb_gv_get(mrb, mrb_intern_lit(mrb, "$mrbtest_verbose")))); + mrb_load_irep(core_test, mrbtest_assert_irep); + mrb_load_irep(core_test, mrbtest_irep); + mrb_t_pass_result(mrb, core_test); + +#ifndef DISABLE_GEMS + mrbgemtest_init(mrb); +#endif + + if (mrb->exc) { + mrb_print_error(mrb); + exit(EXIT_FAILURE); + } + mrb_close(core_test); +} + diff --git a/mrbgems/mruby-test/mrbgem.rake b/mrbgems/mruby-test/mrbgem.rake new file mode 100644 index 000000000..b9616fe9d --- /dev/null +++ b/mrbgems/mruby-test/mrbgem.rake @@ -0,0 +1,69 @@ +MRuby.each_target do + current_dir = File.dirname(__FILE__).relative_path_from(Dir.pwd) + relative_from_root = File.dirname(__FILE__).relative_path_from(MRUBY_ROOT) + current_build_dir = "#{build_dir}/#{relative_from_root}" + + exec = exefile("#{current_build_dir}/mrbtest") + clib = "#{current_build_dir}/mrbtest.c" + mlib = clib.ext(exts.object) + mrbs = Dir.glob("#{current_dir}/t/*.rb") + init = "#{current_dir}/init_mrbtest.c" + ass_c = "#{current_build_dir}/assert.c" + ass_lib = ass_c.ext(exts.object) + + mrbtest_lib = libfile("#{current_build_dir}/mrbtest") + mrbtest_objs = [mlib, ass_lib] + gems.each do |v| + mrbtest_objs.concat v.test_objs + end + file mrbtest_lib => mrbtest_objs do |t| + archiver.run t.name, t.prerequisites + end + + unless build_mrbtest_lib_only? + driver_obj = objfile("#{current_build_dir}/driver") + file exec => [driver_obj, mrbtest_lib, libfile("#{build_dir}/lib/libmruby")] do |t| + gem_flags = gems.map { |g| g.linker.flags } + gem_flags_before_libraries = gems.map { |g| g.linker.flags_before_libraries } + gem_flags_after_libraries = gems.map { |g| g.linker.flags_after_libraries } + gem_libraries = gems.map { |g| g.linker.libraries } + gem_library_paths = gems.map { |g| g.linker.library_paths } + linker.run t.name, t.prerequisites, gem_libraries, gem_library_paths, gem_flags, gem_flags_before_libraries + end + end + + file ass_lib => ass_c + file ass_c => ["#{current_dir}/assert.rb", __FILE__] do |t| + FileUtils.mkdir_p File.dirname t.name + open(t.name, 'w') do |f| + mrbc.run f, [t.prerequisites.first], 'mrbtest_assert_irep' + end + end + + file mlib => clib + file clib => [mrbcfile, init, __FILE__] + mrbs do |t| + _pp "GEN", "*.rb", "#{clib.relative_path}" + FileUtils.mkdir_p File.dirname(clib) + open(clib, 'w') do |f| + f.puts %Q[/*] + f.puts %Q[ * This file contains a list of all] + f.puts %Q[ * test functions.] + f.puts %Q[ *] + f.puts %Q[ * IMPORTANT:] + f.puts %Q[ * This file was generated!] + f.puts %Q[ * All manual changes will get lost.] + f.puts %Q[ */] + f.puts %Q[] + f.puts IO.read(init) + mrbc.run f, mrbs, 'mrbtest_irep' + gems.each do |g| + f.puts %Q[void GENERATED_TMP_mrb_#{g.funcname}_gem_test(mrb_state *mrb);] + end + f.puts %Q[void mrbgemtest_init(mrb_state* mrb) {] + gems.each do |g| + f.puts %Q[ GENERATED_TMP_mrb_#{g.funcname}_gem_test(mrb);] + end + f.puts %Q[}] + end + end +end diff --git a/test/README.md b/test/README.md deleted file mode 100644 index fa4b91e3a..000000000 --- a/test/README.md +++ /dev/null @@ -1,7 +0,0 @@ -Running Tests -============= - -To run the tests, execute the following from the project's root directory. - - $ make test - diff --git a/test/driver.c b/test/driver.c deleted file mode 100644 index 7f0633723..000000000 --- a/test/driver.c +++ /dev/null @@ -1,166 +0,0 @@ -/* -** mrbtest - Test for Embeddable Ruby -** -** This program runs Ruby test programs in test/t directory -** against the current mruby implementation. -*/ - - -#include -#include -#include - -#include "mruby.h" -#include "mruby/proc.h" -#include "mruby/data.h" -#include "mruby/compile.h" -#include "mruby/string.h" -#include "mruby/variable.h" -#include "mruby/array.h" - -void -mrb_init_mrbtest(mrb_state *); - -/* Print a short remark for the user */ -static void -print_hint(void) -{ - printf("mrbtest - Embeddable Ruby Test\n\n"); -} - -static int -check_error(mrb_state *mrb) -{ - /* Error check */ - /* $ko_test and $kill_test should be 0 */ - mrb_value ko_test = mrb_gv_get(mrb, mrb_intern_lit(mrb, "$ko_test")); - mrb_value kill_test = mrb_gv_get(mrb, mrb_intern_lit(mrb, "$kill_test")); - - return mrb_fixnum_p(ko_test) && mrb_fixnum(ko_test) == 0 && mrb_fixnum_p(kill_test) && mrb_fixnum(kill_test) == 0; -} - -static int -eval_test(mrb_state *mrb) -{ - /* evaluate the test */ - mrb_funcall(mrb, mrb_top_self(mrb), "report", 0); - /* did an exception occur? */ - if (mrb->exc) { - mrb_print_error(mrb); - mrb->exc = 0; - return EXIT_FAILURE; - } - else if (!check_error(mrb)) { - return EXIT_FAILURE; - } - return EXIT_SUCCESS; -} - -static void -t_printstr(mrb_state *mrb, mrb_value obj) -{ - char *s; - int len; - - if (mrb_string_p(obj)) { - s = RSTRING_PTR(obj); - len = RSTRING_LEN(obj); - fwrite(s, len, 1, stdout); - } -} - -mrb_value -mrb_t_printstr(mrb_state *mrb, mrb_value self) -{ - mrb_value argv; - - mrb_get_args(mrb, "o", &argv); - t_printstr(mrb, argv); - - return argv; -} - -void -mrb_init_test_driver(mrb_state *mrb, mrb_bool verbose) -{ - struct RClass *krn, *mrbtest; - - krn = mrb->kernel_module; - mrb_define_method(mrb, krn, "__t_printstr__", mrb_t_printstr, MRB_ARGS_REQ(1)); - - mrbtest = mrb_define_module(mrb, "Mrbtest"); - - mrb_define_const(mrb, mrbtest, "FIXNUM_MAX", mrb_fixnum_value(MRB_INT_MAX)); - mrb_define_const(mrb, mrbtest, "FIXNUM_MIN", mrb_fixnum_value(MRB_INT_MIN)); - mrb_define_const(mrb, mrbtest, "FIXNUM_BIT", mrb_fixnum_value(MRB_INT_BIT)); - - if (verbose) { - mrb_gv_set(mrb, mrb_intern_lit(mrb, "$mrbtest_verbose"), mrb_true_value()); - } -} - -void -mrb_t_pass_result(mrb_state *mrb_dst, mrb_state *mrb_src) -{ - mrb_value res_src; - - if (mrb_src->exc) { - mrb_print_error(mrb_src); - exit(EXIT_FAILURE); - } - -#define TEST_COUNT_PASS(name) \ - do { \ - res_src = mrb_gv_get(mrb_src, mrb_intern_lit(mrb_src, "$" #name)); \ - if (mrb_fixnum_p(res_src)) { \ - mrb_value res_dst = mrb_gv_get(mrb_dst, mrb_intern_lit(mrb_dst, "$" #name)); \ - mrb_gv_set(mrb_dst, mrb_intern_lit(mrb_dst, "$" #name), mrb_fixnum_value(mrb_fixnum(res_dst) + mrb_fixnum(res_src))); \ - } \ - } while (FALSE) \ - - TEST_COUNT_PASS(ok_test); - TEST_COUNT_PASS(ko_test); - TEST_COUNT_PASS(kill_test); - -#undef TEST_COUNT_PASS - - res_src = mrb_gv_get(mrb_src, mrb_intern_lit(mrb_src, "$asserts")); - - if (mrb_array_p(res_src)) { - mrb_int i; - mrb_value res_dst = mrb_gv_get(mrb_dst, mrb_intern_lit(mrb_dst, "$asserts")); - for (i = 0; i < RARRAY_LEN(res_src); ++i) { - mrb_value val_src = RARRAY_PTR(res_src)[i]; - mrb_ary_push(mrb_dst, res_dst, mrb_str_new(mrb_dst, RSTRING_PTR(val_src), RSTRING_LEN(val_src))); - } - } -} - -int -main(int argc, char **argv) -{ - mrb_state *mrb; - int ret; - mrb_bool verbose = FALSE; - - print_hint(); - - /* new interpreter instance */ - mrb = mrb_open(); - if (mrb == NULL) { - fprintf(stderr, "Invalid mrb_state, exiting test driver"); - return EXIT_FAILURE; - } - - if (argc == 2 && argv[1][0] == '-' && argv[1][1] == 'v') { - printf("verbose mode: enable\n\n"); - verbose = TRUE; - } - - mrb_init_test_driver(mrb, verbose); - mrb_init_mrbtest(mrb); - ret = eval_test(mrb); - mrb_close(mrb); - - return ret; -} diff --git a/test/init_mrbtest.c b/test/init_mrbtest.c deleted file mode 100644 index 1e2ba92bd..000000000 --- a/test/init_mrbtest.c +++ /dev/null @@ -1,40 +0,0 @@ -#include -#include "mruby.h" -#include "mruby/irep.h" -#include "mruby/variable.h" - -extern const uint8_t mrbtest_assert_irep[]; -extern const uint8_t mrbtest_irep[]; - -void mrbgemtest_init(mrb_state* mrb); -void mrb_init_test_driver(mrb_state* mrb, mrb_bool verbose); -void mrb_t_pass_result(mrb_state *mrb_dst, mrb_state *mrb_src); - -void -mrb_init_mrbtest(mrb_state *mrb) -{ - mrb_state *core_test; - - mrb_load_irep(mrb, mrbtest_assert_irep); - - core_test = mrb_open_core(mrb_default_allocf, NULL); - if (core_test == NULL) { - fprintf(stderr, "Invalid mrb_state, exiting %s", __FUNCTION__); - exit(EXIT_FAILURE); - } - mrb_init_test_driver(core_test, mrb_test(mrb_gv_get(mrb, mrb_intern_lit(mrb, "$mrbtest_verbose")))); - mrb_load_irep(core_test, mrbtest_assert_irep); - mrb_load_irep(core_test, mrbtest_irep); - mrb_t_pass_result(mrb, core_test); - -#ifndef DISABLE_GEMS - mrbgemtest_init(mrb); -#endif - - if (mrb->exc) { - mrb_print_error(mrb); - exit(EXIT_FAILURE); - } - mrb_close(core_test); -} - diff --git a/test/mrbtest.rake b/test/mrbtest.rake deleted file mode 100644 index b9616fe9d..000000000 --- a/test/mrbtest.rake +++ /dev/null @@ -1,69 +0,0 @@ -MRuby.each_target do - current_dir = File.dirname(__FILE__).relative_path_from(Dir.pwd) - relative_from_root = File.dirname(__FILE__).relative_path_from(MRUBY_ROOT) - current_build_dir = "#{build_dir}/#{relative_from_root}" - - exec = exefile("#{current_build_dir}/mrbtest") - clib = "#{current_build_dir}/mrbtest.c" - mlib = clib.ext(exts.object) - mrbs = Dir.glob("#{current_dir}/t/*.rb") - init = "#{current_dir}/init_mrbtest.c" - ass_c = "#{current_build_dir}/assert.c" - ass_lib = ass_c.ext(exts.object) - - mrbtest_lib = libfile("#{current_build_dir}/mrbtest") - mrbtest_objs = [mlib, ass_lib] - gems.each do |v| - mrbtest_objs.concat v.test_objs - end - file mrbtest_lib => mrbtest_objs do |t| - archiver.run t.name, t.prerequisites - end - - unless build_mrbtest_lib_only? - driver_obj = objfile("#{current_build_dir}/driver") - file exec => [driver_obj, mrbtest_lib, libfile("#{build_dir}/lib/libmruby")] do |t| - gem_flags = gems.map { |g| g.linker.flags } - gem_flags_before_libraries = gems.map { |g| g.linker.flags_before_libraries } - gem_flags_after_libraries = gems.map { |g| g.linker.flags_after_libraries } - gem_libraries = gems.map { |g| g.linker.libraries } - gem_library_paths = gems.map { |g| g.linker.library_paths } - linker.run t.name, t.prerequisites, gem_libraries, gem_library_paths, gem_flags, gem_flags_before_libraries - end - end - - file ass_lib => ass_c - file ass_c => ["#{current_dir}/assert.rb", __FILE__] do |t| - FileUtils.mkdir_p File.dirname t.name - open(t.name, 'w') do |f| - mrbc.run f, [t.prerequisites.first], 'mrbtest_assert_irep' - end - end - - file mlib => clib - file clib => [mrbcfile, init, __FILE__] + mrbs do |t| - _pp "GEN", "*.rb", "#{clib.relative_path}" - FileUtils.mkdir_p File.dirname(clib) - open(clib, 'w') do |f| - f.puts %Q[/*] - f.puts %Q[ * This file contains a list of all] - f.puts %Q[ * test functions.] - f.puts %Q[ *] - f.puts %Q[ * IMPORTANT:] - f.puts %Q[ * This file was generated!] - f.puts %Q[ * All manual changes will get lost.] - f.puts %Q[ */] - f.puts %Q[] - f.puts IO.read(init) - mrbc.run f, mrbs, 'mrbtest_irep' - gems.each do |g| - f.puts %Q[void GENERATED_TMP_mrb_#{g.funcname}_gem_test(mrb_state *mrb);] - end - f.puts %Q[void mrbgemtest_init(mrb_state* mrb) {] - gems.each do |g| - f.puts %Q[ GENERATED_TMP_mrb_#{g.funcname}_gem_test(mrb);] - end - f.puts %Q[}] - end - end -end -- cgit v1.2.3 From 69e835cd0f1ab24da191e8c09e23288bf64a2fcf Mon Sep 17 00:00:00 2001 From: Jun Hiroe Date: Thu, 27 Aug 2015 21:44:56 +0900 Subject: Add String#freeze test --- test/t/string.rb | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'test') diff --git a/test/t/string.rb b/test/t/string.rb index ee6fe0848..7326adce9 100644 --- a/test/t/string.rb +++ b/test/t/string.rb @@ -542,3 +542,11 @@ assert('String#each_byte') do assert_equal bytes1, bytes2 end + +assert('String#freeze') do + str = "hello" + str.freeze + + assert_raise(RuntimeError) { str.upcase! } +end + -- cgit v1.2.3 From b432f12fddafb6ad4ac987361bf07560efbc8fad Mon Sep 17 00:00:00 2001 From: Terence Lee Date: Mon, 31 Aug 2015 18:54:42 -0400 Subject: run bintests within subfolders of bintest/ --- test/bintest.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test') diff --git a/test/bintest.rb b/test/bintest.rb index 0ff3341a0..49990abb9 100644 --- a/test/bintest.rb +++ b/test/bintest.rb @@ -2,7 +2,7 @@ $:.unshift File.dirname(File.dirname(File.expand_path(__FILE__))) require 'test/assert.rb' ARGV.each do |gem| - Dir["#{gem}/bintest/*.rb"].each do |file| + Dir["#{gem}/bintest/**/*.rb"].each do |file| load file end end -- cgit v1.2.3 From 74696ffd9625e4dca43aa010d71020f10030de24 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 2 Sep 2015 22:29:01 +0900 Subject: Float << and >> should be more compatible to Fixnum --- mrblib/numeric.rb | 26 ++++++++++++++++++++++---- test/t/float.rb | 22 ++++++++++++++++++++++ 2 files changed, 44 insertions(+), 4 deletions(-) (limited to 'test') diff --git a/mrblib/numeric.rb b/mrblib/numeric.rb index 206185e78..6e4c5027f 100644 --- a/mrblib/numeric.rb +++ b/mrblib/numeric.rb @@ -165,12 +165,30 @@ class Float # floats should be compatible to integers. def >> other n = self.to_i - other.to_i.times { n /= 2 } - n + other = other.to_i + if other < 0 + n << -other + else + other.times { n /= 2 } + if n.abs < 1 + if n >= 0 + 0 + else + -1 + end + else + n.to_i + end + end end def << other n = self.to_i - other.to_i.times { n *= 2 } - n.to_i + other = other.to_i + if other < 0 + n >> -other + else + other.times { n *= 2 } + n + end end end diff --git a/test/t/float.rb b/test/t/float.rb index d45709173..0aab0b1f2 100644 --- a/test/t/float.rb +++ b/test/t/float.rb @@ -178,3 +178,25 @@ assert('Float#nan?') do assert_false (1.0/0.0).nan? assert_false (-1.0/0.0).nan? end + +assert('Float#<<') do + # Left Shift by one + assert_equal 46, 23.0 << 1 + + # Left Shift by a negative is Right Shift + assert_equal 23, 46.0 << -1 +end + +assert('Float#>>') do + # Right Shift by one + assert_equal 23, 46.0 >> 1 + + # Right Shift by a negative is Left Shift + assert_equal 46, 23.0 >> -1 + + # Don't raise on large Right Shift + assert_equal 0, 23.0 >> 128 + + # Don't raise on large Right Shift + assert_equal -1, -23.0 >> 128 +end -- cgit v1.2.3 From 87564dc98f22a7710f9e6565f6750bfaa220f965 Mon Sep 17 00:00:00 2001 From: Zachary Scott Date: Wed, 2 Sep 2015 09:52:37 -0400 Subject: Make travis happy We have do this because mruby's test files are found using MRUBY_ROOT, like this: mrbs = Dir.glob("#{MRUBY_ROOT}/test/t/*.rb") --- test/t/syntax.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/test/t/syntax.rb b/test/t/syntax.rb index dc1a4a3b9..fb6ffe408 100644 --- a/test/t/syntax.rb +++ b/test/t/syntax.rb @@ -1,6 +1,6 @@ assert('__FILE__') do - file = __FILE__ - assert_true 'test/t/syntax.rb' == file || 'test\t\syntax.rb' == file + file = __FILE__.split('test/')[1] + assert_true 't/syntax.rb' == file || 't\syntax.rb' == file end assert('__LINE__') do -- cgit v1.2.3 From 3a462fe4687fa2a52d2c9c20d10ae46901292b99 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 2 Sep 2015 23:41:51 +0900 Subject: Integer << and >> to use Float instead of raising RangeError --- src/numeric.c | 12 +++++++----- test/t/integer.rb | 10 ---------- 2 files changed, 7 insertions(+), 15 deletions(-) (limited to 'test') diff --git a/src/numeric.c b/src/numeric.c index 14c0b76a6..1a3c903f0 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -820,11 +820,13 @@ fix_xor(mrb_state *mrb, mrb_value x) static mrb_value lshift(mrb_state *mrb, mrb_int val, mrb_int width) { - mrb_assert(width >= 0); + mrb_assert(width > 0); if (width > NUMERIC_SHIFT_WIDTH_MAX) { - mrb_raisef(mrb, E_RANGE_ERROR, "width(%S) > (%S:MRB_INT_BIT-1)", - mrb_fixnum_value(width), - mrb_fixnum_value(NUMERIC_SHIFT_WIDTH_MAX)); + mrb_float f = (mrb_float)val; + while (width--) { + f *= 2; + } + return mrb_float_value(mrb, f); } return mrb_fixnum_value(val << width); } @@ -832,7 +834,7 @@ lshift(mrb_state *mrb, mrb_int val, mrb_int width) static mrb_value rshift(mrb_int val, mrb_int width) { - mrb_assert(width >= 0); + mrb_assert(width > 0); if (width >= NUMERIC_SHIFT_WIDTH_MAX) { if (val < 0) { return mrb_fixnum_value(-1); diff --git a/test/t/integer.rb b/test/t/integer.rb index 6b8cc308d..be3c13db2 100644 --- a/test/t/integer.rb +++ b/test/t/integer.rb @@ -147,11 +147,6 @@ assert('Integer#<<', '15.2.8.3.12') do # Left Shift by a negative is Right Shift assert_equal 23, 46 << -1 - - # Raise when shift is too large - assert_raise(RangeError) do - 2 << 128 - end end assert('Integer#>>', '15.2.8.3.13') do @@ -165,11 +160,6 @@ assert('Integer#>>', '15.2.8.3.13') do # Don't raise on large Right Shift assert_equal 0, 23 >> 128 - - # Raise when shift is too large - assert_raise(RangeError) do - 2 >> -128 - end end assert('Integer#ceil', '15.2.8.3.14') do -- cgit v1.2.3 From 698b3c925d757cd7113f9916db2dbb7e2eabf2f4 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 10 Sep 2015 23:03:53 +0900 Subject: add Hash#rehash to handle key modification; ref #2945 --- mrblib/hash.rb | 23 +++++++++++++++++++++++ test/t/hash.rb | 9 +++++++++ 2 files changed, 32 insertions(+) (limited to 'test') diff --git a/mrblib/hash.rb b/mrblib/hash.rb index cb52c1ffe..48ac96e56 100644 --- a/mrblib/hash.rb +++ b/mrblib/hash.rb @@ -319,6 +319,29 @@ class Hash h end + ## + # call-seq: + # hsh.rehash -> hsh + # + # Rebuilds the hash based on the current hash values for each key. If + # values of key objects have changed since they were inserted, this + # method will reindex hsh. + # + # h = {"AAA" => "b"} + # h.keys[0].chop! + # h #=> {"AA"=>"b"} + # h["AA"] #=> nil + # h.rehash #=> {"AA"=>"b"} + # h["AA"] #=> "b" + # + def rehash + h = {} + self.each{|k,v| + h[k] = v + } + self.replace(h) + end + def __update(h) h.each_key{|k| self[k] = h[k]} self diff --git a/test/t/hash.rb b/test/t/hash.rb index eee7c7b6a..3196cc97a 100644 --- a/test/t/hash.rb +++ b/test/t/hash.rb @@ -342,3 +342,12 @@ assert('Hash#inspect') do assert_include ret, '"a"=>100' assert_include ret, '"d"=>400' end + +assert('Hash#rehash') do + h = {[:a] => "b"} + # hash key modified + h.keys[0][0] = :b + # h[[:b]] => nil + h.rehash + assert_equal("b", h[[:b]]) +end -- cgit v1.2.3 From f1c23a0f75a4a38c5077e1df30af200f3700752f Mon Sep 17 00:00:00 2001 From: takahashim Date: Wed, 16 Sep 2015 18:50:03 +0900 Subject: support String#[]= with 3 args --- mrblib/string.rb | 49 ++++++++++++++++++++++++++++++++++++------- test/t/string.rb | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 7 deletions(-) (limited to 'test') diff --git a/mrblib/string.rb b/mrblib/string.rb index 05b13cb43..5765cff9b 100644 --- a/mrblib/string.rb +++ b/mrblib/string.rb @@ -154,13 +154,48 @@ class String end ## - # Modify +self+ by replacing the content of +self+ - # at the position +pos+ with +value+. - def []=(pos, value) - pos += self.length if pos < 0 - b = self[0, pos] - a = self[pos + 1..-1] - self.replace([b, value, a].join('')) + # Modify +self+ by replacing the content of +self+. + # The portion of the string affected is determined using the same criteria as +String#[]+. + def []=(*args) + anum = args.size + if anum == 2 + pos, value = args + if pos.kind_of? String + posnum = self.index(pos) + if posnum + b = self[0, posnum.to_i] + a = self[(posnum + pos.length)..-1] + self.replace([b, value, a].join('')) + return value + else + raise IndexError, "string not matched" + end + else + pos += self.length if pos < 0 + if pos < 0 || pos > self.length + raise IndexError, "index #{args[0]} out of string" + end + b = self[0, pos.to_i] + a = self[pos + 1..-1] + self.replace([b, value, a].join('')) + return value + end + elsif anum == 3 + pos, len, value = args + pos += self.length if pos < 0 + if pos < 0 || pos > self.length + raise IndexError, "index #{args[0]} out of string" + end + if len < 0 + raise IndexError, "negative length #{len}" + end + b = self[0, pos.to_i] + a = self[pos + len..-1] + self.replace([b, value, a].join('')) + return value + else + raise ArgumentError, "wrong number of arguments (#{anum} for 2..3)" + end end ## diff --git a/test/t/string.rb b/test/t/string.rb index 7326adce9..87aec0e21 100644 --- a/test/t/string.rb +++ b/test/t/string.rb @@ -122,6 +122,69 @@ assert('String#[] with Range') do assert_equal 'bc', j2 end +assert('String#[]=') do + # length of args is 1 + a = 'abc' + a[0] = 'X' + assert_equal 'Xbc', a + + b = 'abc' + b[-1] = 'X' + assert_equal 'abX', b + + c = 'abc' + assert_raise(IndexError) do + c[10] = 'X' + end + + d = 'abc' + assert_raise(IndexError) do + d[-10] = 'X' + end + + e = 'abc' + e[1.1] = 'X' + assert_equal 'aXc', e + + + # length of args is 2 + a1 = 'abc' + assert_raise(IndexError) do + a1[0, -1] = 'X' + end + + b1 = 'abc' + assert_raise(IndexError) do + b1[10, 0] = 'X' + end + + c1 = 'abc' + assert_raise(IndexError) do + c1[-10, 0] = 'X' + end + + d1 = 'abc' + d1[0, 0] = 'X' + assert_equal 'Xabc', d1 + + e1 = 'abc' + e1[1, 3] = 'X' + assert_equal 'aX', e1 + + # args is RegExp + # It will be tested in mrbgems. + + # args is String + a3 = 'abc' + a3['bc'] = 'X' + assert_equal a3, 'aX' + + b3 = 'abc' + assert_raise(IndexError) do + b3['XX'] = 'Y' + end +end + assert('String#capitalize', '15.2.10.5.7') do a = 'abc' a.capitalize -- cgit v1.2.3