PHP
ascii
ctypes

PHP、全てのctype関数で、0から255までのascii文字で、chrを通した文字と通さなかった文字を引数とした時の挙動が同じ

PHPのソースコードを読んでいたら、面白いテストコードが見つかりました。以下に示します。

--TEST--
Bug #25745 (ctype functions fail with non-ascii characters)
--SKIPIF--
<?php require_once('skipif.inc'); ?>
--FILE--
<?php
$funcs = array(
    "ctype_alnum", "ctype_alpha", "ctype_cntrl", "ctype_digit",
    "ctype_graph", "ctype_lower", "ctype_print", "ctype_punct",
    "ctype_space", "ctype_upper", "ctype_xdigit"
);

foreach ($funcs as $ctype_func) {
    for ($i = 0; $i < 256; $i++) {
        $a = $ctype_func($i);
        $b = $ctype_func(chr($i));
        if ($a != $b) {
            echo "broken... $ctype_func($i) = $a, $ctype_func(chr($i)) = $b\n";
            exit;
        }
    }
}
echo "ok\n";
?>
--EXPECT--
ok

このテストコードの概要は、
"ctype_alnum", "ctype_alpha", "ctype_cntrl", "ctype_digit",
"ctype_graph", "ctype_lower", "ctype_print", "ctype_punct",
"ctype_space", "ctype_upper", "ctype_xdigit"
の関数群において、0から255の数字と、それに対応するchrを通したascii文字において、挙動が同じであることをテストしています。
\$funcsに、配列の形で、上に示したctype関数群を代入しています。

foreach ($funcs as $ctype_func) {

このコードにより、\$funcsから、配列の要素一つ一つを取り出し、$ctype_funcに代入しています。

for ($i = 0; $i < 256; $i++) {

この部分によって、0から255まで\$iをインクリメントさせてループさせています。

$ctype_func($i)

この部分により、例えば、\$ctype_funcに"ctype_alnum"が定義されていた場合は、以下のコードと等価になります。

ctype_alnum($i)

同じく、

$ctype_func(chr($i));

も、以下のコードと等価になります。

ctype_alnum($i)

if ($a != $b) {

この部分により、0から255までの数字と、それにchrを通して、ascii文字にしたものを、それぞれ\$ctype_func(\$i)と\$ctype_func(chr(\$i))に引数として導入した場合、それが同じ結果を返すかどうかを検査してます。
同じ結果が返ってこなかった場合は、これはバグなので、エラーを出力することになります。具体的には、以下のコードが実行されることになります。

echo "broken... $ctype_func($i) = $a, $ctype_func(chr($i)) = $b\n";
            exit;

で、もし、同じ結果が返ってこなかった場合、そこでプログラムは終了することになります。
なので、エラーの場合は、以下のコードは実行されません。

echo "ok\n";

もちろん、エラーがなかった場合は、このコードは実行されます。通常は、okが出力されるのが通常です。