(57)【特許請求の範囲】
【請求項１】
コンピュータに、
テスト対象のプログラムから、配列にアクセスする命令に含まれ、かつ該配列の要素を指定する指数を抽出し、抽出した指数に基づいて、前記テスト対象のプログラムからアクセスされる配列の最大指数を算出し、
前記テスト対象のプログラムのシンボリック実行時におけるシンボル化対象の配列のバリエーションとして、算出した前記最大指数に対応する要素数の配列のバリエーションを設定したドライバを生成する
ことを含む処理を実行させるドライバ生成プログラム。
【請求項２】
前記最大指数を算出する際に、前記テスト対象のプログラムに含まれる変数が使用されている指数については、該変数が取り得る最大値を用いて該指数の値を計算する請求項１記載のドライバ生成プログラム。
【請求項３】
前記最大指数を算出する際に、前記テスト対象のプログラムのシンボリック実行時に該テスト対象のプログラムから呼び出されるスタブの返却値を使用する指数については、該返却値を用いて該指数の値を計算する請求項１又は請求項２記載のドライバ生成プログラム。
【請求項４】
前記スタブの返却値が変更された場合には、前記最大指数を再度算出し、該最大指数が更新された場合には、前記ドライバに設定する配列のバリエーションを追加する請求項３記載のドライバ生成プログラム。
【請求項５】
前記テスト対象のプログラムに配列の要素を削除する命令が含まれる場合、抽出した指数の値の最大値に、前記配列の要素を削除する命令により削除される要素数を加算した値を、前記最大指数として算出する請求項１〜請求項４のいずれか１項記載のドライバ生成プログラム。
【請求項６】
前記指数を抽出する際、前記テスト対象のプログラムを制御フローに変換し、該制御フローをトラバースして、前記配列にアクセスする命令を探索する請求項１〜請求項５のいずれか１項記載のドライバ生成プログラム。
【請求項７】
前記配列のバリエーションは、０から前記最大指数に１加算した値まで１ずつ加算した値の各々を要素数とする配列の各々である請求項１〜請求項６のいずれか１項記載のドライバ生成プログラム。
【請求項８】
テスト対象のプログラムから、配列にアクセスする命令に含まれ、かつ該配列の要素を指定する指数を抽出し、抽出した指数に基づいて、前記テスト対象のプログラムからアクセスされる配列の最大指数を算出する算出部と、
前記テスト対象のプログラムのシンボリック実行時におけるシンボル化対象の配列のバリエーションとして、算出した前記最大指数に対応する要素数の配列のバリエーションを設定したドライバを生成する生成部と、
を含むドライバ生成装置。
【請求項９】
コンピュータに、
テスト対象のプログラムから、配列にアクセスする命令に含まれ、かつ該配列の要素を指定する指数を抽出し、抽出した指数に基づいて、前記テスト対象のプログラムからアクセスされる配列の最大指数を算出し、
前記テスト対象のプログラムのシンボリック実行時におけるシンボル化対象の配列のバリエーションとして、算出した前記最大指数に対応する要素数の配列のバリエーションを設定したドライバを生成する
ことを含む処理を実行させるドライバ生成方法。
【発明の詳細な説明】
【技術分野】
【０００１】
開示の技術は、ドライバ生成プログラム、ドライバ生成装置、及びドライバ生成方法に関する。
【背景技術】
【０００２】
シンボリック実行技術によるプログラムのテスト技術において、テスト対象のプログラムの実行環境を構築及び設定し、テスト対象のプログラムを起動するプログラムであるドライバを生成する技術が存在する。
【０００３】
例えば、記号テストドライバを反復生成する方法が提案されている。この方法では、１又は複数のコンピューティング装置により、評価されるべきコンピューティング装置に対する命令を決定し、評価されるべき１又は複数の命令及び該命令の一部に対応する記号変数の指示を有する第１の記号テストドライバを生成する。そして、記号変数に関して命令を記号実行し、記号実行の結果から、記号変数の所与の値で命令を実行する１又は複数のコマンドを有するテストケースを決定する。また、コマンド内のオブジェクト指向プログラミングコンポーネントの１又は複数の呼び出しを決定し、決定した呼び出しに基づき呼び出しを有する新しい記号テストドライバを生成する。そして、新しい記号テストドライバを記号実行する。
【０００４】
また、プログラムの中には、オブジェクトや配列型の変数など、非プリミティブな変数が含まれる場合がある。このようなプログラムについて、プログラムのコンパイルやプログラムコードの修正等に関する技術が提案されている。
【０００５】
例えば、主記憶装置の配列領域のサイズ以上の配列領域を必要とするプログラムに対し、主記憶装置と拡張記憶装置との間のデータ転送文を考慮することなく、ソースプログラムに対応した目的プログラムを生成する手法が提案されている。
【０００６】
また、プログラム中から型や添字範囲の宣言を取り出して変数構造体に置き換えてシミュレートして最大値などを収集し、適切な型や添字範囲に自動修正する手法が提案されている。
【先行技術文献】
【特許文献】
【０００７】
【特許文献１】特開２０１４−２１９８２号公報
【特許文献２】特開平０６−３４８５０５号公報
【特許文献３】特開平０７−２８１９０５号公報
【発明の概要】
【発明が解決しようとする課題】
【０００８】
シンボリック実行のためのドライバ生成において、シンボル化したい変数がオブジェクトや配列型などの非プリミティブな変数の場合には、その変数の値のバリエーションをドライバに設定する。
【０００９】
しかし、配列型の変数の中には、プログラムの実行中に、配列の要素数が動的に変更されるものもあり、プログラムコードの静的解析からは、配列の要素数を把握することが困難な場合がある。配列の要素数が適切に把握できない場合には、その配列のバリエーションを適切にドライバに設定することができないため、テストの実行が失敗したり、テスト網羅性が低下したりする場合がある。
【００１０】
開示の技術は、一つの側面として、要素数が動的に変更される配列型の変数をシンボル化の対象とする場合でも、テストの実行失敗及びテスト網羅性の低下を抑制するシンボリック実行のドライバを生成することを目的とする。
【課題を解決するための手段】
【００１１】
開示の技術は、一つの態様として、テスト対象のプログラムから、配列にアクセスする命令に含まれ、かつ該配列の要素を指定する指数を抽出し、抽出した指数に基づいて、前記テスト対象のプログラムからアクセスされる配列の最大指数を算出する。そして、前記テスト対象のプログラムのシンボリック実行時におけるシンボル化対象の配列のバリエーションとして、算出した前記最大指数に対応する要素数の配列のバリエーションを設定したドライバを生成する。
【発明の効果】
【００１２】
一つの側面として、要素数が動的に変更される配列型の変数をシンボル化の対象とする場合でも、テストの実行失敗及びテスト網羅性の低下を抑制するシンボリック実行のドライバを生成することができる、という効果を有する。
【図面の簡単な説明】
【００１３】
【図１】本実施形態に係るドライバ生成装置の概略構成を示す機能ブロック図である。
【図２】シンボリック実行技術を用いたプログラムの単体テストの手順を説明するための図である。
【図３】ドライバの基本構成部分を説明するための図である。
【図４】非プリミティブ型の変数のバリエーションが設定されたドライバを説明するための図である。
【図５】動的配列型の変数をシンボル化することを想定したドライバの生成を説明するための図である。
【図６】配列のバリエーションが設定されたドライバを説明するための図である。
【図７】ドライバ生成装置として機能するコンピュータの概略構成を示すブロック図である。
【図８】ドライバ生成処理の一例を示すフローチャートである。
【図９】動的配列型の変数の抽出を説明するための図である。
【図１０】スタブの一例を示す図である。
【図１１】テスト対象クラスを制御フローに変換した一例を示す図である。
【図１２】制御パスから抽出された実行パスの一例を示す図である。
【図１３】指数の値の計算を説明するための図である。
【図１４】最大指数算出処理の一例を示すフローチャートである。
【図１５】最大指数の算出を説明するための図である。
【図１６】配列の要素を削除する命令により削除される要素数を加算する理由を説明するための図である。
【図１７】最大指数に応じた要素数の配列のバリエーションが設定されたドライバを説明するための図である。
【図１８】スタブが変更された際の最大指数の再算出を説明するための図である。
【図１９】最大指数の更新に応じて配列のバリエーションが追加設定されたドライバを説明するための図である。
【発明を実施するための形態】
【００１４】
以下、図面を参照して、開示の技術に関する実施形態の一例を詳細に説明する。なお、本実施形態では、テスト対象プログラムを、Ｊａｖａ（登録商標）で記述されたクラス及びメソッドとする場合を例に説明する。
【００１５】
図１に示すように、本実施形態に係るドライバ生成装置１０は、テスト対象クラス３１を入力として受け付ける。そして、ドライバ生成装置１０は、テスト対象クラス３１から、シンボリック実行ドライバ３３及びスタブ３２を生成して出力する。
【００１６】
なお、シンボリック実行ドライバ３３（以下、単に「ドライバ３３」という。）とは、テスト対象クラス３１の実行環境を構築及び設定し、テスト対象クラス３１を起動するプログラムである。また、スタブ３２とは、テスト対象クラス３１が呼び出すプログラム部品のダミー実装である。テスト対象クラス３１から呼び出されるプログラム部品は、テスト対象クラス３１のテスト段階では、実装途中であったり、そのプログラム部品のテストが未実施であったりする場合がある。また、プログラム部品が、ファイルやデータベースなどへの外部アクセスを実行するものである場合もある。このような理由で、テスト時において、テスト対象クラス３１から呼び出されるプログラム部品を利用できない場合には、実際のプログラム部品の代わりにスタブ３２を用いる。
【００１７】
ここで、シンボリック実行技術を用いたプログラムの単体テストの手順について説明する。
【００１８】
図２に示すように、まず、ドライバ３３及びスタブ３２を生成する（Ｓ１００）。次に、生成したドライバ３３及びスタブ３２と、テスト対象クラス３１とをシンボリック実行エンジン２００に入力し、シンボリック実行エンジン２００でテストケースが生成される（Ｓ１０１）。そして、生成されたテストケースを使って、単体テストツール２０１によりテストを実行することにより、テスト対象クラス３１についてのテスト結果が得られる（Ｓ１０３）。
【００１９】
シンボリック実行ドライバ３３の基本的な構成には、シンボル変数宣言、テスト対象オブジェクト生成、及びテスト対象クラス呼出の３つの部分が含まれる。例えば、図３右図に示すドライバ３３Ａ（Ｄｒｉｖｅｒ０１）が、図３左図に示すテスト対象クラス３１Ａ（ＴａｒｇｅｔＣｌａｓｓ０１）に対応するドライバ３１であるとする。なお、この例では、テスト対象クラス３１Ａ内の変数ｓｔｒ及びｉをシンボル化することを想定している。
【００２０】
シンボル変数宣言は、破線部４１Ａで示す部分である。シンボル変数宣言の部分では、例えば、＠Ｓｙｍｂｏｌｉｃなどのアノテーションを付加して、シンボル化したい変数が指定される。シンボル変数宣言された変数には、任意の初期値を設定することができる。テスト対象オブジェクト生成は、破線部４２Ａで示す部分である。テスト対象オブジェクト生成の部分では、テスト対象クラス３１Ａがインスタンス化される。テスト対象クラス呼出は、破線部４３Ａで示す部分である。テスト対象クラス呼出では、シンボル変数を引数で渡して、テスト対象クラス３１Ａ内のメソッド（ｍｅｔｈｏｄ１）を実行する。
【００２１】
なお、ドライバ３３は、テスト対象クラス３１に含まれる１メソッドにつき１つ必要である。
【００２２】
上記のシンボル変数宣言において、＠Ｓｙｍｂｏｌｉｃでシンボル化が可能な変数は、プリミティブなデータ型の変数のみである。プリミティブなデータ型の変数であれば、シンボル変数として宣言しておくことで、シンボリック実行エンジン２００によるシンボリック実行の際に、シンボル化された変数のバリエーションを解析しながら実行パスが抽出される。
【００２３】
シンボル化したい変数がオブジェクト型の場合には、テスト対象クラス３１を、例えば、ＡＳＭなどのフリーソフトを用いて静的解析して、オブジェクト内のプリミティブなデータ型の変数を抽出する。そして、抽出した変数をシンボル変数宣言すると共に、オブジェクトのバリエーションを設定する。
【００２４】
例えば、図４右図に示すドライバ３３Ｂ（Ｄｒｉｖｅｒ０２）が、図４左図に示すテスト対象クラス３１Ｂ（ＴａｒｇｅｔＣｌａｓｓ０２）に対応するドライバであるとする。なお、この例では、テスト対象クラス３１Ｂ内の変数ｐをシンボル化することを想定している。変数ｐは、ユーザ定義オブジェクトＰｅｒｓｏｎの変数であり、プリミティブなデータ型ではないため、＠Ｓｙｍｂｏｌｉｃによるシンボル変数宣言はできない。この場合、ユーザ定義オブジェクトＰｅｒｓｏｎのユーザ定義オブジェクトクラス３４Ｂからプリミティブなデータ型の変数ａｇｅを抽出し、シンボル変数宣言する（破線部４１Ｂの３〜４行目）。なお、同じくプリミティブなデータ型の変数ｎａｍｅについては、テスト対象クラス３１Ｂ内で使用されていないため、シンボル変数宣言されていない。
【００２５】
また、テスト対象クラス３１Ｂを解析すると、変数ｐがｎｕｌｌか否か、及びａｇｅが２０より小さいか否かで分岐する条件文が存在することがわかる（テスト対象クラス３１Ｂの３〜４行目）。そこで、変数ｐがｎｕｌｌの場合とｎｕｌｌではない場合のバリエーションを生成する（破線部４１Ｂの１〜２行目及び破線部４４Ｂ）。これにより、シンボル変数宣言した変数ａｇｅとあわせて、変数ｐについて、ｎｕｌｌ、ａｇｅ＜２０のオブジェクトｐ、及びａｇｅ≧２０のオブジェクトｐのバリエーションが設定される。シンボリック実行時には、上記のようにバリエーションが設定された変数ｐが、テスト対象クラス呼出（破線部４３Ｂ）で引数として渡され、テスト対象クラス３１Ａ内のメソッド（ｍｅｔｈｏｄ２）が実行される。
【００２６】
シンボル化したい変数が、プログラム実行中に配列の要素数が動的に変更される動的配列型の変数（例えば、ＡｒｒａｙＬｉｓｔなど）の場合には、シグネチャを分析するだけでは、その配列の要素数を把握することができない。例えば、図５に示すテスト対象クラス３１Ｃ（ＴａｒｇｅｔＣｌａｓｓ０３）に対応するドライバとして、変数ｘ及びｌｉｓｔをシンボル化することを想定したドライバを生成することを考える。この場合、図５の破線部５１に示すように、シグネチャからは変数ｌｉｓｔのサイズ（配列の要素数）を把握することはできない。
【００２７】
また、配列型の変数にアクセスする命令には、配列の要素を指定する指数が含まれる。例えば、ＡｒｒａｙＬｉｓｔの場合は、ｇｅｔメソッドの引数として指数が指定される。なお、本実施形態では、要素数がｎの配列の指数は、０，１，・・・，ｎ−１とする。ここで、破線部５２に示すように、ＬｉｂＣｌａｓｓ．ｌｉｂ０１（）で参照される参照ライブラリ３５Ｃには、ユーザが入力した値を返却することが規定されている。すなわち、ＬｉｂＣｌａｓｓ．ｌｉｂ０１（）は不定値であるため、ｌｉｓｔ．ｇｅｔ（ｂ＋ＬｉｂＣｌａｓｓ．ｌｉｂ０１（））は、ｌｉｓｔのどの要素にアクセスする命令であるかを把握することができない。
【００２８】
このような動的配列型の変数をシンボル化の対象とする場合、配列の要素数を予め定めた固定の値とし、その要素数に対応する配列のバリエーションを生成することが考えられる。
【００２９】
図６に、テスト対象クラス３１Ｃ（ＴａｒｇｅｔＣｌａｓｓ０３）について、要素数を２として、変数ｌｉｓｔの配列のバリエーションを設定したドライバ３３Ｃの例を示す。この例では、破線部４１Ｃの１〜２行目及び破線部４４Ｃにより、変数ｌｉｓｔの配列のバリエーションとして、ｎｕｌｌ、空配列、１要素を持つ配列、及び２要素を持つ配列が設定されている。また、破線部４１Ｃの３〜４行目は、配列のサイズを制御するための変数をシンボル変数宣言したものである。また、破線部４１Ｃの５〜８行目は、配列の各要素の値（プリミティブなデータ型）をシンボル変数宣言したものである。
【００３０】
このように、配列の要素数を固定した場合、テスト対象クラス３１内に、固定した要素数以上の配列の位置にアクセスする命令が存在する場合には、テスト対象クラス３１の実行時にエラーが発生し、テストの実行が失敗してしまう。例えば、図６に示すテスト対象クラス３１Ｃをドライバ３３Ｃ（要素数＝２で固定）で実行した場合において、１０行目でＬｉｂＣｌａｓｓ．ｌｉｂ０１（）の返却値が１以上であるとする。この場合、指数は２以上となり、最大でも指数０及び１に対応する２要素しか持たない変数ｌｉｓｔの配列にアクセスすることができず、ＮｕｌｌＰｏｉｎｔｅｒＥｘｃｅｐｔｉｏｎの例外が発生する。１５行目では、指数は４であるため、同様に、ＮｕｌｌＰｏｉｎｔｅｒＥｘｃｅｐｔｉｏｎの例外が発生する。また、４行目及び１６行目からｉ＝０，１，２，３であることが分かるが、１７行目でｉ＝３の場合も同様に、ＮｕｌｌＰｏｉｎｔｅｒＥｘｃｅｐｔｉｏｎの例外が発生する。
【００３１】
また、テスト対象クラス３１内に、配列の要素数に応じて分岐する条件文が存在する場合、固定した要素数ではない値に応じた分岐先の命令が実行されず、テスト網羅性（コードカバレッジ）が低下する場合がある。例えば、図６に示すテスト対象クラス３１Ｃをドライバ３３Ｃ（要素数＝２で固定）で実行した場合、変数ｌｉｓｔの配列のバリエーションとして、要素数が４以上の配列のバリエーションは存在しない。そのため、５行目の条件分岐は常にｔｒｕｅとなり、ｆａｌｓｅの場合の分岐先である８行目以降の命令が実行されない。これにより、コードカバレッジが１００％にならない。
【００３２】
そこで、本実施形態では、動的配列型の変数をシンボル化する際の配列のバリエーションを最適化してドライバ３３を生成する。以下、ドライバ生成装置１０の各部について詳述する。
【００３３】
図１に示すように、ドライバ生成装置１０は、機能的には、スタブ生成部１１と、算出部１２と、ドライバ生成部１３とを含む。
【００３４】
スタブ生成部１１は、入力されたテスト対象クラス３１から、シンボリック実行時に呼び出されるスタブ３２を生成する。スタブの生成方法は、従来既知の手法を用いることができるため、本実施形態では詳細な説明を省略する。
【００３５】
算出部１２は、テスト対象クラス３１から、シンボル化対象の変数である配列にアクセスする命令に含まれる指数を抽出する。そして、算出部１２は、抽出した指数に基づいて、テスト対象クラス３１における、シンボル化対象の変数である配列にアクセスする際に用いられる指数の最大値（以下、「最大指数」という）を算出する。
【００３６】
具体的には、算出部１２は、テスト対象クラス３１からシンボル化対象の動的配列型の変数を抽出し、集合ＳＹＭ２１に格納する。また、算出部１２は、テスト対象クラス３１のプログラムコードを、Control Flow Graph Generatorなどのフリーソフトを用いて、制御フローに変換する。そして、算出部１２は、制御フローをトラバースして、配列にアクセスする命令を探索し、その命令に含まれる指数を抽出し、集合ＩＮＤＥＸ２２に格納する。ＩＮＤＥＸ２２は、シンボル化対象の動的配列型の変数毎に用意される。
【００３７】
また、算出部１２は、テスト対象クラス３１から整数型のローカル変数を抽出し、集合ＶＡＲ２３に格納する。そして、算出部１２は、ＩＮＤＥＸ２２に格納された指数が、テスト対象クラス３１に含まれる整数型の変数を使用している場合には、制御フローをトラバースして、その整数型の変数が取り得る最大値を算出し、ＶＡＲ２３に記録する。また、算出部１２は、ＩＮＤＥＸ２２に格納された指数が、スタブ３２からの返却値を使用している場合には、スタブ３２からの返却値を取得する。また、算出部１２は、テスト対象クラス３１に含まれる、シンボル化対象の変数である配列の要素を削除する命令の数を削除カウンタ２４に記録する。例えばＡｒｒａｙＬｉｓｔの場合は、配列の要素を削除する命令はｒｅｍｏｖｅメソッド等である。なお、削除カウンタ２４は、シンボル化対象の動的配列型の変数毎に用意される。そして、算出部１２は、ＳＹＭ２１、ＩＮＤＥＸ２２、ＶＡＲ２３、及び削除カウンタ２４に格納された値を用いて、最大指数を算出する。
【００３８】
また、算出部１２は、スタブ３２のプログラムコードが変更され、スタブ３２からの返却値が変更された場合には、最大指数を再算出する。
【００３９】
ドライバ生成部１３は、算出部１２により算出された最大指数に対応する要素数の配列のバリエーションを設定したドライバ３３を生成する。最大指数に対応する要素数とは、ここでは、最大指数を尾指数（配列の末尾の要素に対応する指数）とする要素数までの各要素数である。具体的には、ドライバ生成部１３は、最大指数がｎ−１の場合、要素数が０，１，・・・，ｎの各々となる配列のバリエーションを設定したドライバ３３を生成する。
【００４０】
また、ドライバ生成部１３は、算出部１２により最大指数が再算出され、最大指数が新たな値に更新された場合には、更新された最大指数の値に応じて、ドライバ３３に配列のバリエーションを追加設定する。
【００４１】
ドライバ生成装置１０は、例えば、図７に示すコンピュータ６０で実現することができる。コンピュータ６０はＣＰＵ６１、一時記憶領域としてのメモリ６２、及び不揮発性の記憶部６３を備える。また、コンピュータ６０は、表示装置及び入力装置等の入出力装置６４、記録媒体６９に対するデータの読み込みと書き込みとを制御するread/write（Ｒ／Ｗ）部６５、及びインターネット等のネットワークに接続されるネットワークinterface（Ｉ／Ｆ）６６を備える。ＣＰＵ６１、メモリ６２、記憶部６３、入出力装置６４、Ｒ／Ｗ部６５、及びネットワークＩ／Ｆ６６は、バス６７を介して互いに接続される。
【００４２】
記憶部６３は、Hard Disk Drive（ＨＤＤ）、solid state drive（ＳＳＤ）、フラッシュメモリ等によって実現できる。記憶媒体としての記憶部６３には、コンピュータ６０をドライバ生成装置１０として機能させるためのドライバ生成プログラム７０が記憶される。
【００４３】
ＣＰＵ６１は、ドライバ生成プログラム７０を記憶部６３から読み出してメモリ６２に展開し、ドライバ生成プログラム７０が有するプロセスを順次実行する。ドライバ生成プログラム７０は、スタブ生成プロセス７１と、算出プロセス７２と、ドライバ生成プロセス７３とを有する。ＣＰＵ６１は、スタブ生成プロセス７１を実行することで、図１に示すスタブ生成部１１として動作する。また、ＣＰＵ６１は、算出プロセス７２を実行することで、図１に示す算出部１２として動作する。また、ＣＰＵ６１は、ドライバ生成プロセス７３を実行することで、図１に示すドライバ生成部１３として動作する。これにより、ドライバ生成プログラム７０を実行したコンピュータ６０が、ドライバ生成装置１０として機能することになる。
【００４４】
なお、ドライバ生成プログラム７０により実現される機能は、例えば半導体集積回路、より詳しくはApplication Specific Integrated Circuit（ＡＳＩＣ）等で実現することも可能である。
【００４５】
次に、本実施形態に係るドライバ生成装置１０の作用について説明する。ドライバ生成装置１０にテスト対象クラス３１が入力されると、ドライバ生成装置１０において、図８に示すドライバ生成処理が実行される。なお、ここでは、図９左図に示すようなテスト対象クラス３１Ｃ（ＴａｒｇｅｔＣｌａｓｓ０３）が入力され、テスト対象クラス３１Ｃの整数型の変数ｘ、及び動的配列型の変数ｌｉｓｔをシンボル化の対象とする場合について説明する。また、テスト対象クラス３１Ｃの１０行目では、参照ライブラリ３５Ｃが参照される。
【００４６】
図８に示すドライバ生成処理のステップＳ１１で、算出部１２が、シンボル化対象の動的配列型の変数を格納するための集合ＳＹＭ２１、及び整数型のローカル変数を格納するための集合ＶＡＲ２３の各々を空集合として用意する。
【００４７】
次に、ステップＳ１２で、算出部１２は、テスト対象クラス３１Ｃからシンボル化対象の動的配列型の変数を抽出し、ＳＹＭ２１に格納する。ここでは、図９の（１）に示すように、変数ｌｉｓｔがＳＹＭ２１に格納される。
【００４８】
次に、ステップＳ１３で、算出部１２が、ＳＹＭ２１に格納した変数ｋ毎に、空集合の集合ＩＮＤＥＸｋ２２、及び初期値（０）に設定された削除カウンタｋ２４を用意する。ここでは、図９の（２）に示すように、変数ｌｉｓｔについてのＩＮＤＥＸｌｉｓｔ２２及び削除カウンタｌｉｓｔ２４が用意される。
【００４９】
次に、ステップＳ１４で、スタブ生成部１１が、参照ライブラリ３５Ｃのダミー部品として、図１０に示すようなスタブ３２Ｃを生成する。図１０の例では、スタブ３２Ｃは、テスト対象クラス３１Ｃの１０行目の実行時に、ＬｉｂＣｌａｓｓ．ｌｉｂ０１（））で呼び出され、返却値として「０」を返却する。
【００５０】
次に、ステップＳ１５で、算出部１２が、テスト対象クラス３１Ｃのプログラムコードを制御フローに変換する。ここでは、テスト対象クラス３１Ｃのプログラムコードは、図１１に示すような制御フローに変換される。
【００５１】
次に、ステップＳ１６で、算出部１２が、制御フローをトラバースして、全ての実行パスを抽出する。ここでは、図１２に示すように、８通りの実行パスが抽出される。なお、図１２に示す実行パスのＡ、Ｂ、・・・は、図１１に示す制御フローの各命令文（ステップ）に付した符号に対応している。
【００５２】
次に、ステップＳ１７で、算出部１２が、各実行パスをトラバースして、整数型のローカル変数を抽出し、抽出したローカル変数をＶＡＲ２３に格納する。具体的には、算出部１２が図１２に示す実行パス１をトラバースする際に、図１３の（１）に示すように、整数型のローカル変数ａを含む命令文Ａ、ローカル変数ｂを含む命令文Ｂ、及びローカル変数ｉを含む命令文Ｌの各々を通る。そこで、算出部１２は、ローカル変数ａ、ｂ、及びｉを抽出し、抽出したローカル変数ａ、ｂ、及びｉをＶＡＲ２３に格納する。他の実行パス２〜８をトラバースした場合も同じ抽出結果になるため、最終的には、図１３の（２）に示すように、ＶＡＲ２３に、ローカル変数ａ、ｂ、及びｉの３つの変数が格納された状態となる。
【００５３】
次に、ステップＳ２０で、図１４に詳細を示す最大指数算出処理が実行される。
【００５４】
最大指数算出処理のステップＳ２１で、算出部１２が、ＳＹＭ２１に格納された各変数ｋについて、各実行パスをトラバースして、変数ｋにアクセスする命令に含まれる指数を抽出し、ＩＮＤＥＸｋ２２に格納する。
【００５５】
具体的には、算出部１２が実行パス１をトラバースする際に、図１３の（３）に示すように、変数ｌｉｓｔにアクセスする命令文Ｆ、Ｇ、及びＫの各々を通る。そこで、算出部１２は、命令文Ｆ、Ｇ、及びＫの各々に含まれる指数ａ、ｂ＋ＬｉｂＣｌａｓｓ．ｌｉｂ０１（）、及び４をＩＮＤＥＸｌｉｓｔ２２に格納する。また、算出部１２が実行パス５をトラバースする際に、図１３の（４）に示すように、変数ｌｉｓｔにアクセスする命令文Ｆ、Ｇ、Ｋ、及びＮの各々を通る。そこで、算出部１２は、初めて通った命令文Ｎに含まれる指数ｉをＩＮＤＥＸｌｉｓｔ２２に格納する。他の実行パス２〜４及び６〜８をトラバースした場合には、初めて通る命令文は存在しない。そのため、最終的には、図１３の（５）に示すように、ＩＮＤＥＸｌｉｓｔ２２に、ａ、ｂ＋ＬｉｂＣｌａｓｓ．ｌｉｂ０１（）、４、及びｉの４つの指数が格納された状態となる。
【００５６】
次に、ステップＳ２２で、算出部１２が、変数ｋの配列から要素を削除する命令をカウントし、削除カウンタｋ２４にセットする。具体的には、算出部１２が実行パス３をトラバースする際に、図１３の（５）に示すようにし、変数ｌｉｓｔの配列から要素を削除する命令文Ｊを通る。そこで、算出部１２は、削除カウンタｌｉｓｔ２４の値を１インクリメントする。実行パス４、７、及び８でも命令文Ｊを通るが、命令文Ｊは実行パス３で１回通ったため、同じ命令文について２回目以降に通る場合にはカウントしない。最終的には、図１３の（６）に示すように、削除カウンタｌｉｓｔ２４の値は１となる。
【００５７】
次に、ステップＳ２３で、ＶＡＲ２３に格納された各ローカル変数ｊについて、各実行パスをトラバースして、各ローカル変数ｊが取り得る最大値を算出し、ＶＡＲ２３に記録する。
【００５８】
具体的には、算出部１２は、ＶＡＲ２３に格納されたローカル変数ａについて、実行パス１をトラバースして、命令文Ａでａ＝１に初期化し、命令文Ｄで１加算してａ＝２を得る。また、算出部１２は、実行パス２をトラバースして、命令文Ａでａ＝１に初期化し、命令文Ｅで１減算してａ＝０を得る。算出部１２は、実行パス３、５、及び７のトラバースでは、実行パス１と同様に、ａ＝２を得る。また、算出部１２は、実行パス４、６、及び８のトラバースでは、実行パス２と同様に、ａ＝０を得る。したがって、算出部１２は、ローカル変数ａの最大値を、ＭＡＸ（０，２）＝２と算出し、ローカル変数ａに対応付けて、最大値２をＶＡＲ２３に記録する。
【００５９】
また、算出部１２は、ＶＡＲ２３に格納されたローカル変数ｂについて、実行パス１をトラバースして、命令文Ｂでｂ＝２を得る。ローカル変数ｂについては、他のいずれの実行パスのトラバースでも同様の結果となる。したがって、算出部１２は、ローカル変数ｂの最大値を、ＭＡＸ（２）＝２と算出し、ローカル変数ｂに対応付けて、最大値２をＶＡＲ２３に記録する。
【００６０】
また、算出部１２は、ＶＡＲ２３に格納されたローカル変数ｉについて、実行パス１をトラバースして、命令文Ｌでｉ＝１を得る。算出部１２は、実行パス２、３、及び４のトラバースでは、実行パス１と同様に、ｉ＝１を得る。また、算出部１２は、実行パス５をトラバースして、命令文Ｍで、ｉの値はｂ＊２−１まで命令文Ｏの１加算の計算を繰り返すため、ｉ＝１＋（ｂ＊２−１）＝ｂ＊２を得る。ローカル変数ｂの最大値は２であるため、算出部１２は、ローカル変数ｉの最大値を、ＭＡＸ（１，ｂ＊２）＝ＭＡＸ（１，ＭＡＸ（ｂ）＊２）＝ＭＡＸ（１，２＊２）＝ＭＡＸ（１，４）＝４と算出する。そして、算出部１２は、ローカル変数ｉに対応付けて、最大値４をＶＡＲ２３に記録する。
【００６１】
これにより、ＶＡＲ２３は、最終的には、図１３の（７）に示すように、各ローカル変数とその最大値とが格納された状態となる。
【００６２】
次に、ステップＳ２４で、算出部１２が、ＶＡＲ２３に格納された各ローカル変数ｊの最大値、及び削除カウンタｋ２４の値を用いて、各変数ｋの最大指数を算出し、ＩＮＤＥＸｋ２２に記録する。
【００６３】
具体的には、図１５に示すように、ＩＮＤＥＸｌｉｓｔ２２に格納された各指数がローカル変数を含む場合には、算出部１２は、ＶＡＲ２３に記録されている各ローカル変数の最大値をその指数に代入する。例えば、算出部１２は、ＩＮＤＥＸｌｉｓｔ２２に格納されている指数ａに、ＶＡＲ２３に記録されているローカル変数ａの最大値２を代入する。
【００６４】
また、ＩＮＤＥＸｌｉｓｔ２２に格納された各指数がスタブ３２からの返却値を含む場合には、算出部１２は、スタブ生成部１１により生成されたスタブ３２を参照して、スタブ３２の返却値をその指数に代入する。例えば、算出部１２は、ＩＮＤＥＸｌｉｓｔ２２に格納されている指数ｂ＋ＬｉｂＣｌａｓｓ．ｌｉｂ０１（）に含まれるＬｉｂＣｌａｓｓ．ｌｉｂ０１（）に、スタブ３２Ｃからの返却値０を代入する。
【００６５】
そして、算出部１２は、ＩＮＤＥＸｌｉｓｔ２２に格納された値の最大値を取得し、その最大値に削除カウンタｌｉｓｔ２４の値を加算した値を、変数ｌｉｓｔについての最大指数として算出し、ＩＮＤＥＸｌｉｓｔ２２に記録する。ここでは、図１５に示すように、ＩＮＤＥＸｌｉｓｔ２２に格納された値の最大値は４であり、これに削除カウンタｌｉｓｔ２４の値１が加算され、変数ｌｉｓｔについての最大指数は５となる。
【００６６】
ここで、指数の最大値に削除カウンタ２４の値を加算する理由について説明する。
【００６７】
要素を削除する前の配列がｎ個の要素を持つ場合において、要素をｍ個削除すると、その配列の尾指数はｎ−１−ｍになる。配列の指数ｐ（削除カウンタ２４の値を加算する前の指数の最大値）にアクセスするとき、ｎ−１−ｍがｐ以上でないと、ＮｕｌｌＰｏｉｎｔｅｒＥｘｃｅｐｔｉｏｎの例外が発生する。そのため、ｎ−１−ｎ≧ｐ（つまりｎ−１≧ｐ＋ｍ）の条件を満たすように、指数ｐに少なくともｍの値を加算して最大指数を算出する必要がある。すなわち、指数ｐは、テスト対象クラス３１で使用される指数の最大値ではあるが、実際の配列の要素数の最大値を算出するためには、配列の要素を削除する命令も考慮する必要がある。
【００６８】
例えば、テスト対象クラス３１Ｃの１０行目の段階（命令文Ｇ、図９及び図１１参照）で、配列が図１６に示すように５個の要素を持っているとする。この場合、配列の尾指数は４である。テスト対象クラス３１Ｃの１１〜１４行目（命令文Ｈ、Ｉ、及びＪ、図９及び図１１参照）が、図１６の枠５３内に相当する。配列の要素が１つ削除されると要素数は４となり、尾指数は３となる。この場合、テスト対象クラス３１Ｃの１５行目（命令文Ｋ、図９及び図１１参照）で配列の指数４にアクセスした際に、ＮｕｌｌＰｏｉｎｔｅｒＥｘｃｅｐｔｉｏｎの例外が発生する。なお、配列の要素を追加する命令については、配列へのアクセスに用いる指数より、実際の配列の指数の方が大きくなる処理であるため、特に考慮する必要はない。
【００６９】
ＳＹＭ２１に格納された各変数ｋについての最大指数の算出が終了すると、最大指数算出処理は終了し、処理は図８に示すドライバ生成処理に戻る。
【００７０】
次に、ドライバ生成処理のステップＳ３１で、ドライバ生成部１３が、ＩＮＤＥＸｋ２２に記録された各変数ｋの最大指数を尾指数とする要素数までの各要素数の配列のバリエーションを設定したドライバ３３を生成する。例えば、変数ｌｉｓｔについての最大指数が５と算出されている場合には、ドライバ生成部１３は、図１７の破線部４６に示すように、要素数が０、１、２、３、４、５、及び６の配列のバリエーションを、ドライバ３３Ｄに設定する。
【００７１】
次に、ステップＳ３２で、算出部１２が、上記ステップＳ１４で生成されたスタブ３２が、例えばユーザにより修正されるなどして、変更されたか否かを判定する。例えば、スタブ３２が変更された場合に、その旨を示すフラグを設定しておいたり、上記ステップＳ１４で生成されたスタブ３２と、本ステップ実行時におけるスタブ３２とに差分があるか否かを判定したりすることにより、本ステップの判定を行うことができる。スタブ３２が変更されている場合には、処理は図１４に示す最大指数算出処理のステップＳ２３へ移行する。
【００７２】
スタブ３２が変更された後のステップＳ２３及びＳ２４では、算出部１２が、変更後のスタブ３２の返却値を用いて、各変数ｋについての最大指数を再算出する。例えば、図１８に示すように、ＬｉｂＣｌａｓｓ．ｌｉｂ０１（）で呼び出されるスタブ３２Ｃの返却値が０から３に変更されたとする。この場合、図１８の破線の楕円部で示すように、変数ｌｉｓｔについての最大指数は５から６に更新される。
【００７３】
次に、図８に示すドライバ生成処理に戻り、ステップＳ３１で、ドライバ生成部１３が、更新された最大指数の値に応じて、ドライバ３３に配列のバリエーションを追加設定する。図１８に示すように、変数ｌｉｓｔについての最大指数が５から６に更新された場合には、ドライバ生成部１３は、図１９の破線部４７に示すように、要素数が７の配列のバリエーションをドライバ３３Ｄに追加設定する。
【００７４】
なお、スタブ３２からの返却値が変更されても、スタブ３２からの返却値を使用する指数より大きな値の指数がＩＮＤＥＸｋ２２に存在する場合には、前回算出された最大指数は更新されない。その場合には、ドライバ生成部１３による配列のバリエーションの追加も行われない。
【００７５】
ステップＳ３２で、スタブ３２が変更されていないと判定されると、ドライバ生成処理は終了する。
【００７６】
以上説明したように、本実施形態に係るドライバ生成装置によれば、テスト対象クラスにおいて、配列にアクセスする命令に含まれる指数の最大値に対応する要素数の配列のバリエーションを設定したドライバを生成する。このように生成されたドライバを用いてシンボリック実行によりテストケースを生成すると、配列にアクセスする命令箇所でのテストの実行失敗を抑制することができる。また、配列の要素数に応じた条件分岐においても、何れかの分岐先の命令が実行されないといったテスト網羅性の低下を抑制することができる。これにより、テストの効率化が図れる。
【００７７】
例えば、図９に示すテスト対象クラス３１Ｃに対して、図１０に示すスタブ３２Ｃ（ＬｉｂＣｌａｓｓ．ｌｉｂ０１（）に対する返却値が０）、及び図１７に示すドライバ３３Ｄが生成されたとする。ドライバ３３Ｄには、要素数が０、１、２、３、４、５、及び６の配列のバリエーションが設定されている。
【００７８】
このドライバ３３Ｄでテスト対象クラス３１Ｃを実行した場合、ＬｉｂＣｌａｓｓ．ｌｉｂ０１（）の返却値は０であるため、１０行目において、ｌｉｓｔ．ｇｅｔ（２＋０）でｌｉｓｔにアクセスされる。ドライバ３３Ｄには、要素数が３以上の配列のバリエーションが存在するため、ＮｕｌｌＰｏｉｎｔｅｒＥｘｃｅｐｔｉｏｎの例外は発生せず、ｌｉｓｔ．ｇｅｔ（２＋０）が問題なく実行される。
【００７９】
また、テスト対象クラス３１Ｃの１５行目のｌｉｓｔ．ｇｅｔ（４）についても、ドライバ３３Ｄには、要素数が５以上の配列のバリエーションが存在するため、ＮｕｌｌＰｏｉｎｔｅｒＥｘｃｅｐｔｉｏｎの例外は発生せず、ｌｉｓｔ．ｇｅｔ（４）が問題なく実行される。
【００８０】
また、テスト対象クラス３１Ｃの１７行目のｌｉｓｔ．ｇｅｔ（ｉ）について、ｉ＝０，１，２，３であるが、ドライバ３３Ｄには、要素数が１〜４の各配列のバリエーションが存在する。そのため、ＮｕｌｌＰｏｉｎｔｅｒＥｘｃｅｐｔｉｏｎの例外は発生せず、ｌｉｓｔ．ｇｅｔ（ｉ）が問題なく実行される。
【００８１】
また、ドライバ３３Ｄには、要素数が３以下の配列のバリエーションも、要素数が４以上の配列のバリエーションも存在する。したがって、５行目の条件分岐は、ｔｒｕｅの場合及びｆａｌｓｅの場合共に実行され、コードカバレッジが向上する。
【００８２】
なお、上記実施形態では、Ｊａｖａ（登録商標）で記述されたクラス及びメソッドを、テスト対象のプログラムとする場合について説明したが、これに限定されない。開示の技術は、他の言語で記述されたプログラム、特に、オブジェクト指向言語で記述されたプログラムに適用可能である。
【００８３】
また、上記では、ドライバ生成プログラム７０が記憶部６３に予め記憶（インストール）されている態様を説明したが、これに限定されない。開示の技術に係るプログラムは、ＣＤ−ＲＯＭ、ＤＶＤ−ＲＯＭ、ＵＳＢメモリ等の記録媒体に記録された形態で提供することも可能である。
【００８４】
以上の実施形態に関し、更に以下の付記を開示する。
【００８５】
（付記１）
コンピュータに、
テスト対象のプログラムから、配列にアクセスする命令に含まれ、かつ該配列の要素を指定する指数を抽出し、抽出した指数に基づいて、前記テスト対象のプログラムからアクセスされる配列の最大指数を算出し、
前記テスト対象のプログラムのシンボリック実行時におけるシンボル化対象の配列のバリエーションとして、算出した前記最大指数に対応する要素数の配列のバリエーションを設定したドライバを生成する
ことを含む処理を実行させるドライバ生成プログラム。
【００８６】
（付記２）
前記最大指数を算出する際に、前記テスト対象のプログラムに含まれる変数が使用されている指数については、該変数が取り得る最大値を用いて該指数の値を計算する付記１記載のドライバ生成プログラム。
【００８７】
（付記３）
前記最大指数を算出する際に、前記テスト対象のプログラムのシンボリック実行時に該テスト対象のプログラムから呼び出されるスタブの返却値を使用する指数については、該返却値を用いて該指数の値を計算する付記１又は付記２記載のドライバ生成プログラム。
【００８８】
（付記４）
前記スタブの返却値が変更された場合には、前記最大指数を再度算出し、該最大指数が更新された場合には、前記ドライバに設定する配列のバリエーションを追加する付記３記載のドライバ生成プログラム。
【００８９】
（付記５）
前記テスト対象のプログラムに配列の要素を削除する命令が含まれる場合、抽出した指数の値の最大値に、前記配列の要素を削除する命令により削除される要素数を加算した値を、前記最大指数として算出する付記１〜付記４のいずれか１項記載のドライバ生成プログラム。
【００９０】
（付記６）
前記指数を抽出する際、前記テスト対象のプログラムを制御フローに変換し、該制御フローをトラバースして、前記配列にアクセスする命令を探索する付記１〜付記５のいずれか１項記載のドライバ生成プログラム。
【００９１】
（付記７）
前記配列のバリエーションは、０から前記最大指数に１加算した値まで１ずつ加算した値の各々を要素数とする配列の各々である付記１〜付記６のいずれか１項記載のドライバ生成プログラム。
【００９２】
（付記８）
テスト対象のプログラムから、配列にアクセスする命令に含まれ、かつ該配列の要素を指定する指数を抽出し、抽出した指数に基づいて、前記テスト対象のプログラムからアクセスされる配列の最大指数を算出する算出部と、
前記テスト対象のプログラムのシンボリック実行時におけるシンボル化対象の配列のバリエーションとして、算出した前記最大指数に対応する要素数の配列のバリエーションを設定したドライバを生成する生成部と、
を含むドライバ生成装置。
【００９３】
（付記９）
前記算出部は、前記最大指数を算出する際に、前記テスト対象のプログラムに含まれる変数が使用されている指数については、該変数が取り得る最大値を用いて該指数の値を計算する付記８記載のドライバ生成装置。
【００９４】
（付記１０）
前記算出部は、前記最大指数を算出する際に、前記テスト対象のプログラムのシンボリック実行時に該テスト対象のプログラムから呼び出されるスタブの返却値を使用する指数については、該返却値を用いて該指数の値を計算する付記８又は付記９記載のドライバ生成装置。
【００９５】
（付記１１）
前記スタブの返却値が変更された場合には、前記算出部は、前記最大指数を再度算出し、該最大指数が更新された場合には、前記生成部は、前記ドライバに設定する配列のバリエーションを追加する付記１０記載のドライバ生成装置。
【００９６】
（付記１２）
前記算出部は、前記テスト対象のプログラムに配列の要素を削除する命令が含まれる場合、抽出した指数の値の最大値に、前記配列の要素を削除する命令により削除される要素数を加算した値を、前記最大指数として算出する付記８〜付記１１のいずれか１項記載のドライバ生成装置。
【００９７】
（付記１３）
前記算出部は、前記指数を抽出する際、前記テスト対象のプログラムを制御フローに変換し、該制御フローをトラバースして、前記配列にアクセスする命令を探索する付記８〜付記１２のいずれか１項記載のドライバ生成装置。
【００９８】
（付記１４）
前記配列のバリエーションは、０から前記最大指数に１加算した値まで１ずつ加算した値の各々を要素数とする配列の各々である付記８〜付記１３のいずれか１項記載のドライバ生成装置。
【００９９】
（付記１５）
コンピュータに、
テスト対象のプログラムから、配列にアクセスする命令に含まれ、かつ該配列の要素を指定する指数を抽出し、抽出した指数に基づいて、前記テスト対象のプログラムからアクセスされる配列の最大指数を算出し、
前記テスト対象のプログラムのシンボリック実行時におけるシンボル化対象の配列のバリエーションとして、算出した前記最大指数に対応する要素数の配列のバリエーションを設定したドライバを生成する
ことを含む処理を実行させるドライバ生成方法。
【０１００】
（付記１６）
前記最大指数を算出する際に、前記テスト対象のプログラムに含まれる変数が使用されている指数については、該変数が取り得る最大値を用いて該指数の値を計算する付記１５記載のドライバ生成方法。
【０１０１】
（付記１７）
前記最大指数を算出する際に、前記テスト対象のプログラムのシンボリック実行時に該テスト対象のプログラムから呼び出されるスタブの返却値を使用する指数については、該返却値を用いて該指数の値を計算する付記１５又は付記１６記載のドライバ生成方法。
【０１０２】
（付記１８）
前記スタブの返却値が変更された場合には、前記最大指数を再度算出し、該最大指数が更新された場合には、前記ドライバに設定する配列のバリエーションを追加する付記１７記載のドライバ生成方法。
【０１０３】
（付記１９）
前記テスト対象のプログラムに配列の要素を削除する命令が含まれる場合、抽出した指数の値の最大値に、前記配列の要素を削除する命令により削除される要素数を加算した値を、前記最大指数として算出する付記１５〜付記１８のいずれか１項記載のドライバ生成方法。
【０１０４】
（付記２０）
前記指数を抽出する際、前記テスト対象のプログラムを制御フローに変換し、該制御フローをトラバースして、前記配列にアクセスする命令を探索する付記１５〜付記１９のいずれか１項記載のドライバ生成方法。
【０１０５】
（付記２１）
前記配列のバリエーションは、０から前記最大指数に１加算した値まで１ずつ加算した値の各々を要素数とする配列の各々である付記１５〜付記２０のいずれか１項記載のドライバ生成方法。
【０１０６】
（付記２２）
コンピュータに、
テスト対象のプログラムから、配列にアクセスする命令に含まれ、かつ該配列の要素を指定する指数を抽出し、抽出した指数に基づいて、前記テスト対象のプログラムからアクセスされる配列の最大指数を算出し、
前記テスト対象のプログラムのシンボリック実行時におけるシンボル化対象の配列のバリエーションとして、算出した前記最大指数に対応する要素数の配列のバリエーションを設定したドライバを生成する
ことを含む処理を実行させるドライバ生成プログラムを記憶した記憶媒体。
【符号の説明】
【０１０７】
１０   ドライバ生成装置
１１   スタブ生成部
１２   算出部
１３   ドライバ生成部
２１   ＳＹＭ集合
２２   ＩＮＤＥＸ集合
２３   ＶＡＲ集合
２４   削除カウンタ
３１   テスト対象クラス
３２   スタブ
３３   ドライバ
６０   コンピュータ
６１   ＣＰＵ
６２   メモリ
６３   記憶部
６９   記録媒体
７０   ドライバ生成プログラム
【図１】
0006583033.tif 000002
【図２】
0006583033.tif 000003
【図３】
0006583033.tif 000004
【図４】
0006583033.tif 000005
【図５】
0006583033.tif 000006
【図６】
0006583033.tif 000007
【図７】
0006583033.tif 000008
【図８】
0006583033.tif 000009
【図９】
0006583033.tif 000010
【図１０】
0006583033.tif 000011
【図１１】
0006583033.tif 000012
【図１２】
0006583033.tif 000013
【図１３】
0006583033.tif 000014
【図１４】
0006583033.tif 000015
【図１５】
0006583033.tif 000016
【図１６】
0006583033.tif 000017
【図１７】
0006583033.tif 000018
【図１８】
0006583033.tif 000019
【図１９】
0006583033.tif 000020