diff --git a/Rakefile b/Rakefile index 5d512c8..d81dd1f 100644 --- a/Rakefile +++ b/Rakefile @@ -7,4 +7,11 @@ Rake::TestTask.new(:test) do |t| t.test_files = FileList["test/**/test_*.rb"] end +task :sync_tool do + require 'fileutils' + FileUtils.cp "../ruby/tool/lib/test/unit/core_assertions.rb", "./test/lib" + FileUtils.cp "../ruby/tool/lib/envutil.rb", "./test/lib" + FileUtils.cp "../ruby/tool/lib/find_executable.rb", "./test/lib" +end + task :default => :test diff --git a/test/lib/core_assertions.rb b/test/lib/core_assertions.rb index 39964d9..adb797b 100644 --- a/test/lib/core_assertions.rb +++ b/test/lib/core_assertions.rb @@ -194,7 +194,11 @@ def assert_nothing_raised(*args) end if ((args.empty? && !as) || args.any? {|a| a.instance_of?(Module) ? e.is_a?(a) : e.class == a }) - msg = message(msg) { "Exception raised:\n<#{mu_pp(e)}>" } + msg = message(msg) { + "Exception raised:\n<#{mu_pp(e)}>\n" + + "Backtrace:\n" + + e.backtrace.map{|frame| " #{frame}"}.join("\n") + } raise MiniTest::Assertion, msg.call, bt else raise @@ -287,6 +291,7 @@ def assert_separately(args, file = nil, line = nil, src, ignore_stderr: nil, **o args = args.dup args.insert((Hash === args.first ? 1 : 0), "-w", "--disable=gems", *$:.map {|l| "-I#{l}"}) stdout, stderr, status = EnvUtil.invoke_ruby(args, src, capture_stdout, true, **opt) + ensure if res_c res_c.close res = res_p.read @@ -294,6 +299,7 @@ def assert_separately(args, file = nil, line = nil, src, ignore_stderr: nil, **o else res = stdout end + raise if $! abort = status.coredump? || (status.signaled? && ABORT_SIGNALS.include?(status.termsig)) assert(!abort, FailDesc[status, nil, stderr]) self._assertions += res[/^assertions=(\d+)/, 1].to_i @@ -450,6 +456,49 @@ def assert_raise_with_message(exception, expected, msg = nil, &block) ex end + # pattern_list is an array which contains regexp and :*. + # :* means any sequence. + # + # pattern_list is anchored. + # Use [:*, regexp, :*] for non-anchored match. + def assert_pattern_list(pattern_list, actual, message=nil) + rest = actual + anchored = true + pattern_list.each_with_index {|pattern, i| + if pattern == :* + anchored = false + else + if anchored + match = /\A#{pattern}/.match(rest) + else + match = pattern.match(rest) + end + unless match + msg = message(msg) { + expect_msg = "Expected #{mu_pp pattern}\n" + if /\n[^\n]/ =~ rest + actual_mesg = +"to match\n" + rest.scan(/.*\n+/) { + actual_mesg << ' ' << $&.inspect << "+\n" + } + actual_mesg.sub!(/\+\n\z/, '') + else + actual_mesg = "to match " + mu_pp(rest) + end + actual_mesg << "\nafter #{i} patterns with #{actual.length - rest.length} characters" + expect_msg + actual_mesg + } + assert false, msg + end + rest = match.post_match + anchored = true + end + } + if anchored + assert_equal("", rest) + end + end + def assert_warning(pat, msg = nil) result = nil stderr = EnvUtil.with_default_internal(pat.encoding) { diff --git a/test/lib/envutil.rb b/test/lib/envutil.rb index 2faf483..0bd8bdb 100644 --- a/test/lib/envutil.rb +++ b/test/lib/envutil.rb @@ -86,7 +86,20 @@ def terminate(pid, signal = :TERM, pgroup = nil, reprieve = 1) when nil, false pgroup = pid end + + lldb = true if /darwin/ =~ RUBY_PLATFORM + while signal = signals.shift + + if lldb and [:ABRT, :KILL].include?(signal) + lldb = false + # sudo -n: --non-interactive + # lldb -p: attach + # -o: run command + system(*%W[sudo -n lldb -p #{pid} --batch -o bt\ all -o call\ rb_vmdebug_stack_dump_all_threads() -o quit]) + true + end + begin Process.kill signal, pgroup rescue Errno::EINVAL @@ -100,6 +113,8 @@ def terminate(pid, signal = :TERM, pgroup = nil, reprieve = 1) begin Timeout.timeout(reprieve) {Process.wait(pid)} rescue Timeout::Error + else + break end end end @@ -137,8 +152,10 @@ def invoke_ruby(args, stdin_data = "", capture_stdout = false, capture_stderr = args = [args] if args.kind_of?(String) pid = spawn(child_env, *precommand, rubybin, *args, **opt) in_c.close - out_c.close if capture_stdout - err_c.close if capture_stderr && capture_stderr != :merge_to_stdout + out_c&.close + out_c = nil + err_c&.close + err_c = nil if block_given? return yield in_p, out_p, err_p, pid else @@ -242,7 +259,11 @@ def with_default_internal(enc) def labeled_module(name, &block) Module.new do - singleton_class.class_eval {define_method(:to_s) {name}; alias inspect to_s} + singleton_class.class_eval { + define_method(:to_s) {name} + alias inspect to_s + alias name to_s + } class_eval(&block) if block end end @@ -250,7 +271,11 @@ def labeled_module(name, &block) def labeled_class(name, superclass = Object, &block) Class.new(superclass) do - singleton_class.class_eval {define_method(:to_s) {name}; alias inspect to_s} + singleton_class.class_eval { + define_method(:to_s) {name} + alias inspect to_s + alias name to_s + } class_eval(&block) if block end end