Projects

Ticket #336 (new defect)

Opened 2 years ago

Last modified 11 months ago

Defining a method with a colon somewhere in the name and whitespace at the end will loose the trailing whitespace. (was: NoMethodError with shoulda tests)

Reported by: macruby@… Owned by: lsansonetti@…
Priority: major Milestone: MacRuby 1.0
Component: MacRuby Keywords: #reduction
Cc: kayla.rosebud@…

Description

When running shoulda tests a NoMethodError is raised, not quite sure how/why as it looks like the test passes.

Attachments

macruby.shoulda.rb Download (0.6 KB) - added by macruby@… 2 years ago.
Shoulda test example
tc_foo.rb Download (314 bytes) - added by mike@… 21 months ago.
Simple test case with no Cocoa dependency

Change History

Changed 2 years ago by macruby@…

Shoulda test example

  Changed 2 years ago by macruby@…

Apologies for the extremely bad formatting, here is a slightly better formatted version

require 'test/unit'
require 'rubygems'
require 'shoulda'
require 'shoulda/test_unit'

framework 'Foundation'

class MacRubyShouldaTest < Test::Unit::TestCase
  context "NSString instance" do
    setup do
      @string = NSString.stringWithString("~/Documents")
    end
    should "expand tilde in path" do
      assert @string.stringByExpandingTildeInPath.isEqualToString("#{ENV['HOME']}/Documents")
    end
  end
end

with the output of

Started
E.
Finished in 0.096728 seconds.

  1) Error:
test: NSString instance should expand tilde in path.(MacRubyShouldaTest):
NoMethodError: undefined method `test: NSString instance should expand tilde in path.' for #<MacRubyShouldaTest:0x2004db7c0>
    0:in `send:'
    0:in `run:'
    0:in `each'
    0:in `each'
    0:in `run_test_suites:'
    0:in `run:'

2 tests, 1 assertions, 0 failures, 1 errors, 0 skips

  Changed 2 years ago by eloy.de.enige@…

Thanks for the report!

In the meantime you could give Bacon a try if you want. It's a sweet lean test framework and all of it's tests run on MacRuby 0.5. However, until a new version is released you will have to grab the HEAD version from:  http://github.com/chneukirchen/bacon

follow-up: ↓ 4   Changed 2 years ago by macruby@…

Thanks, not sure what I've done now but I can't seem to get macruby or macirb to load any gems at all. Can't work out why as it was working this morning.

in reply to: ↑ 3   Changed 2 years ago by macruby@…

Replying to macruby@…:

Thanks, not sure what I've done now but I can't seem to get macruby or macirb to load any gems at all. Can't work out why as it was working this morning.

Noticed that rip was in my $LOAD_PATH so I've installed Bacon with that, working much more smoothly now.

  Changed 2 years ago by eloy.de.enige@…

Great tip, thanks!

  Changed 21 months ago by lsansonetti@…

  • milestone MacRuby 0.5 deleted

We need a reduction for that problem.

Changed 21 months ago by mike@…

Simple test case with no Cocoa dependency

  Changed 21 months ago by mike@…

I've been trying to create a reduction, but haven't been successful yet. I have gotten closer to the problem though.

In shoulda/context.rb in create_test_from_should_hash (line 337) shoulda binds the new method names to the test class. In MacRuby, something goes wrong here. We end up with two new methods bound instead of one and they have slightly different names. In Ruby 1.9, we just get the bound method.

So, if you use the tc_foo.rb example and set a break point in Ruby 1.9, after the define_method:

> ruby -rdebug tc_foo.rb
Debug.rb
Emacs support available.

tc_foo.rb:1:require 'rubygems' 
(rdb:1) break /Users/mtaylor/.gem/ruby/1.8/gems/thoughtbot-shoulda-2.10.2/lib/shoulda/context.rb:345
Set breakpoint 1 at /Users/mtaylor/.gem/ruby/1.8/gems/thoughtbot-shoulda-2.10.2/lib/shoulda/context.rb:345
(rdb:1) c
Breakpoint 1, create_test_from_should_hash at /Users/mtaylor/.gem/ruby/1.8/gems/thoughtbot-shoulda-2.10.2/lib/shoulda/context.rb:345
/Users/mtaylor/.gem/ruby/1.8/gems/thoughtbot-shoulda-2.10.2/lib/shoulda/context.rb:345:      test_unit_class.send(:define_method, test_name) do
(rdb:1) n
/Users/mtaylor/.gem/ruby/1.8/gems/thoughtbot-shoulda-2.10.2/lib/shoulda/context.rb:392:      subcontexts.each { |context| context.build }
(rdb:1) test_unit_class.instance_methods

If you then print test_unit_class.instance_methods you can see that the list includes "test: My factorial method should return 1 when passed 0. "

Now, I couldn't figure out how to get macrubyd to break in context.rb, so I injected some puts statements. After the call to define_method we end up with two entries in test_unit_class.instance_methods

  "test: My factorial method should return 1 when passed 0. :"
  "test: My factorial method should return 1 when passed 0."

The last method should match the one MacRuby is looking for in the error message:

test: My factorial method should return 1 when passed 0.(TC_Test):
NoMethodError: undefined method `test: My factorial method should return 1 when passed 0.' for #<TC_Test:0x2002772e0>

