|
|
| |
| |
| |
|
|
| def run_comprehensive_test(): |
| """Run comprehensive test suite for url_dataset.py""" |
| print("URL_DATASET.PY COMPREHENSIVE TEST SUITE") |
| print("=" * 60) |
| print("Testing all classes and functions in url_dataset.py") |
|
|
| import tempfile |
| import json |
| import hashlib |
| from unittest.mock import patch, MagicMock |
| from io import BytesIO |
| import requests |
| from collections import Counter |
| from torchvision import transforms |
|
|
| tests_passed = 0 |
| tests_failed = 0 |
| failed_tests = [] |
|
|
| def run_test(test_name, test_func): |
| nonlocal tests_passed, tests_failed, failed_tests |
| print(f"\n{'=' * 60}") |
| print(f"Running: {test_name}") |
| print(f"{'=' * 60}") |
| try: |
| test_func() |
| tests_passed += 1 |
| print(f"β
PASSED: {test_name}") |
| except Exception as e: |
| tests_failed += 1 |
| failed_tests.append(f"{test_name}: {str(e)}") |
| print(f"β FAILED: {test_name}") |
| print(f"Error: {str(e)}") |
|
|
| def create_mock_data(num_items=10): |
| """Create mock JSON data""" |
| mock_data = [] |
| decades = ['1960s', '1970s', '1980s', '1990s', '2000s'] |
| for i in range(num_items): |
| mock_data.append({ |
| "id": f"test_id_{i}", |
| "product_id": f"product_{i % 3}", |
| "name": f"Test Product {i}", |
| "decade": decades[i % 5], |
| "url": f"https://example.com/image_{i}.jpg", |
| "classification": f"test_class_{i % 2}", |
| "makers": f"test_maker_{i % 2}", |
| "country": f"test_country_{i % 3}" |
| }) |
| return mock_data |
|
|
| def create_mock_image(size=(200, 200)): |
| """Create mock PIL image""" |
| array = np.random.randint(0, 255, (*size, 3), dtype=np.uint8) |
| return Image.fromarray(array) |
|
|
| def test_base_dataset(): |
| """Test BaseDataset functionality""" |
| print("Testing BaseDataset...") |
|
|
| with tempfile.TemporaryDirectory() as temp_dir: |
| temp_path = Path(temp_dir) |
| split_file = temp_path / "test.json" |
|
|
| mock_data = create_mock_data(10) |
| with open(split_file, 'w') as f: |
| json.dump(mock_data, f) |
|
|
| dataset = BaseDataset(str(split_file)) |
|
|
| print(f"β BaseDataset initialized with {len(dataset)} items") |
| print(f"β Number of classes: {dataset.num_classes}") |
| print(f"β Class names: {dataset.decades}") |
|
|
| assert len(dataset) == 10 |
| assert dataset.num_classes == 5 |
| assert dataset.decades == ['1960s', '1970s', '1980s', '1990s', '2000s'] |
|
|
| labels = dataset.get_labels() |
| print(f"β Labels: {labels}") |
| assert len(labels) == 10 |
|
|
| metadata = dataset.get_metadata(0) |
| expected_keys = ['id', 'product_id', 'name', 'decade', 'url', 'classification', 'makers', 'country'] |
| for key in expected_keys: |
| assert key in metadata |
| print(f"β Metadata keys: {list(metadata.keys())}") |
|
|
| def test_url_dataset_mock(): |
| """Test URLDataset with mocked requests""" |
| print("Testing URLDataset with mocked requests...") |
|
|
| with tempfile.TemporaryDirectory() as temp_dir: |
| temp_path = Path(temp_dir) |
| cache_dir = temp_path / "cache" |
| split_file = temp_path / "test.json" |
|
|
| mock_data = create_mock_data(5) |
| with open(split_file, 'w') as f: |
| json.dump(mock_data, f) |
|
|
| |
| test_transform = transforms.Compose([ |
| transforms.Resize((224, 224)), |
| transforms.ToTensor() |
| ]) |
|
|
| mock_image = create_mock_image((300, 300)) |
| mock_response = MagicMock() |
| mock_response.content = BytesIO() |
| mock_image.save(mock_response.content, 'JPEG') |
| mock_response.content = mock_response.content.getvalue() |
| mock_response.raise_for_status = MagicMock() |
|
|
| with patch('requests.get', return_value=mock_response): |
| dataset = URLDataset( |
| split_file=str(split_file), |
| cache_dir=str(cache_dir), |
| transform=test_transform, |
| max_retries=2, |
| timeout=5, |
| fallback_on_error=True |
| ) |
|
|
| print(f"β URLDataset initialized with {len(dataset)} items") |
| print(f"β Cache directory: {dataset.cache_dir}") |
|
|
| test_url = "https://example.com/test.jpg" |
| cache_path = dataset._get_cache_path(test_url) |
| print(f"β Cache path generation: {cache_path.name}") |
|
|
| |
| image, label, metadata = dataset[0] |
|
|
| assert isinstance(image, torch.Tensor) |
| assert image.dtype == torch.float32 |
| assert 0 <= label < 5 |
| assert isinstance(metadata, dict) |
|
|
| print(f"β First item loaded: shape={image.shape}, label={label}, decade={metadata['decade']}") |
|
|
| |
| stats = dataset.get_statistics() |
| print(f"β Statistics: {stats}") |
|
|
| def test_url_dataset_fallback(): |
| """Test URLDataset fallback behavior""" |
| print("Testing URLDataset fallback behavior...") |
|
|
| with tempfile.TemporaryDirectory() as temp_dir: |
| temp_path = Path(temp_dir) |
| cache_dir = temp_path / "cache" |
| split_file = temp_path / "test.json" |
|
|
| mock_data = create_mock_data(3) |
| with open(split_file, 'w') as f: |
| json.dump(mock_data, f) |
|
|
| |
| test_transform = transforms.Compose([ |
| transforms.Resize((224, 224)), |
| transforms.ToTensor() |
| ]) |
|
|
| with patch('requests.get', side_effect=requests.exceptions.ConnectionError("Mock connection error")): |
| dataset = URLDataset( |
| split_file=str(split_file), |
| cache_dir=str(cache_dir), |
| transform=test_transform, |
| max_retries=1, |
| timeout=1, |
| fallback_on_error=True |
| ) |
|
|
| |
| image, label, metadata = dataset[0] |
|
|
| assert isinstance(image, torch.Tensor) |
| print(f"β Fallback image loaded: shape={image.shape}") |
|
|
| stats = dataset.get_statistics() |
| assert stats['failures'] > 0 |
| print(f"β Failure tracked in statistics: {stats['failures']} failures") |
|
|
| def test_cached_dataset(): |
| """Test CachedDataset functionality""" |
| print("Testing CachedDataset...") |
|
|
| with tempfile.TemporaryDirectory() as temp_dir: |
| temp_path = Path(temp_dir) |
| images_dir = temp_path / "images" |
| images_dir.mkdir() |
| split_file = temp_path / "test.json" |
|
|
| mock_data = create_mock_data(5) |
| with open(split_file, 'w') as f: |
| json.dump(mock_data, f) |
|
|
| |
| for i in range(3): |
| url = mock_data[i]['url'] |
| url_hash = hashlib.md5(url.encode()).hexdigest() |
| cache_path = images_dir / f"{url_hash}.jpg" |
|
|
| mock_image = create_mock_image((200, 200)) |
| mock_image.save(cache_path, 'JPEG') |
|
|
| print(f"β Created {len(list(images_dir.glob('*.jpg')))} cached images") |
|
|
| |
| test_transform = transforms.Compose([ |
| transforms.Resize((224, 224)), |
| transforms.ToTensor() |
| ]) |
|
|
| dataset = CachedDataset( |
| split_file=str(split_file), |
| images_dir=str(images_dir), |
| transform=test_transform, |
| verify_images=True |
| ) |
|
|
| print(f"β CachedDataset initialized with {len(dataset)} valid images") |
| assert len(dataset) == 3 |
|
|
| image, label, metadata = dataset[0] |
| assert isinstance(image, torch.Tensor) |
| assert 0 <= label < 5 |
| print(f"β Cached item loaded: shape={image.shape}, label={label}") |
|
|
| def test_subset_creation(): |
| """Test subset creation""" |
| print("Testing create_subset_dataset...") |
|
|
| with tempfile.TemporaryDirectory() as temp_dir: |
| temp_path = Path(temp_dir) |
| split_file = temp_path / "test.json" |
|
|
| mock_data = create_mock_data(50) |
| with open(split_file, 'w') as f: |
| json.dump(mock_data, f) |
|
|
| original_dataset = BaseDataset(str(split_file)) |
| original_size = len(original_dataset) |
|
|
| print(f"β Original dataset size: {original_size}") |
|
|
| subset_dataset = create_subset_dataset(original_dataset, fraction=0.2, seed=42) |
| subset_size = len(subset_dataset) |
|
|
| print(f"β Subset dataset size: {subset_size}") |
| print(f"β Subset fraction: {subset_size / original_size:.2f}") |
|
|
| assert subset_size >= 5 |
| assert subset_size <= original_size |
|
|
| subset_labels = subset_dataset.get_labels() |
| unique_labels = set(subset_labels) |
| print(f"β Subset has {len(unique_labels)} unique classes: {unique_labels}") |
|
|
| def test_download_images(): |
| """Test bulk download functionality""" |
| print("Testing download_dataset_images with mocked requests...") |
|
|
| with tempfile.TemporaryDirectory() as temp_dir: |
| temp_path = Path(temp_dir) |
| cache_dir = temp_path / "cache" |
|
|
| split_files = [] |
| for split_name in ["train", "val"]: |
| split_file = temp_path / f"{split_name}.json" |
| mock_data = create_mock_data(5) |
| |
| for i, item in enumerate(mock_data): |
| item['url'] = f"https://example.com/{split_name}_image_{i}.jpg" |
|
|
| with open(split_file, 'w') as f: |
| json.dump(mock_data, f) |
| split_files.append(str(split_file)) |
|
|
| mock_image = create_mock_image((200, 200)) |
| mock_response = MagicMock() |
| mock_response.content = BytesIO() |
| mock_image.save(mock_response.content, 'JPEG') |
| mock_response.content = mock_response.content.getvalue() |
| mock_response.raise_for_status = MagicMock() |
|
|
| with patch('requests.get', return_value=mock_response): |
| results = download_dataset_images( |
| split_files=split_files, |
| cache_dir=str(cache_dir), |
| num_workers=2, |
| skip_existing=True |
| ) |
|
|
| print(f"β Download results: {results}") |
|
|
| expected_keys = ['cached', 'downloaded', 'failed'] |
| for key in expected_keys: |
| assert key in results |
|
|
| cached_images = list(cache_dir.glob('*.jpg')) |
| print(f"β Created {len(cached_images)} cached image files") |
|
|
| def test_edge_cases(): |
| """Test edge cases""" |
| print("Testing edge cases...") |
|
|
| with tempfile.TemporaryDirectory() as temp_dir: |
| temp_path = Path(temp_dir) |
|
|
| |
| empty_split_file = temp_path / "empty.json" |
| with open(empty_split_file, 'w') as f: |
| json.dump([], f) |
|
|
| empty_dataset = BaseDataset(str(empty_split_file)) |
| assert len(empty_dataset) == 0 |
| print("β Empty dataset handled correctly") |
|
|
| |
| try: |
| malformed_split_file = temp_path / "malformed.json" |
| with open(malformed_split_file, 'w') as f: |
| f.write("invalid json") |
|
|
| BaseDataset(str(malformed_split_file)) |
| assert False, "Should have raised exception" |
| except json.JSONDecodeError: |
| print("β Malformed JSON handled correctly") |
|
|
| |
| split_file = temp_path / "test.json" |
| mock_data = create_mock_data(2) |
| with open(split_file, 'w') as f: |
| json.dump(mock_data, f) |
|
|
| test_transform = transforms.Compose([ |
| transforms.Resize((224, 224)), |
| transforms.ToTensor() |
| ]) |
|
|
| with patch('requests.get', side_effect=Exception("Mock error")): |
| dataset = URLDataset( |
| split_file=str(split_file), |
| transform=test_transform, |
| fallback_on_error=False, |
| max_retries=1 |
| ) |
|
|
| try: |
| image, label, metadata = dataset[0] |
| assert False, "Should have raised exception" |
| except (ValueError, Exception): |
| print("β No-fallback error handling works correctly") |
|
|
| def test_performance(): |
| """Test performance""" |
| print("Testing performance...") |
|
|
| with tempfile.TemporaryDirectory() as temp_dir: |
| temp_path = Path(temp_dir) |
| split_file = temp_path / "perf_test.json" |
|
|
| mock_data = create_mock_data(100) |
| with open(split_file, 'w') as f: |
| json.dump(mock_data, f) |
|
|
| import time |
|
|
| start_time = time.time() |
| dataset = BaseDataset(str(split_file)) |
| init_time = time.time() - start_time |
|
|
| print(f"β BaseDataset initialization: {init_time:.3f}s for {len(dataset)} items") |
|
|
| start_time = time.time() |
| labels = dataset.get_labels() |
| label_time = time.time() - start_time |
|
|
| print(f"β Label extraction: {label_time:.3f}s for {len(labels)} labels") |
|
|
| start_time = time.time() |
| for i in range(min(10, len(dataset))): |
| metadata = dataset.get_metadata(i) |
| metadata_time = time.time() - start_time |
|
|
| print(f"β Metadata extraction: {metadata_time:.3f}s for 10 items") |
|
|
| assert init_time < 1.0 |
| assert label_time < 0.1 |
|
|
| |
| tests = [ |
| ("BaseDataset Functionality", test_base_dataset), |
| ("URLDataset with Mocked Requests", test_url_dataset_mock), |
| ("URLDataset Fallback Behavior", test_url_dataset_fallback), |
| ("CachedDataset Functionality", test_cached_dataset), |
| ("Subset Creation", test_subset_creation), |
| ("Bulk Download with Mocked Requests", test_download_images), |
| ("Edge Cases and Error Handling", test_edge_cases), |
| ("Performance Testing", test_performance), |
| ] |
|
|
| for test_name, test_func in tests: |
| run_test(test_name, test_func) |
|
|
| |
| print(f"\n{'=' * 60}") |
| print(f"TEST SUMMARY") |
| print(f"{'=' * 60}") |
| print(f"Total tests: {len(tests)}") |
| print(f"β
Passed: {tests_passed}") |
| print(f"β Failed: {tests_failed}") |
|
|
| if failed_tests: |
| print(f"\nFailed tests:") |
| for failure in failed_tests: |
| print(f" - {failure}") |
|
|
| success = tests_failed == 0 |
| if success: |
| print(f"\nπ ALL TESTS PASSED! url_dataset.py is working correctly.") |
| else: |
| print(f"\nβ SOME TESTS FAILED! Check the issues above.") |
|
|
| return success |
|
|
|
|
| |
| if __name__ == "__main__": |
| import sys |
|
|
| if len(sys.argv) > 1 and sys.argv[1] == "--comprehensive": |
| |
| run_comprehensive_test() |
| else: |
| |
| |
| pass |