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

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

このコミットは、Go言語のnetパッケージのテストにおいて、AndroidプラットフォームをLinuxと同様に扱うように変更するものです。具体的には、runtime.GOOSの値がandroidである場合に、特定のテストケースでlinuxと同じパスを通るように修正されています。これにより、Android環境でのテストの互換性と正確性が向上します。

コミット

commit 8b6dafa80eadf44a4854c5b0deca1f879e38eb73
Author: David Crawshaw <david.crawshaw@zentus.com>
Date:   Tue Jul 8 13:41:18 2014 -0400

    net: treat android like linux in tests
    
    LGTM=bradfitz
    R=golang-codereviews, bradfitz
    CC=golang-codereviews
    https://golang.org/cl/112810043

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

https://github.com/golang/go/commit/8b6dafa80eadf44a4854c5b0deca1f879e38eb73

元コミット内容

net: treat android like linux in tests

LGTM=bradfitz
R=golang-codereviews, bradfitz
CC=golang-codereviews
https://golang.org/cl/112810043

変更の背景

Go言語はクロスプラットフォーム対応を重視しており、様々なオペレーティングシステム(OS)で動作するように設計されています。Androidもそのターゲットの一つです。しかし、Goのテストスイートは、各OSの特性やシステムコールの振る舞いの違いを考慮して、特定のOSでのみスキップされたり、異なるロジックが適用されたりすることがあります。

このコミット以前は、netパッケージの一部のテストにおいて、AndroidがLinuxとは異なるOSとして扱われていました。しかし、AndroidはLinuxカーネルをベースにしており、ネットワーク関連の多くのシステムコールや振る舞いがLinuxと共通しています。そのため、Android環境でこれらのテストを実行する際に、Linuxでは成功するはずのテストがAndroidではスキップされたり、予期せぬ失敗をしたりする可能性がありました。

この変更の背景には、Android環境でのGoのテストカバレッジと正確性を向上させる目的があります。AndroidのネットワークスタックがLinuxと類似している部分については、テストもLinuxと同様に実行することで、より堅牢なテスト結果を得られるようになります。

前提知識の解説

runtime.GOOS

runtime.GOOSはGo言語の標準ライブラリruntimeパッケージで提供される定数で、Goプログラムがコンパイルされ、実行されるオペレーティングシステムの名前を表します。例えば、Linuxでは"linux"、macOSでは"darwin"、Windowsでは"windows"、そしてAndroidでは"android"という文字列が返されます。この定数を利用することで、OSに依存する処理を条件分岐させることができます。

Unixドメインソケット (unixpacket)

Unixドメインソケットは、同じホスト上のプロセス間通信(IPC)に使用されるソケットの一種です。ネットワークソケット(TCP/IPなど)とは異なり、ファイルシステム上のパス名(例: /tmp/mysocket)に関連付けられることが特徴です。unixpacketは、Unixドメインソケットの中でもデータグラム(パケット)指向の通信を提供するタイプです。これは、信頼性のある接続を確立するTCPのようなストリームソケットとは異なり、個々のデータグラムが独立して送受信されます。

/etc/servicesファイル

/etc/servicesは、Unix系OSにおいて、サービス名とポート番号のマッピングを定義するテキストファイルです。例えば、HTTPサービスがポート80を使用することなどが記述されています。Goのnetパッケージのテストでは、このファイルが存在するかどうか、またはその内容を読み取れるかどうかを検証するテストケースが存在することがあります。WindowsやPlan 9などのOSにはこのファイルが存在しないため、これらのOSでは関連するテストがスキップされることがあります。AndroidもLinuxカーネルベースですが、ファイルシステムの構造や特定のシステムファイルの有無はデスクトップLinuxとは異なる場合があります。

Unixドメインソケットのオートバインド機能 (@プレフィックス)

LinuxのUnixドメインソケットには、抽象名前空間(abstract namespace)という機能があります。これは、ファイルシステム上に実際のファイルを作成せずにソケットをバインドできる機能です。ソケットアドレスのパスが@で始まる場合、そのソケットは抽象名前空間にバインドされます。これにより、ファイルシステム上の名前衝突を避けたり、ソケットファイルの後処理(削除)が不要になったりする利点があります。この機能はLinux特有のものであり、他のUnix系OSではサポートされていない場合があります。

