summaryrefslogtreecommitdiffhomepage
path: root/test/assert.rb
diff options
context:
space:
mode:
Diffstat (limited to 'test/assert.rb')
-rw-r--r--test/assert.rb373
1 files changed, 245 insertions, 128 deletions
diff --git a/test/assert.rb b/test/assert.rb
index a9baae5e1..c493cbbc0 100644
--- a/test/assert.rb
+++ b/test/assert.rb
@@ -1,17 +1,47 @@
+$undefined = Object.new
$ok_test = 0
$ko_test = 0
$kill_test = 0
+$skip_test = 0
$asserts = []
$test_start = Time.now if Object.const_defined?(:Time)
-# Implementation of print due to the reason that there might be no print
-def t_print(*args)
- i = 0
- len = args.size
- while i < len
- str = args[i].to_s
- __t_printstr__ str rescue print str
- i += 1
+unless RUBY_ENGINE == "mruby"
+ # For bintest on Ruby
+ def t_print(*args)
+ print(*args)
+ $stdout.flush
+ nil
+ 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
@@ -19,16 +49,17 @@ end
# Create the assertion in a readable way
def assertion_string(err, str, iso=nil, e=nil, bt=nil)
msg = "#{err}#{str}"
- msg += " [#{iso}]" if iso && iso != ''
- msg += " => #{e.cause}" if e && e.respond_to?(:cause)
- msg += " => #{e.message}" if e && !e.respond_to?(:cause)
- msg += " (mrbgems: #{GEMNAME})" if Object.const_defined?(:GEMNAME)
- if $mrbtest_assert && $mrbtest_assert.size > 0
+ 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.each do |idx, assert_msg, diff|
- msg += "\n - Assertion[#{idx}] Failed: #{assert_msg}\n#{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
@@ -43,206 +74,292 @@ 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, nil))
- $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('.')
end
+ 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
- if e.class.to_s == 'MRubyTestSkip'
- $asserts.push(assertion_string('Skip: ', str, iso, e, nil))
- t_print('?')
+ $asserts.push(assertion_string("#{e.class}: ", str, iso, e, bt))
+ $kill_test += 1
+ t_print('X')
+ ensure
+ 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
- $asserts.push(assertion_string("#{e.class}: ", str, iso, e, bt))
- $kill_test += 1
- t_print('X')
+ parent_asserts.concat $asserts
end
- ensure
- $mrbtest_assert = nil
+ $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
def assertion_diff(exp, act)
- " Expected: #{exp.inspect}\n" +
+ " Expected: #{exp.inspect}\n" \
" Actual: #{act.inspect}"
end
-def assert_true(ret, msg = nil, diff = nil)
- if $mrbtest_assert
- $mrbtest_assert_idx += 1
- unless ret
- msg = "Expected #{ret.inspect} to be true" unless msg
- diff = assertion_diff(true, ret) unless diff
- $mrbtest_assert.push([$mrbtest_assert_idx, msg, diff])
+def assert_true(obj, msg = nil, diff = nil)
+ 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.to_s, msg, diff])
end
end
- ret
+ obj
end
-def assert_false(ret, msg = nil, diff = nil)
- if $mrbtest_assert
- $mrbtest_assert_idx += 1
- if ret
- msg = "Expected #{ret.inspect} to be false" unless msg
- diff = assertion_diff(false, ret) unless diff
+def assert_false(obj, msg = nil, diff = nil)
+ unless obj == false
+ diff ||= " Expected #{obj.inspect} to be false."
+ end
+ assert_true(!obj, msg, diff)
+end
+
+def assert_equal(exp, act_or_msg = nil, msg = nil, &block)
+ ret, exp, act, msg = _eval_assertion(:==, exp, act_or_msg, msg, block)
+ unless ret
+ diff = assertion_diff(exp, act)
+ end
+ assert_true(ret, msg, diff)
+end
- $mrbtest_assert.push([$mrbtest_assert_idx, msg, diff])
+def assert_not_equal(exp, act_or_msg = nil, msg = nil, &block)
+ ret, exp, act, msg = _eval_assertion(:==, exp, act_or_msg, msg, block)
+ if ret
+ diff = " Expected #{act.inspect} to not be equal to #{exp.inspect}."
+ end
+ assert_true(!ret, msg, diff)
+end
+
+def assert_same(*args); _assert_same(true, *args) end
+def assert_not_same(*args); _assert_same(false, *args) end
+def _assert_same(affirmed, exp, act, msg = nil)
+ unless ret = exp.equal?(act) == affirmed
+ exp_str, act_str = [exp, act].map do |o|
+ "#{o.inspect} (class=#{o.class}, oid=#{o.__id__})"
end
+ diff = " Expected #{act_str} to #{'not ' unless affirmed}be the same as #{exp_str}."
end
- !ret
+ assert_true(ret, msg, diff)
end
-def assert_equal(arg1, arg2 = nil, arg3 = nil)
- if block_given?
- exp, act, msg = arg1, yield, arg2
- else
- exp, act, msg = arg1, arg2, arg3
+def assert_nil(obj, msg = nil)
+ unless ret = obj.nil?
+ diff = " Expected #{obj.inspect} to be nil."
end
+ assert_true(ret, msg, diff)
+end
- msg = "Expected to be equal" unless msg
- diff = assertion_diff(exp, act)
- assert_true(exp == act, msg, diff)
+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)
+ unless ret = collection.include?(obj) == affirmed
+ diff = " Expected #{collection.inspect} to #{'not ' unless affirmed}include #{obj.inspect}."
+ end
+ assert_true(ret, msg, diff)
end
-def assert_not_equal(arg1, arg2 = nil, arg3 = nil)
- if block_given?
- exp, act, msg = arg1, yield, arg2
- else
- exp, act, msg = arg1, arg2, arg3
+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
- msg = "Expected to be not equal" unless msg
- diff = assertion_diff(exp, act)
- assert_false(exp == act, msg, diff)
+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 $undefined.equal?(obj2)
+ 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
-def assert_nil(obj, msg = nil)
- msg = "Expected #{obj.inspect} to be nil" unless msg
- diff = assertion_diff(nil, obj)
- assert_true(obj.nil?, msg, diff)
+##
+# Fail unless +str+ matches against +pattern+.
+#
+# +pattern+ is interpreted as pattern for File.fnmatch?. It may contain the
+# following metacharacters:
+#
+# <code>*</code> ::
+# Matches any string.
+#
+# <code>?</code> ::
+# Matches any one character.
+#
+# <code>[_SET_]</code>, <code>[^_SET_]</code> (<code>[!_SET_]</code>) ::
+# Matches any one character in _SET_. Behaves like character sets in
+# Regexp, including set negation (<code>[^a-z]</code>).
+#
+# <code>{_A_,_B_}</code> ::
+# Matches pattern _A_ or pattern _B_.
+#
+# <code> \ </code> ::
+# 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
-def assert_include(collection, obj, msg = nil)
- msg = "Expected #{collection.inspect} to include #{obj.inspect}" unless msg
- diff = " Collection: #{collection.inspect}\n" +
- " Object: #{obj.inspect}"
- assert_true(collection.include?(obj), msg, diff)
+##
+# Fails unless +obj+ is a kind of +cls+.
+def assert_kind_of(cls, obj, msg = nil)
+ unless ret = obj.kind_of?(cls)
+ diff = " Expected #{obj.inspect} to be a kind of #{cls}, not #{obj.class}."
+ end
+ assert_true(ret, msg, diff)
end
-def assert_not_include(collection, obj, msg = nil)
- msg = "Expected #{collection.inspect} to not include #{obj.inspect}" unless msg
- diff = " Collection: #{collection.inspect}\n" +
- " Object: #{obj.inspect}"
- assert_false(collection.include?(obj), msg, diff)
+##
+# 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.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}.")
+ else
+ pass
+ end
end
def assert_raise(*exc)
- return true unless $mrbtest_assert
- $mrbtest_assert_idx += 1
-
msg = (exc.last.is_a? String) ? exc.pop : nil
-
+ exc = exc.empty? ? StandardError : exc.size == 1 ? exc[0] : exc
begin
yield
- msg ||= "Expected to raise #{exc} but nothing was raised."
- diff = nil
- $mrbtest_assert.push [$mrbtest_assert_idx, msg, diff]
- false
rescue *exc
- true
+ pass
rescue Exception => e
- msg ||= "Expected to raise #{exc}, not"
- diff = " Class: <#{e.class}>\n" +
- " Message: #{e.message}"
- $mrbtest_assert.push [$mrbtest_assert_idx, msg, diff]
- false
+ diff = " #{exc} exception expected, not\n" \
+ " Class: <#{e.class}>\n" \
+ " Message: <#{e}>"
+ flunk(msg, diff)
+ else
+ diff = " #{exc} expected but nothing was raised."
+ flunk(msg, diff)
end
end
def assert_nothing_raised(msg = nil)
- return true unless $mrbtest_assert
- $mrbtest_assert_idx += 1
-
begin
yield
- true
rescue Exception => e
- msg ||= "Expected not to raise #{exc.join(', ')} but it raised"
- diff = " Class: <#{e.class}>\n" +
- " Message: #{e.message}"
- $mrbtest_assert.push [$mrbtest_assert_idx, msg, diff]
- false
+ diff = " Exception raised:\n" \
+ " Class: <#{e.class}>\n" \
+ " Message: <#{e}>"
+ flunk(msg, diff)
+ else
+ pass
end
end
-##
-# Fails unless +obj+ is a kind of +cls+.
-def assert_kind_of(cls, obj, msg = nil)
- msg = "Expected #{obj.inspect} to be a kind of #{cls}, not #{obj.class}" unless msg
- diff = assertion_diff(cls, obj.class)
- assert_true(obj.kind_of?(cls), msg, diff)
+def pass
+ assert_true(true)
end
-##
-# Fails unless +exp+ is equal to +act+ in terms of a Float
-def assert_float(exp, act, msg = nil)
- msg = "Float #{exp} expected to be equal to float #{act}" unless msg
- diff = assertion_diff(exp, act)
- assert_true check_float(exp, act), msg, diff
+def flunk(msg = "Epic Fail!", diff = "")
+ assert_true(false, msg, diff)
end
##
# Report the test result and print all assertions
# which were reported broken.
-def report()
+def report
t_print("\n")
$asserts.each do |msg|
- t_print "#{msg}\n"
+ t_print("#{msg}\n")
end
- $total_test = $ok_test+$ko_test+$kill_test
+ $total_test = $ok_test + $ko_test + $kill_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")
if Object.const_defined?(:Time)
t_time = Time.now - $test_start
t_print(" Time: #{t_time.round(2)} seconds\n")
end
+
+ $ko_test == 0 && $kill_test == 0
end
-##
-# Performs fuzzy check for equality on methods returning floats
-def check_float(a, b)
- tolerance = Mrbtest::FLOAT_TOLERANCE
- a = a.to_f
- b = b.to_f
- if a.finite? and b.finite?
- (a-b).abs < tolerance
+def _eval_assertion(meth, exp, act_or_msg, msg, block)
+ if block
+ exp, act, msg = exp, block.call, act_or_msg
else
- true
+ exp, act, msg = exp, act_or_msg, msg
end
+ return exp.__send__(meth, act), exp, act, msg
end
##
# Skip the test
-class MRubyTestSkip < NotImplementedError
- attr_accessor :cause
- def initialize(cause)
- @cause = cause
- end
-end
+class MRubyTestSkip < NotImplementedError; end
def skip(cause = "")
raise MRubyTestSkip.new(cause)