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

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

このコミットは、Go言語の標準ライブラリであるlog/syslogパッケージのテストコードにおける改善を目的としています。具体的には、unixおよびunixgramソケットを使用するテストケースにおいて、テスト実行後に作成されたソケットファイルを確実に削除する処理を追加しています。これにより、テスト実行環境のクリーンアップを徹底し、テストの再現性と安定性を向上させています。

コミット

  • コミットハッシュ: 705b4544d61fb103a5900e6c099b3c7aafeb91f7
  • 作者: Shenghou Ma minux.ma@gmail.com
  • コミット日時: 2013年2月9日 土曜日 08:19:09 +0800

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

https://github.com/golang/go/commit/705b4544d61fb103a5900e6c099b3c7aafeb91f7

元コミット内容

log/syslog: remove socket files after tests

R=golang-dev, iant
CC=golang-dev
https://golang.org/cl/7305065

変更の背景

Go言語のlog/syslogパッケージは、システムログデーモン(syslogd)へのメッセージ送信機能を提供します。このパッケージのテストでは、unixドメインソケットやunixgramソケットを使用して、syslogdの動作をシミュレートするサーバーを起動することがあります。これらのソケットは、ファイルシステム上に特殊なファイル(ソケットファイル)として作成されます。

このコミットが導入される以前は、これらのテストが終了した後も、作成されたソケットファイルがファイルシステム上に残ってしまう可能性がありました。ソケットファイルが残存すると、以下のような問題が発生する可能性があります。

  1. ディスクスペースの消費: 多数のテストが繰り返し実行される環境では、不要なソケットファイルが蓄積され、ディスクスペースを消費する可能性があります。
  2. テストの不安定性: 次のテスト実行時に、以前のテストが残したソケットファイルが予期せぬ干渉を引き起こし、テストが失敗する原因となる可能性があります。例えば、同じパスにソケットを作成しようとした際に、ファイルが既に存在するためにエラーとなる、といったケースが考えられます。
  3. クリーンなテスト環境の維持: テストは、毎回クリーンな状態で実行されることが理想です。これにより、テスト結果が他のテストや以前の実行の影響を受けず、信頼性が高まります。

このコミットは、これらの問題を解決し、テストの健全性と信頼性を向上させるために、テスト終了後のソケットファイルの自動削除を導入しました。

前提知識の解説

Go言語のlog/syslogパッケージ

log/syslogパッケージは、GoプログラムからUNIX系システムで広く使われているsyslogプロトコルを通じてログメッセージを送信するための機能を提供します。このパッケージは、TCP、UDP、UNIXドメインソケットなど、様々なネットワークプロトコルを介してsyslogデーモンと通信できます。

UNIXドメインソケット (unix, unixgram)

UNIXドメインソケットは、同じホスト上のプロセス間通信(IPC)メカニズムの一つです。TCP/IPソケットがネットワークを介した通信に使用されるのに対し、UNIXドメインソケットはファイルシステム上のパス名に関連付けられ、ファイルとして表現されます。

  • unix (ストリームソケット): TCPソケットに似ており、信頼性の高い、接続指向のバイトストリーム通信を提供します。
  • unixgram (データグラムソケット): UDPソケットに似ており、信頼性の低い、コネクションレスのデータグラム通信を提供します。

これらのソケットは、ファイルシステム上に実体を持つため、テストなどで一時的に作成された場合、明示的に削除しないと残存してしまいます。

Go言語のdeferキーワード

deferステートメントは、Go言語の非常に強力な機能の一つです。deferに続く関数呼び出しは、その関数がリターンする直前(パニックが発生した場合も含む)に実行されることを保証します。これは、リソースのクリーンアップ(ファイルのクローズ、ロックの解放、ソケットファイルの削除など)を確実に行うために非常に便利です。

deferはLIFO(Last-In, First-Out)順で実行されます。つまり、複数のdeferステートメントがある場合、最後に登録されたものが最初に実行されます。

os.Remove関数

Go言語のosパッケージは、オペレーティングシステムとのインタラクションのための機能を提供します。os.Remove(name string)関数は、指定されたパスのファイルまたは空のディレクトリを削除するために使用されます。このコミットでは、テストによって作成されたソケットファイルを削除するためにこの関数が利用されています。

技術的詳細

このコミットの主要な変更は、src/pkg/log/syslog/syslog_test.goファイル内のテスト関数にdefer os.Remove(addr)という行を追加することです。

