Rabu, 16 Desember 2009

Storable, Regexp, bugs, bugs, bugs

A few hours spent yesterday trying to find out why some of my tests keep failing under certain conditions. Turns out I did a Storable::dclone() on an object, and that object contains a regular
expression. And Storable Don't Do No Regex. Worse is, Storable doesn't complain but will just freeze/thaw the regexes into garbage.
$ perl -MStorable=dclone -MData::Dumper -e'
print "Storable version = $Storable::VERSION\n";
$re = qr/abc/;
print Dumper $re;
print Dumper dclone $re;'
Storable version = 2.21
$VAR1 = qr/(?-xism:abc)/;
$VAR1 = bless( do{\(my $o = undef)}, 'Regexp' );

This means:
$ perl -MStorable=freeze -E'say "yikes" if freeze(qr/a/) eq freeze(qr/b/)'
yikes

Since regexes are so common in Perl, maybe some warnings in Storable documentation should be in order? I'm sure many more bums are in line waiting to be bitten by this. (Bug report filed).

There is Regexp::Copy which contains Regexp::Storable, which is supposed to add regexp (de)serialization to Storable, but turns out that it still has bugs. Even this very simple case will yield a wrong answer:
$ perl -MData::Dumper -MStorable=dclone -MRegexp::Copy -E'say "Regexp::Copy version = $Regexp::Copy::VERSION"; say Dumper dclone([qr/a/, qr/b/])'
Regexp::Copy version = 0.06
$VAR1 = [
qr/(?-xism:b)/,
qr/(?-xism:b)/
];

(Btw, if you "use Regexp::Copy" before/without "use Storable", it will also result in an error. So that's couple of bug reports filed in).

Sadly it's unclear whether these will be fixed soon. The bug queues for Storable and Regexp::Copy contains unresolved entries several years old.

I first tried to switch to Data::Compare (as actually I was just comparing data structure freeze()'s for comparison, as well as some cloning). But turns out that Data::Compare doesn't deal with recursive/circular structure yet (bug filed).

Finally I resorted to using the good ol' Data::Dumper for serializing/comparison part, and Clone for the cloning part.

Is it just me (I hope it's just me) or do other people find serializing/deserializing modules in CPAN tend to be more buggy than, say, Ruby ones? I've never *once* encountered a problem with Ruby's yaml module, yet aside from Storable and Regexp case above, I have also been bitten several times by bugs in YAML.pm, YAML::Syck, and YAML::XS. The last one is this.

And with a couple of bugs in my own code unrelated to all the above, that makes the most number of bugs found/reported between yesterday and today. Not bad after all, but still I'm worried.

5 komentar:

  1. #!/usr/bin/perl

    use strict;
    use warnings;
    use Storable ();
    use Test::More tests => 1;

    sub Regexp::STORABLE_freeze {
    return "$_[0]";
    }

    sub Regexp::STORABLE_attach {
    return qr/$_[0]/;
    }

    my $foo = qr/foo/;
    isa_ok( $foo, 'Regexp' );

    # Clone it
    my $clone = Storable::dclone( $foo );
    isa_ok( $clone, 'Regexp' );
    is_deeply( $foo, $clone, Regexp clones correctly );

    BalasHapus
  2. er... make that tests => 3 :)

    BalasHapus
  3. Komentar ini telah dihapus oleh pengarang.

    BalasHapus
  4. Neato! I might switch back to Storable after this.

    BalasHapus
  5. Turns out is_deeply() can't be used here, since it doesn't handle regexp too!

    $ perl -E'use Test::More tests => 1; say "# perl version = $]\n# Test::More version = $Test::More::VERSION"; is_deeply(qr/a/, qr/b/)'
    1..1
    # perl version = 5.010001
    # Test::More version = 0.94
    ok 1

    Nasty indeed. #53469 submitted to RT.

    BalasHapus

Catatan: Hanya anggota dari blog ini yang dapat mengirim komentar.