1import unittest
2from ctypes import *
3
4formats = "bBhHiIlLqQfd"
5
6formats = c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint, \
7          c_long, c_ulonglong, c_float, c_double, c_longdouble
8
9class ArrayTestCase(unittest.TestCase):
10    def test_simple(self):
11        # create classes holding simple numeric types, and check
12        # various properties.
13
14        init = range(15, 25)
15
16        for fmt in formats:
17            alen = len(init)
18            int_array = ARRAY(fmt, alen)
19
20            ia = int_array(*init)
21            # length of instance ok?
22            self.assertEqual(len(ia), alen)
23
24            # slot values ok?
25            values = [ia[i] for i in range(len(init))]
26            self.assertEqual(values, init)
27
28            # change the items
29            from operator import setitem
30            new_values = range(42, 42+alen)
31            [setitem(ia, n, new_values[n]) for n in range(alen)]
32            values = [ia[i] for i in range(len(init))]
33            self.assertEqual(values, new_values)
34
35            # are the items initialized to 0?
36            ia = int_array()
37            values = [ia[i] for i in range(len(init))]
38            self.assertEqual(values, [0] * len(init))
39
40            # Too many initializers should be caught
41            self.assertRaises(IndexError, int_array, *range(alen*2))
42
43        CharArray = ARRAY(c_char, 3)
44
45        ca = CharArray("a", "b", "c")
46
47        # Should this work? It doesn't:
48        # CharArray("abc")
49        self.assertRaises(TypeError, CharArray, "abc")
50
51        self.assertEqual(ca[0], "a")
52        self.assertEqual(ca[1], "b")
53        self.assertEqual(ca[2], "c")
54        self.assertEqual(ca[-3], "a")
55        self.assertEqual(ca[-2], "b")
56        self.assertEqual(ca[-1], "c")
57
58        self.assertEqual(len(ca), 3)
59
60        # slicing is now supported, but not extended slicing (3-argument)!
61        from operator import getslice, delitem
62        self.assertRaises(TypeError, getslice, ca, 0, 1, -1)
63
64        # cannot delete items
65        self.assertRaises(TypeError, delitem, ca, 0)
66
67    def test_numeric_arrays(self):
68
69        alen = 5
70
71        numarray = ARRAY(c_int, alen)
72
73        na = numarray()
74        values = [na[i] for i in range(alen)]
75        self.assertEqual(values, [0] * alen)
76
77        na = numarray(*[c_int()] * alen)
78        values = [na[i] for i in range(alen)]
79        self.assertEqual(values, [0]*alen)
80
81        na = numarray(1, 2, 3, 4, 5)
82        values = [i for i in na]
83        self.assertEqual(values, [1, 2, 3, 4, 5])
84
85        na = numarray(*map(c_int, (1, 2, 3, 4, 5)))
86        values = [i for i in na]
87        self.assertEqual(values, [1, 2, 3, 4, 5])
88
89    def test_classcache(self):
90        self.assertTrue(not ARRAY(c_int, 3) is ARRAY(c_int, 4))
91        self.assertTrue(ARRAY(c_int, 3) is ARRAY(c_int, 3))
92
93    def test_from_address(self):
94        # Failed with 0.9.8, reported by JUrner
95        p = create_string_buffer("foo")
96        sz = (c_char * 3).from_address(addressof(p))
97        self.assertEqual(sz[:], "foo")
98        self.assertEqual(sz[::], "foo")
99        self.assertEqual(sz[::-1], "oof")
100        self.assertEqual(sz[::3], "f")
101        self.assertEqual(sz[1:4:2], "o")
102        self.assertEqual(sz.value, "foo")
103
104    try:
105        create_unicode_buffer
106    except NameError:
107        pass
108    else:
109        def test_from_addressW(self):
110            p = create_unicode_buffer("foo")
111            sz = (c_wchar * 3).from_address(addressof(p))
112            self.assertEqual(sz[:], "foo")
113            self.assertEqual(sz[::], "foo")
114            self.assertEqual(sz[::-1], "oof")
115            self.assertEqual(sz[::3], "f")
116            self.assertEqual(sz[1:4:2], "o")
117            self.assertEqual(sz.value, "foo")
118
119    def test_cache(self):
120        # Array types are cached internally in the _ctypes extension,
121        # in a WeakValueDictionary.  Make sure the array type is
122        # removed from the cache when the itemtype goes away.  This
123        # test will not fail, but will show a leak in the testsuite.
124
125        # Create a new type:
126        class my_int(c_int):
127            pass
128        # Create a new array type based on it:
129        t1 = my_int * 1
130        t2 = my_int * 1
131        self.assertTrue(t1 is t2)
132
133if __name__ == '__main__':
134    unittest.main()
135