1 """Unit tests for the memoryview
2
3 Some tests are in test_bytes. Many tests that require _testbuffer.ndarray
4 are in test_buffer.
5 """
6
7 import unittest
8 import test.support
9 import sys
10 import gc
11 import weakref
12 import array
13 import io
14 import copy
15 import pickle
16
17 from test.support import import_helper
18
19
20 class ESC[4;38;5;81mAbstractMemoryTests:
21 source_bytes = b"abcdef"
22
23 @property
24 def _source(self):
25 return self.source_bytes
26
27 @property
28 def _types(self):
29 return filter(None, [self.ro_type, self.rw_type])
30
31 def check_getitem_with_type(self, tp):
32 b = tp(self._source)
33 oldrefcount = sys.getrefcount(b)
34 m = self._view(b)
35 self.assertEqual(m[0], ord(b"a"))
36 self.assertIsInstance(m[0], int)
37 self.assertEqual(m[5], ord(b"f"))
38 self.assertEqual(m[-1], ord(b"f"))
39 self.assertEqual(m[-6], ord(b"a"))
40 # Bounds checking
41 self.assertRaises(IndexError, lambda: m[6])
42 self.assertRaises(IndexError, lambda: m[-7])
43 self.assertRaises(IndexError, lambda: m[sys.maxsize])
44 self.assertRaises(IndexError, lambda: m[-sys.maxsize])
45 # Type checking
46 self.assertRaises(TypeError, lambda: m[None])
47 self.assertRaises(TypeError, lambda: m[0.0])
48 self.assertRaises(TypeError, lambda: m["a"])
49 m = None
50 self.assertEqual(sys.getrefcount(b), oldrefcount)
51
52 def test_getitem(self):
53 for tp in self._types:
54 self.check_getitem_with_type(tp)
55
56 def test_iter(self):
57 for tp in self._types:
58 b = tp(self._source)
59 m = self._view(b)
60 self.assertEqual(list(m), [m[i] for i in range(len(m))])
61
62 def test_setitem_readonly(self):
63 if not self.ro_type:
64 self.skipTest("no read-only type to test")
65 b = self.ro_type(self._source)
66 oldrefcount = sys.getrefcount(b)
67 m = self._view(b)
68 def setitem(value):
69 m[0] = value
70 self.assertRaises(TypeError, setitem, b"a")
71 self.assertRaises(TypeError, setitem, 65)
72 self.assertRaises(TypeError, setitem, memoryview(b"a"))
73 m = None
74 self.assertEqual(sys.getrefcount(b), oldrefcount)
75
76 def test_setitem_writable(self):
77 if not self.rw_type:
78 self.skipTest("no writable type to test")
79 tp = self.rw_type
80 b = self.rw_type(self._source)
81 oldrefcount = sys.getrefcount(b)
82 m = self._view(b)
83 m[0] = ord(b'1')
84 self._check_contents(tp, b, b"1bcdef")
85 m[0:1] = tp(b"0")
86 self._check_contents(tp, b, b"0bcdef")
87 m[1:3] = tp(b"12")
88 self._check_contents(tp, b, b"012def")
89 m[1:1] = tp(b"")
90 self._check_contents(tp, b, b"012def")
91 m[:] = tp(b"abcdef")
92 self._check_contents(tp, b, b"abcdef")
93
94 # Overlapping copies of a view into itself
95 m[0:3] = m[2:5]
96 self._check_contents(tp, b, b"cdedef")
97 m[:] = tp(b"abcdef")
98 m[2:5] = m[0:3]
99 self._check_contents(tp, b, b"ababcf")
100
101 def setitem(key, value):
102 m[key] = tp(value)
103 # Bounds checking
104 self.assertRaises(IndexError, setitem, 6, b"a")
105 self.assertRaises(IndexError, setitem, -7, b"a")
106 self.assertRaises(IndexError, setitem, sys.maxsize, b"a")
107 self.assertRaises(IndexError, setitem, -sys.maxsize, b"a")
108 # Wrong index/slice types
109 self.assertRaises(TypeError, setitem, 0.0, b"a")
110 self.assertRaises(TypeError, setitem, (0,), b"a")
111 self.assertRaises(TypeError, setitem, (slice(0,1,1), 0), b"a")
112 self.assertRaises(TypeError, setitem, (0, slice(0,1,1)), b"a")
113 self.assertRaises(TypeError, setitem, (0,), b"a")
114 self.assertRaises(TypeError, setitem, "a", b"a")
115 # Not implemented: multidimensional slices
116 slices = (slice(0,1,1), slice(0,1,2))
117 self.assertRaises(NotImplementedError, setitem, slices, b"a")
118 # Trying to resize the memory object
119 exc = ValueError if m.format == 'c' else TypeError
120 self.assertRaises(exc, setitem, 0, b"")
121 self.assertRaises(exc, setitem, 0, b"ab")
122 self.assertRaises(ValueError, setitem, slice(1,1), b"a")
123 self.assertRaises(ValueError, setitem, slice(0,2), b"a")
124
125 m = None
126 self.assertEqual(sys.getrefcount(b), oldrefcount)
127
128 def test_delitem(self):
129 for tp in self._types:
130 b = tp(self._source)
131 m = self._view(b)
132 with self.assertRaises(TypeError):
133 del m[1]
134 with self.assertRaises(TypeError):
135 del m[1:4]
136
137 def test_tobytes(self):
138 for tp in self._types:
139 m = self._view(tp(self._source))
140 b = m.tobytes()
141 # This calls self.getitem_type() on each separate byte of b"abcdef"
142 expected = b"".join(
143 self.getitem_type(bytes([c])) for c in b"abcdef")
144 self.assertEqual(b, expected)
145 self.assertIsInstance(b, bytes)
146
147 def test_tolist(self):
148 for tp in self._types:
149 m = self._view(tp(self._source))
150 l = m.tolist()
151 self.assertEqual(l, list(b"abcdef"))
152
153 def test_compare(self):
154 # memoryviews can compare for equality with other objects
155 # having the buffer interface.
156 for tp in self._types:
157 m = self._view(tp(self._source))
158 for tp_comp in self._types:
159 self.assertTrue(m == tp_comp(b"abcdef"))
160 self.assertFalse(m != tp_comp(b"abcdef"))
161 self.assertFalse(m == tp_comp(b"abcde"))
162 self.assertTrue(m != tp_comp(b"abcde"))
163 self.assertFalse(m == tp_comp(b"abcde1"))
164 self.assertTrue(m != tp_comp(b"abcde1"))
165 self.assertTrue(m == m)
166 self.assertTrue(m == m[:])
167 self.assertTrue(m[0:6] == m[:])
168 self.assertFalse(m[0:5] == m)
169
170 # Comparison with objects which don't support the buffer API
171 self.assertFalse(m == "abcdef")
172 self.assertTrue(m != "abcdef")
173 self.assertFalse("abcdef" == m)
174 self.assertTrue("abcdef" != m)
175
176 # Unordered comparisons
177 for c in (m, b"abcdef"):
178 self.assertRaises(TypeError, lambda: m < c)
179 self.assertRaises(TypeError, lambda: c <= m)
180 self.assertRaises(TypeError, lambda: m >= c)
181 self.assertRaises(TypeError, lambda: c > m)
182
183 def check_attributes_with_type(self, tp):
184 m = self._view(tp(self._source))
185 self.assertEqual(m.format, self.format)
186 self.assertEqual(m.itemsize, self.itemsize)
187 self.assertEqual(m.ndim, 1)
188 self.assertEqual(m.shape, (6,))
189 self.assertEqual(len(m), 6)
190 self.assertEqual(m.strides, (self.itemsize,))
191 self.assertEqual(m.suboffsets, ())
192 return m
193
194 def test_attributes_readonly(self):
195 if not self.ro_type:
196 self.skipTest("no read-only type to test")
197 m = self.check_attributes_with_type(self.ro_type)
198 self.assertEqual(m.readonly, True)
199
200 def test_attributes_writable(self):
201 if not self.rw_type:
202 self.skipTest("no writable type to test")
203 m = self.check_attributes_with_type(self.rw_type)
204 self.assertEqual(m.readonly, False)
205
206 def test_getbuffer(self):
207 # Test PyObject_GetBuffer() on a memoryview object.
208 for tp in self._types:
209 b = tp(self._source)
210 oldrefcount = sys.getrefcount(b)
211 m = self._view(b)
212 oldviewrefcount = sys.getrefcount(m)
213 s = str(m, "utf-8")
214 self._check_contents(tp, b, s.encode("utf-8"))
215 self.assertEqual(sys.getrefcount(m), oldviewrefcount)
216 m = None
217 self.assertEqual(sys.getrefcount(b), oldrefcount)
218
219 def test_gc(self):
220 for tp in self._types:
221 if not isinstance(tp, type):
222 # If tp is a factory rather than a plain type, skip
223 continue
224
225 class ESC[4;38;5;81mMyView():
226 def __init__(self, base):
227 self.m = memoryview(base)
228 class ESC[4;38;5;81mMySource(ESC[4;38;5;149mtp):
229 pass
230 class ESC[4;38;5;81mMyObject:
231 pass
232
233 # Create a reference cycle through a memoryview object.
234 # This exercises mbuf_clear().
235 b = MySource(tp(b'abc'))
236 m = self._view(b)
237 o = MyObject()
238 b.m = m
239 b.o = o
240 wr = weakref.ref(o)
241 b = m = o = None
242 # The cycle must be broken
243 gc.collect()
244 self.assertTrue(wr() is None, wr())
245
246 # This exercises memory_clear().
247 m = MyView(tp(b'abc'))
248 o = MyObject()
249 m.x = m
250 m.o = o
251 wr = weakref.ref(o)
252 m = o = None
253 # The cycle must be broken
254 gc.collect()
255 self.assertTrue(wr() is None, wr())
256
257 def _check_released(self, m, tp):
258 check = self.assertRaisesRegex(ValueError, "released")
259 with check: bytes(m)
260 with check: m.tobytes()
261 with check: m.tolist()
262 with check: m[0]
263 with check: m[0] = b'x'
264 with check: len(m)
265 with check: m.format
266 with check: m.itemsize
267 with check: m.ndim
268 with check: m.readonly
269 with check: m.shape
270 with check: m.strides
271 with check:
272 with m:
273 pass
274 # str() and repr() still function
275 self.assertIn("released memory", str(m))
276 self.assertIn("released memory", repr(m))
277 self.assertEqual(m, m)
278 self.assertNotEqual(m, memoryview(tp(self._source)))
279 self.assertNotEqual(m, tp(self._source))
280
281 def test_contextmanager(self):
282 for tp in self._types:
283 b = tp(self._source)
284 m = self._view(b)
285 with m as cm:
286 self.assertIs(cm, m)
287 self._check_released(m, tp)
288 m = self._view(b)
289 # Can release explicitly inside the context manager
290 with m:
291 m.release()
292
293 def test_release(self):
294 for tp in self._types:
295 b = tp(self._source)
296 m = self._view(b)
297 m.release()
298 self._check_released(m, tp)
299 # Can be called a second time (it's a no-op)
300 m.release()
301 self._check_released(m, tp)
302
303 def test_writable_readonly(self):
304 # Issue #10451: memoryview incorrectly exposes a readonly
305 # buffer as writable causing a segfault if using mmap
306 tp = self.ro_type
307 if tp is None:
308 self.skipTest("no read-only type to test")
309 b = tp(self._source)
310 m = self._view(b)
311 i = io.BytesIO(b'ZZZZ')
312 self.assertRaises(TypeError, i.readinto, m)
313
314 def test_getbuf_fail(self):
315 self.assertRaises(TypeError, self._view, {})
316
317 def test_hash(self):
318 # Memoryviews of readonly (hashable) types are hashable, and they
319 # hash as hash(obj.tobytes()).
320 tp = self.ro_type
321 if tp is None:
322 self.skipTest("no read-only type to test")
323 b = tp(self._source)
324 m = self._view(b)
325 self.assertEqual(hash(m), hash(b"abcdef"))
326 # Releasing the memoryview keeps the stored hash value (as with weakrefs)
327 m.release()
328 self.assertEqual(hash(m), hash(b"abcdef"))
329 # Hashing a memoryview for the first time after it is released
330 # results in an error (as with weakrefs).
331 m = self._view(b)
332 m.release()
333 self.assertRaises(ValueError, hash, m)
334
335 def test_hash_writable(self):
336 # Memoryviews of writable types are unhashable
337 tp = self.rw_type
338 if tp is None:
339 self.skipTest("no writable type to test")
340 b = tp(self._source)
341 m = self._view(b)
342 self.assertRaises(ValueError, hash, m)
343
344 def test_weakref(self):
345 # Check memoryviews are weakrefable
346 for tp in self._types:
347 b = tp(self._source)
348 m = self._view(b)
349 L = []
350 def callback(wr, b=b):
351 L.append(b)
352 wr = weakref.ref(m, callback)
353 self.assertIs(wr(), m)
354 del m
355 test.support.gc_collect()
356 self.assertIs(wr(), None)
357 self.assertIs(L[0], b)
358
359 def test_reversed(self):
360 for tp in self._types:
361 b = tp(self._source)
362 m = self._view(b)
363 aslist = list(reversed(m.tolist()))
364 self.assertEqual(list(reversed(m)), aslist)
365 self.assertEqual(list(reversed(m)), list(m[::-1]))
366
367 def test_toreadonly(self):
368 for tp in self._types:
369 b = tp(self._source)
370 m = self._view(b)
371 mm = m.toreadonly()
372 self.assertTrue(mm.readonly)
373 self.assertTrue(memoryview(mm).readonly)
374 self.assertEqual(mm.tolist(), m.tolist())
375 mm.release()
376 m.tolist()
377
378 def test_issue22668(self):
379 a = array.array('H', [256, 256, 256, 256])
380 x = memoryview(a)
381 m = x.cast('B')
382 b = m.cast('H')
383 c = b[0:2]
384 d = memoryview(b)
385
386 del b
387
388 self.assertEqual(c[0], 256)
389 self.assertEqual(d[0], 256)
390 self.assertEqual(c.format, "H")
391 self.assertEqual(d.format, "H")
392
393 _ = m.cast('I')
394 self.assertEqual(c[0], 256)
395 self.assertEqual(d[0], 256)
396 self.assertEqual(c.format, "H")
397 self.assertEqual(d.format, "H")
398
399
400 # Variations on source objects for the buffer: bytes-like objects, then arrays
401 # with itemsize > 1.
402 # NOTE: support for multi-dimensional objects is unimplemented.
403
404 class ESC[4;38;5;81mBaseBytesMemoryTests(ESC[4;38;5;149mAbstractMemoryTests):
405 ro_type = bytes
406 rw_type = bytearray
407 getitem_type = bytes
408 itemsize = 1
409 format = 'B'
410
411 class ESC[4;38;5;81mBaseArrayMemoryTests(ESC[4;38;5;149mAbstractMemoryTests):
412 ro_type = None
413 rw_type = lambda self, b: array.array('i', list(b))
414 getitem_type = lambda self, b: array.array('i', list(b)).tobytes()
415 itemsize = array.array('i').itemsize
416 format = 'i'
417
418 @unittest.skip('XXX test should be adapted for non-byte buffers')
419 def test_getbuffer(self):
420 pass
421
422 @unittest.skip('XXX NotImplementedError: tolist() only supports byte views')
423 def test_tolist(self):
424 pass
425
426
427 # Variations on indirection levels: memoryview, slice of memoryview,
428 # slice of slice of memoryview.
429 # This is important to test allocation subtleties.
430
431 class ESC[4;38;5;81mBaseMemoryviewTests:
432 def _view(self, obj):
433 return memoryview(obj)
434
435 def _check_contents(self, tp, obj, contents):
436 self.assertEqual(obj, tp(contents))
437
438 class ESC[4;38;5;81mBaseMemorySliceTests:
439 source_bytes = b"XabcdefY"
440
441 def _view(self, obj):
442 m = memoryview(obj)
443 return m[1:7]
444
445 def _check_contents(self, tp, obj, contents):
446 self.assertEqual(obj[1:7], tp(contents))
447
448 def test_refs(self):
449 for tp in self._types:
450 m = memoryview(tp(self._source))
451 oldrefcount = sys.getrefcount(m)
452 m[1:2]
453 self.assertEqual(sys.getrefcount(m), oldrefcount)
454
455 class ESC[4;38;5;81mBaseMemorySliceSliceTests:
456 source_bytes = b"XabcdefY"
457
458 def _view(self, obj):
459 m = memoryview(obj)
460 return m[:7][1:]
461
462 def _check_contents(self, tp, obj, contents):
463 self.assertEqual(obj[1:7], tp(contents))
464
465
466 # Concrete test classes
467
468 class ESC[4;38;5;81mBytesMemoryviewTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase,
469 ESC[4;38;5;149mBaseMemoryviewTests, ESC[4;38;5;149mBaseBytesMemoryTests):
470
471 def test_constructor(self):
472 for tp in self._types:
473 ob = tp(self._source)
474 self.assertTrue(memoryview(ob))
475 self.assertTrue(memoryview(object=ob))
476 self.assertRaises(TypeError, memoryview)
477 self.assertRaises(TypeError, memoryview, ob, ob)
478 self.assertRaises(TypeError, memoryview, argument=ob)
479 self.assertRaises(TypeError, memoryview, ob, argument=True)
480
481 class ESC[4;38;5;81mArrayMemoryviewTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase,
482 ESC[4;38;5;149mBaseMemoryviewTests, ESC[4;38;5;149mBaseArrayMemoryTests):
483
484 def test_array_assign(self):
485 # Issue #4569: segfault when mutating a memoryview with itemsize != 1
486 a = array.array('i', range(10))
487 m = memoryview(a)
488 new_a = array.array('i', range(9, -1, -1))
489 m[:] = new_a
490 self.assertEqual(a, new_a)
491
492
493 class ESC[4;38;5;81mBytesMemorySliceTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase,
494 ESC[4;38;5;149mBaseMemorySliceTests, ESC[4;38;5;149mBaseBytesMemoryTests):
495 pass
496
497 class ESC[4;38;5;81mArrayMemorySliceTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase,
498 ESC[4;38;5;149mBaseMemorySliceTests, ESC[4;38;5;149mBaseArrayMemoryTests):
499 pass
500
501 class ESC[4;38;5;81mBytesMemorySliceSliceTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase,
502 ESC[4;38;5;149mBaseMemorySliceSliceTests, ESC[4;38;5;149mBaseBytesMemoryTests):
503 pass
504
505 class ESC[4;38;5;81mArrayMemorySliceSliceTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase,
506 ESC[4;38;5;149mBaseMemorySliceSliceTests, ESC[4;38;5;149mBaseArrayMemoryTests):
507 pass
508
509
510 class ESC[4;38;5;81mOtherTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
511 def test_ctypes_cast(self):
512 # Issue 15944: Allow all source formats when casting to bytes.
513 ctypes = import_helper.import_module("ctypes")
514 p6 = bytes(ctypes.c_double(0.6))
515
516 d = ctypes.c_double()
517 m = memoryview(d).cast("B")
518 m[:2] = p6[:2]
519 m[2:] = p6[2:]
520 self.assertEqual(d.value, 0.6)
521
522 for format in "Bbc":
523 with self.subTest(format):
524 d = ctypes.c_double()
525 m = memoryview(d).cast(format)
526 m[:2] = memoryview(p6).cast(format)[:2]
527 m[2:] = memoryview(p6).cast(format)[2:]
528 self.assertEqual(d.value, 0.6)
529
530 def test_memoryview_hex(self):
531 # Issue #9951: memoryview.hex() segfaults with non-contiguous buffers.
532 x = b'0' * 200000
533 m1 = memoryview(x)
534 m2 = m1[::-1]
535 self.assertEqual(m2.hex(), '30' * 200000)
536
537 def test_copy(self):
538 m = memoryview(b'abc')
539 with self.assertRaises(TypeError):
540 copy.copy(m)
541
542 def test_pickle(self):
543 m = memoryview(b'abc')
544 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
545 with self.assertRaises(TypeError):
546 pickle.dumps(m, proto)
547
548 def test_use_released_memory(self):
549 # gh-92888: Previously it was possible to use a memoryview even after
550 # backing buffer is freed in certain cases. This tests that those
551 # cases raise an exception.
552 size = 128
553 def release():
554 m.release()
555 nonlocal ba
556 ba = bytearray(size)
557 class ESC[4;38;5;81mMyIndex:
558 def __index__(self):
559 release()
560 return 4
561 class ESC[4;38;5;81mMyFloat:
562 def __float__(self):
563 release()
564 return 4.25
565 class ESC[4;38;5;81mMyBool:
566 def __bool__(self):
567 release()
568 return True
569
570 ba = None
571 m = memoryview(bytearray(b'\xff'*size))
572 with self.assertRaises(ValueError):
573 m[MyIndex()]
574
575 ba = None
576 m = memoryview(bytearray(b'\xff'*size))
577 self.assertEqual(list(m[:MyIndex()]), [255] * 4)
578
579 ba = None
580 m = memoryview(bytearray(b'\xff'*size))
581 self.assertEqual(list(m[MyIndex():8]), [255] * 4)
582
583 ba = None
584 m = memoryview(bytearray(b'\xff'*size)).cast('B', (64, 2))
585 with self.assertRaisesRegex(ValueError, "operation forbidden"):
586 m[MyIndex(), 0]
587
588 ba = None
589 m = memoryview(bytearray(b'\xff'*size)).cast('B', (2, 64))
590 with self.assertRaisesRegex(ValueError, "operation forbidden"):
591 m[0, MyIndex()]
592
593 ba = None
594 m = memoryview(bytearray(b'\xff'*size))
595 with self.assertRaisesRegex(ValueError, "operation forbidden"):
596 m[MyIndex()] = 42
597 self.assertEqual(ba[:8], b'\0'*8)
598
599 ba = None
600 m = memoryview(bytearray(b'\xff'*size))
601 with self.assertRaisesRegex(ValueError, "operation forbidden"):
602 m[:MyIndex()] = b'spam'
603 self.assertEqual(ba[:8], b'\0'*8)
604
605 ba = None
606 m = memoryview(bytearray(b'\xff'*size))
607 with self.assertRaisesRegex(ValueError, "operation forbidden"):
608 m[MyIndex():8] = b'spam'
609 self.assertEqual(ba[:8], b'\0'*8)
610
611 ba = None
612 m = memoryview(bytearray(b'\xff'*size)).cast('B', (64, 2))
613 with self.assertRaisesRegex(ValueError, "operation forbidden"):
614 m[MyIndex(), 0] = 42
615 self.assertEqual(ba[8:16], b'\0'*8)
616 ba = None
617 m = memoryview(bytearray(b'\xff'*size)).cast('B', (2, 64))
618 with self.assertRaisesRegex(ValueError, "operation forbidden"):
619 m[0, MyIndex()] = 42
620 self.assertEqual(ba[:8], b'\0'*8)
621
622 ba = None
623 m = memoryview(bytearray(b'\xff'*size))
624 with self.assertRaisesRegex(ValueError, "operation forbidden"):
625 m[0] = MyIndex()
626 self.assertEqual(ba[:8], b'\0'*8)
627
628 for fmt in 'bhilqnBHILQN':
629 with self.subTest(fmt=fmt):
630 ba = None
631 m = memoryview(bytearray(b'\xff'*size)).cast(fmt)
632 with self.assertRaisesRegex(ValueError, "operation forbidden"):
633 m[0] = MyIndex()
634 self.assertEqual(ba[:8], b'\0'*8)
635
636 for fmt in 'fd':
637 with self.subTest(fmt=fmt):
638 ba = None
639 m = memoryview(bytearray(b'\xff'*size)).cast(fmt)
640 with self.assertRaisesRegex(ValueError, "operation forbidden"):
641 m[0] = MyFloat()
642 self.assertEqual(ba[:8], b'\0'*8)
643
644 ba = None
645 m = memoryview(bytearray(b'\xff'*size)).cast('?')
646 with self.assertRaisesRegex(ValueError, "operation forbidden"):
647 m[0] = MyBool()
648 self.assertEqual(ba[:8], b'\0'*8)
649
650 if __name__ == "__main__":
651 unittest.main()