Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 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/astgo/tokenパッケージのテストが実際に実行されていなかった問題を解決するために行われました。

当時のGoプロジェクトでは、テストを実行すべきでないパッケージのリストをNOTEST変数で管理していました。しかし、go/astgo/tokenパッケージは実際にはテストを実行できる状態にあったにも関わらず、これらのパッケージがテスト除外リストに含まれていたため、テストが実行されていませんでした。

さらに、go/astパッケージのテストコードには、Goの可視性ルールに関する問題がありました。テストケースで使用されている構造体フィールドが小文字で定義されていたため、パッケージ外からアクセスできない状態になっていました。

前提知識の解説

Go言語の可視性ルール

Go言語では、識別子の最初の文字が大文字か小文字かによって、その識別子の可視性(アクセス可能性)が決まります。

  • 大文字で始まる識別子: パッケージ外からアクセス可能(エクスポートされた識別子)
  • 小文字で始まる識別子: 同じパッケージ内からのみアクセス可能(パッケージプライベート)

この規則は、変数、関数、型、構造体フィールドなど、すべての識別子に適用されます。

go/astパッケージの役割

go/astパッケージは、Go言語のソースコードの抽象構文木(Abstract Syntax Tree, AST)を表現するためのデータ構造と関数を提供します。主な用途:

  1. 構文木の表現: Go言語の構文要素(式、文、宣言)を木構造で表現
  2. コード解析: 静的解析ツールやコード生成ツールの基盤
  3. リフレクション: 実行時にコードの構造を調べる機能

go/tokenパッケージの役割

go/tokenパッケージは、ソースコードの位置情報やトークンの管理を行います:

  1. 位置情報の管理: ソースファイル内の位置をトークンとして表現
  2. ファイルセットの管理: 複数のソースファイルを一元的に管理
  3. トークン化: ソースコードをトークンに分割する機能

2011年当時のGoビルドシステム

2011年当時、Go言語はまだ1.0がリリースされる前の状態で、現在のgo testコマンドは存在せず、Makefileベースのビルドシステムを使用していました。

  • Makefileの必要性: すべてのパッケージはMakefileを持つ必要があった
  • テスト実行: gotestコマンドを使用してテストを実行
  • NOTEST変数: テストを実行しないパッケージのリストを管理

技術的詳細

1. テスト実行の有効化

このコミットでは、src/pkg/MakefileNOTEST変数からgo/astgo/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  }`},
}

構造の説明

  1. 入力値: struct{ X, Y int }{42, 991}

    • 匿名構造体の定義と初期化
    • フィールドXYはともにint
    • それぞれ42と991で初期化
  2. 期待される出力:

    0  struct { X int; Y int } {
    1  .  X: 42
    2  .  Y: 991
    3  }
    
    • 行番号付きの構造体表現
    • フィールドの型情報と値を含む

プリント機能の動作原理

go/astパッケージのプリント機能は、任意のGoの値を構造化された文字列として表現します。この機能は以下の目的で使用されます:

  1. デバッグ: 複雑なデータ構造の内容を視覚的に確認
  2. テスト: データ構造の内容を期待値と比較
  3. ドキュメント: データ構造の例を示す

可視性修正の重要性

フィールド名を大文字に変更することで:

  1. テストの信頼性: 実際の使用シナリオにより近い状況でのテスト
  2. リフレクション対応: リフレクションを使用した処理での適切な動作
  3. JSON等の外部フォーマット: JSONシリアライゼーション等での正しい動作

関連リンク

参考にした情報源リンク