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

[インデックス 14681] ファイルの概要

このコミットは、Go言語の実験的なツールである exp/gotype のテストファイル src/pkg/exp/gotype/gotype_test.go に関連するものです。gotype は、Goのソースコードを解析し、型情報を表示するためのツールです。このテストファイルは、Go標準ライブラリの様々なパッケージに対して gotype が正しく動作するかどうかを検証するために使用されます。

コミット

このコミットは、exp/gotype のテストにおいて、当時失敗していたいくつかのテストを無効化し、同時に新しいテストを追加することを目的としています。具体的には、crypto/rsanetsyscall パッケージに関連するテストがコメントアウトされ、crypto/x509 パッケージのテストが有効化されています。また、build.Import の呼び出しに CgoEnabled = false のコンテキストが追加されています。

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/acbf011d965f6b6f787f415a7e3e0dfe21f1e9f8

元コミット内容

exp/gotype: disable failing tests and add a few more

R=rsc, alex.brainman
CC=golang-dev
https://golang.org/cl/6948066

変更の背景

このコミットの背景には、exp/gotype のテストスイートが不安定であったこと、特にCgo(GoとC言語の相互運用機能)に関連する問題や、特定のプラットフォーム(Windowsなど)でのビルド環境に依存する問題があったことが示唆されます。

コミットメッセージとコードの変更点から、以下の問題が推測されます。

  1. テストの失敗: crypto/rsanetsyscall パッケージのテストが継続的に失敗していたため、一時的に無効化する必要がありました。コメントには具体的なエラーメッセージが記載されており、これらは gotype がこれらのパッケージの型情報を正しく解析できないことを示しています。
    • crypto/rsa: undeclared name: io - io パッケージの型が正しく認識されていない可能性。
    • net: undeclared name: cgoLookupHost または invalid operation: division by zero - ネットワーク関連のCgo関数や、Windows環境でのインターフェース処理に問題があった可能性。
    • syscall: cannot convert EINVAL (constant 536870951) to error - syscall パッケージの定数変換に問題があった可能性。
  2. Cgoの扱い: gotype がパッケージをインポートする際に、Cgoが有効になっていると問題が発生するケースがあったようです。build.ImportCgoEnabled = false を設定することで、Cgoに依存する部分をスキップし、テストの安定性を向上させようとしています。
  3. テストスイートの改善: 失敗するテストを無効化するだけでなく、crypto/x509 のように以前は無効化されていたが、現在は安定しているテストを再度有効化することで、テストカバレッジを維持・向上させようとしています。

これらの変更は、gotype ツールの開発初期段階における安定化と、テスト環境の整備の一環として行われたと考えられます。

前提知識の解説

exp/gotype

exp/gotype は、Go言語のソースコードを静的に解析し、型情報を抽出・表示するための実験的なツールです。Goコンパイラが内部的に行っている型チェックのロジックの一部を外部から利用できるようにしたもので、IDEのコード補完や静的解析ツールなどで利用されることを想定していました。exp パッケージは、Goの標準ライブラリに将来的に取り込まれる可能性のある、実験的な機能やツールが置かれる場所です。

go test

go test は、Go言語のテストを実行するためのコマンドです。Goのテストは、_test.go で終わるファイルに記述され、Test で始まる関数がテスト関数として認識されます。go test はこれらのテスト関数を実行し、結果を報告します。

build.Import

go/build パッケージは、Goのパッケージをビルドする際のコンテキスト情報を提供し、パッケージのインポートパスを解決するための機能を提供します。build.Import 関数は、指定されたパスからGoパッケージの情報をインポートしようとします。これには、ソースファイルの解析、依存関係の解決などが含まれます。

go/build.Context

go/build.Context は、Goのビルド環境に関する情報(例: GOPATH、GOROOT、OS、アーキテクチャ、Cgoの有効/無効など)をカプセル化する構造体です。build.Default は、現在のシステム環境に基づくデフォルトのビルドコンテキストを提供します。

Cgo

Cgoは、GoプログラムからC言語のコードを呼び出したり、C言語のコードからGoの関数を呼び出したりするためのGoの機能です。Cgoを使用すると、既存のCライブラリをGoから利用したり、パフォーマンスが重要な部分をCで記述したりすることができます。しかし、Cgoはビルドプロセスを複雑にし、クロスコンパイルや特定の環境での問題を引き起こすことがあります。

Go標準ライブラリのパッケージ構造

Goの標準ライブラリは、src/pkg ディレクトリ以下に配置されています。例えば、crypto/rsa パッケージは src/pkg/crypto/rsa に、net パッケージは src/pkg/net にあります。

技術的詳細

このコミットの主要な技術的変更点は、gotype_test.go ファイル内の runTest 関数における build.Import の呼び出し方法の変更と、テスト対象パッケージのリストの更新です。

build.Import のコンテキスト変更

元のコードでは、build.Import(path, "", 0) のように、デフォルトのビルドコンテキストでパッケージをインポートしようとしていました。 変更後、以下のコードが追加されました。

		ctxt := build.Default
		ctxt.CgoEnabled = false
		pkg, err := ctxt.Import(path, "", 0)

