...
 
Commits (3)
......@@ -2,3 +2,4 @@
123456789012345678901234567890
1073741824
4611686018427387904
70368744177664
......@@ -7,3 +7,7 @@ print(abs(-123456789012345678901234567890))
# edge cases for 32 and 64 bit archs (small int overflow when negating)
print(abs(-0x3fffffff - 1))
print(abs(-0x3fffffffffffffff - 1))
# edge case for nan-boxing with 47-bit small int
i = -0x3fffffffffff
print(abs(i - 1))
......@@ -22,6 +22,11 @@ range(1, 4)
range(2, 4)
range(1, 3)
range(7, -5, -4)
range(26, 76, 15)
range(76, 26, -15)
range(75, 25, -15)
range(25, 75, 15)
[]
ValueError
TypeError
TypeError
......@@ -33,6 +33,13 @@ print(range(1, 4)[0:])
print(range(1, 4)[1:])
print(range(1, 4)[:-1])
print(range(7, -2, -4)[:])
print(range(1, 100, 5)[5:15:3])
print(range(1, 100, 5)[15:5:-3])
print(range(100, 1, -5)[5:15:3])
print(range(100, 1, -5)[15:5:-3])
# for this case uPy gives a different stop value but the listed elements are still correct
print(list(range(7, -2, -4)[2:-2:]))
# zero step
try:
......
......@@ -4,6 +4,7 @@ b'123'
b'\\u1234'
b''
b'abc'
b'123'
b'123'
b'123'
......@@ -24,3 +25,4 @@ b'\x00\x01\x02\x03\x04'
255 142 254 125
b'\x80\xff'
b'\x80\xff'
ValueError
......@@ -8,6 +8,9 @@ print(b'\u1234')
print(bytes())
print(bytes(b'abc'))
# make sure empty bytes is converted correctly
print(str(bytes(), 'utf-8'))
a = b"123"
print(a)
print(str(a))
......@@ -53,3 +56,9 @@ print(x[0], x[1], x[2], x[3])
print(bytes([128, 255]))
# For sequence of unknown len
print(bytes(iter([128, 255])))
# Shouldn't be able to make bytes with negative length
try:
bytes(-1)
except ValueError:
print('ValueError')
# test multiple inheritance of user classes
class A:
def __init__(self, x):
print('A init', x)
......@@ -30,6 +32,9 @@ class Sub(A, B):
def g(self):
print(self.x)
print(issubclass(Sub, A))
print(issubclass(Sub, B))
o = Sub()
print(o.x)
o.f()
......
in Sub meth
in Base meth 1
<super: <class 'A'
B foo
123
A foo
1
AttributeError
AttributeError
......@@ -20,3 +20,28 @@ class A:
def p(self):
print(str(super())[:18])
A().p()
# test compiler's handling of long expressions with super
class A:
bar = 123
def foo(self):
print('A foo')
return [1, 2, 3]
class B(A):
def foo(self):
print('B foo')
print(super().bar) # accessing attribute after super()
return super().foo().count(2) # calling a subsequent method
print(B().foo())
# store/delete of super attribute not allowed
assert hasattr(super(B, B()), 'foo')
try:
super(B, B()).foo = 1
except AttributeError:
print('AttributeError')
try:
del super(B, B()).foo
except AttributeError:
print('AttributeError')
......@@ -6,6 +6,11 @@ def f(a, b):
f(1, **{'b':2})
f(1, **{'b':val for val in range(1)})
try:
f(1, **{len:2})
except TypeError:
print('TypeError')
# test calling a method with keywords given by **dict
class A:
......
......@@ -4,8 +4,7 @@ try:
import gc
except ImportError:
print("SKIP")
import sys
sys.exit()
raise SystemExit
print(gc.isenabled())
gc.disable()
......@@ -28,3 +27,8 @@ if hasattr(gc, 'threshold'):
assert(gc.threshold() == 0)
assert(gc.threshold(-1) is None)
assert(gc.threshold() == -1)
# Setting a low threshold should trigger collection at the list alloc
gc.threshold(1)
[[], []]
gc.threshold(-1)
......@@ -167,5 +167,11 @@ False
1585830769456943054292280938484993067044335
3126485650002806059265235559620383787531710118313327355
ValueError
ValueError
97790042259041940531486934491284756629693113480199747651983836990717302663265344753522817614586672201746264372907994845184164134196934599891687938801150895129463347609420553958743394774927862051305987780699581360708557337977386321082887859744005408345406254804346616921865839834206535962803214993135178087569992362
70368744177663
-70368744177663
70368744177664
-70368744177664
True
aaaa
......@@ -75,6 +75,10 @@ try:
print(int("123456789012345678901234567890abcdef"))
except ValueError:
print('ValueError');
try:
print(int("123456789012345678901234567890\x01"))
except ValueError:
print('ValueError');
# test constant integer with more than 255 chars
x = 0x84ce72aa8699df436059f052ac51b6398d2511e49631bcb7e71f89c499b9ee425dfbc13a5f6d408471b054f2655617cbbaf7937b7c80cd8865cf02c8487d30d2b0fbd8b2c4e102e16d828374bbc47b93852f212d5043c3ea720f086178ff798cc4f63f787b9c2e419efa033e7644ea7936f54462dc21a6c4580725f7f0e7d1aaaaaaa
......@@ -86,6 +90,11 @@ x = 1073741823 # small
x = -1073741823 # small
x = 1073741824 # big
x = -1073741824 # big
# for nan-boxing with 47-bit small ints
print(int('0x3fffffffffff', 16)) # small
print(int('-0x3fffffffffff', 16)) # small
print(int('0x400000000000', 16)) # big
print(int('-0x400000000000', 16)) # big
# for 64 bit archs
x = 4611686018427387903 # small
x = -4611686018427387903 # small
......@@ -95,3 +104,7 @@ x = -4611686018427387904 # big
# sys.maxsize is a constant mpz, so test it's compatible with dynamic ones
import sys
print(sys.maxsize + 1 - 1 == sys.maxsize)
# test extraction of big int value via mp_obj_get_int_maybe
x = 1 << 70
print('a' * (x + 4 - x))
2147483646
-2147483646
140737488355326
-140737488355326
9223372036854775806
-9223372036854775806
......@@ -5,6 +5,11 @@ i = 0x3fffffff
print(i + i)
print(-i + -i)
# 47-bit overflow
i = 0x3fffffffffff
print(i + i)
print(-i + -i)
# 63-bit overflow
i = 0x3fffffffffffffff
print(i + i)
......
......@@ -3,5 +3,7 @@ print(i >> 1)
print(i >> 1000)
# result needs rounding up
print(-(1<<70) >> 80)
print(-0xffffffffffffffff >> 32)
i = -(1 << 70)
print(i >> 80)
i = -0xffffffffffffffff
print(i >> 32)
......@@ -19,7 +19,8 @@ print((-a) ^ (1 << 100))
print((-a) ^ (1 << 200))
print((-a) ^ a == 0)
print(bool((-a) ^ a))
print(-1 ^ 0xffffffffffffffff) # carry overflows to higher digit
i = -1
print(i ^ 0xffffffffffffffff) # carry overflows to higher digit
# test + -
......
......@@ -4,3 +4,10 @@ b'd\x00\x00\x00\x00\x00\x00\x00\x00\x00'
256
1
256
True
True
b'\n'
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00d'
1
256
ValueError
......@@ -4,3 +4,19 @@ print((100).to_bytes(10, "little"))
print(int.from_bytes(b"\x00\x01\0\0\0\0\0\0", "little"))
print(int.from_bytes(b"\x01\0\0\0\0\0\0\0", "little"))
print(int.from_bytes(b"\x00\x01\0\0\0\0\0\0", "little"))
# check that extra zero bytes don't change the internal int value
print(int.from_bytes(bytes(20), "little") == 0)
print(int.from_bytes(b"\x01" + bytes(20), "little") == 1)
# big-endian conversion
print((10).to_bytes(1, "big"))
print((100).to_bytes(10, "big"))
print(int.from_bytes(b"\0\0\0\0\0\0\0\0\0\x01", "big"))
print(int.from_bytes(b"\x01\0", "big"))
# negative number of bytes should raise an error
try:
(1).to_bytes(-1, "little")
except ValueError:
print("ValueError")
......@@ -43,3 +43,7 @@ True
True
False
False
False
True
False
TypeError
......@@ -48,3 +48,13 @@ print([1] <= [1, 0])
print([1] <= [1, -1])
print([1, 0] <= [1])
print([1, -1] <= [1])
print([] == {})
print([] != {})
print([1] == (1,))
try:
print([] < {})
except TypeError:
print("TypeError")
# test out-of-memory with malloc
l = list(range(1000))
try:
1000000000 * l
except MemoryError:
print('MemoryError')
print(len(l), l[0], l[-1])
# test out-of-memory with realloc
try:
[].extend(range(1000000000))
except MemoryError:
print('MemoryError')
......@@ -902,3 +902,4 @@ True 2
TypeError
TypeError
TypeError
TypeError
......@@ -60,6 +60,12 @@ except TypeError:
print('TypeError')
# unsupported operator
try:
set('abc') * set('abc')
except TypeError:
print('TypeError')
# unsupported operator with RHS not a set
try:
set('abc') * 2
except TypeError:
......
......@@ -8,6 +8,12 @@ True
False
True
False
True
False
True
False
True
False
False
True
True
......@@ -18,6 +24,12 @@ False
False
False
False
True
True
True
False
True
False
False
True
False
......@@ -31,6 +43,12 @@ False
False
True
False
True
True
True
False
True
False
False
False
False
......@@ -39,6 +57,12 @@ True
False
False
False
False
False
False
False
False
False
True
False
False
......@@ -48,3 +72,9 @@ False
False
True
True
False
False
False
False
False
False
sets = [set(), {1}, {1, 2, 3}, {3, 4, 5}, {5, 6, 7}]
args = sets + [[1], [1, 2], [1, 2 ,3]]
for i in sets:
for j in sets:
for j in args:
print(i.issubset(j))
print(i.issuperset(j))
......@@ -44,3 +44,4 @@ True
False
False
False
True
......@@ -53,3 +53,6 @@ print("1/" <= "1")
# that does have a hash, but the lengths of the two strings are different
import sys
print(sys.version == 'a long string that has a hash')
# this special string would have a hash of 0 but is incremented to 1
print('Q+?' == 'Q' + '+?')
# test subclassing a native type which can be iterated over
class mymap(map):
pass
m = mymap(lambda x: x + 10, range(4))
print(list(m))
......@@ -47,3 +47,7 @@ True
False
True
False
False
True
False
TypeError
......@@ -53,3 +53,13 @@ print((10, 0) > (1, 1))
print((10, 0) < (1, 1))
print((0, 0, 10, 0) > (0, 0, 1, 1))
print((0, 0, 10, 0) < (0, 0, 1, 1))
print(() == {})
print(() != {})
print((1,) == [1])
try:
print(() < {})
except TypeError:
print("TypeError")
False
False
False
False
False
TypeError
TypeError
# Extended float comparisons
class Foo:
pass
foo = Foo()
print(foo == 1.0)
print(1.0 == foo)
print(1.0 == Foo)
print(1.0 == [])
print(1.0 == {})
try:
print(foo < 1.0)
except TypeError:
print("TypeError")
try:
print(1.0 < foo)
except TypeError:
print("TypeError")
116
116.0
116.000
1111
1111.0
1111.000
1234
1234.0
1234.000
5010
5010.0
5010.000
11111
11111.0
11111.000
0
0.0
0.00
0.000
0.0001
0.00006
0.000060
0.0000600
1.00e+12
1.00e+19
# test float formatting
# general rounding
for val in (116, 1111, 1234, 5010, 11111):
print('%.0f' % val)
print('%.1f' % val)
print('%.3f' % val)
# make sure rounding is done at the correct precision
for prec in range(8):
print(('%%.%df' % prec) % 6e-5)
# check certain cases that had a digit value of 10 render as a ":" character
print('%.2e' % float('9' * 51 + 'e-39'))
print('%.2e' % float('9' * 40 + 'e-21'))
# check a case that would render negative digit values, eg ")" characters
# the string is converted back to a float to check for no illegal characters
float('%.23e' % 1e-80)
0.0
0.0
1.0000e+00
1.0000e+20
1.0
1e+20
True
True
9e-36
9e-21
1e-37
1e-37
1e-37
# test parsing of floats
inf = float('inf')
# it shouldn't matter where the decimal point is if the exponent balances the value
print(float('1234') - float('0.1234e4'))
print(float('1.015625') - float('1015625e-6'))
# very large integer part with a very negative exponent should cancel out
print('%.4e' % float('9' * 60 + 'e-60'))
print('%.4e' % float('9' * 60 + 'e-40'))
# many fractional digits
print(float('.' + '9' * 70))
print(float('.' + '9' * 70 + 'e20'))
print(float('.' + '9' * 70 + 'e-50') == float('1e-50'))
# tiny fraction with large exponent
print(float('.' + '0' * 60 + '1e10') == float('1e-51'))
print(float('.' + '0' * 60 + '9e25'))
print(float('.' + '0' * 60 + '9e40'))
# ensure that accuracy is retained when value is close to a subnormal
print(float('1.00000000000000000000e-37'))
print(float('10.0000000000000000000e-38'))
print(float('100.000000000000000000e-39'))
1e+300
1e+200
1.0
1.0
1e+100
1e-100
9.00000000000000e-301
9.00000000000000e-201
9.00000000000000e-01
1e-307
1e-307
1e-307
# test parsing of floats, requiring double-precision
# very large integer part with a very negative exponent should cancel out
print(float('9' * 400 + 'e-100'))
print(float('9' * 400 + 'e-200'))
print(float('9' * 400 + 'e-400'))
# many fractional digits
print(float('.' + '9' * 400))
print(float('.' + '9' * 400 + 'e100'))
print(float('.' + '9' * 400 + 'e-100'))
# tiny fraction with large exponent
print('%.14e' % float('.' + '0' * 400 + '9e100'))
print('%.14e' % float('.' + '0' * 400 + '9e200'))
print('%.14e' % float('.' + '0' * 400 + '9e400'))
# ensure that accuracy is retained when value is close to a subnormal
print(float('1.00000000000000000000e-307'))
print(float('10.0000000000000000000e-308'))
print(float('100.000000000000000000e-309'))
......@@ -3,5 +3,6 @@
7.3787e+18
4.4272e+19
3.0745e+19
4.4272e+19
2.7105e-20
0.125
ZeroDivisionError
......@@ -15,8 +15,12 @@ print("%.5g" % (i / 5))
print("%.5g" % (i * 1.2))
print("%.5g" % (i / 1.2))
# this should delegate to complex
print("%.5g" % (i * 1.2j).imag)
# this should delegate to complex (not for LEON)
#print("%.5g" % (i * 1.2j).imag)
# negative power should produce float
print("%.5g" % (i ** -1))
print("%.5g" % ((2 + i - i) ** -3))
try:
i / 0
......
......@@ -188,7 +188,8 @@ log
1
1.585
0.86135
math domain error
math domain error
math domain error
math domain error
<class 'ValueError'>
<class 'ValueError'>
<class 'ValueError'>
<class 'ValueError'>
<class 'ZeroDivisionError'>
......@@ -4,8 +4,7 @@ try:
from math import *
except ImportError:
print("SKIP")
import sys
sys.exit()
raise SystemExit
test_values = [-100., -1.23456, -1, -0.5, 0.0, 0.5, 1.23456, 100.]
test_values_small = [-10., -1.23456, -1, -0.5, 0.0, 0.5, 1.23456, 10.] # so we don't overflow 32-bit precision
......@@ -52,7 +51,7 @@ binary_functions = [('copysign', copysign, [(23., 42.), (-23., 42.), (23., -42.)
('atan2', atan2, ((1., 0.), (0., 1.), (2., 0.5), (-3., 5.), (-3., -4.),)),
('fmod', fmod, ((1., 1.), (0., 1.), (2., 0.5), (-3., 5.), (-3., -4.),)),
('ldexp', ldexp, ((1., 0), (0., 1), (2., 2), (3., -2), (-3., -4),)),
('log', log, ((2., 2.), (3., 2.), (4., 5.), (0., 1.), (1., 0.), (-1., 1.), (1., -1.))),
('log', log, ((2., 2.), (3., 2.), (4., 5.), (0., 1.), (1., 0.), (-1., 1.), (1., -1.), (2., 1.))),
]
for function_name, function, test_vals in binary_functions:
......@@ -60,5 +59,5 @@ for function_name, function, test_vals in binary_functions:
for value1, value2 in test_vals:
try:
print("{:.5g}".format(function(value1, value2)))
except ValueError as e:
print(str(e))
except (ValueError, ZeroDivisionError) as e:
print(type(e))
......@@ -27,3 +27,5 @@
0.
0.
1
1.0e+01
1.0e+00
......@@ -44,3 +44,6 @@ print(('%.40g' % 1e-3)[:2])
print(('%.40g' % 1e-4)[:2])
print("%.0g" % 1) # 0 precision 'g'
print('%.1e' % 9.99) # round up with positive exponent
print('%.1e' % 0.999) # round up with negative exponent
......@@ -16,7 +16,7 @@ def test(num, num_str):
print('FAIL', num_str, fmt, s, len(s), check)
# check most powers of 10, making sure to include exponents with 3 digits
for e in (-101, -100, -99, -50, -10, -9, -1, 0, 1, 5, 20, 99, 100, 101):
for e in (-101, -100, -99, -50, -10, -9, -1, 0, 1, 5, 20, 30, 99, 100, 101):
print(e)
num = pow(10, e)
test(num, '1e%d' % e)
Exception()
TypeError("unexpected keyword argument 'abcdefghij
TypeError("unexpected keyword argument 'abc",)
RuntimeError('maximum recursion depth exceeded',)
Exception('my exception',)
# test some extreme cases of allocating exceptions and tracebacks
import micropython
# some ports need to allocate heap for the emergency exception
try:
micropython.alloc_emergency_exception_buf(256)
except AttributeError:
pass
def main():
# create an exception with many args while heap is locked
# should revert to empty tuple for args
micropython.heap_lock()
e = Exception(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
micropython.heap_unlock()
print(repr(e))
# create an exception with a long formatted error message while heap is locked
# should use emergency exception buffer and truncate the message
def f():
pass
micropython.heap_lock()
try:
f(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz=1)
except Exception as er:
e = er
micropython.heap_unlock()
print(repr(e)[:50])
# create an exception with a long formatted error message while heap is low
# should use the heap and truncate the message
lst = []
while 1:
try:
lst = [lst]
except MemoryError:
break
try:
f(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz=1)
except Exception as er:
e = er
lst = None
print(repr(e))
# raise a deep exception with the heap locked
# should use emergency exception and be unable to resize traceback array
def g():
g()
micropython.heap_lock()
try:
g()
except Exception as er:
e = er
micropython.heap_unlock()
print(repr(e))
# create an exception on the heap with some traceback on the heap, but then
# raise it with the heap locked so it can't allocate any more traceback
exc = Exception('my exception')
try:
raise exc
except:
pass
def h(e):
raise e
micropython.heap_lock()
try:
h(exc)
except Exception as er:
e = er
micropython.heap_unlock()
print(repr(e))
main()
......@@ -2,13 +2,24 @@
import micropython
l = []
l2 = list(range(100))
micropython.heap_lock()
# general allocation on the heap
try:
print([])
except MemoryError:
print('MemoryError')
# expansion of a heap block
try:
l.extend(l2)
except MemoryError:
print('MemoryError')
micropython.heap_unlock()
# check that allocation works after an unlock
print([])
StopIteration
Traceback (most recent call last):
File "CORE_MICROPYTHON/heapalloc_traceback.py", line 18, in test
StopIteration:
# test that we can generate a traceback without allocating
import micropython
import sys
# preallocate exception instance with some room for a traceback
global_exc = StopIteration()
try:
raise global_exc
except:
pass
def test():
micropython.heap_lock()
global global_exc
global_exc.__traceback__ = None
try:
raise global_exc
except StopIteration:
print('StopIteration')
micropython.heap_unlock()
# call test() with heap allocation disabled
test()
# print the exception that was raised
sys.print_exception(global_exc)
......@@ -15,3 +15,5 @@ NotImplementedError
NotImplementedError
NotImplementedError
AttributeError
TypeError
A.foo
......@@ -4,9 +4,8 @@ try:
import array
import ustruct
except ImportError:
import sys
print("SKIP")
sys.exit()
raise SystemExit
# store to exception attribute is not allowed
try:
......@@ -113,3 +112,18 @@ try:
f.x = 1
except AttributeError:
print('AttributeError')
# can't call a function type (ie make new instances of a function)
try:
type(f)()
except TypeError:
print('TypeError')
# test when object explicitly listed at not-last position in parent tuple
# this is not compliant with CPython because of illegal MRO
class A:
def foo(self):
print('A.foo')
class B(object, A):
pass
B().foo()
# create a large dictionary
d = {}
x = 1
while x < 1000:
d[x] = x
x += 1
print(d[500])
# The aim with this test is to hit the maximum resize/rehash size of a dict,
# where there are no more primes in the table of growing allocation sizes.
# This value is 54907 items.
d = {}
try:
for i in range(54908):
d[i] = i
except MemoryError:
pass
# Just check the dict still has the first value
print(d[0])
[[0], [1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12], [13], [14], [15], [16], [17], [18], [19], [20], [21], [22], [23], [24], [25], [26], [27], [28], [29], [30], [31], [32], [33], [34], [35], [36], [37], [38], [39], [40], [41], [42], [43], [44], [45], [46], [47], [48], [49], [50], [51], [52], [53], [54], [55], [56], [57], [58], [59], [60], [61], [62], [63], [64], [65], [66], [67], [68], [69], [70], [71], [72], [73], [74], [75], [76], [77], [78], [79], [80], [81], [82], [83], [84], [85], [86], [87], [88], [89], [90], [91], [92], [93], [94], [95], [96], [97], [98], [99], [100], [101], [102], [103], [104], [105], [106], [107], [108], [109], [110], [111], [112], [113], [114], [115], [116], [117], [118], [119], [120], [121], [122], [123], [124], [125], [126], [127], [128], [129], [130], [131], [132], [133], [134], [135], [136], [137], [138], [139], [140], [141], [142], [143], [144], [145], [146], [147], [148], [149], [150], [151], [152], [153], [154], [155], [156], [157], [158], [159], [160], [161], [162], [163], [164], [165], [166], [167], [168], [169], [170], [171], [172], [173], [174], [175], [176], [177], [178], [179], [180], [181], [182], [183], [184], [185], [186], [187], [188], [189], [190], [191], [192], [193], [194], [195], [196], [197], [198], [199]]
[[[[[(0, 0, 0, 0)], [(1, 0, 0, 0)], [(2, 0, 0, 0)]], [[(0, 1, 0, 0)], [(1, 1, 0, 0)], [(2, 1, 0, 0)]], [[(0, 2, 0, 0)], [(1, 2, 0, 0)], [(2, 2, 0, 0)]]], [[[(0, 0, 1, 0)], [(1, 0, 1, 0)], [(2, 0, 1, 0)]], [[(0, 1, 1, 0)], [(1, 1, 1, 0)], [(2, 1, 1, 0)]], [[(0, 2, 1, 0)], [(1, 2, 1, 0)], [(2, 2, 1, 0)]]], [[[(0, 0, 2, 0)], [(1, 0, 2, 0)], [(2, 0, 2, 0)]], [[(0, 1, 2, 0)], [(1, 1, 2, 0)], [(2, 1, 2, 0)]], [[(0, 2, 2, 0)], [(1, 2, 2, 0)], [(2, 2, 2, 0)]]]], [[[[(0, 0, 0, 1)], [(1, 0, 0, 1)], [(2, 0, 0, 1)]], [[(0, 1, 0, 1)], [(1, 1, 0, 1)], [(2, 1, 0, 1)]], [[(0, 2, 0, 1)], [(1, 2, 0, 1)], [(2, 2, 0, 1)]]], [[[(0, 0, 1, 1)], [(1, 0, 1, 1)], [(2, 0, 1, 1)]], [[(0, 1, 1, 1)], [(1, 1, 1, 1)], [(2, 1, 1, 1)]], [[(0, 2, 1, 1)], [(1, 2, 1, 1)], [(2, 2, 1, 1)]]], [[[(0, 0, 2, 1)], [(1, 0, 2, 1)], [(2, 0, 2, 1)]], [[(0, 1, 2, 1)], [(1, 1, 2, 1)], [(2, 1, 2, 1)]], [[(0, 2, 2, 1)], [(1, 2, 2, 1)], [(2, 2, 2, 1)]]]], [[[[(0, 0, 0, 2)], [(1, 0, 0, 2)], [(2, 0, 0, 2)]], [[(0, 1, 0, 2)], [(1, 1, 0, 2)], [(2, 1, 0, 2)]], [[(0, 2, 0, 2)], [(1, 2, 0, 2)], [(2, 2, 0, 2)]]], [[[(0, 0, 1, 2)], [(1, 0, 1, 2)], [(2, 0, 1, 2)]], [[(0, 1, 1, 2)], [(1, 1, 1, 2)], [(2, 1, 1, 2)]], [[(0, 2, 1, 2)], [(1, 2, 1, 2)], [(2, 2, 1, 2)]]], [[[(0, 0, 2, 2)], [(1, 0, 2, 2)], [(2, 0, 2, 2)]], [[(0, 1, 2, 2)], [(1, 1, 2, 2)], [(2, 1, 2, 2)]], [[(0, 2, 2, 2)], [(1, 2, 2, 2)], [(2, 2, 2, 2)]]]]]
# test that the GC can trace nested objects
try:
import gc
except ImportError:
print("SKIP")
raise SystemExit
# test a big shallow object pointing to many unique objects
lst = [[i] for i in range(200)]
gc.collect()
print(lst)
# test a deep object
lst = [[[[[(i, j, k, l)] for i in range(3)] for j in range(3)] for k in range(3)] for l in range(3)]
gc.collect()
print(lst)
# test large list sorting (should not stack overflow)
l = list(range(2000))
l.sort()
print(l[0], l[-1])
l.sort(reverse=True)
print(l[0], l[-1])
......@@ -6,6 +6,7 @@
./run-tests.sh CORE_EXTMOD/*.py
./run-tests.sh CORE_MISC/*.py
./run-tests.sh CORE_MICROPYTHON/*.py
./run-tests.sh CORE_STRESS/*.py
./run-tests.sh spacebel_tickets/*.py
./run-tests.sh leon_t1/*.exp
./run-tests.sh -t 2 leon_t2/*.exp
......
......@@ -2,3 +2,6 @@ True
False
True
False
False
False
False
......@@ -2,3 +2,8 @@ print({1:2, 3:4}.keys() == {1:20, 3:40}.keys())
print({1:2, 3:4}.keys() != {1:20, 3:40}.keys())
print({1:2, 3:4}.items() == {1:2, 3:4}.items())
print({1:2, 3:4}.items() != {1:2, 3:4}.items())
# these should evaluate to False
print({1:2}.keys() == {1:2, 3:4}.values())
print({1:2}.keys() == {1:2, 3:4}.keys())
print({1:2}.keys() == {2:3}.keys())
NotImplementedError
123
123
1 2
70368744177664
# relative import not implemented (or gives a KeyError if it is)
try:
__import__('xyz', None, None, None, 1)
except (KeyError, NotImplementedError):
print('NotImplementedError')
# coverage for __repl_print__
__repl_print__(123)
# coverage for mp_identity function
import micropython
c = micropython.const
print(c(123))
# test mp_load_name when it gets the value from locals()
class A:
x = 1
y = x + 1
print(A.x, A.y)
# test overflow of 47-bit small-int in nan-boxing config
i = -0x3fffffffffff
print(-(i - 1))
......@@ -14,6 +14,7 @@ make -C leon-for-tests || exit $?
(cd leon-tests && ./run-tests.sh CORE_EXTMOD/*.exp)
(cd leon-tests && ./run-tests.sh CORE_MISC/*.exp)
(cd leon-tests && ./run-tests.sh CORE_MICROPYTHON/*.exp)
(cd leon-tests && ./run-tests.sh CORE_STRESS/*.exp)
(cd leon-tests && ./run-tests.sh spacebel_tickets/*.exp)
(cd leon-tests && ./run-tests.sh leon_t1/*.exp)
(cd leon-tests && ./run-tests.sh -t 2 leon_t2/*.exp)
......
......@@ -28,8 +28,10 @@
#include <assert.h>
#include "py/runtime.h"
#include "py/stackctrl.h"
void mp_arg_check_num(size_t n_args, size_t n_kw, size_t n_args_min, size_t n_args_max, bool takes_kw) {
MP_STACK_CHECK();
// TODO maybe take the function name as an argument so we can print nicer error messages
if (n_kw && !takes_kw) {
......
......@@ -502,12 +502,12 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) {
#endif
// Couldn't find the module, so fail
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE
mp_raise_msg(&mp_type_ImportError, "module not found");
} else {
#else
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ImportError,
"no module named '%q'", module_name_qstr));
}
#endif
}
#endif // MICROPY_ENABLE_EXTERNAL_IMPORT
......
......@@ -30,6 +30,7 @@
#include "py/gc.h"
#include "py/runtime.h"
#include "py/stackctrl.h"
#if MICROPY_ENABLE_GC && !MICROPY_ENABLE_IMMORTAL_GC
......@@ -357,6 +358,7 @@ void gc_collect_root(void **ptrs, size_t len) {
}
void gc_collect_end(void) {
MP_STACK_CHECK();
gc_deal_with_stack_overflow();
gc_sweep();
MP_STATE_MEM(gc_last_free_atb_index) = 0;
......
......@@ -160,6 +160,7 @@ bool mp_obj_is_callable(mp_obj_t o_in) {
// comparison returns NotImplemented, == and != are decided by comparing the object
// pointer."
bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2) {
MP_STACK_CHECK();
// Float (and complex) NaN is never equal to anything, not even itself,
// so we must have a special check here to cover those cases.
if (o1 == o2
......
......@@ -29,6 +29,7 @@
#include <assert.h>
#include "py/runtime.h"
#include "py/stackctrl.h"
#include "py/bc.h"
#include "py/objgenerator.h"
#include "py/objfun.h"
......@@ -92,6 +93,7 @@ STATIC void gen_instance_print(const mp_print_t *print, mp_obj_t self_in, mp_pri
}
mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw_value, mp_obj_t *ret_val) {
MP_STACK_CHECK();
mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_gen_instance));
mp_obj_gen_instance_t *self = MP_OBJ_TO_PTR(self_in);
if (self->code_state.ip == 0) {
......
......@@ -933,6 +933,7 @@ STATIC NORETURN void terse_str_format_value_error(void) {
#endif
STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *arg_i, size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
MP_STACK_CHECK();
vstr_t vstr;
mp_print_t print;
vstr_init_print(&vstr, 16, &print);
......@@ -1120,7 +1121,6 @@ STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar
// type ::= "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%"
// recursively call the formatter to format any nested specifiers
MP_STACK_CHECK();
vstr_t format_spec_vstr = mp_obj_str_format_helper(format_spec, str, arg_i, n_args, args, kwargs);
const char *s = vstr_null_terminated_str(&format_spec_vstr);
const char *stop = s + format_spec_vstr.len;
......
......@@ -32,6 +32,7 @@
#include "py/objtype.h"
#include "py/runtime.h"
#include "py/stackctrl.h"
#if MICROPY_DEBUG_VERBOSE // print debugging info
#define DEBUG_PRINT (1)
......@@ -47,6 +48,7 @@ STATIC mp_obj_t static_class_method_make_new(const mp_obj_type_t *self_in, size_
// instance object
STATIC int instance_count_native_bases(const mp_obj_type_t *type, const mp_obj_type_t **last_native_base) {
MP_STACK_CHECK();
int count = 0;
for (;;) {
if (type == &mp_type_object) {
......@@ -133,6 +135,7 @@ struct class_lookup_data {
};
STATIC void mp_obj_class_lookup(struct class_lookup_data *lookup, const mp_obj_type_t *type) {
MP_STACK_CHECK();
assert(lookup->dest[0] == MP_OBJ_NULL);
assert(lookup->dest[1] == MP_OBJ_NULL);
for (;;) {
......@@ -272,6 +275,7 @@ STATIC void instance_print(const mp_print_t *print, mp_obj_t self_in, mp_print_k
}
mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, size_t n_kw, const mp_obj_t *args) {
MP_STACK_CHECK();
assert(mp_obj_is_instance_type(self));
// look for __new__ function
......@@ -1198,6 +1202,7 @@ void mp_load_super_method(qstr attr, mp_obj_t *dest) {
// object and classinfo should be type objects
// (but the function will fail gracefully if they are not)
bool mp_obj_is_subclass_fast(mp_const_obj_t object, mp_const_obj_t classinfo) {
MP_STACK_CHECK();
for (;;) {
if (object == classinfo) {
return true;
......
......@@ -33,6 +33,7 @@
#include "py/emitglue.h"
#include "py/persistentcode.h"
#include "py/bc.h"
#include "py/stackctrl.h"
#if MICROPY_PERSISTENT_CODE_LOAD || MICROPY_PERSISTENT_CODE_SAVE
......@@ -165,6 +166,7 @@ STATIC void load_bytecode_qstrs(mp_reader_t *reader, byte *ip, byte *ip_top) {
}
STATIC mp_raw_code_t *load_raw_code(mp_reader_t *reader) {
MP_STACK_CHECK();
// load bytecode
size_t bc_len = read_uint(reader);
byte *bytecode = m_new(byte, bc_len);
......
......@@ -222,6 +222,7 @@ void mp_delete_global(qstr qst) {
}
mp_obj_t mp_unary_op(mp_unary_op_t op, mp_obj_t arg) {
MP_STACK_CHECK();
DEBUG_OP_printf("unary " UINT_FMT " %q %p\n", op, mp_unary_op_method_name[op], arg);
if (op == MP_UNARY_OP_NOT) {
......@@ -283,6 +284,7 @@ mp_obj_t mp_unary_op(mp_unary_op_t op, mp_obj_t arg) {
}
mp_obj_t mp_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) {
MP_STACK_CHECK();
DEBUG_OP_printf("binary " UINT_FMT " %q %p %p\n", op, mp_binary_op_method_name[op], lhs, rhs);
// TODO correctly distinguish inplace operators for mutable objects
......@@ -608,6 +610,7 @@ mp_obj_t mp_call_function_2(mp_obj_t fun, mp_obj_t arg1, mp_obj_t arg2) {
// args contains, eg: arg0 arg1 key0 value0 key1 value1
mp_obj_t mp_call_function_n_kw(mp_obj_t fun_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
MP_STACK_CHECK();
// TODO improve this: fun object can specify its type and we parse here the arguments,
// passing to the function arrays of fixed and keyword arguments
......