1# test some extreme cases of allocating exceptions and tracebacks
2
3import micropython
4
5# Check for stackless build, which can't call functions without
6# allocating a frame on the heap.
7try:
8
9    def stackless():
10        pass
11
12    micropython.heap_lock()
13    stackless()
14    micropython.heap_unlock()
15except RuntimeError:
16    print("SKIP")
17    raise SystemExit
18
19# some ports need to allocate heap for the emergency exception
20try:
21    micropython.alloc_emergency_exception_buf(256)
22except AttributeError:
23    pass
24
25
26def main():
27    # create an exception with many args while heap is locked
28    # should revert to empty tuple for args
29    micropython.heap_lock()
30    e = Exception(
31        0,
32        0,
33        0,
34        0,
35        0,
36        0,
37        0,
38        0,
39        0,
40        0,
41        0,
42        0,
43        0,
44        0,
45        0,
46        0,
47        0,
48        0,
49        0,
50        0,
51        0,
52        0,
53        0,
54        0,
55        0,
56        0,
57        0,
58        0,
59        0,
60        0,
61        0,
62        0,
63        0,
64        0,
65        0,
66        0,
67        0,
68        0,
69        0,
70        0,
71        0,
72        0,
73        0,
74        0,
75        0,
76        0,
77        0,
78        0,
79        0,
80        0,
81        0,
82        0,
83        0,
84        0,
85        0,
86        0,
87        0,
88        0,
89        0,
90        0,
91        0,
92        0,
93        0,
94        0,
95        0,
96    )
97    micropython.heap_unlock()
98    print(repr(e))
99
100    # create an exception with a long formatted error message while heap is locked
101    # should use emergency exception buffer and truncate the message
102    def f():
103        pass
104
105    micropython.heap_lock()
106    try:
107        f(
108            abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz=1
109        )
110    except Exception as er:
111        e = er
112    micropython.heap_unlock()
113    print(repr(e)[:10])
114
115    # create an exception with a long formatted error message while heap is low
116    # should use the heap and truncate the message
117    lst = []
118    while 1:
119        try:
120            lst = [lst]
121        except MemoryError:
122            break
123    try:
124        f(
125            abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz=1
126        )
127    except Exception as er:
128        e = er
129    lst[0][0] = None
130    lst = None
131    print(repr(e)[:10])
132
133    # raise a deep exception with the heap locked
134    # should use emergency exception and be unable to resize traceback array
135    def g():
136        g()
137
138    micropython.heap_lock()
139    try:
140        g()
141    except Exception as er:
142        e = er
143    micropython.heap_unlock()
144    print(repr(e)[:13])
145
146    # create an exception on the heap with some traceback on the heap, but then
147    # raise it with the heap locked so it can't allocate any more traceback
148    exc = Exception("my exception")
149    try:
150        raise exc
151    except:
152        pass
153
154    def h(e):
155        raise e
156
157    micropython.heap_lock()
158    try:
159        h(exc)
160    except Exception as er:
161        e = er
162    micropython.heap_unlock()
163    print(repr(e))
164
165
166main()
167