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

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

このコミットは、Go言語の標準ライブラリnetパッケージ内のdial_test.goファイルに対する変更です。具体的には、TestDialTimeoutというテスト関数において、特定のオペレーティングシステム(OS XとWindows)向けに設けられていた特別なテストロジックに、Plan 9オペレーティングシステムを追加するものです。これにより、TestDialTimeoutがPlan 9環境でも適切に機能し、ネットワーク接続のタイムアウト挙動を正確に検証できるようになります。

コミット

net: add plan9 to TestDialTimeout
     === RUN TestDialTimeout
     --- PASS: TestDialTimeout (0.21 seconds)

R=golang-codereviews, bradfitz, 0intro
CC=golang-codereviews, rsc
https://golang.org/cl/49710050

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

https://github.com/golang/go/commit/830bb3797eefd8f197aef194d758f9bb550daeac

元コミット内容

net: add plan9 to TestDialTimeout

このコミットメッセージは、netパッケージのTestDialTimeout関数にPlan 9のサポートを追加したことを簡潔に示しています。テストが正常に実行され、パスしたことも報告されています。

変更の背景

TestDialTimeoutは、Go言語のnetパッケージが提供するネットワーク接続のタイムアウト機能が正しく動作するかを検証するためのテストです。一部のオペレーティングシステム(OS X 10.7以降やWindowsなど)では、TCPのlistenシステムコールにおけるバックログ(保留中の接続要求をキューに入れる最大数)の挙動が、他のOSと異なる場合があります。具体的には、これらのOSではlistenバックログが無視されるか、非常に大きく設定されているため、テストで意図的に接続を拒否させてタイムアウトを発生させるのが難しいことがあります。

このようなOSでは、テストの信頼性を確保するために、意図的に「死んだ」または到達不能なループバックアドレス(例: 127/8範囲内のアドレス)に接続を試みることで、確実にタイムアウトを発生させる特殊なロジックが導入されていました。

このコミットの背景には、Plan 9オペレーティングシステムも同様のネットワークスタックの特性を持つことが判明した、あるいはその可能性が考慮されたため、TestDialTimeoutがPlan 9環境でも堅牢に動作するように、この特殊なテストロジックの適用対象にPlan 9を追加する必要があったという経緯があります。これにより、Go言語のネットワーク機能のクロスプラットフォームな信頼性が向上します。

前提知識の解説

  • Go言語のnetパッケージ: Go言語の標準ライブラリの一部であり、TCP/IP、UDP、UnixドメインソケットなどのネットワークI/Oプリミティブを提供します。クライアントとサーバーアプリケーションを構築するための基本的な機能が含まれています。
  • TestDialTimeout関数: netパッケージのテストスイートに含まれる関数で、Dial(接続確立)操作が指定されたタイムアウト期間内に完了しない場合に、正しくエラーを返すことを検証します。これは、ネットワークの応答が遅い場合や、接続先が存在しない場合にアプリケーションがハングアップするのを防ぐために非常に重要です。
  • dial_test.go: netパッケージのテストコードが記述されているファイルの一つです。Go言語では、慣習的に_test.goというサフィックスを持つファイルにテストコードを記述します。
  • Plan 9: ベル研究所で開発された分散オペレーティングシステムです。Go言語の開発者の一部はPlan 9の設計思想に影響を受けており、Go言語自体もPlan 9をサポート対象のプラットフォームの一つとしています。
  • switch runtime.GOOS: Go言語のコード内で、コンパイル時または実行時のオペレーティングシステム(runtime.GOOSで取得できる)に基づいて異なる処理を行うための制御構造です。これにより、OS固有の挙動に対応したコードを記述できます。
  • ネットワーク接続のタイムアウト: クライアントがサーバーへの接続を試みる際に、一定時間内に接続が確立されない場合に、その試みを中止してエラーを返すメカニズムです。これにより、アプリケーションが無限に接続待ち状態になることを防ぎます。
  • 127/8アドレス: これはIPv4のループバックアドレス範囲(127.0.0.0から127.255.255.255まで)を指します。通常、127.0.0.1がローカルホストとして使用されますが、この範囲内の他のアドレスは、特に設定されていない限り、ネットワーク上で到達不能な「死んだ」アドレスとして機能します。テストでは、意図的に接続失敗を発生させてタイムアウト挙動を検証するために、このようなアドレスが利用されます。
  • listenのバックログ: TCPソケットのlistenシステムコールに渡される引数の一つで、サーバーが同時に受け入れることができる保留中の接続要求(まだacceptされていない接続)の最大数を指定します。一部のOSでは、このバックログの挙動が標準的でない場合があり、テストの信頼性に影響を与えることがあります。

