# テスト方針書

## 概要

本ドキュメントは、libuv（非同期I/Oライブラリ）プロジェクトのテスト方針を定義する。libuvは完全自前実装のテストフレームワークを採用し、プロセス分離型のテスト実行モデルにより、各テストの独立性と堅牢性を確保している。テスト結果はTAP（Test Anything Protocol）形式で出力され、CI/CDパイプラインとの統合を実現している。

## テスト戦略

### テストレベル

| レベル | 目的 | 担当 |
| --- | --- | --- |
| 単体テスト | libuv APIの各機能（TCP/UDP/FS/タイマー/スレッド等）が仕様通りに動作することを個別に検証する。各テストは別プロセスで実行され、テスト間の干渉を排除する。 | 開発者 |
| 結合テスト | 複数のlibuv機能を組み合わせた動作（例：IPC経由のハンドル受け渡し、イベントループとタイマーの連携）を検証する。ヘルパーサーバー（echo-server等）との通信テストを含む。 | 開発者 |
| システムテスト | クロスプラットフォーム（Linux/macOS/Windows/16アーキテクチャのQEMUエミュレーション）での動作検証、サニタイザー（ASAN/MSAN/TSAN/UBSAN）による品質検査、Linux固有のio_uringバックエンドの二重検証を行う。 | CI/CD自動実行 |
| 受入テスト | libuvの公開API互換性と、アプリケーション統合サンプル（`docs/code/` 配下のサンプルコード）のビルド検証を行う。 | CI/CD自動実行（CI-sample.yml） |

### テスト種別

| 種別 | 概要 | 実施タイミング |
| --- | --- | --- |
| 機能テスト | 178ファイルの `test-*.c` により、TCP/UDP/FS/パイプ/タイマー/スレッド/プロセス/DNS/TTY/IPC/Poll等の全APIカテゴリをカバーする。テスト登録は `test-list.h` で一元管理される。 | 全CI実行時（push/pull request） |
| 性能テスト | 18ファイルの `benchmark-*.c` により、TCP ping-pong レイテンシ、100万async/タイマーハンドル生成、大量接続、スレッドプール throughput等を計測する。タイムアウトは60秒。 | `uv_run_benchmarks` コマンドによる明示的実行 |
| セキュリティテスト | AddressSanitizer（ASAN）によるメモリ破壊検出、MemorySanitizer（MSAN）による未初期化メモリ検出、ThreadSanitizer（TSAN）によるデータ競合検出、UndefinedBehaviorSanitizer（UBSAN）による未定義動作検出を実施する。 | 専用CIワークフロー（sanitizer.yml）で全push/PR時に実行 |
| 静的解析テスト | clang-tidyによる静的コード解析（`tidy-src`, `tidy-test`, `tidy` ターゲット）を実施する。 | CMakeの `tidy` ターゲット実行時 |

## テスト環境

| 環境 | 用途 | 構成 |
| --- | --- | --- |
| Linux (glibc) | Tier 1 メインCI環境 | ubuntu-latest（GitHub Actions）、Autotools + CMake + Ninja |
| macOS | Tier 1 CI環境 | macos-14/15/15-intel（GitHub Actions）、CMake + Ninja、macOS 15ではsudo + `UV_RUN_AS_ROOT=1` |
| Windows | Tier 1 CI環境 | windows-2022/2025（GitHub Actions）、Visual Studio 17 2022（Win32/x64/ARM64）、MinGW（i686/x86_64） |
| Android | Tier 3 CI環境 | ubuntu-latest + Androidエミュレーター（API 30, x86_64）、`UV_TEST_TIMEOUT_MULTIPLIER=5` |
| iOS | クロスコンパイル確認 | macos-14/15、ビルドのみ（テスト実行なし、fork/execve不可のため） |
| QEMU クロスコンパイル | 16アーキテクチャ検証 | ubuntu-24.04 + QEMU（arm/armhf/aarch64/riscv64/ppc/ppc64/ppc64le/s390x/mips/mips64/mipsel/mips64el + u64 slots変種） |
| サニタイザー環境 | メモリ安全性・スレッド安全性検証 | Linux (ubuntu-22.04) + macOS (macos-14) + Windows (windows-2022)、ASAN/MSAN/TSAN/UBSAN |

## テストツール