I will keep trying to find a reduction when I have time, but it may be a few days before I can get back to it.

  Changed 21 months ago by kayla.rosebud@…

  • cc kayla.rosebud@… added

Cc Me!

  Changed 14 months ago by eloy.de.enige@…

  • keywords #reduction added; shoulda removed
  • summary changed from NoMethodError with shoulda tests to Defining a method with a colon somewhere in the name and whitespace at the end will loose the trailing whitespace. (was: NoMethodError with shoulda tests)
  • milestone set to MacRuby 1.0
class X
  # no longer ends with whitespace after defining
  define_method(:"method with :colon and ending with whitespace ") {}

  # but this one does not have a colon, which maintains the whitespace
  define_method(:"method without colon and ending with whitespace ") {}

  p instance_methods(false)
end
% macruby t.rb
[:"method without colon and ending with whitespace ", :"method with :colon and ending with whitespace"]

% ruby19 t.rb
[:"method with :colon and ending with whitespace ", :"method without colon and ending with whitespace "]

So the bug is probably in code that picks it up as a selector (because of the colon).

  Changed 11 months ago by cyberfox@…

Greetings,

Just to be clear, defining a method with a single colon in it will remove ANY last character.

e.g.

class Y
  define_method(:"method with :colon and ending with non-whitespace") {}
  p instance_methods(false)
end

outputs

[:"method with :colon and ending with non-whitespac"]

...which might be considered a more serious bug.

I've tried defining it with various arities, and they have different subtle oddities, e.g.

class XY
  define_method(:"method with :colon and ending with non-whitespace") { |*x| puts x}
  p instance_methods(false)
end

outputs

[:"method with :colon and ending with non-whitespace:", :"method with :colon and ending with non-whitespac"]

Hope this info helps!

-- Morgan Schweers

follow-up: ↓ 12   Changed 11 months ago by cyberfox@…

Greetings, I'm going to guess:

diff --git a/vm.cpp b/vm.cpp
index aa2fac1..0f4b682 100644
--- a/vm.cpp
+++ b/vm.cpp
@@ -2604,7 +2604,9 @@ define_method:
        else if (genuine_selector && arity.min == 0) {
            char buf[100];
            strlcpy(buf, sel_name, sizeof buf);
-           buf[strlen(buf) - 1] = 0; // remove the ending ':'
+           if(buf[strlen(buf)-1] == ':' {
+               buf[strlen(buf) - 1] = 0; // remove the ending ':'
+           }
            sel = sel_registerName(buf);
            types_count = 3;
            redefined = true;

-- Morgan

p.s. I'm trying to build it to test, but it's...more complex than I expected to build. I'm betting it's the answer, though. Or something like it.

in reply to: ↑ 11   Changed 11 months ago by cyberfox@…

Ignore me; I still think the problem is something like that, but...I have no idea where. I _think_ I've gotten it to build, but... I'm just not sure. :/

  Changed 11 months ago by eloy.de.enige@…

To build and test your code you should only need to do: rake miniruby and then test with ./miniruby instead of the full binary.

Note: See TracTickets for help on using tickets.