1import unittest
2import math
3import operator
4import platform
5
6import pygame
7from pygame.compat import long_
8from pygame.colordict import THECOLORS
9
10
11IS_PYPY = "PyPy" == platform.python_implementation()
12################################### CONSTANTS ##################################
13
14rgba_vals = [0, 1, 62, 63, 126, 127, 255]
15
16rgba_combinations = [
17    (r, g, b, a)
18    for r in rgba_vals
19    for g in rgba_vals
20    for b in rgba_vals
21    for a in rgba_vals
22]
23
24################################################################################
25
26
27def rgba_combos_Color_generator():
28    for rgba in rgba_combinations:
29        yield pygame.Color(*rgba)
30
31
32# Python gamma correct
33def gamma_correct(rgba_0_255, gamma):
34    corrected = round(255.0 * math.pow(rgba_0_255 / 255.0, gamma))
35    return max(min(int(corrected), 255), 0)
36
37
38################################################################################
39
40# TODO: add tests for
41# correct_gamma()  -- test against statically defined verified correct values
42# coerce ()        --  ??
43
44
45def _assignr(x, y):
46    x.r = y
47
48
49def _assigng(x, y):
50    x.g = y
51
52
53def _assignb(x, y):
54    x.b = y
55
56
57def _assigna(x, y):
58    x.a = y
59
60
61def _assign_item(x, p, y):
62    x[p] = y
63
64
65class ColorTypeTest(unittest.TestCase):
66    def test_new(self):
67        c = pygame.Color.__new__(pygame.Color)
68        self.assertEqual(c, pygame.Color(0, 0, 0, 255))
69        self.assertEqual(len(c), 4)
70
71    def test_init(self):
72        c = pygame.Color(10, 20, 30, 200)
73        self.assertEqual(c, (10, 20, 30, 200))
74        c.set_length(3)
75        self.assertEqual(len(c), 3)
76        c.__init__(100, 110, 120, 128)
77        self.assertEqual(len(c), 4)
78        self.assertEqual(c, (100, 110, 120, 128))
79
80    def test_invalid_html_hex_codes(self):
81        # This was a problem with the way 2 digit hex numbers were
82        # calculated. The test_hex_digits test is related to the fix.
83        Color = pygame.color.Color
84        self.assertRaises(ValueError, lambda: Color("# f000000"))
85        self.assertRaises(ValueError, lambda: Color("#f 000000"))
86        self.assertRaises(ValueError, lambda: Color("#-f000000"))
87
88    def test_hex_digits(self):
89        # This is an implementation specific test.
90        # Two digit hex numbers are calculated using table lookups
91        # for the upper and lower digits.
92        Color = pygame.color.Color
93        self.assertEqual(Color("#00000000").r, 0x00)
94        self.assertEqual(Color("#10000000").r, 0x10)
95        self.assertEqual(Color("#20000000").r, 0x20)
96        self.assertEqual(Color("#30000000").r, 0x30)
97        self.assertEqual(Color("#40000000").r, 0x40)
98        self.assertEqual(Color("#50000000").r, 0x50)
99        self.assertEqual(Color("#60000000").r, 0x60)
100        self.assertEqual(Color("#70000000").r, 0x70)
101        self.assertEqual(Color("#80000000").r, 0x80)
102        self.assertEqual(Color("#90000000").r, 0x90)
103        self.assertEqual(Color("#A0000000").r, 0xA0)
104        self.assertEqual(Color("#B0000000").r, 0xB0)
105        self.assertEqual(Color("#C0000000").r, 0xC0)
106        self.assertEqual(Color("#D0000000").r, 0xD0)
107        self.assertEqual(Color("#E0000000").r, 0xE0)
108        self.assertEqual(Color("#F0000000").r, 0xF0)
109        self.assertEqual(Color("#01000000").r, 0x01)
110        self.assertEqual(Color("#02000000").r, 0x02)
111        self.assertEqual(Color("#03000000").r, 0x03)
112        self.assertEqual(Color("#04000000").r, 0x04)
113        self.assertEqual(Color("#05000000").r, 0x05)
114        self.assertEqual(Color("#06000000").r, 0x06)
115        self.assertEqual(Color("#07000000").r, 0x07)
116        self.assertEqual(Color("#08000000").r, 0x08)
117        self.assertEqual(Color("#09000000").r, 0x09)
118        self.assertEqual(Color("#0A000000").r, 0x0A)
119        self.assertEqual(Color("#0B000000").r, 0x0B)
120        self.assertEqual(Color("#0C000000").r, 0x0C)
121        self.assertEqual(Color("#0D000000").r, 0x0D)
122        self.assertEqual(Color("#0E000000").r, 0x0E)
123        self.assertEqual(Color("#0F000000").r, 0x0F)
124
125    def test_comparison(self):
126        Color = pygame.color.Color
127
128        # Check valid comparisons
129        self.assertTrue(Color(255, 0, 0, 0) == Color(255, 0, 0, 0))
130        self.assertTrue(Color(0, 255, 0, 0) == Color(0, 255, 0, 0))
131        self.assertTrue(Color(0, 0, 255, 0) == Color(0, 0, 255, 0))
132        self.assertTrue(Color(0, 0, 0, 255) == Color(0, 0, 0, 255))
133        self.assertFalse(Color(0, 0, 0, 0) == Color(255, 0, 0, 0))
134        self.assertFalse(Color(0, 0, 0, 0) == Color(0, 255, 0, 0))
135        self.assertFalse(Color(0, 0, 0, 0) == Color(0, 0, 255, 0))
136        self.assertFalse(Color(0, 0, 0, 0) == Color(0, 0, 0, 255))
137        self.assertTrue(Color(0, 0, 0, 0) != Color(255, 0, 0, 0))
138        self.assertTrue(Color(0, 0, 0, 0) != Color(0, 255, 0, 0))
139        self.assertTrue(Color(0, 0, 0, 0) != Color(0, 0, 255, 0))
140        self.assertTrue(Color(0, 0, 0, 0) != Color(0, 0, 0, 255))
141        self.assertFalse(Color(255, 0, 0, 0) != Color(255, 0, 0, 0))
142        self.assertFalse(Color(0, 255, 0, 0) != Color(0, 255, 0, 0))
143        self.assertFalse(Color(0, 0, 255, 0) != Color(0, 0, 255, 0))
144        self.assertFalse(Color(0, 0, 0, 255) != Color(0, 0, 0, 255))
145
146        self.assertTrue(Color(255, 0, 0, 0) == (255, 0, 0, 0))
147        self.assertTrue(Color(0, 255, 0, 0) == (0, 255, 0, 0))
148        self.assertTrue(Color(0, 0, 255, 0) == (0, 0, 255, 0))
149        self.assertTrue(Color(0, 0, 0, 255) == (0, 0, 0, 255))
150        self.assertFalse(Color(0, 0, 0, 0) == (255, 0, 0, 0))
151        self.assertFalse(Color(0, 0, 0, 0) == (0, 255, 0, 0))
152        self.assertFalse(Color(0, 0, 0, 0) == (0, 0, 255, 0))
153        self.assertFalse(Color(0, 0, 0, 0) == (0, 0, 0, 255))
154        self.assertTrue(Color(0, 0, 0, 0) != (255, 0, 0, 0))
155        self.assertTrue(Color(0, 0, 0, 0) != (0, 255, 0, 0))
156        self.assertTrue(Color(0, 0, 0, 0) != (0, 0, 255, 0))
157        self.assertTrue(Color(0, 0, 0, 0) != (0, 0, 0, 255))
158        self.assertFalse(Color(255, 0, 0, 0) != (255, 0, 0, 0))
159        self.assertFalse(Color(0, 255, 0, 0) != (0, 255, 0, 0))
160        self.assertFalse(Color(0, 0, 255, 0) != (0, 0, 255, 0))
161        self.assertFalse(Color(0, 0, 0, 255) != (0, 0, 0, 255))
162
163        self.assertTrue((255, 0, 0, 0) == Color(255, 0, 0, 0))
164        self.assertTrue((0, 255, 0, 0) == Color(0, 255, 0, 0))
165        self.assertTrue((0, 0, 255, 0) == Color(0, 0, 255, 0))
166        self.assertTrue((0, 0, 0, 255) == Color(0, 0, 0, 255))
167        self.assertFalse((0, 0, 0, 0) == Color(255, 0, 0, 0))
168        self.assertFalse((0, 0, 0, 0) == Color(0, 255, 0, 0))
169        self.assertFalse((0, 0, 0, 0) == Color(0, 0, 255, 0))
170        self.assertFalse((0, 0, 0, 0) == Color(0, 0, 0, 255))
171        self.assertTrue((0, 0, 0, 0) != Color(255, 0, 0, 0))
172        self.assertTrue((0, 0, 0, 0) != Color(0, 255, 0, 0))
173        self.assertTrue((0, 0, 0, 0) != Color(0, 0, 255, 0))
174        self.assertTrue((0, 0, 0, 0) != Color(0, 0, 0, 255))
175        self.assertFalse((255, 0, 0, 0) != Color(255, 0, 0, 0))
176        self.assertFalse((0, 255, 0, 0) != Color(0, 255, 0, 0))
177        self.assertFalse((0, 0, 255, 0) != Color(0, 0, 255, 0))
178        self.assertFalse((0, 0, 0, 255) != Color(0, 0, 0, 255))
179
180        class TupleSubclass(tuple):
181            pass
182
183        self.assertTrue(Color(255, 0, 0, 0) == TupleSubclass((255, 0, 0, 0)))
184        self.assertTrue(TupleSubclass((255, 0, 0, 0)) == Color(255, 0, 0, 0))
185        self.assertFalse(Color(255, 0, 0, 0) != TupleSubclass((255, 0, 0, 0)))
186        self.assertFalse(TupleSubclass((255, 0, 0, 0)) != Color(255, 0, 0, 0))
187
188        # These are not supported so will be unequal.
189        self.assertFalse(Color(255, 0, 0, 0) == "#ff000000")
190        self.assertTrue(Color(255, 0, 0, 0) != "#ff000000")
191
192        self.assertFalse("#ff000000" == Color(255, 0, 0, 0))
193        self.assertTrue("#ff000000" != Color(255, 0, 0, 0))
194
195        self.assertFalse(Color(255, 0, 0, 0) == 0xFF000000)
196        self.assertTrue(Color(255, 0, 0, 0) != 0xFF000000)
197
198        self.assertFalse(0xFF000000 == Color(255, 0, 0, 0))
199        self.assertTrue(0xFF000000 != Color(255, 0, 0, 0))
200
201        self.assertFalse(Color(255, 0, 0, 0) == [255, 0, 0, 0])
202        self.assertTrue(Color(255, 0, 0, 0) != [255, 0, 0, 0])
203
204        self.assertFalse([255, 0, 0, 0] == Color(255, 0, 0, 0))
205        self.assertTrue([255, 0, 0, 0] != Color(255, 0, 0, 0))
206
207        # Comparison is not implemented for invalid color values.
208        class Test(object):
209            def __eq__(self, other):
210                return -1
211
212            def __ne__(self, other):
213                return -2
214
215        class TestTuple(tuple):
216            def __eq__(self, other):
217                return -1
218
219            def __ne__(self, other):
220                return -2
221
222        t = Test()
223        t_tuple = TestTuple(("a", 0, 0, 0))
224        black = Color("black")
225        self.assertEqual(black == t, -1)
226        self.assertEqual(t == black, -1)
227        self.assertEqual(black != t, -2)
228        self.assertEqual(t != black, -2)
229        self.assertEqual(black == t_tuple, -1)
230        self.assertEqual(black != t_tuple, -2)
231        self.assertEqual(t_tuple == black, -1)
232        self.assertEqual(t_tuple != black, -2)
233
234    def test_ignore_whitespace(self):
235        self.assertEqual(pygame.color.Color("red"), pygame.color.Color(" r e d "))
236
237    def test_slice(self):
238        # """|tags: python3_ignore|"""
239
240        # slicing a color gives you back a tuple.
241        # do all sorts of slice combinations.
242        c = pygame.Color(1, 2, 3, 4)
243
244        self.assertEqual((1, 2, 3, 4), c[:])
245        self.assertEqual((1, 2, 3), c[:-1])
246
247        self.assertEqual((), c[:-5])
248
249        self.assertEqual((1, 2, 3, 4), c[:4])
250        self.assertEqual((1, 2, 3, 4), c[:5])
251        self.assertEqual((1, 2), c[:2])
252        self.assertEqual((1,), c[:1])
253        self.assertEqual((), c[:0])
254
255        self.assertEqual((2,), c[1:-2])
256        self.assertEqual((3, 4), c[-2:])
257        self.assertEqual((4,), c[-1:])
258
259        # NOTE: assigning to a slice is currently unsupported.
260
261    def test_unpack(self):
262        # should be able to unpack to r,g,b,a and r,g,b
263        c = pygame.Color(1, 2, 3, 4)
264        r, g, b, a = c
265        self.assertEqual((1, 2, 3, 4), (r, g, b, a))
266        self.assertEqual(c, (r, g, b, a))
267
268        c.set_length(3)
269        r, g, b = c
270        self.assertEqual((1, 2, 3), (r, g, b))
271
272    def test_length(self):
273        # should be able to unpack to r,g,b,a and r,g,b
274        c = pygame.Color(1, 2, 3, 4)
275        self.assertEqual(len(c), 4)
276
277        c.set_length(3)
278        self.assertEqual(len(c), 3)
279
280        # it keeps the old alpha anyway...
281        self.assertEqual(c.a, 4)
282
283        # however you can't get the alpha in this way:
284        self.assertRaises(IndexError, lambda x: c[x], 4)
285
286        c.set_length(4)
287        self.assertEqual(len(c), 4)
288        self.assertEqual(len(c), 4)
289
290        self.assertRaises(ValueError, c.set_length, 5)
291        self.assertRaises(ValueError, c.set_length, -1)
292        self.assertRaises(ValueError, c.set_length, 0)
293        self.assertRaises(ValueError, c.set_length, pow(2, long_(33)))
294
295    def test_case_insensitivity_of_string_args(self):
296        self.assertEqual(pygame.color.Color("red"), pygame.color.Color("Red"))
297
298    def test_color(self):
299        """Ensures Color objects can be created."""
300        color = pygame.Color(0, 0, 0, 0)
301
302        self.assertIsInstance(color, pygame.Color)
303
304    def test_color__rgba_int_args(self):
305        """Ensures Color objects can be created using ints."""
306        color = pygame.Color(10, 20, 30, 40)
307
308        self.assertEqual(color.r, 10)
309        self.assertEqual(color.g, 20)
310        self.assertEqual(color.b, 30)
311        self.assertEqual(color.a, 40)
312
313    def test_color__rgba_int_args_without_alpha(self):
314        """Ensures Color objects can be created without providing alpha."""
315        color = pygame.Color(10, 20, 30)
316
317        self.assertEqual(color.r, 10)
318        self.assertEqual(color.g, 20)
319        self.assertEqual(color.b, 30)
320        self.assertEqual(color.a, 255)
321
322    def test_color__rgba_int_args_invalid_value(self):
323        """Ensures invalid values are detected when creating Color objects."""
324        self.assertRaises(ValueError, pygame.Color, 257, 10, 105, 44)
325        self.assertRaises(ValueError, pygame.Color, 10, 257, 105, 44)
326        self.assertRaises(ValueError, pygame.Color, 10, 105, 257, 44)
327        self.assertRaises(ValueError, pygame.Color, 10, 105, 44, 257)
328
329    def test_color__rgba_int_args_invalid_value_without_alpha(self):
330        """Ensures invalid values are detected when creating Color objects
331        without providing an alpha.
332        """
333        self.assertRaises(ValueError, pygame.Color, 256, 10, 105)
334        self.assertRaises(ValueError, pygame.Color, 10, 256, 105)
335        self.assertRaises(ValueError, pygame.Color, 10, 105, 256)
336
337    def test_color__color_object_arg(self):
338        """Ensures Color objects can be created using Color objects."""
339        color_args = (10, 20, 30, 40)
340        color_obj = pygame.Color(*color_args)
341
342        new_color_obj = pygame.Color(color_obj)
343
344        self.assertIsInstance(new_color_obj, pygame.Color)
345        self.assertEqual(new_color_obj, color_obj)
346        self.assertEqual(new_color_obj.r, color_args[0])
347        self.assertEqual(new_color_obj.g, color_args[1])
348        self.assertEqual(new_color_obj.b, color_args[2])
349        self.assertEqual(new_color_obj.a, color_args[3])
350
351    def test_color__name_str_arg(self):
352        """Ensures Color objects can be created using str names."""
353        for name in ("aquamarine3", "AQUAMARINE3", "AqUAmArIne3"):
354            color = pygame.Color(name)
355
356            self.assertEqual(color.r, 102)
357            self.assertEqual(color.g, 205)
358            self.assertEqual(color.b, 170)
359            self.assertEqual(color.a, 255)
360
361    def test_color__name_str_arg_from_colordict(self):
362        """Ensures Color objects can be created using str names
363        from the THECOLORS dict."""
364        for name, values in THECOLORS.items():
365            color = pygame.Color(name)
366
367            self.assertEqual(color.r, values[0])
368            self.assertEqual(color.g, values[1])
369            self.assertEqual(color.b, values[2])
370            self.assertEqual(color.a, values[3])
371
372    def test_color__html_str_arg(self):
373        """Ensures Color objects can be created using html strings."""
374        # See test_webstyle() for related tests.
375        color = pygame.Color("#a1B2c3D4")
376
377        self.assertEqual(color.r, 0xA1)
378        self.assertEqual(color.g, 0xB2)
379        self.assertEqual(color.b, 0xC3)
380        self.assertEqual(color.a, 0xD4)
381
382    def test_color__hex_str_arg(self):
383        """Ensures Color objects can be created using hex strings."""
384        # See test_webstyle() for related tests.
385        color = pygame.Color("0x1a2B3c4D")
386
387        self.assertEqual(color.r, 0x1A)
388        self.assertEqual(color.g, 0x2B)
389        self.assertEqual(color.b, 0x3C)
390        self.assertEqual(color.a, 0x4D)
391
392    def test_color__int_arg(self):
393        """Ensures Color objects can be created using one int value."""
394        for value in (0x0, 0xFFFFFFFF, 0xAABBCCDD):
395            color = pygame.Color(value)
396
397            self.assertEqual(color.r, (value >> 24) & 0xFF)
398            self.assertEqual(color.g, (value >> 16) & 0xFF)
399            self.assertEqual(color.b, (value >> 8) & 0xFF)
400            self.assertEqual(color.a, value & 0xFF)
401
402    def test_color__int_arg_invalid(self):
403        """Ensures invalid int values are detected when creating Color objects.
404        """
405        with self.assertRaises(ValueError):
406            color = pygame.Color(0x1FFFFFFFF)
407
408    def test_color__sequence_arg(self):
409        """Ensures Color objects can be created using tuples/lists."""
410        color_values = (33, 44, 55, 66)
411        for seq_type in (tuple, list):
412            color = pygame.Color(seq_type(color_values))
413
414            self.assertEqual(color.r, color_values[0])
415            self.assertEqual(color.g, color_values[1])
416            self.assertEqual(color.b, color_values[2])
417            self.assertEqual(color.a, color_values[3])
418
419    def test_color__sequence_arg_without_alpha(self):
420        """Ensures Color objects can be created using tuples/lists
421        without providing an alpha value.
422        """
423        color_values = (33, 44, 55)
424        for seq_type in (tuple, list):
425            color = pygame.Color(seq_type(color_values))
426
427            self.assertEqual(color.r, color_values[0])
428            self.assertEqual(color.g, color_values[1])
429            self.assertEqual(color.b, color_values[2])
430            self.assertEqual(color.a, 255)
431
432    def test_color__sequence_arg_invalid_value(self):
433        """Ensures invalid sequences are detected when creating Color objects.
434        """
435        cls = pygame.Color
436        for seq_type in (tuple, list):
437            self.assertRaises(ValueError, cls, seq_type((256, 90, 80, 70)))
438            self.assertRaises(ValueError, cls, seq_type((100, 256, 80, 70)))
439            self.assertRaises(ValueError, cls, seq_type((100, 90, 256, 70)))
440            self.assertRaises(ValueError, cls, seq_type((100, 90, 80, 256)))
441
442    def test_color__sequence_arg_invalid_value_without_alpha(self):
443        """Ensures invalid sequences are detected when creating Color objects
444        without providing an alpha.
445        """
446        cls = pygame.Color
447        for seq_type in (tuple, list):
448            self.assertRaises(ValueError, cls, seq_type((256, 90, 80)))
449            self.assertRaises(ValueError, cls, seq_type((100, 256, 80)))
450            self.assertRaises(ValueError, cls, seq_type((100, 90, 256)))
451
452    def test_color__sequence_arg_invalid_format(self):
453        """Ensures invalid sequences are detected when creating Color objects
454        with the wrong number of values.
455        """
456        cls = pygame.Color
457        for seq_type in (tuple, list):
458            self.assertRaises(ValueError, cls, seq_type((100,)))
459            self.assertRaises(ValueError, cls, seq_type((100, 90)))
460            self.assertRaises(ValueError, cls, seq_type((100, 90, 80, 70, 60)))
461
462    def test_rgba(self):
463        c = pygame.Color(0)
464        self.assertEqual(c.r, 0)
465        self.assertEqual(c.g, 0)
466        self.assertEqual(c.b, 0)
467        self.assertEqual(c.a, 0)
468
469        # Test simple assignments
470        c.r = 123
471        self.assertEqual(c.r, 123)
472        self.assertRaises(ValueError, _assignr, c, 537)
473        self.assertEqual(c.r, 123)
474        self.assertRaises(ValueError, _assignr, c, -3)
475        self.assertEqual(c.r, 123)
476
477        c.g = 55
478        self.assertEqual(c.g, 55)
479        self.assertRaises(ValueError, _assigng, c, 348)
480        self.assertEqual(c.g, 55)
481        self.assertRaises(ValueError, _assigng, c, -44)
482        self.assertEqual(c.g, 55)
483
484        c.b = 77
485        self.assertEqual(c.b, 77)
486        self.assertRaises(ValueError, _assignb, c, 256)
487        self.assertEqual(c.b, 77)
488        self.assertRaises(ValueError, _assignb, c, -12)
489        self.assertEqual(c.b, 77)
490
491        c.a = 255
492        self.assertEqual(c.a, 255)
493        self.assertRaises(ValueError, _assigna, c, 312)
494        self.assertEqual(c.a, 255)
495        self.assertRaises(ValueError, _assigna, c, -10)
496        self.assertEqual(c.a, 255)
497
498    def test_repr(self):
499        c = pygame.Color(68, 38, 26, 69)
500        t = "(68, 38, 26, 69)"
501        self.assertEqual(repr(c), t)
502
503    def test_add(self):
504        c1 = pygame.Color(0)
505        self.assertEqual(c1.r, 0)
506        self.assertEqual(c1.g, 0)
507        self.assertEqual(c1.b, 0)
508        self.assertEqual(c1.a, 0)
509
510        c2 = pygame.Color(20, 33, 82, 193)
511        self.assertEqual(c2.r, 20)
512        self.assertEqual(c2.g, 33)
513        self.assertEqual(c2.b, 82)
514        self.assertEqual(c2.a, 193)
515
516        c3 = c1 + c2
517        self.assertEqual(c3.r, 20)
518        self.assertEqual(c3.g, 33)
519        self.assertEqual(c3.b, 82)
520        self.assertEqual(c3.a, 193)
521
522        c3 = c3 + c2
523        self.assertEqual(c3.r, 40)
524        self.assertEqual(c3.g, 66)
525        self.assertEqual(c3.b, 164)
526        self.assertEqual(c3.a, 255)
527
528        # Issue #286: Is type checking done for Python 3.x?
529        self.assertRaises(TypeError, operator.add, c1, None)
530        self.assertRaises(TypeError, operator.add, None, c1)
531
532    def test_sub(self):
533        c1 = pygame.Color(0xFFFFFFFF)
534        self.assertEqual(c1.r, 255)
535        self.assertEqual(c1.g, 255)
536        self.assertEqual(c1.b, 255)
537        self.assertEqual(c1.a, 255)
538
539        c2 = pygame.Color(20, 33, 82, 193)
540        self.assertEqual(c2.r, 20)
541        self.assertEqual(c2.g, 33)
542        self.assertEqual(c2.b, 82)
543        self.assertEqual(c2.a, 193)
544
545        c3 = c1 - c2
546        self.assertEqual(c3.r, 235)
547        self.assertEqual(c3.g, 222)
548        self.assertEqual(c3.b, 173)
549        self.assertEqual(c3.a, 62)
550
551        c3 = c3 - c2
552        self.assertEqual(c3.r, 215)
553        self.assertEqual(c3.g, 189)
554        self.assertEqual(c3.b, 91)
555        self.assertEqual(c3.a, 0)
556
557        # Issue #286: Is type checking done for Python 3.x?
558        self.assertRaises(TypeError, operator.sub, c1, None)
559        self.assertRaises(TypeError, operator.sub, None, c1)
560
561    def test_mul(self):
562        c1 = pygame.Color(0x01010101)
563        self.assertEqual(c1.r, 1)
564        self.assertEqual(c1.g, 1)
565        self.assertEqual(c1.b, 1)
566        self.assertEqual(c1.a, 1)
567
568        c2 = pygame.Color(2, 5, 3, 22)
569        self.assertEqual(c2.r, 2)
570        self.assertEqual(c2.g, 5)
571        self.assertEqual(c2.b, 3)
572        self.assertEqual(c2.a, 22)
573
574        c3 = c1 * c2
575        self.assertEqual(c3.r, 2)
576        self.assertEqual(c3.g, 5)
577        self.assertEqual(c3.b, 3)
578        self.assertEqual(c3.a, 22)
579
580        c3 = c3 * c2
581        self.assertEqual(c3.r, 4)
582        self.assertEqual(c3.g, 25)
583        self.assertEqual(c3.b, 9)
584        self.assertEqual(c3.a, 255)
585
586        # Issue #286: Is type checking done for Python 3.x?
587        self.assertRaises(TypeError, operator.mul, c1, None)
588        self.assertRaises(TypeError, operator.mul, None, c1)
589
590    def test_div(self):
591        c1 = pygame.Color(0x80808080)
592        self.assertEqual(c1.r, 128)
593        self.assertEqual(c1.g, 128)
594        self.assertEqual(c1.b, 128)
595        self.assertEqual(c1.a, 128)
596
597        c2 = pygame.Color(2, 4, 8, 16)
598        self.assertEqual(c2.r, 2)
599        self.assertEqual(c2.g, 4)
600        self.assertEqual(c2.b, 8)
601        self.assertEqual(c2.a, 16)
602
603        c3 = c1 // c2
604        self.assertEqual(c3.r, 64)
605        self.assertEqual(c3.g, 32)
606        self.assertEqual(c3.b, 16)
607        self.assertEqual(c3.a, 8)
608
609        c3 = c3 // c2
610        self.assertEqual(c3.r, 32)
611        self.assertEqual(c3.g, 8)
612        self.assertEqual(c3.b, 2)
613        self.assertEqual(c3.a, 0)
614
615        # Issue #286: Is type checking done for Python 3.x?
616        self.assertRaises(TypeError, operator.floordiv, c1, None)
617        self.assertRaises(TypeError, operator.floordiv, None, c1)
618
619        # Division by zero check
620        dividend = pygame.Color(255, 255, 255, 255)
621        for i in range(4):
622            divisor = pygame.Color(64, 64, 64, 64)
623            divisor[i] = 0
624            quotient = pygame.Color(3, 3, 3, 3)
625            quotient[i] = 0
626            self.assertEqual(dividend // divisor, quotient)
627
628    def test_mod(self):
629        c1 = pygame.Color(0xFFFFFFFF)
630        self.assertEqual(c1.r, 255)
631        self.assertEqual(c1.g, 255)
632        self.assertEqual(c1.b, 255)
633        self.assertEqual(c1.a, 255)
634
635        c2 = pygame.Color(2, 4, 8, 16)
636        self.assertEqual(c2.r, 2)
637        self.assertEqual(c2.g, 4)
638        self.assertEqual(c2.b, 8)
639        self.assertEqual(c2.a, 16)
640
641        c3 = c1 % c2
642        self.assertEqual(c3.r, 1)
643        self.assertEqual(c3.g, 3)
644        self.assertEqual(c3.b, 7)
645        self.assertEqual(c3.a, 15)
646
647        # Issue #286: Is type checking done for Python 3.x?
648        self.assertRaises(TypeError, operator.mod, c1, None)
649        self.assertRaises(TypeError, operator.mod, None, c1)
650
651        # Division by zero check
652        dividend = pygame.Color(255, 255, 255, 255)
653        for i in range(4):
654            divisor = pygame.Color(64, 64, 64, 64)
655            divisor[i] = 0
656            quotient = pygame.Color(63, 63, 63, 63)
657            quotient[i] = 0
658            self.assertEqual(dividend % divisor, quotient)
659
660    def test_float(self):
661        c = pygame.Color(0xCC00CC00)
662        self.assertEqual(c.r, 204)
663        self.assertEqual(c.g, 0)
664        self.assertEqual(c.b, 204)
665        self.assertEqual(c.a, 0)
666        self.assertEqual(float(c), float(0xCC00CC00))
667
668        c = pygame.Color(0x33727592)
669        self.assertEqual(c.r, 51)
670        self.assertEqual(c.g, 114)
671        self.assertEqual(c.b, 117)
672        self.assertEqual(c.a, 146)
673        self.assertEqual(float(c), float(0x33727592))
674
675    def test_oct(self):
676        c = pygame.Color(0xCC00CC00)
677        self.assertEqual(c.r, 204)
678        self.assertEqual(c.g, 0)
679        self.assertEqual(c.b, 204)
680        self.assertEqual(c.a, 0)
681        self.assertEqual(oct(c), oct(0xCC00CC00))
682
683        c = pygame.Color(0x33727592)
684        self.assertEqual(c.r, 51)
685        self.assertEqual(c.g, 114)
686        self.assertEqual(c.b, 117)
687        self.assertEqual(c.a, 146)
688        self.assertEqual(oct(c), oct(0x33727592))
689
690    def test_hex(self):
691        c = pygame.Color(0xCC00CC00)
692        self.assertEqual(c.r, 204)
693        self.assertEqual(c.g, 0)
694        self.assertEqual(c.b, 204)
695        self.assertEqual(c.a, 0)
696        self.assertEqual(hex(c), hex(0xCC00CC00))
697
698        c = pygame.Color(0x33727592)
699        self.assertEqual(c.r, 51)
700        self.assertEqual(c.g, 114)
701        self.assertEqual(c.b, 117)
702        self.assertEqual(c.a, 146)
703        self.assertEqual(hex(c), hex(0x33727592))
704
705    def test_webstyle(self):
706        c = pygame.Color("#CC00CC11")
707        self.assertEqual(c.r, 204)
708        self.assertEqual(c.g, 0)
709        self.assertEqual(c.b, 204)
710        self.assertEqual(c.a, 17)
711        self.assertEqual(hex(c), hex(0xCC00CC11))
712
713        c = pygame.Color("#CC00CC")
714        self.assertEqual(c.r, 204)
715        self.assertEqual(c.g, 0)
716        self.assertEqual(c.b, 204)
717        self.assertEqual(c.a, 255)
718        self.assertEqual(hex(c), hex(0xCC00CCFF))
719
720        c = pygame.Color("0xCC00CC11")
721        self.assertEqual(c.r, 204)
722        self.assertEqual(c.g, 0)
723        self.assertEqual(c.b, 204)
724        self.assertEqual(c.a, 17)
725        self.assertEqual(hex(c), hex(0xCC00CC11))
726
727        c = pygame.Color("0xCC00CC")
728        self.assertEqual(c.r, 204)
729        self.assertEqual(c.g, 0)
730        self.assertEqual(c.b, 204)
731        self.assertEqual(c.a, 255)
732        self.assertEqual(hex(c), hex(0xCC00CCFF))
733
734        self.assertRaises(ValueError, pygame.Color, "#cc00qq")
735        self.assertRaises(ValueError, pygame.Color, "0xcc00qq")
736        self.assertRaises(ValueError, pygame.Color, "09abcdef")
737        self.assertRaises(ValueError, pygame.Color, "09abcde")
738        self.assertRaises(ValueError, pygame.Color, "quarky")
739
740    def test_int(self):
741        # This will be a long
742        c = pygame.Color(0xCC00CC00)
743        self.assertEqual(c.r, 204)
744        self.assertEqual(c.g, 0)
745        self.assertEqual(c.b, 204)
746        self.assertEqual(c.a, 0)
747        self.assertEqual(int(c), int(0xCC00CC00))
748
749        # This will be an int
750        c = pygame.Color(0x33727592)
751        self.assertEqual(c.r, 51)
752        self.assertEqual(c.g, 114)
753        self.assertEqual(c.b, 117)
754        self.assertEqual(c.a, 146)
755        self.assertEqual(int(c), int(0x33727592))
756
757    def test_long(self):
758        # This will be a long
759        c = pygame.Color(0xCC00CC00)
760        self.assertEqual(c.r, 204)
761        self.assertEqual(c.g, 0)
762        self.assertEqual(c.b, 204)
763        self.assertEqual(c.a, 0)
764        self.assertEqual(long_(c), long_(0xCC00CC00))
765
766        # This will be an int
767        c = pygame.Color(0x33727592)
768        self.assertEqual(c.r, 51)
769        self.assertEqual(c.g, 114)
770        self.assertEqual(c.b, 117)
771        self.assertEqual(c.a, 146)
772        self.assertEqual(long_(c), long_(0x33727592))
773
774    def test_normalize(self):
775        c = pygame.Color(204, 38, 194, 55)
776        self.assertEqual(c.r, 204)
777        self.assertEqual(c.g, 38)
778        self.assertEqual(c.b, 194)
779        self.assertEqual(c.a, 55)
780
781        t = c.normalize()
782
783        self.assertAlmostEqual(t[0], 0.800000, 5)
784        self.assertAlmostEqual(t[1], 0.149016, 5)
785        self.assertAlmostEqual(t[2], 0.760784, 5)
786        self.assertAlmostEqual(t[3], 0.215686, 5)
787
788    def test_len(self):
789        c = pygame.Color(204, 38, 194, 55)
790        self.assertEqual(len(c), 4)
791
792    def test_get_item(self):
793        c = pygame.Color(204, 38, 194, 55)
794        self.assertEqual(c[0], 204)
795        self.assertEqual(c[1], 38)
796        self.assertEqual(c[2], 194)
797        self.assertEqual(c[3], 55)
798
799    def test_set_item(self):
800        c = pygame.Color(204, 38, 194, 55)
801        self.assertEqual(c[0], 204)
802        self.assertEqual(c[1], 38)
803        self.assertEqual(c[2], 194)
804        self.assertEqual(c[3], 55)
805
806        c[0] = 33
807        self.assertEqual(c[0], 33)
808        c[1] = 48
809        self.assertEqual(c[1], 48)
810        c[2] = 173
811        self.assertEqual(c[2], 173)
812        c[3] = 213
813        self.assertEqual(c[3], 213)
814
815        # Now try some 'invalid' ones
816        self.assertRaises(TypeError, _assign_item, c, 0, 95.485)
817        self.assertEqual(c[0], 33)
818        self.assertRaises(ValueError, _assign_item, c, 1, -83)
819        self.assertEqual(c[1], 48)
820        self.assertRaises(TypeError, _assign_item, c, 2, "Hello")
821        self.assertEqual(c[2], 173)
822
823    def test_Color_type_works_for_Surface_get_and_set_colorkey(self):
824        s = pygame.Surface((32, 32))
825
826        c = pygame.Color(33, 22, 11, 255)
827        s.set_colorkey(c)
828
829        get_r, get_g, get_b, get_a = s.get_colorkey()
830
831        self.assertTrue(get_r == c.r)
832        self.assertTrue(get_g == c.g)
833        self.assertTrue(get_b == c.b)
834        self.assertTrue(get_a == c.a)
835
836    ########## HSLA, HSVA, CMY, I1I2I3 ALL ELEMENTS WITHIN SPECIFIED RANGE #########
837
838    def test_hsla__all_elements_within_limits(self):
839        for c in rgba_combos_Color_generator():
840            h, s, l, a = c.hsla
841            self.assertTrue(0 <= h <= 360)
842            self.assertTrue(0 <= s <= 100)
843            self.assertTrue(0 <= l <= 100)
844            self.assertTrue(0 <= a <= 100)
845
846    def test_hsva__all_elements_within_limits(self):
847        for c in rgba_combos_Color_generator():
848            h, s, v, a = c.hsva
849            self.assertTrue(0 <= h <= 360)
850            self.assertTrue(0 <= s <= 100)
851            self.assertTrue(0 <= v <= 100)
852            self.assertTrue(0 <= a <= 100)
853
854    def test_cmy__all_elements_within_limits(self):
855        for c in rgba_combos_Color_generator():
856            c, m, y = c.cmy
857            self.assertTrue(0 <= c <= 1)
858            self.assertTrue(0 <= m <= 1)
859            self.assertTrue(0 <= y <= 1)
860
861    def test_i1i2i3__all_elements_within_limits(self):
862        for c in rgba_combos_Color_generator():
863            i1, i2, i3 = c.i1i2i3
864            self.assertTrue(0 <= i1 <= 1)
865            self.assertTrue(-0.5 <= i2 <= 0.5)
866            self.assertTrue(-0.5 <= i3 <= 0.5)
867
868    def test_issue_269(self):
869        """PyColor OverflowError on HSVA with hue value of 360
870
871           >>> c = pygame.Color(0)
872           >>> c.hsva = (360,0,0,0)
873           Traceback (most recent call last):
874             File "<stdin>", line 1, in <module>
875           OverflowError: this is not allowed to happen ever
876           >>> pygame.ver
877           '1.9.1release'
878           >>>
879
880        """
881
882        c = pygame.Color(0)
883        c.hsva = 360, 0, 0, 0
884        self.assertEqual(c.hsva, (0, 0, 0, 0))
885        c.hsva = 360, 100, 100, 100
886        self.assertEqual(c.hsva, (0, 100, 100, 100))
887        self.assertEqual(c, (255, 0, 0, 255))
888
889    ####################### COLORSPACE PROPERTY SANITY TESTS #######################
890
891    def colorspaces_converted_should_not_raise(self, prop):
892        fails = 0
893
894        x = 0
895        for c in rgba_combos_Color_generator():
896            x += 1
897
898            other = pygame.Color(0)
899
900            try:
901                setattr(other, prop, getattr(c, prop))
902                # eg other.hsla = c.hsla
903
904            except ValueError:
905                fails += 1
906
907        self.assertTrue(x > 0, "x is combination counter, 0 means no tests!")
908        self.assertTrue((fails, x) == (0, x))
909
910    def test_hsla__sanity_testing_converted_should_not_raise(self):
911        self.colorspaces_converted_should_not_raise("hsla")
912
913    def test_hsva__sanity_testing_converted_should_not_raise(self):
914        self.colorspaces_converted_should_not_raise("hsva")
915
916    def test_cmy__sanity_testing_converted_should_not_raise(self):
917        self.colorspaces_converted_should_not_raise("cmy")
918
919    def test_i1i2i3__sanity_testing_converted_should_not_raise(self):
920        self.colorspaces_converted_should_not_raise("i1i2i3")
921
922    ################################################################################
923
924    def colorspaces_converted_should_equate_bar_rounding(self, prop):
925        for c in rgba_combos_Color_generator():
926            other = pygame.Color(0)
927
928            try:
929                setattr(other, prop, getattr(c, prop))
930                # eg other.hsla = c.hsla
931
932                self.assertTrue(abs(other.r - c.r) <= 1)
933                self.assertTrue(abs(other.b - c.b) <= 1)
934                self.assertTrue(abs(other.g - c.g) <= 1)
935                # CMY and I1I2I3 do not care about the alpha
936                if not prop in ("cmy", "i1i2i3"):
937                    self.assertTrue(abs(other.a - c.a) <= 1)
938
939            except ValueError:
940                pass  # other tests will notify, this tests equation
941
942    def test_hsla__sanity_testing_converted_should_equate_bar_rounding(self):
943        self.colorspaces_converted_should_equate_bar_rounding("hsla")
944
945    def test_hsva__sanity_testing_converted_should_equate_bar_rounding(self):
946        self.colorspaces_converted_should_equate_bar_rounding("hsva")
947
948    def test_cmy__sanity_testing_converted_should_equate_bar_rounding(self):
949        self.colorspaces_converted_should_equate_bar_rounding("cmy")
950
951    def test_i1i2i3__sanity_testing_converted_should_equate_bar_rounding(self):
952        self.colorspaces_converted_should_equate_bar_rounding("i1i2i3")
953
954    ################################################################################
955
956    def test_correct_gamma__verified_against_python_implementation(self):
957        "|tags:slow|"
958        # gamma_correct defined at top of page
959
960        gammas = [i / 10.0 for i in range(1, 31)]  # [0.1 ... 3.0]
961        gammas_len = len(gammas)
962
963        for i, c in enumerate(rgba_combos_Color_generator()):
964            gamma = gammas[i % gammas_len]
965
966            corrected = pygame.Color(*[gamma_correct(x, gamma) for x in tuple(c)])
967            lib_corrected = c.correct_gamma(gamma)
968
969            self.assertTrue(corrected.r == lib_corrected.r)
970            self.assertTrue(corrected.g == lib_corrected.g)
971            self.assertTrue(corrected.b == lib_corrected.b)
972            self.assertTrue(corrected.a == lib_corrected.a)
973
974        # TODO: test against statically defined verified _correct_ values
975        # assert corrected.r == 125 etc.
976
977    def test_pickle(self):
978        import pickle
979
980        c1 = pygame.Color(1, 2, 3, 4)
981        # c2 = pygame.Color(255,254,253,252)
982        pickle_string = pickle.dumps(c1)
983        c1_frompickle = pickle.loads(pickle_string)
984        self.assertEqual(c1, c1_frompickle)
985
986    ################################################################################
987    # only available if ctypes module is also available
988
989    @unittest.skipIf(IS_PYPY, "PyPy has no ctypes")
990    def test_arraystruct(self):
991
992        import pygame.tests.test_utils.arrinter as ai
993        import ctypes as ct
994
995        c_byte_p = ct.POINTER(ct.c_byte)
996        c = pygame.Color(5, 7, 13, 23)
997        flags = ai.PAI_CONTIGUOUS | ai.PAI_FORTRAN | ai.PAI_ALIGNED | ai.PAI_NOTSWAPPED
998        for i in range(1, 5):
999            c.set_length(i)
1000            inter = ai.ArrayInterface(c)
1001            self.assertEqual(inter.two, 2)
1002            self.assertEqual(inter.nd, 1)
1003            self.assertEqual(inter.typekind, "u")
1004            self.assertEqual(inter.itemsize, 1)
1005            self.assertEqual(inter.flags, flags)
1006            self.assertEqual(inter.shape[0], i)
1007            self.assertEqual(inter.strides[0], 1)
1008            data = ct.cast(inter.data, c_byte_p)
1009            for j in range(i):
1010                self.assertEqual(data[j], c[j])
1011
1012    @unittest.skipIf(not pygame.HAVE_NEWBUF, "newbuf not implemented")
1013    def test_newbuf(self):
1014        from pygame.tests.test_utils import buftools
1015        from ctypes import cast, POINTER, c_uint8
1016
1017        class ColorImporter(buftools.Importer):
1018            def __init__(self, color, flags):
1019                super(ColorImporter, self).__init__(color, flags)
1020                self.items = cast(self.buf, POINTER(c_uint8))
1021
1022            def __getitem__(self, index):
1023                if 0 <= index < 4:
1024                    return self.items[index]
1025                raise IndexError(
1026                    "valid index values are between 0 and 3: " "got {}".format(index)
1027                )
1028
1029            def __setitem__(self, index, value):
1030                if 0 <= index < 4:
1031                    self.items[index] = value
1032                else:
1033                    raise IndexError(
1034                        "valid index values are between 0 and 3: "
1035                        "got {}".format(index)
1036                    )
1037
1038        c = pygame.Color(50, 100, 150, 200)
1039        imp = ColorImporter(c, buftools.PyBUF_SIMPLE)
1040        self.assertTrue(imp.obj is c)
1041        self.assertEqual(imp.ndim, 0)
1042        self.assertEqual(imp.itemsize, 1)
1043        self.assertEqual(imp.len, 4)
1044        self.assertTrue(imp.readonly)
1045        self.assertTrue(imp.format is None)
1046        self.assertTrue(imp.shape is None)
1047        self.assertTrue(imp.strides is None)
1048        self.assertTrue(imp.suboffsets is None)
1049        for i in range(4):
1050            self.assertEqual(c[i], imp[i])
1051        imp[0] = 60
1052        self.assertEqual(c.r, 60)
1053        imp[1] = 110
1054        self.assertEqual(c.g, 110)
1055        imp[2] = 160
1056        self.assertEqual(c.b, 160)
1057        imp[3] = 210
1058        self.assertEqual(c.a, 210)
1059        imp = ColorImporter(c, buftools.PyBUF_FORMAT)
1060        self.assertEqual(imp.ndim, 0)
1061        self.assertEqual(imp.itemsize, 1)
1062        self.assertEqual(imp.len, 4)
1063        self.assertEqual(imp.format, "B")
1064        self.assertEqual(imp.ndim, 0)
1065        self.assertEqual(imp.itemsize, 1)
1066        self.assertEqual(imp.len, 4)
1067        imp = ColorImporter(c, buftools.PyBUF_ND)
1068        self.assertEqual(imp.ndim, 1)
1069        self.assertEqual(imp.itemsize, 1)
1070        self.assertEqual(imp.len, 4)
1071        self.assertTrue(imp.format is None)
1072        self.assertEqual(imp.shape, (4,))
1073        self.assertEqual(imp.strides, None)
1074        imp = ColorImporter(c, buftools.PyBUF_STRIDES)
1075        self.assertEqual(imp.ndim, 1)
1076        self.assertTrue(imp.format is None)
1077        self.assertEqual(imp.shape, (4,))
1078        self.assertEqual(imp.strides, (1,))
1079        imp = ColorImporter(c, buftools.PyBUF_C_CONTIGUOUS)
1080        self.assertEqual(imp.ndim, 1)
1081        imp = ColorImporter(c, buftools.PyBUF_F_CONTIGUOUS)
1082        self.assertEqual(imp.ndim, 1)
1083        imp = ColorImporter(c, buftools.PyBUF_ANY_CONTIGUOUS)
1084        self.assertEqual(imp.ndim, 1)
1085        for i in range(1, 5):
1086            c.set_length(i)
1087            imp = ColorImporter(c, buftools.PyBUF_ND)
1088            self.assertEqual(imp.ndim, 1)
1089            self.assertEqual(imp.len, i)
1090            self.assertEqual(imp.shape, (i,))
1091        self.assertRaises(BufferError, ColorImporter, c, buftools.PyBUF_WRITABLE)
1092
1093    def test_lerp(self):
1094        # setup
1095        Color = pygame.color.Color
1096
1097        color0 = Color(0, 0, 0, 0)
1098        color128 = Color(128, 128, 128, 128)
1099        color255 = Color(255, 255, 255, 255)
1100        color100 = Color(100, 100, 100, 100)
1101
1102        # type checking
1103        self.assertTrue(isinstance(color0.lerp(color128, 0.5), Color))
1104
1105        # common value testing
1106        self.assertEqual(color0.lerp(color128, 0.5), Color(64, 64, 64, 64))
1107        self.assertEqual(color0.lerp(color128, 0.5), Color(64, 64, 64, 64))
1108        self.assertEqual(color128.lerp(color255, 0.5), Color(192, 192, 192, 192))
1109        self.assertEqual(color0.lerp(color255, 0.5), Color(128, 128, 128, 128))
1110
1111        # testing extremes
1112        self.assertEqual(color0.lerp(color100, 0), color0)
1113        self.assertEqual(color0.lerp(color100, 0.01), Color(1, 1, 1, 1))
1114        self.assertEqual(color0.lerp(color100, 0.99), Color(99, 99, 99, 99))
1115        self.assertEqual(color0.lerp(color100, 1), color100)
1116
1117        # kwarg testing
1118        self.assertEqual(color0.lerp(color=color100, amount=0.5), Color(50, 50, 50, 50))
1119        self.assertEqual(color0.lerp(amount=0.5, color=color100), Color(50, 50, 50, 50))
1120
1121        # invalid input testing
1122        self.assertRaises(ValueError, lambda: color0.lerp(color128, 2.5))
1123        self.assertRaises(ValueError, lambda: color0.lerp(color128, -0.5))
1124        self.assertRaises(ValueError, lambda: color0.lerp((256, 0, 0, 0), 0.5))
1125        self.assertRaises(ValueError, lambda: color0.lerp((0, 256, 0, 0), 0.5))
1126        self.assertRaises(ValueError, lambda: color0.lerp((0, 0, 256, 0), 0.5))
1127        self.assertRaises(ValueError, lambda: color0.lerp((0, 0, 0, 256), 0.5))
1128        self.assertRaises(TypeError, lambda: color0.lerp(0.2, 0.5))
1129
1130    def test_premul_alpha(self):
1131        # setup
1132        Color = pygame.color.Color
1133
1134        color0 = Color(0, 0, 0, 0)
1135        alpha0 = Color(255, 255, 255, 0)
1136        alpha49 = Color(255, 0, 0, 49)
1137        alpha67 = Color(0, 255, 0, 67)
1138        alpha73 = Color(0, 0, 255, 73)
1139        alpha128 = Color(255, 255, 255, 128)
1140        alpha199 = Color(255, 255, 255, 199)
1141        alpha255 = Color(128, 128, 128, 255)
1142
1143        # type checking
1144        self.assertTrue(isinstance(color0.premul_alpha(), Color))
1145
1146        # hand crafted value testing
1147        self.assertEqual(alpha0.premul_alpha(), Color(0, 0, 0, 0))
1148        self.assertEqual(alpha49.premul_alpha(), Color(49, 0, 0, 49))
1149        self.assertEqual(alpha67.premul_alpha(), Color(0, 67, 0, 67))
1150        self.assertEqual(alpha73.premul_alpha(), Color(0, 0, 73, 73))
1151        self.assertEqual(alpha128.premul_alpha(), Color(128, 128, 128, 128))
1152        self.assertEqual(alpha199.premul_alpha(), Color(199, 199, 199, 199))
1153        self.assertEqual(alpha255.premul_alpha(), Color(128, 128, 128, 255))
1154
1155        # full range of alpha auto sub-testing
1156        test_colors = [(200, 30, 74), (76, 83, 24), (184, 21, 6),
1157                       (74, 4, 74), (76, 83, 24), (184, 21, 234),
1158                       (160, 30, 74), (96, 147, 204), (198, 201, 60),
1159                       (132, 89, 74), (245, 9, 224), (184, 112, 6)]
1160
1161        for r, g, b in test_colors:
1162            for a in range(255):
1163                with self.subTest(r=r, g=g, b=b, a=a):
1164                    alpha = a/255.0
1165                    self.assertEqual(Color(r, g, b, a).premul_alpha(),
1166                                     Color(((r + 1) * a) >> 8,
1167                                           ((g + 1) * a) >> 8,
1168                                           ((b + 1) * a) >> 8,
1169                                           a))
1170
1171    def test_update(self):
1172        c = pygame.color.Color(0, 0, 0)
1173        c.update(1, 2, 3, 4)
1174
1175        self.assertEqual(c.r, 1)
1176        self.assertEqual(c.g, 2)
1177        self.assertEqual(c.b, 3)
1178        self.assertEqual(c.a, 4)
1179
1180        c = pygame.color.Color(0, 0, 0)
1181        c.update([1, 2, 3, 4])
1182
1183        self.assertEqual(c.r, 1)
1184        self.assertEqual(c.g, 2)
1185        self.assertEqual(c.b, 3)
1186        self.assertEqual(c.a, 4)
1187
1188        c = pygame.color.Color(0, 0, 0)
1189        c2 = pygame.color.Color(1, 2, 3, 4)
1190        c.update(c2)
1191
1192        self.assertEqual(c.r, 1)
1193        self.assertEqual(c.g, 2)
1194        self.assertEqual(c.b, 3)
1195        self.assertEqual(c.a, 4)
1196
1197        c = pygame.color.Color(1, 1, 1)
1198        c.update("black")
1199
1200        self.assertEqual(c.r, 0)
1201        self.assertEqual(c.g, 0)
1202        self.assertEqual(c.b, 0)
1203        self.assertEqual(c.a, 255)
1204
1205        c = pygame.color.Color(0, 0, 0, 120)
1206        c.set_length(3)
1207        c.update(1, 2, 3)
1208        self.assertEqual(len(c), 3)
1209        c.set_length(4)
1210        self.assertEqual(c[3], 120)
1211
1212        c.set_length(3)
1213        c.update(1, 2, 3, 4)
1214        self.assertEqual(len(c), 4)
1215
1216class SubclassTest(unittest.TestCase):
1217    class MyColor(pygame.Color):
1218        def __init__(self, *args, **kwds):
1219            super(SubclassTest.MyColor, self).__init__(*args, **kwds)
1220            self.an_attribute = True
1221
1222    def test_add(self):
1223        mc1 = self.MyColor(128, 128, 128, 255)
1224        self.assertTrue(mc1.an_attribute)
1225        c2 = pygame.Color(64, 64, 64, 255)
1226        mc2 = mc1 + c2
1227        self.assertTrue(isinstance(mc2, self.MyColor))
1228        self.assertRaises(AttributeError, getattr, mc2, "an_attribute")
1229        c3 = c2 + mc1
1230        self.assertTrue(type(c3) is pygame.Color)
1231
1232    def test_sub(self):
1233        mc1 = self.MyColor(128, 128, 128, 255)
1234        self.assertTrue(mc1.an_attribute)
1235        c2 = pygame.Color(64, 64, 64, 255)
1236        mc2 = mc1 - c2
1237        self.assertTrue(isinstance(mc2, self.MyColor))
1238        self.assertRaises(AttributeError, getattr, mc2, "an_attribute")
1239        c3 = c2 - mc1
1240        self.assertTrue(type(c3) is pygame.Color)
1241
1242    def test_mul(self):
1243        mc1 = self.MyColor(128, 128, 128, 255)
1244        self.assertTrue(mc1.an_attribute)
1245        c2 = pygame.Color(64, 64, 64, 255)
1246        mc2 = mc1 * c2
1247        self.assertTrue(isinstance(mc2, self.MyColor))
1248        self.assertRaises(AttributeError, getattr, mc2, "an_attribute")
1249        c3 = c2 * mc1
1250        self.assertTrue(type(c3) is pygame.Color)
1251
1252    def test_div(self):
1253        mc1 = self.MyColor(128, 128, 128, 255)
1254        self.assertTrue(mc1.an_attribute)
1255        c2 = pygame.Color(64, 64, 64, 255)
1256        mc2 = mc1 // c2
1257        self.assertTrue(isinstance(mc2, self.MyColor))
1258        self.assertRaises(AttributeError, getattr, mc2, "an_attribute")
1259        c3 = c2 // mc1
1260        self.assertTrue(type(c3) is pygame.Color)
1261
1262    def test_mod(self):
1263        mc1 = self.MyColor(128, 128, 128, 255)
1264        self.assertTrue(mc1.an_attribute)
1265        c2 = pygame.Color(64, 64, 64, 255)
1266        mc2 = mc1 % c2
1267        self.assertTrue(isinstance(mc2, self.MyColor))
1268        self.assertRaises(AttributeError, getattr, mc2, "an_attribute")
1269        c3 = c2 % mc1
1270        self.assertTrue(type(c3) is pygame.Color)
1271
1272    def test_inv(self):
1273        mc1 = self.MyColor(64, 64, 64, 64)
1274        self.assertTrue(mc1.an_attribute)
1275        mc2 = ~mc1
1276        self.assertTrue(isinstance(mc2, self.MyColor))
1277        self.assertRaises(AttributeError, getattr, mc2, "an_attribute")
1278
1279    def test_correct_gamma(self):
1280        mc1 = self.MyColor(64, 70, 75, 255)
1281        self.assertTrue(mc1.an_attribute)
1282        mc2 = mc1.correct_gamma(0.03)
1283        self.assertTrue(isinstance(mc2, self.MyColor))
1284        self.assertRaises(AttributeError, getattr, mc2, "an_attribute")
1285
1286
1287################################################################################
1288
1289if __name__ == "__main__":
1290    unittest.main()
1291