MIRACLE

メールサービス申込 ユーザー登録&ログイン パートナー情報
お問い合わせ FAQ サイトマップ
MIRACLE LINUXの特長 製品紹介 サービス案内 購入 サポート 技術フォーラム

テクノロジー情報



Samba 国際化プロジェクト > ビルドファームの詳細

ビルドファームの詳細

ビルドファームとは、build.samba.org で管理されている自動テスト実行環境です。 最新のSambaのコードは毎日ビルドファームによって機能のリグレッションがないか 確認されています。

自動テストプログラムの必要性

今までSamba日本語版での問題点は、バージョンアップでコードに変更が加わったとき、その変更部分が他の機能に与える影響、つまりリグレッションの確認でした。コードの一部分が変わってしまったため、それまで動いていた機能が動かなくなるなど、その確認にかかる負担もSambaの機能拡大に伴って増えていきました。

Samba 3.0からは全ての文字コード変換はiconvで行われるようになったため、オリジナルのSamba 3.0さえ正確に文字コード変換を行っていればどの言語でも動くようになりました。

ところが、Sambaの開発者の大部分は日本語を含むマルチバイト文字の環境を持っていません。これが意味するところは、そういった環境を持たない開発者にとって国際化のバグ修正は、まず第一にバグ自体が発見できない、また発見されても直し方がわからない、最後に直してもテストする方法がない、という非常に労力を伴う作業になります。

もし国際化を確認するための自動テストを作ることができれば、検証に必要な環境を持ち合わせていない人に対しても、まずバグの存在をわかりやすい形で訴えることができます。また、テストに通ることがバグ修正につながるので、コード修正の確認も容易に行えます。

また、一旦自動テストがSamba開発の枠組みに組み込まれれば、将来的にリリースされるコードもこのテストを通っていることとなり、今後のリリースでは最低限の自動テストを通ったという品質が保証されることになります。

Samba のリグレッションテスト

Sambaのソースコードを展開すると、"testsuite" というディレクトリがあり、 その下にはテストスクリプトが格納された複数のディレクトリが存在します。 ただ、"testsuite/build_farm" 以外のディレクトリは未公開バージョンの DejaGNU を必要とし、これらのテストを行うことは現実的ではありません。

【リスト1】Sambaのソースコードの構造
Samba-3.0.0/COPYING /Manifest /README /Read-Manifest-Now /Roadmap /WHATSNEW.txt /docs/ /examples/ /packaging/ /pcp/ /source/ /swat/ /testsuite/README /build_farm/ <== テストが格納されているディレクトリ /config/ :

このドキュメントでは、"testsuite/build_farm" に格納されたテストを実行する 方法を解説します。これらのテストは単体では動作せず、samba.org の CVS から取得できる build_test によって構築されたテスト環境で実行する必要があります。

ビルドファームとは自動テスト実行環境であり、CVSに登録されている最新のSambaのソースコードに対して、毎日自動テストを実行しています。 ビルドファームではCVSからのソースコード取得に始まり、configure、build、install、test という一連の動作をチェックします。

当プロジェクトではこの自動テスト環境とSambaのテストプログラムに国際化の対応度をチェックするためテストを追加するのパッチを作成しました。

ビルドファームを構築する方法

このテストを実行するにあたり、以下の条件が満たされている必要があります。

  • bash が導入されている
  • CP932 と EUCJP-MS が組み込まれている glibc か libiconv が導入されている
  • perl とその基本的なモジュールが導入されている
  • autoconf のバージョン 2.53 以降が導入されている
  • sudo が導入されている
  • 実行ユーザは root か sudo の権限を持っている
  • 余裕を持ったディスクスペース (ギガ単位)

glibc と libiconv については、パッチについての詳しい情報が iconvについて にて公開されていますので、 参照してください。

以上の条件が満たされているの確認し、ビルドファームを構築します。

まず、samba-3.0.2a-testsets.tar.gz をダウンロードし、glibc が導入されて いる場合には build_farm_glibc.patch、libiconv が導入されている場合は build_farm_libiconv.patch をダウンロードしてください。

ダウンロード:

次に、パッチをあてるオリジナルのビルドファーム作成スクリプト郡を、 samba.org の CVS から入手します。プロジェクト名は "build_farm" です。 ファイルを入手するには、カレントディレクトリにて下記のコマンドを 実行してください。

    $ cvs -d :pserver:cvs@pserver.samba.org:/cvsroot login
    Password: cvs
    $ cvs -z5 -d :pserver:cvs@pserver.samba.org:/cvsroot co build_farm

