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

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

このコミットは、Go言語のobjdumpコマンドのテストに関する変更です。具体的には、objdump_test.goファイルが修正され、AndroidおよびNaCl(Native Client)環境でのテスト実行がスキップされるように変更されました。これは、これらの環境でgo tool nmコマンドが利用できないことに起因するテストの失敗を回避するための対応です。

コミット

commit 8543ed3df5595e584e9b06ae937c7ba72dea9bfe
Author: David Crawshaw <david.crawshaw@zentus.com>
Date:   Tue Jul 8 13:43:22 2014 -0400

    cmd/objdump: skip test on android (no Go tool)
    
    LGTM=minux, iant
    R=golang-codereviews, minux, iant
    CC=golang-codereviews
    https://golang.org/cl/109570043

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

https://github.com/golang/go/commit/8543ed3df5595e584e9b06ae937c7ba72dea9bfe

元コミット内容

cmd/objdump: skip test on android (no Go tool)

このコミットは、cmd/objdumpのテストをAndroid環境でスキップするように変更します。その理由は、Android環境ではgo toolが利用できないためです。

変更の背景

Go言語の開発では、様々なプラットフォーム(OSやアーキテクチャ)での動作を保証するために、広範なテストが行われます。cmd/objdumpは、Goのバイナリを逆アセンブルしてシンボル情報などを表示するためのツールです。このツールのテストは、内部でgo tool nmというコマンドを使用しています。go tool nmは、Goのバイナリからシンボルテーブルを抽出するために使われるユーティリティです。

しかし、AndroidやNaClのような特定の環境では、Goのツールチェイン全体が利用できるわけではありません。特に、go tool nmのような開発・デバッグ用のツールは、これらの組み込み・特殊な環境では提供されないことが一般的です。このため、objdumpのテストがこれらの環境で実行されると、必要なgo tool nmコマンドが見つからずにテストが失敗するという問題が発生していました。

このコミットは、このような環境依存のテスト失敗を回避し、CI/CDパイプラインの健全性を保つことを目的としています。テストが失敗する原因がツールの欠如である場合、その環境でのテストをスキップすることで、他の重要なテストの実行を妨げずに、開発プロセスをスムーズに進めることができます。

前提知識の解説

  • cmd/objdump: Go言語の標準ツールの一つで、Goの実行可能バイナリやオブジェクトファイルを解析し、その内容(特にアセンブリコードやシンボル情報)を表示するために使用されます。C/C++におけるobjdumpコマンドと同様の機能を提供しますが、Goのバイナリ構造に特化しています。デバッグやパフォーマンス分析において、バイナリの内部構造を理解するのに役立ちます。

  • go tool nm: Go言語のツールチェインに含まれるユーティリティの一つです。Goの実行可能バイナリやオブジェクトファイルからシンボルテーブル(関数名、変数名などのシンボルとそのアドレス情報)を抽出するために使用されます。nmは"name list"の略で、Unix系のシステムで広く使われている同名のコマンドに由来します。objdumpのテストでは、このnmツールを使ってシンボル情報を取得し、objdumpが正しくシンボルを解析できるかを確認していました。

  • runtime.GOOS: Go言語の標準ライブラリruntimeパッケージで提供される定数で、プログラムが実行されているオペレーティングシステム(OS)の名前を表す文字列です。例えば、Linuxでは"linux"、macOSでは"darwin"、Windowsでは"windows"、Androidでは"android"、Native Clientでは"nacl"といった値を取ります。この定数を利用することで、OSに依存する処理を条件分岐させることができます。

  • t.Skip() / t.Skipf(): Go言語の標準テストパッケージtestingで提供されるメソッドです。テスト関数内でt.Skip("理由")またはt.Skipf("フォーマット文字列", 引数...)を呼び出すと、そのテストはスキップされ、テスト結果には「SKIP」として記録されます。これは、特定の環境でのみ実行できないテストや、まだ実装されていない機能のテストなどを一時的に無効にする際に便利です。テストが失敗するのではなく、意図的にスキップされたことを明確に示します。

  • AndroidとGoのツールチェイン: AndroidはLinuxカーネルをベースとしたモバイルOSですが、その実行環境は一般的なデスクトップLinuxとは異なります。Go言語はAndroidアプリケーションの開発(Go Mobileプロジェクトなど)もサポートしていますが、Androidデバイス上でGoのコンパイラや開発ツールチェイン全体を直接実行することは通常想定されていません。Goのプログラムはクロスコンパイルされ、Androidデバイスにデプロイされます。そのため、go tool nmのような開発ツールがAndroid環境で利用できないのは自然なことです。

  • NaCl (Native Client): Googleが開発した、Webブラウザ内でネイティブコードを安全に実行するための技術です。Go言語もNaClをターゲットとしてサポートしていましたが、現在は非推奨となっています。NaCl環境もまた、Goの完全なツールチェインが利用できる環境ではありませんでした。

