Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 15714] ファイルの概要

このコミットは、Go言語の標準ライブラリである net/http パッケージ内のテスト TestLinuxSendfile の信頼性を向上させるための変更です。具体的には、strace コマンドのオプションを調整することで、テストが不安定になる(flakyになる)問題を解決しています。

コミット

commit e0fd6d08b2b9251d409442ab871c6a4b1d7c82f3
Author: Dmitriy Vyukov <dvyukov@google.com>
Date:   Tue Mar 12 12:52:49 2013 +0400

    net/http: deflake test
    Update #5005.
    
    R=golang-dev, fullung, bradfitz
    CC=golang-dev
    https://golang.org/cl/7651045

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/e0fd6d08b2b9251d409442ab871c6a4b1d7c82f3

元コミット内容

net/http: deflake test Update #5005.

R=golang-dev, fullung, bradfitz CC=golang-dev https://golang.org/cl/7651045

変更の背景

このコミットの背景には、ソフトウェア開発における「flaky test(不安定なテスト)」という一般的な問題があります。Flaky testとは、コードの変更がないにもかかわらず、実行するたびに成功したり失敗したりするテストのことです。このようなテストは、CI/CDパイプラインの信頼性を損ない、開発者が実際のバグとテストの不安定さを区別するのを困難にします。

net/http パッケージの TestLinuxSendfile は、Linuxカーネルの sendfile システムコールを利用したファイル転送のテストです。sendfile は、ユーザー空間を介さずに直接カーネル空間でデータを転送するため、効率的なファイル転送を可能にします。このテストでは、strace というツールを使って、sendfile システムコールが実際に呼び出されていることを確認していました。

しかし、strace のデフォルトの出力が多すぎたり、テストの実行環境やタイミングによって余分な情報が出力されたりすることで、テストの検証ロジックが期待する出力を得られず、テストが不安定になっていたと考えられます。コミットメッセージにある「Update #5005」は、この不安定なテストに関する内部的な課題追跡番号である可能性が高いです。

前提知識の解説

1. Flaky Test (不安定なテスト)

Flaky testは、テストが非決定的な振る舞いを示す状態を指します。これは、テストが外部要因(ネットワークの遅延、ファイルシステムのI/O、並行処理のタイミング、環境変数、システムリソースなど)に依存している場合に発生しやすいです。Flaky testは、開発者がコードの品質を信頼することを妨げ、CI/CDパイプラインの効率を低下させます。

2. strace コマンド

strace はLinux/Unixシステムで利用される診断ツールです。プログラムが実行するシステムコールや、受け取るシグナルを追跡(トレース)し、その詳細な情報を標準エラー出力に表示します。これにより、プログラムがどのようにOSと対話しているかを理解するのに役立ちます。

  • -f: 子プロセスもトレースします。
  • -q: 冗長なメッセージを抑制し、より簡潔な出力を生成します。
  • -e trace=syscall: 特定のシステムコールのみをトレースします。例えば、-e trace=sendfile とすると sendfile システムコールのみを追跡します。

3. sendfile システムコール

sendfile は、Linuxカーネルが提供するシステムコールで、ファイルディスクリプタから別のファイルディスクリプタへデータを直接転送するために使用されます。特に、ネットワークソケットへのファイル転送において、ユーザー空間へのデータコピーを省略できるため、CPUオーバーヘッドを削減し、I/O性能を向上させることができます。Webサーバーなどで静的ファイルを配信する際によく利用されます。

4. Go言語のテストフレームワーク

Go言語には、標準で testing パッケージが提供されており、これを使ってユニットテストやベンチマークテストを記述します。テスト関数は TestXxx の形式で命名され、go test コマンドで実行されます。

技術的詳細

このコミットは、TestLinuxSendfile テスト内で strace コマンドを実行する際の引数を変更することで、テストの安定化を図っています。

元のコードでは、strace コマンドは以下の引数で実行されていました。 exec.Command("strace", "-f", os.Args[0], "-test.run=TestLinuxSendfileChild")

変更後のコードでは、以下の引数が追加されています。 exec.Command("strace", "-f", "-q", "-e", "trace=sendfile,sendfile64", os.Args[0], "-test.run=TestLinuxSendfileChild")

