From 214179b430ebc1101e28b19248b6166f5e511e6b Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 25 Mar 2015 23:10:09 +0000 Subject: [PATCH] tests: Add tests for SyntaxError, TypeError, and other missing things. This is intended to improve coverage of the test suite. --- tests/basics/array1.py | 9 +++ tests/basics/array_construct.py | 3 + tests/basics/bool1.py | 11 +++ tests/basics/bytearray_slice_assign.py | 5 ++ tests/basics/closure_manyvars.py | 9 +++ tests/basics/fun_str.py | 5 ++ tests/basics/int1.py | 6 ++ tests/basics/int2.py | 7 ++ tests/basics/list_index.py | 3 + tests/basics/memoryview1.py | 4 ++ tests/basics/op_error.py | 43 ++++++++++++ tests/basics/syntaxerror.py | 89 ++++++++++++++++++++++++ tests/basics/try_error.py | 17 +++++ tests/float/complex1.py | 11 +++ tests/float/float1.py | 6 ++ tests/float/int_big_float.py | 3 + tests/micropython/const_error.py | 17 +++-- tests/micropython/const_error.py.exp | 1 + tests/micropython/decorator_error.py | 11 +++ tests/micropython/decorator_error.py.exp | 2 + tests/micropython/native_misc.py | 23 +++++- tests/micropython/native_misc.py.exp | 4 ++ tests/micropython/viper_error.py | 11 +++ tests/micropython/viper_error.py.exp | 2 + 24 files changed, 296 insertions(+), 6 deletions(-) create mode 100644 tests/basics/bool1.py create mode 100644 tests/basics/closure_manyvars.py create mode 100644 tests/basics/fun_str.py create mode 100644 tests/basics/int2.py create mode 100644 tests/basics/op_error.py create mode 100644 tests/basics/syntaxerror.py create mode 100644 tests/basics/try_error.py create mode 100644 tests/micropython/decorator_error.py create mode 100644 tests/micropython/decorator_error.py.exp create mode 100644 tests/micropython/viper_error.py create mode 100644 tests/micropython/viper_error.py.exp diff --git a/tests/basics/array1.py b/tests/basics/array1.py index 6f70fdb911..bce22cc57d 100644 --- a/tests/basics/array1.py +++ b/tests/basics/array1.py @@ -11,3 +11,12 @@ print(i[-1]) print(len(array.array('h'))) print(array.array('i')) +# bool operator acting on arrays +print(bool(array.array('i'))) +print(bool(array.array('i', [1]))) + +# bad typecode +try: + array.array('X') +except ValueError: + print("ValueError") diff --git a/tests/basics/array_construct.py b/tests/basics/array_construct.py index 8c0b4b5973..47c986c940 100644 --- a/tests/basics/array_construct.py +++ b/tests/basics/array_construct.py @@ -14,3 +14,6 @@ print(array('i', bytearray(4))) # convert from other arrays print(array('H', array('b', [1, 2]))) print(array('b', array('I', [1, 2]))) + +# construct from something with unknown length +print(array('i', (i for i in range(10)))) diff --git a/tests/basics/bool1.py b/tests/basics/bool1.py new file mode 100644 index 0000000000..99bd837927 --- /dev/null +++ b/tests/basics/bool1.py @@ -0,0 +1,11 @@ +# tests for bool objects + +# basic logic +print(not False) +print(not True) +print(False and True) +print(False or True) + +# unary operators +print(+True) +print(-True) diff --git a/tests/basics/bytearray_slice_assign.py b/tests/basics/bytearray_slice_assign.py index 0b476ae0ac..a5436c815a 100644 --- a/tests/basics/bytearray_slice_assign.py +++ b/tests/basics/bytearray_slice_assign.py @@ -41,3 +41,8 @@ print(l) l = bytearray(x) #del l[:-3] print(l) + +# slice assignment that extends the array +b = bytearray(2) +b[2:] = bytearray(10) +print(b) diff --git a/tests/basics/closure_manyvars.py b/tests/basics/closure_manyvars.py new file mode 100644 index 0000000000..4ae723726b --- /dev/null +++ b/tests/basics/closure_manyvars.py @@ -0,0 +1,9 @@ +# test closure with lots of closed over variables + +def f(): + a, b, c, d, e, f, g, h = [i for i in range(8)] + def x(): + print(a, b, c, d, e, f, g, h) + x() + +f() diff --git a/tests/basics/fun_str.py b/tests/basics/fun_str.py new file mode 100644 index 0000000000..3cfe46b807 --- /dev/null +++ b/tests/basics/fun_str.py @@ -0,0 +1,5 @@ +# test str of function + +def f(): + pass +print(str(f)[:8]) diff --git a/tests/basics/int1.py b/tests/basics/int1.py index fd9902f935..f4e4c3f096 100644 --- a/tests/basics/int1.py +++ b/tests/basics/int1.py @@ -81,3 +81,9 @@ test('1 1', 16) # check that we don't parse this as a floating point number print(0x1e+1) + +# can't convert list to int +try: + int([]) +except TypeError: + print("TypeError") diff --git a/tests/basics/int2.py b/tests/basics/int2.py new file mode 100644 index 0000000000..9ef20f9c90 --- /dev/null +++ b/tests/basics/int2.py @@ -0,0 +1,7 @@ +# test basic int operations + +# test conversion of bool on RHS of binary op +a = False +print(1 + a) +a = True +print(1 + a) diff --git a/tests/basics/list_index.py b/tests/basics/list_index.py index a669e69c49..0bd28ac9d8 100644 --- a/tests/basics/list_index.py +++ b/tests/basics/list_index.py @@ -32,3 +32,6 @@ except ValueError: print("Raised ValueError") else: print("Did not raise ValueError") + +# 3rd argument to index greater than length of list +print([1, 2].index(1, 0, 4)) diff --git a/tests/basics/memoryview1.py b/tests/basics/memoryview1.py index 894f80a967..2033f4ac2e 100644 --- a/tests/basics/memoryview1.py +++ b/tests/basics/memoryview1.py @@ -25,6 +25,10 @@ m = memoryview(b'1234') print(list(m[1:])) print(list(m[1:-1])) +# this tests get_buffer of memoryview +m = memoryview(bytearray(2)) +print(bytearray(m)) + import array a = array.array('i', [1, 2, 3, 4]) m = memoryview(a) diff --git a/tests/basics/op_error.py b/tests/basics/op_error.py new file mode 100644 index 0000000000..cfd6ffa8c4 --- /dev/null +++ b/tests/basics/op_error.py @@ -0,0 +1,43 @@ +# test errors from bad operations (unary, binary, etc) + +def test_exc(code, exc): + try: + exec(code) + print("no exception") + except exc: + print("right exception") + except: + print("wrong exception") + +# unsupported unary operators +test_exc("~None", TypeError) +test_exc("~[]", TypeError) +test_exc("~bytearray()", TypeError) + +# unsupported binary operators +test_exc("False in True", TypeError) +test_exc("1 * {}", TypeError) +test_exc("1 in 1", TypeError) +test_exc("bytearray() // 2", TypeError) +test_exc("m = memoryview(bytearray())\nm += bytearray()", TypeError) + +# object with buffer protocol needed on rhs +test_exc("bytearray(1) + 1", TypeError) +test_exc("(1 << 70) in 1", TypeError) + +# unsupported subscription +test_exc("1[0]", TypeError) +test_exc("1[0] = 1", TypeError) +test_exc("del 1[0]", TypeError) + +# not callable +test_exc("1()", TypeError) + +# not an iterator +test_exc("next(1)", TypeError) + +# must be an exception type +test_exc("raise 1", TypeError) + +# no such name in import +test_exc("from sys import youcannotimportmebecauseidontexist", ImportError) diff --git a/tests/basics/syntaxerror.py b/tests/basics/syntaxerror.py new file mode 100644 index 0000000000..f53b2c41d2 --- /dev/null +++ b/tests/basics/syntaxerror.py @@ -0,0 +1,89 @@ +# test syntax errors + +def test_syntax(code): + try: + exec(code) + print("no SyntaxError") + except SyntaxError: + print("SyntaxError") + +# can't assign to literals +test_syntax("1 = 2") +test_syntax("'' = 1") +test_syntax("{} = 1") + +# can't assign to comprehension +test_syntax("(i for i in a) = 1") + +# can't assign to function +test_syntax("f() = 1") + +# can't assign to power +test_syntax("f**2 = 1") + +# can't assign to power of composite +test_syntax("f[0]**2 = 1") + +# can't assign to empty tuple +test_syntax("() = 1") + +# can't have multiple *x on LHS +test_syntax("*a, *b = c") + +# can't do augmented assignment to tuple +test_syntax("a, b += c") +test_syntax("(a, b) += c") + +# can't do augmented assignment to list +test_syntax("[a, b] += c") + +# non-default argument can't follow default argument +test_syntax("def f(a=1, b): pass") + +# can't delete these things +test_syntax("del ()") +test_syntax("del f()") +test_syntax("del f[0]**2") +test_syntax("del (a for a in a)") + +# must be in a "loop" +test_syntax("break") +test_syntax("continue") + +# must be in a function +test_syntax("return") +test_syntax("yield") +test_syntax("nonlocal a") + +# errors on uPy but shouldn't +#test_syntax("global a; global a") +#test_syntax("def f():\n a = 1\n global a") + +# default except must be last +test_syntax("try:\n a\nexcept:\n pass\nexcept:\n pass") + +# can't have multiple * or ** +test_syntax("f(*a, *b)") +test_syntax("f(**a, **b)") + +# LHS of keywords must be id's +test_syntax("f(1=2)") + +# non-keyword after keyword +test_syntax("f(a=1, 2)") + +# doesn't error on uPy but should +#test_syntax("f(1, i for i in i)") + +# all elements of dict/set must be pairs or singles +test_syntax("{1:2, 3}") +test_syntax("{1, 2:3}") + +# can't mix non-bytes with bytes when concatenating +test_syntax("'abc' b'def'") + +# can't reuse same name for argument +test_syntax("def f(a, a): pass") + +# nonlocal must exist in outer function/class scope +test_syntax("def f():\n def g():\n nonlocal a") diff --git a/tests/basics/try_error.py b/tests/basics/try_error.py new file mode 100644 index 0000000000..ca2a6f2030 --- /dev/null +++ b/tests/basics/try_error.py @@ -0,0 +1,17 @@ +# test bad exception match + +try: + try: + a + except 1: + pass +except TypeError: + print("TypeError") + +try: + try: + a + except (1,): + pass +except TypeError: + print("TypeError") diff --git a/tests/float/complex1.py b/tests/float/complex1.py index 6cfbff61bc..eafa53746a 100644 --- a/tests/float/complex1.py +++ b/tests/float/complex1.py @@ -16,6 +16,8 @@ print(+(1j)) print(-(1 + 2j)) # binary ops +print(1j + False) +print(1j + True) print(1j + 2) print(1j + 2j) print(1j - 2) @@ -30,3 +32,12 @@ ans = 1j ** 2.5j; print("%.5g %.5g" % (ans.real, ans.imag)) # builtin abs print(abs(1j)) print("%.5g" % abs(1j + 2)) + +# convert bignum to complex on rhs +ans = 1j + (1 << 70); print("%.5g %.5g" % (ans.real, ans.imag)) + +# can't convert rhs to complex +try: + 1j + [] +except TypeError: + print("TypeError") diff --git a/tests/float/float1.py b/tests/float/float1.py index 7b5887ff0b..9e4bb85cd1 100644 --- a/tests/float/float1.py +++ b/tests/float/float1.py @@ -20,6 +20,12 @@ try: except ZeroDivisionError: print("ZeroDivisionError") +# can't convert list to float +try: + float([]) +except TypeError: + print("TypeError") + # test constant float with more than 255 chars x = 1.84728699436059052516398251149631771898472869943605905251639825114963177189847286994360590525163982511496317718984728699436059052516398251149631771898472869943605905251639825114963177189847286994360590525163982511496317718984728699436059052516398251149631771898472869943605905251639825114963177189 print("%.5f" % x) diff --git a/tests/float/int_big_float.py b/tests/float/int_big_float.py index a5fb2700f8..5b8aaa8782 100644 --- a/tests/float/int_big_float.py +++ b/tests/float/int_big_float.py @@ -2,6 +2,9 @@ i = 1 << 65 +# convert bignum to float on rhs +print("%.5g" % (2.0 * i)) + # this should convert to float print("%.5g" % (i / 5)) diff --git a/tests/micropython/const_error.py b/tests/micropython/const_error.py index fa7deaaf31..b46efcae27 100644 --- a/tests/micropython/const_error.py +++ b/tests/micropython/const_error.py @@ -1,6 +1,13 @@ -# make sure syntax error works corrects for bad const definition +# make sure syntax error works correctly for bad const definition -try: - exec("a = const(x)") -except SyntaxError: - print("SyntaxError") +def test_syntax(code): + try: + exec(code) + except SyntaxError: + print("SyntaxError") + +# argument not a constant +test_syntax("a = const(x)") + +# redefined constant +test_syntax("A = const(1); A = const(2)") diff --git a/tests/micropython/const_error.py.exp b/tests/micropython/const_error.py.exp index 8729fc4343..5275689b41 100644 --- a/tests/micropython/const_error.py.exp +++ b/tests/micropython/const_error.py.exp @@ -1 +1,2 @@ SyntaxError +SyntaxError diff --git a/tests/micropython/decorator_error.py b/tests/micropython/decorator_error.py new file mode 100644 index 0000000000..c7da3119f4 --- /dev/null +++ b/tests/micropython/decorator_error.py @@ -0,0 +1,11 @@ +# test syntax errors for uPy-specific decorators + +def test_syntax(code): + try: + exec(code) + except SyntaxError: + print("SyntaxError") + +# invalid micropython decorators +test_syntax("@micropython.a\ndef f(): pass") +test_syntax("@micropython.a.b\ndef f(): pass") diff --git a/tests/micropython/decorator_error.py.exp b/tests/micropython/decorator_error.py.exp new file mode 100644 index 0000000000..5275689b41 --- /dev/null +++ b/tests/micropython/decorator_error.py.exp @@ -0,0 +1,2 @@ +SyntaxError +SyntaxError diff --git a/tests/micropython/native_misc.py b/tests/micropython/native_misc.py index 8f087c4949..0cd521de6c 100644 --- a/tests/micropython/native_misc.py +++ b/tests/micropython/native_misc.py @@ -1,10 +1,31 @@ +# tests for natively compiled functions + +# basic test @micropython.native def native_test(x): print(1, [], x) - native_test(2) # check that GC doesn't collect the native function import gc gc.collect() native_test(3) + +# native with 2 args +@micropython.native +def f(a, b): + print(a + b) +f(1, 2) + +# native with 3 args +@micropython.native +def f(a, b, c): + print(a + b + c) +f(1, 2, 3) + +# check not operator +@micropython.native +def f(a): + print(not a) +f(False) +f(True) diff --git a/tests/micropython/native_misc.py.exp b/tests/micropython/native_misc.py.exp index e1413fd79f..b3e1389ef7 100644 --- a/tests/micropython/native_misc.py.exp +++ b/tests/micropython/native_misc.py.exp @@ -1,2 +1,6 @@ 1 [] 2 1 [] 3 +3 +6 +True +False diff --git a/tests/micropython/viper_error.py b/tests/micropython/viper_error.py new file mode 100644 index 0000000000..514acebd78 --- /dev/null +++ b/tests/micropython/viper_error.py @@ -0,0 +1,11 @@ +# test syntax errors specific to viper code generation + +def test_syntax(code): + try: + exec(code) + except SyntaxError: + print("SyntaxError") + +# viper: annotations must be identifiers +test_syntax("@micropython.viper\ndef f(a:1): pass") +test_syntax("@micropython.viper\ndef f() -> 1: pass") diff --git a/tests/micropython/viper_error.py.exp b/tests/micropython/viper_error.py.exp new file mode 100644 index 0000000000..5275689b41 --- /dev/null +++ b/tests/micropython/viper_error.py.exp @@ -0,0 +1,2 @@ +SyntaxError +SyntaxError