Kouhei Sutou
null+****@clear*****
Mon Aug 12 11:39:17 JST 2013
Kouhei Sutou 2013-08-12 11:39:17 +0900 (Mon, 12 Aug 2013) New Revision: ab11da910534ef0a62a6c71ff1403a93407619d4 https://github.com/groonga/grntest/commit/ab11da910534ef0a62a6c71ff1403a93407619d4 Message: Extract reporters to lib/grntest/reporters/ Added files: lib/grntest/reporters.rb lib/grntest/reporters/base_reporter.rb lib/grntest/reporters/inplace_reporter.rb lib/grntest/reporters/mark_reporter.rb lib/grntest/reporters/stream_reporter.rb Modified files: lib/grntest/tester.rb Added: lib/grntest/reporters.rb (+35 -0) 100644 =================================================================== --- /dev/null +++ lib/grntest/reporters.rb 2013-08-12 11:39:17 +0900 (c96c8b4) @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012-2013 Kouhei Sutou <kou �� clear-code.com> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +require "grntest/reporters/mark_reporter" +require "grntest/reporters/stream_reporter" +require "grntest/reporters/inplace_reporter" + +module Grntest + module Reporters + def create_repoter(tester) + case tester.reporter + when :mark + Reporters::MarkReporter.new(tester) + when :stream + Reporters::StreamReporter.new(tester) + when :inplace + Reporters::InplaceReporter.new(tester) + end + end + end +end Added: lib/grntest/reporters/base_reporter.rb (+375 -0) 100644 =================================================================== --- /dev/null +++ lib/grntest/reporters/base_reporter.rb 2013-08-12 11:39:17 +0900 (399d73d) @@ -0,0 +1,375 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012-2013 Kouhei Sutou <kou �� clear-code.com> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +module Grntest + module Reporters + class BaseReporter + def initialize(tester) + @tester = tester + @term_width = guess_term_width + @output =****@teste***** + @mutex = Mutex.new + reset_current_column + end + + private + def synchronize + @mutex.synchronize do + yield + end + end + + def report_summary(result) + puts(statistics_header) + puts(colorize(statistics(result), result)) + pass_ratio = result.pass_ratio + elapsed_time = result.elapsed_time + summary = "%.4g%% passed in %.4fs." % [pass_ratio, elapsed_time] + puts(colorize(summary, result)) + end + + def columns + [ + # label, format value + ["tests/sec", lambda {|result| "%9.2f" % throughput(result)}], + [" tests", lambda {|result| "%8d" % result.n_tests}], + [" passes", lambda {|result| "%8d" % result.n_passed_tests}], + ["failures", lambda {|result| "%8d" % result.n_failed_tests}], + [" leaked", lambda {|result| "%8d" % result.n_leaked_tests}], + [" omitted", lambda {|result| "%8d" % result.n_omitted_tests}], + ["!checked", lambda {|result| "%8d" % result.n_not_checked_tests}], + ] + end + + def statistics_header + labels = columns.collect do |label, format_value| + label + end + " " + labels.join(" | ") + " |" + end + + def statistics(result) + items = columns.collect do |label, format_value| + format_value.call(result) + end + " " + items.join(" | ") + " |" + end + + def throughput(result) + if result.elapsed_time.zero? + tests_per_second = 0 + else + tests_per_second = result.n_tests / result.elapsed_time + end + tests_per_second + end + + def report_failure(result) + report_marker(result) + report_diff(result.expected, result.actual) + report_marker(result) + end + + def report_actual(result) + report_marker(result) + puts(result.actual) + report_marker(result) + end + + def report_marker(result) + puts(colorize("=" * @term_width, result)) + end + + def report_diff(expected, actual) + create_temporary_file("expected", expected) do |expected_file| + create_temporary_file("actual", actual) do |actual_file| + diff_options =****@teste*****_options.dup + diff_options.concat(["--label", "(expected)", expected_file.path, + "--label", "(actual)", actual_file.path]) + system(@tester.diff, *diff_options) + end + end + end + + def report_test(worker, result) + report_marker(result) + print("[#{worker.id}] ") if****@teste*****_workers > 1 + puts(worker.suite_name) + print(" #{worker.test_name}") + report_test_result(result, worker.status) + end + + def report_test_result(result, label) + message = test_result_message(result, label) + message_width = string_width(message) + rest_width = @term_width - @current_column + if rest_width > message_width + print(" " * (rest_width - message_width)) + end + puts(message) + end + + def test_result_message(result, label) + elapsed_time = result.elapsed_time + formatted_elapsed_time = "%.4fs" % elapsed_time + formatted_elapsed_time = colorize(formatted_elapsed_time, + elapsed_time_status(elapsed_time)) + " #{formatted_elapsed_time} [#{colorize(label, result)}]" + end + + LONG_ELAPSED_TIME = 1.0 + def long_elapsed_time?(elapsed_time) + elapsed_time >= LONG_ELAPSED_TIME + end + + def elapsed_time_status(elapsed_time) + if long_elapsed_time?(elapsed_time) + elapsed_time_status = :failure + else + elapsed_time_status = :not_checked + end + end + + def justify(message, width) + return " " * width if message.nil? + return message.ljust(width) if message.bytesize <= width + half_width = width / 2.0 + elision_mark = "..." + left = message[0, half_width.ceil - elision_mark.size] + right = message[(message.size - half_width.floor)..-1] + "#{left}#{elision_mark}#{right}" + end + + def print(message) + @current_column += string_width(message.to_s) + @output.print(message) + end + + def puts(*messages) + reset_current_column + @output.puts(*messages) + end + + def reset_current_column + @current_column = 0 + end + + def create_temporary_file(key, content) + file = Tempfile.new("groonga-test-#{key}") + file.print(content) + file.close + yield(file) + end + + def guess_term_width + Integer(guess_term_width_from_env || guess_term_width_from_stty || 79) + rescue ArgumentError + 0 + end + + def guess_term_width_from_env + ENV["COLUMNS"] || ENV["TERM_WIDTH"] + end + + def guess_term_width_from_stty + return nil unless STDIN.tty? + + case tty_info + when /(\d+) columns/ + $1 + when /columns (\d+)/ + $1 + else + nil + end + end + + def tty_info + begin + `stty -a` + rescue SystemCallError + nil + end + end + + def string_width(string) + string.gsub(/\e\[[0-9;]+m/, "").size + end + + def result_status(result) + if result.respond_to?(:status) + result.status + else + if result.n_failed_tests > 0 + :failure + elsif result.n_leaked_tests > 0 + :leaked + elsif result.n_omitted_tests > 0 + :omitted + elsif result.n_not_checked_tests > 0 + :not_checked + else + :success + end + end + end + + def colorize(message, result_or_status) + return message unles****@teste*****_color? + if result_or_status.is_a?(Symbol) + status = result_or_status + else + status = result_status(result_or_status) + end + case status + when :success + "%s%s%s" % [success_color, message, reset_color] + when :failure + "%s%s%s" % [failure_color, message, reset_color] + when :leaked + "%s%s%s" % [leaked_color, message, reset_color] + when :omitted + "%s%s%s" % [omitted_color, message, reset_color] + when :not_checked + "%s%s%s" % [not_checked_color, message, reset_color] + else + message + end + end + + def success_color + escape_sequence({ + :color => :green, + :color_256 => [0, 3, 0], + :background => true, + }, + { + :color => :white, + :color_256 => [5, 5, 5], + :bold => true, + }) + end + + def failure_color + escape_sequence({ + :color => :red, + :color_256 => [3, 0, 0], + :background => true, + }, + { + :color => :white, + :color_256 => [5, 5, 5], + :bold => true, + }) + end + + def leaked_color + escape_sequence({ + :color => :magenta, + :color_256 => [3, 0, 3], + :background => true, + }, + { + :color => :white, + :color_256 => [5, 5, 5], + :bold => true, + }) + end + + def omitted_color + escape_sequence({ + :color => :blue, + :color_256 => [0, 0, 1], + :background => true, + }, + { + :color => :white, + :color_256 => [5, 5, 5], + :bold => true, + }) + end + + def not_checked_color + escape_sequence({ + :color => :cyan, + :color_256 => [0, 1, 1], + :background => true, + }, + { + :color => :white, + :color_256 => [5, 5, 5], + :bold => true, + }) + end + + def reset_color + escape_sequence(:reset) + end + + COLOR_NAMES = [ + :black, :red, :green, :yellow, + :blue, :magenta, :cyan, :white, + ] + def escape_sequence(*commands) + sequence = [] + commands.each do |command| + case command + when :reset + sequence << "0" + when :bold + sequence << "1" + when :italic + sequence << "3" + when :underline + sequence << "4" + when Hash + foreground_p = !command[:background] + if available_colors == 256 + sequence << (foreground_p ? "38" : "48") + sequence << "5" + sequence << pack_256_color(*command[:color_256]) + else + color_parameter = foreground_p ? 3 : 4 + color_parameter += 6 if command[:intensity] + color = COLOR_NAMES.index(command[:color]) + sequence << "#{color_parameter}#{color}" + end + end + end + "\e[#{sequence.join(';')}m" + end + + def pack_256_color(red, green, blue) + red * 36 + green * 6 + blue + 16 + end + + def available_colors + case ENV["COLORTERM"] + when "gnome-terminal" + 256 + else + case ENV["TERM"] + when /-256color\z/ + 256 + else + 8 + end + end + end + end + end +end Added: lib/grntest/reporters/inplace_reporter.rb (+208 -0) 100644 =================================================================== --- /dev/null +++ lib/grntest/reporters/inplace_reporter.rb 2013-08-12 11:39:17 +0900 (5baa30a) @@ -0,0 +1,208 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012-2013 Kouhei Sutou <kou �� clear-code.com> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +require "grntest/reporters/base_reporter" + +module Grntest + module Reporters + class InplaceReporter < BaseReporter + def initialize(tester) + super + @last_redraw_time = Time.now + @minimum_redraw_interval = 0.1 + end + + def on_start(result) + @test_suites_result = result + end + + def on_worker_start(worker) + end + + def on_suite_start(worker) + redraw + end + + def on_test_start(worker) + redraw + end + + def on_test_success(worker, result) + redraw + end + + def on_test_failure(worker, result) + redraw do + report_test(worker, result) + report_failure(result) + end + end + + def on_test_leak(worker, result) + redraw do + report_test(worker, result) + report_marker(result) + report_actual(result) unless result.checked? + end + end + + def on_test_omission(worker, result) + redraw do + report_test(worker, result) + report_actual(result) + end + end + + def on_test_no_check(worker, result) + redraw do + report_test(worker, result) + report_actual(result) + end + end + + def on_test_finish(worker, result) + redraw + end + + def on_suite_finish(worker) + redraw + end + + def on_worker_finish(worker) + redraw + end + + def on_finish(result) + draw + puts + report_summary(result) + end + + private + def draw + draw_statistics_header_line + @test_suites_result.workers.each do |worker| + draw_status_line(worker) + draw_test_line(worker) + end + draw_progress_line + end + + def draw_statistics_header_line + puts(statistics_header) + end + + def draw_status_line(worker) + clear_line + left = "[#{colorize(worker.id, worker.result)}] " + right = " [#{worker.status}]" + rest_width = @term_width - @current_column + center_width = rest_width - string_width(left) - string_width(right) + center = justify(worker.suite_name, center_width) + puts("#{left}#{center}#{right}") + end + + def draw_test_line(worker) + clear_line + if worker.test_name + label = " #{worker.test_name}" + else + label = statistics(worker.result) + end + puts(justify(label, @term_width)) + end + + def draw_progress_line + n_done_tests = @test_suites_result.n_tests + n_total_tests = @test_suites_result.n_total_tests + if n_total_tests.zero? + finished_test_ratio = 0.0 + else + finished_test_ratio = n_done_tests.to_f / n_total_tests + end + + start_mark = "|" + finish_mark = "|" + statistics = " [%3d%%]" % (finished_test_ratio * 100) + + progress_width = @term_width + progress_width -= start_mark.bytesize + progress_width -= finish_mark.bytesize + progress_width -= statistics.bytesize + finished_mark = "-" + if n_done_tests == n_total_tests + progress = colorize(finished_mark * progress_width, + @test_suites_result) + else + current_mark = ">" + finished_marks_width = (progress_width * finished_test_ratio).ceil + finished_marks_width -= current_mark.bytesize + finished_marks_width = [0, finished_marks_width].max + progress = finished_mark * finished_marks_width + current_mark + progress = colorize(progress, @test_suites_result) + progress << " " * (progress_width - string_width(progress)) + end + puts("#{start_mark}#{progress}#{finish_mark}#{statistics}") + end + + def redraw + synchronize do + unless block_given? + return if Time.now - @last_redraw_time < @minimum_redraw_interval + end + draw + if block_given? + yield + else + up_n_lines(n_using_lines) + end + @last_redraw_time = Time.now + end + end + + def up_n_lines(n) + print("\e[1A" * n) + end + + def clear_line + print(" " * @term_width) + print("\r") + reset_current_column + end + + def n_using_lines + n_statistics_header_line + n_worker_lines * n_workers + n_progress_lines + end + + def n_statistics_header_line + 1 + end + + def n_worker_lines + 2 + end + + def n_progress_lines + 1 + end + + def n_workers + @tester.n_workers + end + end + end +end Added: lib/grntest/reporters/mark_reporter.rb (+112 -0) 100644 =================================================================== --- /dev/null +++ lib/grntest/reporters/mark_reporter.rb 2013-08-12 11:39:17 +0900 (c7703ba) @@ -0,0 +1,112 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012-2013 Kouhei Sutou <kou �� clear-code.com> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +require "grntest/reporters/base_reporter" + +module Grntest + module Reporters + class MarkReporter < BaseReporter + def initialize(tester) + super + end + + def on_start(result) + end + + def on_worker_start(worker) + end + + def on_suite_start(worker) + end + + def on_test_start(worker) + end + + def on_test_success(worker, result) + synchronize do + report_test_result_mark(".", result) + end + end + + def on_test_failure(worker, result) + synchronize do + report_test_result_mark("F", result) + puts + report_test(worker, result) + report_failure(result) + end + end + + def on_test_leak(worker, result) + synchronize do + report_test_result_mark("L(#{result.n_leaked_objects})", result) + unless result.checked? + puts + report_test(worker, result) + report_actual(result) + end + end + end + + def on_test_omission(worker, result) + synchronize do + report_test_result_mark("O", result) + puts + report_test(worker, result) + report_actual(result) + end + end + + def on_test_no_check(worker, result) + synchronize do + report_test_result_mark("N", result) + puts + report_test(worker, result) + report_actual(result) + end + end + + def on_test_finish(worker, result) + end + + def on_suite_finish(worker) + end + + def on_worker_finish(worker_id) + end + + def on_finish(result) + puts + puts + report_summary(result) + end + + private + def report_test_result_mark(mark, result) + if @term_width < @current_column + mark.bytesize + puts + end + print(colorize(mark, result)) + if @term_width <= @current_column + puts + else + @output.flush + end + end + end + end +end Added: lib/grntest/reporters/stream_reporter.rb (+86 -0) 100644 =================================================================== --- /dev/null +++ lib/grntest/reporters/stream_reporter.rb 2013-08-12 11:39:17 +0900 (7aa5514) @@ -0,0 +1,86 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012-2013 Kouhei Sutou <kou �� clear-code.com> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +require "grntest/reporters/base_reporter" + +module Grntest + module Reporters + class StreamReporter < BaseReporter + def initialize(tester) + super + end + + def on_start(result) + end + + def on_worker_start(worker) + end + + def on_suite_start(worker) + if worker.suite_name.bytesize <= @term_width + puts(worker.suite_name) + else + puts(justify(worker.suite_name, @term_width)) + end + @output.flush + end + + def on_test_start(worker) + print(" #{worker.test_name}") + @output.flush + end + + def on_test_success(worker, result) + report_test_result(result, worker.status) + end + + def on_test_failure(worker, result) + report_test_result(result, worker.status) + report_failure(result) + end + + def on_test_leak(worker, result) + report_test_result(result, worker.status) + report_actual(result) unless result.checked? + end + + def on_test_omission(worker, result) + report_test_result(result, worker.status) + report_actual(result) + end + + def on_test_no_check(worker, result) + report_test_result(result, worker.status) + report_actual(result) + end + + def on_test_finish(worker, result) + end + + def on_suite_finish(worker) + end + + def on_worker_finish(worker_id) + end + + def on_finish(result) + puts + report_summary(result) + end + end + end +end Modified: lib/grntest/tester.rb (+2 -703) =================================================================== --- lib/grntest/tester.rb 2013-08-12 11:29:33 +0900 (89e72de) +++ lib/grntest/tester.rb 2013-08-12 11:39:17 +0900 (c1b480f) @@ -29,6 +29,7 @@ require "msgpack" require "groonga/command" require "grntest/version" +require "grntest/reporters" module Grntest class Tester @@ -662,14 +663,7 @@ module Grntest end def create_reporter - case****@teste***** - when :mark - MarkReporter.new(@tester) - when :stream - StreamReporter.new(@tester) - when :inplace - InplaceReporter.new(@tester) - end + Grntest::Reporters.create_repoter(@tester) end end @@ -1651,700 +1645,5 @@ EOF self.class.new(@host, @port, context) end end - - class BaseReporter - def initialize(tester) - @tester = tester - @term_width = guess_term_width - @output =****@teste***** - @mutex = Mutex.new - reset_current_column - end - - private - def synchronize - @mutex.synchronize do - yield - end - end - - def report_summary(result) - puts(statistics_header) - puts(colorize(statistics(result), result)) - pass_ratio = result.pass_ratio - elapsed_time = result.elapsed_time - summary = "%.4g%% passed in %.4fs." % [pass_ratio, elapsed_time] - puts(colorize(summary, result)) - end - - def columns - [ - # label, format value - ["tests/sec", lambda {|result| "%9.2f" % throughput(result)}], - [" tests", lambda {|result| "%8d" % result.n_tests}], - [" passes", lambda {|result| "%8d" % result.n_passed_tests}], - ["failures", lambda {|result| "%8d" % result.n_failed_tests}], - [" leaked", lambda {|result| "%8d" % result.n_leaked_tests}], - [" omitted", lambda {|result| "%8d" % result.n_omitted_tests}], - ["!checked", lambda {|result| "%8d" % result.n_not_checked_tests}], - ] - end - - def statistics_header - labels = columns.collect do |label, format_value| - label - end - " " + labels.join(" | ") + " |" - end - - def statistics(result) - items = columns.collect do |label, format_value| - format_value.call(result) - end - " " + items.join(" | ") + " |" - end - - def throughput(result) - if result.elapsed_time.zero? - tests_per_second = 0 - else - tests_per_second = result.n_tests / result.elapsed_time - end - tests_per_second - end - - def report_failure(result) - report_marker(result) - report_diff(result.expected, result.actual) - report_marker(result) - end - - def report_actual(result) - report_marker(result) - puts(result.actual) - report_marker(result) - end - - def report_marker(result) - puts(colorize("=" * @term_width, result)) - end - - def report_diff(expected, actual) - create_temporary_file("expected", expected) do |expected_file| - create_temporary_file("actual", actual) do |actual_file| - diff_options =****@teste*****_options.dup - diff_options.concat(["--label", "(expected)", expected_file.path, - "--label", "(actual)", actual_file.path]) - system(@tester.diff, *diff_options) - end - end - end - - def report_test(worker, result) - report_marker(result) - print("[#{worker.id}] ") if****@teste*****_workers > 1 - puts(worker.suite_name) - print(" #{worker.test_name}") - report_test_result(result, worker.status) - end - - def report_test_result(result, label) - message = test_result_message(result, label) - message_width = string_width(message) - rest_width = @term_width - @current_column - if rest_width > message_width - print(" " * (rest_width - message_width)) - end - puts(message) - end - - def test_result_message(result, label) - elapsed_time = result.elapsed_time - formatted_elapsed_time = "%.4fs" % elapsed_time - formatted_elapsed_time = colorize(formatted_elapsed_time, - elapsed_time_status(elapsed_time)) - " #{formatted_elapsed_time} [#{colorize(label, result)}]" - end - - LONG_ELAPSED_TIME = 1.0 - def long_elapsed_time?(elapsed_time) - elapsed_time >= LONG_ELAPSED_TIME - end - - def elapsed_time_status(elapsed_time) - if long_elapsed_time?(elapsed_time) - elapsed_time_status = :failure - else - elapsed_time_status = :not_checked - end - end - - def justify(message, width) - return " " * width if message.nil? - return message.ljust(width) if message.bytesize <= width - half_width = width / 2.0 - elision_mark = "..." - left = message[0, half_width.ceil - elision_mark.size] - right = message[(message.size - half_width.floor)..-1] - "#{left}#{elision_mark}#{right}" - end - - def print(message) - @current_column += string_width(message.to_s) - @output.print(message) - end - - def puts(*messages) - reset_current_column - @output.puts(*messages) - end - - def reset_current_column - @current_column = 0 - end - - def create_temporary_file(key, content) - file = Tempfile.new("groonga-test-#{key}") - file.print(content) - file.close - yield(file) - end - - def guess_term_width - Integer(guess_term_width_from_env || guess_term_width_from_stty || 79) - rescue ArgumentError - 0 - end - - def guess_term_width_from_env - ENV["COLUMNS"] || ENV["TERM_WIDTH"] - end - - def guess_term_width_from_stty - return nil unless STDIN.tty? - - case tty_info - when /(\d+) columns/ - $1 - when /columns (\d+)/ - $1 - else - nil - end - end - - def tty_info - begin - `stty -a` - rescue SystemCallError - nil - end - end - - def string_width(string) - string.gsub(/\e\[[0-9;]+m/, "").size - end - - def result_status(result) - if result.respond_to?(:status) - result.status - else - if result.n_failed_tests > 0 - :failure - elsif result.n_leaked_tests > 0 - :leaked - elsif result.n_omitted_tests > 0 - :omitted - elsif result.n_not_checked_tests > 0 - :not_checked - else - :success - end - end - end - - def colorize(message, result_or_status) - return message unles****@teste*****_color? - if result_or_status.is_a?(Symbol) - status = result_or_status - else - status = result_status(result_or_status) - end - case status - when :success - "%s%s%s" % [success_color, message, reset_color] - when :failure - "%s%s%s" % [failure_color, message, reset_color] - when :leaked - "%s%s%s" % [leaked_color, message, reset_color] - when :omitted - "%s%s%s" % [omitted_color, message, reset_color] - when :not_checked - "%s%s%s" % [not_checked_color, message, reset_color] - else - message - end - end - - def success_color - escape_sequence({ - :color => :green, - :color_256 => [0, 3, 0], - :background => true, - }, - { - :color => :white, - :color_256 => [5, 5, 5], - :bold => true, - }) - end - - def failure_color - escape_sequence({ - :color => :red, - :color_256 => [3, 0, 0], - :background => true, - }, - { - :color => :white, - :color_256 => [5, 5, 5], - :bold => true, - }) - end - - def leaked_color - escape_sequence({ - :color => :magenta, - :color_256 => [3, 0, 3], - :background => true, - }, - { - :color => :white, - :color_256 => [5, 5, 5], - :bold => true, - }) - end - - def omitted_color - escape_sequence({ - :color => :blue, - :color_256 => [0, 0, 1], - :background => true, - }, - { - :color => :white, - :color_256 => [5, 5, 5], - :bold => true, - }) - end - - def not_checked_color - escape_sequence({ - :color => :cyan, - :color_256 => [0, 1, 1], - :background => true, - }, - { - :color => :white, - :color_256 => [5, 5, 5], - :bold => true, - }) - end - - def reset_color - escape_sequence(:reset) - end - - COLOR_NAMES = [ - :black, :red, :green, :yellow, - :blue, :magenta, :cyan, :white, - ] - def escape_sequence(*commands) - sequence = [] - commands.each do |command| - case command - when :reset - sequence << "0" - when :bold - sequence << "1" - when :italic - sequence << "3" - when :underline - sequence << "4" - when Hash - foreground_p = !command[:background] - if available_colors == 256 - sequence << (foreground_p ? "38" : "48") - sequence << "5" - sequence << pack_256_color(*command[:color_256]) - else - color_parameter = foreground_p ? 3 : 4 - color_parameter += 6 if command[:intensity] - color = COLOR_NAMES.index(command[:color]) - sequence << "#{color_parameter}#{color}" - end - end - end - "\e[#{sequence.join(';')}m" - end - - def pack_256_color(red, green, blue) - red * 36 + green * 6 + blue + 16 - end - - def available_colors - case ENV["COLORTERM"] - when "gnome-terminal" - 256 - else - case ENV["TERM"] - when /-256color\z/ - 256 - else - 8 - end - end - end - end - - class MarkReporter < BaseReporter - def initialize(tester) - super - end - - def on_start(result) - end - - def on_worker_start(worker) - end - - def on_suite_start(worker) - end - - def on_test_start(worker) - end - - def on_test_success(worker, result) - synchronize do - report_test_result_mark(".", result) - end - end - - def on_test_failure(worker, result) - synchronize do - report_test_result_mark("F", result) - puts - report_test(worker, result) - report_failure(result) - end - end - - def on_test_leak(worker, result) - synchronize do - report_test_result_mark("L(#{result.n_leaked_objects})", result) - unless result.checked? - puts - report_test(worker, result) - report_actual(result) - end - end - end - - def on_test_omission(worker, result) - synchronize do - report_test_result_mark("O", result) - puts - report_test(worker, result) - report_actual(result) - end - end - - def on_test_no_check(worker, result) - synchronize do - report_test_result_mark("N", result) - puts - report_test(worker, result) - report_actual(result) - end - end - - def on_test_finish(worker, result) - end - - def on_suite_finish(worker) - end - - def on_worker_finish(worker_id) - end - - def on_finish(result) - puts - puts - report_summary(result) - end - - private - def report_test_result_mark(mark, result) - if @term_width < @current_column + mark.bytesize - puts - end - print(colorize(mark, result)) - if @term_width <= @current_column - puts - else - @output.flush - end - end - end - - class StreamReporter < BaseReporter - def initialize(tester) - super - end - - def on_start(result) - end - - def on_worker_start(worker) - end - - def on_suite_start(worker) - if worker.suite_name.bytesize <= @term_width - puts(worker.suite_name) - else - puts(justify(worker.suite_name, @term_width)) - end - @output.flush - end - - def on_test_start(worker) - print(" #{worker.test_name}") - @output.flush - end - - def on_test_success(worker, result) - report_test_result(result, worker.status) - end - - def on_test_failure(worker, result) - report_test_result(result, worker.status) - report_failure(result) - end - - def on_test_leak(worker, result) - report_test_result(result, worker.status) - report_actual(result) unless result.checked? - end - - def on_test_omission(worker, result) - report_test_result(result, worker.status) - report_actual(result) - end - - def on_test_no_check(worker, result) - report_test_result(result, worker.status) - report_actual(result) - end - - def on_test_finish(worker, result) - end - - def on_suite_finish(worker) - end - - def on_worker_finish(worker_id) - end - - def on_finish(result) - puts - report_summary(result) - end - end - - class InplaceReporter < BaseReporter - def initialize(tester) - super - @last_redraw_time = Time.now - @minimum_redraw_interval = 0.1 - end - - def on_start(result) - @test_suites_result = result - end - - def on_worker_start(worker) - end - - def on_suite_start(worker) - redraw - end - - def on_test_start(worker) - redraw - end - - def on_test_success(worker, result) - redraw - end - - def on_test_failure(worker, result) - redraw do - report_test(worker, result) - report_failure(result) - end - end - - def on_test_leak(worker, result) - redraw do - report_test(worker, result) - report_marker(result) - report_actual(result) unless result.checked? - end - end - - def on_test_omission(worker, result) - redraw do - report_test(worker, result) - report_actual(result) - end - end - - def on_test_no_check(worker, result) - redraw do - report_test(worker, result) - report_actual(result) - end - end - - def on_test_finish(worker, result) - redraw - end - - def on_suite_finish(worker) - redraw - end - - def on_worker_finish(worker) - redraw - end - - def on_finish(result) - draw - puts - report_summary(result) - end - - private - def draw - draw_statistics_header_line - @test_suites_result.workers.each do |worker| - draw_status_line(worker) - draw_test_line(worker) - end - draw_progress_line - end - - def draw_statistics_header_line - puts(statistics_header) - end - - def draw_status_line(worker) - clear_line - left = "[#{colorize(worker.id, worker.result)}] " - right = " [#{worker.status}]" - rest_width = @term_width - @current_column - center_width = rest_width - string_width(left) - string_width(right) - center = justify(worker.suite_name, center_width) - puts("#{left}#{center}#{right}") - end - - def draw_test_line(worker) - clear_line - if worker.test_name - label = " #{worker.test_name}" - else - label = statistics(worker.result) - end - puts(justify(label, @term_width)) - end - - def draw_progress_line - n_done_tests = @test_suites_result.n_tests - n_total_tests = @test_suites_result.n_total_tests - if n_total_tests.zero? - finished_test_ratio = 0.0 - else - finished_test_ratio = n_done_tests.to_f / n_total_tests - end - - start_mark = "|" - finish_mark = "|" - statistics = " [%3d%%]" % (finished_test_ratio * 100) - - progress_width = @term_width - progress_width -= start_mark.bytesize - progress_width -= finish_mark.bytesize - progress_width -= statistics.bytesize - finished_mark = "-" - if n_done_tests == n_total_tests - progress = colorize(finished_mark * progress_width, - @test_suites_result) - else - current_mark = ">" - finished_marks_width = (progress_width * finished_test_ratio).ceil - finished_marks_width -= current_mark.bytesize - finished_marks_width = [0, finished_marks_width].max - progress = finished_mark * finished_marks_width + current_mark - progress = colorize(progress, @test_suites_result) - progress << " " * (progress_width - string_width(progress)) - end - puts("#{start_mark}#{progress}#{finish_mark}#{statistics}") - end - - def redraw - synchronize do - unless block_given? - return if Time.now - @last_redraw_time < @minimum_redraw_interval - end - draw - if block_given? - yield - else - up_n_lines(n_using_lines) - end - @last_redraw_time = Time.now - end - end - - def up_n_lines(n) - print("\e[1A" * n) - end - - def clear_line - print(" " * @term_width) - print("\r") - reset_current_column - end - - def n_using_lines - n_statistics_header_line + n_worker_lines * n_workers + n_progress_lines - end - - def n_statistics_header_line - 1 - end - - def n_worker_lines - 2 - end - - def n_progress_lines - 1 - end - - def n_workers - @tester.n_workers - end - end end end -------------- next part -------------- HTML����������������������������... Télécharger