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

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

このコミットは、Go言語のコマンドラインツールgoのテストスクリプト(src/cmd/go/test.bash)における環境変数GOROOTの扱いを修正するものです。特定のテストが、ユーザーの環境にGOROOTが設定されているかどうかに依存して失敗する問題を解決し、テストの再現性と信頼性を向上させています。

コミット

commit 1561230ca02e6e71afbf5f524fa89a4a5e3fab9a
Author: Andrew Gerrand <adg@golang.org>
Date:   Tue Dec 17 12:17:56 2013 +1100

    cmd/go: set GOROOT when testing "go install cmd/fix"
    
    This particular test would never pass unless you had GOROOT set in your
    environment. This changes makes the test use the baked-in GOROOT, as it
    does with GOOS and GOARCH.
    
    R=golang-dev, dave, iant
    CC=golang-dev
    https://golang.org/cl/43080043

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

https://github.com/golang/go/commit/1561230ca02e6e71afbf5f524fa89a4a5e3fab9a

元コミット内容

cmd/go: set GOROOT when testing "go install cmd/fix"

This particular test would never pass unless you had GOROOT set in your
environment. This changes makes the test use the baked-in GOROOT, as it
does with GOOS and GOARCH.

R=golang-dev, dave, iant
CC=golang-dev
https://golang.org/cl/43080043

変更の背景

このコミットが行われた背景には、Go言語のビルドシステムとテスト環境における環境変数の扱いの問題がありました。特にGOROOTという環境変数は、Goのインストールパスを示す重要な変数であり、goコマンドの動作に大きな影響を与えます。

問題となっていたのは、go install cmd/fixという特定のテストが、テスト実行環境でGOROOTが事前に設定されていることを前提としていた点です。これは、テストの独立性と再現性を損なうものでした。理想的なテストは、外部環境に依存せず、常に同じ結果を返す必要があります。しかし、このテストは、開発者やCI/CD環境によってGOROOTの設定が異なる場合に、予期せぬ失敗を引き起こす可能性がありました。

コミットメッセージにある「This particular test would never pass unless you had GOROOT set in your environment.」という記述が、この問題の核心を突いています。テストが特定の環境変数設定に依存しているため、テストの信頼性が低く、開発者がテストを実行するたびに手動で環境を調整する必要があるという非効率性も生じていました。

この変更の目的は、テストスクリプト自体がGOROOTの値を適切に管理することで、テストの実行環境に依存しない、より堅牢で再現性の高いテストを実現することにありました。これは、GOOSGOARCHといった他のビルド関連の環境変数と同様に、テスト内で「焼き付けられた(baked-in)」値を使用するというアプローチを取ることで達成されています。

前提知識の解説

このコミットを理解するためには、以下のGo言語およびシェルスクリプトに関する前提知識が必要です。

  1. Go言語の環境変数 (GOROOT, GOPATH, GOBIN):

    • GOROOT: GoのSDKがインストールされているルートディレクトリを指します。Goのコンパイラ、標準ライブラリ、ツールなどがこのディレクトリ以下に配置されています。goコマンドは、このGOROOTを基点として動作します。通常、Goのインストール時に自動的に設定されるか、go env GOROOTで確認できます。
    • GOPATH: Goのワークスペースディレクトリを指します。Go 1.11以降のGo Modulesの導入によりその重要性は低下しましたが、それ以前のバージョンでは、サードパーティ製パッケージのソースコードやビルドされたバイナリが配置される場所として非常に重要でした。srcpkgbinのサブディレクトリを持ちます。
    • GOBIN: go installコマンドでビルドされた実行可能ファイルが配置されるディレクトリを指します。GOBINが設定されていない場合、実行可能ファイルはGOPATH/binまたはGOROOT/binに配置されます。
  2. go installコマンド:

    • Goのパッケージをコンパイルし、その実行可能ファイルをGOBINで指定されたディレクトリ(またはデフォルトの場所)にインストールするコマンドです。例えば、go install cmd/fixは、Goの標準ツールであるfixコマンドをビルドしてインストールします。
  3. シェルスクリプト (test.bash):

    • このコミットで変更されているsrc/cmd/go/test.bashは、Go言語のgoコマンド自体をテストするためのBashスクリプトです。このようなスクリプトは、Goのビルドプロセスやツールの動作を検証するために使用されます。
    • unsetコマンド: Bashシェルコマンドで、指定された環境変数の設定を解除します。これにより、その変数が現在のシェルセッションから削除されます。
    • exportコマンド: Bashシェルコマンドで、変数を環境変数として設定し、その変数が子プロセスにも引き継がれるようにします。
    • $(command): コマンド置換と呼ばれ、commandの実行結果を文字列として取得し、その場に展開します。例えば、$(./testgo env GOROOT)は、./testgo env GOROOTコマンドの出力(現在のGOROOTの値)を取得します。
  4. テストの再現性:

    • ソフトウェア開発において、テストは常に同じ入力に対して同じ結果を返す必要があります。これを「再現性」と呼びます。環境変数のような外部要因にテストが依存すると、再現性が損なわれ、テストが「flaky」(不安定)になる原因となります。

