txus / mutant

Mutant is a mutation tester. It modifies your code and runs your tests to make sure they fail. The idea is that if code can be changed and your tests don't notice, either that code isn't being covered or it doesn't do anything. This is a rewrite on top of Rubinius.
47 stars 3 forks source link

wrong constant name Virtus::Coercion::String (NameError) #9

Open solnic opened 12 years ago

solnic commented 12 years ago

it's me again :)

An exception occurred running /Users/solnic/.rvm/gems/rbx-head@virtus/bin/mutate
    wrong constant name Virtus::Coercion::String (NameError)

Backtrace:
  Rubinius::Type.coerce_to_constant_name at kernel/common/type.rb:109
               Module(Class)#const_set at kernel/common/module.rb:445
                      Class#initialize at kernel/common/class18.rb:12
             Rubinius.open_class_under at kernel/delta/rubinius18.rb:13
                   Rubinius.open_class at kernel/delta/rubinius.rb:26
                     Object#__script__ at lib/virtus/coercion/string.rb:1
        { } in Mutant::Mutator#mutate at /Users/solnic/.rvm/gems/rbx-head@virtus
                                         /bundler/gems/mutant-68dd0a44a6b4/exe
                                         /../lib/mutant/mutator.rb:27
                            Array#each at kernel/bootstrap/array.rb:68
               Mutant::Mutator#mutate at /Users/solnic/.rvm/gems/rbx-head@virtus
                                         /bundler/gems/mutant-68dd0a44a6b4/exe
                                         /../lib/mutant/mutator.rb:20
                 { } in Mutant.mutate at /Users/solnic/.rvm/gems/rbx-head@virtus
                                         /bundler/gems/mutant-68dd0a44a6b4/exe
                                         /../lib/mutant.rb:25
                            Array#each at kernel/bootstrap/array.rb:68
                        Mutant.mutate at /Users/solnic/.rvm/gems/rbx-head@virtus
                                         /bundler/gems/mutant-68dd0a44a6b4/exe
                                         /../lib/mutant.rb:24
        Mutant::Runners::RSpec#mutate at /Users/solnic/.rvm/gems/rbx-head@virtus
                                         /bundler/gems/mutant-68dd0a44a6b4/exe
                                         /../lib/mutant/runners/rspec.rb:29
           Mutant::Runners::RSpec.run at /Users/solnic/.rvm/gems/rbx-head@virtus
                                         /bundler/gems/mutant-68dd0a44a6b4/exe
                                         /../lib/mutant/runners/rspec.rb:11
                           Mutant.run at /Users/solnic/.rvm/gems/rbx-head@virtus
                                         /bundler/gems/mutant-68dd0a44a6b4/exe
                                         /../lib/mutant.rb:20
                    Object#__script__ at /Users/solnic/.rvm/gems/rbx-head@virtus
                                         /bundler/gems/mutant-68dd0a44a6b4/exe
                                         /mutate:6
                   Kernel(Object)#load at kernel/common/kernel.rb:577
                    Object#__script__ at /Users/solnic/.rvm/gems/rbx-head@virtus
                                         /bin/mutate:19
      Rubinius::CodeLoader#load_script at kernel/delta/codeloader.rb:67
      Rubinius::CodeLoader.load_script at kernel/delta/codeloader.rb:109
               Rubinius::Loader#script at kernel/loader.rb:632
                 Rubinius::Loader#main at kernel/loader.rb:836
dkubb commented 12 years ago

Looking at the stacktrace, just before the exception is thrown Module#const_set is called, then Rubinius::Type.coerce_to_constant_name is called and passed (presumably) whatever was passed into const_set.

Now, based on the error message it looks like the string "Virtus::Coercion::String" was passed in to const_set, which is obviously incorrect. A constant cannot contain colons.

So I'm guessing that wherever the class/module is being set it needs to split up the string and create a "chain" of modules, first "Virtus", then inside that "Coercion", then inside that "String. It would probably have to be smart about using a class or module as appropriate, and setting the correct superclass if applicable. (just a guess)

I think that place may be Mutant::Mutator#class_ast but I'm not 100% familiar with the internals of the mutator atm.