これは、build.Default から現在のビルドコンテキストのコピーを作成し、そのコピーの CgoEnabled フィールドを false に設定しています。そして、この変更されたコンテキスト (ctxt) を使用して Import 関数を呼び出しています。

この変更の意図は、gotype がパッケージを解析する際にCgoに関連する問題を回避することです。Cgoが有効な場合、build.Import はCgoの依存関係を解決しようとしますが、これが gotype の静的解析プロセスと競合したり、特定の環境でビルドエラーを引き起こしたりする可能性がありました。CgoEnabled = false に設定することで、gotype はCgoに依存する部分を無視してパッケージを解析するようになります。これは、gotype が主にGoのコードの型情報を解析することに焦点を当てており、Cgoのランタイム依存関係は不要であるため、適切な対応と言えます。

テスト対象パッケージの変更

var tests = []string{...} リストでは、gotype が型チェックを行うGo標準ライブラリのパッケージが列挙されています。このリストの変更は、gotype のテストの安定性を向上させるためのものです。

  • crypto/rsa の無効化:

    • 変更前: // "crypto/rsa", // src/pkg/crypto/rsa/pkcs1v15.go:21:27: undeclared name: io
    • 変更後: // "crypto/rsa", // intermittent failure: /home/gri/go2/src/pkg/crypto/rsa/pkcs1v15.go:21:27: undeclared name: io crypto/rsa パッケージのテストは、io という名前が宣言されていないというエラーで失敗していました。これは、gotypeio パッケージを正しく解決できないか、または crypto/rsa 内で io パッケージの型が予期しない方法で使用されていることを示唆しています。intermittent failure (断続的な失敗) というコメントが追加されており、この問題が常に発生するわけではないが、不安定であるため無効化されたことがわかります。
  • crypto/x509 の有効化:

    • 変更前: // "crypto/x509", // src/pkg/crypto/x509/root.go:15:10: undeclared name: initSystemRoots
    • 変更後: "crypto/x509", 以前は initSystemRoots という未宣言の名前のエラーで無効化されていた crypto/x509 パッケージのテストが有効化されました。これは、この問題が解決されたか、または gotype の解析ロジックが改善されたことを示しています。
  • net の無効化:

    • 変更前: // "net", // src/pkg/net/lookup_unix.go:56:20: undeclared name: cgoLookupHost
    • 変更後: // "net", // c:\\go\\root\\src\\pkg\\net\\interface_windows.go:54:13: invalid operation: division by zero net パッケージのテストは、当初 cgoLookupHost という未宣言の名前のエラーで失敗していました。変更後、Windows環境での interface_windows.go ファイルにおける「ゼロ除算」エラーが示されています。これは、net パッケージがプラットフォーム固有のCgoコードや、特定の環境での数値計算に依存しており、gotype がこれを正しく扱えないか、またはテスト環境自体に問題があったことを示唆しています。
  • syscall の無効化:

    • 変更前: "syscall",
    • 変更後: // "syscall", c:\\go\\root\\src\\pkg\\syscall\\syscall_windows.go:35:16: cannot convert EINVAL (constant 536870951) to error syscall パッケージのテストは、Windows環境の syscall_windows.go ファイルで、EINVAL 定数を error 型に変換できないというエラーで失敗していました。これは、Goの型システムとCgoを介したシステムコールインターフェースの間の不整合、または特定の定数の扱いに関する問題を示しています。

これらの変更は、gotype がGo標準ライブラリのすべてのパッケージを完璧に解析できるわけではないという現実を反映しており、特にCgoやプラットフォーム固有のコードが絡む場合に課題があることを示しています。テストを無効化することで、CI/CDパイプラインの安定性を保ちつつ、問題の根本原因を特定し、将来的に解決するための時間を稼ぐことができます。

コアとなるコードの変更箇所

