1"""
2These tests are meant to exercise that requests to create objects bigger
3than what the address space allows are properly met with an OverflowError
4(rather than crash weirdly).
5
6Primarily, this means 32-bit builds with at least 2 GiB of available memory.
7You need to pass the -M option to regrtest (e.g. "-M 2.1G") for tests to
8be enabled.
9"""
10
11from test import support
12from test.support import bigaddrspacetest, MAX_Py_ssize_t
13
14import unittest
15import operator
16import sys
17
18
19class BytesTest(unittest.TestCase):
20
21    @bigaddrspacetest
22    def test_concat(self):
23        # Allocate a bytestring that's near the maximum size allowed by
24        # the address space, and then try to build a new, larger one through
25        # concatenation.
26        try:
27            x = b"x" * (MAX_Py_ssize_t - 128)
28            self.assertRaises(OverflowError, operator.add, x, b"x" * 128)
29        finally:
30            x = None
31
32    @bigaddrspacetest
33    def test_optimized_concat(self):
34        try:
35            x = b"x" * (MAX_Py_ssize_t - 128)
36
37            with self.assertRaises(OverflowError) as cm:
38                # this statement used a fast path in ceval.c
39                x = x + b"x" * 128
40
41            with self.assertRaises(OverflowError) as cm:
42                # this statement used a fast path in ceval.c
43                x +=  b"x" * 128
44        finally:
45            x = None
46
47    @bigaddrspacetest
48    def test_repeat(self):
49        try:
50            x = b"x" * (MAX_Py_ssize_t - 128)
51            self.assertRaises(OverflowError, operator.mul, x, 128)
52        finally:
53            x = None
54
55
56class StrTest(unittest.TestCase):
57
58    unicodesize = 4
59
60    @bigaddrspacetest
61    def test_concat(self):
62        try:
63            # Create a string that would fill almost the address space
64            x = "x" * int(MAX_Py_ssize_t // (1.1 * self.unicodesize))
65            # Unicode objects trigger MemoryError in case an operation that's
66            # going to cause a size overflow is executed
67            self.assertRaises(MemoryError, operator.add, x, x)
68        finally:
69            x = None
70
71    @bigaddrspacetest
72    def test_optimized_concat(self):
73        try:
74            x = "x" * int(MAX_Py_ssize_t // (1.1 * self.unicodesize))
75
76            with self.assertRaises(MemoryError) as cm:
77                # this statement uses a fast path in ceval.c
78                x = x + x
79
80            with self.assertRaises(MemoryError) as cm:
81                # this statement uses a fast path in ceval.c
82                x +=  x
83        finally:
84            x = None
85
86    @bigaddrspacetest
87    def test_repeat(self):
88        try:
89            x = "x" * int(MAX_Py_ssize_t // (1.1 * self.unicodesize))
90            self.assertRaises(MemoryError, operator.mul, x, 2)
91        finally:
92            x = None
93
94
95def test_main():
96    support.run_unittest(BytesTest, StrTest)
97
98if __name__ == '__main__':
99    if len(sys.argv) > 1:
100        support.set_memlimit(sys.argv[1])
101    test_main()
102