Merge branch 'master' into blender2.8
[blender.git] / tests / python / rna_array.py
1 # Apache License, Version 2.0
2
3 import unittest
4 import random
5
6 test = bpy.data.test
7
8 # farr - 1-dimensional array of float
9 # fdarr - dynamic 1-dimensional array of float
10 # fmarr - 3-dimensional ([3][4][5]) array of float
11 # fdmarr - dynamic 3-dimensional (ditto size) array of float
12
13 # same as above for other types except that the first letter is "i" for int and "b" for bool
14
15
16 class TestArray(unittest.TestCase):
17     # test that assignment works by: assign -> test value
18     # - rvalue = list of float
19     # - rvalue = list of numbers
20     # test.object
21     # bpy.data.test.farr[3], iarr[3], barr[...], fmarr, imarr, bmarr
22
23     def setUp(self):
24         test.farr = (1.0, 2.0, 3.0)
25         test.iarr = (7, 8, 9)
26         test.barr = (False, True, False)
27
28     # test access
29     # test slice access, negative indices
30     def test_access(self):
31         rvals = ([1.0, 2.0, 3.0], [7, 8, 9], [False, True, False])
32         for arr, rval in zip((test.farr, test.iarr, test.barr), rvals):
33             self.assertEqual(prop_to_list(arr), rval)
34             self.assertEqual(arr[0:3], rval)
35             self.assertEqual(arr[1:2], rval[1:2])
36             self.assertEqual(arr[-1], arr[2])
37             self.assertEqual(arr[-2], arr[1])
38             self.assertEqual(arr[-3], arr[0])
39
40     # fail when index out of bounds
41     def test_access_fail(self):
42         for arr in (test.farr, test.iarr, test.barr):
43             self.assertRaises(IndexError, lambda: arr[4])
44
45     # test assignment of a whole array
46     def test_assign_array(self):
47         # should accept int as float
48         test.farr = (1, 2, 3)
49
50     # fail when: unexpected no. of items, invalid item type
51     def test_assign_array_fail(self):
52         def assign_empty_list(arr):
53             setattr(test, arr, ())
54
55         for arr in ("farr", "iarr", "barr"):
56             self.assertRaises(ValueError, assign_empty_list, arr)
57
58         def assign_invalid_float():
59             test.farr = (1.0, 2.0, "3.0")
60
61         def assign_invalid_int():
62             test.iarr = ("1", 2, 3)
63
64         def assign_invalid_bool():
65             test.barr = (True, 0.123, False)
66
67         for func in [assign_invalid_float, assign_invalid_int, assign_invalid_bool]:
68             self.assertRaises(TypeError, func)
69
70         # shouldn't accept float as int
71         def assign_float_as_int():
72             test.iarr = (1, 2, 3.0)
73         self.assertRaises(TypeError, assign_float_as_int)
74
75         # non-dynamic arrays cannot change size
76         def assign_different_size(arr, val):
77             setattr(test, arr, val)
78         for arr, val in zip(("iarr", "farr", "barr"), ((1, 2), (1.0, 2.0), (True, False))):
79             self.assertRaises(ValueError, assign_different_size, arr, val)
80
81     # test assignment of specific items
82     def test_assign_item(self):
83         for arr, rand_func in zip((test.farr, test.iarr, test.barr), (rand_float, rand_int, rand_bool)):
84             for i in range(len(arr)):
85                 val = rand_func()
86                 arr[i] = val
87
88                 self.assertEqual(arr[i], val)
89
90         # float prop should accept also int
91         for i in range(len(test.farr)):
92             val = rand_int()
93             test.farr[i] = val
94             self.assertEqual(test.farr[i], float(val))
95
96         #
97
98     def test_assign_item_fail(self):
99         def assign_bad_index(arr):
100             arr[4] = 1.0
101
102         def assign_bad_type(arr):
103             arr[1] = "123"
104
105         for arr in [test.farr, test.iarr, test.barr]:
106             self.assertRaises(IndexError, assign_bad_index, arr)
107
108         # not testing bool because bool allows not only (True|False)
109         for arr in [test.farr, test.iarr]:
110             self.assertRaises(TypeError, assign_bad_type, arr)
111
112     def test_dynamic_assign_array(self):
113         # test various lengths here
114         for arr, rand_func in zip(("fdarr", "idarr", "bdarr"), (rand_float, rand_int, rand_bool)):
115             for length in range(1, 64):
116                 rval = make_random_array(length, rand_func)
117                 setattr(test, arr, rval)
118                 self.assertEqual(prop_to_list(getattr(test, arr)), rval)
119
120     def test_dynamic_assign_array_fail(self):
121         # could also test too big length here
122
123         def assign_empty_list(arr):
124             setattr(test, arr, ())
125
126         for arr in ("fdarr", "idarr", "bdarr"):
127             self.assertRaises(ValueError, assign_empty_list, arr)
128
129
130 class TestMArray(unittest.TestCase):
131     def setUp(self):
132         # reset dynamic array sizes
133         for arr, func in zip(("fdmarr", "idmarr", "bdmarr"), (rand_float, rand_int, rand_bool)):
134             setattr(test, arr, make_random_3d_array((3, 4, 5), func))
135
136     # test assignment
137     def test_assign_array(self):
138         for arr, func in zip(("fmarr", "imarr", "bmarr"), (rand_float, rand_int, rand_bool)):
139             # assignment of [3][4][5]
140             rval = make_random_3d_array((3, 4, 5), func)
141             setattr(test, arr, rval)
142             self.assertEqual(prop_to_list(getattr(test, arr)), rval)
143
144         # test assignment of [2][4][5], [1][4][5] should work on dynamic arrays
145
146     def test_assign_array_fail(self):
147         def assign_empty_array():
148             test.fmarr = ()
149         self.assertRaises(ValueError, assign_empty_array)
150
151         def assign_invalid_size(arr, rval):
152             setattr(test, arr, rval)
153
154         # assignment of 3,4,4 or 3,3,5 should raise ex
155         for arr, func in zip(("fmarr", "imarr", "bmarr"), (rand_float, rand_int, rand_bool)):
156             rval = make_random_3d_array((3, 4, 4), func)
157             self.assertRaises(ValueError, assign_invalid_size, arr, rval)
158
159             rval = make_random_3d_array((3, 3, 5), func)
160             self.assertRaises(ValueError, assign_invalid_size, arr, rval)
161
162             rval = make_random_3d_array((3, 3, 3), func)
163             self.assertRaises(ValueError, assign_invalid_size, arr, rval)
164
165     def test_assign_item(self):
166         # arr[i] = x
167         for arr, func in zip(("fmarr", "imarr", "bmarr", "fdmarr", "idmarr", "bdmarr"), (rand_float, rand_int, rand_bool) * 2):
168             rval = make_random_2d_array((4, 5), func)
169
170             for i in range(3):
171                 getattr(test, arr)[i] = rval
172                 self.assertEqual(prop_to_list(getattr(test, arr)[i]), rval)
173
174         # arr[i][j] = x
175         for arr, func in zip(("fmarr", "imarr", "bmarr", "fdmarr", "idmarr", "bdmarr"), (rand_float, rand_int, rand_bool) * 2):
176
177             arr = getattr(test, arr)
178             rval = make_random_array(5, func)
179
180             for i in range(3):
181                 for j in range(4):
182                     arr[i][j] = rval
183                     self.assertEqual(prop_to_list(arr[i][j]), rval)
184
185     def test_assign_item_fail(self):
186         def assign_wrong_size(arr, i, rval):
187             getattr(test, arr)[i] = rval
188
189         # assign wrong size at level 2
190         for arr, func in zip(("fmarr", "imarr", "bmarr"), (rand_float, rand_int, rand_bool)):
191             rval1 = make_random_2d_array((3, 5), func)
192             rval2 = make_random_2d_array((4, 3), func)
193
194             for i in range(3):
195                 self.assertRaises(ValueError, assign_wrong_size, arr, i, rval1)
196                 self.assertRaises(ValueError, assign_wrong_size, arr, i, rval2)
197
198     def test_dynamic_assign_array(self):
199         for arr, func in zip(("fdmarr", "idmarr", "bdmarr"), (rand_float, rand_int, rand_bool)):
200             # assignment of [3][4][5]
201             rval = make_random_3d_array((3, 4, 5), func)
202             setattr(test, arr, rval)
203             self.assertEqual(prop_to_list(getattr(test, arr)), rval)
204
205             # [2][4][5]
206             rval = make_random_3d_array((2, 4, 5), func)
207             setattr(test, arr, rval)
208             self.assertEqual(prop_to_list(getattr(test, arr)), rval)
209
210             # [1][4][5]
211             rval = make_random_3d_array((1, 4, 5), func)
212             setattr(test, arr, rval)
213             self.assertEqual(prop_to_list(getattr(test, arr)), rval)
214
215     # test access
216
217     def test_access(self):
218         pass
219
220     # test slice access, negative indices
221     def test_access_fail(self):
222         pass
223
224
225 random.seed()
226
227
228 def rand_int():
229     return random.randint(-1000, 1000)
230
231
232 def rand_float():
233     return float(rand_int())
234
235
236 def rand_bool():
237     return bool(random.randint(0, 1))
238
239
240 def make_random_array(len, rand_func):
241     arr = []
242     for i in range(len):
243         arr.append(rand_func())
244
245     return arr
246
247
248 def make_random_2d_array(dimsize, rand_func):
249     marr = []
250     for i in range(dimsize[0]):
251         marr.append([])
252
253         for j in range(dimsize[1]):
254             marr[-1].append(rand_func())
255
256     return marr
257
258
259 def make_random_3d_array(dimsize, rand_func):
260     marr = []
261     for i in range(dimsize[0]):
262         marr.append([])
263
264         for j in range(dimsize[1]):
265             marr[-1].append([])
266
267             for k in range(dimsize[2]):
268                 marr[-1][-1].append(rand_func())
269
270     return marr
271
272
273 def prop_to_list(prop):
274     ret = []
275
276     for x in prop:
277         if type(x) not in {bool, int, float}:
278             ret.append(prop_to_list(x))
279         else:
280             ret.append(x)
281
282     return ret
283
284
285 def suite():
286     return unittest.TestSuite([unittest.TestLoader().loadTestsFromTestCase(TestArray), unittest.TestLoader().loadTestsFromTestCase(TestMArray)])
287
288
289 if __name__ == "__main__":
290     unittest.TextTestRunner(verbosity=2).run(suite())