これらの知識を前提として、コミットの変更内容とそれがもたらす影響を深く理解することができます。

技術的詳細

このコミットの技術的詳細は、Goのテストスクリプトがどのように環境変数を管理し、テストの独立性を確保しようとしているかにあります。

src/cmd/go/test.bashスクリプトは、goコマンドの様々な側面をテストするために設計されています。テストの実行前に、スクリプトは通常、テストのクリーンな状態を保証するために特定の環境変数をunset(解除)します。これは、以前のテスト実行やユーザーのシェル環境からの影響を排除するためです。

変更前のスクリプトでは、GOPATHGOBINunsetされていましたが、GOROOTは明示的にunsetされていませんでした。コミットメッセージによると、go install cmd/fixをテストする際に、このGOROOTが環境に設定されているかどうかにテストの成否が依存していました。これは、go installコマンドが、インストール先のパスを決定する際に、環境変数GOROOTの値を参照していたためと考えられます。もしGOROOTが設定されていない場合、go installはデフォルトの場所を探すか、あるいはエラーを発生させる可能性がありました。

このコミットは、以下の2つの主要な変更によってこの問題を解決しています。

  1. GOROOTの明示的なunset:

    -unset GOPATH
     unset GOBIN
    +unset GOPATH
    +unset GOROOT
    

    テストの開始時に、GOPATHGOBINに加えてGOROOTも明示的にunsetされるようになりました。これにより、テストが実行される前に、ユーザーのシェル環境に設定されている可能性のあるGOROOTの値がクリアされ、テストが常にクリーンな状態で開始されることが保証されます。これは、テストの再現性を高める上で非常に重要です。

  2. godocインストールテストにおけるGOROOTの明示的な設定:

    TEST godoc installs into GOROOT
    +GOROOT=$(./testgo env GOROOT)
    rm -f $GOROOT/bin/godoc
    ./testgo install code.google.com/p/go.tools/cmd/godoc
    

    godocコマンドのインストールをテストするセクションでは、GOROOTが明示的に設定されるようになりました。GOROOT=$(./testgo env GOROOT)という行は、テスト用のgoコマンド(./testgo)を使って、現在のGo環境が認識している「正しい」GOROOTのパスを取得し、それをテストスクリプト内のGOROOT変数に設定しています。 このアプローチにより、テストは外部環境のGOROOTに依存することなく、Goツールチェーンが内部的に認識しているGOROOTのパスを使用してgodocをインストールしようとします。これにより、go installコマンドが期待通りに動作し、godocが正しい場所にインストールされることを確実にテストできます。

これらの変更は、Goのテストスイートがより堅牢で、環境に依存しないものになるように設計されています。特に、GOROOTのような重要な環境変数をテストスクリプト内で適切に管理することは、CI/CDパイプラインや異なる開発環境でのテストの信頼性を確保するために不可欠です。

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

