TypeError: singleton can't be dumped
Closed this issue · 6 comments
Hi,
first of all: Thanks for this library :)
While trying pippi
on one of our projects I discovered several TypeError
s after activating pippi
in tests.
A simple reproduction:
require 'bundler/setup'
require 'minitest/autorun'
require 'pippi'
Pippi::AutoRunner.new(:checkset => ENV['PIPPI_CHECKSET'] || "basic")
class MarshalDumpTest < Minitest::Test
def test_dump_broken
Marshal.dump([].select(&:odd?))
end
def test_dump_works
Marshal.dump([].select(&:odd?).dup)
end
end
Output
Run options: --seed 39192
# Running:
E.
Finished in 0.002342s, 853.9608 runs/s, 0.0000 assertions/s.
1) Error:
MarshalDumpTest#test_dump_broken:
TypeError: singleton can't be dumped
test/marshal_dump_test.rb:9:in `dump'
test/marshal_dump_test.rb:9:in `test_dump_broken'
2 runs, 0 assertions, 0 failures, 1 errors, 0 skips
Any pointers how to solve this issue?
@splattael thanks for the report. Hm, I wonder if I introduced bugs with aea9123 - can you please try pippi-0.0.9.gem and see if you get the same errors in your app?
@tcopeland Thanks for your fast response!
I did a git bisect
to find the first "bad" commit:
Git says it's 35871c7
I've run
$ git bisect start master c71de64
$ git bisect run ./test.sh
Already on 'master'
Your branch is up-to-date with 'origin/master'.
35871c7c1afbb1801160767e4b2ea652b9600a61 is the first bad commit
commit 35871c7c1afbb1801160767e4b2ea652b9600a61
Author: Tom Copeland <tom.copeland@livingsocial.com>
Date: Wed Oct 8 23:28:29 2014 -0400
Added SelectFollowedByFirst
And called out the DFA issue on the front page.
:100644 100644 76c0a4829b1df74fa7aec1fd4c5415a3a32101f0 215bbbebfdb8ee5fa0b81a4424f44839f39871a6 M README.md
:040000 040000 8c8afbe057e0d9940ef139b2c9ce0600990e75b1 9b3203b12747a9583a7717820b647e0983fd7de3 M lib
:040000 040000 46ccc3a6d58f492850e39abd1a676b5d1b5406cc 70aa2e7a14956fd6b9f80727360a08cc2a8669ee M test
More info
bisect.log
git bisect start
# good: [c71de64e859a3be05cfd53aabae1bf431ea2e0db] New rule - DetectFollowedByNil
git bisect good c71de64e859a3be05cfd53aabae1bf431ea2e0db
# bad: [5981c8776a3ee46703e00d4698c50c2dbdec609a] Heritage restored
git bisect bad 5981c8776a3ee46703e00d4698c50c2dbdec609a
# bad: [b85fb6cd67839a9fe371e3e228370619810f1214] Docs / gitignore fixes from Igor Kapkov
git bisect bad b85fb6cd67839a9fe371e3e228370619810f1214
# bad: [470c644d7eaee85115981516c65ad4b1973abba9] Detect subsequent method invocations which negate a positive result
git bisect bad 470c644d7eaee85115981516c65ad4b1973abba9
# good: [59d3c023c76326578a9a0bdd129d1eaeb0ca68a6] Remove test script
git bisect good 59d3c023c76326578a9a0bdd129d1eaeb0ca68a6
# good: [4265e35cca32831b8b731cdaaa42f3f00e62806e] Comment out the halting problem
git bisect good 4265e35cca32831b8b731cdaaa42f3f00e62806e
# bad: [e40296385edd4272a9e77fb3db0652fd2210fbb5] Allow clients to specify checksets to autorunner
git bisect bad e40296385edd4272a9e77fb3db0652fd2210fbb5
# bad: [35871c7c1afbb1801160767e4b2ea652b9600a61] Added SelectFollowedByFirst
git bisect bad 35871c7c1afbb1801160767e4b2ea652b9600a61
# good: [1158881bfb5f1cd672fbe996f838696bd8e8c584] Added ReverseFollowedByEach
git bisect good 1158881bfb5f1cd672fbe996f838696bd8e8c584
# first bad commit: [35871c7c1afbb1801160767e4b2ea652b9600a61] Added SelectFollowedByFirst
test.sh
#!/bin/bash
bundle
ruby -Ilib test/marshal_dump_test.rb
test/marshal_dump_test.rb
require 'bundler/setup'
require 'minitest/autorun'
require 'pippi'
require 'pippi/auto_runner'
Pippi::AutoRunner.new
p :VERSION => Pippi::VERSION
class MarshalDumpTest < Minitest::Test
def test_dump_broken
Marshal.dump([].select(&:odd?))
end
def test_dump_works
Marshal.dump([].select(&:odd?).dup)
end
end
I hope this helps 😺
I see, thank you @splattael . Yes, the problem is that the technique I'm using for observing method calls is to add a singleton method to the object that's returned from select
. So when attempting to serialize that object, as discussed here http://www.ruby-doc.org/core-2.1.5/Marshal.html:
irb(main):005:0> Marshal.dump(Object.new.tap {|o| o.define_singleton_method(:foo, proc {}) } )
TypeError: singleton can't be dumped
Hmmm I wonder, maybe we can implement marshal_dump
and remove the singleton method then?
@tcopeland I'll try to work on this in the next couple of days. Thanks!
Mh, obviously I didn't manage to fix this. Sorry for that :-(
No worries @splattael !
I have to say, this project has not turned out to be as productive as I thought... the interprocedural checks haven't been as effective as I thought they'd be; too many false positives. Still, I should revisit this and see if I can come up with a few more checks.