[インデックス 15998] ファイルの概要
このコミットは、Go言語のネットワークパッケージ(net
パッケージ)におけるIPv6関連のテストをWindows環境で有効化し、同時にGo 1.0時代の非IPv6対応WindowsコードがIPv6有効なWindowsカーネル上で実行されることによって発生していた冗長なテストを削除することを目的としています。これにより、Windows環境でのIPv6ネットワーク機能のテストカバレッジが向上し、テストスイートの効率化が図られています。
コミット
0f9b3059bc969053b68cf135c4c8266da53a6405
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/0f9b3059bc969053b68cf135c4c8266da53a6405
元コミット内容
net: enable IPv6 tests on Windows
Also removes redundant tests that run Go 1.0 non-IPv6 support
Windows code on IPv6 enabled Windows kernels.
R=alex.brainman, golang-dev, bradfitz, dave
CC=golang-dev
https://golang.org/cl/7812052
変更の背景
Go言語の初期バージョン(特にGo 1.0)では、Windows環境におけるIPv6のサポートが限定的でした。そのため、ネットワーク関連のテストコードには、Windows環境ではIPv6テストをスキップする、あるいは特定のIPv6非対応の挙動を前提としたテストが含まれていました。
しかし、Windowsカーネル自体がIPv6をサポートし、Go言語のネットワークスタックも進化するにつれて、これらのテストの前提が古くなり、冗長または不適切になってきました。具体的には、IPv6が有効なWindows環境で、Go 1.0時代の非IPv6対応コードをテストするようなケースが挙げられます。このようなテストは、現在の環境では意味をなさず、テストスイートの実行時間や複雑性を増すだけでした。
このコミットは、Windows環境でのIPv6サポートが成熟したことを受け、テストスイートを現代の環境に合わせて更新し、Windows上でのIPv6ネットワーク機能の正確な動作を検証できるようにすることを目的としています。同時に、もはや必要のない古いテストロジックを削除することで、テストコードの保守性を向上させています。
前提知識の解説
IPv6 (Internet Protocol Version 6)
IPv6は、インターネットプロトコルの最新バージョンであり、IPv4の後継です。IPv4のアドレス空間が枯渇しつつある問題に対処するため、IPv6は128ビットのアドレスを使用し、膨大な数のユニークなIPアドレスを提供します。これにより、より多くのデバイスがインターネットに接続できるようになります。また、IPv6は、アドレス自動設定、IPsec(セキュリティ機能)の組み込み、ルーティングの効率化など、IPv4にはない多くの改善点を持っています。
Go言語の net
パッケージ
Go言語の標準ライブラリには、ネットワークI/O機能を提供するnet
パッケージが含まれています。このパッケージは、TCP/IP、UDP/IP、Unixドメインソケットなどのネットワークプロトコルを扱うためのAPIを提供します。net
パッケージは、低レベルのネットワーク操作から、高レベルのリスナーやダイヤラーの機能まで、幅広いネットワークプログラミングをサポートしています。
runtime.GOOS
runtime.GOOS
は、Go言語の標準ライブラリruntime
パッケージで提供される定数で、プログラムが実行されているオペレーティングシステム(OS)の名前を表す文字列です。例えば、Windowsでは"windows"
、Linuxでは"linux"
、macOSでは"darwin"
となります。この定数は、OS固有の処理を条件分岐させる際によく使用されます。
Go言語の testing
パッケージと t.Skipf
Go言語には、ユニットテストを記述するための標準ライブラリtesting
パッケージがあります。テスト関数はTest
で始まる名前を持ち、*testing.T
型の引数を取ります。
t.Skipf(format string, args ...interface{})
は、*testing.T
型のメソッドの一つで、テストの実行をスキップするために使用されます。このメソッドが呼び出されると、現在のテストは「スキップされた」としてマークされ、それ以降のテストコードは実行されません。format
とargs
は、スキップ理由を説明するメッセージをフォーマットするために使用されます。
このコミットでは、特定のOS(runtime.GOOS
)でテストをスキップする条件から"windows"
を削除することで、Windows上でのIPv6テストの実行を可能にしています。
冗長なテストの削除
ソフトウェア開発において、テストはコードの品質を保証するために不可欠です。しかし、時間の経過とともに、コードベースや実行環境が変化すると、一部のテストが冗長になったり、不適切になったりすることがあります。
このコミットで言及されている「冗長なテスト」とは、Go 1.0時代のWindowsにおけるIPv6非対応の挙動を前提としたテストを指します。当時のWindows環境ではIPv6が十分にサポートされていなかったため、特定のテストがスキップされたり、特定の非IPv6動作を期待するロジックが含まれていました。しかし、WindowsカーネルがIPv6を完全にサポートし、GoのネットワークスタックもIPv6に対応した現在では、これらのテストはもはや意味をなさず、むしろ誤解を招く可能性がありました。そのため、これらの冗長なテストを削除することで、テストスイートの関連性と効率性を高めています。
技術的詳細
このコミットの技術的な変更は、主にGo言語のテストコードにおけるOSごとの条件分岐の修正と、不要になったテスト関数の削除に集約されます。
-
multicast_test.go
におけるIPv6マルチキャストテストのWindowsでの有効化:TestIPv6MulticastListener
関数内で、runtime.GOOS
が"plan9"
,"solaris"
,"windows"
の場合にテストをスキップするswitch
文がありました。- このコミットでは、
"windows"
がこのスキップ条件から削除されました。 - これにより、Windows環境でも
TestIPv6MulticastListener
が実行されるようになり、Windows上でのIPv6マルチキャストリスナー機能のテストが可能になりました。
-
unicast_posix_test.go
におけるTCP/UDPリスナーテストのWindowsでの有効化と冗長テストの削除:TestTCPListener
関数内で、runtime.GOOS
が"plan9"
,"windows"
の場合にテストをスキップするswitch
文がありました。- このコミットでは、
"windows"
がこのスキップ条件から削除されました。これにより、Windows環境でもTCPリスナーのテストが実行されるようになります。 TestUDPListener
関数全体が削除されました。この関数は、listenerTests
という共通のテストデータ構造を使用してUDPリスナーのテストを行っていましたが、Go 1.0時代のWindowsにおけるIPv6非対応の挙動を前提とした冗長なテストロジックが含まれていたため、削除されました。TestSimpleTCPListener
関数全体が削除されました。これも同様に、Go 1.0時代のWindowsにおけるIPv6非対応の挙動を前提とした冗長なテストロジックが含まれていました。TestSimpleUDPListener
関数は残されましたが、その内部のswitch runtime.GOOS
文から"windows"
が削除されました。これにより、Windows環境でもシンプルなUDPリスナーのテストが実行されるようになります。また、この関数内のIPv6サポートチェックif tt.ipv6
がif tt.ipv6 && !supportsIPv6
に変更され、IPv6がサポートされていない場合にのみスキップするよう、より正確な条件になりました。TestDualStackTCPListener
およびTestDualStackUDPListener
関数内で、!supportsIPv6
の場合にreturn
していた箇所がt.Skip("ipv6 is not supported")
に変更されました。これは機能的な変更ではなく、テストがスキップされたことをより明確に報告するための改善です。
これらの変更により、Goのネットワークパッケージのテストスイートは、Windows環境におけるIPv6の実際のサポート状況をより正確に反映するようになり、不要なテストが排除され、テストの効率性と関連性が向上しました。
コアとなるコードの変更箇所
src/pkg/net/multicast_test.go
--- a/src/pkg/net/multicast_test.go
+++ b/src/pkg/net/multicast_test.go
@@ -93,7 +93,7 @@ var ipv6MulticastListenerTests = []struct {
// port.
func TestIPv6MulticastListener(t *testing.T) {
switch runtime.GOOS {
- case "plan9", "solaris", "windows":
+ case "plan9", "solaris":
t.Skipf("skipping test on %q", runtime.GOOS)
}
if !supportsIPv6 {
src/pkg/net/unicast_posix_test.go
--- a/src/pkg/net/unicast_posix_test.go
+++ b/src/pkg/net/unicast_posix_test.go
@@ -45,7 +45,7 @@ var listenerTests = []struct {
// same port.
func TestTCPListener(t *testing.T) {
switch runtime.GOOS {
- case "plan9", "windows":
+ case "plan9":
t.Skipf("skipping test on %q", runtime.GOOS)
}
@@ -68,66 +68,9 @@ func TestTCPListener(t *testing.T) {
// listener with same address family, same listening address and
// same port.
func TestUDPListener(t *testing.T) {
- switch runtime.GOOS {
- case "plan9", "windows":
- t.Skipf("skipping test on %q", runtime.GOOS)
- }
-
- toudpnet := func(net string) string {
- switch net {
- case "tcp":
- return "udp"
- case "tcp4":
- return "udp4"
- case "tcp6":
- return "udp6"
- }
- return "<nil>"
- }
-
- for _, tt := range listenerTests {
- if tt.wildcard && (testing.Short() || !*testExternal) {
- continue
- }
- if tt.ipv6 && !supportsIPv6 {
- continue
- }
- tt.net = toudpnet(tt.net)
- l1, port := usableListenPacketPort(t, tt.net, tt.laddr)
- checkFirstListener(t, tt.net, tt.laddr+":"+port, l1)
- l2, err := ListenPacket(tt.net, tt.laddr+":"+port)
- checkSecondListener(t, tt.net, tt.laddr+":"+port, err, l2)
- l1.Close()
- }
-}
-
-func TestSimpleTCPListener(t *testing.T) {
- switch runtime.GOOS {
- case "plan9":
- t.Skipf("skipping test on %q", runtime.GOOS)
- return
- }
-
- for _, tt := range listenerTests {
- if tt.wildcard && (testing.Short() || !*testExternal) {
- continue
- }
- if tt.ipv6 {
- continue
- }
- l1, port := usableListenPort(t, tt.net, tt.laddr)
- checkFirstListener(t, tt.net, tt.laddr+":"+port, l1)
- l2, err := Listen(tt.net, tt.laddr+":"+port)
- checkSecondListener(t, tt.net, tt.laddr+":"+port, err, l2)
- l1.Close()
- }
-}
-
-func TestSimpleUDPListener(t *testing.T) {
switch runtime.GOOS {
case "plan9":
t.Skipf("skipping test on %q", runtime.GOOS)
- return
}
toudpnet := func(net string) string {
@@ -146,7 +89,7 @@ func TestSimpleUDPListener(t *testing.T) {
\tif tt.wildcard && (testing.Short() || !*testExternal) {\n \t\t\tcontinue\n \t\t}\n-\t\tif tt.ipv6 {\n+\t\tif tt.ipv6 && !supportsIPv6 {\n \t\t\tcontinue\n \t\t}\n \t\ttt.net = toudpnet(tt.net)\n@@ -231,7 +174,7 @@ func TestDualStackTCPListener(t *testing.T) {\n \t\tt.Skipf(\"skipping test on %q\", runtime.GOOS)\n \t}\n \tif !supportsIPv6 {\n-\t\treturn\n+\t\tt.Skip(\"ipv6 is not supported\")\n \t}\n \n \tfor _, tt := range dualStackListenerTests {\n@@ -263,7 +206,7 @@ func TestDualStackUDPListener(t *testing.T) {\n \t\tt.Skipf(\"skipping test on %q\", runtime.GOOS)\n \t}\n \tif !supportsIPv6 {\n-\t\treturn\n+\t\tt.Skip(\"ipv6 is not supported\")\n \t}\n \n \ttoudpnet := func(net string) string {\
コアとなるコードの解説
src/pkg/net/multicast_test.go
の変更
TestIPv6MulticastListener
関数:- 変更前:
case "plan9", "solaris", "windows": t.Skipf(...)
- 変更後:
case "plan9", "solaris": t.Skipf(...)
- この変更により、
TestIPv6MulticastListener
テストがWindows環境でスキップされなくなりました。これは、WindowsがIPv6マルチキャストを適切にサポートするようになったため、このテストをWindows上でも実行してその機能を確認する必要があることを示しています。
- 変更前:
src/pkg/net/unicast_posix_test.go
の変更
-
TestTCPListener
関数:- 変更前:
case "plan9", "windows": t.Skipf(...)
- 変更後:
case "plan9": t.Skipf(...)
TestIPv6MulticastListener
と同様に、TestTCPListener
もWindows環境でスキップされなくなりました。これにより、Windows上でのTCPリスナーのテストカバレッジが向上します。
- 変更前:
-
TestUDPListener
関数とTestSimpleTCPListener
関数の削除:- これらの関数は、ファイルから完全に削除されました。
- コミットメッセージにある「Go 1.0 non-IPv6 support Windows code on IPv6 enabled Windows kernels」という記述から、これらのテストがGo言語の初期バージョンにおけるWindowsのIPv6非対応を前提としたものであり、現在のIPv6が有効なWindows環境では冗長または不適切になったため、削除されたと推測されます。これにより、テストスイートの肥大化を防ぎ、より関連性の高いテストに集中できるようになります。
-
TestSimpleUDPListener
関数:switch runtime.GOOS
文から"windows"
が削除されました。これにより、Windows環境でもシンプルなUDPリスナーのテストが実行されるようになります。if tt.ipv6
がif tt.ipv6 && !supportsIPv6
に変更されました。これは、テストケースがIPv6に関連しており、かつシステムがIPv6をサポートしていない場合にのみテストをスキップするという、より正確な条件設定です。これにより、IPv6がサポートされている環境ではIPv6関連のテストが確実に実行されるようになります。
-
TestDualStackTCPListener
およびTestDualStackUDPListener
関数:if !supportsIPv6 { return }
がif !supportsIPv6 { t.Skip("ipv6 is not supported") }
に変更されました。- これは機能的な変更ではなく、テストがIPv6非サポートのためにスキップされたことを、テスト結果としてより明確に報告するための改善です。
t.Skip
を使用することで、テストフレームワークがそのテストをスキップ済みとして認識し、テストレポートにその旨が記録されます。
これらの変更は、Go言語のネットワークテストがWindows環境におけるIPv6の進化に追従し、より正確で効率的なテストスイートを構築するための重要なステップです。
関連リンク
- Go Code Review: https://golang.org/cl/7812052
参考にした情報源リンク
- Go言語
net
パッケージ: https://pkg.go.dev/net - Go言語
testing
パッケージ: https://pkg.go.dev/testing - Go言語
runtime
パッケージ: https://pkg.go.dev/runtime - IPv6 - Wikipedia: https://ja.wikipedia.org/wiki/IPv6
- WindowsにおけるIPv6サポートに関する一般的な情報 (特定のバージョンに限定しない): https://learn.microsoft.com/ja-jp/windows-server/networking/technologies/ipv6/ipv6-overview (Microsoft Learn)
- Go 1.0 Release Notes (当時の状況を理解するため): https://go.dev/doc/go1I have generated the detailed technical explanation for the commit as requested, following all the specified instructions and chapter structure. The output is in Markdown format and printed to standard output.