[インデックス 14990] ファイルの概要
このコミットは、Go言語のコマンドラインツールgo
のテストスクリプトであるsrc/cmd/go/test.bash
に、不足していたテストケースを追加するものです。具体的には、go get
コマンドがGOPATH
が設定されていない場合やGOPATH
がGOROOT
と同じディレクトリを指している場合に、パッケージを$GOROOT
にダウンロードしようとしないことを検証するテストが追加されています。
コミット
cmd/go: add missing tests
These changes to test.bash were intended to be submitted with CL 6941058, but were accidentally excluded from the original CL.
R=golang-dev
CC=golang-dev
https://golang.org/cl/7232043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/c48f7d6b8af8b1a8ced44453a9970801faeeb9f5
元コミット内容
cmd/go: add missing tests
このコミットは、test.bash
への変更であり、元々はCL 6941058
という変更リスト(Change List)と共に提出される予定でしたが、誤って元のCLから除外されてしまったものです。
変更の背景
この変更の背景には、Go言語のツールチェインにおけるgo get
コマンドの特定の挙動に関する問題、特にissue 4186が関係しています。go get
は、Goのパッケージをダウンロードしてインストールするためのコマンドですが、その動作はGOPATH
とGOROOT
という2つの重要な環境変数に依存します。
GOPATH
はGoのワークスペースのルートディレクトリを指定し、ユーザーが開発するGoのソースコード、パッケージ、実行可能ファイルが配置される場所です。一方、GOROOT
はGoのSDK(標準ライブラリやツールチェイン自体)がインストールされているディレクトリを指します。
Goの設計思想として、ユーザーがダウンロードしたサードパーティのパッケージや自身のプロジェクトのコードはGOPATH
内に配置されるべきであり、GOROOT
はGoの標準ライブラリやツールチェインのコードを保持する場所として予約されています。go get
コマンドが誤ってGOROOT
にパッケージをダウンロードしようとすると、Goのインストールが破損したり、予期せぬ動作を引き起こす可能性があります。
このコミットで追加されたテストは、go get
が以下の2つのシナリオで失敗することを確認するためのものです。
GOPATH
が設定されていない場合 (GOPATH=
)GOPATH
がGOROOT
と同じディレクトリを指している場合 (GOPATH=$GOROOT
)
これらのシナリオでgo get
が失敗することは、go get
がGOROOT
にパッケージをダウンロードしようとしないという期待される挙動を保証するために重要です。元のCL 6941058
でこれらのテストが意図せず除外されたため、このコミットで改めて追加されました。
前提知識の解説
Go言語の環境変数 (GOPATH
, GOROOT
)
GOROOT
: Goのインストールディレクトリを指します。Goの標準ライブラリやコンパイラ、その他のツールがここに格納されています。通常、ユーザーはこのディレクトリの内容を変更しません。GOPATH
: Goのワークスペースのルートディレクトリを指します。Go 1.11以降のGo Modulesの導入によりその重要性は薄れましたが、それ以前のバージョンや特定のレガシーなビルドシステムでは依然として重要な役割を果たします。GOPATH
は通常、以下の3つのサブディレクトリを持ちます。src
: ソースコードが配置されます(例:github.com/user/project
)。pkg
: コンパイル済みのパッケージオブジェクトがキャッシュされます。bin
: コンパイル済みの実行可能ファイルが配置されます。go get
コマンドは、デフォルトでパッケージを$GOPATH/src
以下にダウンロードします。
go get
コマンド
go get
は、リモートリポジトリからGoのパッケージをダウンロードし、必要に応じてビルド・インストールするコマンドです。例えば、go get github.com/some/package
と実行すると、指定されたパッケージが$GOPATH/src/github.com/some/package
にダウンロードされます。-d
フラグを付けると、ダウンロードのみを行い、ビルド・インストールは行いません。
mktemp -d
mktemp -d
は、一時的なユニークなディレクトリを作成するためのシェルコマンドです。テスト環境を隔離するために頻繁に使用されます。このコマンドは作成された一時ディレクトリのパスを標準出力に出力します。
code.google.com/p/go.codereview/cmd/hgpatch
これは、Google CodeでホストされていたGoプロジェクトのコードレビューツールに関連するパッケージのパスです。このパッケージ自体が重要なのではなく、go get
がダウンロードを試みる対象として使用されている点が重要です。
src/cmd/go/test.bash
Goプロジェクトのソースツリー内にあるシェルスクリプトで、go
コマンドラインツールの様々な機能のテストを実行するために使用されます。Goのビルドシステムやテストフレームワークの一部として機能します。
技術的詳細
このコミットで追加されたテストは、src/cmd/go/test.bash
スクリプトの既存のテストスイートに組み込まれています。これらのテストは、go get
コマンドがGOPATH
の適切な設定なしにGOROOT
にパッケージをダウンロードしようとしないという、Goツールチェインの重要なセキュリティおよび整合性ルールを強制します。
テストは以下の手順で実行されます。
- 一時ディレクトリの作成:
d=$(mktemp -d)
とmkdir -p $d/src/pkg
を使用して、テスト用のクリーンな一時ディレクトリ構造を作成します。これは、テストが既存のGOPATH
やGOROOT
の設定に影響を与えないようにするためです。 GOPATH
が未設定の場合のテスト:GOPATH= GOROOT=$d ./testgo get -d code.google.com/p/go.codereview/cmd/hgpatch
を実行します。ここで、GOPATH=
はGOPATH
を空に設定し、GOROOT=$d
は一時ディレクトリをGOROOT
として設定します。./testgo
はテスト対象のgo
コマンドのラッパーです。- このコマンドが成功した場合(
if
条件が真の場合)、それはgo get
がGOPATH
が設定されていないにもかかわらずパッケージをダウンロードしてしまったことを意味するため、エラーメッセージを出力し、テストのok
フラグをfalse
に設定します。
GOPATH
がGOROOT
と同じ場合(GOPATH=$GOROOT
)のテスト:- 同様に一時ディレクトリを作成します。
GOPATH=$d GOROOT=$d ./testgo get -d code.google.com/p/go.codereview/cmd/hgpatch
を実行します。ここではGOPATH
とGOROOT
の両方が同じ一時ディレクトリを指しています。- このコマンドが成功した場合、それは
go get
がGOPATH
がGOROOT
と同じであるにもかかわらずパッケージをダウンロードしてしまったことを意味するため、エラーメッセージを出力し、テストのok
フラグをfalse
に設定します。
- 一時ディレクトリのクリーンアップ: 各テストの後に
rm -rf $d
を実行して、作成した一時ディレクトリを削除し、テスト環境をクリーンに保ちます。
これらのテストは、go get
がGOPATH
の適切な設定なしにGOROOT
に書き込みを行わないという、Goツールチェインの堅牢性を保証するために不可欠です。
コアとなるコードの変更箇所
--- a/src/cmd/go/test.bash
+++ b/src/cmd/go/test.bash
@@ -181,6 +181,24 @@ if [ $(GOPATH= ./testgo install 'foo/quxx' 2>&1 | egrep -c '\(\$GOPATH not set\)\
ok=false
fi
+# issue 4186. go get cannot be used to download packages to $GOROOT
+# Test that without GOPATH set, go get should fail
+d=$(mktemp -d)
+mkdir -p $d/src/pkg
+if GOPATH= GOROOT=$d ./testgo get -d code.google.com/p/go.codereview/cmd/hgpatch ; then
+ echo 'go get code.google.com/p/go.codereview/cmd/hgpatch should not succeed with $GOPATH unset'
+ ok=false
+fi
+rm -rf $d
+# Test that with GOPATH=$GOROOT, go get should fail
+d=$(mktemp -d)
+mkdir -p $d/src/pkg
+if GOPATH=$d GOROOT=$d ./testgo get -d code.google.com/p/go.codereview/cmd/hgpatch ; then
+ echo 'go get code.google.com/p/go.codereview/cmd/hgpatch should not succeed with GOPATH=$GOROOT'
+ ok=false
+fi
+rm -rf $d
+
# clean up
rm -rf testdata/bin testdata/bin1
rm -f testgo
コアとなるコードの解説
追加されたコードブロックは、go get
コマンドの特定の挙動をテストするためのものです。
-
# issue 4186. go get cannot be used to download packages to $GOROOT
- この行は、このテストがGoのissue 4186に関連していることを示しています。このissueは、
go get
が$GOROOT
にパッケージをダウンロードできないという期待される挙動に関するものです。
- この行は、このテストがGoのissue 4186に関連していることを示しています。このissueは、
-
# Test that without GOPATH set, go get should fail
- 最初のテストケースのコメントです。
GOPATH
が設定されていない場合にgo get
が失敗することを確認します。
- 最初のテストケースのコメントです。
-
d=$(mktemp -d)
- 一時的なディレクトリを作成し、そのパスを変数
d
に格納します。これはテストの隔離性を保つためです。
- 一時的なディレクトリを作成し、そのパスを変数
-
mkdir -p $d/src/pkg
- 作成した一時ディレクトリ内に、Goのワークスペース構造に必要な
src/pkg
ディレクトリを作成します。
- 作成した一時ディレクトリ内に、Goのワークスペース構造に必要な
-
if GOPATH= GOROOT=$d ./testgo get -d code.google.com/p/go.codereview/cmd/hgpatch ; then
- この行がテストの核心です。
GOPATH=
:GOPATH
環境変数を空に設定します。GOROOT=$d
:GOROOT
環境変数を先ほど作成した一時ディレクトリ$d
に設定します。./testgo get -d code.google.com/p/go.codereview/cmd/hgpatch
:testgo
(go
コマンドのテスト用ラッパー)を使って、hgpatch
パッケージをダウンロードしようとします。-d
フラグはダウンロードのみを行い、ビルドは行いません。
if ... ; then
:このコマンドが成功した場合(つまり、go get
が予期せずパッケージをダウンロードしてしまった場合)に続くブロックが実行されます。
- この行がテストの核心です。
-
echo 'go get code.google.com/p/go.codereview/cmd/hgpatch should not succeed with $GOPATH unset'
- テストが失敗した場合に表示されるエラーメッセージです。
-
ok=false
- テストが失敗したことを示すフラグを設定します。
test.bash
スクリプト全体でこのok
変数が最終的なテスト結果を決定します。
- テストが失敗したことを示すフラグを設定します。
-
rm -rf $d
- 最初のテストケースで使用した一時ディレクトリを削除し、クリーンアップします。
-
# Test that with GOPATH=$GOROOT, go get should fail
- 2番目のテストケースのコメントです。
GOPATH
がGOROOT
と同じディレクトリを指している場合にgo get
が失敗することを確認します。
- 2番目のテストケースのコメントです。
-
d=$(mktemp -d)
- 2番目のテストケースのために、再度新しい一時ディレクトリを作成します。
-
mkdir -p $d/src/pkg
- 新しい一時ディレクトリ内に
src/pkg
を作成します。
- 新しい一時ディレクトリ内に
-
if GOPATH=$d GOROOT=$d ./testgo get -d code.google.com/p/go.codereview/cmd/hgpatch ; then
- この行もテストの核心です。
GOPATH=$d
:GOPATH
を一時ディレクトリ$d
に設定します。GOROOT=$d
:GOROOT
も一時ディレクトリ$d
に設定します。- これにより、
GOPATH
とGOROOT
が同じ場所を指す状況をシミュレートします。
- このコマンドが成功した場合に続くブロックが実行されます。
- この行もテストの核心です。
-
echo 'go get code.google.com/p/go.codereview/cmd/hgpatch should not succeed with GOPATH=$GOROOT'
- 2番目のテストが失敗した場合に表示されるエラーメッセージです。
-
ok=false
- テストが失敗したことを示すフラグを設定します。
-
rm -rf $d
- 2番目のテストケースで使用した一時ディレクトリを削除し、クリーンアップします。
これらのテストは、go get
がGOPATH
の適切な設定なしにGOROOT
に書き込みを行わないという、Goツールチェインの堅牢性を保証するために不可欠です。
関連リンク
- https://golang.org/cl/7232043 (このコミットに対応するGoの変更リスト)
参考にした情報源リンク
- Go issue 4186: cmd/go: go get cannot be used to download packages to $GOROOT
- Go Modules Reference - The Go Programming Language (GOPATHとGo Modulesの関係について)
- Go Command - The Go Programming Language (
go get
コマンドの詳細について) - mktemp man page (mktempコマンドについて)
- Go Code Review - Google Code Archive (hgpatchパッケージの元のホスティング場所)