Test/unit inconsistencies between 1.9 and 1.8

Hello,

We're having problems with ruby 1.9 and test/unit. It looks like when
ObjectSpace is scanned that the methods we are defining aren't being seen.

Any suggestions?

Thanks,
-Adam

% cat 19test.rb
[~/code/planb/root]
require 'test/unit'

class Foo
    attr_reader :attrs
    def initialize
        @attrs = Hash.new
        ("A".."Z").each { |x| @attrs[x] = x.downcase }
    end
end

tclass = Class.new( Test::Unit::TestCase )
Foo.const_set "TestAttr" , tclass

Foo.new.attrs.each_pair do |key,value|
    tclass.class_eval do
        define_method("test_#{key}") do
            assert_equal(key,value.upcase)
        end
    end
end

% /usr/bin/ruby -v
[~/code/planb/root]
ruby 1.8.6 (2007-03-13 patchlevel 0) [i686-darwin8.9.1]
% /usr/bin/ruby 19test.rb
[~/code/planb/root]
Loaded suite 19test
Started
..........................
Finished in 0.002402 seconds.

26 tests, 26 assertions, 0 failures, 0 errors
% /opt/bin/ruby -v
[~/code/planb/root]
ruby 1.9.0 (2007-04-24 patchlevel 0) [i686-darwin8.9.1]
% /opt/bin/ruby 19test.rb
[~/code/planb/root]
Loaded suite 19test
Started
F
Finished in 0.000685 seconds.

  1) Failure:
default_test(Foo::TestAttr)
    [/opt/lib/ruby/1.9/test/unit/assertions.rb:48:in `raise'
     /opt/lib/ruby/1.9/test/unit/assertions.rb:48:in `block in assert_block'
     /opt/lib/ruby/1.9/test/unit/assertions.rb:495:in `_wrap_assertion'
     /opt/lib/ruby/1.9/test/unit/assertions.rb:11240:in `assert_block'
     /opt/lib/ruby/1.9/test/unit/assertions.rb:313:in `flunk'
     /opt/lib/ruby/1.9/test/unit/testcase.rb:107:in `default_test'
     /opt/lib/ruby/1.9/test/unit/testcase.rb:76:in `run'
     /opt/lib/ruby/1.9/test/unit/testsuite.rb:34:in `block in run'
     /opt/lib/ruby/1.9/test/unit/testsuite.rb:33:in `each'
     /opt/lib/ruby/1.9/test/unit/testsuite.rb:33:in `run'
     /opt/lib/ruby/1.9/test/unit/testsuite.rb:34:in `block in run'
     /opt/lib/ruby/1.9/test/unit/testsuite.rb:33:in `each'
     /opt/lib/ruby/1.9/test/unit/testsuite.rb:33:in `run'
     /opt/lib/ruby/1.9/test/unit/ui/testrunnermediator.rb:46:in `run_suite'
     /opt/lib/ruby/1.9/test/unit/ui/console/testrunner.rb:67:in
`start_mediator'
     /opt/lib/ruby/1.9/test/unit/ui/console/testrunner.rb:41:in `start'
     /opt/lib/ruby/1.9/test/unit/ui/testrunnerutilities.rb:29:in `run'
     /opt/lib/ruby/1.9/test/unit/autorunner.rb:215:in `run'
     /opt/lib/ruby/1.9/test/unit/autorunner.rb:12:in `run'
     /opt/lib/ruby/1.9/test/unit.rb:278:in `block in <top (required)>']:
No tests were specified.

1 tests, 1 assertions, 1 failures, 0 errors

I located the problem, below is a small patch ( copy & paste from 1.8sources ).

It appears that a block/proc with no arguments has arity -1.

irb(main):001:0> proc { }.arity
=> -1
irb(main):002:0> proc {|| }.arity
=> -1

and that somebody forgot about that below.

-Adam

Index: lib/test/unit/testcase.rb

···

===================================================================
--- lib/test/unit/testcase.rb (revision 12221)
+++ lib/test/unit/testcase.rb (working copy)
@@ -37,7 +37,9 @@
       # Creates a new instance of the fixture for running the
       # test represented by test_method_name.
       def initialize(test_method_name)
- unless(respond_to?(test_method_name) &&
method(test_method_name).arity == 0)
+ unless(respond_to?(test_method_name) and
+ (method(test_method_name).arity == 0 ||
+ method(test_method_name).arity == -1))
           throw :invalid_test
         end
         @method_name = test_method_name

Awesome. Please post the patch to the ruby project on rubyforge.org.

thanks!

···

On Apr 25, 2007, at 23:56 , Adam Bozanich wrote:

I located the problem, below is a small patch ( copy & paste from 1.8sources ).

[...]

?
AFAIK #arity was redefined in 1.9 to return 0 for Procs with no arguments.
That patch was applied to 1.8 three years ago but it's not supposed to be
needed on 1.9, see [ruby-core:2829].

Also,

RUBY_VERSION # => "1.9.0"
RUBY_RELEASE_DATE # => "2007-02-07"
proc{}.arity # => 0
proc{||}.arity # => 0
Proc.new{}.arity # => 0
require 'test/unit'
class TC < Test::Unit::TestCase
  define_method("test_foo"){ assert true }
end
# >> Loaded suite -
# >> Started
# >> .
# >> Finished in 0.001363 seconds.
# >>
# >> 1 tests, 1 assertions, 0 failures, 0 errors

I can't see any recent reference to arity in the Changelog, and
proc_arity is identical to the one in my build:
http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/proc.c?revision=12212&view=markup

Has this really changed in the last couple months? If so, there's a bug,
either in the Rdoc documentation or the code.

···

On Thu, Apr 26, 2007 at 03:56:25PM +0900, Adam Bozanich wrote:

I located the problem, below is a small patch ( copy & paste from
1.8sources ).

It appears that a block/proc with no arguments has arity -1.

irb(main):001:0> proc { }.arity
=> -1
irb(main):002:0> proc {|| }.arity
=> -1

and that somebody forgot about that below.

-Adam

Index: lib/test/unit/testcase.rb

--- lib/test/unit/testcase.rb (revision 12221)
+++ lib/test/unit/testcase.rb (working copy)

--
Mauricio Fernandez - http://eigenclass.org - singular Ruby
                        ** Latest postings **
On GC and finalizers in Ruby, corrected weak hash table implementations
  http://eigenclass.org/hiki/deferred-finalizers-in-Ruby
simplefold: better vim folding (Ruby, Objective Caml, Perl, PHP, Java)
  http://eigenclass.org/hiki/simplefold

Strange, must be a regression.

irb(main):001:0> RUBY_VERSION
=> "1.9.0"
irb(main):002:0> RUBY_RELEASE_DATE
=> "2007-04-26"
irb(main):003:0> proc{}.arity
=> -1
irb(main):004:0> proc{||}.arity
=> -1
irb(main):005:0> Proc.new{}.arity
=> -1

···

On 4/26/07, Mauricio Fernandez <mfp@acm.org> wrote:

?
AFAIK #arity was redefined in 1.9 to return 0 for Procs with no arguments.
That patch was applied to 1.8 three years ago but it's not supposed to be
needed on 1.9, see [ruby-core:2829].

Also,

RUBY_VERSION # => "1.9.0"
RUBY_RELEASE_DATE # => "2007-02-07"
proc{}.arity # => 0
proc{||}.arity # => 0
Proc.new{}.arity # => 0

>RUBY_VERSION # => "1.9.0"
>RUBY_RELEASE_DATE # => "2007-02-07"
>proc{}.arity # => 0
>proc{||}.arity # => 0
>Proc.new{}.arity # => 0

Strange, must be a regression.

irb(main):001:0> RUBY_VERSION
=> "1.9.0"
irb(main):002:0> RUBY_RELEASE_DATE
=> "2007-04-26"
irb(main):003:0> proc{}.arity
=> -1
irb(main):004:0> proc{||}.arity
=> -1
irb(main):005:0> Proc.new{}.arity
=> -1

Yes, I've traced it back to this:

···

On Thu, Apr 26, 2007 at 06:56:45PM +0900, Adam Bozanich wrote:

On 4/26/07, Mauricio Fernandez <mfp@acm.org> wrote:

Wed Mar 21 20:05:07 2007 Koichi Sasada <ko1@atdot.net>

  * compile.c, parse.y, eval.c, intern.h, iseq.c, lex.c, node.h,
    proc.c, vm.c, vm_macro.def, vm_macro.def, yarvcore.c, yarvcore.h,
    debug.c, debug.h: merge half-baked-1.9 changes. The biggest change
    is to change node structure around NODE_SCOPE, NODE_ARGS. Every
    scope (method/class/block) has own NODE_SCOPE node and NODE_ARGS
    represents more details of arguments information. I'll write a
    document about detail of node structure.

I've sent a bug report to ruby-core.

--
Mauricio Fernandez - http://eigenclass.org - singular Ruby
                        ** Latest postings **
On GC and finalizers in Ruby, corrected weak hash table implementations
  http://eigenclass.org/hiki/deferred-finalizers-in-Ruby
simplefold: better vim folding (Ruby, Objective Caml, Perl, PHP, Java)
  http://eigenclass.org/hiki/simplefold