| ツール | 用途 | バージョン |
| --- | --- | --- |
| 自前テストフレームワーク（task.h / runner.h / runner.c） | テスト定義・アサーション・テスト実行管理。TAP形式で結果出力。プロセス分離型でテスト間干渉を排除。 | libuv同梱（バージョン管理なし） |
| CMake / CTest | ビルドシステム・テスト統合。`uv_test` / `uv_test_a` として登録。`ctest -V` で実行。 | CMake 3.10以上 |
| Autotools (autoconf/automake) | Linux向け代替ビルドシステム。`make check` / `make distcheck` でテスト実行。 | autoconf 2.69以上 |
| Valgrind | メモリリーク・不正メモリアクセス検出。`UV_USE_VALGRIND=1` で有効化。`--leak-check=full --show-reachable=yes` | 外部インストール |
| AddressSanitizer (ASAN) | ヒープ/スタックバッファオーバーフロー、use-after-free等の検出 | Clang/GCC 同梱 |
| MemorySanitizer (MSAN) | 未初期化メモリの読み取り検出（Clang専用） | Clang 同梱 |
| ThreadSanitizer (TSAN) | データ競合・デッドロック検出。`tsansupp.txt` で既知の誤検知を抑制。 | Clang/GCC 同梱 |
| UndefinedBehaviorSanitizer (UBSAN) | 未定義動作（符号付き整数オーバーフロー、ゼロ除算等）の検出 | Clang/GCC 同梱 |
| clang-tidy | 静的コード解析。ソースファイルとテストファイルに分けて実行可能。 | Clang 同梱 |
| GitHub Actions | CI/CDパイプライン。4つのワークフロー（CI-unix/CI-win/sanitizer/CI-sample）で自動実行。 | GitHub提供 |

## カバレッジ目標

| 対象 | 目標値 |
| --- | --- |
| 行カバレッジ | 明示的な数値目標は設定されていない。ただし、178ファイルの機能テストにより全APIカテゴリを網羅的にカバーしている。 |
| 分岐カバレッジ | 明示的な数値目標は設定されていない。Linux環境ではio_uring版テストの二重実行により、バックエンド分岐のカバレッジを強化している。 |

**補足**: CMakeLists.txtおよびCIワークフローに`--coverage`フラグや`gcov`/`lcov`等のカバレッジ計測ツール統合は存在しない。品質保証はサニタイザー（ASAN/MSAN/TSAN/UBSAN）、Valgrind、16アーキテクチャのクロスコンパイル検証、静的解析（clang-tidy）の組み合わせにより実現されている。

## テストデータ

テストデータは `test/fixtures/` ディレクトリに静的ファイルとして配置されている。

| ファイル | 用途 |
| --- | --- |
| `empty_file` | サイズ0のファイル操作テスト |
| `lorem_ipsum.txt` | テキストファイルの読み書きテスト |
| `load_error.node` | `uv_dlopen()` のロード失敗テスト（意図的に不正なバイナリ） |
| `one_file/one_file` | `uv_fs_scandir()` のディレクトリ走査テスト（1ファイルのみ含むディレクトリ） |

また、ネットワーク系テストではヘルパーサーバー（`echo-server.c`, `blackhole-server.c`）を別プロセスで起動し、テスト用の通信相手として使用する。

| ヘルパー | 用途 |
| --- | --- |
| `tcp4_echo_server` / `tcp6_echo_server` | TCP IPv4/IPv6 エコーサーバー（送受信データの正確性検証） |
| `udp4_echo_server` | UDP IPv4 エコーサーバー |
| `pipe_echo_server` | Named Pipe エコーサーバー |
| `tcp4_blackhole_server` | データ廃棄サーバー（ベンチマーク用 throughput計測） |

ヘルパーサーバーの起動完了は、`UV_TEST_RUNNER_FD` 環境変数で渡されたファイルディスクリプタのclose通知により、テストドライバーに伝達される。

## 不具合管理

不具合管理にはGitHub Issuesを使用する。テスト失敗時の情報収集方法は以下の通り。

- **TAP出力による失敗記録**: テストランナーが `not ok N - test_name # exit code X` 形式で失敗を記録し、CI/CDのログに保存される。
- **アサーション失敗の詳細情報**: `task.h` のアサーションマクロは失敗時にファイル名・行番号・実際の値を `stderr` に出力する（例: `Assertion failed in test-timer.c on line 42: 'count == 5' (3 == 5)`）。
- **プラットフォーム条件付きスキップ**: サポートされない機能はプラットフォーム検出マクロ（`NO_FS_EVENTS`, `NO_CPU_AFFINITY`等）により `RETURN_SKIP()` でスキップされ、TAP出力で `# SKIP` として記録される。
- **タイムアウト検知**: テストランナーがデフォルト5秒（ベンチマーク60秒）のタイムアウトを管理し、無応答テストを `SIGTERM` で終了させる。`UV_TEST_TIMEOUT_MULTIPLIER` 環境変数で低速環境向けに倍率調整が可能。

## CI/CD連携

### ワークフロー一覧

