[インデックス 10066] go/ast, go/token: actually run tests; fix go/ast test
コミット
コミットハッシュ: 22dd0ba90dfd832e5a60ec8ef5b986611e0e8fe9
作者: Ian Lance Taylor iant@golang.org
日付: 2011年10月20日 10:30:01 (PDT)
コミットメッセージ: go/ast, go/token: actually run tests; fix go/ast test
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/22dd0ba90dfd832e5a60ec8ef5b986611e0e8fe9
元コミット内容
commit 22dd0ba90dfd832e5a60ec8ef5b986611e0e8fe9
Author: Ian Lance Taylor <iant@golang.org>
Date: Thu Oct 20 10:30:01 2011 -0700
go/ast, go/token: actually run tests; fix go/ast test
R=gri
CC=golang-dev
https://golang.org/cl/5292048
---
src/pkg/Makefile | 2 --
src/pkg/go/ast/print_test.go | 8 ++++----
2 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/src/pkg/Makefile b/src/pkg/Makefile
index e784b26333..ffb1547c56 100644
--- a/src/pkg/Makefile
+++ b/src/pkg/Makefile
@@ -203,9 +203,7 @@ NOTEST+=\
exp/gui\
exp/gui/x11\
exp/sql/driver\
- go/ast\
go/doc\
- go/token\
hash\
http/pprof\
http/httptest\
diff --git a/src/pkg/go/ast/print_test.go b/src/pkg/go/ast/print_test.go
index f4e8f7a78f..a4bc3bb9dc 100644
--- a/src/pkg/go/ast/print_test.go
+++ b/src/pkg/go/ast/print_test.go
@@ -41,10 +41,10 @@ var tests = []struct {
4 }`},
// structs
- {struct{ x, y int }{42, 991},
- `0 struct { x int; y int } {
- 1 . x: 42
- 2 . y: 991
+ {struct{ X, Y int }{42, 991},
+ `0 struct { X int; Y int } {
+ 1 . X: 42
+ 2 . Y: 991
3 }`},
}
変更の背景
2011年10月、Go言語はまだ1.0がリリースされる前の開発段階にあり、プロジェクトはMakefileベースのビルドシステムを使用していました。このコミットは、go/ast
とgo/token
パッケージのテストが実際に実行されていなかった問題を解決するために行われました。
当時のGoプロジェクトでは、テストを実行すべきでないパッケージのリストをNOTEST
変数で管理していました。しかし、go/ast
とgo/token
パッケージは実際にはテストを実行できる状態にあったにも関わらず、これらのパッケージがテスト除外リストに含まれていたため、テストが実行されていませんでした。
さらに、go/ast
パッケージのテストコードには、Goの可視性ルールに関する問題がありました。テストケースで使用されている構造体フィールドが小文字で定義されていたため、パッケージ外からアクセスできない状態になっていました。
前提知識の解説
Go言語の可視性ルール
Go言語では、識別子の最初の文字が大文字か小文字かによって、その識別子の可視性(アクセス可能性)が決まります。
- 大文字で始まる識別子: パッケージ外からアクセス可能(エクスポートされた識別子)
- 小文字で始まる識別子: 同じパッケージ内からのみアクセス可能(パッケージプライベート)
この規則は、変数、関数、型、構造体フィールドなど、すべての識別子に適用されます。
go/astパッケージの役割
go/ast
パッケージは、Go言語のソースコードの抽象構文木(Abstract Syntax Tree, AST)を表現するためのデータ構造と関数を提供します。主な用途:
- 構文木の表現: Go言語の構文要素(式、文、宣言)を木構造で表現
- コード解析: 静的解析ツールやコード生成ツールの基盤
- リフレクション: 実行時にコードの構造を調べる機能
go/tokenパッケージの役割
go/token
パッケージは、ソースコードの位置情報やトークンの管理を行います:
- 位置情報の管理: ソースファイル内の位置をトークンとして表現
- ファイルセットの管理: 複数のソースファイルを一元的に管理
- トークン化: ソースコードをトークンに分割する機能
2011年当時のGoビルドシステム
2011年当時、Go言語はまだ1.0がリリースされる前の状態で、現在のgo test
コマンドは存在せず、Makefileベースのビルドシステムを使用していました。
- Makefileの必要性: すべてのパッケージはMakefileを持つ必要があった
- テスト実行:
gotest
コマンドを使用してテストを実行 - NOTEST変数: テストを実行しないパッケージのリストを管理
技術的詳細
1. テスト実行の有効化
このコミットでは、src/pkg/Makefile
のNOTEST
変数からgo/ast
とgo/token
を削除しました。これにより、これらのパッケージのテストが実行されるようになりました。
NOTEST+=\
exp/gui\
exp/gui/x11\
exp/sql/driver\
- go/ast\
go/doc\
- go/token\
hash\
http/pprof\
http/httptest\
2. 構造体フィールドの可視性修正
go/ast/print_test.go
で定義されているテストケースの構造体フィールドを、小文字から大文字に変更しました。
修正前:
{struct{ x, y int }{42, 991},
`0 struct { x int; y int } {
1 . x: 42
2 . y: 991
3 }`},
修正後:
{struct{ X, Y int }{42, 991},
`0 struct { X int; Y int } {
1 . X: 42
2 . Y: 991
3 }`},
3. 技術的な問題の詳細
なぜ小文字フィールドが問題だったのか
Goの可視性ルールにより、小文字で始まるフィールド(x
, y
)は同じパッケージ内でのみアクセス可能です。しかし、このテストケースでは、構造体の値を出力して期待値と比較する処理が行われており、パッケージ外からのアクセスが必要な可能性がありました。
ASTプリント機能の動作
go/ast
パッケージのプリント機能は、構造体の内容を木構造として表示します。この機能では、構造体のフィールドにアクセスする必要があるため、フィールドがエクスポートされていない(小文字)場合、正しく動作しない可能性がありました。
コアとなるコードの変更箇所
1. Makefile変更(src/pkg/Makefile:203-210)
# 変更前
NOTEST+=\
exp/gui\
exp/gui/x11\
exp/sql/driver\
go/ast\
go/doc\
go/token\
hash\
http/pprof\
http/httptest\
# 変更後
NOTEST+=\
exp/gui\
exp/gui/x11\
exp/sql/driver\
go/doc\
hash\
http/pprof\
http/httptest\
2. テストケース修正(src/pkg/go/ast/print_test.go:37-45)
// 変更前
{struct{ x, y int }{42, 991},
`0 struct { x int; y int } {
1 . x: 42
2 . y: 991
3 }`},
// 変更後
{struct{ X, Y int }{42, 991},
`0 struct { X int; Y int } {
1 . X: 42
2 . Y: 991
3 }`},
コアとなるコードの解説
テストケースの構造
このテストケースは、go/ast
パッケージのプリント機能をテストするものです。
var tests = []struct {
x interface{}
s string
}{
// ... 他のテストケース ...
// structs
{struct{ X, Y int }{42, 991},
`0 struct { X int; Y int } {
1 . X: 42
2 . Y: 991
3 }`},
}
構造の説明
-
入力値:
struct{ X, Y int }{42, 991}
- 匿名構造体の定義と初期化
- フィールド
X
とY
はともにint
型 - それぞれ42と991で初期化
-
期待される出力:
0 struct { X int; Y int } { 1 . X: 42 2 . Y: 991 3 }
- 行番号付きの構造体表現
- フィールドの型情報と値を含む
プリント機能の動作原理
go/ast
パッケージのプリント機能は、任意のGoの値を構造化された文字列として表現します。この機能は以下の目的で使用されます:
- デバッグ: 複雑なデータ構造の内容を視覚的に確認
- テスト: データ構造の内容を期待値と比較
- ドキュメント: データ構造の例を示す
可視性修正の重要性
フィールド名を大文字に変更することで:
- テストの信頼性: 実際の使用シナリオにより近い状況でのテスト
- リフレクション対応: リフレクションを使用した処理での適切な動作
- JSON等の外部フォーマット: JSONシリアライゼーション等での正しい動作
関連リンク
- Go言語公式ドキュメント - Effective Go
- go/ast パッケージドキュメント
- go/token パッケージドキュメント
- Go言語のテストに関する公式ドキュメント
- Go言語の可視性ルールに関する解説