以上のコマンドを入力すると、カレントディレクトリに build_farm ディレクトリが 作成され、ビルドファームを構築するのに必要なファイルが展開されます。 デフォルトのままだと、build.samba.org のマスターサーバと交信を自動的に 行ってしまいます。そこで先ほどダウンロードしたパッチをあて、 スタンド・アローンのビルドファームとして構築します。

ダウンロードしたパッチを、オリジナルのビルドファームに適用するには、 以下のコマンドを実行してください。

    $ patch -p0 < build_farm_glibc.patch (build_farm_libiconv.patch)

また、テスト前に build_farm ディレクトリ直下に samba のソースコードを 展開、パッチを当てます。ディレクトリの名前は samba と指定します。

    $ tar -jxvf samba-3.0.2a.tar.bz2
    $ tar -zxvf samba-3.0.2a-testsets.tar.gz
    $ patch -p0 < samba-3.0.2a-testsets.patch
    $ mv samba-3.0.2a ./build_farm/samba

一度の複数のテストを同時に実行するときはエラーログが大変大きくなる恐れが あります。samba/testsuite/build_farm/runlist というファイルの中に $TEST_ALL という環境変数が設定されているので、この変数の値を調整することを お勧めします。 特に初めてテストを実行する場合、大量のエラーログを吐いてしまう可能性が あるので注意してください。

./samba/testsuite/build_farm/runlist
TEST_ALL="TORTURE-I18N_FILE_CREATE" #TORTURE-I18N_FILE_CREATE_match (# などでコメントアウト)

以上の準備ができたら、build_test スクリプトを実行します。

    $ cd build_farm
    $ ./build_test

テストが終了したら ./build_farm ディレクトリに作成されたログファイルやエラーファイルを参照し、テストが思惑通り実行できたか、テストが全て成功したかの確認を行ってください。

ログファイル build.<プロジェクト名>.<マシン名>.<コンパイラ名>.log
エラーファイル build.<プロジェクト名>.<マシン名>.<コンパイラ名>.err

国際化テストの内訳

テストに使用したデータに関しては、こちらの 「テストに使用したデータ」 を参照してください。