技術的詳細

TestDialTimeout関数は、ネットワーク接続のタイムアウト挙動を検証するために、いくつかの異なるシナリオをテストします。その中には、意図的に接続が失敗するように仕向けるシナリオも含まれます。

このコミットが変更するコードブロックは、runtime.GOOS(現在のOS)に基づいて異なるテスト戦略を適用する部分です。元のコードでは、OS X (darwin) と Windows の場合に特別な処理を行っていました。これらのOSでは、listenシステムコールのバックログが期待通りに機能しない、あるいは非常に大きく設定されているため、通常のテスト手法(例えば、多数の接続を試みてバックログを飽和させることでタイムアウトを誘発する)では信頼性の高いタイムアウトテストが困難でした。

そのため、これらのOSでは、テストは「おそらく死んでいる」127/8範囲内のループバックアドレス(例: 127.0.0.1以外の127.x.y.zアドレスで、実際にサービスが稼働していないもの)への接続を試みます。これにより、接続試行は確実にタイムアウトし、Dial関数のタイムアウト処理が正しく機能するかを検証できます。

このコミットは、この特別な処理を行うcase文に"plan9"を追加します。これは、Plan 9オペレーティングシステムもOS XやWindowsと同様に、listenバックログの挙動が特殊であるか、あるいは同様の理由で「死んだ」アドレスへの接続試行がタイムアウトテストの信頼性を高めるために必要であると判断されたことを意味します。

この変更により、TestDialTimeoutはPlan 9環境でも、そのOSのネットワークスタックの特性を考慮した上で、正確かつ信頼性の高いタイムアウトテストを実行できるようになります。これは、Go言語のネットワーク機能が多様なプラットフォームで一貫して動作することを保証する上で重要な改善です。

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

変更はsrc/pkg/net/dial_test.goファイルの以下の部分で行われました。

--- a/src/pkg/net/dial_test.go
+++ b/src/pkg/net/dial_test.go
@@ -58,7 +58,7 @@ func TestDialTimeout(t *testing.T) {
 			errc <- err
 		}()
 	}
-	case "darwin", "windows":
+	case "darwin", "plan9", "windows":
 		// At least OS X 10.7 seems to accept any number of
 		// connections, ignoring listen's backlog, so resort
 		// to connecting to a hopefully-dead 127/8 address.

コアとなるコードの解説

このコードスニペットは、TestDialTimeout関数内のswitch文の一部です。このswitch文は、runtime.GOOS(現在のオペレーティングシステム)の値に基づいて、異なるテストロジックを実行します。

変更前の行: case "darwin", "windows": これは、現在のOSがmacOS (darwin) または Windows の場合に、続くコードブロックを実行することを示しています。このブロック内のコメントが示すように、これらのOSではlistenのバックログが無視される傾向があるため、テストは「おそらく死んでいる127/8アドレス」への接続を試みることで、タイムアウトを確実に発生させていました。

変更後の行: case "darwin", "plan9", "windows": この変更により、"plan9"が既存のcaseに追加されました。これは、Plan 9オペレーティングシステムもmacOSやWindowsと同様のネットワークスタックの特性を持つため、同じ特殊なタイムアウトテストロジックを適用する必要があることを意味します。

この変更の目的は、TestDialTimeoutがGo言語がサポートするすべてのプラットフォームで、そのプラットフォームのネットワークスタックの特性を考慮した上で、信頼性の高いタイムアウトテストを実行できるようにすることです。これにより、Goのnetパッケージの堅牢性とクロスプラットフォーム互換性が向上します。

関連リンク

参考にした情報源リンク

  • Go言語の公式ドキュメント
  • Go言語のソースコード(特にsrc/pkg/net/dial_test.go
  • TCP listenバックログに関する一般的なネットワーク知識
  • ループバックアドレス(127/8)に関する一般的なネットワーク知識
  • Go言語のコードレビューシステム (Gerrit) の変更履歴 (CL 49710050)
    • https://golang.org/cl/49710050
    • このリンクはコミットメッセージに記載されており、この変更に関する詳細な議論や背景情報が含まれている可能性があります。