[インデックス 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言語の並行処理に関する一般的な知識