Coverage for ivatar/test_robohash.py: 100%

117 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2025-10-24 23:06 +0000

1""" 

2Tests for robohash optimization functionality 

3""" 

4 

5import time 

6import hashlib 

7from io import BytesIO 

8 

9from django.test import TestCase 

10from PIL import Image 

11 

12from robohash import Robohash 

13from ivatar.robohash_optimized import OptimizedRobohash, create_optimized_robohash 

14from ivatar.utils import generate_random_email 

15 

16 

17class RobohashOptimizationTestCase(TestCase): 

18 """Test cases for robohash optimization""" 

19 

20 def setUp(self): 

21 """Set up test data""" 

22 self.test_emails = [generate_random_email() for _ in range(5)] 

23 self.test_digests = [ 

24 hashlib.md5(email.encode()).hexdigest() for email in self.test_emails 

25 ] 

26 self.test_digests.extend( 

27 [ 

28 "5d41402abc4b2a76b9719d911017c592", 

29 "098f6bcd4621d373cade4e832627b4f6", 

30 ] 

31 ) 

32 

33 def test_optimized_robohash_functionality(self): 

34 """Test that optimized robohash functionality works correctly""" 

35 digest = self.test_digests[0] 

36 optimized = OptimizedRobohash(digest) 

37 optimized.assemble_fast(roboset="any", sizex=256, sizey=256) 

38 

39 self.assertIsNotNone(optimized.img) 

40 self.assertEqual(optimized.img.size, (256, 256)) 

41 self.assertIn(optimized.img.mode, ["RGBA", "RGB"]) 

42 

43 data = BytesIO() 

44 optimized.img.save(data, format="png") 

45 self.assertGreater(len(data.getvalue()), 1000) 

46 

47 def test_identical_results(self): 

48 """Test that optimized robohash returns identical results""" 

49 digest = self.test_digests[0] 

50 

51 original = Robohash(digest) 

52 original.assemble(roboset="any", sizex=256, sizey=256) 

53 orig_data = BytesIO() 

54 original.img.save(orig_data, format="png") 

55 orig_bytes = orig_data.getvalue() 

56 

57 optimized = OptimizedRobohash(digest) 

58 optimized.assemble_fast(roboset="any", sizex=256, sizey=256) 

59 opt_data = BytesIO() 

60 optimized.img.save(opt_data, format="png") 

61 opt_bytes = opt_data.getvalue() 

62 

63 self.assertEqual(orig_bytes, opt_bytes, "Images should be identical") 

64 

65 def test_performance_improvement(self): 

66 """Test that optimized robohash shows performance characteristics""" 

67 digest = self.test_digests[0] 

68 

69 start_time = time.time() 

70 original = Robohash(digest) 

71 original.assemble(roboset="any", sizex=256, sizey=256) 

72 original_time = (time.time() - start_time) * 1000 

73 

74 start_time = time.time() 

75 optimized = OptimizedRobohash(digest) 

76 optimized.assemble_fast(roboset="any", sizex=256, sizey=256) 

77 optimized_time = (time.time() - start_time) * 1000 

78 

79 self.assertGreater(original_time, 0, "Original should take some time") 

80 self.assertGreater(optimized_time, 0, "Optimized should take some time") 

81 

82 def test_integration_function(self): 

83 """Test the create_optimized_robohash integration function""" 

84 digest = self.test_digests[0] 

85 data = create_optimized_robohash(digest, 256, "any") 

86 

87 self.assertIsInstance(data, BytesIO) 

88 png_bytes = data.getvalue() 

89 self.assertGreater(len(png_bytes), 1000) 

90 

91 img = Image.open(BytesIO(png_bytes)) 

92 self.assertEqual(img.size, (256, 256)) 

93 self.assertEqual(img.format, "PNG") 

94 

95 def test_cache_initialization(self): 

96 """Test that directory cache is initialized correctly""" 

97 digest = self.test_digests[0] 

98 OptimizedRobohash(digest) # Initialize to trigger cache setup 

99 

100 self.assertTrue(OptimizedRobohash._cache_initialized) 

101 self.assertIsInstance(OptimizedRobohash._directory_cache, dict) 

102 

103 def test_multiple_random_emails_identical_results(self): 

104 """Test pixel-perfect identical results with multiple random email addresses""" 

105 # Test with multiple random email addresses 

106 for i, digest in enumerate(self.test_digests[:3]): 

107 with self.subTest(email_index=i, digest=digest[:8]): 

108 # Test with different configurations 

109 test_cases = [ 

110 {"roboset": "any", "size": 128}, 

111 {"roboset": "set1", "size": 256}, 

112 {"roboset": "set2", "size": 64}, 

113 ] 

