travis ciで失敗したテストを再実行する

perlのmoduleを開発しているとき、travis ciでときどき失敗するテストがあり、失敗するたびにRestart buildボタンをポチっと押すという不毛なことをしていた。

もちろん失敗する原因をちゃんと特定し、テストをなおすのが一番だが、とりあえず失敗したテストを自動でリトライさせるなら下記のように書けばいいことを最近知った。

language: perl
perl:
  - '5.24'
  - '5.22'
  - '5.20'
script:
  - prove --state save -l t || prove --state failed -l
sudo: false

最初のproveで--state saveを指定しておき結果を.proveファイルに保存する。そして失敗したときは、--state failedのテストを対象にproveを再び走らせている。

実際cpmでこうしている。

forkを使うテストではTest2::IPCを使うといい

perlでforkを使うテストでは Test::SharedFork をuseしておくと安心なことが知られているが、最近その実装をみたところTest2がロードされていたら、そのIPC実装を使うように変わっていた。

よっていま、forkを使ったテストを新しく書くなら、直接Test2::IPCを使えばいいと思う。

use strict;
use warnings;
use Test2::IPC;
use Test::More;

my $pid = fork // die;
if ($pid == 0) {
    is 1 + 1, 2;
    exit;
}
waitpid $pid, 0;

done_testing;

実際、Mojo::IOLoop::Signalのテストでそうした。

pipeを他プロセスから読み書きする

長らくpipeは自プロセスもしくは 親子プロセスでしか読み書きできないものと思っていたが、 最近、他のプロセスからも読み書き可能なことを発見した。つまり/proc/pid/fdを使えばよい。

自分としてはかなりの驚きであった。

例えば、

#!/usr/bin/env perl
use strict;
use warnings;

pipe my $read, my $write or die $!;

while (my $line = <$read>) {
    warn "-> GOT: $line";
}

というのを用意したとき下記のように通信できる。

$ perl pipe.pl &
[1] 13801

$ ls -l /proc/13801/fd
total 0
lrwx------ 1 skaji skaji 64 Nov  6 15:30 0 -> /dev/pts/6
lrwx------ 1 skaji skaji 64 Nov  6 15:30 1 -> /dev/pts/6
lrwx------ 1 skaji skaji 64 Nov  6 15:30 2 -> /dev/pts/6
lr-x------ 1 skaji skaji 64 Nov  6 15:30 3 -> pipe:[4096813]
l-wx------ 1 skaji skaji 64 Nov  6 15:30 4 -> pipe:[4096813]

# filedescriptor4が書き込み用pipeなのでそこに書き込む。
$ perl -E 'open my $fh, ">", "/proc/13801/fd/4" or die $!; say {$fh} "hello from $$"'
-> GOT: hello from 13843

なお、同じやり方で例えば tmpfile(3)によってopen、すぐunlinkされたファイルも他プロセスから読み書き可能だ。

use Foo () としたときFoo->importが呼ばれないのはなぜか

perl5の話題。

use FooとするとFooをrequireしつつ、Foo->importが呼ばれることはよく知られているが、 use Foo ()としたときには、importは呼ばれない。

これをどういう風にして実現しているのか前から疑問に思っていた。 というのも普通の関数は「引数なし」と「空リストの引数」を区別できないからだ。

perlソースコードをみたところ、 parseのところで「引数なし」と「空リストの引数」を区別しているとわかった。

https://github.com/Perl/perl5/blob/v5.24.0/op.c#L6048

https://github.com/Perl/perl5/blob/v5.24.0/perly.y#L346-L354

追記

plenv-update

UPDATE Ooops, there already exists https://github.com/hfm/plenv-update . You should use it!


github.com

Are your plenv and its plugins up-to-date?
Make sure they are up-to-date with plenv-update.

plenv-update adds plenv update command that updates plenv and all installed plugins at one time.

f:id:shoichikaji:20161009120844p:plain

Remove all ads

plenv freeze

plenv のplugin、plenv freezeを作った。 github.com

たとえばCPAN moduleを作っている人は、テストのため あるperlのinstallationを コアモジュール以外何もインストールしていない状態に保っていたいことがあるかもしれない。 plenv freezeは、あるperlのinstallationをread only(ファイルは0444, ディレクトリは0555)にすることで、これを助けてくれる。

僕は、このアイデアをgotandapmでのSongmuさんの発表で知った。 http://songmu.github.io/slides/gotandapm4/#6

もともとはmiyagawaさんのアイデアとのこと。

またokinawapmにてpapixさんもこの話をされていた。

ということで、自分含めて少しは需要がありそうなのでpluginとしてまとめてみた。

Remove all ads

Install latest perl to Ubuntu on Windows

Have you tried Ubuntu on Windows? It looks great!

To use perl in Ubuntu on Windows, it seems that we should set dont_use_nlink true in at least File::Find. See https://github.com/Microsoft/BashOnWindows/issues/186 for details.

So here is how to install perl 5.24 to Ubuntu on Windows. Make sure dont_use_nlink defined.

# set LANG explicitly to avoid weird problems....
$ export LANG=en_US.UTF-8

# need cc and make to build perl...
$ apt-get install gcc make

# usual way
$ wget http://www.cpan.org/src/5.0/perl-5.24.0.tar.gz
$ tar xzf perl-5.24.0.tar.gz
$ cd perl-5.24.0

# define dont_use_nlink
$ echo "dont_use_nlink='define'" >> Policy.sh

# back to usual way (change prefix as you want)
$ ./Configure -des -Dprefix=/root/perl
$ make
$ make install

Easy.

Let's install some CPAN modules, say Plack.

$ export PATH=/root/perl/bin:$PATH
$ perl -v
This is perl 5, version 24, subversion 0 (v5.24.0) built for x86_64-linux

# install cpanminus
$ curl -sSL https://cpanmin.us | perl - -nq App::cpanminus

# install some CPAN modules, say Plack
$ cpanm -nq Plack

$ plackup -e 'sub {[200,[],["Hello world!"]]}'
HTTP::Server::PSGI: Accepting connections at http://0:5000/

You can access http://localhost:5000 from your browser in Windows.

No more emulation of fork(). Wow!