overload method in module_eval, how?

S

Simon Strandgaard

I want to overload a testcase method with debug-enabling wrapper.
But it doesn't seems like my Object#debug method gets called at all.

Any ideas how to do this ?

--
Simon Strandgaard


server> ruby test_dbg.rb
Loaded suite TestDbg
Started
F
Finished in 0.008819 seconds.

1) Failure:
default_test(TestDbg) [test_dbg.rb:31]:
No tests were specified.

1 tests, 1 assertions, 1 failures, 0 errors
server> expand -t2 test_dbg.rb
require 'test/unit'

class Object
def self.debug(*args)
args.each{|method|
name = method.id2name
org = "_debug_"+name
code=<<MSG
alias #{org} #{name}
def #{name}(*a,&b)
$stdout.puts("before")
#{org}(*a,&b)
$stdout.puts("after")
end
private :#{org}
MSG
module_eval code
}
end
end

class TestDbg < Test::Unit::TestCase
def test_x
assert_equal(true, true)
end
debug :test_x # uncomment me, and it works!
end

if $0 == __FILE__
require 'test/unit/ui/console/testrunner'
Test::Unit::UI::Console::TestRunner.run(TestDbg)
end
server>
 
T

ts

S> class Object
S> def self.debug(*args)
S> args.each{|method|
S> name = method.id2name
S> org = "_debug_"+name
S> code=<<MSG
S> alias #{org} #{name}
S> def #{name}(*a,&b)

def #{name}(&b)

S> $stdout.puts("before")
S> #{org}(*a,&b)

#{org}(&b)

S> $stdout.puts("after")
S> end
S> private :#{org}
S> MSG
S> module_eval code
S> }
S> end
S> end

S> class TestDbg < Test::Unit::TestCase
S> def test_x

The arity for a test method must be == 0
 
S

Simon Strandgaard

[snip]
S> def #{name}(*a,&b)

def #{name}(&b) [snip]
S> #{org}(*a,&b)

#{org}(&b)

The arity for a test method must be == 0

Thanks Guy.

Though, now I don't understand why my example didn't work?
How to make it general so it works for an arbitrary number of arguments ?
 
T

ts

S> Though, now I don't understand why my example didn't work?

Because the new method that you have defined was

def test_x(*a, b)
end

This give an arity -1, and runit reject these methods it keep only methods
with a zero arity


S> How to make it general so it works for an arbitrary number of arguments ?

You *can't* give an arbitrary number of arguments for a test method
 
S

Simon Strandgaard

S> Though, now I don't understand why my example didn't work?

Because the new method that you have defined was

def test_x(*a, b)
end

This give an arity -1, and runit reject these methods it keep only methods
with a zero arity


S> How to make it general so it works for an arbitrary number of arguments ?

You *can't* give an arbitrary number of arguments for a test method

DrainBammage, thats obvious. Thanks.

BTW: I wonder why the last "p instance_methods" doesn't output anything?

--
Simon Strandgaard

server> ruby test_dbg.rb
["test_x"]
Loaded suite test_dbg
Started
..
Finished in 0.002346 seconds.

1 tests, 1 assertions, 0 failures, 0 errors
server> expand -t2 test_dbg.rb
require 'test/unit'

class Object
def self.debug(*args)
p instance_methods(false)
args.each{|method|
name = method.id2name
org = "_debug_"+name
arguments = (method.arity > 0) ? "(*a,&b)" : "(&b)"
code=<<MSG
alias #{org} #{name}
def #{name}#{arguments}
$stdout.puts("before")
#{org}#{arguments}
$stdout.puts("after")
end
private :#{org}
MSG
module_eval code
}
p instance_methods(false) # No output, why ?
end
end

class TestDbg < Test::Unit::TestCase
def test_x
assert_equal(true, true)
end
debug :test_x
end

if $0 == __FILE__
require 'test/unit/ui/console/testrunner'
Test::Unit::UI::Console::TestRunner.run(TestDbg)
end
server>
 
T

ts

S> BTW: I wonder why the last "p instance_methods" doesn't output anything?

I don't understand, you want to say that you don't see this ?

server> ruby test_dbg.rb
S> ["test_x"]
^^^^^^^^^^
 
S

Simon Strandgaard

S> BTW: I wonder why the last "p instance_methods" doesn't output anything?

I don't understand, you want to say that you don't see this ?

server> ruby test_dbg.rb
S> ["test_x"]
^^^^^^^^^^

I do a print both before and after. Only the first print statement
outputs something. The second doesn't output anything?

It should output the same as the first print-statement, but I get nothing.

any ideas to what can cause such a problem ?
 
T

ts

S> any ideas to what can cause such a problem ?