| ワークフロー | ファイル | トリガー | 用途 |
| --- | --- | --- | --- |
| CI-unix | `.github/workflows/CI-unix.yml` | push / pull_request | Linux/macOS/iOS/Android/QEMU 16アーキテクチャでのビルド・テスト |
| CI-win | `.github/workflows/CI-win.yml` | push / pull_request | Windows（VS2022 Win32/x64/ARM64 + MinGW i686/x86_64）でのビルド・テスト |
| Sanitizer | `.github/workflows/sanitizer.yml` | push / pull_request | ASAN/MSAN/TSAN/UBSANによるメモリ・スレッド安全性検査（Linux/macOS/Windows） |
| CI-sample | `.github/workflows/CI-sample.yml` | push / pull_request | ドキュメントコードサンプルのビルド検証 |

### CI実行フロー

```
push / pull_request
 ├── CI-unix.yml
 │    ├── build-linux: autogen.sh → configure → make distcheck
 │    ├── build-android: CMake → NDK → Androidエミュレーター実行
 │    ├── build-macos: CMake + Ninja → ctest -V
 │    ├── build-ios: CMake クロスコンパイル（テスト実行なし）
 │    └── build-cross-qemu: CMake + クロスコンパイラ → QEMU実行（16アーキテクチャ）
 ├── CI-win.yml
 │    ├── VS2022 Win32/x64/ARM64: CMake → msbuild → ctest -V
 │    ├── VS2022 x64 ASAN/UBSAN: サニタイザー付きビルド → ctest -V
 │    └── MinGW: クロスビルド → Windowsランナーでテスト実行
 ├── sanitizer.yml
 │    ├── Linux: ASAN/MSAN/TSAN/UBSAN各ビルド → ctest -V
 │    ├── macOS: ASAN/TSAN/UBSAN各ビルド → ctest -V
 │    └── Windows: UBSAN（LLVM/Clang 17） → ctest -V
 └── CI-sample.yml
      └── docs/code/サンプルのビルド検証
```

### テスト実行コマンド

| ビルドシステム | テスト実行コマンド |
| --- | --- |
| CMake + CTest | `cd build && ctest -V` |
| Autotools | `make check` / `make distcheck` |
| 直接実行 | `./uv_run_tests` (動的リンク) / `./uv_run_tests_a` (静的リンク) |
| 特定テスト実行 | `./uv_run_tests test_name` |
| ベンチマーク | `./uv_run_benchmarks` |

### 環境変数による制御

| 環境変数 | 用途 |
| --- | --- |
| `UV_TEST_TIMEOUT_MULTIPLIER` | テストタイムアウト倍率（低速環境向け。Android CIでは`5`を設定） |
| `UV_USE_VALGRIND=1` | Valgrind経由でのテスト実行を有効化 |
| `UV_RUN_AS_ROOT=1` | root権限でのテスト実行を許可（macOS 15 CIで使用） |
| `UV_USE_IO_URING=1` | Linuxでio_uringバックエンドを強制使用 |
| `TSAN_OPTIONS` | ThreadSanitizer抑制ファイル指定（`suppressions=$PWD/tsansupp.txt`） |

## 備考

### テストフレームワークの設計思想

libuvのテストフレームワークは以下の設計原則に基づいている。

1. **プロセス分離**: 各テストを別プロセスとして `fork()/execve()` で起動することで、テスト間の状態汚染を完全に排除する。テストのクラッシュや無限ループがテストスイート全体に影響しない。

2. **ゼロ依存**: 外部テストライブラリに依存せず、全て自前実装とすることで、libuv自体のビルド可搬性を損なわない。

3. **TAP互換出力**: 標準化されたTAP形式でテスト結果を出力し、様々なCI/CDツールとの統合を容易にする。

4. **型安全アサーション**: `ASSERT_EQ`（int64_t）、`ASSERT_UINT64_EQ`（uint64_t）、`ASSERT_DOUBLE_EQ`（double）、`ASSERT_STR_EQ`（文字列）、`ASSERT_MEM_EQ`（メモリブロック）等、型別のアサーションマクロにより、失敗時に適切な型での値表示を行う。

### io_uring 二重テスト（Linux固有）

Linux環境では `TEST_FS_IMPL` / `TEST_FS_DECLARE` / `TEST_FS_ENTRY` マクロにより、ファイルシステム操作テストが自動的に通常版とio_uring版の2バリアントで実行される。これにより、従来のepollバックエンドとio_uringバックエンドの両方で動作の正確性が保証される。

### ThreadSanitizer抑制ルール

`tsansupp.txt` で `pthread_barrier_destroy` のデータ競合警告を抑制している。これはglibc内部の `count` フィールドの非同期読み取りに起因する誤検知であり、libuv側のバグではない。

### Windows固有対応

- `uv_win_longpath.manifest` をテストバイナリにリンクし、260文字を超えるファイルパスのテストを可能にしている。
- CI-win.ymlでWindows ARM64ビルドを行うが、ARM64ランナーが利用できないためテスト実行はスキップされる。
- Windows版UBSANではVisual Studio付属のclangにランタイムリンク問題があるため、LLVM/Clang 17を別途使用している。
