From 6626fbc5006d662f8fc69a51660ae7c1e998a1f0 Mon Sep 17 00:00:00 2001 From: KOBAYASHI Shuji Date: Fri, 12 Apr 2019 22:27:07 +0900 Subject: Refine `assert_float` Avoid arithmetic operations when `exp` and/or `act` are infinity or NaN. --- test/assert.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'test/assert.rb') diff --git a/test/assert.rb b/test/assert.rb index c57b04c12..e0fac4d90 100644 --- a/test/assert.rb +++ b/test/assert.rb @@ -149,11 +149,11 @@ end # Fails unless +exp+ is equal to +act+ in terms of a Float def assert_float(exp, act, msg = nil) e, a = exp.to_f, act.to_f - if (e.infinite? || a.infinite?) && e != a || + if e.finite? && a.finite? && (n = (e - a).abs) > Mrbtest::FLOAT_TOLERANCE + flunk(msg, " Expected |#{exp} - #{act}| (#{n}) to be <= #{Mrbtest::FLOAT_TOLERANCE}.") + elsif (e.infinite? || a.infinite?) && e != a || e.nan? && !a.nan? || !e.nan? && a.nan? flunk(msg, " Expected #{act} to be #{exp}.") - elsif (n = (e - a).abs) > Mrbtest::FLOAT_TOLERANCE - flunk(msg, " Expected |#{exp} - #{act}| (#{n}) to be <= #{Mrbtest::FLOAT_TOLERANCE}.") else pass end -- cgit v1.2.3 From 716a99b069461b11c2b46099119f8578cd2c8f3f Mon Sep 17 00:00:00 2001 From: KOBAYASHI Shuji Date: Wed, 3 Apr 2019 21:38:47 +0900 Subject: Add `assert_match` and `assert_not_match` --- mrbgems/mruby-test/driver.c | 146 ++++++++++++++++++++++++++++++++++++++++++++ test/assert.rb | 33 ++++++++++ test/t/module.rb | 7 +-- 3 files changed, 181 insertions(+), 5 deletions(-) (limited to 'test/assert.rb') diff --git a/mrbgems/mruby-test/driver.c b/mrbgems/mruby-test/driver.c index fd180b1bb..9e3dbea9d 100644 --- a/mrbgems/mruby-test/driver.c +++ b/mrbgems/mruby-test/driver.c @@ -62,6 +62,151 @@ t_print(mrb_state *mrb, mrb_value self) return mrb_nil_value(); } +#define UNESCAPE(p, endp) ((p) != (endp) && *(p) == '\\' ? (p)+1 : (p)) +#define CHAR_CMP(c1, c2) ((unsigned char)(c1) - (unsigned char)(c2)) + +static const char * +str_match_bracket(const char *p, const char *pat_end, + const char *s, const char *str_end) +{ + mrb_bool ok = FALSE, negated = FALSE; + + if (p == pat_end) return NULL; + if (*p == '!' || *p == '^') { + negated = TRUE; + ++p; + } + + while (*p != ']') { + const char *t1 = p; + if ((t1 = UNESCAPE(t1, pat_end)) == pat_end) return NULL; + if ((p = t1 + 1) == pat_end) return NULL; + if (p[0] == '-' && p[1] != ']') { + const char *t2 = p + 1; + if ((t2 = UNESCAPE(t2, pat_end)) == pat_end) return NULL; + p = t2 + 1; + if (!ok && CHAR_CMP(*t1, *s) <= 0 && CHAR_CMP(*s, *t2) <= 0) ok = TRUE; + } + else { + if (!ok && CHAR_CMP(*t1, *s) == 0) ok = TRUE; + } + } + + return ok == negated ? NULL : p + 1; +} + +static mrb_bool +str_match_no_brace_p(const char *pat, mrb_int pat_len, + const char *str, mrb_int str_len) +{ + const char *p = pat, *s = str; + const char *pat_end = pat + pat_len, *str_end = str + str_len; + const char *p_tmp = NULL, *s_tmp = NULL; + + for (;;) { + if (p == pat_end) return s == str_end; + switch (*p) { + case '*': + do { ++p; } while (p != pat_end && *p == '*'); + if (UNESCAPE(p, pat_end) == pat_end) return TRUE; + if (s == str_end) return FALSE; + p_tmp = p; + s_tmp = s; + continue; + case '?': + if (s == str_end) return FALSE; + ++p; + ++s; + continue; + case '[': { + const char *t; + if (s == str_end) return FALSE; + if ((t = str_match_bracket(p+1, pat_end, s, str_end))) { + p = t; + ++s; + continue; + } + goto L_failed; + } + } + + /* ordinary */ + p = UNESCAPE(p, pat_end); + if (s == str_end) return p == pat_end; + if (p == pat_end) goto L_failed; + if (*p++ != *s++) goto L_failed; + continue; + + L_failed: + if (p_tmp && s_tmp) { + /* try next '*' position */ + p = p_tmp; + s = ++s_tmp; + continue; + } + + return FALSE; + } +} + +#define COPY_AND_INC(dst, src, len) \ + do { memcpy(dst, src, len); dst += len; } while (0) + +static mrb_bool +str_match_p(mrb_state *mrb, + const char *pat, mrb_int pat_len, + const char *str, mrb_int str_len) +{ + const char *p = pat, *pat_end = pat + pat_len; + const char *lbrace = NULL, *rbrace = NULL; + int nest = 0; + mrb_bool ret = FALSE; + + for (; p != pat_end; ++p) { + if (*p == '{' && nest++ == 0) lbrace = p; + else if (*p == '}' && lbrace && --nest == 0) { rbrace = p; break; } + else if (*p == '\\' && ++p == pat_end) break; + } + + if (lbrace && rbrace) { + /* expand brace */ + char *ex_pat = (char *)mrb_malloc(mrb, pat_len-2); /* expanded pattern */ + char *ex_p = ex_pat; + + COPY_AND_INC(ex_p, pat, lbrace-pat); + p = lbrace; + while (p < rbrace) { + char *orig_ex_p = ex_p; + const char *t = ++p; + for (nest = 0; p < rbrace && !(*p == ',' && nest == 0); ++p) { + if (*p == '{') ++nest; + else if (*p == '}') --nest; + else if (*p == '\\' && ++p == rbrace) break; + } + COPY_AND_INC(ex_p, t, p-t); + COPY_AND_INC(ex_p, rbrace+1, pat_end-rbrace-1); + if ((ret = str_match_p(mrb, ex_pat, ex_p-ex_pat, str, str_len))) break; + ex_p = orig_ex_p; + } + mrb_free(mrb, ex_pat); + } + else if (!lbrace && !rbrace) { + ret = str_match_no_brace_p(pat, pat_len, str, str_len); + } + + return ret; +} + +static mrb_value +m_str_match_p(mrb_state *mrb, mrb_value self) +{ + const char *pat, *str; + mrb_int pat_len, str_len; + + mrb_get_args(mrb, "ss", &pat, &pat_len, &str, &str_len); + return mrb_bool_value(str_match_p(mrb, pat, pat_len, str, str_len)); +} + void mrb_init_test_driver(mrb_state *mrb, mrb_bool verbose) { @@ -69,6 +214,7 @@ mrb_init_test_driver(mrb_state *mrb, mrb_bool verbose) krn = mrb->kernel_module; mrb_define_method(mrb, krn, "t_print", t_print, MRB_ARGS_ANY()); + mrb_define_method(mrb, krn, "_str_match?", m_str_match_p, MRB_ARGS_REQ(2)); mrbtest = mrb_define_module(mrb, "Mrbtest"); diff --git a/test/assert.rb b/test/assert.rb index c57b04c12..4b01bd450 100644 --- a/test/assert.rb +++ b/test/assert.rb @@ -136,6 +136,39 @@ def _assert_include(affirmed, collection, obj, msg = nil) assert_true(ret, msg, diff) end +## +# Fail unless +str+ matches against +pattern+. +# +# +pattern+ is interpreted as pattern for File.fnmatch?. It may contain the +# following metacharacters: +# +# * :: +# Matches any string. +# +# ? :: +# Matches any one character. +# +# [_SET_], [^_SET_] ([!_SET_]) :: +# Matches any one character in _SET_. Behaves like character sets in +# Regexp, including set negation ([^a-z]). +# +# {_A_,_B_} :: +# Matches pattern _A_ or pattern _B_. +# +# \ :: +# Escapes the next character. +def assert_match(*args); _assert_match(true, *args) end +def assert_not_match(*args); _assert_match(false, *args) end +def _assert_match(affirmed, pattern, str, msg = nil) + receiver, *args = RUBY_ENGINE == "mruby" ? + [self, :_str_match?, pattern, str] : + [File, :fnmatch?, pattern, str, File::FNM_EXTGLOB|File::FNM_DOTMATCH] + unless ret = !receiver.__send__(*args) == !affirmed + diff = " Expected #{pattern.inspect} to #{'not ' unless affirmed}match #{str.inspect}." + end + assert_true(ret, msg, diff) +end + ## # Fails unless +obj+ is a kind of +cls+. def assert_kind_of(cls, obj, msg = nil) diff --git a/test/t/module.rb b/test/t/module.rb index ec36855e8..1694ef577 100644 --- a/test/t/module.rb +++ b/test/t/module.rb @@ -640,11 +640,8 @@ assert('Module#to_s') do assert_equal 'SetOuter', SetOuter.to_s assert_equal 'SetOuter::SetInner', SetOuter::SetInner.to_s - mod = Module.new - cls = Class.new - - assert_equal "#", Module.new.to_s + assert_match "#", Class.new.to_s end assert('Module#inspect') do -- cgit v1.2.3 From 0debf154ee9aa4c4f9aa0190a54a810801c3d31d Mon Sep 17 00:00:00 2001 From: KOBAYASHI Shuji Date: Mon, 22 Apr 2019 17:35:49 +0900 Subject: Add `assert_predicate` and `assert_operator` --- test/assert.rb | 20 ++++++++++++++++++++ test/t/float.rb | 20 ++++++++++---------- 2 files changed, 30 insertions(+), 10 deletions(-) (limited to 'test/assert.rb') diff --git a/test/assert.rb b/test/assert.rb index e0fac4d90..385de49bd 100644 --- a/test/assert.rb +++ b/test/assert.rb @@ -1,3 +1,4 @@ +$undefined = Object.new $ok_test = 0 $ko_test = 0 $kill_test = 0 @@ -136,6 +137,25 @@ def _assert_include(affirmed, collection, obj, msg = nil) assert_true(ret, msg, diff) end +def assert_predicate(*args); _assert_predicate(true, *args) end +def assert_not_predicate(*args); _assert_predicate(false, *args) end +def _assert_predicate(affirmed, obj, op, msg = nil) + unless ret = obj.__send__(op) == affirmed + diff = " Expected #{obj.inspect} to #{'not ' unless affirmed}be #{op}." + end + assert_true(ret, msg, diff) +end + +def assert_operator(*args); _assert_operator(true, *args) end +def assert_not_operator(*args); _assert_operator(false, *args) end +def _assert_operator(affirmed, obj1, op, obj2 = $undefined, msg = nil) + return _assert_predicate(affirmed, obj1, op, msg) if obj2 == $undefined + unless ret = obj1.__send__(op, obj2) == affirmed + diff = " Expected #{obj1.inspect} to #{'not ' unless affirmed}be #{op} #{obj2.inspect}." + end + assert_true(ret, msg, diff) +end + ## # Fails unless +obj+ is a kind of +cls+. def assert_kind_of(cls, obj, msg = nil) diff --git a/test/t/float.rb b/test/t/float.rb index 4e9d347b8..b4eb0bfd6 100644 --- a/test/t/float.rb +++ b/test/t/float.rb @@ -82,8 +82,8 @@ assert('Float#ceil', '15.2.9.3.8') do end assert('Float#finite?', '15.2.9.3.9') do - assert_true 3.123456789.finite? - assert_false (1.0 / 0.0).finite? + assert_predicate 3.123456789, :finite? + assert_not_predicate 1.0 / 0.0, :finite? end assert('Float#floor', '15.2.9.3.10') do @@ -139,7 +139,7 @@ assert('Float#round', '15.2.9.3.12') do nan = 0.0/0.0 assert_raise(FloatDomainError){ nan.round } assert_raise(FloatDomainError){ nan.round(-1) } - assert_true(nan.round(1).nan?) + assert_predicate(nan.round(1), :nan?) end assert('Float#to_f', '15.2.9.3.13') do @@ -178,10 +178,10 @@ assert('Float#divmod') do end assert('Float#nan?') do - assert_true (0.0/0.0).nan? - assert_false 0.0.nan? - assert_false (1.0/0.0).nan? - assert_false (-1.0/0.0).nan? + assert_predicate 0.0/0.0, :nan? + assert_not_predicate 0.0, :nan? + assert_not_predicate 1.0/0.0, :nan? + assert_not_predicate -1.0/0.0, :nan? end assert('Float#<<') do @@ -240,9 +240,9 @@ assert('Float#to_s') do end assert('Float#eql?') do - assert_true(5.0.eql?(5.0)) - assert_false(5.0.eql?(5)) - assert_false(5.0.eql?("5.0")) + assert_operator(5.0, :eql?, 5.0) + assert_not_operator(5.0, :eql?, 5) + assert_not_operator(5.0, :eql?, "5.0") end end # const_defined?(:Float) -- cgit v1.2.3 From 1fb635ac03d3948898623126a8b3d7705e9cdb0f Mon Sep 17 00:00:00 2001 From: KOBAYASHI Shuji Date: Fri, 26 Apr 2019 21:36:29 +0900 Subject: Add `assert_raise_with_message` and `assert_raise_with_message_pattern` --- test/assert.rb | 36 ++++++++++++++++++++++++++++++------ test/t/kernel.rb | 10 ++++------ test/t/module.rb | 24 +++++++++++++++++------- 3 files changed, 51 insertions(+), 19 deletions(-) (limited to 'test/assert.rb') diff --git a/test/assert.rb b/test/assert.rb index 121bd0a8e..da313bf6a 100644 --- a/test/assert.rb +++ b/test/assert.rb @@ -6,13 +6,17 @@ $skip_test = 0 $asserts = [] $test_start = Time.now if Object.const_defined?(:Time) +# For bintest on Ruby unless RUBY_ENGINE == "mruby" - # For bintest on Ruby def t_print(*args) print(*args) $stdout.flush nil end + + def _str_match?(pattern, str) + File.fnmatch?(pattern, str, File::FNM_EXTGLOB|File::FNM_DOTMATCH) + end end ## @@ -180,10 +184,7 @@ end def assert_match(*args); _assert_match(true, *args) end def assert_not_match(*args); _assert_match(false, *args) end def _assert_match(affirmed, pattern, str, msg = nil) - receiver, *args = RUBY_ENGINE == "mruby" ? - [self, :_str_match?, pattern, str] : - [File, :fnmatch?, pattern, str, File::FNM_EXTGLOB|File::FNM_DOTMATCH] - unless ret = !receiver.__send__(*args) == !affirmed + unless ret = _str_match?(pattern, str) == affirmed diff = " Expected #{pattern.inspect} to #{'not ' unless affirmed}match #{str.inspect}." end assert_true(ret, msg, diff) @@ -217,8 +218,9 @@ def assert_raise(*exc) exc = exc.empty? ? StandardError : exc.size == 1 ? exc[0] : exc begin yield - rescue *exc + rescue *exc => e pass + e rescue Exception => e diff = " #{exc} exception expected, not\n" \ " Class: <#{e.class}>\n" \ @@ -243,6 +245,28 @@ def assert_nothing_raised(msg = nil) end end +def assert_raise_with_message(*args, &block) + _assert_raise_with_message(:plain, *args, &block) +end +def assert_raise_with_message_pattern(*args, &block) + _assert_raise_with_message(:pattern, *args, &block) +end +def _assert_raise_with_message(type, exc, exp_msg, msg = nil, &block) + e = msg ? assert_raise(exc, msg, &block) : assert_raise(exc, &block) + e ? ($mrbtest_assert_idx -= 1) : (return e) + + err_msg = e.message + unless ret = type == :pattern ? _str_match?(exp_msg, err_msg) : exp_msg == err_msg + diff = " Expected Exception(#{exc}) was raised, but the message doesn't match.\n" + if type == :pattern + diff += " Expected #{exp_msg.inspect} to match #{err_msg.inspect}." + else + diff += assertion_diff(exp_msg, err_msg) + end + end + assert_true(ret, msg, diff) +end + def pass assert_true(true) end diff --git a/test/t/kernel.rb b/test/t/kernel.rb index bf7dbe94c..7fc8cd2e7 100644 --- a/test/t/kernel.rb +++ b/test/t/kernel.rb @@ -346,17 +346,15 @@ assert('Kernel#method_missing', '15.3.1.3.30') do end end no_super_test = NoSuperMethodTestClass.new - begin + msg = "undefined method 'no_super_method_named_this'" + assert_raise_with_message(NoMethodError, msg) do no_super_test.no_super_method_named_this - rescue NoMethodError => e - assert_equal "undefined method 'no_super_method_named_this'", e.message end a = String.new - begin + msg = "undefined method 'no_method_named_this'" + assert_raise_with_message(NoMethodError, msg) do a.no_method_named_this - rescue NoMethodError => e - assert_equal "undefined method 'no_method_named_this'", e.message end end diff --git a/test/t/module.rb b/test/t/module.rb index 09613e1bc..5c659f149 100644 --- a/test/t/module.rb +++ b/test/t/module.rb @@ -21,6 +21,14 @@ def labeled_class(name, supklass = Object, &block) end end +def assert_uninitialized_const(&block) + assert_raise_with_message_pattern(NameError, "uninitialized constant *", &block) +end + +def assert_wrong_const_name(&block) + assert_raise_with_message_pattern(NameError, "wrong constant name *", &block) +end + assert('Module', '15.2.2') do assert_equal Class, Module.class end @@ -221,7 +229,7 @@ assert('Module#const_defined?', '15.2.2.4.20') do assert_true Test4ConstDefined.const_defined?(:Const4Test4ConstDefined) assert_false Test4ConstDefined.const_defined?(:NotExisting) - assert_raise(NameError){ Test4ConstDefined.const_defined?(:wrong_name) } + assert_wrong_const_name{ Test4ConstDefined.const_defined?(:wrong_name) } end assert('Module#const_get', '15.2.2.4.21') do @@ -234,9 +242,9 @@ assert('Module#const_get', '15.2.2.4.21') do assert_equal 42, Object.const_get("Test4ConstGet::Const4Test4ConstGet") assert_raise(TypeError){ Test4ConstGet.const_get(123) } - assert_raise(NameError){ Test4ConstGet.const_get(:I_DO_NOT_EXIST) } - assert_raise(NameError){ Test4ConstGet.const_get("I_DO_NOT_EXIST::ME_NEITHER") } - assert_raise(NameError){ Test4ConstGet.const_get(:wrong_name) } + assert_uninitialized_const{ Test4ConstGet.const_get(:I_DO_NOT_EXIST) } + assert_uninitialized_const{ Test4ConstGet.const_get("I_DO_NOT_EXIST::ME_NEITHER") } + assert_wrong_const_name{ Test4ConstGet.const_get(:wrong_name) } end assert('Module#const_set', '15.2.2.4.23') do @@ -247,7 +255,7 @@ assert('Module#const_set', '15.2.2.4.23') do assert_equal 23, Test4ConstSet.const_set(:Const4Test4ConstSet, 23) assert_equal 23, Test4ConstSet.const_get(:Const4Test4ConstSet) ["", "wrongNAME", "Wrong-Name"].each do |n| - assert_raise(NameError) { Test4ConstSet.const_set(n, 1) } + assert_wrong_const_name { Test4ConstSet.const_set(n, 1) } end end @@ -258,9 +266,11 @@ assert('Module#remove_const', '15.2.2.4.40') do assert_equal 23, Test4RemoveConst.remove_const(:ExistingConst) assert_false Test4RemoveConst.const_defined?(:ExistingConst) - assert_raise(NameError) { Test4RemoveConst.remove_const(:NonExistingConst) } + assert_raise_with_message_pattern(NameError, "constant * not defined") do + Test4RemoveConst.remove_const(:NonExistingConst) + end %i[x X!].each do |n| - assert_raise(NameError) { Test4RemoveConst.remove_const(n) } + assert_wrong_const_name { Test4RemoveConst.remove_const(n) } end end -- cgit v1.2.3 From 4bf6b8c136ecd6b4bf78e9a66c21943f3f8ab506 Mon Sep 17 00:00:00 2001 From: KOBAYASHI Shuji Date: Mon, 29 Apr 2019 11:34:41 +0900 Subject: Refine the default values of `flunk` The default message for the second argument should be set to the first argument because only one argument is normally specified. --- test/assert.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test/assert.rb') diff --git a/test/assert.rb b/test/assert.rb index 121bd0a8e..a9bbc9a05 100644 --- a/test/assert.rb +++ b/test/assert.rb @@ -247,7 +247,7 @@ def pass assert_true(true) end -def flunk(msg = nil, diff = "Epic Fail!") +def flunk(msg = "Epic Fail!", diff = "") assert_true(false, msg, diff) end -- cgit v1.2.3 From a97a455c031c77f01eaae85ce683e9c1346eb8c9 Mon Sep 17 00:00:00 2001 From: KOBAYASHI Shuji Date: Mon, 27 May 2019 20:51:47 +0900 Subject: Use `$undefined.equal?(obj2)` instead of `obj2 == $undefined` in `assert.rb` In case `obj2.==` is broken. --- test/assert.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test/assert.rb') diff --git a/test/assert.rb b/test/assert.rb index a9bbc9a05..5e2e104b3 100644 --- a/test/assert.rb +++ b/test/assert.rb @@ -149,7 +149,7 @@ end def assert_operator(*args); _assert_operator(true, *args) end def assert_not_operator(*args); _assert_operator(false, *args) end def _assert_operator(affirmed, obj1, op, obj2 = $undefined, msg = nil) - return _assert_predicate(affirmed, obj1, op, msg) if obj2 == $undefined + return _assert_predicate(affirmed, obj1, op, msg) if $undefined.equal?(obj2) unless ret = obj1.__send__(op, obj2) == affirmed diff = " Expected #{obj1.inspect} to #{'not ' unless affirmed}be #{op} #{obj2.inspect}." end -- cgit v1.2.3 From 5f9034e4283ccaa99c929a36e2cfbb465e8b31b4 Mon Sep 17 00:00:00 2001 From: dearblue Date: Thu, 6 Jun 2019 22:24:58 +0900 Subject: Nested `assert` for mrbtest When nesting `assert` used in test, it is indented and displayed. Assertion numbers are concatenated by `"-"` at this time. The purpose is to match the apparent numbers when failing with `assert_mruby` which is defined by `mrbgems/mruby-bin-mruby/bintest/mruby.rb` for example. Child assertions "skip" and "info" are reported as parent assertions "info" and `$ok_test += 1`. The child assertions "ko" and "crash" are reported as the parent assertion "ko" and `$ko_test += 1`. When child assertions are mixed, "ko" takes precedence. Incompatibility: - `$mrbtest_assert_idx` takes `nil` or an integer array object. So far it was `nil` or an integer. - `$asserts` points to the top of the internal stack in the `assert`. - `$mrbtest_assert` points to the top of the internal stack in `assert`. --- test/assert.rb | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 82 insertions(+), 11 deletions(-) (limited to 'test/assert.rb') diff --git a/test/assert.rb b/test/assert.rb index 5e2e104b3..c493cbbc0 100644 --- a/test/assert.rb +++ b/test/assert.rb @@ -15,6 +15,36 @@ unless RUBY_ENGINE == "mruby" end end +class Array + def _assertion_join + join("-") + end +end + +class String + def _assertion_indent(indent) + indent = indent.to_s + off = 0 + str = self + while nl = index("\n", off) + nl += 1 + nl += 1 while slice(nl) == "\n" + break if nl >= size + str = indent.dup if off == 0 + str += slice(off, nl - off) + indent + off = nl + end + + if off == 0 + str = indent + self + else + str += slice(off..-1) + end + + str + end +end + ## # Create the assertion in a readable way def assertion_string(err, str, iso=nil, e=nil, bt=nil) @@ -22,14 +52,14 @@ def assertion_string(err, str, iso=nil, e=nil, bt=nil) msg += " [#{iso}]" if iso && !iso.empty? msg += " => #{e}" if e && !e.to_s.empty? msg += " (#{GEMNAME == 'mruby-test' ? 'core' : "mrbgems: #{GEMNAME}"})" - if $mrbtest_assert && $mrbtest_assert.size > 0 + if $mrbtest_assert $mrbtest_assert.each do |idx, assert_msg, diff| msg += "\n - Assertion[#{idx}]" msg += " #{assert_msg}." if assert_msg && !assert_msg.empty? msg += "\n#{diff}" if diff && !diff.empty? end end - msg += "\nbacktrace:\n\t#{bt.join("\n\t")}" if bt + msg += "\nbacktrace:\n #{bt.join("\n ")}" if bt msg end @@ -44,13 +74,35 @@ end def assert(str = 'Assertion failed', iso = '') t_print(str, (iso != '' ? " [#{iso}]" : ''), ' : ') if $mrbtest_verbose begin + $mrbtest_child_noassert ||= [0] + $mrbtest_child_noassert << 0 + parent_asserts = $asserts + $asserts = [] + parent_mrbtest_assert = $mrbtest_assert $mrbtest_assert = [] - $mrbtest_assert_idx = 0 + + if $mrbtest_assert_idx && !$mrbtest_assert_idx.empty? + $mrbtest_assert_idx[-1] += 1 + $mrbtest_assert_idx << 0 + else + $mrbtest_assert_idx = [0] + class << $mrbtest_assert_idx + alias to_s _assertion_join + end + end + yield - if($mrbtest_assert.size > 0) - $asserts.push(assertion_string('Fail: ', str, iso)) - $ko_test += 1 - t_print('F') + if $mrbtest_assert.size > 0 + if $mrbtest_assert.size == $mrbtest_child_noassert[-1] + $asserts.push(assertion_string('Info: ', str, iso)) + $mrbtest_child_noassert[-2] += 1 + $ok_test += 1 + t_print('.') + else + $asserts.push(assertion_string('Fail: ', str, iso)) + $ko_test += 1 + t_print('F') + end else $ok_test += 1 t_print('.') @@ -58,6 +110,7 @@ def assert(str = 'Assertion failed', iso = '') rescue MRubyTestSkip => e $asserts.push(assertion_string('Skip: ', str, iso, e)) $skip_test += 1 + $mrbtest_child_noassert[-2] += 1 t_print('?') rescue Exception => e bt = e.backtrace if $mrbtest_verbose @@ -65,7 +118,25 @@ def assert(str = 'Assertion failed', iso = '') $kill_test += 1 t_print('X') ensure - $mrbtest_assert = nil + if $mrbtest_assert_idx.size > 1 + $asserts.each do |mesg| + idx = $mrbtest_assert_idx[0..-2]._assertion_join + mesg = mesg._assertion_indent(" ") + + # Give `mesg` as a `diff` argument to avoid adding extra periods. + parent_mrbtest_assert << [idx, nil, mesg] + end + else + parent_asserts.concat $asserts + end + $asserts = parent_asserts + + $mrbtest_assert = parent_mrbtest_assert + $mrbtest_assert_idx.pop + $mrbtest_assert_idx = nil if $mrbtest_assert_idx.empty? + $mrbtest_child_noassert.pop + + nil end t_print("\n") if $mrbtest_verbose end @@ -76,11 +147,11 @@ def assertion_diff(exp, act) end def assert_true(obj, msg = nil, diff = nil) - if $mrbtest_assert - $mrbtest_assert_idx += 1 + if $mrbtest_assert_idx && $mrbtest_assert_idx.size > 0 + $mrbtest_assert_idx[-1] += 1 unless obj == true diff ||= " Expected #{obj.inspect} to be true." - $mrbtest_assert.push([$mrbtest_assert_idx, msg, diff]) + $mrbtest_assert.push([$mrbtest_assert_idx.to_s, msg, diff]) end end obj -- cgit v1.2.3 From cd8fc9bcb81a8e9e7e76413f3132b0515c8bd218 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 29 Jul 2019 01:02:03 +0900 Subject: Resolved conflicts in #4320 --- mrbgems/mruby-test/driver.c | 1 + test/assert.rb | 20 +++++++++++++------- 2 files changed, 14 insertions(+), 7 deletions(-) (limited to 'test/assert.rb') diff --git a/mrbgems/mruby-test/driver.c b/mrbgems/mruby-test/driver.c index 602b76c79..b6c9fab35 100644 --- a/mrbgems/mruby-test/driver.c +++ b/mrbgems/mruby-test/driver.c @@ -258,6 +258,7 @@ mrb_t_pass_result(mrb_state *mrb_dst, mrb_state *mrb_src) TEST_COUNT_PASS(ok_test); TEST_COUNT_PASS(ko_test); TEST_COUNT_PASS(kill_test); + TEST_COUNT_PASS(warning_test); TEST_COUNT_PASS(skip_test); #undef TEST_COUNT_PASS diff --git a/test/assert.rb b/test/assert.rb index c493cbbc0..4641e6657 100644 --- a/test/assert.rb +++ b/test/assert.rb @@ -2,6 +2,7 @@ $undefined = Object.new $ok_test = 0 $ko_test = 0 $kill_test = 0 +$warning_test = 0 $skip_test = 0 $asserts = [] $test_start = Time.now if Object.const_defined?(:Time) @@ -103,6 +104,10 @@ def assert(str = 'Assertion failed', iso = '') $ko_test += 1 t_print('F') end + elsif $mrbtest_assert_idx == 0 + $asserts.push(assertion_string('Warn: ', str, iso, 'no assertion')) + $warning_test += 1 + t_print('W') else $ok_test += 1 t_print('.') @@ -332,17 +337,18 @@ def report t_print("#{msg}\n") end - $total_test = $ok_test + $ko_test + $kill_test + $skip_test - t_print("Total: #{$total_test}\n") + $total_test = $ok_test + $ko_test + $kill_test + $warning_test + $skip_test + t_print(" Total: #{$total_test}\n") - t_print(" OK: #{$ok_test}\n") - t_print(" KO: #{$ko_test}\n") - t_print("Crash: #{$kill_test}\n") - t_print(" Skip: #{$skip_test}\n") + t_print(" OK: #{$ok_test}\n") + t_print(" KO: #{$ko_test}\n") + t_print(" Crash: #{$kill_test}\n") + t_print("Warning: #{$warning_test}\n") + t_print(" Skip: #{$skip_test}\n") if Object.const_defined?(:Time) t_time = Time.now - $test_start - t_print(" Time: #{t_time.round(2)} seconds\n") + t_print(" Time: #{t_time.round(2)} seconds\n") end $ko_test == 0 && $kill_test == 0 -- cgit v1.2.3 From ff43b2b97c77812abbcbfe14da4582c6c209be9b Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 29 Jul 2019 01:25:58 +0900 Subject: Fixed a conflict between #4407 and #4540 --- test/assert.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test/assert.rb') diff --git a/test/assert.rb b/test/assert.rb index b2d5011ad..58ee4b913 100644 --- a/test/assert.rb +++ b/test/assert.rb @@ -329,7 +329,7 @@ def assert_raise_with_message_pattern(*args, &block) end def _assert_raise_with_message(type, exc, exp_msg, msg = nil, &block) e = msg ? assert_raise(exc, msg, &block) : assert_raise(exc, &block) - e ? ($mrbtest_assert_idx -= 1) : (return e) + e ? ($mrbtest_assert_idx[-1]-=1) : (return e) err_msg = e.message unless ret = type == :pattern ? _str_match?(exp_msg, err_msg) : exp_msg == err_msg -- cgit v1.2.3 From 5091d047c0b965c4860e8d47cb95f72687b37a7f Mon Sep 17 00:00:00 2001 From: KOBAYASHI Shuji Date: Mon, 29 Jul 2019 21:40:58 +0900 Subject: Fix "Warn if assertion is missing inside `assert`"; ref ff43b2b9 --- test/assert.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test/assert.rb') diff --git a/test/assert.rb b/test/assert.rb index 58ee4b913..a63e626cf 100644 --- a/test/assert.rb +++ b/test/assert.rb @@ -108,7 +108,7 @@ def assert(str = 'Assertion failed', iso = '') $ko_test += 1 t_print('F') end - elsif $mrbtest_assert_idx == 0 + elsif $mrbtest_assert_idx[-1] == 0 $asserts.push(assertion_string('Warn: ', str, iso, 'no assertion')) $warning_test += 1 t_print('W') -- cgit v1.2.3 From 44381f0a0c306a8c778f546926d3febfdf981b45 Mon Sep 17 00:00:00 2001 From: KOBAYASHI Shuji Date: Tue, 30 Jul 2019 12:46:24 +0900 Subject: Refine message to `skip` in nested `assert` - I think "Info" is used only to `skip`, so change to "Skip". - Changed the default value of `assert` and specify the argument explicitly at the caller of `assert` because it is unnatural "Assertion failed" is output even though the assertion doesn't fail. == Example: def assert_foo(exp, act) assert do assert_equal exp[0], act[0] assert_equal exp[1], act[1] end end def assert_bar(exp, act) assert do skip end end def assert_baz(exp, act) assert do assert_equal exp, act assert_bar exp, act end end assert 'test#skip_in_nested_assert' do assert_baz 1, 1 end === Before this patch: ?.. Info: test#skip_in_nested_assert (core) - Assertion[1] Info: Assertion failed (core) - Assertion[1-2] Skip: Assertion failed (core) Total: 3 OK: 2 KO: 0 Crash: 0 Warning: 0 Skip: 1 === After this patch: ??? Skip: test#skip_in_nested_assert (core) - Assertion[1] Skip: assert (core) - Assertion[1-2] Skip: assert (core) Total: 3 OK: 0 KO: 0 Crash: 0 Warning: 0 Skip: 3 --- mrbgems/mruby-bin-mruby/bintest/mruby.rb | 2 +- mrbgems/mruby-complex/test/complex.rb | 2 +- mrbgems/mruby-io/test/io.rb | 2 +- mrbgems/mruby-pack/test/pack.rb | 2 +- mrbgems/mruby-rational/test/rational.rb | 4 ++-- test/assert.rb | 8 ++++---- test/t/numeric.rb | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) (limited to 'test/assert.rb') diff --git a/mrbgems/mruby-bin-mruby/bintest/mruby.rb b/mrbgems/mruby-bin-mruby/bintest/mruby.rb index 5dbbc5592..e032ff79a 100644 --- a/mrbgems/mruby-bin-mruby/bintest/mruby.rb +++ b/mrbgems/mruby-bin-mruby/bintest/mruby.rb @@ -3,7 +3,7 @@ require 'open3' def assert_mruby(exp_out, exp_err, exp_success, args) out, err, stat = Open3.capture3(cmd("mruby"), *args) - assert do + assert "assert_mruby" do assert_operator(exp_out, :===, out, "standard output") assert_operator(exp_err, :===, err, "standard error") assert_equal(exp_success, stat.success?, "exit success?") diff --git a/mrbgems/mruby-complex/test/complex.rb b/mrbgems/mruby-complex/test/complex.rb index 5b7c3bfa4..4ae80515b 100644 --- a/mrbgems/mruby-complex/test/complex.rb +++ b/mrbgems/mruby-complex/test/complex.rb @@ -1,5 +1,5 @@ def assert_complex(real, exp) - assert do + assert "assert_complex" do assert_float real.real, exp.real assert_float real.imaginary, exp.imaginary end diff --git a/mrbgems/mruby-io/test/io.rb b/mrbgems/mruby-io/test/io.rb index 1491a4cfe..3aaa109a8 100644 --- a/mrbgems/mruby-io/test/io.rb +++ b/mrbgems/mruby-io/test/io.rb @@ -5,7 +5,7 @@ MRubyIOTestUtil.io_test_setup $cr, $crlf, $cmd = MRubyIOTestUtil.win? ? [1, "\r\n", "cmd /c "] : [0, "\n", ""] def assert_io_open(meth) - assert do + assert "assert_io_open" do fd = IO.sysopen($mrbtest_io_rfname) assert_equal Fixnum, fd.class io1 = IO.__send__(meth, fd) diff --git a/mrbgems/mruby-pack/test/pack.rb b/mrbgems/mruby-pack/test/pack.rb index 68ef4165f..6832adcc7 100644 --- a/mrbgems/mruby-pack/test/pack.rb +++ b/mrbgems/mruby-pack/test/pack.rb @@ -2,7 +2,7 @@ PACK_IS_LITTLE_ENDIAN = "\x01\00".unpack('S')[0] == 0x01 def assert_pack tmpl, packed, unpacked t = tmpl.inspect - assert do + assert "assert_pack" do assert_equal packed, unpacked.pack(tmpl), "#{unpacked.inspect}.pack(#{t})" assert_equal unpacked, packed.unpack(tmpl), "#{packed.inspect}.unpack(#{t})" end diff --git a/mrbgems/mruby-rational/test/rational.rb b/mrbgems/mruby-rational/test/rational.rb index 11737034b..a8ebb8ea2 100644 --- a/mrbgems/mruby-rational/test/rational.rb +++ b/mrbgems/mruby-rational/test/rational.rb @@ -23,14 +23,14 @@ class ComplexLikeNumeric < UserDefinedNumeric end def assert_rational(exp, real) - assert do + assert "assert_rational" do assert_float exp.numerator, real.numerator assert_float exp.denominator, real.denominator end end def assert_equal_rational(exp, o1, o2) - assert do + assert "assert_equal_rational" do if exp assert_operator(o1, :==, o2) assert_not_operator(o1, :!=, o2) diff --git a/test/assert.rb b/test/assert.rb index 58ee4b913..5ae46ca70 100644 --- a/test/assert.rb +++ b/test/assert.rb @@ -76,7 +76,7 @@ end # iso : The ISO reference code of the feature # which will be tested by this # assertion -def assert(str = 'Assertion failed', iso = '') +def assert(str = 'assert', iso = '') t_print(str, (iso != '' ? " [#{iso}]" : ''), ' : ') if $mrbtest_verbose begin $mrbtest_child_noassert ||= [0] @@ -99,10 +99,10 @@ def assert(str = 'Assertion failed', iso = '') yield if $mrbtest_assert.size > 0 if $mrbtest_assert.size == $mrbtest_child_noassert[-1] - $asserts.push(assertion_string('Info: ', str, iso)) + $asserts.push(assertion_string('Skip: ', str, iso)) $mrbtest_child_noassert[-2] += 1 - $ok_test += 1 - t_print('.') + $skip_test += 1 + t_print('?') else $asserts.push(assertion_string('Fail: ', str, iso)) $ko_test += 1 diff --git a/test/t/numeric.rb b/test/t/numeric.rb index bb95f8ef3..5b1e79153 100644 --- a/test/t/numeric.rb +++ b/test/t/numeric.rb @@ -8,7 +8,7 @@ def assert_step(exp, receiver, args, inf: false) break if inf && exp.size == act.size end expr = "#{receiver.inspect}.step(#{args.map(&:inspect).join(', ')})" - assert do + assert "assert_step" do assert_true(exp.eql?(act), "#{expr}: counters", assertion_diff(exp, act)) assert_same(receiver, ret, "#{expr}: return value") unless inf end -- cgit v1.2.3 From 6c4278144aa508f7756dd06712e5d8214e2b0a1b Mon Sep 17 00:00:00 2001 From: takumakume Date: Thu, 5 Sep 2019 19:51:54 +0900 Subject: add assert_not_nil method --- test/assert.rb | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'test/assert.rb') diff --git a/test/assert.rb b/test/assert.rb index 32dd4ddc6..9b04f5b48 100644 --- a/test/assert.rb +++ b/test/assert.rb @@ -208,6 +208,13 @@ def assert_nil(obj, msg = nil) assert_true(ret, msg, diff) end +def assert_not_nil(obj, msg = nil) + if ret = obj.nil? + diff = " Expected #{obj.inspect} to not be nil." + end + assert_false(ret, msg, diff) +end + def assert_include(*args); _assert_include(true, *args) end def assert_not_include(*args); _assert_include(false, *args) end def _assert_include(affirmed, collection, obj, msg = nil) -- cgit v1.2.3