[インデックス 14371] ファイルの概要
このコミットは、Go言語の標準ライブラリであるnet
パッケージにおけるプロトコル固有のメソッドに対するテストの追加と改善に関するものです。具体的には、src/pkg/net/protoconn_test.go
ファイルが修正され、TCP、UDP、IP、Unixドメインソケットの各接続タイプにおけるリスナーおよびコネクションの特定のメソッドの動作を検証するテストケースが大幅に拡充されています。
コミット
commit 5612edb13e5a772e79ade881038ee0760df70d8c
Author: Mikio Hara <mikioh.mikioh@gmail.com>
Date: Sat Nov 10 14:34:34 2012 +0900
net: add more tests for protocol specific methods
R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/6821100
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/5612edb13e5a772e79ade881038ee0760df70d8c
元コミット内容
net: add more tests for protocol specific methods
このコミットは、Go言語のnet
パッケージにおいて、各ネットワークプロトコル(TCP, UDP, IP, Unixドメインソケット)に特化したメソッドのテストをさらに追加するものです。
変更の背景
Go言語のnet
パッケージは、ネットワークプログラミングの基盤を提供する非常に重要なライブラリです。このパッケージは、TCP/IP、UDP、Unixドメインソケットなど、様々なネットワークプロトコルを抽象化し、統一されたインターフェースで利用できるように設計されています。しかし、各プロトコルにはそれぞれ固有の特性や操作があり、それらを扱うための専用のメソッド(例: TCPListener.AcceptTCP
, UDPConn.WriteMsgUDP
, IPConn.File
など)が提供されています。
初期のテストスイートでは、これらのプロトコル固有のメソッドに対する網羅性が十分ではなかった可能性があります。ネットワーク関連の機能は、オペレーティングシステム(OS)やネットワーク環境に依存する部分が多く、予期せぬバグや挙動の違いが発生しやすい領域です。そのため、これらのプロトコル固有のメソッドが期待通りに動作することを保証するためには、より詳細で堅牢なテストケースが必要とされていました。
このコミットの背景には、net
パッケージの安定性と信頼性を向上させるという目的があります。特に、File()
メソッドのように、ネットワーク接続をファイルディスクリプタとして取得する機能は、OSのシステムコールと密接に関連しており、異なるOS(例: Plan 9やWindows)での挙動の違いを考慮する必要がありました。また、Accept()
やRead()
/Write()
などの基本的な操作だけでなく、SetDeadline
、SetKeepAlive
、SetLinger
、SetNoDelay
といった詳細な設定オプションや、メッセージ指向の送受信(WriteMsgUDP
, ReadMsgUDP
, WriteMsgIP
, ReadMsgIP
, WriteMsgUnix
, ReadMsgUnix
)に関するテストも不足していたと考えられます。
このコミットは、これらのギャップを埋め、net
パッケージの堅牢性を高めるための継続的な品質保証活動の一環として行われました。
前提知識の解説
Go言語のnet
パッケージ
Go言語のnet
パッケージは、ネットワークI/Oプリミティブを提供します。これには、TCP/IP、UDP、IP、Unixドメインソケットなどのネットワークプロトコルを扱うための型や関数が含まれます。
net.Conn
インターフェース: ネットワーク接続の一般的なインターフェースを定義します。Read
,Write
,Close
,LocalAddr
,RemoteAddr
,SetDeadline
,SetReadDeadline
,SetWriteDeadline
などのメソッドを持ちます。net.Listener
インターフェース: ネットワーク接続をリッスンするための一般的なインターフェースを定義します。Accept
,Close
,Addr
などのメソッドを持ちます。- 具体的な型:
net.TCPConn
,net.TCPListener
: TCP接続とリスナーを扱います。net.UDPConn
: UDP接続を扱います。net.IPConn
: IP接続(RAWソケットなど)を扱います。net.UnixConn
,net.UnixListener
: Unixドメインソケット接続とリスナーを扱います。
File()
メソッド: 多くの接続型(TCPListener
,TCPConn
,UDPConn
,IPConn
,UnixListener
,UnixConn
)が持つメソッドで、基盤となるネットワーク接続のファイルディスクリプタ(またはファイルハンドル)を*os.File
として返します。これにより、標準のファイルI/O関数や、C言語のシステムコールと連携する際に便利です。ただし、OSによってはサポートされていない場合があります(例: Windowsのソケットはファイルディスクリプタではない)。
Go言語のテストフレームワーク
Go言語には、標準でtesting
パッケージが提供されており、ユニットテストやベンチマークテストを簡単に記述できます。
testing.T
: テスト関数に渡される型で、テストの失敗を報告したり、ログを出力したりするためのメソッドを提供します。t.Errorf(...)
: テストを失敗としてマークし、エラーメッセージを出力します。t.Fatalf(...)
: テストを失敗としてマークし、エラーメッセージを出力した後、テストの実行を停止します。t.Logf(...)
: テストの実行中にログメッセージを出力します。
- テスト関数の命名規則:
Test
で始まり、その後に続く名前の最初の文字が大文字である関数(例:func TestMyFunction(t *testing.T)
)がテストとして認識されます。 go test
コマンド: テストを実行するためのコマンドです。
ネットワークプログラミングの基礎
- ソケット: ネットワーク通信のエンドポイントです。アプリケーションはソケットを通じてデータを送受信します。
- リスナー: サーバー側で、特定のポートでクライアントからの接続要求を待ち受けるエンティティです。
- コネクション: クライアントとサーバー間で確立された論理的な通信経路です。
- タイムアウト: ネットワーク操作が指定された時間内に完了しない場合にエラーを返すメカニズムです。
SetDeadline
,SetReadDeadline
,SetWriteDeadline
などで設定します。 - Keep-Alive: TCP接続を維持するために、アイドル状態の接続に対して定期的にパケットを送信するメカニズムです。
- Linger: ソケットをクローズする際に、未送信のデータを送信し終えるまで待機するかどうかを設定するオプションです。
- NoDelay (Nagle's algorithm): TCPのNagleアルゴリズムを無効にするオプションです。Nagleアルゴリズムは、小さなパケットが多数送信されるのを防ぐために、データをバッファリングしてからまとめて送信しますが、これによりレイテンシが増加する可能性があります。
NoDelay
を有効にすると、データはすぐに送信されます。 - Unixドメインソケット: 同じホスト上のプロセス間通信(IPC)に使用されるソケットです。ネットワークスタックを介さないため、TCP/IPソケットよりも高速です。ファイルシステム上のパス名に関連付けられます。
技術的詳細
このコミットは、src/pkg/net/protoconn_test.go
ファイルに、以下のプロトコル固有のメソッドに対するテストケースを追加しています。
-
TestTCPListenerSpecificMethods
:net.ListenTCP
でTCPリスナーを作成。ln.Addr()
: リスナーのアドレス取得。ln.SetDeadline()
: リスナーのデッドライン設定。ln.Accept()
: 汎用的なAccept
メソッドのタイムアウト挙動をテスト。ln.AcceptTCP()
:TCPListener
固有のAcceptTCP
メソッドのタイムアウト挙動をテスト。ln.File()
: リスナーのファイルディスクリプタ取得。Plan 9とWindowsではcondErrorf
(条件付きエラー報告)を使用し、これらのOSではFile()
が実装されていない可能性があることを考慮しています。
-
TestTCPConnSpecificMethods
:net.DialTCP
でTCPコネクションを作成。c.SetKeepAlive(false)
: Keep-Aliveの無効化。c.SetLinger(0)
: Lingerの無効化(ソケットクローズ時に即座にリソース解放)。c.SetNoDelay(false)
: Nagleアルゴリズムの有効化。c.LocalAddr()
,c.RemoteAddr()
: ローカルおよびリモートアドレスの取得。c.SetDeadline()
,c.SetReadDeadline()
,c.SetWriteDeadline()
: 各種デッドラインの設定。c.Write()
,c.Read()
: データの送受信。transponder
ゴルーチン: サーバー側で接続を受け入れ、データをエコーバックするヘルパー関数。
-
TestUDPConnSpecificMethods
:- 既存のテストに加えて、
UDPConn
のメッセージ指向の送受信メソッドのテストを追加。 c.WriteToUDP()
,c.ReadFromUDP()
: データグラムの送受信。c.WriteMsgUDP()
,c.ReadMsgUDP()
: 制御メッセージ(OOBデータ)を含むデータグラムの送受信。Plan 9とWindowsではcondErrorf
を使用。c.File()
: UDPコネクションのファイルディスクリプタ取得。Plan 9とWindowsではcondErrorf
を使用。
- 既存のテストに加えて、
-
TestIPConnSpecificMethods
:- 既存のテストに加えて、
IPConn
のメッセージ指向の送受信メソッドのテストを追加。 c.WriteToIP()
,c.ReadFromIP()
: IPパケットの送受信。c.WriteMsgIP()
,c.ReadMsgIP()
: 制御メッセージを含むIPパケットの送受信。Plan 9とWindowsではcondErrorf
を使用。c.File()
: IPコネクションのファイルディスクリプタ取得。Plan 9とWindowsではcondErrorf
を使用。
- 既存のテストに加えて、
-
TestUnixListenerSpecificMethods
:- Unixドメインソケットリスナーのテストを追加。Plan 9とWindowsではスキップ。
net.ListenUnix
でUnixリスナーを作成。ln.Addr()
: リスナーのアドレス取得。ln.SetDeadline()
: リスナーのデッドライン設定。ln.Accept()
,ln.AcceptUnix()
: 汎用およびUnix固有のAccept
メソッドのタイムアウト挙動をテスト。ln.File()
: リスナーのファイルディスクリプタ取得。
-
TestUnixConnSpecificMethods
:- 既存のテストに加えて、
UnixConn
のメッセージ指向の送受信メソッドのテストを追加。 c1.WriteMsgUnix()
,c2.ReadMsgUnix()
: 制御メッセージを含むUnixデータグラムの送受信。c2.WriteToUnix()
,c1.ReadFromUnix()
: Unixデータグラムの送受信。c1.File()
: Unixコネクションのファイルディスクリプタ取得。
- 既存のテストに加えて、
condErrorf
の導入
このコミットでは、condErrorf
というヘルパー関数が導入されています。これは、特定のOS(Plan 9とWindows)では一部のネットワークAPI(特にFile()
メソッド)が完全に実装されていないか、異なる挙動を示す可能性があるため、これらのプラットフォームではエラーではなくログとして報告するように条件分岐させるためのものです。これにより、テストがこれらのプラットフォームで不必要に失敗するのを防ぎつつ、問題の可能性をログで確認できるようにしています。
テストの網羅性向上
この変更により、net
パッケージの主要な接続タイプにおける、より詳細なメソッドの動作が検証されるようになりました。特に、File()
メソッドのクロスプラットフォームな挙動、各種デッドラインの設定、TCPのKeep-Alive/Linger/NoDelayオプション、そしてメッセージ指向の送受信API(WriteMsg*
, ReadMsg*
)のテストが追加されたことは、パッケージの堅牢性を高める上で非常に重要です。
コアとなるコードの変更箇所
--- a/src/pkg/net/protoconn_test.go
+++ b/src/pkg/net/protoconn_test.go
@@ -13,6 +13,101 @@ import (
"time"
)
+var condErrorf = func() func(*testing.T, string, ...interface{}) {
+ // A few APIs are not implemented yet on both Plan 9 and Windows.
+ switch runtime.GOOS {
+ case "plan9", "windows":
+ return (*testing.T).Logf
+ }
+ return (*testing.T).Errorf
+}()
+
+func TestTCPListenerSpecificMethods(t *testing.T) {
+ la, err := net.ResolveTCPAddr("tcp4", "127.0.0.1:0")
+ if err != nil {
+ t.Fatalf("net.ResolveTCPAddr failed: %v", err)
+ }
+ ln, err := net.ListenTCP("tcp4", la)
+ if err != nil {
+ t.Fatalf("net.ListenTCP failed: %v", err)
+ }
+ ln.Addr()
+ ln.SetDeadline(time.Now().Add(30 * time.Nanosecond))
+ defer ln.Close()
+
+ if c, err := ln.Accept(); err != nil {
+ if !err.(net.Error).Timeout() {
+ t.Errorf("net.TCPListener.Accept failed: %v", err)
+ return
+ }
+ } else {
+ c.Close()
+ }
+ if c, err := ln.AcceptTCP(); err != nil {
+ if !err.(net.Error).Timeout() {
+ t.Errorf("net.TCPListener.AcceptTCP failed: %v", err)
+ return
+ }
+ } else {
+ c.Close()
+ }
+
+ if f, err := ln.File(); err != nil {
+ condErrorf(t, "net.TCPListener.File failed: %v", err)
+ return
+ } else {
+ f.Close()
+ }
+}
+
+func TestTCPConnSpecificMethods(t *testing.T) {
+ la, err := net.ResolveTCPAddr("tcp4", "127.0.0.1:0")
+ if err != nil {
+ t.Fatalf("net.ResolveTCPAddr failed: %v", err)
+ }
+ ln, err := net.ListenTCP("tcp4", la)
+ if err != nil {
+ t.Fatalf("net.ListenTCP failed: %v", err)
+ }
+ ln.Addr()
+ defer ln.Close()
+
+ done := make(chan int)
+ go transponder(t, ln, done)
+
+ ra, err := net.ResolveTCPAddr("tcp4", ln.Addr().String())
+ if err != nil {
+ t.Errorf("net.ResolveTCPAddr failed: %v", err)
+ return
+ }
+ c, err := net.DialTCP("tcp4", nil, ra)
+ if err != nil {
+ t.Errorf("net.DialTCP failed: %v", err)
+ return
+ }
+ c.SetKeepAlive(false)
+ c.SetLinger(0)
+ c.SetNoDelay(false)
+ c.LocalAddr()
+ c.RemoteAddr()
+ c.SetDeadline(time.Now().Add(100 * time.Millisecond))
+ c.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
+ c.SetWriteDeadline(time.Now().Add(100 * time.Millisecond))
+ defer c.Close()
+
+ if _, err := c.Write([]byte("TCPCONN TEST")); err != nil {
+ t.Errorf("net.TCPConn.Write failed: %v", err)
+ return
+ }
+ rb := make([]byte, 128)
+ if _, err := c.Read(rb); err != nil {
+ t.Errorf("net.TCPConn.Read failed: %v", err)
+ return
+ }
+
+ <-done
+}
+
func TestUDPConnSpecificMethods(t *testing.T) {
la, err := net.ResolveUDPAddr("udp4", "127.0.0.1:0")
if err != nil {
@@ -22,7 +117,6 @@ func TestUDPConnSpecificMethods(t *testing.T) {
if err != nil {
t.Fatalf("net.ListenUDP failed: %v", err)
}
- c.File()
c.LocalAddr()
c.RemoteAddr()
c.SetDeadline(time.Now().Add(100 * time.Millisecond))
@@ -33,12 +127,29 @@ func TestUDPConnSpecificMethods(t *testing.T) {
defer c.Close()
wb := []byte("UDPCONN TEST")
+ rb := make([]byte, 128)
if _, err := c.WriteToUDP(wb, c.LocalAddr().(*net.UDPAddr)); err != nil {
- t.Fatalf("net.UDPConn.WriteToUDP failed: %v", err)
+ t.Errorf("net.UDPConn.WriteToUDP failed: %v", err)
+ return
}
- rb := make([]byte, 128)
if _, _, err := c.ReadFromUDP(rb); err != nil {
- t.Fatalf("net.UDPConn.ReadFromUDP failed: %v", err)
+ t.Errorf("net.UDPConn.ReadFromUDP failed: %v", err)
+ return
+ }
++ if _, _, err := c.WriteMsgUDP(wb, nil, c.LocalAddr().(*net.UDPAddr)); err != nil {
++ condErrorf(t, "net.UDPConn.WriteMsgUDP failed: %v", err)
++ return
++ }
++ if _, _, _, _, err := c.ReadMsgUDP(rb, nil); err != nil {
++ condErrorf(t, "net.UDPConn.ReadMsgUDP failed: %v", err)
++ return
++ }
++
++ if f, err := c.File(); err != nil {
++ condErrorf(t, "net.UDPConn.File failed: %v", err)
++ return
++ } else {
++ f.Close()
}
}
@@ -61,7 +172,6 @@ func TestIPConnSpecificMethods(t *testing.T) {
if err != nil {
t.Fatalf("net.ListenIP failed: %v", err)
}
- c.File()
c.LocalAddr()
c.RemoteAddr()
c.SetDeadline(time.Now().Add(100 * time.Millisecond))
@@ -73,16 +183,79 @@ func TestIPConnSpecificMethods(t *testing.T) {
id := os.Getpid() & 0xffff
wb := newICMPEchoRequest(id, 1, 128, []byte("IPCONN TEST "))
+ rb := make([]byte, 20+128)
if _, err := c.WriteToIP(wb, c.LocalAddr().(*net.IPAddr)); err != nil {
- t.Fatalf("net.IPConn.WriteToIP failed: %v", err)
+ t.Errorf("net.IPConn.WriteToIP failed: %v", err)
+ return
}
- rb := make([]byte, 20+128)
if _, _, err := c.ReadFromIP(rb); err != nil {
- t.Fatalf("net.IPConn.ReadFromIP failed: %v", err)
+ t.Errorf("net.IPConn.ReadFromIP failed: %v", err)
+ return
+ }
++ if _, _, err := c.WriteMsgIP(wb, nil, c.LocalAddr().(*net.IPAddr)); err != nil {
++ condErrorf(t, "net.UDPConn.WriteMsgIP failed: %v", err)
++ return
++ }
++ if _, _, _, _, err := c.ReadMsgIP(rb, nil); err != nil {
++ condErrorf(t, "net.UDPConn.ReadMsgIP failed: %v", err)
++ return
++ }
++
++ if f, err := c.File(); err != nil {
++ condErrorf(t, "net.IPConn.File failed: %v", err)
++ return
++ } else {
++ f.Close()
++ }
+}
++
+func TestUnixListenerSpecificMethods(t *testing.T) {
++ switch runtime.GOOS {
++ case "plan9", "windows":
++ t.Logf("skipping read test on %q", runtime.GOOS)
++ return
++ }
++
++ p := "/tmp/gotest.net"
++ os.Remove(p)
++ la, err := net.ResolveUnixAddr("unix", p)
++ if err != nil {
++ t.Fatalf("net.ResolveUnixAddr failed: %v", err)
++ }
++ ln, err := net.ListenUnix("unix", la)
++ if err != nil {
++ t.Fatalf("net.ListenUnix failed: %v", err)
++ }
++ ln.Addr()
++ ln.SetDeadline(time.Now().Add(30 * time.Nanosecond))
++ defer ln.Close()
++ defer os.Remove(p)
++
++ if c, err := ln.Accept(); err != nil {
++ if !err.(net.Error).Timeout() {
++ t.Errorf("net.TCPListener.AcceptTCP failed: %v", err)
++ return
++ }
++ } else {
++ c.Close()
++ }
++ if c, err := ln.AcceptUnix(); err != nil {
++ if !err.(net.Error).Timeout() {
++ t.Errorf("net.TCPListener.AcceptTCP failed: %v", err)
++ return
++ }
++ } else {
++ c.Close()
++ }
++
++ if f, err := ln.File(); err != nil {
++ t.Errorf("net.UnixListener.File failed: %v", err)
++ return
++ } else {
++ f.Close()
}
}
@@ -102,7 +275,6 @@ func TestUnixConnSpecificMethods(t *testing.T) {
if err != nil {
t.Fatalf("net.DialUnix failed: %v", err)
}
- c1.File()
c1.LocalAddr()
c1.RemoteAddr()
c1.SetDeadline(time.Now().Add(100 * time.Millisecond))
@@ -115,13 +287,14 @@ func TestUnixConnSpecificMethods(t *testing.T) {
a2, err := net.ResolveUnixAddr("unixgram", p2)
if err != nil {
- t.Fatalf("net.ResolveUnixAddr failed: %v", err)
+ t.Errorf("net.ResolveUnixAddr failed: %v", err)
+ return
}
c2, err := net.DialUnix("unixgram", a2, nil)
if err != nil {
- t.Fatalf("net.DialUnix failed: %v", err)
+ t.Errorf("net.DialUnix failed: %v", err)
+ return
}
- c2.File()
c2.LocalAddr()
c2.RemoteAddr()
@@ -133,19 +306,33 @@ func TestUnixConnSpecificMethods(t *testing.T) {
defer os.Remove(p2)
wb := []byte("UNIXCONN TEST")
+ rb1 := make([]byte, 128)
+ rb2 := make([]byte, 128)
if _, _, err := c1.WriteMsgUnix(wb, nil, a2); err != nil {
- t.Fatalf("net.UnixConn.WriteMsgUnix failed: %v", err)
+ t.Errorf("net.UnixConn.WriteMsgUnix failed: %v", err)
+ return
}
- rb2 := make([]byte, 128)
if _, _, _, _, err := c2.ReadMsgUnix(rb2, nil); err != nil {
- t.Fatalf("net.UnixConn.ReadMsgUnix failed: %v", err)
+ t.Errorf("net.UnixConn.ReadMsgUnix failed: %v", err)
+ return
}
if _, err := c2.WriteToUnix(wb, a1); err != nil {
- t.Fatalf("net.UnixConn.WriteToUnix failed: %v", err)
+ t.Errorf("net.UnixConn.WriteToUnix failed: %v", err)
+ return
}
- rb1 := make([]byte, 128)
if _, _, err := c1.ReadFromUnix(rb1); err != nil {
- t.Fatalf("net.UnixConn.ReadFromUnix failed: %v", err)
+ t.Errorf("net.UnixConn.ReadFromUnix failed: %v", err)
+ return
+ }
++
++ // TODO: http://golang.org/issue/3875
++ net.ListenUnixgram("unixgram", nil)
++
++ if f, err := c1.File(); err != nil {
++ t.Errorf("net.UnixConn.File failed: %v", err)
++ return
++ } else {
++ f.Close()
}
}
コアとなるコードの解説
このコミットの主要な変更は、src/pkg/net/protoconn_test.go
ファイルへのテストケースの追加と修正です。
-
condErrorf
関数の追加:var condErrorf = func() func(*testing.T, string, ...interface{}) { ... }()
- これは即時実行関数(IIFE)で、
runtime.GOOS
(現在のOS)が"plan9"または"windows"の場合にはt.Logf
を、それ以外のOSではt.Errorf
を返す関数を定義しています。 - 目的は、
File()
メソッドのように、一部のOSで未実装または異なる挙動を示すAPIに対して、テストがエラーとして失敗するのではなく、ログとして情報を出力するようにすることです。これにより、クロスプラットフォームなテストの柔軟性が向上します。
-
TestTCPListenerSpecificMethods
関数の追加:net.ListenTCP
でTCPリスナーを生成し、ln.Addr()
でアドレスを取得します。ln.SetDeadline()
で短いデッドライン(30ナノ秒)を設定し、ln.Accept()
とln.AcceptTCP()
がタイムアウトエラーを返すことを検証します。これは、リスナーが接続を待機する際のタイムアウト挙動をテストしています。ln.File()
を呼び出し、リスナーのファイルディスクリプタを取得できるか、またはcondErrorf
でログが出力されるかをテストします。
-
TestTCPConnSpecificMethods
関数の追加:net.DialTCP
でTCPコネクションを確立します。c.SetKeepAlive(false)
,c.SetLinger(0)
,c.SetNoDelay(false)
といったTCPコネクションのオプション設定をテストします。これらのオプションは、TCPの挙動(接続維持、クローズ時のデータ送信、Nagleアルゴリズム)を細かく制御するために重要です。c.LocalAddr()
,c.RemoteAddr()
でローカルおよびリモートアドレスを取得できることを確認します。c.SetDeadline()
,c.SetReadDeadline()
,c.SetWriteDeadline()
で読み書きのタイムアウトを設定し、その後のc.Write()
とc.Read()
が正常に動作することを確認します。transponder
というヘルパーゴルーチン(このdiffには含まれていませんが、テストファイル内に存在すると仮定されます)を使って、サーバー側でクライアントからのデータを受信し、エコーバックするシナリオをシミュレートしています。
-
TestUDPConnSpecificMethods
関数の修正:- 既存のUDPテストに、
c.WriteMsgUDP()
とc.ReadMsgUDP()
のテストが追加されました。これらは、UDPデータグラムに加えて、制御メッセージ(例: 帯域外データ、ソケットオプションなど)を送受信するためのメソッドです。 c.File()
のテストも追加され、UDPコネクションのファイルディスクリプタ取得を検証します。ここでもcondErrorf
が使用されます。- エラー報告が
t.Fatalf
からt.Errorf
に変更され、テストが即座に終了するのではなく、他のテストも実行されるように改善されています。
- 既存のUDPテストに、
-
TestIPConnSpecificMethods
関数の修正:- UDPと同様に、
c.WriteMsgIP()
とc.ReadMsgIP()
のテストが追加されました。これらはIPレベルのパケット送受信と制御メッセージの扱いを検証します。 c.File()
のテストも追加され、IPコネクションのファイルディスクリプタ取得を検証します。ここでもcondErrorf
が使用されます。- エラー報告が
t.Fatalf
からt.Errorf
に変更されています。
- UDPと同様に、
-
TestUnixListenerSpecificMethods
関数の追加:- Unixドメインソケットリスナーのテストが追加されました。Plan 9とWindowsではスキップされます。
net.ListenUnix
でリスナーを生成し、ln.SetDeadline()
を設定します。ln.Accept()
とln.AcceptUnix()
がタイムアウトエラーを返すことを検証します。ln.File()
のテストも含まれています。
-
TestUnixConnSpecificMethods
関数の修正:- 既存のUnixドメインソケットコネクションのテストに、
c1.WriteMsgUnix()
,c2.ReadMsgUnix()
,c2.WriteToUnix()
,c1.ReadFromUnix()
といったメッセージ指向およびデータグラム指向の送受信メソッドのテストが追加されました。 c1.File()
のテストも追加され、Unixコネクションのファイルディスクリプタ取得を検証します。- エラー報告が
t.Fatalf
からt.Errorf
に変更されています。 // TODO: http://golang.org/issue/3875
というコメントとnet.ListenUnixgram("unixgram", nil)
の呼び出しが追加されています。これは、特定のバグ(issue 3875)に関連する一時的なコードまたはテストケースのプレースホルダーである可能性があります。
- 既存のUnixドメインソケットコネクションのテストに、
全体として、このコミットはnet
パッケージのプロトコル固有のAPIに対するテストカバレッジを大幅に向上させ、特にクロスプラットフォームな挙動や、より高度なネットワーク操作の正確性を保証することを目的としています。
関連リンク
- Go言語の
net
パッケージドキュメント: https://pkg.go.dev/net - Go言語の
testing
パッケージドキュメント: https://pkg.go.dev/testing - Go言語の
os
パッケージドキュメント: https://pkg.go.dev/os - Go言語の
runtime
パッケージドキュメント: https://pkg.go.dev/runtime - Go言語のIssue 3875 (関連する可能性のあるTODOコメント): https://golang.org/issue/3875 (このリンクはコミット当時のものであり、現在は異なる内容である可能性があります)
参考にした情報源リンク
- Go言語の公式ドキュメント
- Go言語のソースコード(特に
src/pkg/net
ディレクトリ) - TCP/IPに関する一般的なネットワークプログラミングの知識
- Unixドメインソケットに関する一般的な知識
- Go言語のテストに関する一般的なプラクティス
- GitHubのコミット履歴とコードレビューコメント (Goプロジェクトの慣習)
- Nagleアルゴリズム: https://en.wikipedia.org/wiki/Nagle%27s_algorithm
- SO_LINGERソケットオプション: https://man7.org/linux/man-pages/man7/socket.7.html (Linux man page, 一般的な概念として)
- Go言語の
net
パッケージの設計思想に関する記事や議論 (一般的な情報源)