技術的詳細

このコミットは、Goのnetパッケージ内のテストファイルにおいて、runtime.GOOSの条件分岐に"android"を追加することで、Android環境でのテストの振る舞いをLinuxに合わせるものです。

具体的には、以下の4つのテストファイルが変更されています。

  1. src/pkg/net/conn_test.go:

    • unixpacketソケットのテストにおいて、これまで"darwin", "nacl", "openbsd", "plan9", "windows"でスキップされていたテストに、新たに"android"が追加されました。これは、AndroidもこれらのOSと同様にunixpacketソケットの特定のテストケースをスキップすべきであることを示唆しています。ただし、元のコードではcontinueでスキップされているため、Androidでもスキップされるようになります。
  2. src/pkg/net/multicast_test.go:

    • IPv4マルチキャストリスナーのテストにおいて、これまで"nacl", "plan9"でスキップされていたテストに、新たに"android"が追加されました。これは、Android環境ではマルチキャスト関連のテストが特定の理由(例えば、エミュレータの制限や特定のネットワーク設定)によりスキップされるべきであることを示しています。
  3. src/pkg/net/parse_test.go:

    • /etc/servicesファイルの読み取りテストにおいて、これまで"plan9", "windows"でスキップされていたテストに、新たに"android"が追加されました。これは、Android環境では/etc/servicesファイルが存在しないか、またはテストが期待する形式でアクセスできないため、このテストをスキップする必要があることを示しています。
  4. src/pkg/net/unix_test.go:

    • Unixドメインソケットのローカルおよびリモート名に関するテストにおいて、Linux特有のオートバインド機能(@プレフィックス)の処理がruntime.GOOS == "linux"からswitch runtime.GOOS { case "android", "linux": ... }に変更されました。これにより、Android環境でもLinuxと同様に、空のローカルアドレスが指定された場合にオートバインド機能が適用されるようになります。これは、AndroidのUnixドメインソケットの実装がLinuxのそれと非常に似ており、このオートバインド機能もサポートしていることを示唆しています。

これらの変更は、AndroidがLinuxカーネルをベースにしているという事実を反映し、GoのテストスイートがAndroid環境の特性をより正確に考慮するように調整されたものです。これにより、Android上でのGoアプリケーションのネットワーク機能の信頼性が向上し、開発者はより正確なテスト結果に基づいてコードを開発できるようになります。

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

src/pkg/net/conn_test.go

