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

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

このコミットは、Go言語の標準ライブラリ path/filepath パッケージにおける Clean 関数のテストケースを追加するものです。具体的には、ルートディレクトリからの相対パスで .. (親ディレクトリ) を含む場合の挙動を検証するためのテストが追加されました。これにより、filepath.Clean/../abc のようなパスを正しく /abc と正規化することを確認します。

コミット

  • コミットハッシュ: 8907f94a51345ef738692df611edb710fc555f5a
  • 作者: Han-Wen Nienhuys hanwen@google.com
  • コミット日時: 2012年6月28日 木曜日 09:46:44 -0700

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

https://github.com/golang/go/commit/8907f94a51345ef738692df611edb710fc555f5a

元コミット内容

path/filepath: add test case for rooted ".."

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/6350047

変更の背景

path/filepath パッケージの Clean 関数は、ファイルパスを正規化するための重要な関数です。これまでのテストスイートでは、ルートディレクトリ (/) から始まるパスに .. (親ディレクトリを示すセグメント) が含まれる場合の特定のケース、例えば /../abc のようなパスが適切に処理されることを網羅していなかった可能性があります。

このコミットは、このような「ルート化された ..」を含むパスが Clean 関数によってどのように扱われるべきか、その期待される挙動を明確にし、テストカバレッジを向上させることを目的としています。具体的には、ルートディレクトリより上位のディレクトリは存在しないため、/../abc/abc と正規化されるべきです。このテストケースの追加は、将来的なリグレッションを防ぎ、filepath.Clean の堅牢性を高めるために行われました。

前提知識の解説

Go言語の path/filepath パッケージ

path/filepath パッケージは、Go言語でファイルパスを操作するためのユーティリティ関数を提供します。オペレーティングシステムに依存しないパス操作(例えば、パスの結合、ディレクトリ名の取得、ファイル名の取得など)を行う path パッケージとは異なり、path/filepath は現在のOSのパス規則(Windowsの \ や Unix系の / など)を考慮して動作します。

このパッケージの主要な関数の一つが Clean です。

filepath.Clean 関数

filepath.Clean(path string) 関数は、与えられたパスを「最短で、かつ意味的に等価な」パスに変換します。具体的には以下の処理を行います。

  1. 冗長なセパレータの除去: a//ba/b になります。
  2. . (カレントディレクトリ) の解決: a/./ba/b になります。
  3. .. (親ディレクトリ) の解決: a/b/../ca/c になります。
  4. 末尾のセパレータの除去: a/a になります(ただし、ルートディレクトリ / は例外)。
  5. 空のパスの処理: 空文字列 "". (カレントディレクトリ) になります。

ルート化されたパスと .. の挙動

Unix系システムでは、パスは / (ルートディレクトリ) から始まります。このルートディレクトリはファイルシステムの最上位であり、これより「上位」のディレクトリは存在しません。したがって、/a/../b のようなパスは a ディレクトリから親ディレクトリに戻り、結果として /b となります。

しかし、/../abc のようにルートディレクトリから .. を使ってさらに上位に行こうとする場合、これは意味的にルートディレクトリに留まることを意味します。つまり、/../abc/abc と同じパスを指すべきです。filepath.Clean はこのセマンティクスを正しく処理する必要があります。

技術的詳細

filepath.Clean の内部実装は、パスをセグメントに分割し、スタックのような構造を使って ... を解決していきます。

  • . セグメントは無視されます。
  • .. セグメントは、スタックのトップにある前のセグメントをポップすることで解決されます(つまり、親ディレクトリに戻る)。
  • ルートディレクトリ (/) から始まるパスの場合、スタックが空の状態で .. が現れても、それ以上親ディレクトリに戻ることはできません。この場合、.. は単に無視され、パスはルートディレクトリに留まります。

このコミットで追加されたテストケース {"/../abc", "/abc"} は、まさにこの挙動を検証します。

  1. 入力パスは /../abc です。
  2. Clean 関数はまずルートセパレータ / を処理します。
  3. 次に .. セグメントを処理しようとしますが、現在のパスは既にルートであり、これ以上上位のディレクトリは存在しないため、.. は効果を持ちません。
  4. 最後に abc セグメントが処理され、結果として /abc が返されます。

このテストケースの追加により、filepath.Clean がこの特定のコーナーケースを正しく処理することを保証し、将来的にこのロジックが誤って変更されることを防ぎます。

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

変更は src/pkg/path/filepath/path_test.go ファイルの cleantests 変数に対して行われました。

--- a/src/pkg/path/filepath/path_test.go
+++ b/src/pkg/path/filepath/path_test.go
@@ -20,7 +20,6 @@ type PathTest struct {

 var cleantests = []PathTest{
 	// Already clean
-	{"", "."},
 	{"abc", "abc"},
 	{"abc/def", "abc/def"},
 	{"a/b/c", "a/b/c"},
@@ -31,6 +30,9 @@ var cleantests = []PathTest{
 	{"/abc", "/abc"},
 	{"/", "/"},

+\t// Empty is current dir
+\t{"", "."},
+\n
 	// Remove trailing slash
 	{"abc/", "abc"},
 	{"abc/def/", "abc/def"},
@@ -61,6 +63,7 @@ var cleantests = []PathTest{
 	{"abc/def/../../..", ".."},
 	{"/abc/def/../../..", "/"},
 	{"abc/def/../../../ghi/jkl/../../../mno", "../../mno"},
+\t{"/../abc", "/abc"},

 	// Combinations
 	{"abc/./../def", "def"},

具体的には、以下の変更が行われました。

  1. {"", "."} のテストケースが、// Already clean のセクションから削除され、// Empty is current dir という新しいコメントの下に移動されました。これは機能的な変更ではなく、テストケースの分類と可読性の向上を目的としています。
  2. 最も重要な変更は、{"/../abc", "/abc"} という新しいテストケースが追加されたことです。これは、ルート化されたパスにおける .. の挙動を明示的にテストします。

コアとなるコードの解説

追加されたテストケース {"/../abc", "/abc"} は、filepath.Clean 関数が /../abc という入力パスに対して /abc という期待される出力パスを生成するかどうかを検証します。

  • 入力パス: /../abc
    • 最初の / はルートディレクトリを示します。
    • 次の .. は親ディレクトリを意味しますが、既にルートにいるため、これ以上上位には移動できません。したがって、この .. は実質的に無視されます。
    • 最後の abc はディレクトリまたはファイル名です。
  • 期待される出力パス: /abc
    • filepath.Clean は、ルートからの .. を適切に処理し、パスを /abc に正規化する必要があります。

このテストケースの追加により、filepath.Clean の実装が、ルートパスのセマンティクスを正しく理解し、.. セグメントがルートを越えて移動しようとしないことを保証します。これは、ファイルパスの処理における堅牢性と正確性を高める上で非常に重要です。

関連リンク

  • Go CL 6350047: https://golang.org/cl/6350047 (このコミットに対応するGoのコードレビューシステム上のチェンジリスト)

参考にした情報源リンク