Perlのバグフィックスがテストに影響していた

RPC::XMLもテストに失敗するんだけどでテストが失敗するとかごちゃごちゃ抜かしてたのだが、そもそもの原因らしいものが判明した。原因というのはPerl5.8.8で修正された*1、ある文法に関するバグが関係しているようだ。

その文法というのが、これ。

# 以下は(\$a, \$b, \$c) と同値
\($a, $b, $c)

このやり方で返されたリファレンスを使えば定数に変更を加えることが可能となる、というバグがいままでのPerlにはあった。うちが確認したのは、Perl5.8.6とPerl5.8.7。また、Perl5.8.8では修正済みのようだ。

以下のような検証用のスクリプトを用意した。

use strict;
use Data::Dumper;
use constant HAKOBE => 'hakobe'; # 定数

# 定数のリファレンスを取得して代入
# ただし\()記法経由で
eval {
    my $ref = \(HAKOBE)[0]; # \()記法でリファレンスを取得
    print Dumper $ref;
    $$ref = 'yohei'; #定数を変更
    print Dumper $ref;
};
if ($@) {
    print "error: $@";
} else {
    print "no error\n";
}

$refが示す先は定数なので変更できるはずはない。このスクリプトをPerl5.8.8で実行すると、

$ perl alter_simple.pl 
$VAR1 = \'hakobe';
error: Modification of a read-only value attempted at alter_simple.pl line 10.

と出力される。これはあたりまえ。で、これを、Perl5.8.7あたりで実行すると、

$ perl alter_simple.pl 
$VAR1 = \'hakobe';
$VAR1 = \'yohei';
no error

あれ、変更されちゃった。これは良くない。

ともあれ、現行バージョンのPerl5.8.8では変更できないように修正されているのだから、最新版のPerl使えば問題はないということなのだけど。

それで、RPC::XMLもテストに失敗するんだけどのテストが失敗するのは、テストケースのひとつ、t/10_data.tの中に、

my @vals = \(int(rand 10000) + 1, int(rand 10000) + 1, rand 10001, __FILE__);

という部分があるのが良くない。このコードのあと__FILE__のリファレンスをblessしていて、それがPerl5.8.8では警告されてテストが失敗する。これが警告されないPerl5.8.7ではテストが成功したということだな。なんだか、どんどん説明がややこしくなってしまったけれど。

Perl5.8.8での修正は適切なものだとおもうので、ここはRPC::XMLの中の人がテストケースを修正してくれるといいな。

*1:のだと思う。確認してません。