[インデックス 14550] ファイルの概要
このコミットは、Go言語の標準ライブラリであるnet
パッケージ内のテストコード、具体的にはtimeout_test.go
ファイルに対する変更です。TestVariousDeadlines1Proc
テストにおいて、net.Listener.Accept()
メソッドがエラーを返した場合の報告メカニズムを改善することを目的としています。
コミット
commit 0420eb3b656a7b0aeb04063df6d5989229cdb393
Author: Alex Brainman <alex.brainman@gmail.com>
Date: Tue Dec 4 17:00:19 2012 +1100
net: report Accept error during TestVariousDeadlines1Proc test
R=golang-dev
CC=golang-dev
https://golang.org/cl/6868057
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/0420eb3b656a7b0aeb04063df6d5989229cdb393
元コミット内容
net: report Accept error during TestVariousDeadlines1Proc test
このコミットメッセージは、net
パッケージのTestVariousDeadlines1Proc
テスト中に発生するAccept
エラーを報告するように変更したことを示しています。
変更の背景
Go言語のnet
パッケージは、ネットワーク通信機能を提供する重要なライブラリです。そのテストスイートは、様々なネットワークシナリオにおける挙動の正確性と堅牢性を保証するために不可欠です。timeout_test.go
ファイルに含まれるTestVariousDeadlines1Proc
テストは、ネットワーク接続のタイムアウト処理を検証するためのものです。
このコミットが行われる前は、テスト内のサーバー側でnet.Listener.Accept()
がエラーを返した場合、そのエラーが適切にテストフレームワークに報告されない可能性がありました。具体的には、Accept
がエラーを返した際に、テストが終了しているかどうかをtestsDone()
関数で確認し、テストが終了していない場合にのみt.Fatalf
でエラーを報告していました。しかし、このロジックでは、テストが終了する前に発生したAccept
エラーが、テストのタイムアウトなど他の要因によって見過ごされてしまうリスクがありました。
この変更の背景には、テストの信頼性を向上させ、ネットワーク関連の潜在的なバグをより確実に検出できるようにするという目的があります。Accept
エラーは、リスナーのクローズ、ネットワークの問題、または他の予期せぬ状況によって発生する可能性があり、これらのエラーがテスト中に適切に捕捉され、報告されることは、コードの品質を維持するために非常に重要です。
前提知識の解説
このコミットを理解するためには、以下のGo言語の概念とネットワークプログラミングの基礎知識が必要です。
net
パッケージ: Go言語の標準ライブラリで、TCP/UDPネットワーク、IPアドレスの解決、HTTPクライアント/サーバーなどのネットワーク機能を提供します。net.Listener
インターフェース: ネットワーク接続をリッスンするためのインターフェースです。Accept()
メソッドを持ち、新しい接続が確立されるまでブロックし、その接続を表すnet.Conn
を返します。エラーが発生した場合、Accept()
はエラーを返します。net.Conn
インターフェース: ネットワーク接続を表すインターフェースです。データの読み書き、タイムアウトの設定などを行います。testing
パッケージ: Go言語の標準テストフレームワークです。*testing.T
型はテスト関数に渡され、テストの失敗を報告したり、ログを出力したりするために使用されます。t.Fatalf(format string, args ...interface{})
: テストを失敗としてマークし、指定されたメッセージを出力してテスト関数を終了します。t.Logf(format string, args ...interface{})
: テストの実行中にログメッセージを出力します。
- Goroutine: Go言語の軽量な並行処理の単位です。
go
キーワードを使って関数呼び出しの前に置くことで、その関数を新しいgoroutineで実行できます。 - Channel: Goroutine間で値を安全に送受信するための通信メカニズムです。チャネルは型付けされており、
make(chan Type)
で作成します。- バッファなしチャネル:
make(chan Type)
で作成され、送信と受信が同期します。 - バッファありチャネル:
make(chan Type, capacity)
で作成され、指定された容量まで値をバッファリングできます。
- バッファなしチャネル:
defer
ステートメント: 関数がリターンする直前に実行される関数呼び出しをスケジュールします。リソースの解放(例: ファイルやネットワーク接続のクローズ)によく使用されます。select
ステートメント: 複数のチャネル操作を待機し、準備ができた最初の操作を実行します。タイムアウト処理や複数のイベントソースからの受信によく使用されます。runtime.GOMAXPROCS
: Goランタイムが同時に実行できるOSスレッドの最大数を設定します。テスト環境で並行処理の挙動を制御するために使用されることがあります。
技術的詳細
このコミットは、net/timeout_test.go
内のtestVariousDeadlines
関数におけるAccept
エラーのハンドリングロジックを改善します。以前の実装では、サーバーのAccept
ループ内でエラーが発生した場合、testsDone()
というヘルパー関数を呼び出して、テストが既に終了しているかどうかを確認していました。testsDone()
はdonec
というチャネルからの受信を試み、受信できればテストが終了したと判断していました。もしテストが終了していなければ、t.Fatalf
でエラーを報告していました。
このアプローチの問題点は、donec
チャネルがdefer close(donec)
によって閉じられるものの、testsDone()
がselect
ステートメントで<-donec
のみを待機しているため、donec
が閉じられた後にtestsDone()
が呼び出されると、すぐにtrue
を返してしまうことです。これにより、Accept
エラーが発生したタイミングによっては、テストがまだ完全に終了していないにもかかわらず、エラーが報告されない可能性がありました。また、donec
チャネルはテストの終了を通知するためだけに使われており、Accept
エラー自体を伝えるためのものではありませんでした。
新しい実装では、このdonec
チャネルとtestsDone()
関数を廃止し、代わりにacceptc
という新しいバッファ付きチャネル(make(chan error, 1)
)を導入しています。
変更のポイントは以下の通りです。
donec
チャネルとtestsDone()
関数の削除: テスト終了の確認ロジックを簡素化し、Accept
エラー報告の目的から分離します。acceptc
チャネルの導入:Accept
エラーを専用に報告するためのチャネルです。バッファサイズが1であるため、最大1つのエラーを保持できます。Accept
エラーの送信: サーバーのAccept
ループ内でエラーが発生した場合、以前はtestsDone()
のチェック後にt.Fatalf
を呼び出していた箇所が、acceptc <- err
に変更されます。これにより、Accept
エラーがacceptc
チャネルに非同期で送信されます。- メインテストループでの
Accept
エラーの受信:testVariousDeadlines
関数のメインテストループ(for name, tooLong := range testCases
の後のselect
ステートメント)に、case err := <-acceptc:
という新しいケースが追加されます。これにより、Accept
エラーがacceptc
チャネルに送信されると、このselect
がそのエラーを捕捉し、t.Fatalf("for %v: server Accept = %v", name, err)
を使ってテストを失敗させ、エラーメッセージを詳細に報告します。
この変更により、Accept
エラーが発生した際に、そのエラーが確実にメインテストループに伝達され、テストが失敗としてマークされるようになります。これにより、テストの信頼性が向上し、ネットワーク関連の潜在的な問題がより早期に、かつ明確に検出できるようになります。
コアとなるコードの変更箇所
src/pkg/net/timeout_test.go
--- a/src/pkg/net/timeout_test.go
+++ b/src/pkg/net/timeout_test.go
@@ -410,16 +410,7 @@ func testVariousDeadlines(t *testing.T, maxProcs int) {
defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(maxProcs))
ln := newLocalListener(t)
defer ln.Close()\n- donec := make(chan struct{})\n- defer close(donec)\n-\n-\ttestsDone := func() bool {\n-\t\tselect {\n-\t\tcase <-donec:\n-\t\t\treturn true\n-\t\t}\n-\t\treturn false\n-\t}\n+\tacceptc := make(chan error, 1)\n
// The server, with no timeouts of its own, sending bytes to clients
// as fast as it can.
go func() {
@@ -428,9 +419,7 @@ func testVariousDeadlines(t *testing.T, maxProcs int) {
for {
c, err := ln.Accept()
if err != nil {
-\t\t\t\tif !testsDone() {\n-\t\t\t\t\tt.Fatalf(\"Accept: %v\", err)\n-\t\t\t\t}\n+\t\t\t\tacceptc <- err\n return
}
go func() {
defer c.Close()
@@ -504,6 +493,8 @@ func testVariousDeadlines(t *testing.T, maxProcs int) {
select {
case res := <-servec:
t.Logf("for %v: server in %v wrote %d, %v", name, res.d, res.n, res.err)
+\t\t\tcase err := <-acceptc:\n+\t\t\t\tt.Fatalf("for %v: server Accept = %v", name, err)\n case <-time.After(tooLong):\n t.Fatalf("for %v, timeout waiting for server to finish writing", name)\n }
コアとなるコードの解説
-
donec
チャネルとtestsDone()
関数の削除:- donec := make(chan struct{}) - defer close(donec) - - testsDone := func() bool { - select { - case <-donec: - return true - } - return false - }
以前は、テストが終了したかどうかを判断するために
donec
チャネルとtestsDone()
関数が使用されていました。donec
はdefer close(donec)
によってテスト関数の終了時に閉じられ、testsDone()
はそのチャネルからの受信を試みることでテストの終了を検出していました。このロジックは、Accept
エラーの報告には不適切であり、削除されました。 -
acceptc
チャネルの導入:+ acceptc := make(chan error, 1)
新しく
acceptc
というerror
型のチャネルが導入されました。このチャネルはバッファサイズが1であるため、最大1つのAccept
エラーを保持できます。これは、Accept
ループ内で発生したエラーをメインのテストループに安全に伝えるための専用の通信路として機能します。 -
Accept
エラーの報告ロジックの変更:- if !testsDone() { - t.Fatalf("Accept: %v", err) - } + acceptc <- err
サーバーの
Accept
ループ内でln.Accept()
がエラーを返した場合の処理が変更されました。以前はtestsDone()
でテスト終了を確認し、終了していなければt.Fatalf
で即座にテストを終了させていました。この変更により、エラーが発生するとそのエラー値がacceptc
チャネルに送信されます。これにより、Accept
エラーの発生が非同期的にメインテストループに通知されます。 -
メインテストループでの
Accept
エラーの受信と報告:+ case err := <-acceptc: + t.Fatalf("for %v: server Accept = %v", name, err)
testVariousDeadlines
関数のメインテストループにあるselect
ステートメントに新しいケースが追加されました。このcase err := <-acceptc:
は、acceptc
チャネルにエラーが送信されるのを待ち受けます。エラーが受信されると、t.Fatalf
が呼び出され、テストが失敗としてマークされ、どのテストケース(name
)でAccept
エラーが発生したか、そしてそのエラーの内容(err
)が詳細に報告されます。これにより、Accept
エラーが確実にテスト結果に反映されるようになります。
これらの変更により、Accept
エラーのハンドリングがより堅牢になり、テストの信頼性が向上しました。
関連リンク
- Go言語の
net
パッケージドキュメント: https://pkg.go.dev/net - Go言語の
testing
パッケージドキュメント: https://pkg.go.dev/testing - Go言語のチャネルに関する公式ブログ記事: https://go.dev/blog/pipelines
参考にした情報源リンク
- Go言語の公式ドキュメント
- Go言語のソースコード(
src/pkg/net/timeout_test.go
) - Go言語のコードレビューシステム (Gerrit) の変更リスト: https://golang.org/cl/6868057 (コミットメッセージに記載)
- Go言語の並行処理に関する一般的な知識
[インデックス 14550] ファイルの概要
このコミットは、Go言語の標準ライブラリであるnet
パッケージ内のテストコード、具体的にはtimeout_test.go
ファイルに対する変更です。TestVariousDeadlines1Proc
テストにおいて、net.Listener.Accept()
メソッドがエラーを返した場合の報告メカニズムを改善することを目的としています。
コミット
commit 0420eb3b656a7b0aeb04063df6d5989229cdb393
Author: Alex Brainman <alex.brainman@gmail.com>
Date: Tue Dec 4 17:00:19 2012 +1100
net: report Accept error during TestVariousDeadlines1Proc test
R=golang-dev
CC=golang-dev
https://golang.org/cl/6868057
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/0420eb3b656a7b0aeb04063df6d5989229cdb393
元コミット内容
net: report Accept error during TestVariousDeadlines1Proc test
このコミットメッセージは、net
パッケージのTestVariousDeadlines1Proc
テスト中に発生するAccept
エラーを報告するように変更したことを示しています。
変更の背景
Go言語のnet
パッケージは、ネットワーク通信機能を提供する重要なライブラリです。そのテストスイートは、様々なネットワークシナリオにおける挙動の正確性と堅牢性を保証するために不可欠です。timeout_test.go
ファイルに含まれるTestVariousDeadlines1Proc
テストは、ネットワーク接続のタイムアウト処理を検証するためのものです。
このコミットが行われる前は、テスト内のサーバー側でnet.Listener.Accept()
がエラーを返した場合、そのエラーが適切にテストフレームワークに報告されない可能性がありました。具体的には、Accept
がエラーを返した際に、テストが終了しているかどうかをtestsDone()
関数で確認し、テストが終了していない場合にのみt.Fatalf
でエラーを報告していました。しかし、このロジックでは、テストが終了する前に発生したAccept
エラーが、テストのタイムアウトなど他の要因によって見過ごされてしまうリスクがありました。
この変更の背景には、テストの信頼性を向上させ、ネットワーク関連の潜在的なバグをより確実に検出できるようにするという目的があります。Accept
エラーは、リスナーのクローズ、ネットワークの問題、または他の予期せぬ状況によって発生する可能性があり、これらのエラーがテスト中に適切に捕捉され、報告されることは、コードの品質を維持するために非常に重要です。
前提知識の解説
このコミットを理解するためには、以下のGo言語の概念とネットワークプログラミングの基礎知識が必要です。
net
パッケージ: Go言語の標準ライブラリで、TCP/UDPネットワーク、IPアドレスの解決、HTTPクライアント/サーバーなどのネットワーク機能を提供します。net.Listener
インターフェース: ネットワーク接続をリッスンするためのインターフェースです。Accept()
メソッドを持ち、新しい接続が確立されるまでブロックし、その接続を表すnet.Conn
を返します。エラーが発生した場合、Accept()
はエラーを返します。net.Conn
インターフェース: ネットワーク接続を表すインターフェースです。データの読み書き、タイムアウトの設定などを行います。testing
パッケージ: Go言語の標準テストフレームワークです。*testing.T
型はテスト関数に渡され、テストの失敗を報告したり、ログを出力したりするために使用されます。t.Fatalf(format string, args ...interface{})
: テストを失敗としてマークし、指定されたメッセージを出力してテスト関数を終了します。t.Logf(format string, args ...interface{})
: テストの実行中にログメッセージを出力します。
- Goroutine: Go言語の軽量な並行処理の単位です。
go
キーワードを使って関数呼び出しの前に置くことで、その関数を新しいgoroutineで実行できます。 - Channel: Goroutine間で値を安全に送受信するための通信メカニズムです。チャネルは型付けされており、
make(chan Type)
で作成します。- バッファなしチャネル:
make(chan Type)
で作成され、送信と受信が同期します。 - バッファありチャネル:
make(chan Type, capacity)
で作成され、指定された容量まで値をバッファリングできます。
- バッファなしチャネル:
defer
ステートメント: 関数がリターンする直前に実行される関数呼び出しをスケジュールします。リソースの解放(例: ファイルやネットワーク接続のクローズ)によく使用されます。select
ステートメント: 複数のチャネル操作を待機し、準備ができた最初の操作を実行します。タイムアウト処理や複数のイベントソースからの受信によく使用されます。runtime.GOMAXPROCS
: Goランタイムが同時に実行できるOSスレッドの最大数を設定します。テスト環境で並行処理の挙動を制御するために使用されることがあります。
技術的詳細
このコミットは、net/timeout_test.go
内のtestVariousDeadlines
関数におけるAccept
エラーのハンドリングロジックを改善します。以前の実装では、サーバーのAccept
ループ内でエラーが発生した場合、testsDone()
というヘルパー関数を呼び出して、テストが既に終了しているかどうかを確認していました。testsDone()
はdonec
というチャネルからの受信を試み、受信できればテストが終了したと判断していました。もしテストが終了していなければ、t.Fatalf
でエラーを報告していました。
このアプローチの問題点は、donec
チャネルがdefer close(donec)
によって閉じられるものの、testsDone()
がselect
ステートメントで<-donec
のみを待機しているため、donec
が閉じられた後にtestsDone()
が呼び出されると、すぐにtrue
を返してしまうことです。これにより、Accept
エラーが発生したタイミングによっては、テストがまだ完全に終了していないにもかかわらず、エラーが報告されない可能性がありました。また、donec
チャネルはテストの終了を通知するためだけに使われており、Accept
エラー自体を伝えるためのものではありませんでした。
新しい実装では、このdonec
チャネルとtestsDone()
関数を廃止し、代わりにacceptc
という新しいバッファ付きチャネル(make(chan error, 1)
)を導入しています。
変更のポイントは以下の通りです。
donec
チャネルとtestsDone()
関数の削除: テスト終了の確認ロジックを簡素化し、Accept
エラー報告の目的から分離します。acceptc
チャネルの導入:Accept
エラーを専用に報告するためのチャネルです。バッファサイズが1であるため、最大1つのエラーを保持できます。Accept
エラーの送信: サーバーのAccept
ループ内でエラーが発生した場合、以前はtestsDone()
のチェック後にt.Fatalf
を呼び出していた箇所が、acceptc <- err
に変更されます。これにより、Accept
エラーがacceptc
チャネルに非同期で送信されます。- メインテストループでの
Accept
エラーの受信:testVariousDeadlines
関数のメインテストループ(for name, tooLong := range testCases
の後のselect
ステートメント)に、case err := <-acceptc:
という新しいケースが追加されます。これにより、Accept
エラーがacceptc
チャネルに送信されると、このselect
がそのエラーを捕捉し、t.Fatalf("for %v: server Accept = %v", name, err)
を使ってテストを失敗させ、エラーメッセージを詳細に報告します。
この変更により、Accept
エラーが発生した際に、そのエラーが確実にメインテストループに伝達され、テストが失敗としてマークされるようになります。これにより、テストの信頼性が向上し、ネットワーク関連の潜在的な問題がより早期に、かつ明確に検出できるようになります。
コアとなるコードの変更箇所
src/pkg/net/timeout_test.go
--- a/src/pkg/net/timeout_test.go
+++ b/src/pkg/net/timeout_test.go
@@ -410,16 +410,7 @@ func testVariousDeadlines(t *testing.T, maxProcs int) {
defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(maxProcs))
ln := newLocalListener(t)
defer ln.Close()\n- donec := make(chan struct{})\n- defer close(donec)\n-\n-\ttestsDone := func() bool {\n-\t\tselect {\n-\t\tcase <-donec:\n-\t\t\treturn true\n-\t\t}\n-\t\treturn false\n-\t}\n+\tacceptc := make(chan error, 1)\n
// The server, with no timeouts of its own, sending bytes to clients
// as fast as it can.
go func() {
@@ -428,9 +419,7 @@ func testVariousDeadlines(t *testing.T, maxProcs int) {
for {
c, err := ln.Accept()
if err != nil {
-\t\t\t\tif !testsDone() {\n-\t\t\t\t\tt.Fatalf("Accept: %v", err)\n-\t\t\t\t}\n+\t\t\t\tacceptc <- err\n return
}
go func() {
defer c.Close()
@@ -504,6 +493,8 @@ func testVariousDeadlines(t *testing.T, maxProcs int) {
select {
case res := <-servec:
t.Logf("for %v: server in %v wrote %d, %v", name, res.d, res.n, res.err)
+\t\t\tcase err := <-acceptc:\n+\t\t\t\tt.Fatalf("for %v: server Accept = %v", name, err)\n case <-time.After(tooLong):\n t.Fatalf("for %v, timeout waiting for server to finish writing", name)\n }
コアとなるコードの解説
-
donec
チャネルとtestsDone()
関数の削除:- donec := make(chan struct{}) - defer close(donec) - - testsDone := func() bool { - select { - case <-donec: - return true - } - return false - }
以前は、テストが終了したかどうかを判断するために
donec
チャネルとtestsDone()
関数が使用されていました。donec
はdefer close(donec)
によってテスト関数の終了時に閉じられ、testsDone()
はそのチャネルからの受信を試みることでテストの終了を検出していました。このロジックは、Accept
エラーの報告には不適切であり、削除されました。 -
acceptc
チャネルの導入:+ acceptc := make(chan error, 1)
新しく
acceptc
というerror
型のチャネルが導入されました。このチャネルはバッファサイズが1であるため、最大1つのAccept
エラーを保持できます。これは、Accept
ループ内で発生したエラーをメインのテストループに安全に伝えるための専用の通信路として機能します。 -
Accept
エラーの報告ロジックの変更:- if !testsDone() { - t.Fatalf("Accept: %v", err) - } + acceptc <- err
サーバーの
Accept
ループ内でln.Accept()
がエラーを返した場合の処理が変更されました。以前はtestsDone()
でテスト終了を確認し、終了していなければt.Fatalf
で即座にテストを終了させていました。この変更により、エラーが発生するとそのエラー値がacceptc
チャネルに送信されます。これにより、Accept
エラーの発生が非同期的にメインテストループに通知されます。 -
メインテストループでの
Accept
エラーの受信と報告:+ case err := <-acceptc: + t.Fatalf("for %v: server Accept = %v", name, err)
testVariousDeadlines
関数のメインテストループにあるselect
ステートメントに新しいケースが追加されました。このcase err := <-acceptc:
は、acceptc
チャネルにエラーが送信されるのを待ち受けます。エラーが受信されると、t.Fatalf
が呼び出され、テストが失敗としてマークされ、どのテストケース(name
)でAccept
エラーが発生したか、そしてそのエラーの内容(err
)が詳細に報告されます。これにより、Accept
エラーが確実にテスト結果に反映されるようになります。
これらの変更により、Accept
エラーのハンドリングがより堅牢になり、テストの信頼性が向上しました。
関連リンク
- Go言語の
net
パッケージドキュメント: https://pkg.go.dev/net - Go言語の
testing
パッケージドキュメント: https://pkg.go.dev/testing - Go言語のチャネルに関する公式ブログ記事: https://go.dev/blog/pipelines
参考にした情報源リンク
- Go言語の公式ドキュメント
- Go言語のソースコード(
src/pkg/net/timeout_test.go
) - Go言語のコードレビューシステム (Gerrit) の変更リスト: https://golang.org/cl/6868057 (コミットメッセージに記載)
- Go言語の並行処理に関する一般的な知識