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

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

このコミットは、src/pkg/net/http/cgi/host_test.go ファイルに単一の変更を加えています。このファイルは、Go言語の標準ライブラリである net/http/cgi パッケージのテストスイートの一部であり、CGI (Common Gateway Interface) ホストの動作を検証するためのものです。

コミット

commit 05bf9a456a2c0c5e0c859782d170cd35db019c8b
Author: Brad Fitzpatrick <bradfitz@golang.org>
Date:   Fri Jan 11 15:11:08 2013 -0800

    net/http/cgi: fix test case sensitivity on Windows
    
    Fixes #4645
    
    R=golang-dev, alex.brainman, minux.ma
    CC=golang-dev
    https://golang.org/cl/7105047

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

https://github.com/golang/go/commit/05bf9a456a2c0c5e0c859782d170cd35db019c8b

元コミット内容

net/http/cgi: fix test case sensitivity on Windows

Fixes #4645

R=golang-dev, alex.brainman, minux.ma
CC=golang-dev
https://golang.org/cl/7105047

変更の背景

このコミットは、Goの net/http/cgi パッケージのテストがWindows環境で失敗する問題を修正するために行われました。具体的には、テスト内で現在の作業ディレクトリ (cwd) を比較する際に、Windowsのファイルシステムがパスの大文字・小文字を区別しない(ケースインセンシティブ)という特性が原因で、テストが誤って失敗するケースがありました。

Unix系システム(Linux, macOSなど)のファイルシステムは通常、パスの大文字・小文字を区別します(例: /home/user/file.txt/home/user/File.txt は異なるファイル)。しかし、Windowsのファイルシステム(NTFSなど)はデフォルトで大文字・小文字を区別しません(例: C:\Users\User\Document.txtC:\users\user\document.txt は同じファイルを指します)。

テストコードが期待するパスと実際に取得したパスの文字列比較を行う際、Windows環境では大文字・小文字の違いがあっても同じファイルを指しているにもかかわらず、文字列としては異なるためテストが失敗していました。このコミットは、このWindows特有の挙動に対応し、パスが同じファイルを指しているかどうかを正確に判定することで、テストの信頼性を向上させることを目的としています。

コミットメッセージにある Fixes #4645 は、GoのIssueトラッカーにおける特定の課題(Issue 4645)を解決したことを示しています。Web検索の結果から、このIssueはCGIホストのテストがWindowsで失敗することに関連しており、Perlの子プロセスをGoプロセスに置き換えるという目標も含まれていたようです。

前提知識の解説

CGI (Common Gateway Interface)

CGIは、Webサーバーが外部プログラム(CGIスクリプト)と連携して動的なコンテンツを生成するための標準的なインターフェースです。Webサーバーはクライアントからのリクエストを受け取ると、CGIスクリプトを起動し、リクエスト情報(HTTPヘッダー、クエリ文字列、POSTデータなど)を環境変数や標準入力としてスクリプトに渡します。スクリプトは処理結果を標準出力に書き出し、Webサーバーはそれを受け取ってクライアントに返します。

Go言語の net/http/cgi パッケージは、GoプログラムをCGIスクリプトとして実行したり、GoのHTTPサーバーがCGIスクリプトを起動してその出力を処理したりするための機能を提供します。

Go言語の os パッケージ

Go言語の os パッケージは、オペレーティングシステム(OS)の機能にアクセスするための基本的なインターフェースを提供します。ファイルシステム操作、プロセス管理、環境変数へのアクセスなどが含まれます。

  • os.Stat(name string) (FileInfo, error): 指定されたパス name のファイルまたはディレクトリに関する情報を返します。返される FileInfo インターフェースには、ファイルサイズ、パーミッション、最終更新時刻などの情報が含まれます。
  • os.SameFile(fi1, fi2 FileInfo) bool: 2つの FileInfo インスタンスが同じファイルを参照しているかどうかを報告します。これは、ファイルシステムが異なるパス(例: シンボリックリンク、大文字・小文字の違い)で同じファイルを指す場合でも、それらが物理的に同じファイルであることを正確に判定するために使用されます。特にWindowsのようなケースインセンシティブなファイルシステムでは、パスの文字列比較だけでは不十分な場合に非常に有用です。

Windowsのファイルシステムにおける大文字・小文字の区別

WindowsのNTFSファイルシステムは、デフォルトでファイル名やディレクトリ名の大文字・小文字を区別しません。これは、ユーザーが MyDocument.txtmydocument.txt を同じファイルとして扱えるようにするためです。しかし、内部的にはファイルシステムはファイル名の大文字・小文字情報を保持しています。この特性は、パスの文字列比較を行う際に問題を引き起こすことがあります。例えば、プログラムが C:\path\to\file.txt を期待しているのに、OSが C:\PATH\TO\FILE.TXT を返した場合、文字列としては一致しませんが、同じファイルを指しています。

技術的詳細

このコミットの技術的な核心は、Windowsのファイルシステムにおけるパスのケースインセンシティブな性質を考慮して、テストの比較ロジックを調整することにあります。