@txus does that sound right?

txus commented 12 years ago

Makes sense. You're running that on Virtus right? Could you paste me the bin/mutate ... command you used so that I can reproduce it? I'm not sure about the place where this is happening but Mutant::Mutator#class_ast sounds like a good place to start looking, I'll find out.

dkubb commented 12 years ago

In my case I ran it against another project of mine, but I had to do some tweaking to get it to work under rspec 2.

At the moment I'm using RSpec 1 in the master branch, but I'll create an rspec2 branch to make it easier to repro.

dkubb commented 12 years ago

Here are steps to repro: (I would assume any rbx would repro this, but I was using rbx-head)

rvm rbx-head
git clone git://github.com/dkubb/ice_nine.git
cd ice_nine
git checkout rspec2
gem install bundler && bundle
bundle exec mutate "IceNine::Freezer::Object.deep_freeze" spec/unit/ice_nine/freezer/object/class_methods/deep_freeze_spec.rb

EDIT: the exception I see is wrong constant name IceNine::Freezer::Object (NameError) and the backtrace is:

  Rubinius::Type.coerce_to_constant_name at kernel/common/type.rb:118
               Module(Class)#const_set at kernel/common/module.rb:446
                      Class#initialize at kernel/common/class18.rb:11
             Rubinius.open_class_under at kernel/delta/rubinius18.rb:13
                   Rubinius.open_class at kernel/delta/rubinius.rb:26
                     Object#__script__ at lib/ice_nine/freezer/object.rb:1
        { } in Mutant::Mutator#mutate at /Users/dkubb/.rvm/gems
                                         /rbx-head@ice_nine/gems/mutant-0.1.1
                                         /exe/../lib/mutant/mutator.rb:27
                            Array#each at kernel/bootstrap/array.rb:68
               Mutant::Mutator#mutate at /Users/dkubb/.rvm/gems
                                         /rbx-head@ice_nine/gems/mutant-0.1.1
                                         /exe/../lib/mutant/mutator.rb:20
                 { } in Mutant.mutate at /Users/dkubb/.rvm/gems
                                         /rbx-head@ice_nine/gems/mutant-0.1.1
                                         /exe/../lib/mutant.rb:25
                            Array#each at kernel/bootstrap/array.rb:68
                        Mutant.mutate at /Users/dkubb/.rvm/gems
                                         /rbx-head@ice_nine/gems/mutant-0.1.1
                                         /exe/../lib/mutant.rb:24
        Mutant::Runners::RSpec#mutate at /Users/dkubb/.rvm/gems
                                         /rbx-head@ice_nine/gems/mutant-0.1.1
                                         /exe/../lib/mutant/runners/rspec.rb:29
           Mutant::Runners::RSpec.run at /Users/dkubb/.rvm/gems
                                         /rbx-head@ice_nine/gems/mutant-0.1.1
                                         /exe/../lib/mutant/runners/rspec.rb:11
                           Mutant.run at /Users/dkubb/.rvm/gems
                                         /rbx-head@ice_nine/gems/mutant-0.1.1
                                         /exe/../lib/mutant.rb:20
                    Object#__script__ at /Users/dkubb/.rvm/gems
                                         /rbx-head@ice_nine/gems/mutant-0.1.1
                                         /exe/mutate:6
                   Kernel(Object)#load at kernel/common/kernel.rb:576
                    Object#__script__ at /Users/dkubb/.rvm/gems
                                         /rbx-head@ice_nine/bin/mutate:19
      Rubinius::CodeLoader#load_script at kernel/delta/codeloader.rb:67
      Rubinius::CodeLoader.load_script at kernel/delta/codeloader.rb:109
               Rubinius::Loader#script at kernel/loader.rb:632
                 Rubinius::Loader#main at kernel/loader.rb:836
dkubb commented 12 years ago

Ok, I started to poke around with this. I tried a few hacky attempts to get the AST for a class (or module) and I wasn't satisfied with any of them. I found it a bit hard to even tell if I was on the right track since the docs for this part of Rubinius are pretty sparse.

I'll give it a try again later this week, but I wanted to report that I tried for a couple of hours and didn't make any forward progress on this.