Compare commits

...

4 Commits

8 changed files with 286 additions and 0 deletions

10
.coveragerc Normal file
View File

@ -0,0 +1,10 @@
[run]
branch = True
source = src
omit =
*/tests/*
*/migrations/*
[report]
show_missing = True
fail_under = 80

4
MANIFEST.in Normal file
View File

@ -0,0 +1,4 @@
include LICENSE
include README.md
include requirements.txt
recursive-include src/aiia *

3
pytest.ini Normal file
View File

@ -0,0 +1,3 @@
[pytest]
testpaths = tests/
python_files = test_*.py

2
requirements-dev.txt Normal file
View File

@ -0,0 +1,2 @@
pytest
pytest-mock

View File

@ -0,0 +1,75 @@
import pytest
import torch
import torch.nn as nn
from aiunn import aiuNNTrainer
# Simple mock dataset
class MockDataset(torch.utils.data.Dataset):
def __init__(self, num_samples=10):
self.num_samples = num_samples
def __len__(self):
return self.num_samples
def __getitem__(self, idx):
return torch.randn(3, 64, 64), torch.randn(3, 128, 128)
# Simple mock model
class MockModel(nn.Module):
def __init__(self):
super().__init__()
self.conv = nn.Conv2d(3, 3, 3, padding=1)
def forward(self, x):
return self.conv(x)
def save(self, path):
pass # Mock save method
@pytest.fixture
def trainer():
model = MockModel()
return aiuNNTrainer(model, dataset_class=MockDataset)
def test_trainer_initialization(trainer):
"""Test basic trainer initialization"""
assert trainer.model is not None
assert isinstance(trainer.criterion, nn.MSELoss)
assert trainer.optimizer is None
assert trainer.device in [torch.device('cuda'), torch.device('cpu')]
def test_load_data_basic(trainer):
"""Test basic data loading"""
train_loader, val_loader = trainer.load_data(
dataset_params={'num_samples': 10},
batch_size=2,
validation_split=0.2
)
assert train_loader is not None
assert val_loader is not None
assert len(train_loader) > 0
assert len(val_loader) > 0
def test_load_custom_datasets(trainer):
"""Test loading custom datasets"""
train_dataset = MockDataset(num_samples=10)
val_dataset = MockDataset(num_samples=5)
train_loader, val_loader = trainer.load_data(
custom_train_dataset=train_dataset,
custom_val_dataset=val_dataset,
batch_size=2
)
assert train_loader is not None
assert val_loader is not None
assert len(train_loader) == 5 # 10 samples with batch size 2
assert len(val_loader) == 3 # 5 samples with batch size 2 (rounded up)
def test_error_no_dataset():
"""Test error when no dataset is provided"""
trainer = aiuNNTrainer(MockModel(), dataset_class=None)
with pytest.raises(ValueError):
trainer.load_data(dataset_params={})

View File

@ -0,0 +1,99 @@
# tests/inference/test_inference.py
import pytest
import numpy as np
import torch
from PIL import Image
from aiunn import aiuNNInference
from aiunn.upsampler.aiunn import aiuNN, aiuNNConfig
from aiia import AIIABase, AIIAConfig
import os
import json
from unittest.mock import patch, MagicMock, mock_open
@pytest.fixture
def real_model(tmp_path):
# Create temporary directory for model
model_dir = tmp_path / "model"
model_dir.mkdir()
config = AIIAConfig()
ai_config = aiuNNConfig()
base_model = AIIABase(config)
# Make sure aiuNN is properly configured with all required attributes
upsampler = aiuNN(base_model, config=ai_config)
# Ensure the upsample attribute is properly set if needed
# upsampler.upsample = ... # Add any necessary initialization
# Save the model and config to temporary directory
save_path = str(model_dir / "save")
os.makedirs(save_path, exist_ok=True)
# Save config file
config_data = {
"model_type": "test_model",
"scale": 4,
"in_channels": 3,
"out_channels": 3
}
with open(os.path.join(save_path, "config.json"), "w") as f:
json.dump(config_data, f)
# Save model
upsampler.save(save_path)
# Load model in inference mode
inference_model = aiuNNInference(model_path=save_path, precision='fp16', device='cpu')
return inference_model
@pytest.fixture
def inference(real_model):
return real_model
def test_preprocess_image(inference):
# Create a small test image
test_array = np.zeros((100, 100, 3), dtype=np.uint8)
test_image = Image.fromarray(test_array)
# Test with PIL Image
result = inference.preprocess_image(test_image)
assert isinstance(result, torch.Tensor)
assert result.shape[0] == 1 # batch dimension
assert result.shape[1] == 3 # channels
assert result.shape[2:] == (100, 100) # height, width
def test_postprocess_tensor(inference):
# Create a test tensor
test_tensor = torch.zeros(1, 3, 100, 100)
result = inference.postprocess_tensor(test_tensor)
assert isinstance(result, Image.Image)
assert result.size == (100, 100)
assert result.mode == 'RGB'
def test_save(inference):
# Create a test image
test_image = Image.fromarray(np.zeros((100, 100, 3), dtype=np.uint8))
output_path = "test_output.png"
with patch('os.makedirs') as mock_makedirs:
inference.save(test_image, output_path)
mock_makedirs.assert_called_with(os.path.dirname(os.path.abspath(output_path)), exist_ok=True)
def test_convert_to_binary(inference):
# Create a test image
test_image = Image.fromarray(np.zeros((100, 100, 3), dtype=np.uint8))
result = inference.convert_to_binary(test_image)
assert isinstance(result, bytes)
assert len(result) > 0
def test_process_batch(inference):
# Create test images
test_array = np.zeros((100, 100, 3), dtype=np.uint8)
test_images = [Image.fromarray(test_array) for _ in range(2)]
results = inference.process_batch(test_images)
assert len(results) == 2
assert all(isinstance(img, Image.Image) for img in results)

View File

@ -0,0 +1,48 @@
import os
import tempfile
from aiia import AIIABase, AIIAConfig
from aiunn import aiuNN, aiuNNConfig
def test_save_and_load_model():
# Create a temporary directory to save the model
with tempfile.TemporaryDirectory() as tmpdirname:
# Create configurations and build a base model
config = AIIAConfig()
ai_config = aiuNNConfig()
base_model = AIIABase(config)
upsampler = aiuNN(base_model, config=ai_config)
# Save the model
save_path = os.path.join(tmpdirname, "model")
upsampler.save(save_path)
# Load the model
loaded_upsampler = aiuNN.load(save_path)
# Verify that the loaded model is the same as the original model
assert isinstance(loaded_upsampler, aiuNN)
assert loaded_upsampler.config.__dict__ == upsampler.config.__dict__
def test_save_and_load_model_with_precision():
# Create a temporary directory to save the model
with tempfile.TemporaryDirectory() as tmpdirname:
# Create configurations and build a base model
config = AIIAConfig()
ai_config = aiuNNConfig()
base_model = AIIABase(config)
upsampler = aiuNN(base_model, config=ai_config)
# Save the model
save_path = os.path.join(tmpdirname, "model")
upsampler.save(save_path)
# Load the model with precision 'bf16'
loaded_upsampler = aiuNN.load(save_path, precision="bf16")
# Verify that the loaded model is the same as the original model
assert isinstance(loaded_upsampler, aiuNN)
assert loaded_upsampler.config.__dict__ == upsampler.config.__dict__
if __name__ == "__main__":
test_save_and_load_model()
test_save_and_load_model_with_precision()

View File

@ -0,0 +1,45 @@
import pytest
from aiunn import aiuNNConfig
def test_default_initialization():
config = aiuNNConfig()
assert config.upsample_scale == 2
assert config.upsample_mode == 'bilinear'
assert not config.upsample_align_corners
assert len(config.layers) == 1
assert config.layers[0]['name'] == 'Upsample'
def test_custom_initialization():
custom_config = {
'some_key': 'some_value',
}
config = aiuNNConfig(base_config=custom_config, upsample_scale=3, upsample_mode='nearest', upsample_align_corners=True)
assert config.upsample_scale == 3
assert config.upsample_mode == 'nearest'
assert config.upsample_align_corners
assert len(config.layers) == 1
assert config.layers[0]['name'] == 'Upsample'
def test_add_upsample_layer():
config = aiuNNConfig()
config.add_upsample_layer()
assert len(config.layers) == 1
def test_upsample_layer_not_duplicated():
config = aiuNNConfig()
initial_length = len(config.layers)
# Remove all existing 'Upsample' layers.
for layer in list(config.layers):
if layer.get('name') == 'Upsample':
config.layers.remove(layer)
config.add_upsample_layer()
assert len(config.layers) == 1
def test_base_config_with_to_dict():
class MockBaseConfig:
def to_dict(self):
return {'base_key': 'base_value'}
base_config = MockBaseConfig()
config = aiuNNConfig(base_config=base_config)
assert config.to_dict()['base_key'] == 'base_value'