Files
ivatar/ivatar/test_robohash.py
2025-10-24 17:42:00 +02:00

238 lines
9.4 KiB
Python

"""
Tests for robohash optimization functionality
"""
import time
import hashlib
from io import BytesIO
from django.test import TestCase
from PIL import Image
from robohash import Robohash
from ivatar.robohash_optimized import OptimizedRobohash, create_optimized_robohash
from ivatar.utils import generate_random_email
class RobohashOptimizationTestCase(TestCase):
"""Test cases for robohash optimization"""
def setUp(self):
"""Set up test data"""
self.test_emails = [generate_random_email() for _ in range(5)]
self.test_digests = [
hashlib.md5(email.encode()).hexdigest() for email in self.test_emails
]
self.test_digests.extend(
[
"5d41402abc4b2a76b9719d911017c592",
"098f6bcd4621d373cade4e832627b4f6",
]
)
def test_optimized_robohash_functionality(self):
"""Test that optimized robohash functionality works correctly"""
digest = self.test_digests[0]
optimized = OptimizedRobohash(digest)
optimized.assemble_fast(roboset="any", sizex=256, sizey=256)
self.assertIsNotNone(optimized.img)
self.assertEqual(optimized.img.size, (256, 256))
self.assertIn(optimized.img.mode, ["RGBA", "RGB"])
data = BytesIO()
optimized.img.save(data, format="png")
self.assertGreater(len(data.getvalue()), 1000)
def test_identical_results(self):
"""Test that optimized robohash returns identical results"""
digest = self.test_digests[0]
original = Robohash(digest)
original.assemble(roboset="any", sizex=256, sizey=256)
orig_data = BytesIO()
original.img.save(orig_data, format="png")
orig_bytes = orig_data.getvalue()
optimized = OptimizedRobohash(digest)
optimized.assemble_fast(roboset="any", sizex=256, sizey=256)
opt_data = BytesIO()
optimized.img.save(opt_data, format="png")
opt_bytes = opt_data.getvalue()
self.assertEqual(orig_bytes, opt_bytes, "Images should be identical")
def test_performance_improvement(self):
"""Test that optimized robohash shows performance characteristics"""
digest = self.test_digests[0]
start_time = time.time()
original = Robohash(digest)
original.assemble(roboset="any", sizex=256, sizey=256)
original_time = (time.time() - start_time) * 1000
start_time = time.time()
optimized = OptimizedRobohash(digest)
optimized.assemble_fast(roboset="any", sizex=256, sizey=256)
optimized_time = (time.time() - start_time) * 1000
self.assertGreater(original_time, 0, "Original should take some time")
self.assertGreater(optimized_time, 0, "Optimized should take some time")
def test_integration_function(self):
"""Test the create_optimized_robohash integration function"""
digest = self.test_digests[0]
data = create_optimized_robohash(digest, 256, "any")
self.assertIsInstance(data, BytesIO)
png_bytes = data.getvalue()
self.assertGreater(len(png_bytes), 1000)
img = Image.open(BytesIO(png_bytes))
self.assertEqual(img.size, (256, 256))
self.assertEqual(img.format, "PNG")
def test_cache_initialization(self):
"""Test that directory cache is initialized correctly"""
digest = self.test_digests[0]
OptimizedRobohash(digest) # Initialize to trigger cache setup
self.assertTrue(OptimizedRobohash._cache_initialized)
self.assertIsInstance(OptimizedRobohash._directory_cache, dict)
def test_multiple_random_emails_identical_results(self):
"""Test pixel-perfect identical results with multiple random email addresses"""
# Test with multiple random email addresses
for i, digest in enumerate(self.test_digests[:3]):
with self.subTest(email_index=i, digest=digest[:8]):
# Test with different configurations
test_cases = [
{"roboset": "any", "size": 128},
{"roboset": "set1", "size": 256},
{"roboset": "set2", "size": 64},
]
for case in test_cases:
with self.subTest(case=case):
# Generate original
original = Robohash(digest)
original.assemble(
roboset=case["roboset"],
sizex=case["size"],
sizey=case["size"],
)
orig_data = BytesIO()
original.img.save(orig_data, format="png")
orig_bytes = orig_data.getvalue()
# Generate optimized
optimized = OptimizedRobohash(digest)
optimized.assemble_fast(
roboset=case["roboset"],
sizex=case["size"],
sizey=case["size"],
)
opt_data = BytesIO()
optimized.img.save(opt_data, format="png")
opt_bytes = opt_data.getvalue()
# Verify pixel-perfect identical
self.assertEqual(
orig_bytes,
opt_bytes,
f"Images not pixel-perfect identical for email {i}, "
f"digest {digest[:8]}..., {case['roboset']}, {case['size']}x{case['size']}",
)
def test_performance_improvement_multiple_cases(self):
"""Test that optimized version is consistently faster across multiple cases"""
performance_results = []
# Test with multiple digests and configurations
test_cases = [
{"digest": self.test_digests[0], "roboset": "any", "size": 256},
{"digest": self.test_digests[1], "roboset": "set1", "size": 128},
{"digest": self.test_digests[2], "roboset": "set2", "size": 256},
]
for case in test_cases:
# Measure original
start_time = time.time()
original = Robohash(case["digest"])
original.assemble(
roboset=case["roboset"], sizex=case["size"], sizey=case["size"]
)
original_time = (time.time() - start_time) * 1000
# Measure optimized
start_time = time.time()
optimized = OptimizedRobohash(case["digest"])
optimized.assemble_fast(
roboset=case["roboset"], sizex=case["size"], sizey=case["size"]
)
optimized_time = (time.time() - start_time) * 1000
performance_results.append(
{
"original": original_time,
"optimized": optimized_time,
"improvement": (
original_time / optimized_time if optimized_time > 0 else 0
),
}
)
# Verify all cases show reasonable performance
for i, result in enumerate(performance_results):
with self.subTest(case_index=i):
self.assertGreater(
result["original"], 0, "Original should take measurable time"
)
self.assertGreater(
result["optimized"], 0, "Optimized should take measurable time"
)
# Allow for test environment variance - just ensure both complete successfully
self.assertLess(
result["optimized"],
10000,
"Optimized should complete in reasonable time",
)
def test_random_email_generation_and_processing(self):
"""Test robohash with freshly generated random emails"""
# Generate fresh random emails for this test
fresh_emails = [generate_random_email() for _ in range(5)]
fresh_digests = [
hashlib.md5(email.encode()).hexdigest() for email in fresh_emails
]
for i, (email, digest) in enumerate(zip(fresh_emails, fresh_digests)):
with self.subTest(email=email, digest=digest[:8]):
# Test that both original and optimized can process this email
original = Robohash(digest)
original.assemble(roboset="any", sizex=128, sizey=128)
optimized = OptimizedRobohash(digest)
optimized.assemble_fast(roboset="any", sizex=128, sizey=128)
# Verify both produce valid images
self.assertIsNotNone(original.img)
self.assertIsNotNone(optimized.img)
self.assertEqual(original.img.size, (128, 128))
self.assertEqual(optimized.img.size, (128, 128))
# Verify they produce identical results
orig_data = BytesIO()
original.img.save(orig_data, format="png")
orig_bytes = orig_data.getvalue()
opt_data = BytesIO()
optimized.img.save(opt_data, format="png")
opt_bytes = opt_data.getvalue()
self.assertEqual(
orig_bytes,
opt_bytes,
f"Random email {email} (digest {digest[:8]}...) produced different images",
)