From 818d6a1e4f145f3ff9a60933f71336a034c59536 Mon Sep 17 00:00:00 2001 From: matz Date: Thu, 6 Nov 2003 07:22:39 +0000 Subject: * eval.c (rb_load): allow interrupt during loaded program evaluation. [ruby-dev:21834] * hash.c (rb_hash_fetch): always warn if default argument and a block are supplied at the same time. [ruby-dev:21842] * hash.c (env_fetch): ditto. * array.c (rb_ary_fetch): ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4910 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 12 ++ array.c | 12 +- eval.c | 19 +--- ext/pty/expect_sample.rb | 15 ++- hash.c | 24 ++-- lib/cgi.rb | 16 ++- lib/drb/drb.rb | 1 + lib/test/unit/autorunner.rb | 4 + lib/test/unit/ui/tk/testrunner.rb | 225 ++++++++++++++++++++++++++++++++++++++ 9 files changed, 278 insertions(+), 50 deletions(-) create mode 100644 lib/test/unit/ui/tk/testrunner.rb diff --git a/ChangeLog b/ChangeLog index a6877fe511..0572ef6b23 100644 --- a/ChangeLog +++ b/ChangeLog @@ -35,6 +35,18 @@ Wed Nov 5 22:55:16 2003 Hidetoshi NAGAI * ext/tk/lib/tk.rb : add TkMenu#set_focus support Tcl/Tk's tk_menuSetFocus +Wed Nov 5 17:33:45 2003 Yukihiro Matsumoto + + * eval.c (rb_load): allow interrupt during loaded program + evaluation. [ruby-dev:21834] + + * hash.c (rb_hash_fetch): always warn if default argument and a + block are supplied at the same time. [ruby-dev:21842] + + * hash.c (env_fetch): ditto. + + * array.c (rb_ary_fetch): ditto. + Wed Nov 5 19:08:47 2003 Nobuyoshi Nakada * lib/optparse.rb (OptionParser::Switch::PlacedArgument::parse): diff --git a/array.c b/array.c index ac2bb7d265..ba030bf468 100644 --- a/array.c +++ b/array.c @@ -595,21 +595,21 @@ rb_ary_fetch(argc, argv, ary) VALUE ary; { VALUE pos, ifnone; + long block_given; long idx; rb_scan_args(argc, argv, "11", &pos, &ifnone); + block_given = rb_block_given_p(); + if (block_given && argc == 2) { + rb_warn("block supersedes default value argument"); + } idx = NUM2LONG(pos); if (idx < 0) { idx += RARRAY(ary)->len; } if (idx < 0 || RARRAY(ary)->len <= idx) { - if (rb_block_given_p()) { - if (argc > 1) { - rb_raise(rb_eArgError, "wrong number of arguments"); - } - return rb_yield(pos); - } + if (block_given) return rb_yield(pos); if (argc == 1) { rb_raise(rb_eIndexError, "index %ld out of array", idx); } diff --git a/eval.c b/eval.c index f8543a41f9..48b133ed76 100644 --- a/eval.c +++ b/eval.c @@ -5836,11 +5836,11 @@ rb_load(fname, wrap) ruby_in_eval--; node = ruby_eval_tree; rb_thread_critical = critical; + ALLOW_INTS; if (ruby_nerrs == 0) { eval_node(self, node); } } - ALLOW_INTS; ruby_frame->last_func = last_func; ruby_current_node = last_node; ruby_sourcefile = 0; @@ -9812,22 +9812,6 @@ rb_thread_trap_eval(cmd, sig) VALUE cmd; int sig; { -#if 0 - rb_thread_critical = 0; - if (!rb_thread_dead(curr_thread)) { - rb_thread_ready(curr_thread); - rb_trap_eval(cmd, sig); - return; - } - rb_thread_ready(main_thread); - if (THREAD_SAVE_CONTEXT(curr_thread)) { - return; - } - th_cmd = cmd; - th_sig = sig; - curr_thread = main_thread; - rb_thread_restore_context(curr_thread, RESTORE_TRAP); -#else rb_thread_critical = 0; if (!rb_thread_dead(curr_thread)) { if (THREAD_SAVE_CONTEXT(curr_thread)) { @@ -9838,7 +9822,6 @@ rb_thread_trap_eval(cmd, sig) th_sig = sig; curr_thread = main_thread; rb_thread_restore_context(curr_thread, RESTORE_TRAP); -#endif } static VALUE diff --git a/ext/pty/expect_sample.rb b/ext/pty/expect_sample.rb index 1311476c5d..bf8a2352fe 100644 --- a/ext/pty/expect_sample.rb +++ b/ext/pty/expect_sample.rb @@ -4,17 +4,16 @@ # by A. Ito # # This program reports the latest version of ruby interpreter -# by connecting to ftp server at netlab.co.jp. +# by connecting to ftp server at ruby-lang.org. # require 'pty' require 'expect' fnames = [] -PTY.spawn("ftp ftp.netlab.co.jp") do - |r_f,w_f,pid| +PTY.spawn("ftp ftp.ruby-lang.org") do |r_f,w_f,pid| w_f.sync = true - $expect_verbose = true + $expect_verbose = false r_f.expect(/^Name.*: /) do w_f.print "ftp\n" @@ -31,14 +30,14 @@ PTY.spawn("ftp ftp.netlab.co.jp") do r_f.expect('word:') do w_f.print username+"@\n" end - r_f.expect("ftp> ") do - w_f.print "cd pub/lang/ruby\n" + r_f.expect("> ") do + w_f.print "cd pub/ruby\n" end - r_f.expect("ftp> ") do + r_f.expect("> ") do w_f.print "dir\n" end - r_f.expect("ftp> ") do |output| + r_f.expect("> ") do |output| for x in output[0].split("\n") if x =~ /(ruby.*\.tar\.gz)/ then fnames.push $1 diff --git a/hash.c b/hash.c index 2743ad0e24..75c07797d3 100644 --- a/hash.c +++ b/hash.c @@ -300,16 +300,16 @@ rb_hash_fetch(argc, argv, hash) { VALUE key, if_none; VALUE val; + long block_given; rb_scan_args(argc, argv, "11", &key, &if_none); + block_given = rb_block_given_p(); + if (block_given && argc == 2) { + rb_warn("block supersedes default value argument"); + } if (!st_lookup(RHASH(hash)->tbl, key, &val)) { - if (rb_block_given_p()) { - if (argc > 1) { - rb_raise(rb_eArgError, "wrong number of arguments"); - } - return rb_yield(key); - } + if (block_given) return rb_yield(key); if (argc == 1) { rb_raise(rb_eIndexError, "key not found"); } @@ -1086,9 +1086,14 @@ env_fetch(argc, argv) VALUE *argv; { VALUE key, if_none; + long block_given; char *nam, *env; rb_scan_args(argc, argv, "11", &key, &if_none); + block_given = rb_block_given_p(); + if (block_given && argc == 2) { + rb_warn("block supersedes default value argument"); + } StringValue(key); nam = RSTRING(key)->ptr; if (strlen(nam) != RSTRING(key)->len) { @@ -1096,12 +1101,7 @@ env_fetch(argc, argv) } env = getenv(nam); if (!env) { - if (rb_block_given_p()) { - if (argc > 1) { - rb_raise(rb_eArgError, "wrong number of arguments"); - } - return rb_yield(key); - } + if (block_given) return rb_yield(key); if (argc == 1) { rb_raise(rb_eIndexError, "key not found"); } diff --git a/lib/cgi.rb b/lib/cgi.rb index 43a5aa89f0..fc94772948 100644 --- a/lib/cgi.rb +++ b/lib/cgi.rb @@ -984,7 +984,7 @@ class CGI raise EOFError, "bad content body" end - until -1 == content_length + loop do head = nil if 10240 < content_length require "tempfile" @@ -1020,14 +1020,13 @@ class CGI else stdinput.read(content_length) or '' end - buf += c + buf.concat(c) content_length -= c.size - end buf = buf.sub(/\A((?:.|\n)*?)(?:#{EOL})?#{boundary}(#{EOL}|--)/n) do body.print $1 - if "--" == $2 or EOL == $2 + if "--" == $2 content_length = -1 end "" @@ -1072,7 +1071,8 @@ class CGI else params[name] = [body] end - + break if buf.size == 0 + break if content_length === -1 end params @@ -1115,6 +1115,7 @@ class CGI @multipart = true @params = read_multipart(boundary, Integer(env_table['CONTENT_LENGTH'])) else + @multipart = false @params = CGI::parse( case env_table['REQUEST_METHOD'] when "GET", "HEAD" @@ -1133,10 +1134,13 @@ class CGI end @cookies = CGI::Cookie::parse((env_table['HTTP_COOKIE'] or env_table['COOKIE'])) - end private :initialize_query + def multipart? + @multipart + end + class Value < String # :nodoc: def initialize(str, params) @params = params diff --git a/lib/drb/drb.rb b/lib/drb/drb.rb index fda18401dd..5eb7345e1b 100644 --- a/lib/drb/drb.rb +++ b/lib/drb/drb.rb @@ -1295,6 +1295,7 @@ module DRb end def run + raise if Thread.critical Thread.start do begin while true diff --git a/lib/test/unit/autorunner.rb b/lib/test/unit/autorunner.rb index 803dc27d8b..3f17fadcf5 100644 --- a/lib/test/unit/autorunner.rb +++ b/lib/test/unit/autorunner.rb @@ -29,6 +29,10 @@ module Test require 'test/unit/ui/fox/testrunner' Test::Unit::UI::Fox::TestRunner.run(r.suite) end, + :tk => proc do |r| + require 'test/unit/ui/tk/testrunner' + Test::Unit::UI::Tk::TestRunner.run(r.suite) + end, } OUTPUT_LEVELS = { diff --git a/lib/test/unit/ui/tk/testrunner.rb b/lib/test/unit/ui/tk/testrunner.rb new file mode 100644 index 0000000000..adf5a10222 --- /dev/null +++ b/lib/test/unit/ui/tk/testrunner.rb @@ -0,0 +1,225 @@ +# :nodoc: +# +# Original Author:: Nathaniel Talbott. +# Author:: Kazuhiro NISHIYAMA. +# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved. +# Copyright:: Copyright (c) 2003 Kazuhiro NISHIYAMA. All rights reserved. +# License:: Ruby license. + +require 'tk' +require 'test/unit/ui/testrunnermediator' +require 'test/unit/ui/testrunnerutilities' + +module Test + module Unit + module UI + module Tk # :nodoc: + + # Runs a Test::Unit::TestSuite in a Tk UI. Obviously, + # this one requires you to have Tk + # and the Ruby Tk extension installed. + class TestRunner + extend TestRunnerUtilities + + # Creates a new TestRunner and runs the suite. + def self.run(suite) + new(suite).start + + end + + # Creates a new TestRunner for running the passed + # suite. + def initialize(suite) + if (suite.respond_to?(:suite)) + @suite = suite.suite + else + @suite = suite + end + + @red = false + @fault_detail_list = [] + @run_suite_thread = nil + end + + # Begins the test run. + def start + setup_ui + setup_mediator + attach_to_mediator + start_ui + end + + private + def setup_mediator # :nodoc: + @mediator = TestRunnerMediator.new(@suite) + suite_name = @suite.to_s + if ( @suite.kind_of?(Module) ) + suite_name = @suite.name + end + @suite_name_entry.value = suite_name + end + + def attach_to_mediator # :nodoc: + @run_button.command(method(:run_suite)) + @fault_list.bind('ButtonPress-1', proc{|y| + fault = @fault_detail_list[@fault_list.nearest(y)] + if fault + show_fault(fault) + end + }, '%y') + @mediator.add_listener(TestRunnerMediator::RESET, &method(:reset_ui)) + @mediator.add_listener(TestResult::FAULT, &method(:add_fault)) + @mediator.add_listener(TestResult::CHANGED, &method(:result_changed)) + @mediator.add_listener(TestRunnerMediator::STARTED, &method(:started)) + @mediator.add_listener(TestCase::STARTED, &method(:test_started)) + @mediator.add_listener(TestRunnerMediator::FINISHED, &method(:finished)) + end + + def start_ui # :nodoc: + run_suite + begin + ::Tk.mainloop + rescue Exception + if @run_suite_thread and @run_suite_thread.alive? + @run_suite_thread.raise $! + retry + else + raise + end + end + end + + def stop # :nodoc: + ::Tk.exit + end + + def reset_ui(count) # :nodoc: + @test_total_count = count.to_f + @test_progress_bar.configure('background'=>'green') + @test_progress_bar.place('relwidth'=>0/count) + @red = false + + @test_count_label.value = 0 + @assertion_count_label.value = 0 + @failure_count_label.value = 0 + @error_count_label.value = 0 + + @fault_list.delete(0, 'end') + @fault_detail_list = [] + clear_fault + end + + def add_fault(fault) # :nodoc: + if ( ! @red ) + @test_progress_bar.configure('background'=>'red') + @red = true + end + @fault_detail_list.push fault + @fault_list.insert('end', fault.short_display) + end + + def show_fault(fault) # :nodoc: + raw_show_fault(fault.long_display) + end + + def raw_show_fault(string) # :nodoc: + @detail_text.value = string + end + + def clear_fault # :nodoc: + raw_show_fault("") + end + + def result_changed(result) # :nodoc: + @test_count_label.value = result.run_count + @test_progress_bar.place('relwidth'=>result.run_count/@test_total_count) + @assertion_count_label.value = result.assertion_count + @failure_count_label.value = result.failure_count + @error_count_label.value = result.error_count + end + + def started(result) # :nodoc: + output_status("Started...") + end + + def test_started(test_name) + output_status("Running #{test_name}...") + end + + def finished(elapsed_time) + output_status("Finished in #{elapsed_time} seconds") + end + + def output_status(string) # :nodoc: + @status_entry.value = string + end + + def setup_ui # :nodoc: + @status_entry = TkVariable.new + l = TkLabel.new(nil, 'textvariable'=>@status_entry, 'relief'=>'sunken') + l.pack('side'=>'bottom', 'fill'=>'x') + + suite_frame = TkFrame.new.pack('fill'=>'x') + + @run_button = TkButton.new(suite_frame, 'text'=>'Run') + @run_button.pack('side'=>'right') + + TkLabel.new(suite_frame, 'text'=>'Suite:').pack('side'=>'left') + @suite_name_entry = TkVariable.new + l = TkLabel.new(suite_frame, 'textvariable'=>@suite_name_entry, 'relief'=>'sunken') + l.pack('side'=>'left', 'fill'=>'x', 'expand'=>true) + + f = TkFrame.new(nil, 'relief'=>'sunken', 'borderwidth'=>3, 'height'=>20).pack('fill'=>'x', 'padx'=>1) + @test_progress_bar = TkFrame.new(f, 'background'=>'green').place('anchor'=>'nw', 'relwidth'=>0.0, 'relheight'=>1.0) + + info_frame = TkFrame.new.pack('fill'=>'x', 'expand'=>true) + @test_count_label = create_count_label(info_frame, 'Tests:') + @assertion_count_label = create_count_label(info_frame, 'Assertions:') + @failure_count_label = create_count_label(info_frame, 'Failures:') + @error_count_label = create_count_label(info_frame, 'Errors:') + + fault_list_frame = TkFrame.new.pack('fill'=>'both', 'expand'=>true) + + fault_scrollbar = TkScrollbar.new(fault_list_frame) + fault_scrollbar.pack('side'=>'right', 'fill'=>'y') + @fault_list = TkListbox.new(fault_list_frame) + @fault_list.pack('fill'=>'both', 'expand'=>true) + @fault_list.yscrollbar(fault_scrollbar) + + detail_frame = TkFrame.new.pack('fill'=>'both', 'expand'=>true) + detail_scrollbar_y = TkScrollbar.new(detail_frame) + detail_scrollbar_y.pack('side'=>'right', 'fill'=>'y') + detail_scrollbar_x = TkScrollbar.new(detail_frame) + detail_scrollbar_x.pack('side'=>'bottom', 'fill'=>'x') + @detail_text = TkText.new(detail_frame, 'height'=>10, 'wrap'=>'none') { + bindtags(bindtags - [TkText]) + } + @detail_text.pack('fill'=>'both', 'expand'=>true) + @detail_text.yscrollbar(detail_scrollbar_y) + @detail_text.xscrollbar(detail_scrollbar_x) + end + + def create_count_label(parent, label) # :nodoc: + TkLabel.new(parent, 'text'=>label).pack('side'=>'left', 'expand'=>true) + v = TkVariable.new(0) + TkLabel.new(parent, 'textvariable'=>v).pack('side'=>'left', 'expand'=>true) + v + end + + def run_suite # :nodoc: + run_proc = proc { + @run_suite_thread = Thread.start { + @mediator.run_suite + } + } + TkAfter.new(1000, 1, run_proc).start + end + end + end + end + end +end + +if __FILE__ == $0 + Test::Unit::UI::Tk::TestRunner.start_command_line_test +end -- cgit v1.2.3