Files
wifi-densepose/v1/tests/unit/test_phase_sanitizer.py
Claude 6ed69a3d48 feat: Complete Rust port of WiFi-DensePose with modular crates
Major changes:
- Organized Python v1 implementation into v1/ subdirectory
- Created Rust workspace with 9 modular crates:
  - wifi-densepose-core: Core types, traits, errors
  - wifi-densepose-signal: CSI processing, phase sanitization, FFT
  - wifi-densepose-nn: Neural network inference (ONNX/Candle/tch)
  - wifi-densepose-api: Axum-based REST/WebSocket API
  - wifi-densepose-db: SQLx database layer
  - wifi-densepose-config: Configuration management
  - wifi-densepose-hardware: Hardware abstraction
  - wifi-densepose-wasm: WebAssembly bindings
  - wifi-densepose-cli: Command-line interface

Documentation:
- ADR-001: Workspace structure
- ADR-002: Signal processing library selection
- ADR-003: Neural network inference strategy
- DDD domain model with bounded contexts

Testing:
- 69 tests passing across all crates
- Signal processing: 45 tests
- Neural networks: 21 tests
- Core: 3 doc tests

Performance targets:
- 10x faster CSI processing (~0.5ms vs ~5ms)
- 5x lower memory usage (~100MB vs ~500MB)
- WASM support for browser deployment
2026-01-13 03:11:16 +00:00

107 lines
4.0 KiB
Python

import pytest
import numpy as np
from unittest.mock import Mock, patch
from src.core.phase_sanitizer import PhaseSanitizer
class TestPhaseSanitizer:
"""Test suite for Phase Sanitizer following London School TDD principles"""
@pytest.fixture
def mock_phase_data(self):
"""Generate synthetic phase data for testing"""
# Phase data with unwrapping issues and outliers
return np.array([
[0.1, 0.2, 6.0, 0.4, 0.5], # Contains phase jump at index 2
[-3.0, -0.1, 0.0, 0.1, 0.2], # Contains wrapped phase at index 0
[0.0, 0.1, 0.2, 0.3, 0.4] # Clean phase data
])
@pytest.fixture
def phase_sanitizer(self):
"""Create Phase Sanitizer instance for testing"""
return PhaseSanitizer()
def test_unwrap_phase_removes_discontinuities(self, phase_sanitizer, mock_phase_data):
"""Test that phase unwrapping removes 2π discontinuities"""
# Act
result = phase_sanitizer.unwrap_phase(mock_phase_data)
# Assert
assert result is not None
assert isinstance(result, np.ndarray)
assert result.shape == mock_phase_data.shape
# Check that large jumps are reduced
for i in range(result.shape[0]):
phase_diffs = np.abs(np.diff(result[i]))
assert np.all(phase_diffs < np.pi) # No jumps larger than π
def test_remove_outliers_filters_anomalous_values(self, phase_sanitizer, mock_phase_data):
"""Test that outlier removal filters anomalous phase values"""
# Arrange - Add clear outliers
outlier_data = mock_phase_data.copy()
outlier_data[0, 2] = 100.0 # Clear outlier
# Act
result = phase_sanitizer.remove_outliers(outlier_data)
# Assert
assert result is not None
assert isinstance(result, np.ndarray)
assert result.shape == outlier_data.shape
assert np.abs(result[0, 2]) < 10.0 # Outlier should be corrected
def test_smooth_phase_reduces_noise(self, phase_sanitizer, mock_phase_data):
"""Test that phase smoothing reduces noise while preserving trends"""
# Arrange - Add noise
noisy_data = mock_phase_data + np.random.normal(0, 0.1, mock_phase_data.shape)
# Act
result = phase_sanitizer.smooth_phase(noisy_data)
# Assert
assert result is not None
assert isinstance(result, np.ndarray)
assert result.shape == noisy_data.shape
# Smoothed data should have lower variance
original_variance = np.var(noisy_data)
smoothed_variance = np.var(result)
assert smoothed_variance <= original_variance
def test_sanitize_handles_empty_input(self, phase_sanitizer):
"""Test that sanitizer handles empty input gracefully"""
# Arrange
empty_data = np.array([])
# Act & Assert
with pytest.raises(ValueError, match="Phase data cannot be empty"):
phase_sanitizer.sanitize(empty_data)
def test_sanitize_full_pipeline_integration(self, phase_sanitizer, mock_phase_data):
"""Test that full sanitization pipeline works correctly"""
# Act
result = phase_sanitizer.sanitize(mock_phase_data)
# Assert
assert result is not None
assert isinstance(result, np.ndarray)
assert result.shape == mock_phase_data.shape
# Result should be within reasonable phase bounds
assert np.all(result >= -2*np.pi)
assert np.all(result <= 2*np.pi)
def test_sanitize_performance_requirement(self, phase_sanitizer, mock_phase_data):
"""Test that phase sanitization meets performance requirements (<5ms)"""
import time
# Act
start_time = time.time()
result = phase_sanitizer.sanitize(mock_phase_data)
processing_time = time.time() - start_time
# Assert
assert processing_time < 0.005 # <5ms requirement
assert result is not None