[インデックス 13586] ファイルの概要
このコミットは、Go言語プロジェクトにおけるCGO(C言語との相互運用)テストの実行方法を刷新するものです。具体的には、misc/cgo/life
および misc/cgo/stdio
ディレクトリ内のCGOテストが、個別のシェルスクリプト(test.bash
)に依存する形式から、Go言語で書かれた汎用テストランナーである test/run.go
を利用する形式へと移行されました。これにより、テストインフラの統一と、将来的なWindows環境でのCGO stdio
テストの有効化に向けた基盤が整備されました。
コミット
commit 1e95429c3fbfb9a30bd8a68e95bce4f882b40aec
Author: Shenghou Ma <minux.ma@gmail.com>
Date: Tue Aug 7 09:38:35 2012 +0800
misc/cgo/{life,stdio}, test/run.go: use test/run.go to do the cgo tests
Enhances test/run.go to support testing other directories
Will enable stdio tests on Windows in a follow-up CL.
R=golang-dev, alex.brainman, rsc
CC=golang-dev
https://golang.org/cl/6220049
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/1e95429c3fbfb9a30bd8a68e95bce4f882b40aec
元コミット内容
このコミットの目的は、misc/cgo/{life,stdio}
にあるCGOテストを、test/run.go
を使用するように変更することです。これに伴い、test/run.go
は他のディレクトリのテストもサポートするように機能拡張されました。将来的には、この変更によってWindows環境での stdio
テストも有効にできるようになります。
変更の背景
Go言語のプロジェクトでは、様々な種類のテストが存在し、それぞれ異なる方法で実行されることがありました。特にCGO関連のテストは、C言語のコードをコンパイル・リンクする必要があるため、プラットフォーム固有のシェルスクリプト(test.bash
)に依存しているケースが見られました。しかし、このような個別のスクリプトは、テスト実行の複雑性を増し、異なるOS環境(特にWindows)での互換性の問題を引き起こす可能性がありました。
このコミットの背景には、以下の課題意識があったと考えられます。
- テスト実行の統一化: 個別のシェルスクリプトに依存するのではなく、Go言語で書かれた単一のテストランナー (
test/run.go
) にテスト実行ロジックを集約することで、テストインフラの保守性を向上させ、一貫したテスト実行フローを確立したいという意図がありました。 - クロスプラットフォーム対応の強化:
test.bash
のようなシェルスクリプトはUnix系OSに特化しており、Windows環境でのテスト実行には別途test.bat
のようなバッチファイルが必要でした。test/run.go
のようなGo言語製のツールに移行することで、Go言語のクロスプラットフォーム特性を活かし、より容易にWindowsを含む多様な環境でテストを実行できるようになります。コミットメッセージにある「Will enable stdio tests on Windows in a follow-up CL.」という記述は、この目的を明確に示しています。 - テストの柔軟性向上:
test/run.go
がディレクトリ単位でのテスト実行をサポートするように拡張されることで、特定のテストスイート全体を簡単に実行できるようになり、テストの管理と実行がより柔軟になります。 - テスト結果の標準化:
golden.out
ファイルをmain.out
やrun.out
にリネームし、新しい.out
ファイルを追加していることから、テストの期待出力の管理方法も統一・標準化しようとしていることが伺えます。
これらの背景から、Goプロジェクト全体のテストインフラの健全性と効率性を高めるための戦略的な変更であったと言えます。
前提知識の解説
このコミットを理解するためには、以下の概念が重要です。
- CGO: Go言語とC言語のコードを相互運用するためのGoの機能です。GoプログラムからCライブラリを呼び出したり、CプログラムからGo関数を呼び出したりすることができます。CGOを使用するプログラムは、通常のGoプログラムとは異なるビルドプロセスを必要とし、Cコンパイラ(GCCなど)に依存します。
- Goのテストフレームワーク: Go言語には標準で
testing
パッケージが提供されており、ユニットテストやベンチマークテストを記述できます。しかし、Goプロジェクトの内部では、より複雑な統合テストやシステムテストのために、test/run.go
のようなカスタムテストランナーが使用されることがあります。 test/run.go
: Goプロジェクトの内部で使用される、特定のテストシナリオを実行するためのカスタムテストランナーです。これはGoの標準テストフレームワークとは異なり、特定のディレクトリ内のGoファイルを実行し、その出力が期待される出力(golden.out
や.out
ファイル)と一致するかどうかを検証するような、より高レベルなテストロジックを実装しています。- シェルスクリプト (
.bash
,.bat
): Unix系OSではBashスクリプト(.bash
)、Windowsではバッチファイル(.bat
)が、コマンドラインからの操作や自動化されたタスク実行によく用いられます。Goプロジェクトのテストでも、ビルド、実行、結果の比較といった一連の処理を自動化するためにこれらのスクリプトが使われていました。 - ゴールデンファイルテスト (Golden File Testing): テスト対象のプログラムが生成する出力(テキスト、画像など)を、事前に用意された「ゴールデンファイル」(期待される正しい出力を含むファイル)と比較することで、プログラムの動作が正しいことを検証するテスト手法です。出力が複雑でアサーションを記述しにくい場合や、出力の変更を視覚的に確認したい場合に有効です。このコミットでは、
golden.out
ファイルがmain.out
やrun.out
にリネームされ、新しい.out
ファイルが追加されていることから、この手法が用いられていることがわかります。 // skip
および// cmpout
ディレクティブ: Goのソースコード内に記述される特殊なコメントで、test/run.go
のようなカスタムテストランナーによって解釈されるメタデータです。// skip
: このファイルまたはテストケースをテスト実行から除外することを示唆します。// cmpout
: このGoプログラムの実行結果を、対応する.out
ファイルと比較して検証することを示唆します。これはゴールデンファイルテストの一種です。
技術的詳細
このコミットの技術的な変更は、主に以下の3つの側面から構成されます。
-
テスト実行ロジックのGo言語への移行:
misc/cgo/life/test.bash
とmisc/cgo/stdio/test.bash
という2つのシェルスクリプトが削除されました。これらのスクリプトは、CGOプログラムのビルド、実行、そしてその出力とgolden.out
ファイルとの比較を行っていました。- 代わりに、
src/run.bash
とsrc/run.bat
が変更され、CGOテストの実行にgo run $GOROOT/test/run.go - .
(Unix系) またはgo run %GOROOT%\test\run.go - ..\misc\cgo\life
(Windows) の形式でtest/run.go
を呼び出すようになりました。これにより、テスト実行の制御がGo言語製のツールに一元化されます。
-
test/run.go
の機能拡張:test/run.go
は、コマンドライン引数の解析ロジックが大幅に強化されました。以前は個別の.go
ファイルのみを引数として受け取っていましたが、この変更により、ディレクトリパスも引数として受け取れるようになりました。fi, err := os.Stat(arg); err == nil && fi.IsDir()
のチェックが追加され、引数がディレクトリであるかどうかが判断されます。- もし引数がディレクトリであれば、
goFiles(arg)
関数(コミット差分には含まれていませんが、ディレクトリ内のGoファイルを列挙する関数と推測されます)を使ってそのディレクトリ内のすべてのGoファイルを検出し、それぞれに対してstartTest
を呼び出すようになりました。 - 引数が
.go
ファイルであれば、filepath.Split
を使ってディレクトリとファイル名に分割し、startTest
を呼び出します。 - これにより、
test/run.go
はgo run run.go - ./fixedbugs
のように、特定のディレクトリ内のすべてのテストを実行できるようになり、テストの管理がより柔軟になりました。 - また、
log.Fatalf("can't yet deal with non-directory and non-go file %q", arg)
というエラーメッセージが追加され、.go
ファイルでもディレクトリでもない引数に対してはエラーを出すようになりました。これは、test/run.go
が処理できる入力の範囲を明確にしています。
-
テスト出力ファイルの管理とディレクティブの導入:
misc/cgo/life/golden.out
がmisc/cgo/life/main.out
にリネームされました。misc/cgo/stdio/golden.out
がmisc/cgo/stdio/run.out
にリネームされました。misc/cgo/stdio/chain.out
,misc/cgo/stdio/fib.out
,misc/cgo/stdio/hello.out
といった新しい.out
ファイルが追加されました。これらは、対応するCGOプログラムの期待される出力を格納するゴールデンファイルとして機能します。misc/cgo/life/life.go
とmisc/cgo/stdio/file.go
に// skip
コメントが追加されました。これはtest/run.go
がこれらのファイルをテスト対象から除外するための指示であると考えられます。misc/cgo/life/main.go
,misc/cgo/stdio/chain.go
,misc/cgo/stdio/fib.go
,misc/cgo/stdio/hello.go
に// cmpout
コメントが追加されました。これはtest/run.go
がこれらのGoプログラムを実行し、その標準出力が対応する.out
ファイルの内容と一致するかどうかを比較検証するための指示であると考えられます。
これらの変更により、GoプロジェクトのCGOテストは、より統一され、クロスプラットフォーム対応が強化され、柔軟な実行が可能となるテストインフラへと進化しました。
コアとなるコードの変更箇所
このコミットにおけるコアとなるコードの変更箇所は、主に test/run.go
と、テスト実行スクリプトである src/run.bash
および src/run.bat
です。
test/run.go
の変更点
--- a/test/run.go
+++ b/test/run.go
@@ -77,16 +77,23 @@ func main() {
if flag.NArg() > 0 {
for _, arg := range flag.Args() {
if arg == "-" || arg == "--" {
- // Permit running either:
+ // Permit running:
// $ go run run.go - env.go
// $ go run run.go -- env.go
+ // $ go run run.go - ./fixedbugs
+ // $ go run run.go -- ./fixedbugs
continue
}
- if !strings.HasSuffix(arg, ".go") {
- log.Fatalf("can't yet deal with non-go file %q", arg)
+ if fi, err := os.Stat(arg); err == nil && fi.IsDir() {
+ for _, baseGoFile := range goFiles(arg) {
+ tests = append(tests, startTest(arg, baseGoFile))
+ }
+ } else if strings.HasSuffix(arg, ".go") {
+ dir, file := filepath.Split(arg)
+ tests = append(tests, startTest(dir, file))
+ } else {
+ log.Fatalf("can't yet deal with non-directory and non-go file %q", arg)
}
- dir, file := filepath.Split(arg)
- tests = append(tests, startTest(dir, file))
}
} else {
for _, dir := range dirs {
src/run.bash
の変更点
--- a/src/run.bash
+++ b/src/run.bash
@@ -49,12 +49,12 @@ xcd() {
[ "$CGO_ENABLED" != 1 ] ||
[ "$GOHOSTOS" == windows ] ||
(xcd ../misc/cgo/stdio
-./test.bash
+go run $GOROOT/test/run.go - .
) || exit $?
[ "$CGO_ENABLED" != 1 ] ||
(xcd ../misc/cgo/life
-./test.bash
+go run $GOROOT/test/run.go - .
) || exit $?
[ "$CGO_ENABLED" != 1 ] ||
src/run.bat
の変更点
--- a/src/run.bat
+++ b/src/run.bat
@@ -30,6 +30,13 @@ echo.
:: at least runtime/debug test will fail.
set GOROOT_FINAL=\
+:: get CGO_ENABLED
+go env > env.bat
+if errorlevel 1 goto fail
+call env.bat
+del env.bat
+echo.
+
echo # Testing packages.
go test std -short -timeout=120s
if errorlevel 1 goto fail
@@ -56,6 +63,15 @@ echo.\n
::if errorlevel 1 goto fail
::echo.\n
+:: cgo tests
+:: TODO: Other cgo tests
+if x%CGO_ENABLED% == x0 goto nocgo
+echo # ..\misc\cgo\life
+go run %GOROOT%\test\run.go - ..\misc\cgo\life
+if errorlevel 1 goto fail
+echo.\n
+:nocgo
+\n
:: TODO: The other tests in run.bash.\n
\n
echo # test
コアとなるコードの解説
test/run.go
の変更解説
この変更は、test/run.go
がコマンドライン引数として受け取る対象を拡張し、より汎用的なテストランナーとしての役割を強化しています。
- 引数処理の分岐: 以前は引数が
.go
ファイルであることのみを想定していましたが、if fi, err := os.Stat(arg); err == nil && fi.IsDir()
という条件分岐が追加されました。os.Stat(arg)
: 引数arg
のファイル情報を取得します。fi.IsDir()
: 取得したファイル情報がディレクトリであるかどうかを判定します。
- ディレクトリ内のテスト実行: 引数がディレクトリであると判定された場合、
for _, baseGoFile := range goFiles(arg)
ループが実行されます。goFiles(arg)
: この関数はコミット差分には含まれていませんが、指定されたディレクトリarg
内にあるすべてのGoソースファイル(テスト対象となるファイル)のリストを返すものと推測されます。- ループ内で、検出された各Goファイルに対して
startTest(arg, baseGoFile)
が呼び出されます。これにより、ディレクトリ内の複数のテストが自動的に実行されるようになります。
- 単一Goファイルのテスト実行: 引数が依然として単一の
.go
ファイルである場合は、else if strings.HasSuffix(arg, ".go")
のブロックが実行され、以前と同様にfilepath.Split
でディレクトリとファイル名に分割し、startTest
を呼び出します。 - エラーハンドリングの強化:
else { log.Fatalf("can't yet deal with non-directory and non-go file %q", arg) }
が追加されました。これにより、.go
ファイルでもディレクトリでもない不正な引数が渡された場合に、より明確なエラーメッセージを出力してプログラムを終了するようになりました。これは、テストランナーの堅牢性を高める変更です。
この変更により、test/run.go
は、個別のGoテストファイルだけでなく、特定のディレクトリにまとめられたテストスイート全体を効率的に実行できる、より強力なツールとなりました。
src/run.bash
および src/run.bat
の変更解説
これらのシェルスクリプト(Unix系OS用とWindows用)は、Goプロジェクトの主要なテスト実行エントリポイントです。変更の目的は、CGOテストの実行方法を、個別の test.bash
スクリプトから、Go言語製の test/run.go
へと切り替えることです。
src/run.bash
:misc/cgo/stdio
およびmisc/cgo/life
ディレクトリでのテスト実行部分が、./test.bash
の呼び出しからgo run $GOROOT/test/run.go - .
へと変更されました。$GOROOT/test/run.go
: Goのインストールディレクトリにあるtest/run.go
を指定しています。- .
:test/run.go
に渡される引数で、現在のディレクトリ(.
)内のテストを実行するように指示しています。これは、test/run.go
の機能拡張と連携しています。
src/run.bat
:- Windows環境でのCGOテスト実行ロジックが追加されました。
go env > env.bat
とcall env.bat
を使ってCGO_ENABLED
環境変数を取得しています。これは、CGOが有効になっている場合にのみCGOテストを実行するための条件分岐 (if x%CGO_ENABLED% == x0 goto nocgo
) を可能にします。go run %GOROOT%\test\run.go - ..\misc\cgo\life
:misc/cgo/life
ディレクトリのCGOテストをtest/run.go
を使って実行するように変更されています。コミットメッセージにある「Will enable stdio tests on Windows in a follow-up CL.」の通り、この時点ではstdio
テストは含まれていませんが、将来的な拡張を見越した基盤が作られています。
これらの変更により、Goプロジェクトのビルドおよびテストシステムは、CGOテストの実行において、より統一されたGo言語ベースのアプローチを採用するようになりました。これにより、テストの信頼性、保守性、そしてクロスプラットフォーム互換性が向上します。
関連リンク
- Go言語公式ドキュメント: https://go.dev/
- Go言語のCGOに関するドキュメント: https://go.dev/blog/cgo
- Go言語のテストに関するドキュメント: https://go.dev/doc/code#testing
参考にした情報源リンク
- Go言語のソースコード (GitHub): https://github.com/golang/go
- Gerrit Code Review (Goプロジェクト): https://go.dev/cl/ (コミットメッセージに記載されている
https://golang.org/cl/6220049
は、このGerritインスタンス上の変更リストへのリンクです。) - Go言語のテストにおけるゴールデンファイル: (一般的な概念であり、特定の公式ドキュメントは少ないですが、Goコミュニティで広く使われているパターンです。)
- 例: https://pkg.go.dev/cmd/go#hdr-Test_packages (直接的な言及はないが、テストの出力比較の文脈で理解される)
- Goのテストに関するブログ記事やチュートリアルで言及されることが多い。