--- a/src/pkg/net/conn_test.go
+++ b/src/pkg/net/conn_test.go
@@ -38,7 +38,7 @@ func TestConnAndListener(t *testing.T) {
 		case "unixpacket":
 			switch runtime.GOOS {
-			case "darwin", "nacl", "openbsd", "plan9", "windows":
+			case "android", "darwin", "nacl", "openbsd", "plan9", "windows":
 				continue
 			case "freebsd": // FreeBSD 8 doesn't support unixpacket
 				continue

src/pkg/net/multicast_test.go

--- a/src/pkg/net/multicast_test.go
+++ b/src/pkg/net/multicast_test.go
@@ -25,7 +25,7 @@ var ipv4MulticastListenerTests = []struct {
 // port.
 func TestIPv4MulticastListener(t *testing.T) {
 	switch runtime.GOOS {
-	case "nacl", "plan9":
+	case "android", "nacl", "plan9":
 		t.Skipf("skipping test on %q", runtime.GOOS)
 	case "solaris":
 		t.Skipf("skipping test on solaris, see issue 7399")

src/pkg/net/parse_test.go

--- a/src/pkg/net/parse_test.go
+++ b/src/pkg/net/parse_test.go
@@ -12,9 +12,9 @@ import (
 )
 
 func TestReadLine(t *testing.T) {
-	// /etc/services file does not exist on windows and Plan 9.
+	// /etc/services file does not exist on android, plan9, windows.
 	switch runtime.GOOS {
-	case "plan9", "windows":
+	case "android", "plan9", "windows":
 		t.Skipf("skipping test on %q", runtime.GOOS)
 	}
 	filename := "/etc/services" // a nice big file

src/pkg/net/unix_test.go

--- a/src/pkg/net/unix_test.go
+++ b/src/pkg/net/unix_test.go
@@ -256,8 +256,11 @@ func TestUnixConnLocalAndRemoteNames(t *testing.T) {
 			t.Fatalf("UnixConn.Write failed: %v", err)
 		}
 
-		if runtime.GOOS == "linux" && laddr == "" {
-			laddr = "@" // autobind feature
+		switch runtime.GOOS {
+		case "android", "linux":
+			if laddr == "" {
+				laddr = "@" // autobind feature
+			}
 		}
 		var connAddrs = [3]struct{ got, want Addr }{
 			{ln.Addr(), ta},
@@ -308,9 +311,13 @@ func TestUnixgramConnLocalAndRemoteNames(t *testing.T) {
 			}
 		}()
 
-		if runtime.GOOS == "linux" && laddr == "" {
-			laddr = "@" // autobind feature
+		switch runtime.GOOS {
+		case "android", "linux":
+			if laddr == "" {
+				laddr = "@" // autobind feature
+			}
 		}
+
 		var connAddrs = [4]struct{ got, want Addr }{
 			{c1.LocalAddr(), ta},
 			{c1.RemoteAddr(), nil},

コアとなるコードの解説

src/pkg/net/conn_test.go および src/pkg/net/multicast_test.go

これらのファイルでは、runtime.GOOSswitch文のcase節に"android"が追加されています。これは、unixpacketソケットのテストやIPv4マルチキャストリスナーのテストが、Android環境では他の特定のOS(darwin, nacl, openbsd, plan9, windowsなど)と同様にスキップされるべきであることを示しています。これは、Androidのネットワークスタックの特性や、テスト環境の制約により、これらのテストがAndroidでは適切に実行できない、あるいは期待される結果が得られないためと考えられます。

src/pkg/net/parse_test.go

このファイルでは、/etc/servicesファイルの読み取りテストにおいて、runtime.GOOSswitch文のcase節に"android"が追加されています。これにより、Android環境でもPlan 9やWindowsと同様に、このテストがスキップされるようになります。AndroidはLinuxカーネルをベースにしていますが、ファイルシステムの構造や特定のシステムファイルの配置はデスクトップLinuxとは異なる場合があり、/etc/servicesファイルが存在しないか、テストが期待する形式でアクセスできない可能性があります。

src/pkg/net/unix_test.go

このファイルでは、Unixドメインソケットのオートバインド機能に関するロジックが変更されています。元々はif runtime.GOOS == "linux"という条件でLinuxのみに適用されていたオートバインド処理が、switch runtime.GOOS { case "android", "linux": ... }という形式に変更されました。

この変更は非常に重要です。これは、AndroidのUnixドメインソケットの実装がLinuxのそれと非常に類似しており、Linuxが提供する抽象名前空間のオートバインド機能(ソケットアドレスが@で始まる場合にファイルシステム上にファイルを作成せずにバインドする機能)をAndroidもサポートしていることを示唆しています。これにより、Android環境でもLinuxと同様に、空のローカルアドレスが指定された場合にソケットが自動的に抽象名前空間にバインドされ、テストが正しく動作するようになります。この変更は、AndroidがGoのネットワークスタックにおいて、よりLinuxに近い振る舞いをすることが期待されていることを明確に示しています。

全体として、これらの変更は、AndroidがGoのテストスイートにおいて、そのLinuxベースの性質をより正確に反映するように調整されたものであり、Android上でのGoアプリケーションのネットワーク機能の互換性と信頼性を高めることに貢献しています。

関連リンク

参考にした情報源リンク

  • Go言語 runtimeパッケージのドキュメント: https://pkg.go.dev/runtime
  • Unixドメインソケットに関する一般的な情報 (例: Wikipedia, man pages)
  • LinuxのUnixドメインソケットの抽象名前空間に関する情報 (例: man 7 unix)
  • AndroidのLinuxカーネルベースに関する情報 (例: Android Developersドキュメント)