startServer関数は、テストのために一時的なsyslogサーバーを起動し、そのサーバーがリッスンしているアドレス(addr)を返します。unixまたはunixgramトランスポートを使用する場合、このaddrはファイルシステム上のソケットファイルのパスになります。

追加されたdefer os.Remove(addr)は、以下のメカニズムで機能します。

  1. 条件付き削除: TestWithSimulated関数内では、if tr == "unix" || tr == "unixgram"という条件文が追加されています。これは、unixまたはunixgramソケットを使用する場合にのみ、ソケットファイルの削除処理をスケジュールすることを意味します。TCPやUDPなどのネットワークソケットはファイルシステム上に実体を持たないため、削除の必要がありません。
  2. deferによる確実な実行: deferキーワードを使用することで、TestWithSimulatedTestFlapTestConcurrentReconnectといったテスト関数が正常に終了するか、あるいはパニックによって異常終了するかにかかわらず、os.Remove(addr)が確実に呼び出されることが保証されます。これにより、テストがどのように終了しても、一時的なソケットファイルが残存するのを防ぎます。
  3. アドレスの利用: addr変数はstartServer関数から返されるソケットファイルのパスであり、os.Removeはこのパスを使用して正確なファイルを削除します。

この変更により、各テストケースが終了するたびに、そのテストが作成した一時的なソケットファイルが自動的にクリーンアップされ、ファイルシステムの汚染を防ぎ、テストの独立性と信頼性が向上します。

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

変更はsrc/pkg/log/syslog/syslog_test.goファイルに集中しています。

--- a/src/pkg/log/syslog/syslog_test.go
+++ b/src/pkg/log/syslog/syslog_test.go
@@ -110,6 +110,9 @@ func TestWithSimulated(t *testing.T) {
 	for _, tr := range transport {
 		done := make(chan string)
 		addr := startServer(tr, "", done)
+		if tr == "unix" || tr == "unixgram" {
+			defer os.Remove(addr)
+		}
 		s, err := Dial(tr, addr, LOG_INFO|LOG_USER, "syslog_test")
 		if err != nil {
 			t.Fatalf("Dial() failed: %v", err)
@@ -127,6 +130,7 @@ func TestFlap(t *testing.T) {
 	net := "unix"
 	done := make(chan string)
 	addr := startServer(net, "", done)
+	defer os.Remove(addr)
 
 	s, err := Dial(net, addr, LOG_INFO|LOG_USER, "syslog_test")
 	if err != nil {
@@ -278,6 +282,7 @@ func TestConcurrentReconnect(t *testing.T) {
 	net := "unix"
 	done := make(chan string)
 	addr := startServer(net, "", done)
+	defer os.Remove(addr)
 
 	// count all the messages arriving
 	count := make(chan int)

コアとなるコードの解説

TestWithSimulated関数内の変更

		addr := startServer(tr, "", done)
		if tr == "unix" || tr == "unixgram" {
			defer os.Remove(addr)
		}

この部分では、startServerが返すaddr(サーバーのアドレス)が、unixまたはunixgramトランスポートの場合にのみ、os.Remove(addr)deferしています。これは、これらのトランスポートがファイルシステム上にソケットファイルを作成するため、テスト終了後にそのファイルを削除する必要があるからです。他のトランスポート(例: tcp, udp)はファイルを作成しないため、このクリーンアップは不要です。

TestFlap関数内の変更

	net := "unix"
	done := make(chan string)
	addr := startServer(net, "", done)
	defer os.Remove(addr)

TestFlap関数はunixトランスポートを明示的に使用しているため、条件分岐なしで直接defer os.Remove(addr)が追加されています。これにより、このテストが作成するunixソケットファイルが確実に削除されます。

TestConcurrentReconnect関数内の変更

	net := "unix"
	done := make(chan string)
	addr := startServer(net, "", done)
	defer os.Remove(addr)

TestConcurrentReconnect関数もunixトランスポートを明示的に使用しており、TestFlapと同様に、条件分岐なしでdefer os.Remove(addr)が追加されています。これにより、このテストが作成するunixソケットファイルも確実に削除されます。

これらの変更は、Goのdeferメカニズムを効果的に利用し、テストの実行がどのように終了しても、一時的なソケットファイルがファイルシステム上に残らないようにすることで、テスト環境のクリーンアップとテストの信頼性を大幅に向上させています。

関連リンク

参考にした情報源リンク

特になし。提供されたコミット情報とGo言語の一般的な知識に基づいています。