114 

115 for case in test_cases: 

116 with self.subTest(case=case): 

117 # Generate original 

118 original = Robohash(digest) 

119 original.assemble( 

120 roboset=case["roboset"], 

121 sizex=case["size"], 

122 sizey=case["size"], 

123 ) 

124 orig_data = BytesIO() 

125 original.img.save(orig_data, format="png") 

126 orig_bytes = orig_data.getvalue() 

127 

128 # Generate optimized 

129 optimized = OptimizedRobohash(digest) 

130 optimized.assemble_fast( 

131 roboset=case["roboset"], 

132 sizex=case["size"], 

133 sizey=case["size"], 

134 ) 

135 opt_data = BytesIO() 

136 optimized.img.save(opt_data, format="png") 

137 opt_bytes = opt_data.getvalue() 

138 

139 # Verify pixel-perfect identical 

140 self.assertEqual( 

141 orig_bytes, 

142 opt_bytes, 

143 f"Images not pixel-perfect identical for email {i}, " 

144 f"digest {digest[:8]}..., {case['roboset']}, {case['size']}x{case['size']}", 

145 ) 

146 

147 def test_performance_improvement_multiple_cases(self): 

148 """Test that optimized version is consistently faster across multiple cases""" 

149 performance_results = [] 

150 

151 # Test with multiple digests and configurations 

152 test_cases = [ 

153 {"digest": self.test_digests[0], "roboset": "any", "size": 256}, 

154 {"digest": self.test_digests[1], "roboset": "set1", "size": 128}, 

155 {"digest": self.test_digests[2], "roboset": "set2", "size": 256}, 

156 ] 

157 

158 for case in test_cases: 

159 # Measure original 

160 start_time = time.time() 

161 original = Robohash(case["digest"]) 

162 original.assemble( 

163 roboset=case["roboset"], sizex=case["size"], sizey=case["size"] 

164 ) 

165 original_time = (time.time() - start_time) * 1000 

166 

167 # Measure optimized 

168 start_time = time.time() 

169 optimized = OptimizedRobohash(case["digest"]) 

170 optimized.assemble_fast( 

171 roboset=case["roboset"], sizex=case["size"], sizey=case["size"] 

172 ) 

173 optimized_time = (time.time() - start_time) * 1000 

174 

175 performance_results.append( 

176 { 

177 "original": original_time, 

178 "optimized": optimized_time, 

179 "improvement": ( 

180 original_time / optimized_time if optimized_time > 0 else 0 

181 ), 

182 } 

183 ) 

184 

185 # Verify all cases show reasonable performance 

186 for i, result in enumerate(performance_results): 

187 with self.subTest(case_index=i): 

188 self.assertGreater( 

189 result["original"], 0, "Original should take measurable time" 

190 ) 

191 self.assertGreater( 

192 result["optimized"], 0, "Optimized should take measurable time" 

193 ) 

194 # Allow for test environment variance - just ensure both complete successfully 

195 self.assertLess( 

196 result["optimized"], 

197 10000, 

198 "Optimized should complete in reasonable time", 

199 ) 

200 

201 def test_random_email_generation_and_processing(self): 

202 """Test robohash with freshly generated random emails""" 

203 # Generate fresh random emails for this test 

204 fresh_emails = [generate_random_email() for _ in range(5)] 

205 fresh_digests = [ 

206 hashlib.md5(email.encode()).hexdigest() for email in fresh_emails 

207 ] 

208 

209 for i, (email, digest) in enumerate(zip(fresh_emails, fresh_digests)): 

210 with self.subTest(email=email, digest=digest[:8]): 

211 # Test that both original and optimized can process this email 

212 original = Robohash(digest) 

213 original.assemble(roboset="any", sizex=128, sizey=128) 

214 

215 optimized = OptimizedRobohash(digest) 

216 optimized.assemble_fast(roboset="any", sizex=128, sizey=128) 

217 

218 # Verify both produce valid images 

219 self.assertIsNotNone(original.img) 

220 self.assertIsNotNone(optimized.img) 

221 self.assertEqual(original.img.size, (128, 128)) 

222 self.assertEqual(optimized.img.size, (128, 128)) 

223 

224 # Verify they produce identical results 

225 orig_data = BytesIO() 

226 original.img.save(orig_data, format="png") 

227 orig_bytes = orig_data.getvalue() 

228 

229 opt_data = BytesIO() 

230 optimized.img.save(opt_data, format="png") 

231 opt_bytes = opt_data.getvalue() 

232 

233 self.assertEqual( 

234 orig_bytes, 

235 opt_bytes, 

236 f"Random email {email} (digest {digest[:8]}...) produced different images", 

237 )