# CallTrace テスト戦略
## 1. テスト戦略概要
### 1.1 品質目標
- **機能正確性**: 100%の主要ユースケースで正常動作
- **パフォーマンス**: ベースライン性能の5%以内のオーバーヘッド
- **信頼性**: 24時間連続実行でクラッシュなし
- **互換性**: 主要Linuxディストリビューション対応
- **セキュリティ**: メモリ安全性とプライバシー保護
### 1.2 テストピラミッド構成
```
/\
/ \ E2E Tests (5%)
/____\ - システム全体の動作検証
/ \
/ \ Integration Tests (25%)
/__________\ - コンポーネント間連携検証
/ \
/______________\ Unit Tests (70%)
- 個別関数・モジュール検証
```
## 2. ユニットテスト戦略
### 2.1 テスト対象
**Core Modules**:
- `calltrace.c`: API関数群
- `hooks.c`: フック機構
- `state.c`: 状態管理
- `json_output.c`: JSON生成
**Utility Modules**:
- `symbols.c`: シンボル解決
- `filters.c`: フィルタリング
- `threads.c`: スレッド管理
- `timestamp.c`: 時刻処理
### 2.2 テストケース設計
#### 2.2.1 calltrace.c テスト
```c
// tests/unit/test_calltrace.c
#include <check.h>
#include "calltrace/calltrace.h"
START_TEST(test_calltrace_init_success) {
calltrace_config_t config = {0};
config.output_file = "/tmp/test_output.json";
config.max_depth = 50;
calltrace_error_t result = calltrace_init(&config);
ck_assert_int_eq(result, CALLTRACE_OK);
// Cleanup
calltrace_cleanup();
}
END_TEST
START_TEST(test_calltrace_init_null_config) {
calltrace_error_t result = calltrace_init(NULL);
ck_assert_int_eq(result, CALLTRACE_OK); // デフォルト設定で成功
calltrace_cleanup();
}
END_TEST
START_TEST(test_calltrace_double_init) {
calltrace_config_t config = {0};
calltrace_init(&config);
calltrace_error_t result = calltrace_init(&config);
ck_assert_int_eq(result, CALLTRACE_ERROR_INIT); // 二重初期化エラー
calltrace_cleanup();
}
END_TEST
```
#### 2.2.2 フィルタテスト
```c
// tests/unit/test_filters.c
START_TEST(test_wildcard_matching) {
// ワイルドカードパターンテスト
ck_assert(calltrace_match_pattern("main", "main"));
ck_assert(calltrace_match_pattern("main*", "main_function"));
ck_assert(calltrace_match_pattern("*_init", "system_init"));
ck_assert(!calltrace_match_pattern("main", "other"));
}
END_TEST
START_TEST(test_exclude_patterns) {
calltrace_add_filter("!__*");
ck_assert(!calltrace_should_trace("__libc_start_main"));
ck_assert(calltrace_should_trace("main"));
}
END_TEST
```
### 2.3 モックとスタブ戦略
#### 2.3.1 システムコールモック
```c
// tests/mocks/mock_syscalls.h
typedef struct {
int call_count;
void* return_value;
int errno_value;
} mock_call_info_t;
extern mock_call_info_t mock_dlsym_info;
// dlsym()のモック実装
void* mock_dlsym(void* handle, const char* symbol);
#define dlsym mock_dlsym
```
#### 2.3.2 ファイルI/Oモック
```c
// ファイル出力をメモリバッファにリダイレクト
typedef struct {
char* buffer;
size_t size;
size_t position;
} mock_file_t;
FILE* mock_fopen(const char* filename, const char* mode);
int mock_fprintf(FILE* stream, const char* format, ...);
```
## 3. 統合テスト戦略
### 3.1 コンポーネント統合テスト
#### 3.1.1 LD_PRELOAD統合テスト
```bash
#!/bin/bash
# tests/integration/test_ld_preload.sh
# テストプログラム作成
cat > test_program.c << 'EOF'
#include <stdio.h>
#include <unistd.h>
void test_function_a() {
printf("Function A called\n");
}
void test_function_b() {
printf("Function B called\n");
test_function_a();
}
int main() {
printf("Starting test program\n");
test_function_b();
printf("Test program completed\n");
return 0;
}
EOF
gcc -o test_program test_program.c
# CallTrace付きで実行
LD_PRELOAD=../build/libcalltrace.so ./test_program > output.json
# JSON出力検証
jq '.trace_session.calls | length' output.json
# 期待値: 4 (main, test_function_b, test_function_a, printf呼び出し)
```
#### 3.1.2 マルチスレッド統合テスト
```c
// tests/integration/multithread_test.c
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
void* worker_thread(void* arg) {
int thread_id = *(int*)arg;
printf("Worker %d starting\n", thread_id);
// 複数の関数呼び出し
for (int i = 0; i < 5; i++) {
usleep(10000); // 10ms
printf("Worker %d iteration %d\n", thread_id, i);
}
printf("Worker %d finished\n", thread_id);
return NULL;
}
int main() {
const int NUM_THREADS = 4;
pthread_t threads[NUM_THREADS];
int thread_ids[NUM_THREADS];
// スレッド作成
for (int i = 0; i < NUM_THREADS; i++) {
thread_ids[i] = i;
pthread_create(&threads[i], NULL, worker_thread, &thread_ids[i]);
}
// スレッド終了待機
for (int i = 0; i < NUM_THREADS; i++) {
pthread_join(threads[i], NULL);
}
return 0;
}
```
### 3.2 システム統合テスト
#### 3.2.1 実アプリケーションテスト
```bash
# tests/integration/real_apps/
# 実際のアプリケーションでの動作検証
# 1. GNU Coreutils
test_coreutils() {
LD_PRELOAD=../libcalltrace.so ls -la /tmp
LD_PRELOAD=../libcalltrace.so find /tmp -name "*.tmp"
LD_PRELOAD=../libcalltrace.so grep "pattern" /etc/passwd
}
# 2. 開発ツール
test_development_tools() {
LD_PRELOAD=../libcalltrace.so gcc --version
LD_PRELOAD=../libcalltrace.so make --version
}
# 3. Python/Node.js
test_interpreters() {
LD_PRELOAD=../libcalltrace.so python3 -c "print('Hello')"
LD_PRELOAD=../libcalltrace.so node -e "console.log('Hello')"
}
```
## 4. パフォーマンステスト戦略
### 4.1 ベンチマーク設計
#### 4.1.1 オーバーヘッド測定
```c
// tests/performance/overhead_benchmark.c
#include <time.h>
#include <stdio.h>
// 再帰呼び出しパフォーマンステスト
void recursive_function(int depth) {
if (depth <= 0) return;
recursive_function(depth - 1);
}
// ループ呼び出しパフォーマンステスト
void loop_calls(int iterations) {
for (int i = 0; i < iterations; i++) {
printf("Iteration %d\n", i);
}
}
int main() {
clock_t start, end;
// ベースライン測定
start = clock();
for (int i = 0; i < 1000; i++) {
recursive_function(20);
loop_calls(100);
}
end = clock();
double baseline_time = ((double)(end - start)) / CLOCKS_PER_SEC;
printf("Baseline time: %f seconds\n", baseline_time);
return 0;
}
```
#### 4.1.2 メモリ使用量テスト
```bash
#!/bin/bash
# tests/performance/memory_usage.sh
# Valgrind Massifでメモリプロファイリング
valgrind --tool=massif --time-unit=B \
env LD_PRELOAD=../libcalltrace.so ./memory_intensive_program
# メモリ使用量レポート生成
ms_print massif.out.* > memory_report.txt
```
### 4.2 スケーラビリティテスト
#### 4.2.1 大量関数呼び出しテスト
```c
// tests/performance/scale_test.c
void deep_recursion(int depth) {
if (depth <= 0) return;
deep_recursion(depth - 1);
}
void wide_calls(int width) {
for (int i = 0; i < width; i++) {
printf("Call %d\n", i);
}
}
int main() {
// 深い再帰 (1000レベル)
deep_recursion(1000);
// 広い呼び出し (10000回)
wide_calls(10000);
return 0;
}
```
## 5. 互換性テスト戦略
### 5.1 プラットフォーム互換性
#### 5.1.1 Linuxディストリビューション
- Ubuntu 20.04 LTS, 22.04 LTS
- CentOS 7, 8
- RHEL 8, 9
- Debian 10, 11
- Fedora 35, 36
#### 5.1.2 アーキテクチャ
- x86_64 (主要ターゲット)
- ARM64 (検証対象)
### 5.2 ライブラリ互換性テスト
```bash
# tests/compatibility/library_versions.sh
# 異なるGLIBCバージョンでのテスト
test_glibc_versions() {
for version in 2.17 2.28 2.31 2.35; do
echo "Testing with GLIBC $version"
# Docker環境で各バージョンをテスト
docker run glibc:$version ./run_tests.sh
done
}
# 異なるGCCバージョンでのビルドテスト
test_compiler_versions() {
for gcc_version in 7 8 9 10 11; do
echo "Building with GCC $gcc_version"
CC=gcc-$gcc_version cmake --build build
./run_basic_tests.sh
done
}
```
## 6. セキュリティテスト戦略
### 6.1 メモリ安全性テスト
#### 6.1.1 AddressSanitizer
```bash
# メモリエラー検出
cmake -DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_C_FLAGS="-fsanitize=address -g" \
-DCMAKE_CXX_FLAGS="-fsanitize=address -g"
make
./run_all_tests.sh
```
#### 6.1.2 ThreadSanitizer
```bash
# 競合状態検出
cmake -DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_C_FLAGS="-fsanitize=thread -g" \
-DCMAKE_CXX_FLAGS="-fsanitize=thread -g"
make
./run_multithreaded_tests.sh
```
### 6.2 権限昇格テスト
```bash
# tests/security/privilege_test.sh
# setuidプログラムでの動作確認
test_setuid_programs() {
# setuidプログラム作成
sudo cp /bin/echo /tmp/test_setuid
sudo chmod u+s /tmp/test_setuid
# CallTraceが適切に無効化されることを確認
LD_PRELOAD=../libcalltrace.so /tmp/test_setuid "Hello"
# トレース出力が生成されないことを確認
[[ ! -f calltrace_output.json ]] || exit 1
}
```
## 7. CI/CD統合戦略
### 7.1 パイプライン構成
#### 7.1.1 Pre-commit Hooks
```bash
#!/bin/bash
# .git/hooks/pre-commit
# コードフォーマット検証
echo "Checking code format..."
# 静的解析
echo "Running static analysis..."
cppcheck --enable=all --error-exitcode=1 src/ include/
# 単体テスト実行
echo "Running unit tests..."
cmake --build build --target test
```
#### 7.1.2 Pull Request検証
```yaml
# .github/workflows/pr_validation.yml
name: Pull Request Validation
on:
pull_request:
branches: [ main, develop ]
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build and Test
run: |
./scripts/build.sh -t Debug -T
- name: Performance Regression Check
run: |
./scripts/performance_check.sh
- name: Security Scan
run: |
./scripts/security_scan.sh
```
### 7.2 品質ゲート
#### 7.2.1 コードカバレッジ閾値
- ユニットテスト: 85%以上
- 統合テスト: 70%以上
- 全体: 80%以上
#### 7.2.2 パフォーマンス基準
- オーバーヘッド: 5%以内
- メモリ使用量: 100MB以内
- ビルド時間: 5分以内
#### 7.2.3 セキュリティ基準
- 静的解析エラー: 0件
- メモリエラー: 0件
- セキュリティ脆弱性: 0件
## 8. テストデータ管理
### 8.1 テストケースデータ
```
tests/
├── data/
│ ├── sample_programs/ # テスト用プログラム
│ ├── expected_outputs/ # 期待される出力
│ ├── config_files/ # テスト用設定
│ └── performance_baselines/ # パフォーマンスベースライン
```
### 8.2 テスト結果アーカイブ
- ビルドごとのテスト結果保存
- パフォーマンス履歴トラッキング
- リグレッション検出機能
## 9. テスト自動化
### 9.1 継続的テスト実行
```bash
# scripts/continuous_testing.sh
#!/bin/bash
while true; do
# 変更検知
if git diff --quiet HEAD~1 HEAD; then
echo "No changes detected"
sleep 60
continue
fi
echo "Changes detected, running tests..."
# 増分テスト実行
./scripts/run_tests.sh --incremental
# 結果保存
cp test_results.xml "results/$(date +%Y%m%d_%H%M%S)_test_results.xml"
sleep 300 # 5分間隔
done
```
### 9.2 テストレポート生成
```python
# scripts/generate_test_report.py
import json
import xml.etree.ElementTree as ET
from datetime import datetime
def generate_html_report(test_results):
"""テスト結果のHTML形式レポート生成"""
html = f"""
<html>
<head><title>CallTrace Test Report</title></head>
<body>
<h1>Test Results - {datetime.now()}</h1>
<h2>Summary</h2>
<ul>
<li>Total Tests: {test_results['total']}</li>
<li>Passed: {test_results['passed']}</li>
<li>Failed: {test_results['failed']}</li>
<li>Coverage: {test_results['coverage']}%</li>
</ul>
</body>
</html>
"""
return html
```
この包括的なテスト戦略により、CallTraceライブラリの品質と信頼性を確保します。