HP SoftBench 環境 C / C 十十用テスト検証ツ David L. Neuder ソフトウェア製品のテストは、ソフトウェアの開発サイ クルに応していくっかの異なる形態をとる。図 1 ( 59 ペー ジ ) はテストがおこなわれる時機を表している。プロジェ クトのスケジュール、ソフトウェア製品の種類などの要因 によって、すべての局面でテストをおこなうか否か、どの 程度詳細にテストをおこなうかが決まる。通常、実行可能 モジュールのテストは、ソフトウェア製品の種類にかかわ りなく、部分的にも ( モジュール単位のテスト ) 、全体的に も ( 統合テスト ) テストされる。モジュール単位のテストの 場合、コードと同時にそのテストのためのコードも書かれ るので、開発者がコードを熟知しており、遺漏が少なくな る傾向がある。適切に構成されたモジュール・テストは、 欠陥の見落としや、コードの修正によって生しる副作用を 減らすのに著しい効果がある。しかし、自動化された支援 がなけれは、開発者がすべてのモジュールをテストするコ ードを書くのにかなりの時間を費やしてしまうし、テスト の有効性の測定も困難になる [ 1 ] 。 HP Branch VaIidator は、ソフトウェアの実行および テストの検証をおこなうツールであり、分岐分析を用いて モジュール単位のテストの効率を高める。このツールは、 C プログラムを分析し、ソフトウェア・アプリケーション のどの分岐が実行されたのかを論理的に検証する。分岐は、 コード中のデシジョン・ポイント以降の経路として定義さ れる。デシジョン・ポイント以降のさまざまな経路が、そ れぞれアプリケーションの分岐になる。 HP Branch Validator は、これらの分岐がすくなくとも 1 度は実行さ れたかどうかを調べる。図 2 ( 59 べージ ) に、プログラム・ はじめに 58 フローにおけるデシジョン・ポイントの分岐を示す。 HP Branch VaIidator は Encapsulator [ 1 ] [ 2 ] を使 うことで染みやすいウインドウ・インターフェイスを提 供し、分岐カバレッジ ( coverage ) の分析処理を手早くで きるようにしている。このインターフェイスにより、 HP Branch Validator は、スタンドアローンの製品としても、 統合された SoftBench 環境 [2] の一員としても実行でき るようになっている。さらに、コマンド行インターフェイ ス上から、 SoftBench 使用時に作成されるレポートに似た 分岐カバレッジレポートを作成することもできる。このた め、グラフィカルでない端末でも実行できる。 HP BranchVaIidator のネイテイプ・バージョンと組 込みバージョンは、いすれも HP 9000 シリーズ 300 / 400 / 800 をホストとして実行される。組込みバージョンは、組 込みマイクロプロセッサ開発アプリケーションのための AxLS C 言語をサポートする。ネイテイプ・バージョン は、 HP-UX C および C 十十をサポートする。 HP Branch VaIidator は、 C プログラムを処理するよ うに設計されている。 C 十十プログラムを扱う場合には、 C 十十のファイルを C のファイルに変換しなければならな い。処理はこの C ファイルに対しておこなわれる。 C 十十コ ンパイラの適切なオプションを選べば、 C 十十ファイルか らオプジェクト・ファイルへのコンパイル処理は 1 度です む。このようにして得られた分析結果は、もとの C 十十ソ ースファイルに反映される。 HP Branch Validator は、 HP Branch Validator プ ロセッサ、 HP BranchValidator レポート・ジェネレー 夕、 HP Branch Validator SoftBench インターフェイ スの 3 つの部分からなる。図 3 (59ページ ) に、 HPBranch ValidatorSoftBench インターフェイスの画面の例を示す。 UNIX MAGAZINE 1991.12
分岐を分析の対象から除外または無視したり、特定の分岐 が実行された場合に警告を受けることができる。マップフ ァイルにはこの情報が含まれており、これらの条件がみつ かった場合、レホート・ジェネレータはこの情報に従って 適切な対応を施す。これらの測定方法は、コマンド行オプ ションによってコンパイル時に選択される。 HP Branch VaIidator の 2 つのプリプロセッサによる 処理が終了すれば、コードは標準の C または ANSI C コン パイラでコンノヾイルできる。 HP BranchValidator のダ ンプ・ユーティリティは各ファイルの HP Branch Validator データをダンプする方法を知っている。そし て、このなかでコンパイルとリンクをおこなったあと、得 られた実行形式が実行され、一連のテストが課せられる。 この実行形式ファイルは、終了ないしはデータのダンプ指 示が出されると、ダンプファイルを生成する。このファイ —hit-—total-—%- function _IA_ 3 / 12 ( 66.67 ) keyconvert 9 ( 66.67 ) bitpos 1 ( 0.0 の error 5 ( 60.00 ) getkeyvalue 7 ( 71.43 ) twobits HP SoftBench 、、、ルはレホート・ジェネレータによって解釈され、分岐カバ レッジの結果に関するサマリおよびソースレベルのレポー トが生成される。 レポート・ジェネレータ HP Branch Validator のレポート・ジェネレータは、 プリプロセッサによって変換された各関数のなかで実行ま たはヒットした分岐の数と割合を表すサマリレポートを作 成し、ソースレポートは実行されなかった個々の分岐につ いての情報を提供する。レポート・ジェネレータは、プロ グラムの実行中に分岐配列に格納された情報と、プリプロ セッサが生成したマップファイルからレポートを作成する。 典型的なサマリレポートは次のようになる。 file convert . C convert . C driver. C getkey. c multibits. c 22 out of 34 retaxned branches executed(64.71 % ) の分岐のうちの 22 が実行されたことを示している。この の分岐カバレッジは 64.71 % で、全部で 5 つの関数の 34 の 12 分岐のうちの 8 すなわち 66.67 % が実行され、合計 この例では、ファイル convert. c 中の関数 keyconvert [ 23 branches were ignored] レポート・ジェネレータのソースレホートでは、実行さ れない関数の個々の分岐についての情報を提供する。この 情報には、分岐の行番号、ソースファイル名、および分岐 のどの部分が実行されないかを説明する情報が含まれる。 典型的なソースレポートは次のような形式をとる。 分析において 23 の分岐が無視されている。 keyconvert convert . C ( 1 ) co Ⅱ dit 土 0 Ⅱ of ' if ) was never ・ I*R ( 旧 36 ー > if (keycode > KEY-9) ( 1 ) conditional Of ' if ' was never FALSE = 1 ) 44 ー > if ( ho て iz ( 1 ) conditional 0f 'd0 while ' was never NUE 49 ー > while (horiz ! = 0 ) ; ( 1 ) conditional 0f 'do while ' was never FALSE 49 ー > while (horiz ! = 0 ) ; 8 out of 12 branches executed(66.67 % ) ( Ⅱ 0 ' e1se ' statement) / * special case for 0 key * / この例では、ファイル convert. c 中の関数 keyconvert のなかの 4 つの分岐が実行されていない。最初は 36 行目 UNIX MAGAZINE 1991.12 の分岐であり、この分岐の条件部はけして真にならない ( keycode の値は絶対に KEY-9 よりも大きくならない ) 。 65
プ、分岐のソースファイルにおける行と列の範囲を示して いる。そして、最後に分岐を制御する部分のソースコード が含まれる。これは分岐を無見すべきか否かを決定すると きに使われる。 HP BranchValidator のプリプロセッサは、実際には 2 つのプリプロセッサ HP SoftBench 、、、 2 つのプリプロセッサから構成され、順番に呼び出される。 最初のプリプロセッサは ANSI C プリプロセッサを基本 としているが、ソースがより簡単に参照できるように拡張 されている。拡張されているのは、マクロがどのように展 開されるかについての情報を 2 番目のプリプロセッサに与 える機能である。たとえば、次のマクロ定義とマクロ呼出 しを考えてみよう。 #define IF-GREATER_5_SQUARE(a) if (a > 5 ) {a = a*a; } IF-GREATER-5-SQUARE(c) ; この結果は次のようなコードになる。 AAif (c>5){c=c*c ; FBIF-GREATER-5-SQUARE(c)T; A 、 B 、 AC(Ctrl-A 、 B 、 C) は、マクロが呼び出され たときに、もとのマクロソースの列と行の位置を調べるた めに使われる。この情報は、あるマクロに関連する分岐を もとのマクロテキストにマップするために使用される。 1 番目のプリプロセッサは、行番号情報も付加して、処理さ れたテキストともとのテキストの対応が容易にとれるよう にする。 UNIX MAGAZINE 1991.12 配列が値 0 に初期化されることを示す。つまり、分岐が の各要素は 0 ( ゼロ ) に初期化される。 2 行目は 20 個の ・配列を作成する。その要素数は分岐の数であり、配列中 2 番目のプリプロセッサは以下の処理をおこなう。 変換する ) はリスト 4 ( 63 べージ ) のようになる。 セッサを呼び出した結果 ( 分岐分析用にソースファイルを プロセッサの場合と結果は同しである。 2 番目のプリプロ A 、 B 、 C が付加されることを除けば、標準の C プリ ページ ) のようになる。 最初のプリプロセッサを呼び出した結果はリスト 3 ( 62 がどのような処理をおこなうかを示す。 スト 2 ( 62 ページ ) のソースプログラムは、プリプロセッサ ァイルにマップするために必要な情報が含まれている。リ このマップファイルには、特定の分岐を関連するソースフ 配列定義を付加する。さらに、マッフファイルも生成する。 ファイルを yacc と lex を使って解釈し、適切な分岐文と 果を解析する。最初のプリプロセッサによって生成された 2 番目のプリプロセッサは、最初のプリプロセッサの結 20 カ所あることを示している。 ・各分岐ごとに、 ◆ 1 つの配列工ントリを割り当てる。 ◆ 2 番目のプリプロセッサは、以下に挙げるさまざまな部 機能もある。 って、あるいは指定されたルーチンの実行前に呼び出す のダンプルーチンを HP ー UX のシステムシグナルによ データ配列に含まれるデータをダンプする。さらに、 ダンプルーチン ( 61 行目 ) は、ルーチンが終了するときに ・最後に分岐分析ダンプルーチンへの呼出しを挿入する。 の数などのパラメータを指定する。 ようにするものである。データ領域はコンパイル、分岐 ルの不整合を防ぎ、ソースファイルの変更を監視できる 域を作成する ( 62 ~ 85 行目 ) 。このデータはマップファイ ・新しく作成されたソースファイルの終りに環境データ領 ープなど ) 、関連する行番号と列番号などを示す。 用に作成する。これは、その分岐の種類 ( if 文、 for ル ◆マップファイルへのエントリを、分岐の配列工ントリ とを示す。 実行されたとき、 2 番目の配列要素がセットされるこ 条件式、、赶 ( a = = O)" が偽である場合に対応する分岐が 番目の配列要素がセットされることを示す。 19 行目は が真である場合に対応する分岐が実行されたとき、 1 と同し行に挿入される。 17 行目は条件式、、 if(a==O)" 文の正しい行番号を報告できるように、最初の実行文 れたことを表す。また、代入文は、デバッガがソース 文は対応する配列のエントリを 1 にセットし、実行さ 代入文を分岐内の最初の実行文として挿入する。代入 61
リスト 5 C 十十のサマリレポートの例 IA___function file_ 1 / 1 / 1 / 3 / 2 / 3 / 19 / 10 / 6 / 4 / 2 / 1 / 5 / 2 / 7 / 1 / 1 (100.00)BoardRec : : SetPiece(PieceRec*) 1 ( 100.00 ) Boa て dRec : : C1ear() 1 ( 100.00 ) BoardRec : :Repaint(ScrnRec*) 3 ( 100.00 ) BoardRec : : Repaint() 3 ( 66.67)DoRep1ace(void*) 3 ( 18.00)DoPaintMe(void*) 21 (90.48)Paint(int ,int,Direction,Direction, 11 (90.91)TripF10w(void*) 7(85.71)F10wRefigureDe1tas() 5 ( 80.00)F10wRepaint() 3 ( 66.67 ) 矼。 wF t ( ) 1 ( 100.8 ) FI 。 t t ( ) 5 ( 100.00 ) I Ⅱ itLeveI ( ) 3 ( 66.67)PieceRec: :Paint(ScrnRec* , int ,int) 9 ( 77.78)ScrnRec : :RefigureSizes() 1 ( 18.00)ScrnRec: :GetPieceCache(PieceRec*) int) 情報を表示できるようにするウィジェット ) に関係した 問題は、ユーサーがどの行を選択したかを正確に決めるの が困難な点である。これは、行のテキストは返されるが行 番号は返されないからである。 2 つの同しテキスト行が画 面上にある場合、どちらの行をユーザーが選択したかを知 るのは不可能である。この問題を回避するために、各行に 行番号を付加した。番号は各テキスト行の終り ( 通常はリス トウィジェットの画面外 ) に付けられた。リストウィジェッ トを右にスクロールすれば、ユーザーはこれらの番号を見 ることができるが、通常時には表示されない。ューサーの 選択したテキスト行と同時に行番号も読み込まれ、ユーサ ーが選択したのがどの行で、次の行がどの行かが分かる。 Encapsulator の 2 番目の問題は、アプリケーションの 名前として複数ワードのラベルを使用できないことである。 Encapsulator は連続した文字列しか名前として受け付け ないので、 HP Branch VaIidator の名前を画面上に 、、 Branch VaIidator" のような表示することはできない。 さらに、名前は 9 文字までという制限がある。この問題を 回避するために、、、 BBA 〃という名前を使うことにした。 れは、 HP Branch Validator の技術のうち、とくに基礎 的な分岐分析を表す名称である。 一般に、 Encapsulator は HP Branch Validator に実 装の容易なグラフィック・インターフェイスを提供してい る。これによって、市場に出すまでの時間がめざましく短 縮できる一方で、多くの機能を実装できた。さらに、 HP Branch Validator SoftBench インターフェイスをはか のプラットフォームに移植するには、 Encapsulator ファ イルをたんに再コンパイルするだけでよい。しかし、 HP UNIX MAGAZINE 1991.12 HP SoftBench . C . C board board.. C board. C board.. C board. ースレポート ( 部分 ) は次ページのリスト 6 のようになる。 上記のファイルに対する HP Branch VaIidator のソ リスト 5 に C 十十のサマリレポートの例を示す。 c 十十 filt ( 1) ューティリティを実行しなければならない。 を使う場合、読みやすい関数呼出しを生成させるために みえる。コマンド行バージョンの HP BranchValidator Branch Validator からは C 十十の関数名は暗号化されて Branch Validator は本来は C のツールであり、 HP ンターフェイスのいすれからでも見ることができる。 HP C 十十の分岐分析の結果は、コマンド行と SoftBench イ イル内の分岐に対応する C 十十のソース行を参照する。 ッサは、これらの行とファイル指示を取り出して、 C ファ イルに入れられる。 HPBranchValidator のプリプロセ のファイルに関する行とファイルの指示は標準の C ファ きる。 C 十十のファイルを C に変換しているあいだ、 C 十十 ルからオプジェクト・ファイルへのコンパイルは 1 度でで かのオプションとともに使用すれは、 C 十十ソースファイ のである。 C 十十のための十 i コンパイラ・オプションをほ BranchVaIidator にその C ファイルをコンパイルさせる で扱うには、 C 十十のファイルを C に翻訳してから、 HP 関する情報も提供する。 C 十十を HP Branch VaIidator HP Branch VaIidator は C 十十の実行されない分岐に C 十十の分岐 純ではなかった。 VaIidator レポート・ジェネレータの移植は、それほど単 Branch Validator のプリプロセッサおよひ HP Branch screen . C screen . C pxece . C init . C f10v. c f10w. c f10V. c f10 . c f10W. c f10w. c 69
HP SoftBench 2 番目は 44 行目の分岐であり、これは偽にならない (horiz の値はつねに 1 である ) 。 0 'else' statement" という文は、もとのコードには else 条件がなかったことを 示す情報メッセージである。最後の 2 つのメッセージは同 し 49 行目の分岐に関するものである。分岐の条件が真に も偽にもならないというのは、言い換えればこの分岐が 1 度も実行されないことを示している。このような場合、こ ( 3 ) ) then ' part of ' if ' was never executed ゝの分岐の前には return 文があるはすである。 1 つの上位の分岐により分岐のグループ全体が制御さ れる場合、実行されないことが示されるのは全体を制御し ている分岐ただ 1 つだけである。説明文の前にある括弧内 の数は、制御文のために実行されることのない隠れた分岐 の数である。たとえは歌の例を見てみよう。 55 ー > 56 58 59 60 52 / * First test : if both ho て iz 田 id vert are 0 * / = の (vert = = 0 ) ) if ( (horiz retuxn (KEY-NONE) ; else return (KEYEROR) ; if (is-error) is_error = check_error() , この ( 全体を制御する ) 分岐が実行されなかったという ことは、 3 つの下位の分岐も実行されないことを意味する。 3 つの分岐の 1 番目は "if( (horiz = = O) &&(vert = = O) ) 〃 分岐の then 節であり、 2 番目は "if(is-error)" 分岐の then 節、 3 番目は hf (is-error)" 分岐の else 節である。 ソースレポートは着目したい分岐について、より多くのソ ース行を要求に応して表示できることもこの例から分かる。 HP Branch Validator によって変換されたプログラム は、実行されるつど、環境データとともに分岐配列に格納 されるデータをダンプファイルに追加する。 次にレポート・ジェネレータは、各ソースファイルのダ ンプファイルとマップファイルを調べて、サマリレポート およびソース行レポートを生成するための情報を得る。と くに、レポート・ジェネレータは、変換された各ソースフ ァイルのそれぞれの分岐配列を調べる。マップファイルか ら、分岐の種類と実行される分岐の配列要素に入る値カ吩 かる。特定の分岐が実行されなかった場合、分岐の種類と 実行されなかった理由が報告される。分岐に対応するソー スコードは、マップファイルに保存されている分岐の行番 号から得られる。次に、分岐のソースがもとのソースファ イルから読み直される。たとえば、 ( 4 ) conditional of ) if ) was never IRIJE 53 ー > if (value ー 0 ) if (value > 1900 ) の場合、分岐 if(value = = O) の then 節は 35 番目の配列要 66 素に代入されている。この分岐は実行されなかったので、 35 番目の配列要素の値は 0 ( ゼロ ) である。レポート・ジェ ネレータが配列要素 35 をみつけると、レポート・ジェネレ ータはその値と if 条件文の then 節を結びつける。また、 この分岐の行番号、 if 条件のソースの範囲、およびこの分 岐が実行されなかったことで影響を受ける分岐の数 ( 4 ) が 分かる。 HP Branch VaIidator を使用する目的は、できるかぎ り高い分岐カバレッジを達成することである。さらに何度 もテストを繰り返すことが、より高いカバレッジを達成す る主要な方法である。しかし、テストをおこなっても無駄 な分岐や、ほかのユーサーによってすでに徹底的にテスト されている部分もあるだろう。どちらの場合にも、これら の分岐を無視するか、関数全体を分岐カバレッジの計測対 象から除外することが重要になるであろう。 HP Branch Validator には、レポートを作成するとき にユーサーがレポート・ジェネレータに対して特定のファ イル、関数および分岐を無視させる機能がある。この機能 を使うには、無視すべきファイル、関数および分岐の名前 を、、 ignore ファイルクに入力する。レポート・ジェネレー タはレポートの準備をするときに ignore ファイルを調べ て、そのなかにリストされている項目 ( ファイル、関数およ び分岐文 ) をレポートから削除する。この機能は、レポー ト・ジェネレータが ignore ファイル内の各項目を ignore ハッシュ・テープルに登録することで働く。各ファイル、 UNIX MAGAZINE 1991.12
HP SoftBench 関数および分岐が順に調べられるとき、ます、それが ignore ハッシュ・テープルに入っているか否かが検査され る。ある項目が ignore ハッシュ・テーフ・ルのなかにある場 合には、その項目は無視 ( あるいはスキップ ) される。分岐 を無視するには、ユーサーは分岐の制御文を表す文字列を 入力しなければならない。レポート・ジェネレータは、マ ップファイルに含まれている各分岐のための制御文と ignore ファイルに含まれている制御文とを比較する。たと えば ignore ファイルに /users/cc/driver. C /users/cc/convert . C keyconvert /users/cc/convert . C bitpos : case 32 : という情報が含まれている場合には、以下の分岐は無視さ れる。 ・ファイル /users/cc/dnver. c 内のすべての分岐 ・ファイノレ /users/cc/convert. c 内の関数 keyconvert 内のすべての分岐 ・ファイル /users/cc/convert. c 内の関数 bitpos 内の case 32 : に関連する分岐 SoftBench インターフェイス SoftBench インターフェイスは HP Branch Validator のコマンド行インターフェイスよりも親しみ やすいユーザー・インターフェイスである。 SoftBench イ ンターフェイスを使えば、ユーザーは分岐カバレッジを対 ートの例を示す。関数ヒストグラムは、同し関数サマリ情 報をヒストグラムの形式で提供する ( 図 6 ) 。これにより、 話的に調べ、実行されていない分岐を素早くみつけ、分岐 指定された分岐カバレッジの基準を満たしていない関数 カバレッジの結果を改善するために適切な対応をとること を素早くみつけることができる。 ができる。たんにマウスポタンをクリックするだけで、ユ ソースレポートは、指定したファイルまたは関数のなか ーサーは、分岐の無視、通過しなかった分岐を含むソース ファイルの編集、前後の実行されていない分岐の位置を決 の通過しなかった分岐とソースコードを表示することが できる。図 7 はソースレポートの例で、指定した関数中の めることができる。 SoftBench インターフェイスは、ファイルと関数のサマ 通過しなかった分岐を表示している。 リレポート、関数ヒストグラム・レポート、ソースレポー SoftBench インターフェイスは、レポート・ジェネレー トの 3 つの基本的なレポートを提供する。ファイルと関数 タとさまざまなフィルタを使用して、これらのサマリ、ヒ のサマリレポートは、標準レポート・ジェネレータのレポ ストグラムおよびソースレポートを作りだす。ューザーが ートに似ているが、関数単位でのカバレッジ情報に加えて サマリまたはヒストグラム・レポートを選択した場合には、 実行された分岐数のサマリ情報もファイル単位で提供す レポート・ジェネレータが実行されてサマリレポートを生 成し、対応するサマリまたはヒストグラム・レポートを生 るところが異なる。図 5 に、ファイルと関数のサマリレポ 図 5 ファイルと関数のサマリレポート 0 司 SoftBench ー 88A BBA Actions Edit Settings Help CO 猷 e 気 : hplsdln:/usr/hp64000/demo/bba/dem02/* Hit-—Total—%—」 A—Function— Summary convert . 0 keyconvert bitpos Tota1s d 1 V . C 1 ( 0 . 00 ) 1 ( 0.0 の 5 out 0f 22 retained branches executed ( 22.73 え ) 23 branches were ignored ] 「 0 Tota1s 図 6 関数ヒストグラム・レポート SoftBench ー 88A BBA Actions Edit Settings Help Context: hplsdln : ん s 「 / hP64000 / demo / bba / d0m02 / * File/Function: 一 bitpos 0 「 0 getkeyva lu ・ twobits 0 司 っ 1 0 0 1 っ 1 ・ 0 「′ Convert . C d 「に「 . c getkey. c mu 1 t i b i t 5 . c 図 7 関数 keyconvert のソースレポート ロローロ 0 司 SoftBench ー Source ofFunction: keyconvertin File: convert. c Branch: Ne 対 Previous no 「 0 Add Pragma 00 ( 1 ) switch never went to 'case bitpos horiz) 十 KEY—F; keycode 2 9 30 break; ( 1 ) switch never went to 'case' case 4 : / 本 pressin third column Of keys ま / ー〉 31 bitpos hO 「 iz ) 十 KEY—I ー 32 keycode 33 break; ( 3 ) switch never went to 'case' case 8 : / ま pressing fourth column Of keys 本 / ー〉 34 keycode = bitpos(horiz) 十 KEY—6; 35 2 : / す SeC011(l CO ーいⅡ 1 Ot / ー〉 2 8 67 UNIX MAGAZINE 1991.12
HP SoftBench 図ー ソフトウェア開発におけるテストの時機 システムの仕様 テストに不合格 ・仕様のテスト ソフトウェアの 設計 テストに不合格 図 2 BBA Con ー 0 気 . ~ 分・岐 . 図 3 テ、シジョン If-E1se/Switch ・ポイントと分岐 システムの 仕様に基づいた テスト項目の作成 ソフトウェアの テスト項目の作成 設計に基づいた モジュール単位の テスト項目の作成 ・テストの アーカイプ —Case ポイント テーシジョン・ Whi1e/D0—Whi1e/For 、 - ー - ・分岐アシション・ 分岐 SoftBench インターフェイス中の HP Brach Validator ・設計のテスト ソフトウェアの 実装 ハードウェアと ソフトウェアの 統合 実行可能な ソフトウェア NO テストに関連する作業 プリプロセッサ ロ 役立つ作業 Branch Va ato 「が SottBench ー 6 日 A Actions Edit Settings Help ・ hpls 引 n : ん“ / hP64000 / demo / bb / d0E02 / * P0「C0nしー-ーHi虱09ー0n1-ーーーー . —Function 3 3 0 keyconvert bitpos twobits So れ日 ench 一日日 A にに一 k e V V 日一いに 0 司 File 0 司 i',et k e v . c mu ー t i b i t s . c COnvert . C ソフトウェア はテストに合格 したか ? yes ・十分にテストしたか Yes 製品のリリース Sou 「 ( 0 Function: 00 ⅸ eyv 引 uo inFile: 9 ・ⅸ・ 0 if' was n に ve 「 TRUE ( 1 ) conditional of 52 / 第 FirSt test: if both horiz and vert are 0 , just return 51 55 56 5 7 58 59 - ) 5 3 / 第 i f ( ( h 0 r i / return(KEY_NONE); SeCond: if more than 0 れ・ key pressed, return an に rro 「 ((twobits(horiz) ! = 0 ) HP Branch VaIidator のプリプロセッサは、 C のプリ プロセッサに代わって C または C 十十のコードを分岐分 析に適した形式に変換する。プリプロセッサは、どの分岐 が実行されたかを記録するための配列の定義文と、その配 列を用いて記録をおこなう代入文をソースファイルに挿入 する。さらに、プリプロセッサはマップファイルを生成す る。このマップファイルには、分岐をソースファイル内の 関連する行に対応させるための情報が記録される。プリプ ロセッサがどのように働くかを次の小さなソースファイル UNIX MAGAZINE 1991.12 int he110 ; yousay(hello) extern int goodbye ; で見てみよう。 if ( he110 = = goodbye) goodbye = he110 + 3 ; else goodbye = he110 ー 5 ; このファイルを HP Branch VaIidator で変換すると、 リスト 1 ( 60 ページ ) のような中間ファイルが生成され、コ ンパイルされる。 この中間ファイルには、 HP BranchVaIidator のプリ プロセッサがもとのソースコードに付加した命令文が含ま れている。追加されたのは、分岐配列 ( 1 行目で定義されて いる char-bA-array[3 ] = {O};) と、分岐実行文 ( 7 、 8 、 10 行で定義されている一 bA ー a ay [ x ] = 1 ; ) および分岐の 検証処理を管理する構造体である。 1 行目の分岐配列は、 実行された分岐を記録する。対応する分岐が実行されると、 配列要素に 1 がセットされる。分岐文は、もとのプログラ ムの論理を変えないように挿入されている。 7 行目の最初 59
HP SoftBench リストー HP Branch Validator によって生成された中問ファイル 1 2 3 4 5 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 static unsigned char —bA—array [ 3 extern. int goodbye ; yousay(hello) int he110 ; -bA-array [ 0 ] {-bA-arrayC1] {-bA-array [ 2 ] = 1 ; if ( he110 = = goodbye) 1 ; goodbye = he110 ー 5 ; } 1 ; goodbye = he110 + 3 ; } struct —bA—probe—struct— char *sourcepath; unsiB1ed char *dataarray; unsigned int numentries ; unsigned char optionsC4] ; char sourcemodtime [ 9 ] ; char mapsuffix; unsigned char insertprotocol ; { 6 , / * Branch Va1idator internal version * / struct —bA-probe—struct——bA—eybdoog-20med-crs-abb-tsetws— "/swtest/bba/src/dem02/goodbye. c" Path to this file * / -bA—array , Pointer tO Branch Array * / Number 0f branches * / {0xa7, 0X05 , 0X02 , 0X8 } , Branch Va1idator compile options * / Data 0f compilation (encoded) * / Map file extension * / 図 4 HP Branch Va ⅱ dator マップファイルの例 :id Basis Branch Ana1ysis Source Mapping Fi1e : p て 0t0C01 6 :options 205A7 : cppver @(). 01.00 030Ct90 )@ : source 0 /swtest/bba/src/dem02/goodbye. c :modtime B{jp'gMbp 0 6 2 6 22 @if ( he110 = = goodbye)@ :probe 1 1 0 0 2 7 5 7 24 :ct1 :probe 2 2 0 0 2 9 5 9 24 :ct1 0 6 2 6 22 @if ( he110 goodbye) :probe 0 0 0 0 1 6 2 10 0 :fname 0 3 0 3 12 @yousay@ の文は、この関数が呼び出されたか否かを記録する。 8 行 目の文は if 条件の then 節が、 10 行目の文は if 条件の else 節がそれぞれ実行されたか否かを記録する。 プリプロセッサは自動的に記号、、 { 〃と、、 } 〃を挿入し て、もとのプログラムの論理を維持する。これらの代入文 および分岐の文字配列は単純なものなので、分岐ごとにか かる処理時間およびメモリの使用量はできるかぎり抑えら れている ( 通常、時間とメモリ使用量の増加は 20 % 以内で ある ) 。 13 ~ 36 行目には、 HP BranchValidator が使用する構 60 造体定義とデータ構造が追加されている。このデータ構造 は日付、ファイル名、コンパイル・オプションおよび分岐 配列へのポインタを記録するものである。このデータ構造 体は適宜ファイルにダンプされ、レポート・ジェネレータ によって処理される。このファイルから生成されたマップ ファイルを図 4 に示す。 このマップファイルは、分岐配列の要素をソースコード 中の分岐と対応させるのに必要な情報を含んでいる。分岐 配列の各要素は、、、 :probe" で始まる行で表される。各プロ ープ ( pr 。 be ) の数値は、各分岐ごとの分岐の種類とスコー UNIX MAGAZINE 1991.12
HP SoftBench リスト 6 ソースレポートの例 DORep1ace(void*)board. C (l)conditional 0f ' if' was never FALSE ( 取 0 'else' statement) 56 57 田 59 ー > 61 62 [control lines] static void DORep1ace(void*){ nevpiece = 肌 L ・ newboard ->SetPiece (newpiece ) ; if(nevpiece){ Paint(int, int,Direction,Direction,int)fIow. C ( 1 ) executed 75 76 78 ー > 79 80 81 77 97 98 99 104 103 102 101 100 XFi11Rectang1e(dpy, window, gc, xO + ssize IPIX , yO + issize, ipix, flowwidth) ; break; case BadDir: Punt("Bad in direction in Paint ! " ) ; OPIX = numpxx ー IPIX ; ( 1 ) 'case' code was never executed XFiIIRectang1e(dpy, vindow, gc , x0 + hssize, y0 Put("Bad out Direction ⅲ paint ! " ) ・ BadDir : break; opix, flowwidth) ; 十 ISSIZe, HPBranchValidator のコマンド行インターフェイス において、一貫しない唯一の残念な点は、サマリレポート で報告されるファイル名である。報告されるファイル名は C のファイル名であって、 C 十十のファイル名ではない。単 純に C の拡張子を C 十十の拡張子に置き換えれば、 C 十十 のファイル名が分かる。この例では . c を . C で置き換えて いる。つまり、 board. c を board. C にしている。 、ゝコマンド行インターフェイスでは、分岐を無視しようと したときに生しうるもう 1 つの問題がある。特定の分岐を 無視するには、 C のファイル名のほかに、 C 十十の暗号化さ れた関数名と暗号化された分岐の全体を ignore ファイル に入力しなければならない。たとえば、 78 行目と 101 行目 の case 文を無視するには、 /disc. 14.4/games/xp1umb/f10w. c :Paint FiT19DirectionT3TI : case ー 1 ; というシーケンスを ignore ファイルに入力しなければな らない。これは多少困難な作業だ。というのはかなり多く の文字を ignore ファイルにタイプ入力しなければならす、 また分岐関数名と文を知るためには、ファイル flow. c を 調べなければならないからである。 SoftBench インターフェイスは、マップファイルとさま ざまなフィルタを使って C 十十の正しい結果を出力する ことにより、これらの欠点を克服している。すべての C フ ァイルは、もとの C 十十ファイルが存在すれはそれらにマ ップされる。さらに、分岐を無視するためには、マウスポ 70 タンをクリックすればよい。 SoftBench インターフェイス はマップファイルを読み取り、亜しいファイル名、関数名、 および関数の分岐文字列と無視する分岐を決定する。図 8 ( 71 ページ ) に、 HP Branch Validator SoftBench イン ターフェイスを用いて、 C 十十プログラムの一部分を調べ ている例を示す。これは、 EncapsuIator を使用して欠点を 克服し、コマンド行インターフェイスのもつ能力を大きく 拡張できることを示している。 UNIX MAGAZINE 1991.12
HP SoftBench 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 83 85 86 / * Do—whiIe 100P * / while ( (b !=0)?(-bA-array [ 16 ] = 1 , 1 ) : (-bA-arrayC17]=1 , の ) ; / * Macro conditional * / if (c>5){-bA-array[18]=1 ;c=c*c; else -bA-arrayC19]=1 ; -bA—1abeI: —bA-dump() ; {struct —bA—probe-struct— char *sourcepath ; uns igned char *dataarray ; unsigned int numentries; unsigned char options [ 4 ] ; char sourcemodt ime [ 9 ] ; char mapsuffix; unsigned char insertprotocol; / * Branch Va1idator internal version * / —bA—e1pmas—20med—abb—omed_00046ph—rsu—2—csid— struct _bA_probe_struct— / * Map file extension * / {0xff , Oxff , 0X03 , 0X00 } , / * Date Of compilation (encoded) * / " / disc. 37.2/usr/hp64000/demo/bba/dem02/sampIe. c't / * P0inter tO Branch Array * / -bA-array , / * Number Of branches * / 20 , / * Branch Va1idator compile options * / Path tO this file * / 分に分岐分析をおこなう代入式を追加する。 ・関数 : 関数の最初の実行文として配列への代入式を追加 する。 16 行目は、関数が実行されると 0 番目の配列要素 に 1 が代入されることを示す。 ・ if 文 : すべての if 文の then 節に、最初の実行文とし て、配列への代入式を追加する。 ・ else 文 : すべての if 文の else 節に、最初の実行文とし て配列への代入式を追加する。オプションとして、 else 条件と配列への代入を else 文が書かれていなかった場 所に追加することもできる。 ・ while 文 : すべての while ループについて、ループ内の 最初の実行文として配列への代入式が追加される。 while ループがかならず実行される ( ループがスキップ されない ) か否かのテストに加えて、 do-while ループが 複数回実行されるか否かを調べるテストも実行できる。 44 ~ 45 行目および 55 ~ 57 行目は while ループの完全 なテストを示している。 44 ~ 45 行目の while ループで は、ループが場合によってスキップされることがあるか 否かを調べるために一時変数を利用している。 64 ・ for 文 : すべての for ループについて、ループ内の最初 の実行文として配列への代入文が追加される。 for ルー プ構文の 3 番目の文 ( 訳注 : f 。 r ( 式 1 : 式 2 ; 式 3 ) { } に おける式 3 のこと ) が実行されるか否かを調べるテスト をオプションで実行できる。 for ループ構文の 3 番目の 文は、ループに break または return が含まれている場 合には飛ひ越されることがある。 ・ case 文と default 文 : switch 文のなかの case 文また は default 文に続く最初の実行文として、配列への代入 文が追加される。指定された case 文または default 文 のコードが、上位の case 文を通り抜けてきたものとし て実行されるのか、あるいは指定された case の直接呼 出しとして実行されるのかを調べるためのテストを、オ プションで実行することもできる。さらに、 default 文を もたない case 文の場合には、 default 文を追加してその 実行を検出する ( 41 行目 ) 。 ・条件代入 : 配列への代入文を 2 つ追加して、条件代入文 の条件部が真か偽かを検出する機能を選択できる。 プリプロセッサの付加機能によって、ユーザーは特定の UNIX MAGAZINE 1991.12