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

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

このコミットは、Go言語のmisc/cgo/testtlsパッケージ内のテストtls.goを修正し、テストの信頼性(flakiness)を向上させることを目的としています。特に、ARMアーキテクチャ上でのスレッドローカルストレージ(TLS)の挙動に関する潜在的な問題を確実に検出できるように、テストの初期状態チェックを強化しています。

コミット

commit abd556ab70c652f480936540ed6598a3048c0669
Author: Russ Cox <rsc@golang.org>
Date:   Tue Jan 21 19:44:51 2014 -0500

    misc/cgo/testtls: make test less flaky
    
    Now it should always fail on ARM.
    (The fix is on its way too.)
    
    R=iant, r, dave
    CC=golang-codereviews
    https://golang.org/cl/55140043

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

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

元コミット内容

このコミットは、misc/cgo/testtls/tls.goファイルに対して以下の変更を加えています。

diff --git a/misc/cgo/testtls/tls.go b/misc/cgo/testtls/tls.go
index a9546a61c2..8e9ee70033 100644
--- a/misc/cgo/testtls/tls.go
+++ b/misc/cgo/testtls/tls.go
@@ -15,14 +15,16 @@ import (
 )
 
 func testTLS(t *testing.T) {
-	var keyVal C.int = 1234
-
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
-	C.setTLS(C.int(keyVal))
-	storedVal := C.getTLS()
-
-	if storedVal != keyVal {
-		t.Fatalf("stored %d want %d", storedVal, keyVal)
+
+	// 変更点1: テスト開始時にTLSが0であることを確認
+	if val := C.getTLS(); val != 0 {
+		t.Fatalf("at start, C.getTLS() = %#x, want 0", val)
+	}
+
+	// 変更点2: keyValを定数として定義し、設定後に値が一致するか確認
+	const keyVal = 0x1234
+	C.setTLS(keyVal)
+	if val := C.getTLS(); val != keyVal {
+		t.Fatalf("at end, C.getTLS() = %#x, want %#x", val, keyVal)
 	}
 }

変更の背景

このコミットの主な背景は、misc/cgo/testtlsパッケージ内のTLSテストが不安定(flaky)であったことです。特に、ARMアーキテクチャ上でこのテストが期待通りに失敗しない、つまりTLSの挙動に問題があるにもかかわらずテストがパスしてしまう可能性がありました。

テストの不安定性は、テストが実行されるたびに異なる結果を出す現象を指します。これは、テストの実行環境や以前のテストの残存状態に依存して結果が変わる場合に発生します。このTLSテストの場合、以前のテスト実行やシステムの状態がスレッドローカルストレージ(TLS)に予期せぬ値を残している可能性があり、それが原因でC.getTLS()が初期状態で非ゼロの値を返し、テストが誤って成功してしまうことが考えられます。

このコミットは、テストの開始時にTLSの値が確実にゼロであることを検証するステップを追加することで、この不安定性を解消しようとしています。これにより、テストは常にクリーンな状態から開始され、C.setTLSC.getTLSの機能が正しく動作しているかをより厳密にチェックできるようになります。

また、コミットメッセージにある「Now it should always fail on ARM. (The fix is on its way too.)」という記述は非常に重要です。これは、このテストがARMアーキテクチャにおけるTLSの実装上のバグを露呈させるために意図的に修正されたことを示唆しています。つまり、このコミットはバグを修正するものではなく、バグを確実に再現・検出するためのテスト強化であり、実際のバグ修正は別のコミットで行われる予定であることを示しています。

前提知識の解説

Cgo

Cgoは、GoプログラムからC言語のコードを呼び出すためのGoの機能です。Goはシステムプログラミング言語であり、既存のCライブラリやOSのAPIと連携する必要がある場面が多くあります。Cgoを使用することで、Goのコード内でCの関数を呼び出したり、Cのデータ構造を扱ったりすることが可能になります。

misc/cgo/testtlsパッケージは、Cgoを使用してスレッドローカルストレージ(TLS)を操作するテストを行っています。これは、GoのランタイムがCライブラリとどのように連携してTLSを管理しているかを検証する重要なテストです。

スレッドローカルストレージ (TLS: Thread Local Storage)

スレッドローカルストレージ(TLS)は、マルチスレッドプログラミングにおいて、各スレッドがそれぞれ独立したデータを保持するためのメカニズムです。通常、グローバル変数や静的変数はプロセス内のすべてのスレッドで共有されますが、TLSを使用すると、同じ変数名であっても各スレッドが独自のコピーを持つことができます。

TLSは、以下のような場面で利用されます。

  • スレッド固有の状態管理: 各スレッドが独自のコンテキストや状態を持つ必要がある場合(例: エラーコード、データベース接続、乱数生成器のシード)。
  • 再入可能性の確保: スレッドセーフでないライブラリ関数を、各スレッドが独立したデータで安全に呼び出せるようにする場合。

TLSの実装は、オペレーティングシステムやコンパイラに依存します。C言語では、pthread_key_create, pthread_setspecific, pthread_getspecificなどのPOSIXスレッドAPIや、コンパイラ拡張(例: GCCの__threadキーワード)が一般的に使用されます。GoのCgoを通じてCのTLS関数を呼び出す場合、GoのランタイムとCのランタイムがどのようにTLSを協調して管理するかが重要になります。

runtime.LockOSThread()runtime.UnlockOSThread()

Goのランタイムは、Goルーチン(goroutine)をOSスレッドに多重化して実行します。通常、Goルーチンは特定のOSスレッドに固定されず、Goスケジューラによって異なるOSスレッド上で実行される可能性があります。

runtime.LockOSThread()関数は、現在のGoルーチンを現在のOSスレッドに「ロック」します。つまり、そのGoルーチンはruntime.UnlockOSThread()が呼び出されるまで、そのOSスレッドから離れることができなくなります。これにより、Goルーチンが実行されている間、常に同じOSスレッド上で実行されることが保証されます。

この関数は、以下のような場合に特に重要です。

  • Cgoとの連携: C言語のライブラリがスレッドローカルストレージ(TLS)やOSスレッド固有のAPI(例: GUIライブラリ、OpenGLコンテキスト)を使用する場合、GoルーチンがOSスレッド間を移動すると問題が発生する可能性があります。LockOSThreadを使用することで、Cgo呼び出しが常に同じOSスレッド上で行われることを保証し、TLSなどのスレッド固有の状態が正しく維持されるようにします。
  • OSスレッドのプロパティ操作: OSスレッドの優先度設定やアフィニティ設定など、OSスレッド固有のプロパティを操作する場合。

このコミットのテストでは、runtime.LockOSThread()を使用することで、C.setTLSC.getTLSの呼び出しが常に同じOSスレッド上で行われることを保証し、TLSのテストがスレッドの移動によって影響を受けないようにしています。

ARMアーキテクチャ

ARM(Advanced RISC Machine)は、モバイルデバイスや組み込みシステムで広く使用されているCPUアーキテクチャです。x86アーキテクチャとは異なる命令セットやメモリモデルを持つため、低レベルのシステムプログラミングやランタイムの実装において、アーキテクチャ固有の考慮事項が必要になることがあります。

このコミットでARMが特に言及されているのは、GoのランタイムやCgoがARM上でTLSを扱う際に、x86など他のアーキテクチャとは異なる挙動やバグが存在する可能性があったためと考えられます。

技術的詳細

このコミットは、misc/cgo/testtls/tls.go内のtestTLS関数を修正しています。このテストは、Cgoを介してC言語で実装されたsetTLSgetTLS関数を呼び出し、スレッドローカルストレージ(TLS)の機能が正しく動作するかを検証します。

修正の核心は、テストの開始時にC.getTLS()が返す値が0であることを厳密にチェックする点にあります。

  1. 初期状態の保証:

    • 変更前: テストはkeyVal1234に設定し、その後にC.setTLSを呼び出し、C.getTLSで取得した値がkeyValと一致するかを検証していました。しかし、テストが実行される前にTLSに何らかの残存データがあった場合、そのデータが偶然1234であったり、setTLSが正しく機能していなくてもテストがパスしてしまう可能性がありました。
    • 変更後: if val := C.getTLS(); val != 0 { t.Fatalf(...) }という行が追加されました。これは、C.setTLSを呼び出す前に、TLSが初期状態でゼロであることを明示的に確認します。もしゼロでなければ、それはテスト環境がクリーンでないか、TLSの初期化に問題があることを示し、テストは失敗します。これにより、テストの再現性と信頼性が大幅に向上します。
  2. 定数の使用と値の明確化:

    • var keyVal C.int = 1234const keyVal = 0x1234に変更されました。0x1234という16進数の値は、デバッグ時にメモリダンプなどで識別しやすく、テスト用の「マジックナンバー」としてよく使われます。constにすることで、値が不変であることが明確になります。
  3. ARM固有の問題の検出: コミットメッセージにある「Now it should always fail on ARM.」という記述は、このテストの修正が、ARMアーキテクチャにおけるTLSの実装上のバグを確実に露呈させるためのものであることを示しています。つまり、このテストは、ARM上でのTLSの挙動が期待通りでない場合に、以前は不安定にパスしていたかもしれないが、今後は確実に失敗するように設計されています。これにより、開発者はARM固有のTLS問題を特定し、修正するための明確なシグナルを得ることができます。

この修正は、テストの堅牢性を高め、特定のアーキテクチャ(ARM)における潜在的なランタイムバグの検出を可能にするための、典型的なテスト駆動開発のアプローチと言えます。

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

変更はmisc/cgo/testtls/tls.goファイル内のtestTLS関数に集中しています。

 func testTLS(t *testing.T) {
-	var keyVal C.int = 1234
-
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
-	C.setTLS(C.int(keyVal))
-	storedVal := C.getTLS()
-
-	if storedVal != keyVal {
-		t.Fatalf("stored %d want %d", storedVal, keyVal)
+	if val := C.getTLS(); val != 0 {
+		t.Fatalf("at start, C.getTLS() = %#x, want 0", val)
+	}
+
+	const keyVal = 0x1234
+	C.setTLS(keyVal)
+	if val := C.getTLS(); val != keyVal {
+		t.Fatalf("at end, C.getTLS() = %#x, want %#x", val, keyVal)
 	}
 }

コアとなるコードの解説

  1. if val := C.getTLS(); val != 0 { ... }:

    • この行は、C.getTLS()関数を呼び出して現在のスレッドローカルストレージ(TLS)の値を取得し、それが0であるかどうかをチェックします。
    • もしval0でなければ、t.Fatalfが呼び出され、テストは失敗します。エラーメッセージには、取得された値(%#xで16進数表示)と期待される値0が表示されます。
    • このチェックにより、テストが常にクリーンなTLS状態から開始されることが保証され、以前のテスト実行やシステムの状態による影響を排除し、テストの不安定性を解消します。
  2. const keyVal = 0x1234:

    • 以前はvar keyVal C.int = 1234として定義されていたテスト用の値が、constキーワードを使用して0x1234という16進数の定数として再定義されました。
    • constにすることで、この値がテスト中に変更されないことが保証されます。また、0x1234という値は、デバッグ時に特定のテストデータとして識別しやすいという利点があります。
  3. C.setTLS(keyVal):

    • keyValで定義された値をTLSに設定するために、Cgoを介してC言語のsetTLS関数が呼び出されます。
  4. if val := C.getTLS(); val != keyVal { ... }:

    • C.setTLSで値を設定した後、再度C.getTLS()を呼び出してTLSから値を取得し、それがkeyValと一致するかを検証します。
    • もし一致しなければ、t.Fatalfが呼び出され、テストは失敗します。エラーメッセージには、取得された値と期待される値が表示されます。
    • このチェックは、setTLSgetTLSのペアが正しく機能していることを確認する主要なアサーションです。

これらの変更により、テストはより厳密になり、特にARMアーキテクチャのような特定の環境でTLSの挙動に問題がある場合に、その問題を確実に検出できるようになりました。

関連リンク

参考にした情報源リンク

  • Go言語のコミット履歴と関連するコードレビュー
  • Go言語の公式ドキュメント
  • スレッドローカルストレージに関する一般的な情報源 (例: Wikipedia, プログラミング関連の技術記事)
  • ARMアーキテクチャに関する一般的な情報源
  • Goのテストにおけるflakinessに関する議論 (一般的なソフトウェアテストのプラクティス)

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

このコミットは、Go言語のmisc/cgo/testtlsパッケージ内のテストtls.goを修正し、テストの信頼性(flakiness)を向上させることを目的としています。特に、ARMアーキテクチャ上でのスレッドローカルストレージ(TLS)の挙動に関する潜在的な問題を確実に検出できるように、テストの初期状態チェックを強化しています。

コミット

commit abd556ab70c652f480936540ed6598a3048c0669
Author: Russ Cox <rsc@golang.org>
Date:   Tue Jan 21 19:44:51 2014 -0500

    misc/cgo/testtls: make test less flaky
    
    Now it should always fail on ARM.
    (The fix is on its way too.)
    
    R=iant, r, dave
    CC=golang-codereviews
    https://golang.org/cl/55140043

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

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

元コミット内容

このコミットは、misc/cgo/testtls/tls.goファイルに対して以下の変更を加えています。

diff --git a/misc/cgo/testtls/tls.go b/misc/cgo/testtls/tls.go
index a9546a61c2..8e9ee70033 100644
--- a/misc/cgo/testtls/tls.go
+++ b/misc/cgo/testtls/tls.go
@@ -15,14 +15,16 @@ import (
 )
 
 func testTLS(t *testing.T) {
-	var keyVal C.int = 1234
-
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
-	C.setTLS(C.int(keyVal))
-	storedVal := C.getTLS()
-
-	if storedVal != keyVal {
-		t.Fatalf("stored %d want %d", storedVal, keyVal)
+
+	// 変更点1: テスト開始時にTLSが0であることを確認
+	if val := C.getTLS(); val != 0 {
+		t.Fatalf("at start, C.getTLS() = %#x, want 0", val)
+	}
+
+	// 変更点2: keyValを定数として定義し、設定後に値が一致するか確認
+	const keyVal = 0x1234
+	C.setTLS(keyVal)
+	if val := C.getTLS(); val != keyVal {
+		t.Fatalf("at end, C.getTLS() = %#x, want %#x", val, keyVal)
 	}
 }

変更の背景

このコミットの主な背景は、misc/cgo/testtlsパッケージ内のTLSテストが不安定(flaky)であったことです。特に、ARMアーキテクチャ上でこのテストが期待通りに失敗しない、つまりTLSの挙動に問題があるにもかかわらずテストがパスしてしまう可能性がありました。

テストの不安定性は、テストが実行されるたびに異なる結果を出す現象を指します。これは、テストの実行環境や以前のテストの残存状態に依存して結果が変わる場合に発生します。このTLSテストの場合、以前のテスト実行やシステムの状態がスレッドローカルストレージ(TLS)に予期せぬ値を残している可能性があり、それが原因でC.getTLS()が初期状態で非ゼロの値を返し、テストが誤って成功してしまうことが考えられます。

このコミットは、テストの開始時にTLSの値が確実にゼロであることを検証するステップを追加することで、この不安定性を解消しようとしています。これにより、テストは常にクリーンな状態から開始され、C.setTLSC.getTLSの機能が正しく動作しているかをより厳密にチェックできるようになります。

また、コミットメッセージにある「Now it should always fail on ARM. (The fix is on its way too.)」という記述は非常に重要です。これは、このテストがARMアーキテクチャにおけるTLSの実装上のバグを露呈させるために意図的に修正されたことを示唆しています。つまり、このコミットはバグを修正するものではなく、バグを確実に再現・検出するためのテスト強化であり、実際のバグ修正は別のコミットで行われる予定であることを示しています。

前提知識の解説

Cgo

Cgoは、GoプログラムからC言語のコードを呼び出すためのGoの機能です。Goはシステムプログラミング言語であり、既存のCライブラリやOSのAPIと連携する必要がある場面が多くあります。Cgoを使用することで、Goのコード内でCの関数を呼び出したり、Cのデータ構造を扱ったりすることが可能になります。

misc/cgo/testtlsパッケージは、Cgoを使用してスレッドローカルストレージ(TLS)を操作するテストを行っています。これは、GoのランタイムがCライブラリとどのように連携してTLSを管理しているかを検証する重要なテストです。

スレッドローカルストレージ (TLS: Thread Local Storage)

スレッドローカルストレージ(TLS)は、マルチスレッドプログラミングにおいて、各スレッドがそれぞれ独立したデータを保持するためのメカニズムです。通常、グローバル変数や静的変数はプロセス内のすべてのスレッドで共有されますが、TLSを使用すると、同じ変数名であっても各スレッドが独自のコピーを持つことができます。

TLSは、以下のような場面で利用されます。

  • スレッド固有の状態管理: 各スレッドが独自のコンテキストや状態を持つ必要がある場合(例: エラーコード、データベース接続、乱数生成器のシード)。
  • 再入可能性の確保: スレッドセーフでないライブラリ関数を、各スレッドが独立したデータで安全に呼び出せるようにする場合。

TLSの実装は、オペレーティングシステムやコンパイラに依存します。C言語では、pthread_key_create, pthread_setspecific, pthread_getspecificなどのPOSIXスレッドAPIや、コンパイラ拡張(例: GCCの__threadキーワード)が一般的に使用されます。GoのCgoを通じてCのTLS関数を呼び出す場合、GoのランタイムとCのランタイムがどのようにTLSを協調して管理するかが重要になります。

runtime.LockOSThread()runtime.UnlockOSThread()

Goのランタイムは、Goルーチン(goroutine)をOSスレッドに多重化して実行します。通常、Goルーチンは特定のOSスレッドに固定されず、Goスケジューラによって異なるOSスレッド上で実行される可能性があります。

runtime.LockOSThread()関数は、現在のGoルーチンを現在のOSスレッドに「ロック」します。つまり、そのGoルーチンはruntime.UnlockOSThread()が呼び出されるまで、そのOSスレッドから離れることができなくなります。これにより、Goルーチンが実行されている間、常に同じOSスレッド上で実行されることが保証されます。

この関数は、以下のような場合に特に重要です。

  • Cgoとの連携: C言語のライブラリがスレッドローカルストレージ(TLS)やOSスレッド固有のAPI(例: GUIライブラリ、OpenGLコンテキスト)を使用する場合、GoルーチンがOSスレッド間を移動すると問題が発生する可能性があります。LockOSThreadを使用することで、Cgo呼び出しが常に同じOSスレッド上で行われることを保証し、TLSなどのスレッド固有の状態が正しく維持されるようにします。
  • OSスレッドのプロパティ操作: OSスレッドの優先度設定やアフィニティ設定など、OSスレッド固有のプロパティを操作する場合。

このコミットのテストでは、runtime.LockOSThread()を使用することで、C.setTLSC.getTLSの呼び出しが常に同じOSスレッド上で行われることを保証し、TLSのテストがスレッドの移動によって影響を受けないようにしています。

ARMアーキテクチャ

ARM(Advanced RISC Machine)は、モバイルデバイスや組み込みシステムで広く使用されているCPUアーキテクチャです。x86アーキテクチャとは異なる命令セットやメモリモデルを持つため、低レベルのシステムプログラミングやランタイムの実装において、アーキテクチャ固有の考慮事項が必要になることがあります。

このコミットでARMが特に言及されているのは、GoのランタイムやCgoがARM上でTLSを扱う際に、x86など他のアーキテクチャとは異なる挙動やバグが存在する可能性があったためと考えられます。

技術的詳細

このコミットは、misc/cgo/testtls/tls.go内のtestTLS関数を修正しています。このテストは、Cgoを介してC言語で実装されたsetTLSgetTLS関数を呼び出し、スレッドローカルストレージ(TLS)の機能が正しく動作するかを検証します。

修正の核心は、テストの開始時にC.getTLS()が返す値が0であることを厳密にチェックする点にあります。

  1. 初期状態の保証:

    • 変更前: テストはkeyVal1234に設定し、その後にC.setTLSを呼び出し、C.getTLSで取得した値がkeyValと一致するかを検証していました。しかし、テストが実行される前にTLSに何らかの残存データがあった場合、そのデータが偶然1234であったり、setTLSが正しく機能していなくてもテストがパスしてしまう可能性がありました。
    • 変更後: if val := C.getTLS(); val != 0 { t.Fatalf(...) }という行が追加されました。これは、C.setTLSを呼び出す前に、TLSが初期状態でゼロであることを明示的に確認します。もしゼロでなければ、それはテスト環境がクリーンでないか、TLSの初期化に問題があることを示し、テストは失敗します。これにより、テストの再現性と信頼性が大幅に向上します。
  2. 定数の使用と値の明確化:

    • var keyVal C.int = 1234const keyVal = 0x1234に変更されました。0x1234という16進数の値は、デバッグ時にメモリダンプなどで識別しやすく、テスト用の「マジックナンバー」としてよく使われます。constにすることで、値が不変であることが明確になります。
  3. ARM固有の問題の検出: コミットメッセージにある「Now it should always fail on ARM.」という記述は、このテストの修正が、ARMアーキテクチャにおけるTLSの実装上のバグを確実に露呈させるためのものであることを示しています。つまり、このテストは、ARM上でのTLSの挙動が期待通りでない場合に、以前は不安定にパスしていたかもしれないが、今後は確実に失敗するように設計されています。これにより、開発者はARM固有のTLS問題を特定し、修正するための明確なシグナルを得ることができます。

この修正は、テストの堅牢性を高め、特定のアーキテクチャ(ARM)における潜在的なランタイムバグの検出を可能にするための、典型的なテスト駆動開発のアプローチと言えます。

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

変更はmisc/cgo/testtls/tls.goファイル内のtestTLS関数に集中しています。

 func testTLS(t *testing.T) {
-	var keyVal C.int = 1234
-
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
-	C.setTLS(C.int(keyVal))
-	storedVal := C.getTLS()
-
-	if storedVal != keyVal {
-		t.Fatalf("stored %d want %d", storedVal, keyVal)
+	if val := C.getTLS(); val != 0 {
+		t.Fatalf("at start, C.getTLS() = %#x, want 0", val)
+	}
+
+	const keyVal = 0x1234
+	C.setTLS(keyVal)
+	if val := C.getTLS(); val != keyVal {
+		t.Fatalf("at end, C.getTLS() = %#x, want %#x", val, keyVal)
 	}
 }

コアとなるコードの解説

  1. if val := C.getTLS(); val != 0 { ... }:

    • この行は、C.getTLS()関数を呼び出して現在のスレッドローカルストレージ(TLS)の値を取得し、それが0であるかどうかをチェックします。
    • もしval0でなければ、t.Fatalfが呼び出され、テストは失敗します。エラーメッセージには、取得された値(%#xで16進数表示)と期待される値0が表示されます。
    • このチェックにより、テストが常にクリーンなTLS状態から開始されることが保証され、以前のテスト実行やシステムの状態による影響を排除し、テストの不安定性を解消します。
  2. const keyVal = 0x1234:

    • 以前はvar keyVal C.int = 1234として定義されていたテスト用の値が、constキーワードを使用して0x1234という16進数の定数として再定義されました。
    • constにすることで、この値がテスト中に変更されないことが保証されます。また、0x1234という値は、デバッグ時に特定のテストデータとして識別しやすいという利点があります。
  3. C.setTLS(keyVal):

    • keyValで定義された値をTLSに設定するために、Cgoを介してC言語のsetTLS関数が呼び出されます。
  4. if val := C.getTLS(); val != keyVal { ... }:

    • C.setTLSで値を設定した後、再度C.getTLS()を呼び出してTLSから値を取得し、それがkeyValと一致するかを検証します。
    • もし一致しなければ、t.Fatalfが呼び出され、テストは失敗します。エラーメッセージには、取得された値と期待される値が表示されます。
    • このチェックは、setTLSgetTLSのペアが正しく機能していることを確認する主要なアサーションです。

これらの変更により、テストはより厳密になり、特にARMアーキテクチャのような特定の環境でTLSの挙動に問題がある場合に、その問題を確実に検出できるようになりました。

関連リンク

参考にした情報源リンク

  • Go言語のコミット履歴と関連するコードレビュー
  • Go言語の公式ドキュメント
  • スレッドローカルストレージに関する一般的な情報源 (例: Wikipedia, プログラミング関連の技術記事)
  • ARMアーキテクチャに関する一般的な情報源
  • Goのテストにおけるflakinessに関する議論 (一般的なソフトウェアテストのプラクティス)