【表1】 作成したテストの内容
テスト内容オリジナルのテスト結果テスト名
マルチバイト文字を含んだファイル作成 torture-I18N_FILE_CREATE
torture-I18N_FILE_CREATE_match
torture-I18N_FILE_CREATE_necibm
torture-I18N_FILE_CREATE_unmatch
マルチバイト文字を含んだファイル削除 torture-I18N_FILE_DELETE
torture-I18N_FILE_DELETE_match
torture-I18N_FILE_DELETE_necibm
torture-I18N_FILE_DELETE_unmatch
マルチバイト文字を含んだファイル編集 torture-I18N_FILE_MODIFY
torture-I18N_FILE_MODIFY_match
torture-I18N_FILE_MODIFY_necibm
torture-I18N_FILE_MODIFY_unmatch
マルチバイト文字を含んだファイルコピー torture-I18N_FILE_COPY
torture-I18N_FILE_COPY_match
torture-I18N_FILE_COPY_necibm
torture-I18N_FILE_COPY_unmatch
マルチバイト文字を含んだファイル移動 torture-I18N_FILE_MOVE
torture-I18N_FILE_MOVE_match
torture-I18N_FILE_MOVE_necibm
torture-I18N_FILE_MOVE_unmatch
マルチバイト文字を含んだファイル情報取得 torture-I18N_FILE_SIZE
torture-I18N_FILE_SIZE_match
torture-I18N_FILE_SIZE_necibm
torture-I18N_FILE_SIZE_unmatch
torture-I18N_FILE_OWNER
torture-I18N_FILE_OWNER_match
torture-I18N_FILE_OWNER_necibm
torture-I18N_FILE_OWNER_unmatch
マルチバイト文字を含んだディレクトリ作成 torture-I18N_DIR_CREATE
torture-I18N_DIR_CREATE_match
torture-I18N_DIR_CREATE_necibm
torture-I18N_DIR_CREATE_unmatch
マルチバイト文字を含んだディレクトリ削除 torture-I18N_DIR_DELETE
torture-I18N_DIR_DELETE_match
torture-I18N_DIR_DELETE_necibm
torture-I18N_DIR_DELETE_unmatch
マルチバイト文字を含んだディレクトリ参照 torture-I18N_DIR_REF
torture-I18N_DIR_REF_match
torture-I18N_DIR_REF_necibm
torture-I18N_DIR_REF_unmatch
マルチバイト文字を含んだユーザで共有にアクセス torture-I18N_USER_TCON
torture-I18N_USER_TCON_match
torture-I18N_USER_TCON_necibm
torture-I18N_USER_TCON_unmatch
マルチバイト文字を含んだファイル・ディレクトリをごみ箱に削除 torture-I18N_FILE_RECYCLE
torture-I18N_FILE_RECYCLE_match
torture-I18N_FILE_RECYCLE_necibm
torture-I18N_FILE_RECYCLE_unmatch
torture-I18N_DIR_RECYCLE
torture-I18N_DIR_RECYCLE_match
torture-I18N_DIR_RECYCLE_necibm
マルチバイト文字を含んだ共有名一覧を取得 × torture-I18N_NETSHAREENUM
マルチバイト文字を含んだ共有・プリンタへのクライアント接続 × torture-I18N_TCON
torture-I18N_TCON_match
torture-I18N_TCON_unmatch
torture-I18N_TCON2
torture-I18N_TCON2_match
torture-I18N_TCON2_unmatch
torture-I18N_USER_TCON2
torture-I18N_USER_TCON2_match
torture-I18N_USER_TCON2_necibm
torture-I18N_USER_TCON2_unmatch
マルチバイト文字を含んだプリンタ名から印刷 × torture-I18N_SHARE_DOSPRINT
マルチバイト文字を含むSambaサーバのコンピュータ名の確認 × basicsmb-i18n_netbiosname
マルチバイト文字を含むコンピュータ名の共有一覧を取得 × basicsmb-i18n_netbiosname_share
マルチバイト文字を含むコンピュータ名にユーザ認証 × basicsmb-i18n_netbiosname_logon
マルチバイト文字を含むコンピュータ名の共有内のファイル一覧を取得 × basicsmb-i18n_netbiosname_file
マルチバイト文字を含むコンピュータ名からIPアドレスを解決 × basicsmb-i18n_nameresolv
マルチバイト文字を含むワークグループを含んだワークグループ一覧の取得 × basicsmb-i18n_workgroup
マルチバイト文字を含むグループ・マッピングを設定 basicsmb-i18n_groupmap_add
マルチバイト文字を含むユーザー情報を設定 basicsmb-i18n_pdbedit_modify
lib-I18N_convert_string
lib-I18N_strupper_w
lib-I18N_strlower_w
lib-I18N_toupper_w
lib-I18N_tolower_w
lib-I18N_strcmp_w
lib-I18N_strcasecmp_w
lib-I18N_strstr_w
lib-I18N_strdup_w
lib-I18N_strncpy_w
lib-I18N_strchr_w
lib-I18N_strrchr_w
lib-I18N_strcat_w
lib-I18N_strequal_w

ビルドファームの構造

構築されたビルドファームは以下のようになります。

【リスト2】ビルドファームの構造
./build_farm/ ... $test_root /build_test /build_test.fns /generic.fns /<project>/ ... $tree /source/ ... $source /testsuite/build_farm/ ... $testsuite /runlist /<TEST>.test : /basicsmb.fns /template/ /data/ /prefix/<project>/ ... $prefix /build.<project>.<host>.<compiler>.log /build.<project>.<host>.<compiler>.err

それぞれのファイル、ディレクトリの説明は以下になります。

build_test ユーザが実際に実行するスクリプト
build_test.fns 環境構築・テストを行う関数を定義するファイル
generic.fns テストを行うプロジェクト (ここでは samba) を指定するファイル
<project> プロジェクトのソースコードが格納されているディレクトリ
runlist そのプロジェクトに対して実行するテストを指定するファイル
prefix/<project> make install のターゲットディレクトリ
build.<project>.<host>.<compiler>.log ログメッセージのログ
build.<project>.<host>.<compiler>.err エラーメッセージのログ

また、変数名は以下のようになります。

$test_root ビルドファームのディレクトリ
$tree プロジェクトが格納されているディレクトリ
$source プロジェクトのソースが格納されているディレクトリ
$testsuite プロジェクトのテストが格納されているディレクトリ
$prefix ビルドファームで構築したバイナリのインストール先

Sambaに対する新しいテストを加えたい場合は、$testsuite の中に新しいテストファイル <TEST>.test (<TEST> は任意の名前) を追加し、$testsuite/runlist の中にエントリを追加します。