技術的詳細

このコミットの技術的な変更は非常にシンプルで、objdump_test.go内のテスト関数が実行される前に、現在のOSがAndroidまたはNaClであるかをチェックし、該当する場合はテストをスキップするというものです。

変更前は、loadSyms, runObjDump, buildObjdumpの各関数内で、runtime.GOOS == "nacl"という条件でNaCl環境でのみスキップしていました。これは、NaCl環境でもgo tool nmが利用できないためです。

変更後は、この条件がswitch runtime.GOOS文に拡張され、"android""nacl"の両方でテストがスキップされるようになりました。これにより、Android環境でも同様の問題が解決されます。

具体的には、以下のコードパターンが適用されています。

// 変更前
if runtime.GOOS == "nacl" {
    t.Skip("skipping on nacl")
}

// 変更後
switch runtime.GOOS {
case "android", "nacl":
    t.Skipf("skipping on %s", runtime.GOOS)
}

t.Skipfを使用することで、スキップ理由に現在のOS名を含めることができ、テストレポートの可読性が向上します。

この変更は、Goのクロスプラットフォーム開発における現実的な課題への対応を示しています。すべてのプラットフォームで同じテストを完全に実行できるわけではないため、特定の環境で利用できないツールや機能に依存するテストは、その環境でスキップするというプラクティスが採用されています。これにより、テストスイート全体の実行時間を短縮し、無関係な環境でのテスト失敗によるノイズを減らすことができます。

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

変更はsrc/cmd/objdump/objdump_test.goファイルに集中しています。

--- a/src/cmd/objdump/objdump_test.go
+++ b/src/cmd/objdump/objdump_test.go
@@ -19,8 +19,9 @@ import (
 )
 
 func loadSyms(t *testing.T) map[string]string {
-	if runtime.GOOS == "nacl" {
-		t.Skip("skipping on nacl")
+	switch runtime.GOOS {
+	case "android", "nacl":
+		t.Skipf("skipping on %s", runtime.GOOS)
 	}
 
 	cmd := exec.Command("go", "tool", "nm", os.Args[0])
@@ -44,8 +45,9 @@ func loadSyms(t *testing.T) map[string]string {
 }
 
 func runObjDump(t *testing.T, exe, startaddr, endaddr string) (path, lineno string) {
-	if runtime.GOOS == "nacl" {
-		t.Skip("skipping on nacl")
+	switch runtime.GOOS {
+	case "android", "nacl":
+		t.Skipf("skipping on %s", runtime.GOOS)
 	}
 
 	cmd := exec.Command(exe, os.Args[0], startaddr, endaddr)
@@ -111,8 +113,9 @@ func TestObjDump(t *testing.T) {
 }
 
 func buildObjdump(t *testing.T) (tmp, exe string) {
-	if runtime.GOOS == "nacl" {
-		t.Skip("skipping on nacl")
+	switch runtime.GOOS {
+	case "android", "nacl":
+		t.Skipf("skipping on %s", runtime.GOOS)
 	}
 
 	tmp, err := ioutil.TempDir("", "TestObjDump")

コアとなるコードの解説

上記のdiffが示すように、loadSyms, runObjDump, buildObjdumpという3つのテストヘルパー関数(またはテスト関連関数)の冒頭に、OS判定とスキップ処理が追加されています。

  1. func loadSyms(t *testing.T) map[string]string: この関数は、テスト対象のバイナリからシンボル情報をロードするためにgo tool nmコマンドを実行します。変更前はNaCl環境でのみスキップしていましたが、変更後はAndroid環境でもスキップするようになりました。

  2. func runObjDump(t *testing.T, exe, startaddr, endaddr string) (path, lineno string): この関数は、objdumpコマンドを実際に実行し、その出力を解析します。この関数もgo tool nmの出力に依存する可能性があるため、同様にAndroidとNaClでスキップされます。

  3. func buildObjdump(t *testing.T) (tmp, exe string): この関数は、objdumpのテストに必要な一時ファイルや実行可能ファイルをビルドする役割を担っています。ビルドプロセス自体がgo toolに依存する可能性があるため、ここでもAndroidとNaClでのスキップが導入されました。

これらの変更により、AndroidおよびNaCl環境でgo tool nmが利用できないことによるテストの失敗が回避され、CIシステムがより正確な結果を報告できるようになります。t.Skipfを使用することで、どのOSでテストがスキップされたのかがテストログに明示的に表示され、デバッグやテスト結果の理解に役立ちます。

関連リンク

参考にした情報源リンク

  • Go言語の公式ドキュメント
  • Go言語のソースコード(特にsrc/cmd/objdump/objdump_test.go
  • Go言語のIssueトラッカーやコードレビューシステム(CL 109570043)
  • 一般的なGo言語のテストプラクティスに関する情報