S> args.each{|method|
S> name = method.id2name
S> org = "_debug_"+name
S> arguments = (method.arity > 0) ? "(*a,&b)" : "(&b)"

svg% ruby -e 'def test_x() end; :test_x.arity'
-e:1: undefined method `arity' for :test_x:Symbol (NoMethodError)
svg%

svg% ruby -e 'def test_x() end; p method:)test_x).arity'
0
svg%

and you can have an arity < 0
 
S

Simon Strandgaard

S> any ideas to what can cause such a problem ?

S> args.each{|method|
S> name = method.id2name
S> org = "_debug_"+name
S> arguments = (method.arity > 0) ? "(*a,&b)" : "(&b)"

svg% ruby -e 'def test_x() end; :test_x.arity'
-e:1: undefined method `arity' for :test_x:Symbol (NoMethodError)
svg%

svg% ruby -e 'def test_x() end; p method:)test_x).arity'
0
svg%

and you can have an arity < 0

changing so it becomes (arity != 0), will that be ok?

Still only the first output statement are working.
I don't understand why the successive print-statements doesn't output
anything. Any hints ?


--
Simon Strandgaard

server> ruby test_dbg.rb
["test_x"]
Loaded suite test_dbg
Started
..
Finished in 0.003568 seconds.

1 tests, 1 assertions, 0 failures, 0 errors
server> expand -t2 test_dbg.rb
require 'test/unit'

class Object
def self.debug(*args)
p instance_methods(false)
args.each{|m|
name = m.id2name
org = "_debug_"+name
n = method(m).arity
puts "method=#{name} arity=#{n}" # No output, why ?
arguments = (n != 0) ? "(*a,&b)" : "(&b)"
code=<<MSG
alias #{org} #{name}
def #{name}#{arguments}
$stdout.puts("before")
#{org}#{arguments}
$stdout.puts("after")
end
private :#{org}
MSG
module_eval code
}
p instance_methods(false) # No output, why ?
end
end

class TestDbg < Test::Unit::TestCase
def test_x
assert_equal(true, true)
end
debug :test_x
end

require 'test/unit/ui/console/testrunner'
Test::Unit::UI::Console::TestRunner.run(TestDbg)
server>
 
T

ts

S> Still only the first output statement are working.
S> I don't understand why the successive print-statements doesn't output
S> anything. Any hints ?


I've given the hint : method is a Symbol, and the method Symbol#arity is
not defined.

You must first call Kernel#method with the symbol as argument and then
call arity

svg% ruby -e 'def test_x() end; method = :test_x; p method(method).class'
Method
svg%

svg% ruby -e 'def test_x() end; method = :test_x; p method(method).arity'
0
svg%
 
S

Simon Strandgaard

S> Still only the first output statement are working.
S> I don't understand why the successive print-statements doesn't output
S> anything. Any hints ?


I've given the hint : method is a Symbol, and the method Symbol#arity is
not defined.

You must first call Kernel#method with the symbol as argument and then
call arity

svg% ruby -e 'def test_x() end; method = :test_x; p method(method).class'
Method
svg%

svg% ruby -e 'def test_x() end; method = :test_x; p method(method).arity'
0
svg%

I think I do symbol2method lookup wrong. How does I lookup
the symbol in the instance namespace ?

--
Simon Strandgaard


server> ruby test_dbg.rb
["test_x"]
symbol = test_x
ERROR: symbol2method failure, #<NameError: undefined method `test_x' for class `Class'>
method =
method.class = NilClass
Loaded suite test_dbg
Started
..
Finished in 0.002409 seconds.

1 tests, 1 assertions, 0 failures, 0 errors
server> expand -t2 test_dbg.rb
require 'test/unit'

class Object
def self.debug(*args)
p instance_methods(false)
args.each{|symbol|
puts "symbol = #{symbol}"

begin
meth = method(symbol)
rescue => e
puts "ERROR: symbol2method failure, " + e.inspect
end
puts "method = #{meth}"
puts "method.class = #{meth.class}"

n = meth.arity
puts "arity=#{n}"

name = symbol.id2name
org = "_debug_"+name
arguments = (n != 0) ? "(*a,&b)" : "(&b)"
code=<<MSG
alias #{org} #{name}
def #{name}#{arguments}
$stdout.puts("before")
#{org}#{arguments}
$stdout.puts("after")
end
private :#{org}
MSG
module_eval code
}
p instance_methods(false)
end
end

class TestDbg < Test::Unit::TestCase
def test_x
assert_equal(true, true)
end
debug :test_x
end

require 'test/unit/ui/console/testrunner'
Test::Unit::UI::Console::TestRunner.run(TestDbg)
server>
 
T

ts

S> class Object
S> def self.debug(*args)
S> p instance_methods(false)
S> args.each{|symbol|
S> puts "symbol = #{symbol}"
S> begin
S> meth = method(symbol)

meth = instance_method(symbol)

S> rescue => e
S> puts "ERROR: symbol2method failure, " + e.inspect
S> end
 
S

Simon Strandgaard

S> class Object
S> def self.debug(*args)
S> p instance_methods(false)
S> args.each{|symbol|
S> puts "symbol = #{symbol}"
S> begin
S> meth = method(symbol)

meth = instance_method(symbol)

S> rescue => e
S> puts "ERROR: symbol2method failure, " + e.inspect
S> end

Guy you are ruby-wizard #1.
All my problems has been swept away.

Thanks.. you have helped so many times.. I think I+others own you
some beers someday ;-)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,983
Messages
2,570,187
Members
46,747
Latest member
jojoBizaroo

Latest Threads

Top