--- a/src/pkg/exp/gotype/gotype_test.go
+++ b/src/pkg/exp/gotype/gotype_test.go
@@ -25,7 +25,9 @@ func runTest(t *testing.T, path string) {
 	} else {
 		// package directory
 		// TODO(gri) gotype should use the build package instead
-		pkg, err := build.Import(path, "", 0)
+		ctxt := build.Default
+		ctxt.CgoEnabled = false
+		pkg, err := ctxt.Import(path, "", 0)
 		if err != nil {
 			t.Errorf("build.Import error for path = %s: %s", path, err)
 			return
@@ -77,13 +79,13 @@ var tests = []string{\n 	\"crypto/md5\",\n 	\"crypto/rand\",\n 	\"crypto/rc4\",\n-\t// \"crypto/rsa\", // src/pkg/crypto/rsa/pkcs1v15.go:21:27: undeclared name: io\n+\t// \"crypto/rsa\", // intermittent failure: /home/gri/go2/src/pkg/crypto/rsa/pkcs1v15.go:21:27: undeclared name: io\n \t\"crypto/sha1\",\n \t\"crypto/sha256\",\n \t\"crypto/sha512\",\n \t\"crypto/subtle\",\n \t\"crypto/tls\",\n-\t// \"crypto/x509\", // src/pkg/crypto/x509/root.go:15:10: undeclared name: initSystemRoots\n+\t\"crypto/x509\",\n \t\"crypto/x509/pkix\",\n \n \t\"database/sql\",\n@@ -152,7 +154,7 @@ var tests = []string{\n \t\"mime\",\n \t\"mime/multipart\",\n \n-\t// \"net\", // src/pkg/net/lookup_unix.go:56:20: undeclared name: cgoLookupHost\n+\t// \"net\", // c:\\go\\root\\src\\pkg\\net\\interface_windows.go:54:13: invalid operation: division by zero\n \t\"net/http\",\n \t\"net/http/cgi\",\n \t\"net/http/fcgi\",\n@@ -186,7 +188,7 @@ var tests = []string{\n \t\"sync\",\n \t\"sync/atomic\",\n \n-\t\"syscall\",\n+\t// \"syscall\", c:\\go\\root\\src\\pkg\\syscall\\syscall_windows.go:35:16: cannot convert EINVAL (constant 536870951) to error\n \n \t\"testing\",\n \t\"testing/iotest\",\n```

## コアとなるコードの解説

### `runTest` 関数の変更
`runTest` 関数は、指定されたGoパッケージに対して `gotype` を実行し、その結果を検証するテストヘルパー関数です。

```go
-		pkg, err := build.Import(path, "", 0)
+		ctxt := build.Default
+		ctxt.CgoEnabled = false
+		pkg, err := ctxt.Import(path, "", 0)

この変更は、build.Import を呼び出す際に、Cgoを無効にしたカスタムのビルドコンテキストを使用するようにしています。

  1. ctxt := build.Default: go/build パッケージの Default コンテキスト(現在のシステム環境に基づくデフォルト設定)を ctxt 変数にコピーします。これにより、元の build.Default が変更されることなく、ローカルな変更が可能になります。
  2. ctxt.CgoEnabled = false: コピーしたコンテキスト ctxtCgoEnabled フィールドを false に設定します。これにより、このコンテキストを使用してパッケージをインポートする際に、Cgoに関連する処理(Cソースファイルのコンパイルなど)がスキップされます。
  3. pkg, err := ctxt.Import(path, "", 0): 変更された ctxt コンテキストを使用して build.Import を呼び出します。これにより、gotype はCgoに依存しない形でパッケージの情報を取得しようとします。

この変更は、gotype がCgoを含むパッケージを解析する際に発生していた問題を回避するためのものです。gotype は静的解析ツールであり、Cgoのランタイム依存関係は通常必要ありません。そのため、Cgoを無効にすることで、解析の安定性と速度を向上させることができます。

tests 変数の変更

tests 変数は、gotype が型チェックを行うGo標準ライブラリのパッケージパスの文字列スライスです。このリストの変更は、テストの安定化とカバレッジの調整を目的としています。

  • crypto/rsa:

    • 以前はコメントアウトされており、src/pkg/crypto/rsa/pkcs1v15.go:21:27: undeclared name: io というエラーメッセージが付記されていました。
    • 変更後もコメントアウトされたままですが、エラーメッセージが intermittent failure: /home/gri/go2/src/pkg/crypto/rsa/pkcs1v15.go:21:27: undeclared name: io に更新されています。これは、このテストが断続的に失敗することを示しており、問題が解決されていないため引き続き無効化されていることを意味します。
  • crypto/x509:

    • 以前はコメントアウトされており、src/pkg/crypto/x509/root.go:15:10: undeclared name: initSystemRoots というエラーメッセージが付記されていました。
    • 変更後はコメントアウトが解除され、"crypto/x509" が有効なテスト対象として追加されています。これは、以前の問題が解決されたか、gotype の解析能力が向上したため、このパッケージのテストを再度実行できるようになったことを示します。
  • net:

    • 以前はコメントアウトされており、src/pkg/net/lookup_unix.go:56:20: undeclared name: cgoLookupHost というエラーメッセージが付記されていました。
    • 変更後もコメントアウトされたままですが、エラーメッセージが c:\go\root\src\pkg\net\interface_windows.go:54:13: invalid operation: division by zero に更新されています。これは、net パッケージのテストが引き続き失敗しており、特にWindows環境での問題が顕著であることを示しています。
  • syscall:

    • 以前は有効なテスト対象として "syscall" が含まれていました。
    • 変更後はコメントアウトされ、c:\go\root\src\pkg\syscall\syscall_windows.go:35:16: cannot convert EINVAL (constant 536870951) to error というエラーメッセージが付記されています。これは、syscall パッケージのテストがWindows環境で失敗するようになったため、一時的に無効化されたことを示します。

これらの変更は、gotype のテストスイートの現実的な状態を反映しており、安定したCI/CDパイプラインを維持するために、失敗するテストを一時的に無効化し、問題が解決されたテストを再度有効化するというプラクティスに従っています。

関連リンク

参考にした情報源リンク

  • なし (提供されたコミット情報と一般的なGoの知識に基づいています)