net/http/cgi/host_test.go 内のテストでは、CGIスクリプトが返す環境変数(m マップ)を、期待される値(expectedMap)と比較しています。この環境変数の中には、CGIスクリプトの実行時のカレントワーキングディレクトリ (cwd) が含まれることがあります。

問題は、Windows環境でCGIスクリプトが返す cwd のパスが、テストコードが期待するパスと大文字・小文字の点で異なる場合があることです。例えば、テストが C:\Go\src\pkg\net\http\cgi を期待しているのに、CGIスクリプトが C:\go\src\pkg\net\http\cgi を返した場合、文字列比較 got != expectedtrue となり、テストが失敗してしまいます。

この問題を解決するために、コミットでは os.Statos.SameFile を利用しています。

  1. os.Stat(got): 実際に取得した cwd パス (got) のファイル情報を取得します。
  2. os.Stat(expected): 期待される cwd パス (expected) のファイル情報を取得します。
  3. os.SameFile(fi1, fi2): これら2つのファイル情報が、ファイルシステム上で同じ物理的なファイルを指しているかどうかを判定します。もし同じファイルを指していれば、大文字・小文字の違いは無視され、論理的には一致していると判断できます。
  4. if os.SameFile(fi1, fi2) { got = expected }: os.SameFiletrue を返した場合、つまり両方のパスが同じファイルを指している場合、got の値を expected の値で上書きします。これにより、その後の文字列比較 got != expectedfalse となり、テストが正しくパスするようになります。

このアプローチにより、Windows環境でのテストの誤検出が解消され、テストの信頼性が向上します。

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

diff --git a/src/pkg/net/http/cgi/host_test.go b/src/pkg/net/http/cgi/host_test.go
index 0dc16c2990..811525900b 100644
--- a/src/pkg/net/http/cgi/host_test.go
+++ b/src/pkg/net/http/cgi/host_test.go
@@ -63,7 +63,16 @@ readlines:
 	}
 
 	for key, expected := range expectedMap {
-		if got := m[key]; got != expected {
+		got := m[key]
+		if key == "cwd" {
+			// For Windows. golang.org/issue/4645.
+			fi1, _ := os.Stat(got)
+			fi2, _ := os.Stat(expected)
+			if os.SameFile(fi1, fi2) {
+				got = expected
+			}
+		}
+		if got != expected {
 			t.Errorf("for key %q got %q; expected %q", key, got, expected)
 		}
 	}

コアとなるコードの解説

変更は src/pkg/net/http/cgi/host_test.go ファイルの for key, expected := range expectedMap ループ内で行われています。

元のコードでは、m[key] から取得した値 gotexpected を直接比較していました。

if got := m[key]; got != expected {
    t.Errorf("for key %q got %q; expected %q", key, got, expected)
}

修正後のコードでは、まず got を変数に代入し、その後に特定の条件分岐を追加しています。

got := m[key] // m[key] の値を got に代入
if key == "cwd" { // もし現在のキーが "cwd" (カレントワーキングディレクトリ) であれば
    // For Windows. golang.org/issue/4645.
    fi1, _ := os.Stat(got)      // 取得したパス (got) のファイル情報を取得
    fi2, _ := os.Stat(expected) // 期待されるパス (expected) のファイル情報を取得
    if os.SameFile(fi1, fi2) {  // 2つのファイル情報が同じファイルを指していれば
        got = expected          // got の値を expected で上書き (大文字・小文字の違いを吸収)
    }
}
if got != expected { // 最終的な got と expected を比較
    t.Errorf("for key %q got %q; expected %q", key, got, expected)
}

この変更のポイントは以下の通りです。

  1. got の変数化: if ステートメント内で直接 got を宣言するのではなく、先に got := m[key] として変数に代入することで、その後の条件分岐内で got の値を変更できるようにしています。
  2. cwd キーの特別扱い: if key == "cwd" という条件を追加し、環境変数のキーが "cwd" の場合にのみ特別な処理を行うようにしています。これは、cwd がファイルパスであり、Windowsのケースインセンシティブな特性の影響を受ける可能性が高いからです。
  3. os.Statos.SameFile の利用:
    • os.Stat(got)os.Stat(expected) を呼び出すことで、それぞれのパスが指すファイル(またはディレクトリ)のメタデータ(FileInfo)を取得します。エラーハンドリングは省略されていますが、テストコードなので簡略化されています。
    • os.SameFile(fi1, fi2) は、取得した2つの FileInfo がファイルシステム上で同じ物理的なエンティティを指しているかどうかを効率的かつ正確に判断します。これにより、パスの文字列が大文字・小文字の違いで異なっていても、同じファイルを指していれば true を返します。
  4. got の上書き: os.SameFiletrue を返した場合、つまり論理的に同じパスであると判断された場合、got = expected とすることで、got の値を expected の値に強制的に合わせます。これにより、その後の if got != expected の比較が、大文字・小文字の違いに影響されずに、ファイルシステム上の実体としての一致を評価できるようになります。

この修正により、Windows環境で cwd のパスが大文字・小文字の違いによってテストが誤って失敗することがなくなり、テストの堅牢性が向上しました。

関連リンク

参考にした情報源リンク