[インデックス 15228] ファイルの概要
このコミットは、Go言語の標準ライブラリである net
パッケージ内のテストファイル src/pkg/net/fd_unix_test.go
に関連するものです。このファイルは、Unix系システムにおけるネットワークファイルディスクリプタ(netFD
)の挙動、特にI/O多重化メカニズムであるポーリング(pollster
)との連携に関するテストを含んでいます。
コミット
commit 8c30b3f038fe140d7f05ebe60d090e1d4a2eb3b5
Author: Dave Cheney <dave@cheney.net>
Date: Thu Feb 14 10:11:16 2013 +1100
net: remove noisy test for issue 3590
The test for issue 3590 causes an error to be printed to stderr when run (although the error is obscured during go test std). This is confusing for people who get breakage in the net package as the error is harmless and most likely unrelated to their build breakage.
Given the way the test works, by reaching into the guts of the netFD, I can't see a way to silence the error without adding a bunch of code to support the test, therefore I am suggesting the test be removed before Go 1.1 ships.
R=alex.brainman, mikioh.mikioh, rsc
CC=golang-dev
https://golang.org/cl/7307110
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/8c30b3f038fe140d7f05ebe60d090e1d4a2eb3b5
元コミット内容
このコミットは、Go言語の net
パッケージから、issue 3590
に関連する「ノイズの多いテスト」を削除するものです。このテストは実行時に標準エラー出力(stderr)にエラーメッセージを出力しますが、これは無害であり、ユーザーが net
パッケージでビルドの問題に遭遇した際に混乱を招く原因となっていました。テストの性質上、エラー出力を抑制することが困難であったため、Go 1.1のリリース前にテストを削除することが提案されました。
変更の背景
この変更の主な背景は、src/pkg/net/fd_unix_test.go
内の TestAddFDReturnsError
というテストが、実行時に標準エラー出力(stderr)に不要なエラーメッセージを出力していたことにあります。このエラーはテストの意図とは異なり、実際の機能的な問題を示すものではありませんでした。しかし、go test std
のようなコマンドで標準ライブラリ全体のテストを実行する際には、この無害なエラーメッセージが他の重要なエラーメッセージに紛れてしまい、開発者やユーザーが net
パッケージ関連の問題をデバッグする際に混乱を招いていました。
特に、net
パッケージでビルドの破損や予期せぬ挙動に直面した人々にとって、この無害なエラーメッセージは、問題の原因がこのテストにあると誤解させる可能性がありました。コミットメッセージには、「エラーは無害であり、ビルドの破損とはほとんど関係がない」と明記されています。
テストの内部実装が netFD
の内部構造に深く依存しており、エラー出力を抑制するためには多くの追加コードが必要となるため、テスト自体を削除することが最も現実的な解決策と判断されました。Go 1.1のリリースを控えていた時期であり、安定性とユーザー体験の向上が優先された結果、このテストの削除が決定されました。
前提知識の解説
net
パッケージ: Go言語の標準ライブラリの一部で、ネットワークI/O機能を提供します。TCP/IP、UDP、Unixドメインソケットなどのネットワークプロトコルを扱うためのAPIが含まれています。- ファイルディスクリプタ (File Descriptor, FD): Unix系OSにおいて、ファイルやソケットなどのI/Oリソースを識別するためにカーネルが割り当てる整数値です。ネットワーク接続もFDとして扱われます。
netFD
: Go言語のnet
パッケージ内部で、ネットワーク接続に関連するファイルディスクリプタを抽象化し、管理するための構造体です。これには、FD自体だけでなく、その状態や関連するポーリングメカニズムへの参照が含まれます。netFd.AddFD
:net
パッケージの内部関数で、新しいファイルディスクリプタをポーリングシステムに追加する役割を担います。これにより、Goランタイムは複数のネットワーク接続からのI/Oイベントを効率的に監視できます。- ポーリング (Polling) /
pollster
: 多数のI/O操作を効率的に処理するためのメカニズムです。Unix系システムでは、epoll
(Linux),kqueue
(FreeBSD/macOS),poll
,select
などがこれに該当します。Goのランタイムは、これらのシステムコールを利用して、多数のネットワーク接続からのデータ到着や書き込み可能イベントを待機し、ゴルーチンをスケジューリングします。pollster
は、このポーリングメカニズムを抽象化した内部コンポーネントを指します。 - 標準エラー出力 (stderr): プログラムがエラーメッセージや診断情報を出力するために使用する標準的な出力ストリームです。通常、コンソールに表示されます。
go test std
: Goの標準ライブラリに含まれるすべてのパッケージのテストを実行するコマンドです。
技術的詳細
TestAddFDReturnsError
テストは、netFd.AddFD
が基盤となるポーリングシステムからエラーを適切に返すことを検証しようとしていました。具体的には、netFD
の内部にある pollServer
を意図的にクローズした状態に置き換え、その後にネットワークI/O操作(c.Read(b[:])
)を実行することで、netFd.AddFD
がエラーを発生させることを期待していました。
このテストが「ノイズの多い」とされた理由は、pollServer
を強制的にクローズするという、通常の運用では発生しないような内部状態をシミュレートしていたためです。この操作が、基盤となるシステムコールやGoランタイムの内部処理において、標準エラー出力にエラーメッセージを吐き出す副作用を引き起こしていました。コミットメッセージによると、このエラーは「無害」であり、テストの目的である netFd.AddFD
のエラーハンドリングの検証自体は成功していたものの、その過程で発生するstderrへの出力が問題でした。
エラー出力を抑制するためには、テストコードが netFD
のさらに深い内部構造に介入し、エラーメッセージの発生源を特定し、それを抑制するための複雑なロジックを追加する必要がありました。しかし、これはテストの目的を超えて、プロダクションコードに近い複雑さをテストコードに持ち込むことになり、保守性の低下を招きます。コミットメッセージにある「netFD
の内部に深く入り込む」という表現は、この複雑さと、テストのためだけに多くのコードを追加することの非効率性を示唆しています。
Go 1.1のリリースが迫る中で、この無害だが混乱を招くエラーメッセージを排除し、ユーザー体験を向上させることは重要でした。テストの目的が、netFd.AddFD
がパニックを起こすのではなくエラーを返すことを確認することであったと推測されますが、この特定のテストケースが引き起こす副作用が、その価値を上回ると判断されました。結果として、テストを修正するよりも、テスト自体を削除する方がシンプルで効果的な解決策であると結論付けられました。
コアとなるコードの変更箇所
変更は src/pkg/net/fd_unix_test.go
ファイルに対して行われました。
--- a/src/pkg/net/fd_unix_test.go
+++ b/src/pkg/net/fd_unix_test.go
@@ -12,54 +12,6 @@ import (
"testing"
)
-// Issue 3590. netFd.AddFD should return an error
-// from the underlying pollster rather than panicing.
-func TestAddFDReturnsError(t *testing.T) {
- ln := newLocalListener(t).(*TCPListener)
- defer ln.Close()
- connected := make(chan bool)
- go func() {
- for {
- c, err := ln.Accept()
- if err != nil {
- return
- }
- connected <- true
- defer c.Close()
- }
- }()
-
- c, err := DialTCP("tcp", nil, ln.Addr().(*TCPAddr))
- if err != nil {
- t.Fatal(err)
- }
- defer c.Close()
- <-connected
-
- // replace c's pollServer with a closed version.
- ps, err := newPollServer()
- if err != nil {
- t.Fatal(err)
- }
- ps.poll.Close()
- c.conn.fd.pollServer = ps
-
- var b [1]byte
- _, err = c.Read(b[:])
- if err, ok := err.(*OpError); ok {
- if err.Op == "addfd" {
- return
- }
- if err, ok := err.Err.(*OpError); ok {
- // the err is sometimes wrapped by another OpError
- if err.Op == "addfd" {
- return
- }
- }
- }
- t.Error("unexpected error:", err)
-}
-
var chkReadErrTests = []struct {
n int
err error
具体的には、TestAddFDReturnsError
という関数全体が削除されています。この変更により、48行が削除されました。
コアとなるコードの解説
削除された TestAddFDReturnsError
関数は、netFd.AddFD
がパニック(panic)を起こすのではなく、適切なエラーを返すことを検証することを目的としていました。
テストのロジックは以下の通りです。
- TCPリスナーを作成し、接続を確立します。
- 確立された接続
c
の内部にあるnetFD
のpollServer
を、意図的にクローズされた新しいpollServer
に置き換えます。これは、netFD
の内部実装に深く介入する操作です。 - その後、接続
c
からの読み取り操作(c.Read(b[:])
)を試みます。この読み取り操作の過程で、netFd.AddFD
が呼び出され、クローズされたpollServer
にFDを追加しようとすることでエラーが発生することを期待します。 - 発生したエラーが
OpError
型であり、そのOp
フィールドが"addfd"
であることを確認します。これは、netFd.AddFD
が期待通りにエラーを返したことを意味します。
このテストは、netFd.AddFD
が予期せぬパニックを引き起こす可能性を防ぐためのものでしたが、前述の通り、pollServer
を強制的にクローズするという特殊な状況が、無害なstderr出力という副作用を生み出していました。この副作用がGo 1.1のリリースにおけるユーザー体験を損なうと判断されたため、テストの目的は理解されつつも、その実装が引き起こす問題の方が大きいと判断され、削除に至りました。
テストの削除は、netFd.AddFD
のエラーハンドリングが他のテストやコードパスで十分にカバーされているか、あるいはこの特定のテストケースがカバーしようとしていたエッジケースが、実際の運用において重要度が低いと判断されたことを示唆しています。
関連リンク
- Go CL 7307110: https://golang.org/cl/7307110
参考にした情報源リンク
- Web search results for "Go issue 3590 netFd.AddFD":
- documentation.help (https://vertexaisearch.cloud.com/grounding-api-redirect/AUZIYQH9pH-2UWEmw6nayWZWIM42zQ2aiYzsVEigAVLEYi_Pqo0E0jH_oY1Q6DBy87zKKO3DQdK_PLkKgcyiA5X0CBJgeqz3U4BjeofvVhpjwYGulIcUlncbhN5EUIHcKC-V7YyAewY=)
- dev.to (https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQFoZBeswQC0oWpsqpmWgNxIA9xfIHV9mFytfg3wZhhAcV2nTadOhDrnRRYy05HAak4FBjIfAljHmP-dtB4_gA3UxDfcgApi4qaOZ6c_wmalAmKHpLYeXYowgc2RuNqacLFJsFG2I87Wqsy3NX_3dO8MfAAPKgGi7emEGFjFzbsld_dx2iMOCg3vak0eYGg=)
- Go言語の
net
パッケージに関する一般的な情報 - Unix系OSにおけるファイルディスクリプタとポーリングメカニズムに関する一般的な知識
- Go言語のテストに関する一般的な知識