補足資料: 各ファイルの構造

このセクションでは、ビルドファームで行われる処理について説明します。

build_test

build_test.fns をロードして関数を使用可能にします。

generic.fns を実行します。

        :
  . build_test.fns
  . generic.fns
        :

generic.fns

build_test.fns で定義されている test_tree() 関数に対し、 テストを行うプロジェクトのブランチを指定します。

test_tree() 関数の引数は以下のとおりです。

  test_tree <project> <source directory> <compiler> [<actions> ...]

Samba 3.0 のテストをする場合は以下のようになっています。

  test_tree samba source gcc

build_test.fns

テストファームの構築やテスト実行などは、このファイルの中で定義されている関数で呼ばれています。

test_tree() 関数

実行ユーザ名とホスト名を取得します。

プロジェクトのテストスクリプトの格納ディレクトリを指定します。($testsuite)

取得したソースに対してチェックサムを実行し、以前のビルド時と diff がない場合には処理を終了します。

test_tree で 4 番目以降のパラメータが指定されていない場合には実行する項目として $actions 変数に "configure build install test" が選択されます。

これ以降は実際にテストが行われ、その内容はログへと出力されます。

標準出力は build.<PROJECT>.<HOST>.<COMPILER>.log ($log)、エラー出力は build.<PROJECT>.<HOST>.<COMPILER>.err ($err) へとリダイレクトされます。

それぞれの実行項目に対してソースディレクトリに移動した後、action_$action() 関数を実行します。

    test_tree() {

        log="build.$tree.$host.$compiler.log"
        err="build.$tree.$host.$compiler.err"
        sum="build.$tree.$host.$compiler.sum"
        lck="$test_root/build.$tree.lck"

        /* Lock がかかっている場合は終了 */
        if ! lock_file "$lck"; then
                return
        fi

        /* ユーザ名の取得 */
        if [ ! $USER = "" ]; then
            whoami=$USER
        else
            if [ ! $LOGNAME = "" ]; then
                whoami=$LOGNAME
            else
                whoami=build
            fi
        fi

        /* インストール先を指定 */
        prefix="$prefix/$tree"

        /* テストスクリプトの格納ディレクトリ指定 */
        testsuite=testsuite/build_farm

        /* configure のオプション指定 */
        config_and_prefix="$config --prefix=$prefix"

        /* 実行内容を取得 */
        actions="$*"
        if [ "$actions" = "" ]; then
            actions="configure build install test"
        fi

        (
            for action in $actions; do
                srcdir=$test_root/$tree/$source
                cd $srcdir
                export srcdir

                echo Running action $action
                ( action_$action )
                if [ $? != 0 ]; then
                    echo "ACTION FAILED: $action";
                    break;
                fi
            done
        ) > "$log" 2> "$err"
            :
    }

action_configure() 関数

configure のオプションの prefix を $prefix に指定する以外は、 デフォルトのオプションで configure が実行されます。

action_build() 関数

make を行う target を指定します。

Samba 3.0 の場合は proto, everything, torture が実行されます。

action_install() 関数

make を行う target を指定します。

Samba 3.0 の場合は proto, everything, torture が実行されます。

action_test() 関数

プロジェクト名が samba を含む場合、action_test_samba() を実行します。

action_test_samba() 関数

Sambaのテストを実行する関数です。

  action_test_samba() {

        logfile="$prefix/var/log.smbd"

        LIBSMB_PROG=$prefix/sbin/smbd
        export LIBSMB_PROG

        . $test_root/$tree/$testsuite/runlist
        testlist=$TEST_ALL

        for test in $testlist; do
            each_test $test;
            if [ $tstatus != 0 ]; then
                totalfailed=`expr $totalfailed + 1`;
                loglevel=10
                each_test $test
                loglevel=1
            fi
        done
        echo "contents of $logfile:"
        cat $logfile
        echo "FAILED TESTS: $FAILED_TESTS"
        echo "TEST STATUS: $totalfailed"
          :
  }

ビルドした smbd のパスを $LIBSMB_PROG 変数に指定します。

$test_root/$tree/$testsuite/runlist から $TEST_ALL 変数をロードします。

$TEST_ALL にはテスト名のリストが指定されていて、each_test() 関数によってそれぞれのテストが実行されます。具体的には、$test_root/$tree/$testsuite にある、<TEST>.test が実行されます。あるテストが失敗すると、ビルドファームはログレベルを10にあげて再度同じテストを実行します。

