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

[インデックス 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()などの基本的な操作だけでなく、SetDeadlineSetKeepAliveSetLingerSetNoDelayといった詳細な設定オプションや、メッセージ指向の送受信(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ファイルに、以下のプロトコル固有のメソッドに対するテストケースを追加しています。

  1. TestTCPListenerSpecificMethods:

    • net.ListenTCPでTCPリスナーを作成。
    • ln.Addr(): リスナーのアドレス取得。
    • ln.SetDeadline(): リスナーのデッドライン設定。
    • ln.Accept(): 汎用的なAcceptメソッドのタイムアウト挙動をテスト。
    • ln.AcceptTCP(): TCPListener固有のAcceptTCPメソッドのタイムアウト挙動をテスト。
    • ln.File(): リスナーのファイルディスクリプタ取得。Plan 9とWindowsではcondErrorf(条件付きエラー報告)を使用し、これらのOSではFile()が実装されていない可能性があることを考慮しています。
  2. 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ゴルーチン: サーバー側で接続を受け入れ、データをエコーバックするヘルパー関数。
  3. TestUDPConnSpecificMethods:

    • 既存のテストに加えて、UDPConnのメッセージ指向の送受信メソッドのテストを追加。
    • c.WriteToUDP(), c.ReadFromUDP(): データグラムの送受信。
    • c.WriteMsgUDP(), c.ReadMsgUDP(): 制御メッセージ(OOBデータ)を含むデータグラムの送受信。Plan 9とWindowsではcondErrorfを使用。
    • c.File(): UDPコネクションのファイルディスクリプタ取得。Plan 9とWindowsではcondErrorfを使用。
  4. TestIPConnSpecificMethods:

    • 既存のテストに加えて、IPConnのメッセージ指向の送受信メソッドのテストを追加。
    • c.WriteToIP(), c.ReadFromIP(): IPパケットの送受信。
    • c.WriteMsgIP(), c.ReadMsgIP(): 制御メッセージを含むIPパケットの送受信。Plan 9とWindowsではcondErrorfを使用。
    • c.File(): IPコネクションのファイルディスクリプタ取得。Plan 9とWindowsではcondErrorfを使用。
  5. TestUnixListenerSpecificMethods:

    • Unixドメインソケットリスナーのテストを追加。Plan 9とWindowsではスキップ。
    • net.ListenUnixでUnixリスナーを作成。
    • ln.Addr(): リスナーのアドレス取得。
    • ln.SetDeadline(): リスナーのデッドライン設定。
    • ln.Accept(), ln.AcceptUnix(): 汎用およびUnix固有のAcceptメソッドのタイムアウト挙動をテスト。
    • ln.File(): リスナーのファイルディスクリプタ取得。
  6. 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ファイルへのテストケースの追加と修正です。

  1. condErrorf関数の追加:

    • var condErrorf = func() func(*testing.T, string, ...interface{}) { ... }()
    • これは即時実行関数(IIFE)で、runtime.GOOS(現在のOS)が"plan9"または"windows"の場合にはt.Logfを、それ以外のOSではt.Errorfを返す関数を定義しています。
    • 目的は、File()メソッドのように、一部のOSで未実装または異なる挙動を示すAPIに対して、テストがエラーとして失敗するのではなく、ログとして情報を出力するようにすることです。これにより、クロスプラットフォームなテストの柔軟性が向上します。
  2. TestTCPListenerSpecificMethods関数の追加:

    • net.ListenTCPでTCPリスナーを生成し、ln.Addr()でアドレスを取得します。
    • ln.SetDeadline()で短いデッドライン(30ナノ秒)を設定し、ln.Accept()ln.AcceptTCP()がタイムアウトエラーを返すことを検証します。これは、リスナーが接続を待機する際のタイムアウト挙動をテストしています。
    • ln.File()を呼び出し、リスナーのファイルディスクリプタを取得できるか、またはcondErrorfでログが出力されるかをテストします。
  3. 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には含まれていませんが、テストファイル内に存在すると仮定されます)を使って、サーバー側でクライアントからのデータを受信し、エコーバックするシナリオをシミュレートしています。
  4. TestUDPConnSpecificMethods関数の修正:

    • 既存のUDPテストに、c.WriteMsgUDP()c.ReadMsgUDP()のテストが追加されました。これらは、UDPデータグラムに加えて、制御メッセージ(例: 帯域外データ、ソケットオプションなど)を送受信するためのメソッドです。
    • c.File()のテストも追加され、UDPコネクションのファイルディスクリプタ取得を検証します。ここでもcondErrorfが使用されます。
    • エラー報告がt.Fatalfからt.Errorfに変更され、テストが即座に終了するのではなく、他のテストも実行されるように改善されています。
  5. TestIPConnSpecificMethods関数の修正:

    • UDPと同様に、c.WriteMsgIP()c.ReadMsgIP()のテストが追加されました。これらはIPレベルのパケット送受信と制御メッセージの扱いを検証します。
    • c.File()のテストも追加され、IPコネクションのファイルディスクリプタ取得を検証します。ここでもcondErrorfが使用されます。
    • エラー報告がt.Fatalfからt.Errorfに変更されています。
  6. TestUnixListenerSpecificMethods関数の追加:

    • Unixドメインソケットリスナーのテストが追加されました。Plan 9とWindowsではスキップされます。
    • net.ListenUnixでリスナーを生成し、ln.SetDeadline()を設定します。
    • ln.Accept()ln.AcceptUnix()がタイムアウトエラーを返すことを検証します。
    • ln.File()のテストも含まれています。
  7. 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)に関連する一時的なコードまたはテストケースのプレースホルダーである可能性があります。

全体として、このコミットはnetパッケージのプロトコル固有のAPIに対するテストカバレッジを大幅に向上させ、特にクロスプラットフォームな挙動や、より高度なネットワーク操作の正確性を保証することを目的としています。

関連リンク

参考にした情報源リンク

  • 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パッケージの設計思想に関する記事や議論 (一般的な情報源)