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

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

このコミットは、Go言語の標準ライブラリosパッケージ内のテストTestReaddirStatFailuresに関する変更です。具体的には、このテストがPlan 9オペレーティングシステム上で実行されないように修正されています。

コミット

commit 6f97ef28af33fb8c9a2ce19ae74f04cfbead7e7c
Author: David du Colombier <0intro@gmail.com>
Date:   Mon Jan 13 13:24:59 2014 +0100

    os: disable TestReaddirStatFailures on Plan 9
    
    R=rsc, dave, aram, jeremyjackins, lucio.dere
    CC=golang-codereviews, jas
    https://golang.org/cl/50980043

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

https://github.com/golang/go/commit/6f97ef28af33fb8c9a2ce19ae74f04cfbead7e7c

元コミット内容

os: disable TestReaddirStatFailures on Plan 9

R=rsc, dave, aram, jeremyjackins, lucio.dere
CC=golang-codereviews, jas
https://golang.org/cl/50980043

変更の背景

TestReaddirStatFailuresは、os.Readdir関数がディレクトリ内のエントリを読み取る際に、一部のエントリに対してLstat(シンボリックリンクを解決しないstatシステムコール)が失敗した場合の挙動をテストするためのものです。

元のコードでは、Windows環境ではこのテストをスキップしていました。その理由は、Windowsのファイルシステム関連のシステムコールがUnix系OSとは異なり、Lstatを使用するような構造になっていないため、テストの意図するシナリオ(Lstatの失敗をシミュレートすること)が機能しないためでした。

このコミットの背景には、Plan 9環境においても同様の問題が存在することが判明したことがあります。Plan 9もまた、そのファイルシステムとシステムコールの設計が他のUnix系OSとは異なり、TestReaddirStatFailuresが期待通りに動作しない、あるいはテストの前提が成り立たない状況であったと考えられます。テストが特定の環境で常に失敗するか、またはテストの目的がその環境のシステムコール構造に合致しない場合、その環境でのテストをスキップすることは一般的なプラクティスです。これにより、CI/CDパイプラインのノイズを減らし、テスト結果の信頼性を向上させることができます。

前提知識の解説

  • osパッケージ: Go言語の標準ライブラリの一部で、オペレーティングシステムとのインタラクション(ファイルシステム操作、プロセス管理など)を提供します。
  • os.Readdir: 指定されたディレクトリ内のすべてのファイルとディレクトリの情報を読み取り、os.FileInfoインターフェースのスライスとして返します。
  • os.FileInfo: ファイルのメタデータ(名前、サイズ、パーミッション、最終更新時刻など)を表すインターフェースです。
  • Lstatシステムコール: ファイルの情報を取得するシステムコールの一つです。statと異なり、シンボリックリンクを解決せずに、そのシンボリックリンク自体の情報を返します。TestReaddirStatFailuresでは、このLstatが意図的に失敗するシナリオをテストしています。
  • runtime.GOOS: Goプログラムが実行されているオペレーティングシステムを示す文字列定数です。例えば、"linux", "windows", "darwin" (macOS), "plan9"などがあります。
  • Plan 9: ベル研究所で開発された分散オペレーティングシステムです。Unixの概念をさらに推し進め、すべてのリソースをファイルとして扱うという思想が特徴です。ファイルシステムやシステムコールの設計がUnix系OSとは異なる点が多く、Go言語の移植においてもその違いが考慮されることがあります。
  • テストのスキップ: Goのテストフレームワークでは、t.Skip()t.Skipf()を使って、特定の条件(例: 特定のOS、特定の環境変数)が満たされない場合にテストの実行をスキップすることができます。これにより、テストが不必要に失敗するのを防ぎ、テストスイート全体の信頼性を保ちます。

技術的詳細

TestReaddirStatFailuresは、os.Readdirがディレクトリを読み取る際に、内部的に呼び出されるLstatが失敗した場合の挙動を検証するテストです。このテストは、Readdirが部分的な成功(一部のエントリは読み取れるが、一部のエントリのLstatは失敗する)を適切に処理し、エラーを返すことを確認することを目的としています。

テストのメカニズムは、通常、Lstatの動作をフック(差し替え)して、特定の条件下でエラーを返すようにシミュレートすることで実現されます。しかし、WindowsやPlan 9のようなOSでは、Readdirの実装がLstatを直接使用しない、あるいはLstatの失敗をシミュレートするフックが機能しないような異なるシステムコール構造を持っている場合があります。

具体的には、Windowsの場合、ReaddirFindFirstFile/FindNextFileのようなAPIを使用し、これらのAPIはファイル情報を一度に取得するため、個々のエントリに対するLstatのような追加の呼び出しは行われません。同様に、Plan 9のファイルシステムインターフェースも、Unixのreaddirlstatの組み合わせとは異なるセマンティクスを持つ可能性があります。

このため、これらの環境でTestReaddirStatFailuresを実行しても、テストの意図するシナリオが再現されず、テストが常に失敗するか、あるいはテストの目的が達成されないことになります。このコミットは、このような環境依存の挙動を考慮し、テストの実行をスキップすることで、テストスイートの安定性を向上させています。

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

変更はsrc/pkg/os/os_test.goファイル内のTestReaddirStatFailures関数にあります。

--- a/src/pkg/os/os_test.go
+++ b/src/pkg/os/os_test.go
@@ -396,11 +396,12 @@ func touch(t *testing.T, name string) {
 }
 
 func TestReaddirStatFailures(t *testing.T) {
-	if runtime.GOOS == "windows" {
-		// Windows already does this correctly, but is
-		// structured with different syscalls such that it
-		// doesn't use Lstat, so the hook below for testing it
-		// wouldn't work.
+	switch runtime.GOOS {
+	case "windows", "plan9":
+		// Windows and Plan 9 already do this correctly,
+		// but are structured with different syscalls such
+		// that they don't use Lstat, so the hook below for
+		// testing it wouldn't work.
 		t.Skipf("skipping test on %v", runtime.GOOS)
 	}
 	dir, err := ioutil.TempDir("", "")

コアとなるコードの解説

変更前は、if runtime.GOOS == "windows"という条件文でWindows環境でのみテストをスキップしていました。

変更後は、switch runtime.GOOS文が導入され、"windows"に加えて"plan9"もスキップ対象に追加されました。これにより、WindowsとPlan 9の両方の環境でTestReaddirStatFailuresが実行される前にt.Skipfが呼び出され、テストがスキップされるようになります。

コメントも更新され、「Windows and Plan 9 already do this correctly, but are structured with different syscalls such that they don't use Lstat, so the hook below for testing it wouldn't work.」と記述されています。これは、これらのOSがReaddirの失敗ケースを適切に処理するものの、その内部実装がLstatを使用しないため、テストが意図するLstatの失敗をシミュレートするフックが機能しないことを明確にしています。

この変更は、Goのクロスプラットフォーム対応における細かな調整の一例であり、特定のOSのシステムコール特性に合わせてテストの挙動を調整することの重要性を示しています。

関連リンク

参考にした情報源リンク

  • Go言語のソースコード (特にsrc/pkg/os/)
  • Go言語の公式ドキュメント
  • Plan 9のシステムコールに関する一般的な情報 (Web検索)
  • statlstatシステムコールの違いに関する情報 (Web検索)
  • WindowsのファイルI/O APIに関する情報 (Web検索)
  • Go言語のコミット履歴とコードレビュー (GitHub, Go Gerrit)