追加された引数の意味は以下の通りです。

  • -q: strace の冗長なメッセージ(例えば、プロセスのアタッチ/デタッチに関する情報など)を抑制します。これにより、テストが解析する出力がよりクリーンになり、不要な情報による誤判定を防ぎます。
  • -e trace=sendfile,sendfile64: strace が追跡するシステムコールを sendfilesendfile64 に限定します。これにより、テストが本当に確認したいシステムコールのみが出力されるようになり、他のシステムコールによるノイズが排除されます。sendfile64 は、大きなファイル(2GB以上)を扱うための sendfile の64ビット版です。

これらの変更により、strace の出力がより予測可能かつ簡潔になり、テストが sendfile システムコールの呼び出しを正確に検出できるようになります。結果として、テストの実行が環境やタイミングに左右されにくくなり、不安定さが解消されます。

コアとなるコードの変更箇所

src/pkg/net/http/fs_test.go ファイルの以下の行が変更されています。

--- a/src/pkg/net/http/fs_test.go
+++ b/src/pkg/net/http/fs_test.go
@@ -697,7 +697,7 @@ func TestLinuxSendfile(t *testing.T) {
 	defer ln.Close()
 
 	var buf bytes.Buffer
-	child := exec.Command("strace", "-f", os.Args[0], "-test.run=TestLinuxSendfileChild")
+	child := exec.Command("strace", "-f", "-q", "-e", "trace=sendfile,sendfile64", os.Args[0], "-test.run=TestLinuxSendfileChild")
 	child.ExtraFiles = append(child.ExtraFiles, lnf)
 	child.Env = append([]string{"GO_WANT_HELPER_PROCESS=1"}, os.Environ()...)
 	child.Stdout = &buf

コアとなるコードの解説

変更された行は、exec.Command 関数を使って strace コマンドを実行している部分です。

  • child := exec.Command(...): これは、新しいプロセスとして外部コマンド(この場合は strace)を実行するためのGoの標準ライブラリ関数です。
  • 変更前: exec.Command("strace", "-f", os.Args[0], "-test.run=TestLinuxSendfileChild")
    • strace: 実行するコマンド名。
    • -f: 子プロセスもトレースするオプション。
    • os.Args[0]: 現在実行中のGoテストバイナリのパス。これにより、strace はテストバイナリ自体をトレースします。
    • -test.run=TestLinuxSendfileChild: Goテストフレームワークのオプションで、TestLinuxSendfileChild という名前のテスト関数のみを実行するように指定しています。これは、TestLinuxSendfile テストが、strace でトレースされる子プロセスとして TestLinuxSendfileChild を実行する構造になっているためです。
  • 変更後: exec.Command("strace", "-f", "-q", "-e", "trace=sendfile,sendfile64", os.Args[0], "-test.run=TestLinuxSendfileChild")
    • -q: strace の出力を静かに(quietly)するオプション。これにより、不要な診断メッセージが抑制されます。
    • -e: strace がトレースするイベントを指定するオプション。
    • trace=sendfile,sendfile64: -e オプションの引数で、sendfilesendfile64 のシステムコールのみをトレースするように指定しています。

この変更により、strace の出力が最小限かつ関連性の高い情報に絞られ、TestLinuxSendfilesendfile システムコールの呼び出しをより確実に検出できるようになり、テストの不安定性が解消されました。

関連リンク

  • Go言語の net/http パッケージ: https://pkg.go.dev/net/http
  • strace のmanページ (Linux): man strace
  • sendfile システムコール (Linux): man sendfile

参考にした情報源リンク

  • Go言語の公式ドキュメント
  • strace コマンドのドキュメント
  • sendfile システムコールのドキュメント
  • 一般的なソフトウェアテストにおける「Flaky Test」に関する情報
  • GitHubのコミット履歴
  • Goのコードレビューシステム (Gerrit) のCL (Change-list) リンク: https://golang.org/cl/7651045 (ただし、このリンクは現在アクセスできない可能性があります。GoプロジェクトはGerritからGitHubに移行しています。)