追記: 1.30でsleepとretryのデフォルトが変更になりました。詳しくはドキュメントを参考にしてください

追記2: 2.00でsleepとretryがなくなりました。代わりにmax_waitが追加されました。詳しくはドキュメントを参考にしてください。blogも書いた

TCPサーバ・クライアントのテストには欠かせない、みんな大好きtokuhiromのみんな大好きTest::TCP。Plackのサーバのテストなら

use Plack::Loader;
use Test::TCP;

test_tcp(
    server => sub {
        my $loader = Plack::Loader->load(
            'Monoceros',
            port => $port,
            max_workers => 5
        );
        $loader->run($app);
        exit;
    },
    client => sub {
        my $port = shift;
        my $ua = LWP::UserAgent->new;
        my $res = $ua->get("http://localhost:$port/");
        ok($res->is_success)
    }
);

このように書くだけで、空いているTCPポートを探して、fork()した上でserver、clientのコードを実行してくれます。便利!!

内部的には

1. 空いているポートを探す
2. fork()
3. [子プロセス] serverのコードを実行
4. [親プロセス] 見つけたポートがconnectできるようになるまで待つ
5. [親プロセス] clientのコードを実行
6. [親プロセス] 子プロセスにTERMを送って、終了まで待つ

という順になってます。

ところが、最近Test::TCPを使ったテストが手元やtravis-ciでは問題ないのにcpantestersでコケるということが多くなっていて、そのほとんどが「4」でtimeoutしていました。なんでかなぁと思ってTest::TCPを見ていると1.27でポートに接続できるようになるまで待つ時間が短くなっていたのに気付きました。

https://metacpan.org/diff/release/TOKUHIROM/Test-TCP-1.26/TOKUHIROM/Test-TCP-1.27

0.1秒sleepの100回、10秒だったのが0.001秒sleepの100回retryの0.1秒になってます。テストを速く終わらせるためかなと思いますが、手元では0.1秒以内でサーバが起動しても、cpantestersではかなり重い・遅い環境もあるので、0.1秒ではforkとサーバの起動が間に合わなくなってしまっているのでしょう。

ということでとりあえず、MonocerosではTest::TCPのwait_portを上書きしてみました。

{
    no warnings 'redefine';
    *Test::TCP::wait_port = sub {
        my $port = shift;
        Net::EmptyPort::wait_port($port, 0.1, 40) 
            or die "cannot open port: $port";
    };
}

このようにしたところ、Monocerosのテストが失敗することはなくなりました。

この件をtokuhirom氏に報告したところ、オプションでsleep時間とretry回数を指定できるようにアップデートしてくれました。

use Test::TCP;

test_tcp(
    server => sub { .. },
    client => sub { .. },
    wait_port_retry => 40,
    wait_port_sleep => 0.1
);

これで安心ですね。

あとは、Test::TCPを使っているPlack::Test::Serverでも同じ問題起きるので、どうにかしたいと思う五月末

このブログ記事について

このページは、Masahiro Naganoが2013年5月31日 16:27に書いたブログ記事です。

ひとつ前のブログ記事は「Monoceros 運用系の機能追加のお知らせ。最大保持コネクション数とステータス表示ミドルウェアが追加されました」です。

次のブログ記事は「PSGI/Plackアプリケーションの起動方法いろいろと本番環境アレコレ」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

ウェブページ

OpenID対応しています OpenIDについて
Powered by Movable Type 4.27-ja