[インデックス 19322] ファイルの概要
このコミットは、Go言語のcmd/nm
ツールのテストファイルであるsrc/cmd/nm/nm_test.go
に対する変更です。nm
ツールは、Unix系のシステムにおける同名のコマンドと同様に、実行可能ファイルやオブジェクトファイルのシンボルテーブルを検査するために使用されます。このテストファイルは、nm
ツールのビルドと実行が正しく行われることを検証します。
コミット
commit 2a7ab1616f861087c6da320f7de360949868384a
Author: Alex Brainman <alex.brainman@gmail.com>
Date: Mon May 12 09:26:05 2014 +1000
cmd/nm: do not write to GOROOT testdata directories during TestNM
LGTM=bradfitz
R=bradfitz, 0intro
CC=golang-codereviews
https://golang.org/cl/95280043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/2a7ab1616f861087c6da320f7de360949868384a
元コミット内容
cmd/nm: do not write to GOROOT testdata directories during TestNM
LGTM=bradfitz
R=bradfitz, 0intro
CC=golang-codereviews
https://golang.org/cl/95280043
変更の背景
このコミットの背景には、Goのテストフレームワークにおける一般的な問題、特にテストが実行される環境のクリーンさを保つという課題があります。以前のTestNM
の実装では、go build -o testnm.exe cmd/nm
コマンドを使用してtestnm.exe
という実行ファイルをテストが実行されるディレクトリ(多くの場合、GOROOT
内のソースディレクトリ)に直接生成していました。
このアプローチにはいくつかの問題がありました。
- 作業ディレクトリの汚染: テストが実行されるたびに、
testnm.exe
というファイルがソースコードリポジトリ内に生成され、テスト終了後に削除されるものの、一時的に作業ディレクトリを汚染していました。これは、特に並行してテストが実行される場合や、テストが異常終了した場合に問題を引き起こす可能性がありました。 GOROOT
の整合性:GOROOT
はGoのインストールディレクトリであり、その内容は通常、Goの配布物の一部として管理されるべきです。テストがGOROOT
内のディレクトリにファイルを書き込むことは、GOROOT
の整合性を損なう可能性があり、予期せぬ副作用やビルド環境の不安定化を招く恐れがありました。- クリーンアップの信頼性:
defer os.Remove("testnm.exe")
によるクリーンアップは、テストが正常に終了した場合にのみ機能します。テストがパニックを起こしたり、予期せぬエラーで終了したりした場合、testnm.exe
が残ってしまう可能性がありました。
これらの問題を解決し、テストの独立性と信頼性を高めるために、テスト中に生成される一時ファイルをGOROOT
の外部にある一時ディレクトリに配置し、テスト終了後に確実にクリーンアップする変更が必要とされました。
前提知識の解説
go build
go build
コマンドは、Goのソースコードをコンパイルして実行可能ファイルやパッケージを生成するために使用されます。-o
フラグを使用すると、出力される実行可能ファイルの名前とパスを指定できます。
cmd/nm
cmd/nm
は、Goツールチェーンの一部として提供されるnm
コマンドの実装です。nm
は"name list"の略で、Unix系のシステムで広く使われているユーティリティです。実行可能ファイル、オブジェクトファイル、共有ライブラリなどのバイナリファイルに含まれるシンボル(関数名、変数名など)のリストを表示するために使用されます。デバッグやバイナリの解析に役立ちます。
GOROOT
GOROOT
は、Go言語のインストールディレクトリを指す環境変数です。Goの標準ライブラリ、ツール、ドキュメントなどがこのディレクトリに格納されています。Goのビルドシステムは、このGOROOT
パスを基にGoの標準パッケージやツールを見つけます。
testdata
ディレクトリ
Goのテストでは、テストに必要なデータファイルをtestdata
という名前のディレクトリに配置する慣習があります。go test
コマンドは、testdata
ディレクトリを特別扱いし、テスト実行時にその内容をテストバイナリに含めたり、テストコードからアクセスできるようにしたりします。このコミットで言及されているGOROOT testdata directories
は、Goの標準ライブラリやツールのテストデータが格納されているディレクトリを指します。
io/ioutil
パッケージ
io/ioutil
パッケージは、Go 1.16で非推奨となり、Go 1.18で削除されましたが、このコミットが作成された2014年当時は、ファイルやディレクトリのI/O操作を簡素化するためのユーティリティ関数を提供していました。特に、ioutil.TempDir
関数は一時ディレクトリを作成するために使用されます。
ioutil.TempDir(dir, pattern)
この関数は、指定されたdir
ディレクトリ内に、指定されたpattern
に基づいてユニークな名前の一時ディレクトリを作成します。dir
が空文字列の場合、システムのデフォルトの一時ディレクトリ(例: /tmp
)が使用されます。この関数は作成された一時ディレクトリのパスを返します。
os.RemoveAll(path)
この関数は、指定されたパスにあるファイルまたはディレクトリ(およびその中のすべての内容)を再帰的に削除します。一時ディレクトリのクリーンアップによく使用されます。
defer
ステートメント
Go言語のdefer
ステートメントは、そのステートメントを含む関数がリターンする直前に、指定された関数呼び出しを実行することを保証します。これは、リソースの解放(ファイルのクローズ、ロックの解除、一時ディレクトリの削除など)を確実に行うために非常に便利です。たとえ関数がエラーで終了しても、defer
された関数は実行されます。
技術的詳細
このコミットの技術的な核心は、テスト中に生成される一時的な実行ファイルtestnm.exe
の配置場所を、永続的なソースツリー内から一時ディレクトリへと変更することにあります。
具体的な変更点は以下の通りです。
io/ioutil
のインポート: 一時ディレクトリを作成するために、io/ioutil
パッケージがインポートされます。- 一時ディレクトリの作成:
tmpDir, err := ioutil.TempDir("", "TestNM") if err != nil { t.Fatal("TempDir failed: ", err) }
ioutil.TempDir("", "TestNM")
を呼び出すことで、システムのデフォルトの一時ディレクトリ(例:/tmp
)内にTestNM
というプレフィックスを持つユニークな名前の一時ディレクトリが作成されます。このディレクトリのパスはtmpDir
変数に格納されます。エラーが発生した場合は、テストが失敗します。 - 一時ディレクトリの確実なクリーンアップ:
defer os.RemoveAll(tmpDir)
defer
ステートメントを使用してos.RemoveAll(tmpDir)
が呼び出されます。これにより、TestNM
関数が終了する際に(正常終了、エラー終了、パニックのいずれであっても)、作成された一時ディレクトリとその内容が確実に削除されます。これは、テスト後の環境をクリーンに保つ上で非常に重要です。 testnm.exe
のビルドパスの変更:// 変更前: // out, err := exec.Command("go", "build", "-o", "testnm.exe", "cmd/nm").CombinedOutput() // defer os.Remove("testnm.exe") // 変更後: testnmpath := filepath.Join(tmpDir, "testnm.exe") out, err := exec.Command("go", "build", "-o", testnmpath, "cmd/nm").CombinedOutput()
testnm.exe
の出力先が、現在のディレクトリから新しく作成された一時ディレクトリ内のパス(testnmpath
)に変更されます。これにより、testnm.exe
がソースツリーを汚染することがなくなります。また、一時ディレクトリ全体がos.RemoveAll
で削除されるため、個別のos.Remove("testnm.exe")
は不要になります。testnm.exe
の実行パスの変更:// 変更前: // cmd := exec.Command("./testnm.exe", exepath) // cmd := exec.Command("./testnm.exe", os.Args[0]) // 変更後: cmd := exec.Command(testnmpath, exepath) cmd := exec.Command(testnmpath, os.Args[0])
testnm.exe
を実行する際のパスも、相対パス./testnm.exe
から、一時ディレクトリ内の絶対パスtestnmpath
に変更されます。これにより、テストがどこから実行されても、正しいtestnm.exe
が参照されることが保証されます。
これらの変更により、TestNM
はより堅牢になり、テスト環境への副作用を最小限に抑えることができるようになりました。
コアとなるコードの変更箇所
--- a/src/cmd/nm/nm_test.go
+++ b/src/cmd/nm/nm_test.go
@@ -8,6 +8,7 @@ import (
"bufio"
"bytes"
"fmt"
+ "io/ioutil"
"os"
"os/exec"
"path/filepath"
@@ -54,11 +55,17 @@ func checkSymbols(t *testing.T, nmoutput []byte) {
}
func TestNM(t *testing.T) {
- out, err := exec.Command("go", "build", "-o", "testnm.exe", "cmd/nm").CombinedOutput()
+ tmpDir, err := ioutil.TempDir("", "TestNM")
if err != nil {
- t.Fatalf("go build -o testnm.exe cmd/nm: %v\n%s", err, string(out))
+ t.Fatal("TempDir failed: ", err)
+ }
+ defer os.RemoveAll(tmpDir)
+
+ testnmpath := filepath.Join(tmpDir, "testnm.exe")
+ out, err := exec.Command("go", "build", "-o", testnmpath, "cmd/nm").CombinedOutput()
+ if err != nil {
+ t.Fatalf("go build -o %v cmd/nm: %v\n%s", testnmpath, err, string(out))
}
- defer os.Remove("testnm.exe")
testfiles := []string{
"elf/testdata/gcc-386-freebsd-exec",
@@ -72,14 +79,14 @@ func TestNM(t *testing.T) {
}
for _, f := range testfiles {
exepath := filepath.Join(runtime.GOROOT(), "src", "pkg", "debug", f)
- cmd := exec.Command("./testnm.exe", exepath)
+ cmd := exec.Command(testnmpath, exepath)
out, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("go tool nm %v: %v\\n%s", exepath, err, string(out))
}
}
- cmd := exec.Command("./testnm.exe", os.Args[0])
+ cmd := exec.Command(testnmpath, os.Args[0])
out, err = cmd.CombinedOutput()
if err != nil {
t.Fatalf("go tool nm %v: %v\\n%s", os.Args[0], err, string(out))
コアとなるコードの解説
-
+ "io/ioutil"
:io/ioutil
パッケージが新しくインポートされました。これは、一時ディレクトリを作成するためのioutil.TempDir
関数を使用するために必要です。 -
- out, err := exec.Command("go", "build", "-o", "testnm.exe", "cmd/nm").CombinedOutput()
:testnm.exe
を現在のディレクトリにビルドしていた元の行が削除されました。 -
+ tmpDir, err := ioutil.TempDir("", "TestNM")
:ioutil.TempDir
関数を呼び出して、システムの一時ディレクトリ内にTestNM
というプレフィックスを持つ新しい一時ディレクトリを作成します。このディレクトリのパスはtmpDir
変数に格納されます。 -
+ if err != nil { t.Fatal("TempDir failed: ", err) }
:ioutil.TempDir
の呼び出しでエラーが発生した場合のハンドリングです。エラーが発生した場合は、テストを即座に終了させます。 -
+ defer os.RemoveAll(tmpDir)
:defer
ステートメントにより、TestNM
関数が終了する際にos.RemoveAll(tmpDir)
が実行されることが保証されます。これにより、作成された一時ディレクトリとその内容(testnm.exe
を含む)が確実に削除され、テスト後の環境がクリーンに保たれます。 -
- defer os.Remove("testnm.exe")
: 以前のtestnm.exe
を個別に削除するdefer
ステートメントは、一時ディレクトリ全体を削除するdefer os.RemoveAll(tmpDir)
によって不要になったため削除されました。 -
+ testnmpath := filepath.Join(tmpDir, "testnm.exe")
: 新しく作成された一時ディレクトリtmpDir
の中にtestnm.exe
という名前で実行ファイルを配置するための完全なパスを構築します。 -
+ out, err := exec.Command("go", "build", "-o", testnmpath, "cmd/nm").CombinedOutput()
:go build
コマンドの出力先が、現在のディレクトリからtestnmpath
(一時ディレクトリ内のパス)に変更されました。これにより、ビルドされた実行ファイルが一時ディレクトリに格納されます。 -
+ if err != nil { t.Fatalf("go build -o %v cmd/nm: %v\\n%s", testnmpath, err, string(out)) }
: ビルドコマンドでエラーが発生した場合のハンドリングです。エラーメッセージには、ビルド先のパスtestnmpath
が含まれるようになりました。 -
- cmd := exec.Command("./testnm.exe", exepath)
および- cmd := exec.Command("./testnm.exe", os.Args[0])
:testnm.exe
を実行する際に、相対パス./testnm.exe
を使用していた行が削除されました。 -
+ cmd := exec.Command(testnmpath, exepath)
および+ cmd := exec.Command(testnmpath, os.Args[0])
:testnm.exe
を実行する際に、一時ディレクトリ内にビルドされた実行ファイルの絶対パスtestnmpath
を使用するように変更されました。これにより、テストの実行場所に関わらず、正しいtestnm.exe
が確実に実行されます。
これらの変更により、TestNM
はより堅牢で、テスト環境に副作用を与えないようになりました。
関連リンク
参考にした情報源リンク
- Go言語のioutil.TempDir関数について (Go 1.16以降は
os.MkdirTemp
の使用が推奨されますが、当時の情報として) - Go言語のdeferステートメント
- Go言語のos.RemoveAll関数について
- Go言語のgo buildコマンドについて
- Unix nmコマンド
- Goのテストにおけるtestdataディレクトリ
- GOROOT環境変数
# [インデックス 19322] ファイルの概要
このコミットは、Go言語の`cmd/nm`ツールのテストファイルである`src/cmd/nm/nm_test.go`に対する変更です。`nm`ツールは、Unix系のシステムにおける同名のコマンドと同様に、実行可能ファイルやオブジェクトファイルのシンボルテーブルを検査するために使用されます。このテストファイルは、`nm`ツールのビルドと実行が正しく行われることを検証します。
## コミット
commit 2a7ab1616f861087c6da320f7de360949868384a Author: Alex Brainman alex.brainman@gmail.com Date: Mon May 12 09:26:05 2014 +1000
cmd/nm: do not write to GOROOT testdata directories during TestNM
LGTM=bradfitz
R=bradfitz, 0intro
CC=golang-codereviews
https://golang.org/cl/95280043
## GitHub上でのコミットページへのリンク
[https://github.com/golang/go/commit/2a7ab1616f861087c6da320f7de360949868384a](https://github.com/golang/go/commit/2a7ab1616f861087c6da320f7de360949868384a)
## 元コミット内容
cmd/nm: do not write to GOROOT testdata directories during TestNM
LGTM=bradfitz R=bradfitz, 0intro CC=golang-codereviews https://golang.org/cl/95280043
## 変更の背景
このコミットの背景には、Goのテストフレームワークにおける一般的な問題、特にテストが実行される環境のクリーンさを保つという課題があります。以前の`TestNM`の実装では、`go build -o testnm.exe cmd/nm`コマンドを使用して`testnm.exe`という実行ファイルをテストが実行されるディレクトリ(多くの場合、`GOROOT`内のソースディレクトリ)に直接生成していました。
このアプローチにはいくつかの問題がありました。
1. **作業ディレクトリの汚染**: テストが実行されるたびに、`testnm.exe`というファイルがソースコードリポジトリ内に生成され、テスト終了後に削除されるものの、一時的に作業ディレクトリを汚染していました。これは、特に並行してテストが実行される場合や、テストが異常終了した場合に問題を引き起こす可能性がありました。
2. **`GOROOT`の整合性**: `GOROOT`はGoのインストールディレクトリであり、その内容は通常、Goの配布物の一部として管理されるべきです。テストが`GOROOT`内のディレクトリにファイルを書き込むことは、`GOROOT`の整合性を損なう可能性があり、予期せぬ副作用やビルド環境の不安定化を招く恐れがありました。
3. **クリーンアップの信頼性**: `defer os.Remove("testnm.exe")`によるクリーンアップは、テストが正常に終了した場合にのみ機能します。テストがパニックを起こしたり、予期せぬエラーで終了したりした場合、`testnm.exe`が残ってしまう可能性がありました。
これらの問題を解決し、テストの独立性と信頼性を高めるために、テスト中に生成される一時ファイルを`GOROOT`の外部にある一時ディレクトリに配置し、テスト終了後に確実にクリーンアップする変更が必要とされました。
## 前提知識の解説
### `go build`
`go build`コマンドは、Goのソースコードをコンパイルして実行可能ファイルやパッケージを生成するために使用されます。`-o`フラグを使用すると、出力される実行可能ファイルの名前とパスを指定できます。
### `cmd/nm`
`cmd/nm`は、Goツールチェーンの一部として提供される`nm`コマンドの実装です。`nm`は"name list"の略で、Unix系のシステムで広く使われているユーティリティです。実行可能ファイル、オブジェクトファイル、共有ライブラリなどのバイナリファイルに含まれるシンボル(関数名、変数名など)のリストを表示するために使用されます。デバッグやバイナリの解析に役立ちます。
### `GOROOT`
`GOROOT`は、Go言語のインストールディレクトリを指す環境変数です。Goの標準ライブラリ、ツール、ドキュメントなどがこのディレクトリに格納されています。Goのビルドシステムは、この`GOROOT`パスを基にGoの標準パッケージやツールを見つけます。
### `testdata`ディレクトリ
Goのテストでは、テストに必要なデータファイルを`testdata`という名前のディレクトリに配置する慣習があります。`go test`コマンドは、`testdata`ディレクトリを特別扱いし、テスト実行時にその内容をテストバイナリに含めたり、テストコードからアクセスできるようにしたりします。このコミットで言及されている`GOROOT testdata directories`は、Goの標準ライブラリやツールのテストデータが格納されているディレクトリを指します。
### `io/ioutil`パッケージ
`io/ioutil`パッケージは、Go 1.16で非推奨となり、Go 1.18で削除されましたが、このコミットが作成された2014年当時は、ファイルやディレクトリのI/O操作を簡素化するためのユーティリティ関数を提供していました。特に、`ioutil.TempDir`関数は一時ディレクトリを作成するために使用されます。
### `ioutil.TempDir(dir, pattern)`
この関数は、指定された`dir`ディレクトリ内に、指定された`pattern`に基づいてユニークな名前の一時ディレクトリを作成します。`dir`が空文字列の場合、システムのデフォルトの一時ディレクトリ(例: `/tmp`)が使用されます。この関数は作成された一時ディレクトリのパスを返します。
### `os.RemoveAll(path)`
この関数は、指定されたパスにあるファイルまたはディレクトリ(およびその中のすべての内容)を再帰的に削除します。一時ディレクトリのクリーンアップによく使用されます。
### `defer`ステートメント
Go言語の`defer`ステートメントは、そのステートメントを含む関数がリターンする直前に、指定された関数呼び出しを実行することを保証します。これは、リソースの解放(ファイルのクローズ、ロックの解除、一時ディレクトリの削除など)を確実に行うために非常に便利です。たとえ関数がエラーで終了しても、`defer`された関数は実行されます。
## 技術的詳細
このコミットの技術的な核心は、テスト中に生成される一時的な実行ファイル`testnm.exe`の配置場所を、永続的なソースツリー内から一時ディレクトリへと変更することにあります。
具体的な変更点は以下の通りです。
1. **`io/ioutil`のインポート**: 一時ディレクトリを作成するために、`io/ioutil`パッケージがインポートされます。
2. **一時ディレクトリの作成**:
```go
tmpDir, err := ioutil.TempDir("", "TestNM")
if err != nil {
t.Fatal("TempDir failed: ", err)
}
```
`ioutil.TempDir("", "TestNM")`を呼び出すことで、システムのデフォルトの一時ディレクトリ(例: `/tmp`)内に`TestNM`というプレフィックスを持つユニークな名前の一時ディレクトリが作成されます。このディレクトリのパスは`tmpDir`変数に格納されます。エラーが発生した場合は、テストが失敗します。
3. **一時ディレクトリの確実なクリーンアップ**:
```go
defer os.RemoveAll(tmpDir)
```
`defer`ステートメントを使用して`os.RemoveAll(tmpDir)`が呼び出されます。これにより、`TestNM`関数が終了する際に(正常終了、エラー終了、パニックのいずれであっても)、作成された一時ディレクトリとその内容が確実に削除されます。これは、テスト後の環境をクリーンに保つ上で非常に重要です。
4. **`testnm.exe`のビルドパスの変更**:
```go
// 変更前:
// out, err := exec.Command("go", "build", "-o", "testnm.exe", "cmd/nm").CombinedOutput()
// defer os.Remove("testnm.exe")
// 変更後:
testnmpath := filepath.Join(tmpDir, "testnm.exe")
out, err := exec.Command("go", "build", "-o", testnmpath, "cmd/nm").CombinedOutput()
```
`testnm.exe`の出力先が、現在のディレクトリから新しく作成された一時ディレクトリ内のパス(`testnmpath`)に変更されます。これにより、`testnm.exe`がソースツリーを汚染することがなくなります。また、一時ディレクトリ全体が`os.RemoveAll`で削除されるため、個別の`os.Remove("testnm.exe")`は不要になります。
5. **`testnm.exe`の実行パスの変更**:
```go
// 変更前:
// cmd := exec.Command("./testnm.exe", exepath)
// cmd := exec.Command("./testnm.exe", os.Args[0])
// 変更後:
cmd := exec.Command(testnmpath, exepath)
cmd := exec.Command(testnmpath, os.Args[0])
```
`testnm.exe`を実行する際のパスも、相対パス`./testnm.exe`から、一時ディレクトリ内の絶対パス`testnmpath`に変更されます。これにより、テストがどこから実行されても、正しい`testnm.exe`が参照されることが保証されます。
これらの変更により、`TestNM`はより堅牢になり、テスト環境への副作用を最小限に抑えることができるようになりました。
## コアとなるコードの変更箇所
```diff
--- a/src/cmd/nm/nm_test.go
+++ b/src/cmd/nm/nm_test.go
@@ -8,6 +8,7 @@ import (
"bufio"
"bytes"
"fmt"
+ "io/ioutil"
"os"
"os/exec"
"path/filepath"
@@ -54,11 +55,17 @@ func checkSymbols(t *testing.T, nmoutput []byte) {
}
func TestNM(t *testing.T) {
- out, err := exec.Command("go", "build", "-o", "testnm.exe", "cmd/nm").CombinedOutput()
+ tmpDir, err := ioutil.TempDir("", "TestNM")
if err != nil {
- t.Fatalf("go build -o testnm.exe cmd/nm: %v\\n%s", err, string(out))
+ t.Fatal("TempDir failed: ", err)
+ }
+ defer os.RemoveAll(tmpDir)
+
+ testnmpath := filepath.Join(tmpDir, "testnm.exe")
+ out, err := exec.Command("go", "build", "-o", testnmpath, "cmd/nm").CombinedOutput()
+ if err != nil {
+ t.Fatalf("go build -o %v cmd/nm: %v\\n%s", testnmpath, err, string(out))
}
- defer os.Remove("testnm.exe")
testfiles := []string{
"elf/testdata/gcc-386-freebsd-exec",
@@ -72,14 +79,14 @@ func TestNM(t *testing.T) {
}
for _, f := range testfiles {
exepath := filepath.Join(runtime.GOROOT(), "src", "pkg", "debug", f)
- cmd := exec.Command("./testnm.exe", exepath)
+ cmd := exec.Command(testnmpath, exepath)
out, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("go tool nm %v: %v\\n%s", exepath, err, string(out))
}
}
- cmd := exec.Command("./testnm.exe", os.Args[0])
+ cmd := exec.Command(testnmpath, os.Args[0])
out, err = cmd.CombinedOutput()
if err != nil {
t.Fatalf("go tool nm %v: %v\\n%s", os.Args[0], err, string(out))
コアとなるコードの解説
-
+ "io/ioutil"
:io/ioutil
パッケージが新しくインポートされました。これは、一時ディレクトリを作成するためのioutil.TempDir
関数を使用するために必要です。 -
- out, err := exec.Command("go", "build", "-o", "testnm.exe", "cmd/nm").CombinedOutput()
:testnm.exe
を現在のディレクトリにビルドしていた元の行が削除されました。 -
+ tmpDir, err := ioutil.TempDir("", "TestNM")
:ioutil.TempDir
関数を呼び出して、システムの一時ディレクトリ内にTestNM
というプレフィックスを持つ新しい一時ディレクトリを作成します。このディレクトリのパスはtmpDir
変数に格納されます。 -
+ if err != nil { t.Fatal("TempDir failed: ", err) }
:ioutil.TempDir
の呼び出しでエラーが発生した場合のハンドリングです。エラーが発生した場合は、テストを即座に終了させます。 -
+ defer os.RemoveAll(tmpDir)
:defer
ステートメントにより、TestNM
関数が終了する際にos.RemoveAll(tmpDir)
が実行されることが保証されます。これにより、作成された一時ディレクトリとその内容(testnm.exe
を含む)が確実に削除され、テスト後の環境がクリーンに保たれます。 -
- defer os.Remove("testnm.exe")
: 以前のtestnm.exe
を個別に削除するdefer
ステートメントは、一時ディレクトリ全体を削除するdefer os.RemoveAll(tmpDir)
によって不要になったため削除されました。 -
+ testnmpath := filepath.Join(tmpDir, "testnm.exe")
: 新しく作成された一時ディレクトリtmpDir
の中にtestnm.exe
という名前で実行ファイルを配置するための完全なパスを構築します。 -
+ out, err := exec.Command("go", "build", "-o", testnmpath, "cmd/nm").CombinedOutput()
:go build
コマンドの出力先が、現在のディレクトリからtestnmpath
(一時ディレクトリ内のパス)に変更されました。これにより、ビルドされた実行ファイルが一時ディレクトリに格納されます。 -
+ if err != nil { t.Fatalf("go build -o %v cmd/nm: %v\\n%s", testnmpath, err, string(out)) }
: ビルドコマンドでエラーが発生した場合のハンドリングです。エラーメッセージには、ビルド先のパスtestnmpath
が含まれるようになりました。 -
- cmd := exec.Command("./testnm.exe", exepath)
および- cmd := exec.Command("./testnm.exe", os.Args[0])
:testnm.exe
を実行する際に、相対パス./testnm.exe
を使用していた行が削除されました。 -
+ cmd := exec.Command(testnmpath, exepath)
および+ cmd := exec.Command(testnmpath, os.Args[0])
:testnm.exe
を実行する際に、一時ディレクトリ内にビルドされた実行ファイルの絶対パスtestnmpath
を使用するように変更されました。これにより、テストの実行場所に関わらず、正しいtestnm.exe
が確実に実行されます。
これらの変更により、TestNM
はより堅牢で、テスト環境に副作用を与えないようになりました。
関連リンク
参考にした情報源リンク
- Go言語のioutil.TempDir関数について (Go 1.16以降は
os.MkdirTemp
の使用が推奨されますが、当時の情報として) - Go言語のdeferステートメント
- Go言語のos.RemoveAll関数について
- Go言語のgo buildコマンドについて
- Unix nmコマンド
- Goのテストにおけるtestdataディレクトリ
- GOROOT環境変数