[インデックス 18516] ファイルの概要
このコミットは、Go言語の標準ライブラリnet
パッケージ内のTestDNSThreadLimit
というテストの挙動を変更するものです。具体的には、このテストがデフォルトで実行されないようにし、明示的なフラグ(-dnsflood
)を指定した場合にのみ実行されるように修正しています。これにより、テストが引き起こす可能性のあるネットワークへの負荷や仮想環境での問題を防ぐことが目的です。
コミット
commit 2277e8d3c9c3f14aa9536f4aaeea6bfa6c316f3f
Author: Mikio Hara <mikioh.mikioh@gmail.com>
Date: Fri Feb 14 12:20:21 2014 +0900
net: disable TestDNSThreadLimit even in non-short mode by default
TestDNSThreadLimit creates tons of DNS queries and it occasionally
causes an unintentional traffic jam and/or crash of some virtual
machine software, especially its builtin networking stuff.
We can run TestDNSThreadLimit with -dnsflood flag instead.
LGTM=dave, rsc
R=rsc, dave
CC=golang-codereviews
https://golang.org/cl/63600043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/2277e8d3c9c3f14aa9536f4aaeea6bfa6c316f3f
元コミット内容
net: disable TestDNSThreadLimit even in non-short mode by default
TestDNSThreadLimit
は大量のDNSクエリを生成するため、意図しないトラフィックジャムや、特に仮想マシンの内蔵ネットワーキング機能のクラッシュを引き起こすことがあります。
代わりに、-dnsflood
フラグを使ってTestDNSThreadLimit
を実行できます。
変更の背景
TestDNSThreadLimit
は、Goのnet
パッケージが同時に処理できるDNSクエリのスレッド数やリミットをテストするために設計されたものです。このテストは、その性質上、短時間で非常に大量のDNSクエリを生成します。
コミットメッセージに明記されているように、この大量のDNSクエリの生成は、以下のような問題を引き起こす可能性がありました。
- 意図しないトラフィックジャム (unintentional traffic jam): テストが実行される環境のネットワーク帯域を一時的に飽和させたり、DNSサーバーに過度な負荷をかけたりする可能性があります。これは、共有ネットワーク環境や、テスト環境が本番環境と同一のDNSリゾルバを使用している場合に特に問題となります。
- 仮想マシンソフトウェアのクラッシュ (crash of some virtual machine software): 特に仮想化ソフトウェアに内蔵されているネットワーク機能が、短期間に集中する大量のDNSクエリ処理に耐えきれず、不安定になったりクラッシュしたりするケースがあったようです。これは、開発者がローカルの仮想環境でテストを実行する際に、予期せぬ問題に直面する原因となっていました。
これらの問題を回避し、開発者やCI/CD環境でのテスト実行の安定性を向上させるため、このテストをデフォルトで無効化し、必要に応じて明示的に有効化するメカニズムが導入されました。
前提知識の解説
1. DNS (Domain Name System)
DNSは、インターネット上のドメイン名(例: www.example.com
)をIPアドレス(例: 192.0.2.1
)に変換するための分散型データベースシステムです。ユーザーがウェブサイトにアクセスしたり、アプリケーションがリモートサービスと通信したりする際、まずDNSクエリを発行してドメイン名に対応するIPアドレスを解決します。TestDNSThreadLimit
は、このDNSクエリを大量に発行することで、システムが同時に処理できるDNS解決の能力を試すテストです。
2. Go言語のtesting
パッケージ
Go言語には、ユニットテストやベンチマークテストを記述するための標準パッケージtesting
が用意されています。
func TestXxx(t *testing.T)
: テスト関数はTest
で始まり、*testing.T
型の引数を取ります。t.Skip(args ...interface{})
: このメソッドが呼び出されると、現在のテストはスキップされます。テストが特定の条件を満たさない場合(例: 外部ネットワーク接続が必要なテストでネットワークがない場合、またはリソースを大量に消費するテストを通常実行したくない場合)に利用されます。testing.Short()
: この関数は、go test -short
フラグが指定された場合にtrue
を返します。通常、時間がかかるテストや外部リソースに依存するテストを、go test -short
実行時にはスキップするために使用されます。これにより、開発中の迅速なテスト実行が可能になります。
3. Go言語のflag
パッケージ
Go言語のflag
パッケージは、コマンドライン引数を解析するための機能を提供します。
flag.Bool(name string, value bool, usage string) *bool
: ブール型のコマンドラインフラグを定義します。name
はフラグ名(例:dnsflood
)、value
はデフォルト値、usage
はフラグの説明です。この関数は、フラグの値へのポインタを返します。flag.Parse()
: コマンドライン引数を解析し、定義されたフラグに値を割り当てます。通常、main
関数の冒頭で呼び出されます。
このコミットでは、flag
パッケージを使用して新しいコマンドラインフラグ-dnsflood
を導入し、このフラグが指定された場合にのみTestDNSThreadLimit
が実行されるように制御しています。
技術的詳細
このコミットの技術的な変更点は、src/pkg/net/z_last_test.go
ファイル内のTestDNSThreadLimit
関数の冒頭にある条件分岐のロジックを変更したことです。
変更前は、以下の条件でテストがスキップされていました。
if testing.Short() || !*testExternal {
t.Skip("skipping test to avoid external network")
}
これは、「go test -short
が指定された場合」または「testExternal
フラグがfalse
の場合(つまり外部ネットワークへのアクセスを許可しない場合)」にテストをスキップするという意味です。TestDNSThreadLimit
は大量のDNSクエリを生成するため、外部ネットワークへのアクセスが必須であり、また時間がかかるテストであるため、testing.Short()
によるスキップは理にかなっていました。
しかし、このコミットでは、TestDNSThreadLimit
が引き起こす可能性のある問題(トラフィックジャム、VMクラッシュ)が、testing.Short()
モードではない通常実行時にも発生しうることが認識されました。そこで、より明示的な制御が必要と判断されました。
変更後、以下のようになりました。
var testDNSFlood = flag.Bool("dnsflood", false, "whether to test dns query flooding")
func TestDNSThreadLimit(t *testing.T) {
if !*testDNSFlood {
t.Skip("test disabled; use -dnsflood to enable")
}
// ... 既存のテストロジック ...
}
この変更により、以下の点が実現されました。
- 新しいフラグの導入:
flag.Bool("dnsflood", false, ...)
によって、testDNSFlood
という新しいブール型フラグが導入されました。このフラグのデフォルト値はfalse
です。 - デフォルトでのテスト無効化:
if !*testDNSFlood
という条件により、-dnsflood
フラグがコマンドラインで指定されない限り(つまりtestDNSFlood
がfalse
のままの場合)、TestDNSThreadLimit
は常にスキップされるようになりました。 - 明示的な有効化: ユーザーがこのテストを実行したい場合は、
go test -dnsflood
のようにコマンドラインで明示的にフラグを指定する必要があります。これにより、テストが引き起こす可能性のある影響を理解した上で、意図的に実行することが求められるようになりました。 testing.Short()
からの独立:testing.Short()
によるスキップ条件は削除され、TestDNSThreadLimit
の実行は完全に-dnsflood
フラグによって制御されるようになりました。これにより、go test
の通常実行時でも、この負荷の高いテストが意図せず実行されることがなくなりました。
この変更は、テストの実行環境への影響を最小限に抑えつつ、必要に応じて特定のテストを実行できる柔軟性を提供する、Goのテストフレームワークにおける一般的なプラクティスを反映しています。
コアとなるコードの変更箇所
--- a/src/pkg/net/z_last_test.go
+++ b/src/pkg/net/z_last_test.go
@@ -5,13 +5,16 @@
package net
import (
+ "flag"
"fmt"
"testing"
)
+var testDNSFlood = flag.Bool("dnsflood", false, "whether to test dns query flooding")
+
func TestDNSThreadLimit(t *testing.T) {
- if testing.Short() || !*testExternal {
- t.Skip("skipping test to avoid external network")
+ if !*testDNSFlood {
+ t.Skip("test disabled; use -dnsflood to enable")
}
const N = 10000
コアとなるコードの解説
-
import "flag"
の追加:flag
パッケージを使用するために、インポートリストに"flag"
が追加されました。 -
var testDNSFlood = flag.Bool("dnsflood", false, "whether to test dns query flooding")
の追加: これは、新しいコマンドラインフラグdnsflood
を定義しています。"dnsflood"
: フラグの名前です。コマンドラインで-dnsflood
として使用されます。false
: このフラグのデフォルト値です。つまり、-dnsflood
が指定されない限り、testDNSFlood
変数の値はfalse
になります。"whether to test dns query flooding"
: このフラグの用途を説明するヘルプメッセージです。
-
TestDNSThreadLimit
関数の条件分岐の変更:- 変更前:
この行は、if testing.Short() || !*testExternal { t.Skip("skipping test to avoid external network") }
go test -short
が指定された場合、またはtestExternal
フラグがfalse
(外部ネットワークへのアクセスが許可されていない)の場合にテストをスキップしていました。 - 変更後:
この行は、if !*testDNSFlood { t.Skip("test disabled; use -dnsflood to enable") }
testDNSFlood
フラグがfalse
の場合(つまり、コマンドラインで-dnsflood
が指定されていない場合)にテストをスキップするように変更されました。スキップメッセージも「テストは無効化されています。有効にするには-dnsflood
を使用してください」と、より具体的に変更されています。
- 変更前:
この変更により、TestDNSThreadLimit
はデフォルトでは実行されなくなり、開発者やCIシステムが意図的に-dnsflood
フラグを指定した場合にのみ実行されるようになりました。これにより、テストが引き起こす可能性のあるネットワーク負荷や仮想環境の問題を回避し、テスト実行の安定性が向上します。
関連リンク
- Go言語の
testing
パッケージドキュメント: https://pkg.go.dev/testing - Go言語の
flag
パッケージドキュメント: https://pkg.go.dev/flag - このコミットのGo CL (Code Review) ページ: https://golang.org/cl/63600043
参考にした情報源リンク
- GitHubのコミットページ: https://github.com/golang/go/commit/2277e8d3c9c3f14aa9536f4aaeea6bfa6c316f3f
- Go言語の公式ドキュメント (testing, flagパッケージ): https://go.dev/pkg/
- DNSの基本概念に関する一般的な情報源 (例: Wikipedia, MDN Web Docsなど)