each_test() 関数

引数を受け取り、$test_root/$tree/$testsuite の中の同名のテストスクリプトを各自実行します。テストに失敗したら FAILED TEST としてカウントされます。

runlist

このファイルには $TEST_ALL という変数が定義されており、この変数にはテスト名のリストが指定されています。具体的には、$test_root/$tree/$testsuite にある、.test が実行されます

例えば下記のように記述されてあると、

  TEST_ALL="basicsmb-sharelist torture-I18N_FILE"

実行されるテストスクリプトは以下の二つになります。

  • $test_root/$tree/$testsuite/basic-smb-sharelist.TEST
  • $test_root/$tree/$testsuite/torture-I18N_FILE.TEST

<TEST>.test

$test_root/$tree/$testsuite/<TEST>.test は bash スクリプトです。

それぞれのテストは成功すると 0 を返し、それ以外の場合にはエラーを返します。

デフォルトではテスト前に $prefix/lib/ が毎回削除されるため、そのたびに smb.conf などの必要なファイルを testsuite/build_farm/template 以下からインポートし、LMHOSTS を設定します。この処理は basicsmb.fns の template_conf_setup() 関数で 行われています。また、パスワード認証は smbpasswd が使用されていて、 basicsmb.fns の test_smbpasswd() 関数で設定されます。

これらの関数は必需ではありませんが、ほとんどのテストケースではこれらの関数を呼び出して、サーバ環境のセットアップを行っています。

補足資料: 自動テスト実行下におけるsmbdの呼び出し

smbclient などのSMBクライアントがサーバに接続する際、$LIBSMB_PROG 変数が設定されていると、クライアントは cli_connect() 関数実行時に通常の接続ではなく、smbd をフォークプロセスとして起動させ、標準の入出力をこの接続につなげます。

下のコードを参照すると、環境変数が設定されていると sock_exec() 関数を呼んでいることがわかります。

【ソース1】./build_farm/samba/source/libsmb/cli_connect.c
BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip) { : if (getenv("LIBSMB_PROG")) { cli->fd = sock_exec(getenv("LIBSMB_PROG")); } else { /* try 445 first, then 139 */ int port = cli->port?cli->port:445; cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, port, cli->timeout); if (cli->fd == -1 && cli->port == 0) { port = 139; cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, port, cli->timeout); } if (cli->fd != -1) cli->port = port; } : }

sock_exec() 関数はfork()して新しいプロセスを起動し、親と子供の入出力をパイプでつなげます。他のプロセスからはこのソケットには接続できません。

【ソース2】./build_farm/samba/source/lib/sock_exec.c
int sock_exec(const char *prog) { int fd[2]; if (socketpair_tcp(fd) != 0) { DEBUG(0,("socketpair_tcp failed (%s)\n", strerror(errno))); return -1; } if (fork() == 0) { close(fd[0]); close(0); close(1); dup(fd[1]); dup(fd[1]); exit(system(prog)); } close(fd[1]); return fd[0]; }

ビルドファームの環境では $LIBSMB_PROG が定義されているので、SMBクライアントがサーバに接続しようとするたびにテスト環境でビルドした smbd に対して起動、接続することになります。

CVS で取得した build_farm ディレクトリの中の build_test.fns には、テスト実行時には常に $LIBSMB_PROG が指定されています。

【ソース3】./build_farm/build_test.fns
action_test_samba() { : LIBSMB_PROG=$prefix/sbin/smbd export LIBSMB_PROG : }

もし外部のWindowsサーバを参照するテストを作成したい場合は、この環境変数をリセットし、適切な smb.conf の設定を行ってからテストを実行してください。

なお、ビルドファームでビルドした smbd が参照する smb.conf のデフォルトの格納先は "$prefix/lib/smb.conf" です。

【ソース4】任意のテスト 例:) ./build_farm/samba/testsuite/build_farm/basictest.test
test_dummy() { _LIBSMB_PROG_BACKUP="$LIBSMB_PROG" unset LIBSMB_PROG <_テスト_実行_> LIBSMB_PROG="$_LIBSMB_PROG_BACKUP" export LIBSMB_PROG } test_dummy

これで、ビルドファームでビルドしたクライアントでも外部サーバを参照することができます。



会社情報 採用情報 個人情報保護方針 情報セキュリティ基本方針 商標等取り扱い事項 English
Copyright(c)2000-2015 MIRACLE LINUX CORPORATION. All Rights Reserved.