summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/mruby.h2
-rw-r--r--include/mruby/boxing_word.h10
-rw-r--r--include/mruby/error.h7
-rw-r--r--include/mruby/object.h10
-rw-r--r--include/mruby/value.h3
-rw-r--r--include/mruby/variable.h2
-rw-r--r--mrbgems/full-core.gembox4
-rw-r--r--mrbgems/mruby-enumerator/mrbgem.rake1
-rw-r--r--mrbgems/mruby-eval/src/eval.c29
-rw-r--r--mrbgems/mruby-eval/test/eval.rb10
-rw-r--r--mrbgems/mruby-fiber/src/fiber.c17
-rw-r--r--mrbgems/mruby-hash-ext/mrbgem.rake2
-rw-r--r--mrbgems/mruby-numeric-ext/test/numeric.rb9
-rw-r--r--mrbgems/mruby-string-utf8/src/string.c2
-rw-r--r--mrblib/array.rb13
-rw-r--r--mrblib/hash.rb20
-rw-r--r--mrblib/kernel.rb5
-rw-r--r--src/backtrace.c3
-rw-r--r--src/class.c40
-rw-r--r--src/dump.c4
-rw-r--r--src/error.c3
-rw-r--r--src/gc.c11
-rw-r--r--src/kernel.c1
-rw-r--r--src/proc.c4
-rw-r--r--src/state.c6
-rw-r--r--src/string.c2
-rw-r--r--src/symbol.c4
-rw-r--r--src/variable.c3
-rw-r--r--src/vm.c5
-rw-r--r--tasks/mrbgem_spec.rake49
-rw-r--r--tasks/mrbgems_test.rake98
-rw-r--r--test/assert.rb6
-rw-r--r--test/driver.c72
-rw-r--r--test/init_mrbtest.c15
-rw-r--r--test/mrbtest.rake12
-rw-r--r--test/no_mrb_open_test_dummy.rb2
-rw-r--r--test/t/module.rb10
37 files changed, 331 insertions, 165 deletions
diff --git a/include/mruby.h b/include/mruby.h
index d91e024d1..c4466de4c 100644
--- a/include/mruby.h
+++ b/include/mruby.h
@@ -112,6 +112,7 @@ typedef struct mrb_state {
struct mrb_jmpbuf *jmp;
mrb_allocf allocf; /* memory allocation function */
+ void *allocf_ud; /* auxiliary data of allocf */
struct mrb_context *c;
struct mrb_context *root_c;
@@ -385,6 +386,7 @@ void mrb_print_error(mrb_state *mrb);
#define E_SYNTAX_ERROR (mrb_class_get(mrb, "SyntaxError"))
#define E_LOCALJUMP_ERROR (mrb_class_get(mrb, "LocalJumpError"))
#define E_REGEXP_ERROR (mrb_class_get(mrb, "RegexpError"))
+#define E_SYSSTACK_ERROR (mrb_class_get(mrb, "SystemStackError"))
#define E_NOTIMP_ERROR (mrb_class_get(mrb, "NotImplementedError"))
#define E_FLOATDOMAIN_ERROR (mrb_class_get(mrb, "FloatDomainError"))
diff --git a/include/mruby/boxing_word.h b/include/mruby/boxing_word.h
index 6057311a8..92e6ae6de 100644
--- a/include/mruby/boxing_word.h
+++ b/include/mruby/boxing_word.h
@@ -11,6 +11,16 @@
# error MRB_INT16 is too small for MRB_WORD_BOXING.
#endif
+struct RFloat {
+ MRB_OBJECT_HEADER;
+ mrb_float f;
+};
+
+struct RCptr {
+ MRB_OBJECT_HEADER;
+ void *p;
+};
+
#define MRB_FIXNUM_SHIFT 1
#define MRB_TT_HAS_BASIC MRB_TT_FLOAT
diff --git a/include/mruby/error.h b/include/mruby/error.h
index 4d37f1701..210ae3449 100644
--- a/include/mruby/error.h
+++ b/include/mruby/error.h
@@ -11,6 +11,13 @@
extern "C" {
#endif
+struct RException {
+ MRB_OBJECT_HEADER;
+ struct iv_tbl *iv;
+};
+
+#define mrb_exc_ptr(v) ((struct RException*)mrb_ptr(v))
+
void mrb_sys_fail(mrb_state *mrb, const char *mesg);
mrb_value mrb_exc_new_str(mrb_state *mrb, struct RClass* c, mrb_value str);
#define mrb_exc_new_str_lit(mrb, c, lit) mrb_exc_new_str(mrb, c, mrb_str_new_lit(mrb, lit))
diff --git a/include/mruby/object.h b/include/mruby/object.h
index f6a9f4081..56917a021 100644
--- a/include/mruby/object.h
+++ b/include/mruby/object.h
@@ -55,14 +55,4 @@ struct RFiber {
struct mrb_context *cxt;
};
-struct RFloat {
- MRB_OBJECT_HEADER;
- mrb_float f;
-};
-
-struct RCptr {
- MRB_OBJECT_HEADER;
- void *p;
-};
-
#endif /* MRUBY_OBJECT_H */
diff --git a/include/mruby/value.h b/include/mruby/value.h
index f16fa20a6..ae75f9c23 100644
--- a/include/mruby/value.h
+++ b/include/mruby/value.h
@@ -122,6 +122,7 @@ enum mrb_vtype {
#define mrb_string_p(o) (mrb_type(o) == MRB_TT_STRING)
#define mrb_hash_p(o) (mrb_type(o) == MRB_TT_HASH)
#define mrb_cptr_p(o) (mrb_type(o) == MRB_TT_CPTR)
+#define mrb_exception_p(o) (mrb_type(o) == MRB_TT_EXCEPTION)
#define mrb_test(o) mrb_bool(o)
mrb_bool mrb_regexp_p(struct mrb_state*, mrb_value);
@@ -129,6 +130,7 @@ static inline mrb_value
mrb_float_value(struct mrb_state *mrb, mrb_float f)
{
mrb_value v;
+ (void) mrb;
SET_FLOAT_VALUE(mrb, v, f);
return v;
}
@@ -137,6 +139,7 @@ static inline mrb_value
mrb_cptr_value(struct mrb_state *mrb, void *p)
{
mrb_value v;
+ (void) mrb;
SET_CPTR_VALUE(mrb,v,p);
return v;
}
diff --git a/include/mruby/variable.h b/include/mruby/variable.h
index 68a4e5889..f3bf6ac8e 100644
--- a/include/mruby/variable.h
+++ b/include/mruby/variable.h
@@ -48,7 +48,7 @@ void mrb_iv_set(mrb_state *mrb, mrb_value obj, mrb_sym sym, mrb_value v);
mrb_bool mrb_iv_defined(mrb_state*, mrb_value, mrb_sym);
mrb_value mrb_iv_remove(mrb_state *mrb, mrb_value obj, mrb_sym sym);
void mrb_iv_copy(mrb_state *mrb, mrb_value dst, mrb_value src);
-int mrb_const_defined_at(mrb_state *mrb, struct RClass *klass, mrb_sym id);
+mrb_bool mrb_const_defined_at(mrb_state *mrb, struct RClass *klass, mrb_sym id);
mrb_value mrb_mod_constants(mrb_state *mrb, mrb_value mod);
mrb_value mrb_f_global_variables(mrb_state *mrb, mrb_value self);
mrb_value mrb_gv_get(mrb_state *mrb, mrb_sym sym);
diff --git a/mrbgems/full-core.gembox b/mrbgems/full-core.gembox
index 4a6ebbc80..4dbb13e92 100644
--- a/mrbgems/full-core.gembox
+++ b/mrbgems/full-core.gembox
@@ -2,8 +2,8 @@ MRuby::GemBox.new do |conf|
conf.gem :core => "mruby-sprintf"
conf.gem :core => "mruby-print"
- Dir.glob("#{root}/mrbgems/mruby-*") do |x|
- g = File.basename(x)
+ Dir.glob("#{root}/mrbgems/mruby-*/mrbgem.rake") do |x|
+ g = File.basename File.dirname x
conf.gem :core => g unless g =~ /^mruby-(print|sprintf)$/
end
end
diff --git a/mrbgems/mruby-enumerator/mrbgem.rake b/mrbgems/mruby-enumerator/mrbgem.rake
index abcc54e7a..8757a15ea 100644
--- a/mrbgems/mruby-enumerator/mrbgem.rake
+++ b/mrbgems/mruby-enumerator/mrbgem.rake
@@ -2,5 +2,6 @@ MRuby::Gem::Specification.new('mruby-enumerator') do |spec|
spec.license = 'MIT'
spec.author = 'mruby developers'
spec.add_dependency('mruby-fiber', :core => 'mruby-fiber')
+ spec.add_dependency 'mruby-enum-ext', :core => 'mruby-enum-ext'
spec.summary = 'Enumerator class'
end
diff --git a/mrbgems/mruby-eval/src/eval.c b/mrbgems/mruby-eval/src/eval.c
index 6ca7d4fc2..ece769faf 100644
--- a/mrbgems/mruby-eval/src/eval.c
+++ b/mrbgems/mruby-eval/src/eval.c
@@ -173,10 +173,39 @@ f_eval(mrb_state *mrb, mrb_value self)
return ret;
}
+mrb_value mrb_obj_instance_eval(mrb_state *mrb, mrb_value self);
+
+#define CI_ACC_SKIP -1
+
+static mrb_value
+f_instance_eval(mrb_state *mrb, mrb_value self)
+{
+ mrb_value b;
+ mrb_int argc; mrb_value *argv;
+
+ mrb_get_args(mrb, "*&", &argv, &argc, &b);
+
+ if (mrb_nil_p(b)) {
+ char *s;
+ mrb_int len;
+ char *file = NULL;
+ mrb_int line = 1;
+
+ mrb_get_args(mrb, "s|zi", &s, &len, &file, &line);
+ mrb->c->ci->acc = CI_ACC_SKIP;
+ return mrb_run(mrb, create_proc_from_string(mrb, s, len, mrb_nil_value(), file, line), self);
+ }
+ else {
+ mrb_get_args(mrb, "&", &b);
+ return mrb_obj_instance_eval(mrb, self);
+ }
+}
+
void
mrb_mruby_eval_gem_init(mrb_state* mrb)
{
mrb_define_module_function(mrb, mrb->kernel_module, "eval", f_eval, MRB_ARGS_ARG(1, 3));
+ mrb_define_method(mrb, mrb->kernel_module, "instance_eval", f_instance_eval, MRB_ARGS_ARG(1, 2));
}
void
diff --git a/mrbgems/mruby-eval/test/eval.rb b/mrbgems/mruby-eval/test/eval.rb
index eb51f396a..87c64732d 100644
--- a/mrbgems/mruby-eval/test/eval.rb
+++ b/mrbgems/mruby-eval/test/eval.rb
@@ -50,3 +50,13 @@ assert 'eval syntax error' do
eval 'p "test'
end
end
+
+assert('String instance_eval') do
+ obj = Object.new
+ obj.instance_variable_set :@test, 'test'
+ assert_raise(ArgumentError) { obj.instance_eval(0) { } }
+ assert_raise(ArgumentError) { obj.instance_eval('0', 'test', 0, 'test') }
+ assert_equal(['test.rb', 10]) { obj.instance_eval('[__FILE__, __LINE__]', 'test.rb', 10)}
+ assert_equal('test') { obj.instance_eval('@test') }
+ assert_equal('test') { obj.instance_eval { @test } }
+end
diff --git a/mrbgems/mruby-fiber/src/fiber.c b/mrbgems/mruby-fiber/src/fiber.c
index ddb31ea38..824a564f6 100644
--- a/mrbgems/mruby-fiber/src/fiber.c
+++ b/mrbgems/mruby-fiber/src/fiber.c
@@ -69,6 +69,7 @@ fiber_init(mrb_state *mrb, mrb_value self)
struct RProc *p;
mrb_callinfo *ci;
mrb_value blk;
+ size_t slen;
mrb_get_args(mrb, "&", &blk);
@@ -85,14 +86,18 @@ fiber_init(mrb_state *mrb, mrb_value self)
c = f->cxt;
/* initialize VM stack */
- c->stbase = (mrb_value *)mrb_malloc(mrb, FIBER_STACK_INIT_SIZE*sizeof(mrb_value));
- c->stend = c->stbase + FIBER_STACK_INIT_SIZE;
+ slen = FIBER_STACK_INIT_SIZE;
+ if (p->body.irep->nregs > slen) {
+ slen += p->body.irep->nregs;
+ }
+ c->stbase = (mrb_value *)mrb_malloc(mrb, slen*sizeof(mrb_value));
+ c->stend = c->stbase + slen;
c->stack = c->stbase;
#ifdef MRB_NAN_BOXING
{
mrb_value *p = c->stbase;
- mrb_value *pend = p + FIBER_STACK_INIT_SIZE;
+ mrb_value *pend = c->stend;
while (p < pend) {
SET_NIL_VALUE(*p);
@@ -100,7 +105,7 @@ fiber_init(mrb_state *mrb, mrb_value self)
}
}
#else
- memset(c->stbase, 0, FIBER_STACK_INIT_SIZE * sizeof(mrb_value));
+ memset(c->stbase, 0, slen * sizeof(mrb_value));
#endif
/* copy receiver from a block */
@@ -274,7 +279,8 @@ fiber_transfer(mrb_state *mrb, mrb_value self)
mrb->c->status = MRB_FIBER_TRANSFERRED;
mrb->c = c;
c->status = MRB_FIBER_RUNNING;
- MARK_CONTEXT_MODIFY(c);
+ MARK_CONTEXT_MODIFY(c);
+ mrb_write_barrier(mrb, (struct RBasic*)c->fib);
return fiber_result(mrb, a, len);
}
@@ -305,6 +311,7 @@ mrb_fiber_yield(mrb_state *mrb, mrb_int len, const mrb_value *a)
mrb->c = c->prev;
c->prev = NULL;
MARK_CONTEXT_MODIFY(mrb->c);
+ mrb_write_barrier(mrb, (struct RBasic*)c->fib);
return fiber_result(mrb, a, len);
}
diff --git a/mrbgems/mruby-hash-ext/mrbgem.rake b/mrbgems/mruby-hash-ext/mrbgem.rake
index e1ce8e767..663de2166 100644
--- a/mrbgems/mruby-hash-ext/mrbgem.rake
+++ b/mrbgems/mruby-hash-ext/mrbgem.rake
@@ -2,4 +2,6 @@ MRuby::Gem::Specification.new('mruby-hash-ext') do |spec|
spec.license = 'MIT'
spec.author = 'mruby developers'
spec.summary = 'extensional Hash class'
+ spec.add_dependency 'mruby-enum-ext', :core => 'mruby-enum-ext'
+ spec.add_dependency 'mruby-array-ext', :core => 'mruby-array-ext'
end
diff --git a/mrbgems/mruby-numeric-ext/test/numeric.rb b/mrbgems/mruby-numeric-ext/test/numeric.rb
index 4d9e83113..96644da69 100644
--- a/mrbgems/mruby-numeric-ext/test/numeric.rb
+++ b/mrbgems/mruby-numeric-ext/test/numeric.rb
@@ -5,13 +5,8 @@ assert('Integer#chr') do
assert_equal("A", 65.chr)
assert_equal("B", 0x42.chr)
- if "こんにちわ世界".size == 7 then
- # UTF-8 gem is configured
- assert_raise(RangeError) { 0x110000.chr }
- else
- # multibyte encoding (not support yet)
- assert_raise(RangeError) { 256.chr }
- end
+ # multibyte encoding (not support yet)
+ assert_raise(RangeError) { 256.chr }
end
assert('Integer#div') do
diff --git a/mrbgems/mruby-string-utf8/src/string.c b/mrbgems/mruby-string-utf8/src/string.c
index 67f54ee02..a1b779f95 100644
--- a/mrbgems/mruby-string-utf8/src/string.c
+++ b/mrbgems/mruby-string-utf8/src/string.c
@@ -608,7 +608,7 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str)
while (ptr < eptr &&
(end = mrb_memsearch(sptr, slen, ptr, eptr - ptr)) >= 0) {
- // mrb_ary_push(mrb, result, str_subseq(mrb, str, ptr - temp, end));
+ /* mrb_ary_push(mrb, result, str_subseq(mrb, str, ptr - temp, end)); */
mrb_ary_push(mrb, result, mrb_str_new(mrb, ptr, end));
mrb_gc_arena_restore(mrb, ai);
ptr += end + slen;
diff --git a/mrblib/array.rb b/mrblib/array.rb
index 3218aa858..bd8d5930f 100644
--- a/mrblib/array.rb
+++ b/mrblib/array.rb
@@ -84,13 +84,20 @@ class Array
self
end
+ def _inspect
+ return "[]" if self.size == 0
+ "["+self.map{|x|x.inspect}.join(", ")+"]"
+ end
##
- # Private method for Array creation.
+ # Return the contents of this array as a string.
#
# ISO 15.2.12.5.31 (x)
def inspect
- return "[]" if self.size == 0
- "["+self.map{|x|x.inspect}.join(", ")+"]"
+ begin
+ self._inspect
+ rescue SystemStackError
+ "[...]"
+ end
end
# ISO 15.2.12.5.32 (x)
alias to_s inspect
diff --git a/mrblib/hash.rb b/mrblib/hash.rb
index 9bb146b27..e7c51fb1f 100644
--- a/mrblib/hash.rb
+++ b/mrblib/hash.rb
@@ -192,16 +192,24 @@ class Hash
h
end
- ##
- # Return the contents of this hash as a string.
- #
- # ISO 15.2.13.4.30 (x)
- def inspect
+ # internal method for Hash inspection
+ def _inspect
return "{}" if self.size == 0
"{"+self.map {|k,v|
- k.inspect + "=>" + v.inspect
+ k._inspect + "=>" + v._inspect
}.join(", ")+"}"
end
+ ##
+ # Return the contents of this hash as a string.
+ #
+ # ISO 15.2.13.4.30 (x)
+ def inspect
+ begin
+ self._inspect
+ rescue SystemStackError
+ "{...}"
+ end
+ end
# ISO 15.2.13.4.31 (x)
alias to_s inspect
diff --git a/mrblib/kernel.rb b/mrblib/kernel.rb
index d0fe47300..476ec8e18 100644
--- a/mrblib/kernel.rb
+++ b/mrblib/kernel.rb
@@ -39,6 +39,11 @@ module Kernel
!(self =~ y)
end
+ # internal method for inspect
+ def _inspect
+ self.inspect
+ end
+
def to_enum(*a)
raise NotImplementedError.new("fiber required for enumerator")
end
diff --git a/src/backtrace.c b/src/backtrace.c
index 1e1f9fa1a..d02d11350 100644
--- a/src/backtrace.c
+++ b/src/backtrace.c
@@ -147,6 +147,9 @@ exc_output_backtrace(mrb_state *mrb, struct RObject *exc, output_stream_func fun
void
mrb_print_backtrace(mrb_state *mrb)
{
+ if (!mrb->exc || mrb_obj_is_kind_of(mrb, mrb_obj_value(mrb->exc), E_SYSSTACK_ERROR)) {
+ return;
+ }
exc_output_backtrace(mrb, mrb->exc, print_backtrace_i, (void*)stderr);
}
diff --git a/src/class.c b/src/class.c
index 2b42a6a92..4522e4529 100644
--- a/src/class.c
+++ b/src/class.c
@@ -1206,7 +1206,7 @@ mrb_bob_missing(mrb_state *mrb, mrb_value mod)
/* method missing in inspect; avoid recursion */
repr = mrb_any_to_s(mrb, mod);
}
- else if (mrb_respond_to(mrb, mod, inspect)) {
+ else if (mrb_respond_to(mrb, mod, inspect) && mrb->c->ci - mrb->c->cibase < 64) {
repr = mrb_funcall_argv(mrb, mod, inspect, 0, 0);
if (RSTRING_LEN(repr) > 64) {
repr = mrb_any_to_s(mrb, mod);
@@ -1946,6 +1946,43 @@ mrb_mod_eqq(mrb_state *mrb, mrb_value mod)
return mrb_bool_value(eqq);
}
+mrb_value
+mrb_mod_module_function(mrb_state *mrb, mrb_value mod)
+{
+ mrb_value *argv;
+ mrb_int argc, i;
+ mrb_sym mid;
+ struct RProc *method_rproc;
+ struct RClass *rclass;
+ int ai;
+
+ mrb_check_type(mrb, mod, MRB_TT_MODULE);
+
+ mrb_get_args(mrb, "*", &argv, &argc);
+ if(argc == 0) {
+ /* set MODFUNC SCOPE if implemented */
+ return mod;
+ }
+
+ /* set PRIVATE method visibility if implemented */
+ /* mrb_mod_dummy_visibility(mrb, mod); */
+
+ for (i=0; i<argc; i++) {
+ mrb_check_type(mrb, argv[i], MRB_TT_SYMBOL);
+
+ mid = mrb_symbol(argv[i]);
+ rclass = mrb_class_ptr(mod);
+ method_rproc = mrb_method_search(mrb, rclass, mid);
+
+ prepare_singleton_class(mrb, (struct RBasic*)rclass);
+ ai = mrb_gc_arena_save(mrb);
+ mrb_define_method_raw(mrb, rclass->c, mid, method_rproc);
+ mrb_gc_arena_restore(mrb, ai);
+ }
+
+ return mod;
+}
+
void
mrb_init_class(mrb_state *mrb)
{
@@ -2009,6 +2046,7 @@ mrb_init_class(mrb_state *mrb)
mrb_define_method(mrb, mod, "instance_methods", mrb_mod_instance_methods, MRB_ARGS_ANY()); /* 15.2.2.4.33 */
mrb_define_method(mrb, mod, "method_defined?", mrb_mod_method_defined, MRB_ARGS_REQ(1)); /* 15.2.2.4.34 */
mrb_define_method(mrb, mod, "module_eval", mrb_mod_module_eval, MRB_ARGS_ANY()); /* 15.2.2.4.35 */
+ mrb_define_method(mrb, mod, "module_function", mrb_mod_module_function, MRB_ARGS_ANY());
mrb_define_method(mrb, mod, "private", mrb_mod_dummy_visibility, MRB_ARGS_ANY()); /* 15.2.2.4.36 */
mrb_define_method(mrb, mod, "protected", mrb_mod_dummy_visibility, MRB_ARGS_ANY()); /* 15.2.2.4.37 */
mrb_define_method(mrb, mod, "public", mrb_mod_dummy_visibility, MRB_ARGS_ANY()); /* 15.2.2.4.38 */
diff --git a/src/dump.c b/src/dump.c
index b820f1a68..e019baa99 100644
--- a/src/dump.c
+++ b/src/dump.c
@@ -952,7 +952,9 @@ mrb_dump_irep_binary(mrb_state *mrb, mrb_irep *irep, int debug_info, FILE* fp)
result = mrb_dump_irep(mrb, irep, debug_info, &bin, &bin_size);
if (result == MRB_DUMP_OK) {
- fwrite(bin, bin_size, 1, fp);
+ if (fwrite(bin, sizeof(bin[0]), bin_size, fp) != bin_size) {
+ result = MRB_DUMP_WRITE_FAULT;
+ }
}
mrb_free(mrb, bin);
diff --git a/src/error.c b/src/error.c
index dcb6063f8..223e2137e 100644
--- a/src/error.c
+++ b/src/error.c
@@ -15,6 +15,7 @@
#include "mruby/variable.h"
#include "mruby/debug.h"
#include "mruby/error.h"
+#include "mruby/class.h"
#include "mrb_throw.h"
mrb_value
@@ -442,6 +443,7 @@ mrb_init_exception(mrb_state *mrb)
struct RClass *exception, *runtime_error, *script_error;
mrb->eException_class = exception = mrb_define_class(mrb, "Exception", mrb->object_class); /* 15.2.22 */
+ MRB_SET_INSTANCE_TT(exception, MRB_TT_EXCEPTION);
mrb_define_class_method(mrb, exception, "exception", mrb_instance_new, MRB_ARGS_ANY());
mrb_define_method(mrb, exception, "exception", exc_exception, MRB_ARGS_ANY());
mrb_define_method(mrb, exception, "initialize", exc_initialize, MRB_ARGS_ANY());
@@ -455,4 +457,5 @@ mrb_init_exception(mrb_state *mrb)
mrb->nomem_err = mrb_obj_ptr(mrb_exc_new_str(mrb, runtime_error, mrb_str_new_lit(mrb, "Out of memory")));
script_error = mrb_define_class(mrb, "ScriptError", mrb->eException_class); /* 15.2.37 */
mrb_define_class(mrb, "SyntaxError", script_error); /* 15.2.38 */
+ mrb_define_class(mrb, "SystemStackError", exception);
}
diff --git a/src/gc.c b/src/gc.c
index 8e982de6d..bdcbc5208 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -16,6 +16,7 @@
#include "mruby/string.h"
#include "mruby/variable.h"
#include "mruby/gc.h"
+#include "mruby/error.h"
/*
= Tri-color Incremental Garbage Collection
@@ -107,6 +108,7 @@ typedef struct {
struct RRange range;
struct RData data;
struct RProc proc;
+ struct RException exc;
#ifdef MRB_WORD_BOXING
struct RFloat floatv;
struct RCptr cptr;
@@ -171,10 +173,10 @@ mrb_realloc_simple(mrb_state *mrb, void *p, size_t len)
{
void *p2;
- p2 = (mrb->allocf)(mrb, p, len, mrb->ud);
+ p2 = (mrb->allocf)(mrb, p, len, mrb->allocf_ud);
if (!p2 && len > 0 && mrb->heaps) {
mrb_full_gc(mrb);
- p2 = (mrb->allocf)(mrb, p, len, mrb->ud);
+ p2 = (mrb->allocf)(mrb, p, len, mrb->allocf_ud);
}
return p2;
@@ -240,7 +242,7 @@ mrb_calloc(mrb_state *mrb, size_t nelem, size_t len)
void
mrb_free(mrb_state *mrb, void *p)
{
- (mrb->allocf)(mrb, p, 0, mrb->ud);
+ (mrb->allocf)(mrb, p, 0, mrb->allocf_ud);
}
#ifndef MRB_HEAP_PAGE_SIZE
@@ -513,6 +515,7 @@ gc_mark_children(mrb_state *mrb, struct RBasic *obj)
case MRB_TT_OBJECT:
case MRB_TT_DATA:
+ case MRB_TT_EXCEPTION:
mrb_gc_mark_iv(mrb, (struct RObject*)obj);
break;
@@ -612,6 +615,7 @@ obj_free(mrb_state *mrb, struct RBasic *obj)
#endif
case MRB_TT_OBJECT:
+ case MRB_TT_EXCEPTION:
mrb_gc_free_iv(mrb, (struct RObject*)obj);
break;
@@ -747,6 +751,7 @@ gc_gray_mark(mrb_state *mrb, struct RBasic *obj)
case MRB_TT_OBJECT:
case MRB_TT_DATA:
+ case MRB_TT_EXCEPTION:
children += mrb_gc_mark_iv_size(mrb, (struct RObject*)obj);
break;
diff --git a/src/kernel.c b/src/kernel.c
index 0258e5c15..5ba318b1d 100644
--- a/src/kernel.c
+++ b/src/kernel.c
@@ -275,6 +275,7 @@ init_copy(mrb_state *mrb, mrb_value dest, mrb_value obj)
case MRB_TT_SCLASS:
case MRB_TT_HASH:
case MRB_TT_DATA:
+ case MRB_TT_EXCEPTION:
mrb_iv_copy(mrb, dest, obj);
break;
diff --git a/src/proc.c b/src/proc.c
index 1511725d9..9e63e5f08 100644
--- a/src/proc.c
+++ b/src/proc.c
@@ -153,11 +153,11 @@ mrb_proc_arity(mrb_state *mrb, mrb_value self)
int ma, ra, pa, arity;
if (MRB_PROC_CFUNC_P(p)) {
- // TODO cfunc aspec not implemented yet
+ /* TODO cfunc aspec not implemented yet */
return mrb_fixnum_value(-1);
}
- // arity is depend on OP_ENTER
+ /* arity is depend on OP_ENTER */
if (GET_OPCODE(*iseq) != OP_ENTER) {
return mrb_fixnum_value(0);
}
diff --git a/src/state.c b/src/state.c
index ff0182f22..9c40c842c 100644
--- a/src/state.c
+++ b/src/state.c
@@ -29,15 +29,11 @@ mrb_open_core(mrb_allocf f, void *ud)
static const struct mrb_context mrb_context_zero = { 0 };
mrb_state *mrb;
-#ifdef MRB_NAN_BOXING
- mrb_static_assert(sizeof(void*) == 4, "when using NaN boxing sizeof pointer must be 4 byte");
-#endif
-
mrb = (mrb_state *)(f)(NULL, NULL, sizeof(mrb_state), ud);
if (mrb == NULL) return NULL;
*mrb = mrb_state_zero;
- mrb->ud = ud;
+ mrb->allocf_ud = ud;
mrb->allocf = f;
mrb->current_white_part = MRB_GC_WHITE_A;
mrb->atexit_stack_len = 0;
diff --git a/src/string.c b/src/string.c
index a22060e37..16e7f9ffd 100644
--- a/src/string.c
+++ b/src/string.c
@@ -1799,7 +1799,7 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str)
}
}
else if (split_type == string) {
- char *ptr = RSTRING_PTR(str); // s->as.ary
+ char *ptr = RSTRING_PTR(str); /* s->as.ary */
char *temp = ptr;
char *eptr = RSTRING_END(str);
mrb_int slen = RSTRING_LEN(spat);
diff --git a/src/symbol.c b/src/symbol.c
index 148adc6fe..cf4945185 100644
--- a/src/symbol.c
+++ b/src/symbol.c
@@ -216,12 +216,10 @@ static mrb_value
sym_equal(mrb_state *mrb, mrb_value sym1)
{
mrb_value sym2;
- mrb_bool equal_p;
mrb_get_args(mrb, "o", &sym2);
- equal_p = mrb_obj_equal(mrb, sym1, sym2);
- return mrb_bool_value(equal_p);
+ return mrb_bool_value(mrb_obj_equal(mrb, sym1, sym2));
}
/* 15.2.11.3.2 */
diff --git a/src/variable.c b/src/variable.c
index 74bb591cf..58cd08304 100644
--- a/src/variable.c
+++ b/src/variable.c
@@ -459,6 +459,7 @@ obj_iv_p(mrb_value obj)
case MRB_TT_SCLASS:
case MRB_TT_HASH:
case MRB_TT_DATA:
+ case MRB_TT_EXCEPTION:
return TRUE;
default:
return FALSE;
@@ -1085,7 +1086,7 @@ retry:
return FALSE;
}
-int
+mrb_bool
mrb_const_defined_at(mrb_state *mrb, struct RClass *klass, mrb_sym id)
{
return mrb_const_defined_0(mrb, klass, id, TRUE, FALSE);
diff --git a/src/vm.c b/src/vm.c
index 20a51eff4..d4a8fd68d 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -160,7 +160,7 @@ stack_extend_alloc(mrb_state *mrb, int room, int keep)
to prevent infinite recursion. However, do this only after resizing the stack, so mrb_raise has stack space to work with. */
if (size > MRB_STACK_MAX) {
init_new_stack_space(mrb, room, keep);
- mrb_raise(mrb, E_RUNTIME_ERROR, "stack level too deep. (limit=" TO_STR(MRB_STACK_MAX) ")");
+ mrb_raise(mrb, E_SYSSTACK_ERROR, "stack level too deep. (limit=" TO_STR(MRB_STACK_MAX) ")");
}
}
@@ -484,6 +484,9 @@ eval_under(mrb_state *mrb, mrb_value self, mrb_value blk, struct RClass *c)
struct RProc *p;
mrb_callinfo *ci;
+ if (mrb_nil_p(blk)) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given");
+ }
ci = mrb->c->ci;
if (ci->acc == CI_ACC_DIRECT) {
return mrb_yield_with_class(mrb, blk, 0, 0, self, c);
diff --git a/tasks/mrbgem_spec.rake b/tasks/mrbgem_spec.rake
index 2a15a1f46..745b2f29d 100644
--- a/tasks/mrbgem_spec.rake
+++ b/tasks/mrbgem_spec.rake
@@ -45,10 +45,6 @@ module MRuby
MRuby::Gem.current = self
end
- def run_test_in_other_mrb_state?
- not test_preload.nil? or not test_objs.empty? or not test_args.empty?
- end
-
def setup
MRuby::Gem.current = self
MRuby::Build::COMMANDS.each do |command|
@@ -66,6 +62,7 @@ module MRuby
@test_objs = Dir.glob("#{dir}/test/*.{c,cpp,cxx,cc,m,asm,s,S}").map do |f|
objfile(f.relative_path_from(dir).to_s.pathmap("#{build_dir}/%X"))
end
+ @custom_test_init = !@test_objs.empty?
@test_preload = nil # 'test/assert.rb'
@test_args = {}
@@ -184,13 +181,19 @@ module MRuby
print_gem_comment(f)
f.puts %Q[#include <stdlib.h>]
f.puts %Q[#include "mruby.h"]
- f.puts %Q[#include "mruby/array.h"]
f.puts %Q[#include "mruby/irep.h"]
- f.puts %Q[#include "mruby/string.h"]
f.puts %Q[#include "mruby/variable.h"]
f.puts %Q[#include "mruby/hash.h"] unless test_args.empty?
end
+ def test_dependencies
+ [@name]
+ end
+
+ def custom_test_init?
+ @custom_test_init
+ end
+
def version_ok?(req_versions)
req_versions.map do |req|
cmp, ver = req.split
@@ -290,7 +293,7 @@ module MRuby
@ary.empty?
end
- def check(build)
+ def generate_gem_table
gem_table = @ary.reduce({}) { |res,v| res[v.name] = v; res }
default_gems = []
@@ -335,9 +338,29 @@ module MRuby
fail "Conflicts of gem `#{g.name}` found: #{cfls.join ', '}" unless cfls.empty?
end
- class << gem_table
+ gem_table
+ end
+
+ def tsort_dependencies ary, table, all_dependency_listed = false
+ unless all_dependency_listed
+ left = ary.dup
+ until left.empty?
+ v = left.pop
+ table[v].dependencies.each do |dep|
+ left.push dep[:gem]
+ ary.push dep[:gem]
+ end
+ end
+ end
+
+ ary.uniq!
+ table.instance_variable_set :@root_gems, ary
+ class << table
include TSort
- alias tsort_each_node each_key
+ def tsort_each_node &b
+ @root_gems.each &b
+ end
+
def tsort_each_child(n, &b)
fetch(n).dependencies.each do |v|
b.call v[:gem]
@@ -346,10 +369,16 @@ module MRuby
end
begin
- @ary = gem_table.tsort.map { |v| gem_table[v] }
+ table.tsort.map { |v| table[v] }
rescue TSort::Cyclic => e
fail "Circular mrbgem dependency found: #{e.message}"
end
+ end
+
+ def check(build)
+ gem_table = generate_gem_table
+
+ @ary = tsort_dependencies gem_table.keys, gem_table, true
each do |g|
import_include_paths(g)
diff --git a/tasks/mrbgems_test.rake b/tasks/mrbgems_test.rake
index 2fdf5f171..b732fa772 100644
--- a/tasks/mrbgems_test.rake
+++ b/tasks/mrbgems_test.rake
@@ -1,16 +1,13 @@
MRuby.each_target do
- no_mrb_open_test_gem = []
+ gem_table = gems.generate_gem_table
gems.each do |g|
- unless g.run_test_in_other_mrb_state?
- no_mrb_open_test_gem << g
- next
- end
-
test_rbobj = g.test_rbireps.ext(exts.object)
+ g.test_objs << test_rbobj
+ dep_list = gems.tsort_dependencies g.test_dependencies, gem_table
file test_rbobj => g.test_rbireps
- file g.test_rbireps => [g.test_rbfiles].flatten + [g.build.mrbcfile, __FILE__] do |t|
+ file g.test_rbireps => [g.test_rbfiles].flatten + [File.join(g.dir, 'mrbgem.rake'), g.build.mrbcfile, __FILE__, "#{MRUBY_ROOT}/tasks/mrbgem_spec.rake"] do |t|
open(t.name, 'w') do |f|
g.print_gem_test_header(f)
test_preload = g.test_preload and [g.dir, MRUBY_ROOT].map {|dir|
@@ -33,22 +30,27 @@ MRuby.each_target do
g.build.mrbc.run f, rbfile, "gem_test_irep_#{g.funcname}_#{i}"
end
f.puts %Q[void mrb_#{g.funcname}_gem_test(mrb_state *mrb);] unless g.test_objs.empty?
+ dep_list.each do |d|
+ f.puts %Q[void GENERATED_TMP_mrb_#{d.funcname}_gem_init(mrb_state *mrb);]
+ f.puts %Q[void GENERATED_TMP_mrb_#{d.funcname}_gem_final(mrb_state *mrb);]
+ end
+ f.puts %Q[void mrb_init_test_driver(mrb_state *mrb, mrb_bool verbose);]
+ f.puts %Q[void mrb_t_pass_result(mrb_state *dst, mrb_state *src);]
f.puts %Q[void GENERATED_TMP_mrb_#{g.funcname}_gem_test(mrb_state *mrb) {]
unless g.test_rbfiles.empty?
f.puts %Q[ mrb_state *mrb2;]
- if g.test_args.empty?
- f.puts %Q[ mrb_value val1, val2, val3, ary1, ary2;]
- else
- f.puts %Q[ mrb_value val1, val2, val3, ary1, ary2, test_args_hash;]
+ unless g.test_args.empty?
+ f.puts %Q[ mrb_value test_args_hash;]
end
f.puts %Q[ int ai;]
g.test_rbfiles.count.times do |i|
f.puts %Q[ ai = mrb_gc_arena_save(mrb);]
- f.puts %Q[ mrb2 = mrb_open();]
- f.puts %Q[ val3 = mrb_gv_get(mrb, mrb_intern_lit(mrb, "$mrbtest_verbose"));]
- f.puts %Q[ if (mrb_test(val3)) {]
- f.puts %Q[ mrb_gv_set(mrb2, mrb_intern_lit(mrb2, "$mrbtest_verbose"), val3);]
- f.puts %Q[ }]
+ f.puts %Q[ mrb2 = mrb_open_core(mrb_default_allocf, NULL);]
+ dep_list.each do |d|
+ f.puts %Q[ GENERATED_TMP_mrb_#{d.funcname}_gem_init(mrb2);]
+ f.puts %Q[ mrb_state_atexit(mrb2, GENERATED_TMP_mrb_#{d.funcname}_gem_final);]
+ end
+ f.puts %Q[ mrb_init_test_driver(mrb2, mrb_test(mrb_gv_get(mrb, mrb_intern_lit(mrb, "$mrbtest_verbose"))));]
if test_preload.nil?
f.puts %Q[ mrb_load_irep(mrb2, mrbtest_assert_irep);]
else
@@ -70,33 +72,12 @@ MRuby.each_target do
f.puts %Q[ mrb_const_set(mrb2, mrb_obj_value(mrb2->object_class), mrb_intern_lit(mrb2, "TEST_ARGS"), test_args_hash); ]
end
- f.puts %Q[ mrb_#{g.funcname}_gem_test(mrb2);] unless g.test_objs.empty?
+ f.puts %Q[ mrb_#{g.funcname}_gem_test(mrb2);] if g.custom_test_init?
f.puts %Q[ mrb_load_irep(mrb2, gem_test_irep_#{g.funcname}_#{i});]
- f.puts %Q[ if (mrb2->exc) {]
- f.puts %Q[ mrb_print_error(mrb2);]
- f.puts %Q[ exit(EXIT_FAILURE);]
- f.puts %Q[ }]
f.puts %Q[ ]
- %w(ok_test ko_test kill_test).each do |vname|
- f.puts %Q[ val2 = mrb_gv_get(mrb2, mrb_intern_lit(mrb2, "$#{vname}"));]
- f.puts %Q[ if (mrb_fixnum_p(val2)) {]
- f.puts %Q[ val1 = mrb_gv_get(mrb, mrb_intern_lit(mrb, "$#{vname}"));]
- f.puts %Q[ mrb_gv_set(mrb, mrb_intern_lit(mrb, "$#{vname}"), mrb_fixnum_value(mrb_fixnum(val1) + mrb_fixnum(val2)));]
- f.puts %Q[ }\n]
- end
-
- f.puts %Q[ ary2 = mrb_gv_get(mrb2, mrb_intern_lit(mrb2, "$asserts"));]
- f.puts %Q[ if (mrb_test(ary2)) {]
- f.puts %Q[ ary1 = mrb_gv_get(mrb, mrb_intern_lit(mrb, "$asserts"));]
- f.puts %Q[ val2 = mrb_ary_shift(mrb2, ary2);]
- f.puts %Q[ ]
- f.puts %Q[ while (mrb_test(val2)) {]
- f.puts %Q[ mrb_ary_push(mrb, ary1, mrb_str_new(mrb, RSTRING_PTR(val2), RSTRING_LEN(val2)));]
- f.puts %Q[ val2 = mrb_ary_shift(mrb2, ary2);]
- f.puts %Q[ }]
- f.puts %Q[ }]
+ f.puts %Q[ mrb_t_pass_result(mrb, mrb2);]
f.puts %Q[ mrb_close(mrb2);]
f.puts %Q[ mrb_gc_arena_restore(mrb, ai);]
end
@@ -104,44 +85,5 @@ MRuby.each_target do
f.puts %Q[}]
end
end
-
- end
-
- no_mrb_open_test = "#{build_dir}/test/no_mrb_open_test"
- no_mrb_open_test_rbfiles = no_mrb_open_test_gem.reduce([]) { |res, v|
- res += v.test_rbfiles
- }
- if no_mrb_open_test_rbfiles.empty?
- no_mrb_open_test_rbfiles << "#{MRUBY_ROOT}/test/no_mrb_open_test_dummy.rb"
- end
-
- no_mrb_open_test_lib = no_mrb_open_test.ext(exts.object)
- file no_mrb_open_test_lib => "#{no_mrb_open_test}.c"
- file "#{no_mrb_open_test}.c" => no_mrb_open_test_rbfiles + [MRUBY_CONFIG, __FILE__] do |t|
- open(t.name, 'w') do |f|
- f.puts %Q[/*]
- f.puts %Q[ * This file contains a test code for following gems:]
- no_mrb_open_test_gem.each { |g| f.puts %Q[ * #{g.name}] }
- 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 %Q[\#include "mruby.h"]
- f.puts %Q[\#include "mruby/irep.h"]
-
- f.puts %Q[]
-
- mrbc.run f, no_mrb_open_test_rbfiles, "no_mrb_open_gem_test_irep"
-
- f.puts %Q[]
-
- f.puts %Q[void no_mrb_open_mrbgem_test(mrb_state *mrb) {]
- f.puts %Q[ mrb_load_irep(mrb, no_mrb_open_gem_test_irep);]
- f.puts %Q[}]
- end
end
end
diff --git a/test/assert.rb b/test/assert.rb
index a4ee00299..72e4d3b37 100644
--- a/test/assert.rb
+++ b/test/assert.rb
@@ -21,7 +21,7 @@ end
##
# Create the assertion in a readable way
-def assertion_string(err, str, iso=nil, e=nil)
+def assertion_string(err, str, iso=nil, e=nil, bt=nil)
msg = "#{err}#{str}"
msg += " [#{iso}]" if iso && iso != ''
msg += " => #{e.message}" if e
@@ -31,6 +31,7 @@ def assertion_string(err, str, iso=nil, e=nil)
msg += "\n - Assertion[#{idx}] Failed: #{str}\n#{diff}"
end
end
+ msg += "\nbacktrace:\n\t#{bt.join("\n\t")}" if bt
msg
end
@@ -56,11 +57,12 @@ def assert(str = 'Assertion failed', iso = '')
t_print('.')
end
rescue Exception => e
+ bt = e.backtrace if $mrbtest_verbose
if e.class.to_s == 'MRubyTestSkip'
$asserts.push "Skip: #{str} #{iso} #{e.cause}"
t_print('?')
else
- $asserts.push(assertion_string("#{e.class}: ", str, iso, e))
+ $asserts.push(assertion_string("#{e.class}: ", str, iso, e, bt))
$kill_test += 1
t_print('X')
end
diff --git a/test/driver.c b/test/driver.c
index 7fd8ef720..66d64d3de 100644
--- a/test/driver.c
+++ b/test/driver.c
@@ -16,6 +16,7 @@
#include "mruby/compile.h"
#include "mruby/string.h"
#include "mruby/variable.h"
+#include "mruby/array.h"
void
mrb_init_mrbtest(mrb_state *);
@@ -81,13 +82,68 @@ mrb_t_printstr(mrb_state *mrb, mrb_value self)
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;
- struct RClass *krn;
- struct RClass *mrbtest;
int ret;
+ mrb_bool verbose = FALSE;
print_hint();
@@ -100,18 +156,10 @@ main(int argc, char **argv)
if (argc == 2 && argv[1][0] == '-' && argv[1][1] == 'v') {
printf("verbose mode: enable\n\n");
- mrb_gv_set(mrb, mrb_intern_lit(mrb, "$mrbtest_verbose"), mrb_true_value());
+ verbose = TRUE;
}
- 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));
-
+ mrb_init_test_driver(mrb, verbose);
mrb_init_mrbtest(mrb);
ret = eval_test(mrb);
mrb_close(mrb);
diff --git a/test/init_mrbtest.c b/test/init_mrbtest.c
index 3ce42f661..2a32f4930 100644
--- a/test/init_mrbtest.c
+++ b/test/init_mrbtest.c
@@ -1,23 +1,36 @@
#include <stdlib.h>
#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);
- mrb_load_irep(mrb, mrbtest_irep);
+
+ core_test = mrb_open_core(mrb_default_allocf, NULL);
+ 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
index c28cf3577..b9616fe9d 100644
--- a/test/mrbtest.rake
+++ b/test/mrbtest.rake
@@ -12,11 +12,13 @@ MRuby.each_target do
ass_lib = ass_c.ext(exts.object)
mrbtest_lib = libfile("#{current_build_dir}/mrbtest")
- gem_test_files = gems.select { |g| g.run_test_in_other_mrb_state? }.map { |g| g.test_rbireps.ext(exts.object) }
- file mrbtest_lib => [mlib, ass_lib, gems.map(&:test_objs), gem_test_files].flatten do |t|
+ 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
- file mrbtest_lib => "#{build_dir}/test/no_mrb_open_test.c".ext(exts.object)
unless build_mrbtest_lib_only?
driver_obj = objfile("#{current_build_dir}/driver")
@@ -55,16 +57,12 @@ MRuby.each_target do
f.puts IO.read(init)
mrbc.run f, mrbs, 'mrbtest_irep'
gems.each do |g|
- next unless g.run_test_in_other_mrb_state?
f.puts %Q[void GENERATED_TMP_mrb_#{g.funcname}_gem_test(mrb_state *mrb);]
end
- f.puts %Q[void no_mrb_open_mrbgem_test(mrb_state *mrb);]
f.puts %Q[void mrbgemtest_init(mrb_state* mrb) {]
gems.each do |g|
- next unless g.run_test_in_other_mrb_state?
f.puts %Q[ GENERATED_TMP_mrb_#{g.funcname}_gem_test(mrb);]
end
- f.puts %Q[ no_mrb_open_mrbgem_test(mrb);]
f.puts %Q[}]
end
end
diff --git a/test/no_mrb_open_test_dummy.rb b/test/no_mrb_open_test_dummy.rb
deleted file mode 100644
index 5181c0a45..000000000
--- a/test/no_mrb_open_test_dummy.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-#dummy
-
diff --git a/test/t/module.rb b/test/t/module.rb
index 5ac794330..2e19f350f 100644
--- a/test/t/module.rb
+++ b/test/t/module.rb
@@ -522,3 +522,13 @@ assert('clone Module') do
B.new.foo
end
+
+assert('Module#module_function') do
+ module M
+ def modfunc; end
+ module_function :modfunc
+ end
+
+ assert_true M.respond_to?(:modfunc)
+end
+