--- a/src/cmd/go/test.bash
+++ b/src/cmd/go/test.bash
@@ -36,8 +36,9 @@ stop() {\n ok=true\n allok=true\n \n-unset GOPATH\n unset GOBIN\n+unset GOPATH\n+unset GOROOT\n \n TEST \'file:line in error messages\'\n # Test that error messages have file:line information at beginning of\n@@ -258,6 +259,7 @@ if [ ! -x $d/gobin/godoc ]; then\n fi\n \n TEST godoc installs into GOROOT\n+GOROOT=$(./testgo env GOROOT)\n rm -f $GOROOT/bin/godoc\n ./testgo install code.google.com/p/go.tools/cmd/godoc\n if [ ! -x $GOROOT/bin/godoc ]; then\n```

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

このコミットは、`src/cmd/go/test.bash`というシェルスクリプトの2箇所を変更しています。

1.  **テスト開始時の環境変数クリアの強化**:
    ```diff
    -unset GOPATH
     unset GOBIN
    +unset GOPATH
    +unset GOROOT
    ```
    この部分の変更は、テストスクリプトの冒頭近く、テスト実行環境をクリーンアップするセクションで行われています。
    *   `-unset GOPATH`: 変更前は`GOPATH`が`unset`されていました。
    *   `unset GOBIN`: `GOBIN`は変更前後で`unset`されています。
    *   `+unset GOPATH`: `GOPATH`の`unset`が再度追加されていますが、これは実質的に変更前の行を移動し、その後に`GOROOT`の`unset`を追加するためのものです。
    *   `+unset GOROOT`: **この行が最も重要な追加です。** これにより、テストが開始される前に、ユーザーの環境に設定されている可能性のある`GOROOT`環境変数が明示的に解除されます。これにより、テストが外部の`GOROOT`設定に依存せず、常に予測可能なクリーンな状態で実行されることが保証されます。これは、テストの再現性と独立性を高めるための重要なステップです。

2.  **`godoc`インストールテストにおける`GOROOT`の明示的な設定**:
    ```diff
    TEST godoc installs into GOROOT
    +GOROOT=$(./testgo env GOROOT)
    rm -f $GOROOT/bin/godoc
    ./testgo install code.google.com/p/go.tools/cmd/godoc
    if [ ! -x $GOROOT/bin/godoc ]; then
    ```
    この変更は、`godoc`コマンドが`GOROOT`配下に正しくインストールされることをテストするセクションで行われています。
    *   `TEST godoc installs into GOROOT`: これはテストケースのタイトルを示すコメントです。
    *   `+GOROOT=$(./testgo env GOROOT)`: **この行が追加された主要な変更です。**
        *   `./testgo env GOROOT`: これは、テスト用の`go`コマンド(`./testgo`)を実行し、現在のGo環境が認識している`GOROOT`のパスを取得するコマンドです。
        *   `$(...)`: シェルのコマンド置換構文で、`./testgo env GOROOT`の実行結果(例: `/usr/local/go`)を文字列として取得します。
        *   `GOROOT=...`: 取得した`GOROOT`のパスを、このテストセクション内での`GOROOT`環境変数として設定しています。これにより、このテストは、Goツールチェーンが内部的に認識している`GOROOT`のパスを使用して`godoc`をインストールしようとします。
    *   `rm -f $GOROOT/bin/godoc`: 設定された`GOROOT`パスに基づいて、既存の`godoc`バイナリを削除します。
    *   `./testgo install code.google.com/p/go.tools/cmd/godoc`: `godoc`をインストールします。この`install`コマンドは、直前に設定された`GOROOT`の値を参照して動作します。

これらの変更により、`test.bash`スクリプトは、`GOROOT`環境変数の扱いに関してより自己完結的かつ堅牢になりました。テストの開始時に`GOROOT`をクリアし、特定のテストで必要に応じてGoツールチェーンが提供する「正しい」`GOROOT`の値を明示的に設定することで、テストの信頼性と再現性が大幅に向上しています。

## 関連リンク

*   Go CL 43080043: [https://golang.org/cl/43080043](https://golang.org/cl/43080043)

## 参考にした情報源リンク

*   Go言語の公式ドキュメント (GOROOT, GOPATH, go installに関する情報)
*   Bashシェルスクリプトのドキュメント (unset, export, コマンド置換に関する情報)
*   Go言語のテストに関する一般的なプラクティス