[インデックス 17235] ファイルの概要
このコミットは、Go言語の標準ライブラリ net
パッケージ内の TestTCPStress
テストの実行時間を短縮することを目的としています。特に、FreeBSD環境のビルドボットで発生していたテストのタイムアウト問題を解決するために、testing.Short()
フラグを利用してテストのメッセージ数を削減する変更が加えられました。
コミット
commit f8ca13c3e5a85d6f9dbce499aca8006c104376ee
Author: Dmitriy Vyukov <dvyukov@google.com>
Date: Wed Aug 14 21:53:27 2013 +0400
net: make TCPStress test shorter
It timeouts on freebsd builders:
http://build.golang.org/log/3d8169e13bff912bebf6fd3c54b34ad2d29a7221
but there are always runnable goroutines,
which suggests that it's slowly progressing.
R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/12939043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/f8ca13c3e5a85d6f9dbce499aca8006c104376ee
元コミット内容
net: make TCPStress test shorter
It timeouts on freebsd builders:
http://build.golang.org/log/3d8169e13bff912bebf6fd3c54b34ad2d29a7221
but there are always runnable goroutines,
which suggests that it's slowly progressing.
R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/12939043
変更の背景
このコミットの主な背景は、Goプロジェクトの継続的インテグレーション(CI)システム、特にFreeBSD環境のビルドボットで発生していた TestTCPStress
テストのタイムアウト問題です。コミットメッセージに記載されているログリンク(http://build.golang.org/log/3d8169e13bff912bebf6fd3c54b34ad2d29a7221
)は、この問題が実際に発生していたことを示しています。
テストがタイムアウトする一方で、「常に実行可能なゴルーチンが存在する」という記述は、テスト自体がデッドロックしているわけではなく、単に処理に時間がかかりすぎていることを示唆しています。これは、テストが想定よりも多くのリソース(CPU時間、ネットワークI/Oなど)を消費しているか、特定の環境(この場合はFreeBSD)でパフォーマンスが低下している可能性を示しています。
CIシステムにおいてテストのタイムアウトは、ビルドの失敗や遅延を引き起こし、開発プロセスのボトルネックとなります。そのため、テストのロジックを変更せずに、実行時間を短縮する対策が必要とされました。Goの testing
パッケージが提供する testing.Short()
フラグは、このようなシナリオでテストの実行時間を調整するための標準的なメカニズムです。
前提知識の解説
Go言語の testing
パッケージ
Go言語には、ユニットテストやベンチマークテストを記述するための組み込みの testing
パッケージが用意されています。テストファイルは通常、テスト対象のソースファイルと同じディレクトリに _test.go
というサフィックスを付けて配置されます。テスト関数は Test
で始まり、*testing.T
型の引数を取ります。
testing.Short()
フラグ
testing.Short()
は、testing
パッケージが提供する関数で、テストが「短い」モードで実行されているかどうかを示すブール値を返します。このモードは、go test -short
コマンドライン引数を使用して有効にできます。
testing.Short()
フラグの主な目的は、開発者がローカルでテストを実行する際に、時間のかかるテスト(例: ネットワークテスト、ファイルI/Oが多いテスト、大規模なデータセットを扱うテスト)をスキップまたは短縮できるようにすることです。これにより、開発サイクルを高速化し、CIシステムでの実行時間を最適化することができます。
テストコード内で if testing.Short() { ... }
のように条件分岐を記述することで、短いモードの場合にテストの反復回数を減らしたり、一部のテストケースをスキップしたりするロジックを実装できます。
CI/CD環境におけるテストのタイムアウト
継続的インテグレーション(CI)および継続的デリバリー(CD)パイプラインでは、テストの実行時間は非常に重要です。テストが長すぎると、フィードバックループが長くなり、開発者の生産性が低下します。また、CIシステムには通常、個々のテストやビルド全体に対してタイムアウトが設定されています。このタイムアウトを超過すると、テストは強制終了され、ビルドは失敗とマークされます。
ネットワークテストやストレステストのように、実行に時間がかかる可能性のあるテストは、CI環境の安定性や効率性に影響を与えることがあります。このような場合、testing.Short()
のようなメカニズムを利用して、CI環境ではテストの負荷を軽減し、ローカル開発環境ではより徹底的なテストを実行できるようにすることが一般的です。
Goの net
パッケージとTCP通信
net
パッケージは、Go言語でネットワークI/Oを扱うための主要なパッケージです。TCP/IP、UDP、Unixドメインソケットなど、さまざまなネットワークプロトコルをサポートしています。TestTCPStress
は、この net
パッケージのTCP通信機能のストレス耐性をテストするものであり、多数の接続とメッセージの送受信をシミュレートすることで、ネットワークスタックの堅牢性やパフォーマンスを検証します。
技術的詳細
このコミットの技術的な核心は、Goの testing.Short()
フラグを利用して、TestTCPStress
テストの実行ロジックを動的に変更することにあります。
元のコードでは、msgs
(メッセージ数)が 1e4
(10,000) という定数で定義されていました。これは、テストが常に10,000個のメッセージを送受信しようとすることを意味します。FreeBSDのビルドボットでタイムアウトが発生した原因は、このメッセージ数が多すぎたため、特定の環境下でテストが完了するまでに許容された時間を超えてしまったことにあります。
変更後、msgs
は定数ではなく変数として宣言され、その初期値は引き続き 1e4
となります。しかし、その直後に if testing.Short() { msgs = 1e2 }
という条件分岐が追加されました。
この変更により、以下の挙動が実現されます。
- 通常実行時(
go test
):testing.Short()
はfalse
を返すため、msgs
の値は1e4
(10,000) のままとなり、テストはフルスケールで実行されます。 - 短いモード実行時(
go test -short
):testing.Short()
はtrue
を返すため、msgs
の値は1e2
(100) に上書きされます。これにより、テストが送受信するメッセージ数が100分の1に削減され、実行時間が大幅に短縮されます。
このアプローチは、テストの網羅性を損なうことなく、CI環境でのタイムアウト問題を回避するための効果的な手段です。開発者はローカルで完全なテストを実行し、CIシステムではより高速なサブセットのテストを実行することで、開発ワークフローの効率を向上させることができます。
コアとなるコードの変更箇所
src/pkg/net/tcp_test.go
ファイルの以下の部分が変更されました。
--- a/src/pkg/net/tcp_test.go
+++ b/src/pkg/net/tcp_test.go
@@ -497,8 +497,11 @@ func TestTCPReadWriteMallocs(t *testing.T) {
func TestTCPStress(t *testing.T) {
const conns = 2
- const msgs = 1e4
const msgLen = 512
+ msgs := int(1e4)
+ if testing.Short() {
+ msgs = 1e2
+ }
sendMsg := func(c Conn, buf []byte) bool {
n, err := c.Write(buf)
コアとなるコードの解説
変更されたコードブロックは TestTCPStress
関数内にあります。
-
const msgs = 1e4
の削除: 元のコードではmsgs
が定数として定義されていました。定数はコンパイル時に値が決定され、実行時に変更することはできません。 -
msgs := int(1e4)
の追加:msgs
が変数として再定義されました。1e4
は浮動小数点リテラルですが、int()
で明示的に整数型にキャストされています。これにより、msgs
は初期値として10,000を持ちますが、後で値を変更できるようになります。 -
if testing.Short() { msgs = 1e2 }
の追加: この行が変更の核心です。testing.Short()
: この関数は、go test -short
コマンドでテストが実行された場合にtrue
を返します。それ以外の場合はfalse
を返します。msgs = 1e2
:testing.Short()
がtrue
を返した場合、つまりテストが短いモードで実行されている場合、msgs
の値は1e2
(100) に上書きされます。
この変更により、TestTCPStress
テストは、go test -short
が指定された場合には100メッセージのみを処理し、それ以外の場合(通常の go test
やCI環境でのフルテスト実行時)には10,000メッセージを処理するようになります。これにより、FreeBSDビルドボットでのタイムアウト問題が解決され、同時にテストの網羅性も維持されます。
関連リンク
- GitHubコミットページ: https://github.com/golang/go/commit/f8ca13c3e5a85d6f9dbce499aca8006c104376ee
- Gerrit Change-Id (CL): https://golang.org/cl/12939043 (このリンクは古いGerritインスタンスのものであり、現在はアクセスできない可能性がありますが、コミットメッセージに記載されていたものです。)
参考にした情報源リンク
- Go言語
testing
パッケージ公式ドキュメント: https://pkg.go.dev/testing testing.Short()
の詳細に関する情報 (Goのドキュメントや関連するブログ記事など)go help testflag
コマンドの出力 (ローカル環境でgo help testflag
を実行すると-short
フラグに関する説明が得られます)- Goのテストに関する一般的な情報源 (例: "Effective Go" の Testing セクションなど)
- 継続的インテグレーション (CI) および継続的デリバリー (CD) の概念に関する一般的な情報源
- TCP/IPプロトコルおよびネットワークプログラミングに関する一般的な情報源
- FreeBSDオペレーティングシステムに関する一般的な情報源
- GoプロジェクトのビルドシステムおよびCIインフラに関する一般的な情報源 (Goの公式ブログや開発者向けドキュメントなど)