diff options
Diffstat (limited to 'tests')
336 files changed, 3990 insertions, 865 deletions
diff --git a/tests/basics/array_q.py b/tests/basics/array_intbig.py index 2975cd385..4a3b2a0d4 100644 --- a/tests/basics/array_q.py +++ b/tests/basics/array_intbig.py @@ -1,4 +1,4 @@ -# test array('q') and array('Q') +# test array types QqLl that require big-ints try: from array import array @@ -7,6 +7,9 @@ except ImportError: print("SKIP") sys.exit() +print(array('L', [0, 2**32-1])) +print(array('l', [-2**31, 0, 2**31-1])) + print(array('q')) print(array('Q')) diff --git a/tests/basics/array_micropython.py b/tests/basics/array_micropython.py index 8e904bdfe..0c1df0923 100644 --- a/tests/basics/array_micropython.py +++ b/tests/basics/array_micropython.py @@ -1,5 +1,10 @@ # test MicroPython-specific features of array.array -import array +try: + import array +except ImportError: + import sys + print("SKIP") + sys.exit() # arrays of objects a = array.array('O') diff --git a/tests/basics/attrtuple1.py b/tests/basics/attrtuple1.py index c4daaaf25..597bfc2a3 100644 --- a/tests/basics/attrtuple1.py +++ b/tests/basics/attrtuple1.py @@ -4,6 +4,15 @@ import sys t = sys.implementation +# It can be just a normal tuple on small ports +try: + t.name +except AttributeError: + import sys + print("SKIP") + sys.exit() + + # test printing of attrtuple print(str(t).find("version=") > 0) diff --git a/tests/basics/boundmeth1.py b/tests/basics/boundmeth1.py index a72887275..f483ba406 100644 --- a/tests/basics/boundmeth1.py +++ b/tests/basics/boundmeth1.py @@ -22,3 +22,9 @@ print(m(1)) # bound method with lots of extra args m = A().h print(m(1, 2, 3, 4, 5, 6)) + +# can't assign attributes to a bound method +try: + A().f.x = 1 +except AttributeError: + print('AttributeError') diff --git a/tests/basics/builtin_abs.py b/tests/basics/builtin_abs.py index 788bc450f..142344e22 100644 --- a/tests/basics/builtin_abs.py +++ b/tests/basics/builtin_abs.py @@ -4,11 +4,3 @@ print(abs(False)) print(abs(True)) print(abs(1)) print(abs(-1)) - -# bignum -print(abs(123456789012345678901234567890)) -print(abs(-123456789012345678901234567890)) - -# edge cases for 32 and 64 bit archs (small int overflow when negating) -print(abs(-0x3fffffff - 1)) -print(abs(-0x3fffffffffffffff - 1)) diff --git a/tests/basics/builtin_abs_intbig.py b/tests/basics/builtin_abs_intbig.py new file mode 100644 index 000000000..3dd5ea89f --- /dev/null +++ b/tests/basics/builtin_abs_intbig.py @@ -0,0 +1,9 @@ +# test builtin abs + +# bignum +print(abs(123456789012345678901234567890)) +print(abs(-123456789012345678901234567890)) + +# edge cases for 32 and 64 bit archs (small int overflow when negating) +print(abs(-0x3fffffff - 1)) +print(abs(-0x3fffffffffffffff - 1)) diff --git a/tests/basics/builtin_bin.py b/tests/basics/builtin_bin.py index f6b6079de..85af406ce 100644 --- a/tests/basics/builtin_bin.py +++ b/tests/basics/builtin_bin.py @@ -8,5 +8,4 @@ print(bin(-15)) print(bin(12345)) print(bin(0b10101)) -print(bin(12345678901234567890)) print(bin(0b10101010101010101010)) diff --git a/tests/basics/builtin_bin_intbig.py b/tests/basics/builtin_bin_intbig.py new file mode 100644 index 000000000..345e1f687 --- /dev/null +++ b/tests/basics/builtin_bin_intbig.py @@ -0,0 +1,3 @@ +# test builtin bin function + +print(bin(12345678901234567890)) diff --git a/tests/basics/builtin_delattr.py b/tests/basics/builtin_delattr.py index 3743df227..9b38837e4 100644 --- a/tests/basics/builtin_delattr.py +++ b/tests/basics/builtin_delattr.py @@ -1,4 +1,10 @@ # test builtin delattr +try: + delattr +except: + import sys + print("SKIP") + sys.exit() class A: pass a = A() diff --git a/tests/basics/builtin_dir.py b/tests/basics/builtin_dir.py index 843467e78..16e7e669e 100644 --- a/tests/basics/builtin_dir.py +++ b/tests/basics/builtin_dir.py @@ -5,7 +5,7 @@ print('__name__' in dir()) # dir of module import sys -print('platform' in dir(sys)) +print('exit' in dir(sys)) # dir of type print('append' in dir(list)) diff --git a/tests/basics/builtin_divmod.py b/tests/basics/builtin_divmod.py index c3b865819..26b3ae382 100644 --- a/tests/basics/builtin_divmod.py +++ b/tests/basics/builtin_divmod.py @@ -10,18 +10,6 @@ except ZeroDivisionError: print("ZeroDivisionError") try: - divmod(1 << 65, 0) -except ZeroDivisionError: - print("ZeroDivisionError") - -try: divmod('a', 'b') except TypeError: print("TypeError") - -# bignum -l = (1 << 65) + 123 -print(divmod(3, l)) -print(divmod(l, 5)) -print(divmod(l + 3, l)) -print(divmod(l * 20, l + 2)) diff --git a/tests/basics/builtin_divmod_intbig.py b/tests/basics/builtin_divmod_intbig.py new file mode 100644 index 000000000..758e83415 --- /dev/null +++ b/tests/basics/builtin_divmod_intbig.py @@ -0,0 +1,13 @@ +# test builtin divmod + +try: + divmod(1 << 65, 0) +except ZeroDivisionError: + print("ZeroDivisionError") + +# bignum +l = (1 << 65) + 123 +print(divmod(3, l)) +print(divmod(l, 5)) +print(divmod(l + 3, l)) +print(divmod(l * 20, l + 2)) diff --git a/tests/basics/builtin_hash.py b/tests/basics/builtin_hash.py index ffea08e57..704895fbb 100644 --- a/tests/basics/builtin_hash.py +++ b/tests/basics/builtin_hash.py @@ -4,8 +4,6 @@ print(hash(False)) print(hash(True)) print({():1}) # hash tuple print({(1,):1}) # hash non-empty tuple -print({1 << 66:1}) # hash big int -print({-(1 << 66):2}) # hash negative big int print(hash in {hash:1}) # hash function try: @@ -50,9 +48,3 @@ class E: def __hash__(self): return True print(hash(E())) - -# __hash__ returning a large number should be truncated -class F: - def __hash__(self): - return 1 << 70 | 1 -print(hash(F()) != 0) diff --git a/tests/basics/builtin_hash_intbig.py b/tests/basics/builtin_hash_intbig.py new file mode 100644 index 000000000..0092c0f3a --- /dev/null +++ b/tests/basics/builtin_hash_intbig.py @@ -0,0 +1,10 @@ +# test builtin hash function + +print({1 << 66:1}) # hash big int +print({-(1 << 66):2}) # hash negative big int + +# __hash__ returning a large number should be truncated +class F: + def __hash__(self): + return 1 << 70 | 1 +print(hash(F()) != 0) diff --git a/tests/basics/builtin_help.py b/tests/basics/builtin_help.py new file mode 100644 index 000000000..d554f308d --- /dev/null +++ b/tests/basics/builtin_help.py @@ -0,0 +1,18 @@ +# test builtin help function + +try: + help +except NameError: + print("SKIP") + import sys + sys.exit() + +help() # no args +help(help) # help for a function +help(int) # help for a class +help(1) # help for an instance +import micropython +help(micropython) # help for a module +help('modules') # list available modules + +print('done') # so last bit of output is predictable diff --git a/tests/basics/builtin_help.py.exp b/tests/basics/builtin_help.py.exp new file mode 100644 index 000000000..ed8a7d74b --- /dev/null +++ b/tests/basics/builtin_help.py.exp @@ -0,0 +1,14 @@ +######## +object <function> is of type function +object <class 'int'> is of type type + from_bytes -- <classmethod> + to_bytes -- <function> +object 1 is of type int + from_bytes -- <classmethod> + to_bytes -- <function> +object <module 'micropython'> is of type module + __name__ -- micropython + const -- <function> + opt_level -- <function> +######## +done diff --git a/tests/basics/builtin_hex.py b/tests/basics/builtin_hex.py index 7d1c98a7a..95d74257e 100644 --- a/tests/basics/builtin_hex.py +++ b/tests/basics/builtin_hex.py @@ -7,6 +7,3 @@ print(hex(-15)) print(hex(12345)) print(hex(0x12345)) - -print(hex(12345678901234567890)) -print(hex(0x12345678901234567890)) diff --git a/tests/basics/builtin_hex_intbig.py b/tests/basics/builtin_hex_intbig.py new file mode 100644 index 000000000..7049ca3f5 --- /dev/null +++ b/tests/basics/builtin_hex_intbig.py @@ -0,0 +1,4 @@ +# test builtin hex function + +print(hex(12345678901234567890)) +print(hex(0x12345678901234567890)) diff --git a/tests/basics/builtin_minmax.py b/tests/basics/builtin_minmax.py index d395d4421..a925b3fe9 100644 --- a/tests/basics/builtin_minmax.py +++ b/tests/basics/builtin_minmax.py @@ -1,4 +1,11 @@ # test builtin min and max functions +try: + min + max +except: + import sys + print("SKIP") + sys.exit() print(min(0,1)) print(min(1,0)) diff --git a/tests/basics/builtin_oct.py b/tests/basics/builtin_oct.py index d8ba8e434..6dc48a6fa 100644 --- a/tests/basics/builtin_oct.py +++ b/tests/basics/builtin_oct.py @@ -7,6 +7,3 @@ print(oct(-15)) print(oct(12345)) print(oct(0o12345)) - -print(oct(12345678901234567890)) -print(oct(0o12345670123456701234)) diff --git a/tests/basics/builtin_oct_intbig.py b/tests/basics/builtin_oct_intbig.py new file mode 100644 index 000000000..4dc28ab46 --- /dev/null +++ b/tests/basics/builtin_oct_intbig.py @@ -0,0 +1,4 @@ +# test builtin oct function + +print(oct(12345678901234567890)) +print(oct(0o12345670123456701234)) diff --git a/tests/basics/builtin_override.py b/tests/basics/builtin_override.py index e245985ad..f3632e59a 100644 --- a/tests/basics/builtin_override.py +++ b/tests/basics/builtin_override.py @@ -3,7 +3,13 @@ import builtins # override generic builtin -builtins.abs = lambda x: x + 1 +try: + builtins.abs = lambda x: x + 1 +except AttributeError: + import sys + print("SKIP") + sys.exit() + print(abs(1)) # __build_class__ is handled in a special way diff --git a/tests/basics/builtin_pow.py b/tests/basics/builtin_pow.py index a19ab8c84..5012a76be 100644 --- a/tests/basics/builtin_pow.py +++ b/tests/basics/builtin_pow.py @@ -1,11 +1,7 @@ # test builtin pow() with integral values - # 2 arg version + print(pow(0, 1)) print(pow(1, 0)) print(pow(-2, 3)) print(pow(3, 8)) - -# 3 arg version -print(pow(3, 4, 7)) - diff --git a/tests/basics/builtin_pow3.py b/tests/basics/builtin_pow3.py new file mode 100644 index 000000000..dec7253bb --- /dev/null +++ b/tests/basics/builtin_pow3.py @@ -0,0 +1,25 @@ +# test builtin pow() with integral values +# 3 arg version + +try: + print(pow(3, 4, 7)) +except NotImplementedError: + import sys + print("SKIP") + sys.exit() + +# 3 arg pow is defined to only work on integers +try: + print(pow("x", 5, 6)) +except TypeError: + print("TypeError expected") + +try: + print(pow(4, "y", 6)) +except TypeError: + print("TypeError expected") + +try: + print(pow(4, 5, "z")) +except TypeError: + print("TypeError expected") diff --git a/tests/basics/builtin_pow3_intbig.py b/tests/basics/builtin_pow3_intbig.py new file mode 100644 index 000000000..9f482cbde --- /dev/null +++ b/tests/basics/builtin_pow3_intbig.py @@ -0,0 +1,23 @@ +# test builtin pow() with integral values +# 3 arg version + +try: + print(pow(3, 4, 7)) +except NotImplementedError: + import sys + print("SKIP") + sys.exit() + +print(pow(555557, 1000002, 1000003)) + +# Tests for 3 arg pow with large values + +# This value happens to be prime +x = 0xd48a1e2a099b1395895527112937a391d02d4a208bce5d74b281cf35a57362502726f79a632f063a83c0eba66196712d963aa7279ab8a504110a668c0fc38a7983c51e6ee7a85cae87097686ccdc359ee4bbf2c583bce524e3f7836bded1c771a4efcb25c09460a862fc98e18f7303df46aaeb34da46b0c4d61d5cd78350f3edb60e6bc4befa712a849 +y = 0x3accf60bb1a5365e4250d1588eb0fe6cd81ad495e9063f90880229f2a625e98c59387238670936afb2cafc5b79448e4414d6cd5e9901aa845aa122db58ddd7b9f2b17414600a18c47494ed1f3d49d005a5 + +print(hex(pow(2, 200, x))) # Should not overflow, just 1 << 200 +print(hex(pow(2, x-1, x))) # Should be 1, since x is prime +print(hex(pow(y, x-1, x))) # Should be 1, since x is prime +print(hex(pow(y, y-1, x))) # Should be a 'big value' +print(hex(pow(y, y-1, y))) # Should be a 'big value' diff --git a/tests/basics/builtin_property.py b/tests/basics/builtin_property.py index 403abd62f..ff4ff073c 100644 --- a/tests/basics/builtin_property.py +++ b/tests/basics/builtin_property.py @@ -1,4 +1,10 @@ # test builtin property +try: + property +except: + import sys + print("SKIP") + sys.exit() # create a property object explicitly property() diff --git a/tests/basics/builtin_range.py b/tests/basics/builtin_range.py index 59fc0344a..0e2fabd82 100644 --- a/tests/basics/builtin_range.py +++ b/tests/basics/builtin_range.py @@ -33,11 +33,16 @@ 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]) -# attrs -print(range(1, 2, 3).start) -print(range(1, 2, 3).stop) -print(range(1, 2, 3).step) +# zero step +try: + range(1, 2, 0) +except ValueError: + print("ValueError") # bad unary op try: @@ -50,9 +55,3 @@ try: range(1)[0] = 1 except TypeError: print("TypeError") - -# bad attr (can't store) -try: - range(4).start = 0 -except AttributeError: - print('AttributeError') diff --git a/tests/basics/builtin_range_attrs.py b/tests/basics/builtin_range_attrs.py new file mode 100644 index 000000000..9327c802a --- /dev/null +++ b/tests/basics/builtin_range_attrs.py @@ -0,0 +1,19 @@ +# test attributes of builtin range type + +try: + range(0).start +except AttributeError: + import sys + print("SKIP") + sys.exit() + +# attrs +print(range(1, 2, 3).start) +print(range(1, 2, 3).stop) +print(range(1, 2, 3).step) + +# bad attr (can't store) +try: + range(4).start = 0 +except AttributeError: + print('AttributeError') diff --git a/tests/basics/builtin_reversed.py b/tests/basics/builtin_reversed.py index f129a4f5d..59e9c7821 100644 --- a/tests/basics/builtin_reversed.py +++ b/tests/basics/builtin_reversed.py @@ -1,4 +1,10 @@ # test the builtin reverse() function +try: + reversed +except: + import sys + print("SKIP") + sys.exit() # list print(list(reversed([]))) diff --git a/tests/basics/builtin_sorted.py b/tests/basics/builtin_sorted.py index a4f71a15e..68855b61b 100644 --- a/tests/basics/builtin_sorted.py +++ b/tests/basics/builtin_sorted.py @@ -1,4 +1,11 @@ # test builtin sorted +try: + sorted + set +except: + import sys + print("SKIP") + sys.exit() print(sorted(set(range(100)))) print(sorted(set(range(100)), key=lambda x: x + 100*(x % 2))) diff --git a/tests/basics/bytearray_construct.py b/tests/basics/bytearray_construct.py index 1c45f6fcf..9c8f3adaa 100644 --- a/tests/basics/bytearray_construct.py +++ b/tests/basics/bytearray_construct.py @@ -1,12 +1,6 @@ # test construction of bytearray from different objects -from array import array - # bytes, tuple, list print(bytearray(b'123')) print(bytearray((1, 2))) print(bytearray([1, 2])) - -# arrays -print(bytearray(array('b', [1, 2]))) -print(bytearray(array('h', [0x101, 0x202]))) diff --git a/tests/basics/bytearray_construct_array.py b/tests/basics/bytearray_construct_array.py new file mode 100644 index 000000000..6d45cafda --- /dev/null +++ b/tests/basics/bytearray_construct_array.py @@ -0,0 +1,11 @@ +# test construction of bytearray from different objects +try: + from array import array +except ImportError: + import sys + print("SKIP") + sys.exit() + +# arrays +print(bytearray(array('b', [1, 2]))) +print(bytearray(array('h', [0x101, 0x202]))) diff --git a/tests/basics/bytearray_construct_endian.py b/tests/basics/bytearray_construct_endian.py index dbd635c0c..f68f9b89d 100644 --- a/tests/basics/bytearray_construct_endian.py +++ b/tests/basics/bytearray_construct_endian.py @@ -1,6 +1,10 @@ # test construction of bytearray from different objects - -from array import array +try: + from array import array +except ImportError: + import sys + print("SKIP") + sys.exit() # arrays print(bytearray(array('h', [1, 2]))) diff --git a/tests/basics/bytearray_longint.py b/tests/basics/bytearray_intbig.py index 334eabe12..334eabe12 100644 --- a/tests/basics/bytearray_longint.py +++ b/tests/basics/bytearray_intbig.py diff --git a/tests/basics/bytearray_slice_assign.py b/tests/basics/bytearray_slice_assign.py index 510e784da..c4b5c43e3 100644 --- a/tests/basics/bytearray_slice_assign.py +++ b/tests/basics/bytearray_slice_assign.py @@ -51,6 +51,11 @@ b = bytearray(10) b[:-1] = bytearray(500) print(len(b), b[0], b[-1]) +# extension with self on RHS +b = bytearray(x) +b[4:] = b +print(b) + # Assignment of bytes to array slice b = bytearray(2) b[1:1] = b"12345" diff --git a/tests/basics/bytes_add.py b/tests/basics/bytes_add.py index 7a887db23..ebccf0662 100644 --- a/tests/basics/bytes_add.py +++ b/tests/basics/bytes_add.py @@ -3,9 +3,6 @@ print(b"123" + b"456") print(b"123" + bytearray(2)) -import array - -# should be byteorder-neutral -print(b"123" + array.array('h', [0x1515])) - -print(b"\x01\x02" + array.array('b', [1, 2])) +print(b"123" + b"") # RHS is empty, can be optimised +print(b"" + b"123") # LHS is empty, can be optimised +print(b"" + bytearray(1)) # LHS is empty but can't be optimised diff --git a/tests/basics/bytes_add_array.py b/tests/basics/bytes_add_array.py new file mode 100644 index 000000000..2b8cbccef --- /dev/null +++ b/tests/basics/bytes_add_array.py @@ -0,0 +1,12 @@ +# test bytes + other +try: + import array +except ImportError: + import sys + print("SKIP") + sys.exit() + +# should be byteorder-neutral +print(b"123" + array.array('h', [0x1515])) + +print(b"\x01\x02" + array.array('b', [1, 2])) diff --git a/tests/basics/bytes_add_endian.py b/tests/basics/bytes_add_endian.py index 5471280d9..1bbd0f2c3 100644 --- a/tests/basics/bytes_add_endian.py +++ b/tests/basics/bytes_add_endian.py @@ -1,5 +1,9 @@ # test bytes + other - -import array +try: + import array +except ImportError: + import sys + print("SKIP") + sys.exit() print(b"123" + array.array('i', [1])) diff --git a/tests/basics/bytes_compare2.py b/tests/basics/bytes_compare2.py index 8959da3ae..4d5de21d2 100644 --- a/tests/basics/bytes_compare2.py +++ b/tests/basics/bytes_compare2.py @@ -3,9 +3,3 @@ print(b"123" == bytearray(b"123")) print(b'123' < bytearray(b"124")) print(b'123' > bytearray(b"122")) print(bytearray(b"23") in b"1234") - -import array - -print(array.array('b', [1, 2]) in b'\x01\x02\x03') -# CPython gives False here -#print(b"\x01\x02\x03" == array.array("B", [1, 2, 3])) diff --git a/tests/basics/bytes_compare_array.py b/tests/basics/bytes_compare_array.py new file mode 100644 index 000000000..ad41d1d37 --- /dev/null +++ b/tests/basics/bytes_compare_array.py @@ -0,0 +1,10 @@ +try: + import array +except ImportError: + import sys + print("SKIP") + sys.exit() + +print(array.array('b', [1, 2]) in b'\x01\x02\x03') +# CPython gives False here +#print(b"\x01\x02\x03" == array.array("B", [1, 2, 3])) diff --git a/tests/basics/bytes_construct.py b/tests/basics/bytes_construct.py index 59e02f063..0d638c08f 100644 --- a/tests/basics/bytes_construct.py +++ b/tests/basics/bytes_construct.py @@ -1,19 +1,10 @@ # test construction of bytes from different objects -from array import array - # tuple, list, bytearray print(bytes((1, 2))) print(bytes([1, 2])) print(bytes(bytearray(4))) -# arrays -print(bytes(array('b', [1, 2]))) -print(bytes(array('h', [0x101, 0x202]))) - -# long ints -print(ord(bytes([14953042807679334000 & 0xff]))) - # constructor value out of range try: bytes([-1]) diff --git a/tests/basics/bytes_construct_array.py b/tests/basics/bytes_construct_array.py new file mode 100644 index 000000000..72c2d0c58 --- /dev/null +++ b/tests/basics/bytes_construct_array.py @@ -0,0 +1,11 @@ +# test construction of bytes from different objects +try: + from array import array +except ImportError: + import sys + print("SKIP") + sys.exit() + +# arrays +print(bytes(array('b', [1, 2]))) +print(bytes(array('h', [0x101, 0x202]))) diff --git a/tests/basics/bytes_construct_endian.py b/tests/basics/bytes_construct_endian.py index 1912f63a4..77e0eaaa5 100644 --- a/tests/basics/bytes_construct_endian.py +++ b/tests/basics/bytes_construct_endian.py @@ -1,6 +1,11 @@ # test construction of bytes from different objects -from array import array +try: + from array import array +except ImportError: + import sys + print("SKIP") + sys.exit() # arrays print(bytes(array('h', [1, 2]))) diff --git a/tests/basics/bytes_construct_intbig.py b/tests/basics/bytes_construct_intbig.py new file mode 100644 index 000000000..c32de185f --- /dev/null +++ b/tests/basics/bytes_construct_intbig.py @@ -0,0 +1,4 @@ +# test construction of bytes from different objects + +# long ints +print(ord(bytes([14953042807679334000 & 0xff]))) diff --git a/tests/basics/class_delattr_setattr.py b/tests/basics/class_delattr_setattr.py new file mode 100644 index 000000000..0d061aee6 --- /dev/null +++ b/tests/basics/class_delattr_setattr.py @@ -0,0 +1,63 @@ +# test __delattr__ and __setattr__ + +# feature test for __setattr__/__delattr__ +try: + class Test(): + def __delattr__(self, attr): pass + del Test().noexist +except AttributeError: + import sys + print('SKIP') + sys.exit() + +# this class just prints the calls to see if they were executed +class A(): + def __getattr__(self, attr): + print('get', attr) + return 1 + def __setattr__(self, attr, val): + print('set', attr, val) + def __delattr__(self, attr): + print('del', attr) +a = A() + +# check basic behaviour +print(getattr(a, 'foo')) +setattr(a, 'bar', 2) +delattr(a, 'baz') + +# check meta behaviour +getattr(a, '__getattr__') # should not call A.__getattr__ +getattr(a, '__setattr__') # should not call A.__getattr__ +getattr(a, '__delattr__') # should not call A.__getattr__ +setattr(a, '__setattr__', 1) # should call A.__setattr__ +delattr(a, '__delattr__') # should call A.__delattr__ + +# this class acts like a dictionary +class B: + def __init__(self, d): + # store the dict in the class, not instance, so + # we don't get infinite recursion in __getattr_ + B.d = d + + def __getattr__(self, attr): + if attr in B.d: + return B.d[attr] + else: + raise AttributeError(attr) + + def __setattr__(self, attr, value): + B.d[attr] = value + + def __delattr__(self, attr): + del B.d[attr] + +a = B({"a":1, "b":2}) +print(a.a, a.b) +a.a = 3 +print(a.a, a.b) +del a.a +try: + print(a.a) +except AttributeError: + print("AttributeError") diff --git a/tests/basics/class_descriptor.py b/tests/basics/class_descriptor.py index 25b373e47..7f295f071 100644 --- a/tests/basics/class_descriptor.py +++ b/tests/basics/class_descriptor.py @@ -18,6 +18,13 @@ class Main: Forward = Descriptor() m = Main() +try: + m.__class__ +except AttributeError: + import sys + print("SKIP") + sys.exit() + r = m.Forward if 'Descriptor' in repr(r.__class__): print('SKIP') diff --git a/tests/basics/class_new.py b/tests/basics/class_new.py index a6a34c581..0198456b2 100644 --- a/tests/basics/class_new.py +++ b/tests/basics/class_new.py @@ -1,3 +1,11 @@ +try: + # If we don't expose object.__new__ (small ports), there's + # nothing to test. + object.__new__ +except AttributeError: + import sys + print("SKIP") + sys.exit() class A: def __new__(cls): print("A.__new__") diff --git a/tests/basics/class_store_class.py b/tests/basics/class_store_class.py index 10b94d3c6..00a291586 100644 --- a/tests/basics/class_store_class.py +++ b/tests/basics/class_store_class.py @@ -5,7 +5,12 @@ try: from collections import namedtuple except ImportError: - from ucollections import namedtuple + try: + from ucollections import namedtuple + except ImportError: + import sys + print("SKIP") + sys.exit() _DefragResultBase = namedtuple('DefragResult', [ 'foo', 'bar' ]) diff --git a/tests/basics/class_super.py b/tests/basics/class_super.py index 4b052d8f3..1338ef452 100644 --- a/tests/basics/class_super.py +++ b/tests/basics/class_super.py @@ -20,3 +20,17 @@ 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()) diff --git a/tests/basics/class_super_aslocal.py b/tests/basics/class_super_aslocal.py new file mode 100644 index 000000000..c9259110a --- /dev/null +++ b/tests/basics/class_super_aslocal.py @@ -0,0 +1,9 @@ +# test using the name "super" as a local variable + +class A: + def foo(self): + super = [1, 2] + super.pop() + print(super) + +A().foo() diff --git a/tests/basics/class_super_closure.py b/tests/basics/class_super_closure.py new file mode 100644 index 000000000..41acae90d --- /dev/null +++ b/tests/basics/class_super_closure.py @@ -0,0 +1,18 @@ +# test that no-arg super() works when self is closed over + +class A: + def __init__(self): + self.val = 4 + def foo(self): + # we access a member of self to check that self is correct + return list(range(self.val)) +class B(A): + def foo(self): + # self is closed over because it's referenced in the list comprehension + # and then super() must detect this and load from the closure cell + return [self.bar(i) for i in super().foo()] + def bar(self, x): + return 2 * x + +print(A().foo()) +print(B().foo()) diff --git a/tests/basics/class_super_object.py b/tests/basics/class_super_object.py index 21b97328e..a841d34ab 100644 --- a/tests/basics/class_super_object.py +++ b/tests/basics/class_super_object.py @@ -1,4 +1,12 @@ # Calling object.__init__() via super().__init__ +try: + # If we don't expose object.__init__ (small ports), there's + # nothing to test. + object.__init__ +except AttributeError: + import sys + print("SKIP") + sys.exit() class Test(object): def __init__(self): diff --git a/tests/basics/comprehension1.py b/tests/basics/comprehension1.py index 7f541ee53..892d6b4e3 100644 --- a/tests/basics/comprehension1.py +++ b/tests/basics/comprehension1.py @@ -14,7 +14,6 @@ def f(): print(d[0], d[1], d[2], d[3], d[4]) # set comprehension - - print({a for a in range(5)}) + # see set_comprehension.py f() diff --git a/tests/basics/containment.py b/tests/basics/containment.py index f8be04e92..bae366113 100644 --- a/tests/basics/containment.py +++ b/tests/basics/containment.py @@ -1,5 +1,6 @@ +# sets, see set_containment for i in 1, 2: - for o in {1:2}, {1}, {1:2}.keys(): + for o in {1:2}, {1:2}.keys(): print("{} in {}: {}".format(i, o, i in o)) print("{} not in {}: {}".format(i, o, i not in o)) diff --git a/tests/basics/dict_fromkeys.py b/tests/basics/dict_fromkeys.py index bfad347c8..7b11319a2 100644 --- a/tests/basics/dict_fromkeys.py +++ b/tests/basics/dict_fromkeys.py @@ -7,7 +7,3 @@ d = dict.fromkeys([1, 2, 3, 4], 42) l = list(d.values()) l.sort() print(l) - -# argument to fromkeys has no __len__ -d = dict.fromkeys(reversed(range(1))) -print(d) diff --git a/tests/basics/dict_fromkeys2.py b/tests/basics/dict_fromkeys2.py new file mode 100644 index 000000000..7ea0cc5b3 --- /dev/null +++ b/tests/basics/dict_fromkeys2.py @@ -0,0 +1,11 @@ +try: + reversed +except: + import sys + print("SKIP") + sys.exit() + +# argument to fromkeys has no __len__ +d = dict.fromkeys(reversed(range(1))) +#d = dict.fromkeys((x for x in range(1))) +print(d) diff --git a/tests/basics/enumerate.py b/tests/basics/enumerate.py index 00595cb0f..3cc1350a0 100644 --- a/tests/basics/enumerate.py +++ b/tests/basics/enumerate.py @@ -1,3 +1,10 @@ +try: + enumerate +except: + import sys + print("SKIP") + sys.exit() + print(list(enumerate([]))) print(list(enumerate([1, 2, 3]))) print(list(enumerate([1, 2, 3], 5))) diff --git a/tests/basics/filter.py b/tests/basics/filter.py index 5883e3d00..d0b36733c 100644 --- a/tests/basics/filter.py +++ b/tests/basics/filter.py @@ -1,2 +1,9 @@ +try: + filter +except: + import sys + print("SKIP") + sys.exit() + print(list(filter(lambda x: x & 1, range(-3, 4)))) print(list(filter(None, range(-3, 4)))) diff --git a/tests/basics/floordivide.py b/tests/basics/floordivide.py index 930313d6c..60e7634b1 100644 --- a/tests/basics/floordivide.py +++ b/tests/basics/floordivide.py @@ -12,18 +12,3 @@ print(a // b) print(a // -b) print(-a // b) print(-a // -b) - -if True: - a = 987654321987987987987987987987 - b = 19 - - print(a // b) - print(a // -b) - print(-a // b) - print(-a // -b) - a = 10000000000000000000000000000000000000000000 - b = 100 - print(a // b) - print(a // -b) - print(-a // b) - print(-a // -b) diff --git a/tests/basics/floordivide_intbig.py b/tests/basics/floordivide_intbig.py new file mode 100644 index 000000000..422329fcd --- /dev/null +++ b/tests/basics/floordivide_intbig.py @@ -0,0 +1,15 @@ +# check modulo matches python definition + +a = 987654321987987987987987987987 +b = 19 + +print(a // b) +print(a // -b) +print(-a // b) +print(-a // -b) +a = 10000000000000000000000000000000000000000000 +b = 100 +print(a // b) +print(a // -b) +print(-a // b) +print(-a // -b) diff --git a/tests/basics/for_range.py b/tests/basics/for_range.py index 58a8f7caa..fc736277d 100644 --- a/tests/basics/for_range.py +++ b/tests/basics/for_range.py @@ -6,6 +6,13 @@ for x in range(*(1, 3)): for x in range(1, *(6, 2)): print(x) +# zero step +try: + for x in range(1, 2, 0): + pass +except ValueError: + print('ValueError') + # apply args using ** try: for x in range(**{'end':1}): diff --git a/tests/basics/fun_calldblstar3.py b/tests/basics/fun_calldblstar3.py index 4367e68df..b796d52c7 100644 --- a/tests/basics/fun_calldblstar3.py +++ b/tests/basics/fun_calldblstar3.py @@ -5,7 +5,8 @@ def foo(**kw): class Mapping: def keys(self): - return ['a', 'b', 'c'] + # the long string checks the case of string interning + return ['a', 'b', 'c', 'abcdefghijklmnopqrst'] def __getitem__(self, key): if key == 'a': diff --git a/tests/basics/fun_callstar.py b/tests/basics/fun_callstar.py index 2275d3d4f..a27a288a3 100644 --- a/tests/basics/fun_callstar.py +++ b/tests/basics/fun_callstar.py @@ -17,6 +17,11 @@ foo(*range(3)) # pos then iterator foo(1, *range(2, 4)) +# an iterator with many elements +def foo(*rest): + print(rest) +foo(*range(10)) + # method calls with *pos class A: diff --git a/tests/basics/fun_error.py b/tests/basics/fun_error.py index 305b24911..367fe0b7f 100644 --- a/tests/basics/fun_error.py +++ b/tests/basics/fun_error.py @@ -27,8 +27,5 @@ test_exc("[].sort(1)", TypeError) # function with keyword args given extra keyword args test_exc("[].sort(noexist=1)", TypeError) -# function with keyword args not given a specific keyword arg -test_exc("enumerate()", TypeError) - # kw given for positional, but a different positional is missing test_exc("def f(x, y): pass\nf(x=1)", TypeError) diff --git a/tests/basics/fun_error2.py b/tests/basics/fun_error2.py new file mode 100644 index 000000000..c4d2c0b64 --- /dev/null +++ b/tests/basics/fun_error2.py @@ -0,0 +1,19 @@ +# test errors from bad function calls +try: + enumerate +except: + print("SKIP") + import sys + sys.exit() + +def test_exc(code, exc): + try: + exec(code) + print("no exception") + except exc: + print("right exception") + except: + print("wrong exception") + +# function with keyword args not given a specific keyword arg +test_exc("enumerate()", TypeError) diff --git a/tests/basics/gen_yield_from_close.py b/tests/basics/gen_yield_from_close.py index d66691ff9..833986105 100644 --- a/tests/basics/gen_yield_from_close.py +++ b/tests/basics/gen_yield_from_close.py @@ -102,7 +102,7 @@ except RuntimeError: # case where close is propagated up to a built-in iterator def gen8(): - g = reversed([2, 1]) + g = range(2) yield from g g = gen8() print(next(g)) diff --git a/tests/basics/gen_yield_from_throw2.py b/tests/basics/gen_yield_from_throw2.py index 2cff9e08b..0abfdd8cc 100644 --- a/tests/basics/gen_yield_from_throw2.py +++ b/tests/basics/gen_yield_from_throw2.py @@ -1,5 +1,5 @@ -# uPy differs from CPython for this test -# generator ignored GeneratorExit +# generator ignores a thrown GeneratorExit (this is allowed) + def gen(): try: yield 123 @@ -7,9 +7,12 @@ def gen(): print('GeneratorExit') yield 456 +# thrown a class g = gen() print(next(g)) -try: - g.throw(GeneratorExit) -except RuntimeError: - print('RuntimeError') +print(g.throw(GeneratorExit)) + +# thrown an instance +g = gen() +print(next(g)) +print(g.throw(GeneratorExit())) diff --git a/tests/basics/gen_yield_from_throw2.py.exp b/tests/basics/gen_yield_from_throw2.py.exp deleted file mode 100644 index d5805b494..000000000 --- a/tests/basics/gen_yield_from_throw2.py.exp +++ /dev/null @@ -1,3 +0,0 @@ -123 -GeneratorExit -RuntimeError diff --git a/tests/basics/gen_yield_from_throw3.py b/tests/basics/gen_yield_from_throw3.py new file mode 100644 index 000000000..0f6c7c842 --- /dev/null +++ b/tests/basics/gen_yield_from_throw3.py @@ -0,0 +1,30 @@ +# yield-from a user-defined generator with a throw() method + +class Iter: + def __iter__(self): + return self + + def __next__(self): + return 1 + + def throw(self, x): + print('throw', x) + return 456 + +def gen(): + yield from Iter() + +# calling close() should not call throw() +g = gen() +print(next(g)) +g.close() + +# can throw a non-exception object +g = gen() +print(next(g)) +print(g.throw(123)) + +# throwing an exception class just injects that class +g = gen() +print(next(g)) +print(g.throw(ZeroDivisionError)) diff --git a/tests/basics/int_mpz.py b/tests/basics/int_big1.py index 425bc21b6..425bc21b6 100644 --- a/tests/basics/int_mpz.py +++ b/tests/basics/int_big1.py diff --git a/tests/basics/int_bytes.py b/tests/basics/int_bytes.py index 2f468da44..93c00bba1 100644 --- a/tests/basics/int_bytes.py +++ b/tests/basics/int_bytes.py @@ -1,7 +1,10 @@ print((10).to_bytes(1, "little")) print((111111).to_bytes(4, "little")) print((100).to_bytes(10, "little")) -print((2**64).to_bytes(9, "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) diff --git a/tests/basics/int_bytes_intbig.py b/tests/basics/int_bytes_intbig.py new file mode 100644 index 000000000..0e0ad1cbb --- /dev/null +++ b/tests/basics/int_bytes_intbig.py @@ -0,0 +1,12 @@ +print((2**64).to_bytes(9, "little")) + +b = bytes(range(20)) + +il = int.from_bytes(b, "little") +ib = int.from_bytes(b, "big") +print(il) +print(ib) +print(il.to_bytes(20, "little")) + +# check that extra zero bytes don't change the internal int value +print(int.from_bytes(b + bytes(10), "little") == int.from_bytes(b, "little")) diff --git a/tests/basics/int_bytes_notimpl.py b/tests/basics/int_bytes_notimpl.py index b47d6ab58..b149f4496 100644 --- a/tests/basics/int_bytes_notimpl.py +++ b/tests/basics/int_bytes_notimpl.py @@ -2,8 +2,3 @@ try: print((10).to_bytes(1, "big")) except Exception as e: print(type(e)) - -try: - print(int.from_bytes(b"\0", "big")) -except Exception as e: - print(type(e)) diff --git a/tests/basics/int_bytes_notimpl.py.exp b/tests/basics/int_bytes_notimpl.py.exp index d1bf338eb..606649a69 100644 --- a/tests/basics/int_bytes_notimpl.py.exp +++ b/tests/basics/int_bytes_notimpl.py.exp @@ -1,2 +1 @@ <class 'NotImplementedError'> -<class 'NotImplementedError'> diff --git a/tests/basics/int_constfolding.py b/tests/basics/int_constfolding.py index aa38fa6b8..7bb538378 100644 --- a/tests/basics/int_constfolding.py +++ b/tests/basics/int_constfolding.py @@ -7,19 +7,11 @@ print(+100) # negation print(-1) print(-(-1)) -print(-0x3fffffff) # 32-bit edge case -print(-0x3fffffffffffffff) # 64-bit edge case -print(-(-0x3fffffff - 1)) # 32-bit edge case -print(-(-0x3fffffffffffffff - 1)) # 64-bit edge case # 1's complement print(~0) print(~1) print(~-1) -print(~0x3fffffff) # 32-bit edge case -print(~0x3fffffffffffffff) # 64-bit edge case -print(~(-0x3fffffff - 1)) # 32-bit edge case -print(~(-0x3fffffffffffffff - 1)) # 64-bit edge case # addition print(1 + 2) @@ -37,9 +29,3 @@ print(123 // 7, 123 % 7) print(-123 // 7, -123 % 7) print(123 // -7, 123 % -7) print(-123 // -7, -123 % -7) - -# zero big-num on rhs -print(1 + ((1 << 65) - (1 << 65))) - -# negative big-num on rhs -print(1 + (-(1 << 65))) diff --git a/tests/basics/int_constfolding_intbig.py b/tests/basics/int_constfolding_intbig.py new file mode 100644 index 000000000..714f1559a --- /dev/null +++ b/tests/basics/int_constfolding_intbig.py @@ -0,0 +1,19 @@ +# tests int constant folding in compiler + +# negation +print(-0x3fffffff) # 32-bit edge case +print(-0x3fffffffffffffff) # 64-bit edge case +print(-(-0x3fffffff - 1)) # 32-bit edge case +print(-(-0x3fffffffffffffff - 1)) # 64-bit edge case + +# 1's complement +print(~0x3fffffff) # 32-bit edge case +print(~0x3fffffffffffffff) # 64-bit edge case +print(~(-0x3fffffff - 1)) # 32-bit edge case +print(~(-0x3fffffffffffffff - 1)) # 64-bit edge case + +# zero big-num on rhs +print(1 + ((1 << 65) - (1 << 65))) + +# negative big-num on rhs +print(1 + (-(1 << 65))) diff --git a/tests/basics/int_divmod.py b/tests/basics/int_divmod.py index 3c76cd958..2e878135f 100644 --- a/tests/basics/int_divmod.py +++ b/tests/basics/int_divmod.py @@ -5,11 +5,3 @@ for i in range(-2, 3): for j in range(-4, 5): if j != 0: print(i, j, i // j, i % j, divmod(i, j)) - -# this tests bignum modulo -a = 987654321987987987987987987987 -b = 19 -print(a % b) -print(a % -b) -print(-a % b) -print(-a % -b) diff --git a/tests/basics/int_divmod_intbig.py b/tests/basics/int_divmod_intbig.py new file mode 100644 index 000000000..ea8de07f2 --- /dev/null +++ b/tests/basics/int_divmod_intbig.py @@ -0,0 +1,9 @@ +# test integer floor division and modulo + +# this tests bignum modulo +a = 987654321987987987987987987987 +b = 19 +print(a % b) +print(a % -b) +print(-a % b) +print(-a % -b) diff --git a/tests/basics/int_long.py b/tests/basics/int_intbig.py index a22075d1f..a22075d1f 100644 --- a/tests/basics/int_long.py +++ b/tests/basics/int_intbig.py diff --git a/tests/basics/iter0.py b/tests/basics/iter0.py index 6110e8fa5..d20ade7fe 100644 --- a/tests/basics/iter0.py +++ b/tests/basics/iter0.py @@ -4,3 +4,6 @@ try: pass except TypeError: print('TypeError') + +# builtin type that is iterable, calling __next__ explicitly +print(iter(range(4)).__next__()) diff --git a/tests/basics/iter_of_iter.py b/tests/basics/iter_of_iter.py index 70282aa97..d775b6a44 100644 --- a/tests/basics/iter_of_iter.py +++ b/tests/basics/iter_of_iter.py @@ -4,5 +4,4 @@ i = iter(iter([1, 2, 3])) print(list(i)) i = iter(iter({1:2, 3:4, 5:6})) print(sorted(i)) -i = iter(iter({1, 2, 3})) -print(sorted(i)) +# set, see set_iter_of_iter.py diff --git a/tests/basics/lexer.py b/tests/basics/lexer.py index 5f12afa70..244de8cb9 100644 --- a/tests/basics/lexer.py +++ b/tests/basics/lexer.py @@ -9,6 +9,14 @@ exec("\n") exec("\n\n") exec("\r") exec("\r\r") +exec("\t") +exec("\r\n") +exec("\nprint(1)") +exec("\rprint(2)") +exec("\r\nprint(3)") +exec("\n5") +exec("\r6") +exec("\r\n7") print(eval("1")) print(eval("12")) print(eval("123")) @@ -19,6 +27,14 @@ print(eval("1\r")) print(eval("12\r")) print(eval("123\r")) +# line continuation +print(eval("'123' \\\r '456'")) +print(eval("'123' \\\n '456'")) +print(eval("'123' \\\r\n '456'")) +print(eval("'123'\\\r'456'")) +print(eval("'123'\\\n'456'")) +print(eval("'123'\\\r\n'456'")) + # backslash used to escape a line-break in a string print('a\ b') diff --git a/tests/basics/list_slice_3arg.py b/tests/basics/list_slice_3arg.py index 8578d5855..a5eda8034 100644 --- a/tests/basics/list_slice_3arg.py +++ b/tests/basics/list_slice_3arg.py @@ -26,3 +26,14 @@ print(x[-1:-1:-1]) print(x[-1:-2:-1]) print(x[-1:-11:-1]) print(x[-10:-11:-1]) +print(x[:-15:-1]) + +# test negative indices that are out-of-bounds +print([][::-1]) +print([1][::-1]) +print([][0:-10:-1]) +print([1][0:-10:-1]) +print([][:-20:-1]) +print([1][:-20:-1]) +print([][-20::-1]) +print([1][-20::-1]) diff --git a/tests/basics/list_slice_assign.py b/tests/basics/list_slice_assign.py index baa9a0081..1ad1ef27c 100644 --- a/tests/basics/list_slice_assign.py +++ b/tests/basics/list_slice_assign.py @@ -34,3 +34,14 @@ print(l) l = list(x) del l[:-3] print(l) + +# assign a tuple +l = [1, 2, 3] +l[0:1] = (10, 11, 12) +print(l) + +# RHS of slice must be an iterable +try: + [][0:1] = 123 +except TypeError: + print('TypeError') diff --git a/tests/basics/list_slice_assign_grow.py b/tests/basics/list_slice_assign_grow.py index 12b1541e3..fa256235f 100644 --- a/tests/basics/list_slice_assign_grow.py +++ b/tests/basics/list_slice_assign_grow.py @@ -26,3 +26,8 @@ print(l) l = list(x) l[100:100] = [10, 20, 30, 40] print(l) + +# growing by using itself on RHS +l = list(range(10)) +l[4:] = l +print(l) diff --git a/tests/basics/map.py b/tests/basics/map.py index 62dca44ed..8fce352c2 100644 --- a/tests/basics/map.py +++ b/tests/basics/map.py @@ -1,4 +1,4 @@ print(list(map(lambda x: x & 1, range(-3, 4)))) print(list(map(abs, range(-3, 4)))) -print(list(map(set, [[i] for i in range(-3, 4)]))) +print(list(map(tuple, [[i] for i in range(-3, 4)]))) print(list(map(pow, range(4), range(4)))) diff --git a/tests/basics/memoryview1.py b/tests/basics/memoryview1.py index 1cd411195..a771acdda 100644 --- a/tests/basics/memoryview1.py +++ b/tests/basics/memoryview1.py @@ -1,4 +1,10 @@ # test memoryview +try: + memoryview +except: + import sys + print("SKIP") + sys.exit() # test reading from bytes b = b'1234' @@ -12,6 +18,10 @@ try: m[0] = 1 except TypeError: print("TypeError") +try: + m[0:2] = b'00' +except TypeError: + print("TypeError") # test writing to bytearray b = bytearray(b) diff --git a/tests/basics/memoryview2.py b/tests/basics/memoryview2.py index 5117d7a68..4b5af852b 100644 --- a/tests/basics/memoryview2.py +++ b/tests/basics/memoryview2.py @@ -1,13 +1,14 @@ # test memoryview accessing maximum values for signed/unsigned elements - -from array import array +try: + from array import array + memoryview +except: + import sys + print("SKIP") + sys.exit() print(list(memoryview(b'\x7f\x80\x81\xff'))) print(list(memoryview(array('b', [0x7f, -0x80])))) print(list(memoryview(array('B', [0x7f, 0x80, 0x81, 0xff])))) print(list(memoryview(array('h', [0x7f00, -0x8000])))) print(list(memoryview(array('H', [0x7f00, 0x8000, 0x8100, 0xffff])))) - -# these constructors give an internal overflow in uPy -#print(list(memoryview(array('i', [0x7f000000, -0x80000000])))) -#print(list(memoryview(array('I', [0x7f000000, 0x80000000, 0x81000000, 0xffffffff])))) diff --git a/tests/basics/memoryview_gc.py b/tests/basics/memoryview_gc.py index a1e4baad4..9d4857e36 100644 --- a/tests/basics/memoryview_gc.py +++ b/tests/basics/memoryview_gc.py @@ -1,4 +1,10 @@ # test memoryview retains pointer to original object/buffer +try: + memoryview +except: + import sys + print("SKIP") + sys.exit() b = bytearray(10) m = memoryview(b)[1:] diff --git a/tests/basics/memoryview_intbig.py b/tests/basics/memoryview_intbig.py new file mode 100644 index 000000000..180f15d18 --- /dev/null +++ b/tests/basics/memoryview_intbig.py @@ -0,0 +1,11 @@ +# test memoryview accessing maximum values for signed/unsigned elements +try: + from array import array + memoryview +except: + import sys + print("SKIP") + sys.exit() + +print(list(memoryview(array('i', [0x7f000000, -0x80000000])))) +print(list(memoryview(array('I', [0x7f000000, 0x80000000, 0x81000000, 0xffffffff])))) diff --git a/tests/basics/namedtuple1.py b/tests/basics/namedtuple1.py index 346e32fbf..132dcf96b 100644 --- a/tests/basics/namedtuple1.py +++ b/tests/basics/namedtuple1.py @@ -1,7 +1,12 @@ try: - from collections import namedtuple + try: + from collections import namedtuple + except ImportError: + from ucollections import namedtuple except ImportError: - from ucollections import namedtuple + import sys + print("SKIP") + sys.exit() T = namedtuple("Tup", ["foo", "bar"]) # CPython prints fully qualified name, what we don't bother to do so far diff --git a/tests/basics/object_new.py b/tests/basics/object_new.py index befb5bfc2..568feccda 100644 --- a/tests/basics/object_new.py +++ b/tests/basics/object_new.py @@ -2,6 +2,14 @@ # (non-initialized) instance of class. # See e.g. http://infohost.nmt.edu/tcc/help/pubs/python/web/new-new-method.html # TODO: Find reference in CPython docs +try: + # If we don't expose object.__new__ (small ports), there's + # nothing to test. + object.__new__ +except AttributeError: + import sys + print("SKIP") + sys.exit() class Foo: diff --git a/tests/basics/op_error.py b/tests/basics/op_error.py index 19ce04bc5..b30b5f0a3 100644 --- a/tests/basics/op_error.py +++ b/tests/basics/op_error.py @@ -20,11 +20,9 @@ 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) diff --git a/tests/basics/op_error_intbig.py b/tests/basics/op_error_intbig.py new file mode 100644 index 000000000..432c05a9f --- /dev/null +++ b/tests/basics/op_error_intbig.py @@ -0,0 +1,13 @@ +# 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") + +# object with buffer protocol needed on rhs +test_exc("(1 << 70) in 1", TypeError) diff --git a/tests/basics/op_error_memoryview.py b/tests/basics/op_error_memoryview.py new file mode 100644 index 000000000..658ededc8 --- /dev/null +++ b/tests/basics/op_error_memoryview.py @@ -0,0 +1,19 @@ +# test errors from bad operations (unary, binary, etc) +try: + memoryview +except: + import sys + print("SKIP") + sys.exit() + +def test_exc(code, exc): + try: + exec(code) + print("no exception") + except exc: + print("right exception") + except: + print("wrong exception") + +# unsupported binary operators +test_exc("m = memoryview(bytearray())\nm += bytearray()", TypeError) diff --git a/tests/basics/ordereddict1.py b/tests/basics/ordereddict1.py index 5e8b2413b..7147968c5 100644 --- a/tests/basics/ordereddict1.py +++ b/tests/basics/ordereddict1.py @@ -9,8 +9,19 @@ except ImportError: sys.exit() d = OrderedDict([(10, 20), ("b", 100), (1, 2)]) +print(len(d)) print(list(d.keys())) print(list(d.values())) del d["b"] +print(len(d)) +print(list(d.keys())) +print(list(d.values())) + +# access remaining elements after deleting +print(d[10], d[1]) + +# add an element after deleting +d["abc"] = 123 +print(len(d)) print(list(d.keys())) print(list(d.values())) diff --git a/tests/basics/python34.py b/tests/basics/python34.py index 7f7a1e015..a23f347d6 100644 --- a/tests/basics/python34.py +++ b/tests/basics/python34.py @@ -1,4 +1,4 @@ -# tests that differ when running under Python 3.4 vs 3.5 +# tests that differ when running under Python 3.4 vs 3.5/3.6 # from basics/fun_kwvarargs.py # test evaluation order of arguments (in 3.4 it's backwards, 3.5 it's fixed) @@ -13,14 +13,15 @@ f4(*print_ret(['a', 'b']), kw_arg=print_ret(None)) {print_ret(1):print_ret(2)} # from basics/syntaxerror.py -# can't have multiple * or ** (in 3.5 we can) def test_syntax(code): try: exec(code) except SyntaxError: print("SyntaxError") -test_syntax("f(*a, *b)") -test_syntax("f(**a, **b)") +test_syntax("f(*a, *b)") # can't have multiple * (in 3.5 we can) +test_syntax("f(**a, **b)") # can't have multiple ** (in 3.5 we can) +test_syntax("() = []") # can't assign to empty tuple (in 3.6 we can) +test_syntax("del ()") # can't delete empty tuple (in 3.6 we can) # from basics/sys1.py # uPy prints version 3.4 diff --git a/tests/basics/python34.py.exp b/tests/basics/python34.py.exp index 637f77ce8..f497df3b8 100644 --- a/tests/basics/python34.py.exp +++ b/tests/basics/python34.py.exp @@ -5,5 +5,7 @@ None 1 SyntaxError SyntaxError +SyntaxError +SyntaxError 3.4 3 4 diff --git a/tests/basics/set_binop.py b/tests/basics/set_binop.py index a3657d84b..7848920b6 100644 --- a/tests/basics/set_binop.py +++ b/tests/basics/set_binop.py @@ -29,6 +29,25 @@ for s in sets: print(set('abc') == 1) +# make sure inplace operators modify the set + +s1 = s2 = set('abc') +s1 |= set('ad') +print(s1 is s2, len(s1)) + +s1 = s2 = set('abc') +s1 ^= set('ad') +print(s1 is s2, len(s1)) + +s1 = s2 = set('abc') +s1 &= set('ad') +print(s1 is s2, len(s1)) + +s1 = s2 = set('abc') +s1 -= set('ad') +print(s1 is s2, len(s1)) + +# unsupported operator try: set('abc') * 2 except TypeError: diff --git a/tests/basics/set_comprehension.py b/tests/basics/set_comprehension.py new file mode 100644 index 000000000..12a9a29d3 --- /dev/null +++ b/tests/basics/set_comprehension.py @@ -0,0 +1 @@ +print({a for a in range(5)}) diff --git a/tests/basics/set_containment.py b/tests/basics/set_containment.py new file mode 100644 index 000000000..97694f74c --- /dev/null +++ b/tests/basics/set_containment.py @@ -0,0 +1,4 @@ +for i in 1, 2: + for o in {}, {1}, {2}: + print("{} in {}: {}".format(i, o, i in o)) + print("{} not in {}: {}".format(i, o, i not in o)) diff --git a/tests/basics/set_iter_of_iter.py b/tests/basics/set_iter_of_iter.py new file mode 100644 index 000000000..e3e91fa45 --- /dev/null +++ b/tests/basics/set_iter_of_iter.py @@ -0,0 +1,2 @@ +i = iter(iter({1, 2, 3})) +print(sorted(i)) diff --git a/tests/basics/slice_bignum.py b/tests/basics/slice_intbig.py index cc820522b..cc820522b 100644 --- a/tests/basics/slice_bignum.py +++ b/tests/basics/slice_intbig.py diff --git a/tests/basics/special_methods.py b/tests/basics/special_methods.py index 1df7a7c4c..9f57247c1 100644 --- a/tests/basics/special_methods.py +++ b/tests/basics/special_methods.py @@ -105,42 +105,4 @@ cud1 > cud2 cud1 + cud2 cud1 - cud2 -# the following require MICROPY_PY_ALL_SPECIAL_METHODS -+cud1 --cud1 -~cud1 -cud1 * cud2 -cud1 / cud2 -cud2 // cud1 -cud1 += cud2 -cud1 -= cud2 - -# TODO: the following operations are not supported on every ports -# -# ne is not supported, !(eq) is called instead -#cud1 != cud2 -# -# binary and is not supported -# cud1 & cud2 -# -# binary lshift is not supported -# cud1<<1 -# -# modulus is not supported -# cud1 % 2 -# -# binary or is not supported -# cud1 | cud2 -# -# pow is not supported -# cud1**2 -# -# rshift is not suported -# cud1>>1 -# -# xor is not supported -# cud1^cud2 -# -# in the followin test, cpython still calls __eq__ -# cud3=cud1 -# cud3==cud1 +# more in special_methods2.py diff --git a/tests/basics/special_methods2.py b/tests/basics/special_methods2.py new file mode 100644 index 000000000..3623b30dc --- /dev/null +++ b/tests/basics/special_methods2.py @@ -0,0 +1,145 @@ +class Cud(): + + def __init__(self): + #print("__init__ called") + pass + + def __repr__(self): + print("__repr__ called") + return "" + + def __lt__(self, other): + print("__lt__ called") + + def __le__(self, other): + print("__le__ called") + + def __eq__(self, other): + print("__eq__ called") + + def __ne__(self, other): + print("__ne__ called") + + def __ge__(self, other): + print("__ge__ called") + + def __gt__(self, other): + print("__gt__ called") + + def __abs__(self): + print("__abs__ called") + + def __add__(self, other): + print("__add__ called") + + def __and__(self, other): + print("__and__ called") + + def __floordiv__(self, other): + print("__floordiv__ called") + + def __index__(self, other): + print("__index__ called") + + def __inv__(self): + print("__inv__ called") + + def __invert__(self): + print("__invert__ called") + + def __lshift__(self, val): + print("__lshift__ called") + + def __mod__(self, val): + print("__mod__ called") + + def __mul__(self, other): + print("__mul__ called") + + def __matmul__(self, other): + print("__matmul__ called") + + def __neg__(self): + print("__neg__ called") + + def __or__(self, other): + print("__or__ called") + + def __pos__(self): + print("__pos__ called") + + def __pow__(self, val): + print("__pow__ called") + + def __rshift__(self, val): + print("__rshift__ called") + + def __sub__(self, other): + print("__sub__ called") + + def __truediv__(self, other): + print("__truediv__ called") + + def __div__(self, other): + print("__div__ called") + + def __xor__(self, other): + print("__xor__ called") + + def __iadd__(self, other): + print("__iadd__ called") + return self + + def __isub__(self, other): + print("__isub__ called") + return self + +cud1 = Cud() +cud2 = Cud() + +try: + +cud1 +except TypeError: + import sys + print("SKIP") + sys.exit() + +# the following require MICROPY_PY_ALL_SPECIAL_METHODS ++cud1 +-cud1 +~cud1 +cud1 * cud2 +cud1 / cud2 +cud2 // cud1 +cud1 += cud2 +cud1 -= cud2 + +# TODO: the following operations are not supported on every ports +# +# ne is not supported, !(eq) is called instead +#cud1 != cud2 +# +# binary and is not supported +# cud1 & cud2 +# +# binary lshift is not supported +# cud1<<1 +# +# modulus is not supported +# cud1 % 2 +# +# binary or is not supported +# cud1 | cud2 +# +# pow is not supported +# cud1**2 +# +# rshift is not suported +# cud1>>1 +# +# xor is not supported +# cud1^cud2 +# +# in the followin test, cpython still calls __eq__ +# cud3=cud1 +# cud3==cud1 diff --git a/tests/basics/string_format2.py b/tests/basics/string_format2.py index e211535be..881ff4f80 100644 --- a/tests/basics/string_format2.py +++ b/tests/basics/string_format2.py @@ -1,6 +1,6 @@ # comprehensive functionality test for {} format string -int_tests = False # these take a while, and some give wrong results +int_tests = False # these take a while char_tests = True str_tests = True diff --git a/tests/basics/string_format_modulo.py b/tests/basics/string_format_modulo.py index 2e4909220..77bbcfbe3 100644 --- a/tests/basics/string_format_modulo.py +++ b/tests/basics/string_format_modulo.py @@ -33,38 +33,11 @@ print("%c" % 48) print("%c" % 'a') print("%10s" % 'abc') print("%-10s" % 'abc') -print("%d" % 10) -print("%+d" % 10) -print("% d" % 10) -print("%d" % -10) -print("%d" % True) -print("%i" % -10) -print("%i" % True) -print("%u" % -10) -print("%u" % True) -print("%x" % 18) -print("%o" % 18) -print("%X" % 18) -print("%#x" % 18) -print("%#X" % 18) -print("%#6o" % 18) -print("%#6x" % 18) -print("%#06x" % 18) - -print("%*d" % (5, 10)) -print("%*.*d" % (2, 2, 20)) -print("%*.*d" % (5, 8, 20)) - -print(">%8.4d<" % -12) -print(">% 8.4d<" % -12) -print(">%+8.4d<" % 12) -print(">%+8.4d<" % -12) -print(">%08.4d<" % -12) -print(">%08.4d<" % 12) -print(">%-8.4d<" % -12) -print(">%-08.4d<" % -12) -print(">%-+08.4d<" % -12) -print(">%-+08.4d<" % 12) + +# Should be able to print dicts; in this case they aren't used +# to lookup keywords in formats like %(foo)s +print('%s' % {}) +print('%s' % ({},)) # Cases when "*" used and there's not enough values total try: @@ -77,6 +50,7 @@ except TypeError: print("TypeError") print("%(foo)s" % {"foo": "bar", "baz": False}) +print("%s %(foo)s %(foo)s" % {"foo": 1}) try: print("%(foo)s" % {}) except KeyError: @@ -87,6 +61,16 @@ try: except TypeError: print("TypeError") +# When using %(foo)s format the single argument must be a dict +try: + '%(foo)s' % 1 +except TypeError: + print('TypeError') +try: + '%(foo)s' % ({},) +except TypeError: + print('TypeError') + try: '%(a' % {'a':1} except ValueError: diff --git a/tests/basics/string_format_modulo_int.py b/tests/basics/string_format_modulo_int.py new file mode 100644 index 000000000..d1f29db22 --- /dev/null +++ b/tests/basics/string_format_modulo_int.py @@ -0,0 +1,41 @@ +# test string modulo formatting with int values + +# basic cases +print("%d" % 10) +print("%+d" % 10) +print("% d" % 10) +print("%d" % -10) +print("%d" % True) +print("%i" % -10) +print("%i" % True) +print("%u" % -10) +print("%u" % True) +print("%x" % 18) +print("%o" % 18) +print("%X" % 18) +print("%#x" % 18) +print("%#X" % 18) +print("%#6o" % 18) +print("%#6x" % 18) +print("%#06x" % 18) + +# with * +print("%*d" % (5, 10)) +print("%*.*d" % (2, 2, 20)) +print("%*.*d" % (5, 8, 20)) + +# precision +for val in (-12, 12): + print(">%8.4d<" % val) + print(">% 8.4d<" % val) + print(">%+8.4d<" % val) + print(">%08.4d<" % val) + print(">%-8.4d<" % val) + print(">%-08.4d<" % val) + print(">%-+08.4d<" % val) + +# test + option with various amount of padding +for pad in ('', ' ', '0'): + for n in (1, 2, 3): + for val in (-1, 0, 1): + print(('%+' + pad + str(n) + 'd') % val) diff --git a/tests/basics/string_join.py b/tests/basics/string_join.py index b8694c01e..82f1b799a 100644 --- a/tests/basics/string_join.py +++ b/tests/basics/string_join.py @@ -14,6 +14,11 @@ print(','.join('abc' for i in range(5))) print(b','.join([b'abc', b'123'])) try: + ''.join(None) +except TypeError: + print("TypeError") + +try: print(b','.join(['abc', b'123'])) except TypeError: print("TypeError") @@ -25,3 +30,13 @@ except TypeError: # joined by the compiler print("a" "b") +print("a" '''b''') +print("a" # inline comment + "b") +print("a" \ + "b") + +# the following should not be joined by the compiler +x = 'a' +'b' +print(x) diff --git a/tests/basics/struct1.py b/tests/basics/struct1.py index d89519a2f..bb6877c78 100644 --- a/tests/basics/struct1.py +++ b/tests/basics/struct1.py @@ -37,34 +37,6 @@ s = struct.pack("BHBI", 10, 100, 200, 300) v = struct.unpack("BHBI", s) print(v == (10, 100, 200, 300)) -# check maximum pack on 32-bit machine -print(struct.pack("<I", 2**32 - 1)) -print(struct.pack("<I", 0xffffffff)) - -# long long ints -print(struct.pack("<Q", 2**64 - 1)) -print(struct.pack(">Q", 2**64 - 1)) -print(struct.pack("<Q", 0xffffffffffffffff)) -print(struct.pack(">Q", 0xffffffffffffffff)) -print(struct.pack("<q", -1)) -print(struct.pack(">q", -1)) -print(struct.pack("<Q", 1234567890123456789)) -print(struct.pack("<q", -1234567890123456789)) -print(struct.pack(">Q", 1234567890123456789)) -print(struct.pack(">q", -1234567890123456789)) -print(struct.unpack("<Q", b"\x12\x34\x56\x78\x90\x12\x34\x56")) -print(struct.unpack(">Q", b"\x12\x34\x56\x78\x90\x12\x34\x56")) -print(struct.unpack("<q", b"\x12\x34\x56\x78\x90\x12\x34\xf6")) -print(struct.unpack(">q", b"\xf2\x34\x56\x78\x90\x12\x34\x56")) - -# check maximum unpack -print(struct.unpack("<I", b"\xff\xff\xff\xff")) -print(struct.unpack("<Q", b"\xff\xff\xff\xff\xff\xff\xff\xff")) - -# check small int overflow -print(struct.unpack("<i", b'\xff\xff\xff\x7f')) -print(struct.unpack("<q", b'\xff\xff\xff\xff\xff\xff\xff\x7f')) - # network byte order print(struct.pack('!i', 123)) diff --git a/tests/basics/struct1_intbig.py b/tests/basics/struct1_intbig.py new file mode 100644 index 000000000..7f4c3ce12 --- /dev/null +++ b/tests/basics/struct1_intbig.py @@ -0,0 +1,37 @@ +try: + import ustruct as struct +except: + try: + import struct + except ImportError: + import sys + print("SKIP") + sys.exit() + +# check maximum pack on 32-bit machine +print(struct.pack("<I", 2**32 - 1)) +print(struct.pack("<I", 0xffffffff)) + +# long long ints +print(struct.pack("<Q", 2**64 - 1)) +print(struct.pack(">Q", 2**64 - 1)) +print(struct.pack("<Q", 0xffffffffffffffff)) +print(struct.pack(">Q", 0xffffffffffffffff)) +print(struct.pack("<q", -1)) +print(struct.pack(">q", -1)) +print(struct.pack("<Q", 1234567890123456789)) +print(struct.pack("<q", -1234567890123456789)) +print(struct.pack(">Q", 1234567890123456789)) +print(struct.pack(">q", -1234567890123456789)) +print(struct.unpack("<Q", b"\x12\x34\x56\x78\x90\x12\x34\x56")) +print(struct.unpack(">Q", b"\x12\x34\x56\x78\x90\x12\x34\x56")) +print(struct.unpack("<q", b"\x12\x34\x56\x78\x90\x12\x34\xf6")) +print(struct.unpack(">q", b"\xf2\x34\x56\x78\x90\x12\x34\x56")) + +# check maximum unpack +print(struct.unpack("<I", b"\xff\xff\xff\xff")) +print(struct.unpack("<Q", b"\xff\xff\xff\xff\xff\xff\xff\xff")) + +# check small int overflow +print(struct.unpack("<i", b'\xff\xff\xff\x7f')) +print(struct.unpack("<q", b'\xff\xff\xff\xff\xff\xff\xff\x7f')) diff --git a/tests/basics/struct2.py b/tests/basics/struct2.py index 6dd963260..e3f8bbebf 100644 --- a/tests/basics/struct2.py +++ b/tests/basics/struct2.py @@ -26,7 +26,17 @@ print(struct.calcsize('0s1s0H2H')) print(struct.unpack('<0s1s0H2H', b'01234')) print(struct.pack('<0s1s0H2H', b'abc', b'abc', 258, 515)) -# check that zero of an unknown type raises an exception +# check that unknown types raise an exception +try: + struct.unpack('z', b'1') +except: + print('Exception') + +try: + struct.pack('z', (b'1',)) +except: + print('Exception') + try: struct.calcsize('0z') except: diff --git a/tests/basics/struct_micropython.py b/tests/basics/struct_micropython.py index e3b0ea508..53306dad6 100644 --- a/tests/basics/struct_micropython.py +++ b/tests/basics/struct_micropython.py @@ -18,3 +18,16 @@ o = A() s = struct.pack("<O", o) o2 = struct.unpack("<O", s) print(o is o2[0]) + +# pack and unpack pointer to a string +# This requires uctypes to get the address of the string and instead of +# putting this in a dedicated test that can be skipped we simply pass +# if the import fails. +try: + import uctypes + o = uctypes.addressof('abc') + s = struct.pack("<S", o) + o2 = struct.unpack("<S", s) + assert o2[0] == 'abc' +except ImportError: + pass diff --git a/tests/basics/subclass_classmethod.py b/tests/basics/subclass_classmethod.py index ae5fbd1aa..48f164b36 100644 --- a/tests/basics/subclass_classmethod.py +++ b/tests/basics/subclass_classmethod.py @@ -5,6 +5,13 @@ class Base: def foo(cls): print(cls.__name__) +try: + Base.__name__ +except AttributeError: + import sys + print("SKIP") + sys.exit() + class Sub(Base): pass diff --git a/tests/basics/syntaxerror.py b/tests/basics/syntaxerror.py index e5cbbac06..4161de017 100644 --- a/tests/basics/syntaxerror.py +++ b/tests/basics/syntaxerror.py @@ -46,9 +46,6 @@ 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 *x on RHS test_syntax("x = *x") @@ -66,7 +63,6 @@ test_syntax("[a, b] += c") 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)") diff --git a/tests/basics/sys1.py b/tests/basics/sys1.py index 816c8823a..29ef974d1 100644 --- a/tests/basics/sys1.py +++ b/tests/basics/sys1.py @@ -6,8 +6,18 @@ print(sys.__name__) print(type(sys.path)) print(type(sys.argv)) print(sys.byteorder in ('little', 'big')) -print(sys.maxsize > 100) -print(sys.implementation.name in ('cpython', 'micropython')) + +try: + print(sys.maxsize > 100) +except AttributeError: + # Effectively skip subtests + print(True) + +try: + print(sys.implementation.name in ('cpython', 'micropython')) +except AttributeError: + # Effectively skip subtests + print(True) try: sys.exit() diff --git a/tests/basics/try_finally_loops.py b/tests/basics/try_finally_loops.py index 06a6b4a0c..a4b80196f 100644 --- a/tests/basics/try_finally_loops.py +++ b/tests/basics/try_finally_loops.py @@ -41,3 +41,28 @@ for i in [1]: break finally: print('finally 4') + +# Test unwind-jump where there is nothing in the body of the try or finally. +# This checks that the bytecode emitter allocates enough stack for the unwind. +for i in [1]: + try: + break + finally: + pass + +# The following test checks that the globals dict is valid after a call to a +# function that has an unwind jump. +# There was a bug where an unwind jump would trash the globals dict upon return +# from a function, because it used the Python-stack incorrectly. +def f(): + for i in [1]: + try: + break + finally: + pass +def g(): + global global_var + f() + print(global_var) +global_var = 'global' +g() diff --git a/tests/basics/tuple1.py b/tests/basics/tuple1.py index 2993391d5..a7956c107 100644 --- a/tests/basics/tuple1.py +++ b/tests/basics/tuple1.py @@ -17,6 +17,10 @@ print(x[2:3]) print(x + (10, 100, 10000)) +# inplace add operator +x += (10, 11, 12) +print(x) + # construction of tuple from large iterator (tests implementation detail of uPy) print(tuple(range(20))) diff --git a/tests/basics/unpack1.py b/tests/basics/unpack1.py index 0e8ec592c..1e8b53aa1 100644 --- a/tests/basics/unpack1.py +++ b/tests/basics/unpack1.py @@ -41,7 +41,7 @@ a, *b, c = 24, 25, 26, 27 ; print(a, b) a = [28, 29] *b, = a -print(a, b, a == b) +print(a, b, a == b, a is b) [*a] = [1, 2, 3] print(a) diff --git a/tests/basics/zip.py b/tests/basics/zip.py index c0109094f..958addb7a 100644 --- a/tests/basics/zip.py +++ b/tests/basics/zip.py @@ -1,2 +1,10 @@ +try: + zip + set +except NameError: + print("SKIP") + import sys + sys.exit() + print(list(zip())) -print(list(zip([1], {2,3}))) +print(list(zip([1], set([2, 3])))) diff --git a/tests/cmdline/cmd_parsetree.py.exp b/tests/cmdline/cmd_parsetree.py.exp index 06fbeadfc..d9f81d8d4 100644 --- a/tests/cmdline/cmd_parsetree.py.exp +++ b/tests/cmdline/cmd_parsetree.py.exp @@ -1,28 +1,28 @@ ---------------- -[ 4] rule(2) (n=8) - tok(5) -[ 4] rule(78) (n=4) +[ 4] rule(1) (n=8) + tok(4) +[ 4] rule(22) (n=4) id(i) -[ 4] rule(131) (n=1) +[ 4] rule(44) (n=1) NULL -[ 5] rule(42) (n=0) +[ 5] rule(8) (n=0) NULL -[ 6] rule(32) (n=2) +[ 6] rule(5) (n=2) id(a) - tok(15) -[ 7] rule(32) (n=2) + tok(14) +[ 7] rule(5) (n=2) id(b) str(str) -[ 8] rule(32) (n=2) +[ 8] rule(5) (n=2) id(c) -[ 8] literal str(a very long str that will not be interned) -[ 9] rule(32) (n=2) +[ 8] literal \.\+ +[ 9] rule(5) (n=2) id(d) bytes(bytes) -[ 10] rule(32) (n=2) +[ 10] rule(5) (n=2) id(e) -[ 10] literal bytes(a very long bytes that will not be interned) -[ 11] rule(32) (n=2) +[ 10] literal \.\+ +[ 11] rule(5) (n=2) id(f) [ 11] literal \.\+ ---------------- @@ -31,7 +31,7 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): ######## \.\+5b arg names: -(N_STATE 2) +(N_STATE 5) (N_EXC_STACK 0) bc=-1 line=1 bc=0 line=4 @@ -43,7 +43,7 @@ arg names: bc=32 line=10 bc=37 line=11 00 BUILD_TUPLE 0 -02 GET_ITER +02 GET_ITER_STACK 03 FOR_ITER 12 06 STORE_NAME i 09 JUMP 3 diff --git a/tests/cmdline/cmd_showbc.py b/tests/cmdline/cmd_showbc.py index 2f4e953bb..6e99fc418 100644 --- a/tests/cmdline/cmd_showbc.py +++ b/tests/cmdline/cmd_showbc.py @@ -150,3 +150,7 @@ class Class: # delete name del Class + +# load super method +def f(self): + super().f() diff --git a/tests/cmdline/cmd_showbc.py.exp b/tests/cmdline/cmd_showbc.py.exp index 1f0c054cf..1e015eb03 100644 --- a/tests/cmdline/cmd_showbc.py.exp +++ b/tests/cmdline/cmd_showbc.py.exp @@ -7,7 +7,7 @@ arg names: (N_EXC_STACK 0) bc=-1 line=1 ######## - bc=\\d\+ line=152 + bc=\\d\+ line=155 00 MAKE_FUNCTION \.\+ \\d\+ STORE_NAME f \\d\+ MAKE_FUNCTION \.\+ @@ -25,6 +25,8 @@ arg names: \\d\+ CALL_FUNCTION n=2 nkw=0 \\d\+ STORE_NAME Class \\d\+ DELETE_NAME Class +\\d\+ MAKE_FUNCTION \.\+ +\\d\+ STORE_NAME f \\d\+ LOAD_CONST_NONE \\d\+ RETURN_VALUE File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ bytes) @@ -175,14 +177,12 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): \\d\+ LOAD_FAST 15 \\d\+ MAKE_CLOSURE \.\+ 2 \\d\+ LOAD_FAST 2 -\\d\+ GET_ITER \\d\+ CALL_FUNCTION n=1 nkw=0 \\d\+ STORE_FAST 0 \\d\+ LOAD_FAST 14 \\d\+ LOAD_FAST 15 \\d\+ MAKE_CLOSURE \.\+ 2 \\d\+ LOAD_FAST 2 -\\d\+ GET_ITER \\d\+ CALL_FUNCTION n=1 nkw=0 \\d\+ STORE_FAST 0 \\d\+ LOAD_FAST 0 @@ -245,7 +245,7 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): \\d\+ LOAD_FAST 0 \\d\+ STORE_FAST 0 \\d\+ LOAD_DEREF 14 -\\d\+ GET_ITER +\\d\+ GET_ITER_STACK \\d\+ FOR_ITER \\d\+ \\d\+ STORE_FAST 0 \\d\+ LOAD_FAST 1 @@ -430,63 +430,85 @@ arg names: 10 STORE_NAME __qualname__ 13 LOAD_CONST_NONE 14 RETURN_VALUE +File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ bytes) +Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): +######## +\.\+5b +arg names: self +(N_STATE 4) +(N_EXC_STACK 0) + bc=-1 line=1 + bc=0 line=156 +00 LOAD_GLOBAL super (cache=0) +\\d\+ LOAD_GLOBAL __class__ (cache=0) +\\d\+ LOAD_FAST 0 +\\d\+ LOAD_SUPER_METHOD f +\\d\+ CALL_METHOD n=0 nkw=0 +\\d\+ POP_TOP +\\d\+ LOAD_CONST_NONE +\\d\+ RETURN_VALUE File cmdline/cmd_showbc.py, code block '<genexpr>' (descriptor: \.\+, bytecode @\.\+ bytes) Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): ######## \.\+5b arg names: * * * -(N_STATE 6) +(N_STATE 9) (N_EXC_STACK 0) bc=-\\d\+ line=1 -00 LOAD_FAST 2 -01 FOR_ITER 17 -04 STORE_FAST 3 -05 LOAD_DEREF 1 -07 POP_JUMP_IF_FALSE 1 -10 LOAD_DEREF 0 -12 YIELD_VALUE -13 POP_TOP -14 JUMP 1 -17 LOAD_CONST_NONE -18 RETURN_VALUE +00 LOAD_NULL +01 LOAD_FAST 2 +02 LOAD_NULL +03 LOAD_NULL +04 FOR_ITER 20 +07 STORE_FAST 3 +08 LOAD_DEREF 1 +10 POP_JUMP_IF_FALSE 4 +13 LOAD_DEREF 0 +15 YIELD_VALUE +16 POP_TOP +17 JUMP 4 +20 LOAD_CONST_NONE +21 RETURN_VALUE File cmdline/cmd_showbc.py, code block '<listcomp>' (descriptor: \.\+, bytecode @\.\+ bytes) Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): ######## \.\+5b arg names: * * * -(N_STATE 7) +(N_STATE 10) (N_EXC_STACK 0) bc=-\\d\+ line=1 00 BUILD_LIST 0 02 LOAD_FAST 2 -03 FOR_ITER 19 -06 STORE_FAST 3 -07 LOAD_DEREF 1 -09 POP_JUMP_IF_FALSE 3 -12 LOAD_DEREF 0 -14 STORE_COMP 8 -16 JUMP 3 -19 RETURN_VALUE +03 GET_ITER_STACK +04 FOR_ITER 20 +07 STORE_FAST 3 +08 LOAD_DEREF 1 +10 POP_JUMP_IF_FALSE 4 +13 LOAD_DEREF 0 +15 STORE_COMP 20 +17 JUMP 4 +20 RETURN_VALUE File cmdline/cmd_showbc.py, code block '<dictcomp>' (descriptor: \.\+, bytecode @\.\+ bytes) Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): ######## \.\+5b arg names: * * * -(N_STATE 8) +(N_STATE 11) (N_EXC_STACK 0) bc=-\\d\+ line=1 ######## 00 BUILD_MAP 0 02 LOAD_FAST 2 -03 FOR_ITER 21 -06 STORE_FAST 3 -07 LOAD_DEREF 1 -09 POP_JUMP_IF_FALSE 3 -12 LOAD_DEREF 0 -14 LOAD_DEREF 0 -16 STORE_COMP 13 -18 JUMP 3 -21 RETURN_VALUE +03 GET_ITER_STACK +04 FOR_ITER 22 +07 STORE_FAST 3 +08 LOAD_DEREF 1 +10 POP_JUMP_IF_FALSE 4 +13 LOAD_DEREF 0 +15 LOAD_DEREF 0 +17 STORE_COMP 25 +19 JUMP 4 +22 RETURN_VALUE File cmdline/cmd_showbc.py, code block 'closure' (descriptor: \.\+, bytecode @\.\+ bytes) Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): ######## diff --git a/tests/cpydiff/core_arguments.py b/tests/cpydiff/core_arguments.py new file mode 100644 index 000000000..4734a8062 --- /dev/null +++ b/tests/cpydiff/core_arguments.py @@ -0,0 +1,10 @@ +""" +categories: Core +description: Error messages for methods may display unexpected argument counts +cause: MicroPython counts "self" as an argument. +workaround: Interpret error messages with the information above in mind. +""" +try: + [].append() +except Exception as e: + print(e) diff --git a/tests/cpydiff/core_class_delnotimpl.py b/tests/cpydiff/core_class_delnotimpl.py new file mode 100644 index 000000000..c51c3d536 --- /dev/null +++ b/tests/cpydiff/core_class_delnotimpl.py @@ -0,0 +1,16 @@ +""" +categories: Core,Classes +description: Special method __del__ not implemented for user-defined classes +cause: Unknown +workaround: Unknown +""" +import gc + +class Foo(): + def __del__(self): + print('__del__') + +f = Foo() +del f + +gc.collect() diff --git a/tests/cpydiff/core_class_supermultiple.py b/tests/cpydiff/core_class_supermultiple.py new file mode 100644 index 000000000..adf4a17a8 --- /dev/null +++ b/tests/cpydiff/core_class_supermultiple.py @@ -0,0 +1,27 @@ +""" +categories: Core,Classes +description: When inheriting from multiple classes super() only calls one class +cause: Depth first non-exhaustive method resolution order +workaround: Unknown +""" +class A: + def __init__(self): + print("A.__init__") + +class B(A): + def __init__(self): + print("B.__init__") + super().__init__() + +class C(A): + def __init__(self): + print("C.__init__") + super().__init__() + + +class D(B,C): + def __init__(self): + print("D.__init__") + super().__init__() + +D() diff --git a/tests/cpydiff/core_class_superproperty.py b/tests/cpydiff/core_class_superproperty.py new file mode 100644 index 000000000..1ec210550 --- /dev/null +++ b/tests/cpydiff/core_class_superproperty.py @@ -0,0 +1,18 @@ +""" +categories: Core,Classes +description: Calling super() getter property in subclass will return a property object, not the value +cause: Unknown +workaround: Unknown +""" +class A: + @property + def p(self): + return {"a":10} + +class AA(A): + @property + def p(self): + return super().p + +a = AA() +print(a.p) diff --git a/tests/cpydiff/core_function_unpacking.py b/tests/cpydiff/core_function_unpacking.py new file mode 100644 index 000000000..01d25ee4d --- /dev/null +++ b/tests/cpydiff/core_function_unpacking.py @@ -0,0 +1,7 @@ +""" +categories: Core,Functions +description: Unpacking function arguments in non-last position isn't detected as an error +cause: Unknown +workaround: The syntax below is invalid, never use it in applications. +""" +print(*(1, 2), 3) diff --git a/tests/cpydiff/core_function_userattr.py b/tests/cpydiff/core_function_userattr.py new file mode 100644 index 000000000..297293908 --- /dev/null +++ b/tests/cpydiff/core_function_userattr.py @@ -0,0 +1,11 @@ +""" +categories: Core,Functions +description: User-defined attributes for functions are not supported +cause: MicroPython is highly optimized for memory usage. +workaround: Use external dictionary, e.g. ``FUNC_X[f] = 0``. +""" +def f(): + pass + +f.x = 0 +print(f.x) diff --git a/tests/cpydiff/core_generator_noexit.py b/tests/cpydiff/core_generator_noexit.py new file mode 100644 index 000000000..c25fbe75a --- /dev/null +++ b/tests/cpydiff/core_generator_noexit.py @@ -0,0 +1,24 @@ +""" +categories: Core,Generator +description: Context manager __exit__() not called in a generator which does not run to completion +cause: Unknown +workaround: Unknown +""" +class foo(object): + def __enter__(self): + print('Enter') + def __exit__(self, *args): + print('Exit') + +def bar(x): + with foo(): + while True: + x += 1 + yield x + +def func(): + g = bar(0) + for _ in range(3): + print(next(g)) + +func() diff --git a/tests/cpydiff/core_import_path.py b/tests/cpydiff/core_import_path.py new file mode 100644 index 000000000..04fc4bd5b --- /dev/null +++ b/tests/cpydiff/core_import_path.py @@ -0,0 +1,9 @@ +""" +categories: Core,import +description: __path__ attribute of a package has a different type (single string instead of list of strings) in MicroPython +cause: MicroPython does't support namespace packages split across filesystem. Beyond that, MicroPython's import system is highly optimized for minimal memory usage. +workaround: Details of import handling is inherently implementation dependent. Don't rely on such details in portable applications. +""" +import modules + +print(modules.__path__) diff --git a/tests/cpydiff/core_import_prereg.py b/tests/cpydiff/core_import_prereg.py new file mode 100644 index 000000000..4a7121782 --- /dev/null +++ b/tests/cpydiff/core_import_prereg.py @@ -0,0 +1,17 @@ +""" +categories: Core,import +description: Failed to load modules are still registered as loaded +cause: To make module handling more efficient, it's not wrapped with exception handling. +workaround: Test modules before production use; during development, use ``del sys.modules["name"]``, or just soft or hard reset the board. +""" +import sys + +try: + from modules import foo +except NameError as e: + print(e) +try: + from modules import foo + print('Should not get here') +except NameError as e: + print(e) diff --git a/tests/cpydiff/core_import_split_ns_pkgs.py b/tests/cpydiff/core_import_split_ns_pkgs.py new file mode 100644 index 000000000..700620c47 --- /dev/null +++ b/tests/cpydiff/core_import_split_ns_pkgs.py @@ -0,0 +1,14 @@ +""" +categories: Core,import +description: MicroPython does't support namespace packages split across filesystem. +cause: MicroPython's import system is highly optimized for simplicity, minimal memory usage, and minimal filesystem search overhead. +workaround: Don't install modules belonging to the same namespace package in different directories. For MicroPython, it's recommended to have at most 3-component module search paths: for your current application, per-user (writable), system-wide (non-writable). +""" +import sys +sys.path.append(sys.path[1] + "/modules") +sys.path.append(sys.path[1] + "/modules2") + +import subpkg.foo +import subpkg.bar + +print("Two modules of a split namespace package imported") diff --git a/tests/cpydiff/core_mro.py b/tests/cpydiff/core_mro.py new file mode 100644 index 000000000..35b898b30 --- /dev/null +++ b/tests/cpydiff/core_mro.py @@ -0,0 +1,15 @@ +""" +categories: Core +description: Method Resolution Order (MRO) is not compliant with CPython +cause: Unknown +workaround: Unknown +""" +class Foo: + def __str__(self): + return "Foo" + +class C(tuple, Foo): + pass + +t = C((1, 2, 3)) +print(t) diff --git a/tests/cpydiff/modules/__init__.py b/tests/cpydiff/modules/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/cpydiff/modules/__init__.py diff --git a/tests/cpydiff/modules/foo.py b/tests/cpydiff/modules/foo.py new file mode 100644 index 000000000..e6e33a7b4 --- /dev/null +++ b/tests/cpydiff/modules/foo.py @@ -0,0 +1,2 @@ +print('foo') +xxx diff --git a/tests/cpydiff/modules/subpkg/foo.py b/tests/cpydiff/modules/subpkg/foo.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/cpydiff/modules/subpkg/foo.py diff --git a/tests/cpydiff/modules2/subpkg/bar.py b/tests/cpydiff/modules2/subpkg/bar.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/cpydiff/modules2/subpkg/bar.py diff --git a/tests/cpydiff/modules_array_containment.py b/tests/cpydiff/modules_array_containment.py new file mode 100644 index 000000000..190a3c276 --- /dev/null +++ b/tests/cpydiff/modules_array_containment.py @@ -0,0 +1,8 @@ +""" +categories: Modules,array +description: Looking for integer not implemented +cause: Unknown +workaround: Unknown +""" +import array +print(1 in array.array('B', b'12')) diff --git a/tests/cpydiff/modules_array_deletion.py b/tests/cpydiff/modules_array_deletion.py new file mode 100644 index 000000000..97f988da2 --- /dev/null +++ b/tests/cpydiff/modules_array_deletion.py @@ -0,0 +1,10 @@ +""" +categories: Modules,array +description: Array deletion not implemented +cause: Unknown +workaround: Unknown +""" +import array +a = array.array('b', (1, 2, 3)) +del a[1] +print(a) diff --git a/tests/cpydiff/modules_array_subscrstep.py b/tests/cpydiff/modules_array_subscrstep.py new file mode 100644 index 000000000..1103f1826 --- /dev/null +++ b/tests/cpydiff/modules_array_subscrstep.py @@ -0,0 +1,9 @@ +""" +categories: Modules,array +description: Subscript with step != 1 is not yet implemented +cause: Unknown +workaround: Unknown +""" +import array +a = array.array('b', (1, 2, 3)) +print(a[3:2:2]) diff --git a/tests/cpydiff/modules_deque.py b/tests/cpydiff/modules_deque.py new file mode 100644 index 000000000..dc9369d02 --- /dev/null +++ b/tests/cpydiff/modules_deque.py @@ -0,0 +1,9 @@ +""" +categories: Modules,deque +description: Deque not implemented +cause: Unknown +workaround: Use regular queues or lists creatively +""" +import collections +D = collections.deque() +print(D) diff --git a/tests/cpydiff/modules_json_nonserializable.py b/tests/cpydiff/modules_json_nonserializable.py new file mode 100644 index 000000000..913b734e8 --- /dev/null +++ b/tests/cpydiff/modules_json_nonserializable.py @@ -0,0 +1,14 @@ +""" +categories: Modules,json +description: JSON module does not throw exception when object is not serialisable +cause: Unknown +workaround: Unknown +""" +import json +a = bytes(x for x in range(256)) +try: + z = json.dumps(a) + x = json.loads(z) + print('Should not get here') +except TypeError: + print('TypeError') diff --git a/tests/cpydiff/modules_struct_fewargs.py b/tests/cpydiff/modules_struct_fewargs.py new file mode 100644 index 000000000..08d32ca67 --- /dev/null +++ b/tests/cpydiff/modules_struct_fewargs.py @@ -0,0 +1,12 @@ +""" +categories: Modules,struct +description: Struct pack with too few args, not checked by uPy +cause: Unknown +workaround: Unknown +""" +import struct +try: + print(struct.pack('bb', 1)) + print('Should not get here') +except: + print('struct.error') diff --git a/tests/cpydiff/modules_struct_manyargs.py b/tests/cpydiff/modules_struct_manyargs.py new file mode 100644 index 000000000..cdbb5c672 --- /dev/null +++ b/tests/cpydiff/modules_struct_manyargs.py @@ -0,0 +1,12 @@ +""" +categories: Modules,struct +description: Struct pack with too many args, not checked by uPy +cause: Unknown +workaround: Unknown +""" +import struct +try: + print(struct.pack('bb', 1, 2, 3)) + print('Should not get here') +except: + print('struct.error') diff --git a/tests/cpydiff/modules_sys_stdassign.py b/tests/cpydiff/modules_sys_stdassign.py new file mode 100644 index 000000000..096af430e --- /dev/null +++ b/tests/cpydiff/modules_sys_stdassign.py @@ -0,0 +1,9 @@ +""" +categories: Modules,sys +description: Override sys.stdin, sys.stdout and sys.stderr. Impossible as they are stored in read-only memory. +cause: Unknown +workaround: Unknown +""" +import sys +sys.stdin = None +print(sys.stdin) diff --git a/tests/cpydiff/syntax_spaces.py b/tests/cpydiff/syntax_spaces.py new file mode 100644 index 000000000..8578a51e2 --- /dev/null +++ b/tests/cpydiff/syntax_spaces.py @@ -0,0 +1,18 @@ +""" +categories: Syntax,Spaces +description: uPy requires spaces between literal numbers and keywords, CPy doesn't +cause: Unknown +workaround: Unknown +""" +try: + print(eval('1and 0')) +except SyntaxError: + print('Should have worked') +try: + print(eval('1or 0')) +except SyntaxError: + print('Should have worked') +try: + print(eval('1if 1else 0')) +except SyntaxError: + print('Should have worked') diff --git a/tests/cpydiff/syntax_unicode_nameesc.py b/tests/cpydiff/syntax_unicode_nameesc.py new file mode 100644 index 000000000..21628c974 --- /dev/null +++ b/tests/cpydiff/syntax_unicode_nameesc.py @@ -0,0 +1,7 @@ +""" +categories: Syntax,Unicode +description: Unicode name escapes are not implemented +cause: Unknown +workaround: Unknown +""" +print("\N{LATIN SMALL LETTER A}") diff --git a/tests/cpydiff/types_bytearray_sliceassign.py b/tests/cpydiff/types_bytearray_sliceassign.py new file mode 100644 index 000000000..e4068b04b --- /dev/null +++ b/tests/cpydiff/types_bytearray_sliceassign.py @@ -0,0 +1,9 @@ +""" +categories: Types,bytearray +description: Array slice assignment with unsupported RHS +cause: Unknown +workaround: Unknown +""" +b = bytearray(4) +b[0:1] = [1, 2] +print(b) diff --git a/tests/cpydiff/types_bytes_keywords.py b/tests/cpydiff/types_bytes_keywords.py new file mode 100644 index 000000000..35119e28f --- /dev/null +++ b/tests/cpydiff/types_bytes_keywords.py @@ -0,0 +1,7 @@ +""" +categories: Types,bytes +description: bytes(...) with keywords not implemented +cause: Unknown +workaround: Input the encoding format directly. eg. ``print(bytes('abc', 'utf-8'))`` +""" +print(bytes('abc', encoding='utf8')) diff --git a/tests/cpydiff/types_bytes_subscrstep.py b/tests/cpydiff/types_bytes_subscrstep.py new file mode 100644 index 000000000..fd1602d65 --- /dev/null +++ b/tests/cpydiff/types_bytes_subscrstep.py @@ -0,0 +1,7 @@ +""" +categories: Types,bytes +description: Bytes subscr with step != 1 not implemented +cause: Unknown +workaround: Unknown +""" +print(b'123'[0:3:2]) diff --git a/tests/cpydiff/types_exception_chaining.py b/tests/cpydiff/types_exception_chaining.py new file mode 100644 index 000000000..836c4eb3e --- /dev/null +++ b/tests/cpydiff/types_exception_chaining.py @@ -0,0 +1,10 @@ +""" +categories: Types,Exception +description: Exception chaining not implemented +cause: Unknown +workaround: Unknown +""" +try: + raise TypeError +except TypeError: + raise ValueError diff --git a/tests/cpydiff/types_exception_instancevar.py b/tests/cpydiff/types_exception_instancevar.py new file mode 100644 index 000000000..d1015e96c --- /dev/null +++ b/tests/cpydiff/types_exception_instancevar.py @@ -0,0 +1,9 @@ +""" +categories: Types,Exception +description: Assign instance variable to exception +cause: Unknown +workaround: Unknown +""" +e = Exception() +e.x = 0 +print(e.x) diff --git a/tests/cpydiff/types_exception_loops.py b/tests/cpydiff/types_exception_loops.py new file mode 100644 index 000000000..a142e4757 --- /dev/null +++ b/tests/cpydiff/types_exception_loops.py @@ -0,0 +1,12 @@ +""" +categories: Types,Exception +description: While loop guards will obscure exception line number reporting due to being optimised onto the end of the code block +cause: Unknown +workaround: Unknown +""" +l = ["-foo", "-bar"] + +i = 0 +while l[i][0] == "-": + print("iter") + i += 1 diff --git a/tests/cpydiff/types_exception_subclassinit.py b/tests/cpydiff/types_exception_subclassinit.py new file mode 100644 index 000000000..177094646 --- /dev/null +++ b/tests/cpydiff/types_exception_subclassinit.py @@ -0,0 +1,11 @@ +""" +categories: Types,Exception +description: Exception.__init__ raises TypeError if overridden and called by subclass +cause: Unknown +workaround: Unknown +""" +class A(Exception): + def __init__(self): + Exception.__init__(self) + +a = A() diff --git a/tests/cpydiff/types_float_rounding.py b/tests/cpydiff/types_float_rounding.py new file mode 100644 index 000000000..647f61ba2 --- /dev/null +++ b/tests/cpydiff/types_float_rounding.py @@ -0,0 +1,9 @@ +""" +categories: Types,float +description: uPy and CPython outputs formats differ +cause: Unknown +workaround: Unknown +""" +print('%.1g' % -9.9) +print('%.1e' % 9.99) +print('%.1e' % 0.999) diff --git a/tests/cpydiff/types_int_subclassconv.py b/tests/cpydiff/types_int_subclassconv.py new file mode 100644 index 000000000..565fbad4b --- /dev/null +++ b/tests/cpydiff/types_int_subclassconv.py @@ -0,0 +1,11 @@ +""" +categories: Types,int +description: No int conversion for int-derived types available +cause: Unknown +workaround: Unknown +""" +class A(int): + __add__ = lambda self, other: A(int(self) + other) + +a = A(42) +print(a+a) diff --git a/tests/cpydiff/types_int_tobytesfloat.py b/tests/cpydiff/types_int_tobytesfloat.py new file mode 100644 index 000000000..5d5b980fa --- /dev/null +++ b/tests/cpydiff/types_int_tobytesfloat.py @@ -0,0 +1,10 @@ +""" +categories: Types,int +description: Incorrect error message when passing float into to_bytes +cause: Unknown +workaround: Unknown +""" +try: + int('1').to_bytes(1.0) +except TypeError as e: + print(e) diff --git a/tests/cpydiff/types_list_delete_subscrstep.py b/tests/cpydiff/types_list_delete_subscrstep.py new file mode 100644 index 000000000..f524fa8dc --- /dev/null +++ b/tests/cpydiff/types_list_delete_subscrstep.py @@ -0,0 +1,9 @@ +""" +categories: Types,list +description: List delete with step != 1 not implemented +cause: Unknown +workaround: Unknown +""" +l = [1, 2, 3, 4] +del l[0:4:2] +print(l) diff --git a/tests/cpydiff/types_list_store_noniter.py b/tests/cpydiff/types_list_store_noniter.py new file mode 100644 index 000000000..1d69b4a82 --- /dev/null +++ b/tests/cpydiff/types_list_store_noniter.py @@ -0,0 +1,9 @@ +""" +categories: Types,list +description: List slice-store with non-iterable on RHS is not implemented +cause: RHS is restricted to be a tuple or list +workaround: Use ``list(<iter>)`` on RHS to convert the iterable to a list +""" +l = [10, 20] +l[0:1] = range(4) +print(l) diff --git a/tests/cpydiff/types_list_store_subscrstep.py b/tests/cpydiff/types_list_store_subscrstep.py new file mode 100644 index 000000000..2de2e1a3c --- /dev/null +++ b/tests/cpydiff/types_list_store_subscrstep.py @@ -0,0 +1,9 @@ +""" +categories: Types,list +description: List store with step != 1 not implemented +cause: Unknown +workaround: Unknown +""" +l = [1, 2, 3, 4] +l[0:4:2] = [5, 6] +print(l) diff --git a/tests/cpydiff/types_str_decodeerror.py b/tests/cpydiff/types_str_decodeerror.py new file mode 100644 index 000000000..944db98fe --- /dev/null +++ b/tests/cpydiff/types_str_decodeerror.py @@ -0,0 +1,11 @@ +""" +categories: Types,str +description: UnicodeDecodeError not raised when expected +cause: Unknown +workaround: Unknown +""" +try: + print(repr(str(b"\xa1\x80", 'utf8'))) + print('Should not get here') +except UnicodeDecodeError: + print('UnicodeDecodeError') diff --git a/tests/cpydiff/types_str_endswith.py b/tests/cpydiff/types_str_endswith.py new file mode 100644 index 000000000..ac2600bd2 --- /dev/null +++ b/tests/cpydiff/types_str_endswith.py @@ -0,0 +1,7 @@ +""" +categories: Types,str +description: Start/end indices such as str.endswith(s, start) not implemented +cause: Unknown +workaround: Unknown +""" +print('abc'.endswith('c', 1)) diff --git a/tests/cpydiff/types_str_formatsubscr.py b/tests/cpydiff/types_str_formatsubscr.py new file mode 100644 index 000000000..dd1d8d33d --- /dev/null +++ b/tests/cpydiff/types_str_formatsubscr.py @@ -0,0 +1,7 @@ +""" +categories: Types,str +description: Attributes/subscr not implemented +cause: Unknown +workaround: Unknown +""" +print('{a[0]}'.format(a=[1, 2])) diff --git a/tests/cpydiff/types_str_keywords.py b/tests/cpydiff/types_str_keywords.py new file mode 100644 index 000000000..b336b1a73 --- /dev/null +++ b/tests/cpydiff/types_str_keywords.py @@ -0,0 +1,7 @@ +""" +categories: Types,str +description: str(...) with keywords not implemented +cause: Unknown +workaround: Input the encoding format directly. eg ``print(bytes('abc', 'utf-8'))`` +""" +print(str(b'abc', encoding='utf8')) diff --git a/tests/cpydiff/types_str_rsplitnone.py b/tests/cpydiff/types_str_rsplitnone.py new file mode 100644 index 000000000..cadf86987 --- /dev/null +++ b/tests/cpydiff/types_str_rsplitnone.py @@ -0,0 +1,7 @@ +""" +categories: Types,str +description: None as first argument for rsplit such as str.rsplit(None, n) not implemented +cause: Unknown +workaround: Unknown +""" +print('a a a'.rsplit(None, 1)) diff --git a/tests/cpydiff/types_str_subclassequality.py b/tests/cpydiff/types_str_subclassequality.py new file mode 100644 index 000000000..8aec1ea78 --- /dev/null +++ b/tests/cpydiff/types_str_subclassequality.py @@ -0,0 +1,11 @@ +""" +categories: Types,str +description: Instance of a subclass of str cannot be compared for equality with an instance of a str +cause: Unknown +workaround: Unknown +""" +class S(str): + pass + +s = S('hello') +print(s == 'hello') diff --git a/tests/cpydiff/types_str_subscrstep.py b/tests/cpydiff/types_str_subscrstep.py new file mode 100644 index 000000000..0c2fce1b1 --- /dev/null +++ b/tests/cpydiff/types_str_subscrstep.py @@ -0,0 +1,7 @@ +""" +categories: Types,str +description: Subscript with step != 1 is not yet implemented +cause: Unknown +workaround: Unknown +""" +print('abcdefghi'[0:9:2]) diff --git a/tests/cpydiff/types_tuple_subscrstep.py b/tests/cpydiff/types_tuple_subscrstep.py new file mode 100644 index 000000000..f90f3c5bf --- /dev/null +++ b/tests/cpydiff/types_tuple_subscrstep.py @@ -0,0 +1,7 @@ +""" +categories: Types,tuple +description: Tuple load with step != 1 not implemented +cause: Unknown +workaround: Unknown +""" +print((1, 2, 3, 4)[0:4:2]) diff --git a/tests/extmod/framebuf1.py b/tests/extmod/framebuf1.py index cdc7e5b18..990b0b120 100644 --- a/tests/extmod/framebuf1.py +++ b/tests/extmod/framebuf1.py @@ -7,93 +7,104 @@ except ImportError: w = 5 h = 16 -buf = bytearray(w * h // 8) -fbuf = framebuf.FrameBuffer(buf, w, h, framebuf.MVLSB) - -# access as buffer -print(memoryview(fbuf)[0]) - -# fill -fbuf.fill(1) -print(buf) -fbuf.fill(0) -print(buf) - -# put pixel -fbuf.pixel(0, 0, 1) -fbuf.pixel(4, 0, 1) -fbuf.pixel(0, 15, 1) -fbuf.pixel(4, 15, 1) -print(buf) - -# clear pixel -fbuf.pixel(4, 15, 0) -print(buf) - -# get pixel -print(fbuf.pixel(0, 0), fbuf.pixel(1, 1)) - -# hline -fbuf.fill(0) -fbuf.hline(0, 1, w, 1) -print('hline', buf) - -# vline -fbuf.fill(0) -fbuf.vline(1, 0, h, 1) -print('vline', buf) - -# rect -fbuf.fill(0) -fbuf.rect(1, 1, 3, 3, 1) -print('rect', buf) - -#fill rect -fbuf.fill(0) -fbuf.fill_rect(1, 1, 3, 3, 1) -print('fill_rect', buf) - -# line -fbuf.fill(0) -fbuf.line(1, 1, 3, 3, 1) -print('line', buf) - -# line steep negative gradient -fbuf.fill(0) -fbuf.line(3, 3, 2, 1, 1) -print('line', buf) - -# scroll -fbuf.fill(0) -fbuf.pixel(2, 7, 1) -fbuf.scroll(0, 1) -print(buf) -fbuf.scroll(0, -2) -print(buf) -fbuf.scroll(1, 0) -print(buf) -fbuf.scroll(-1, 0) -print(buf) -fbuf.scroll(2, 2) -print(buf) - -# print text -fbuf.fill(0) -fbuf.text("hello", 0, 0, 1) -print(buf) -fbuf.text("hello", 0, 0, 0) # clear -print(buf) - -# char out of font range set to chr(127) -fbuf.text(str(chr(31)), 0, 0) -print(buf) - -# test invalid constructor +size = w * h // 8 +buf = bytearray(size) +maps = {framebuf.MONO_VLSB : 'MONO_VLSB', + framebuf.MONO_HLSB : 'MONO_HLSB', + framebuf.MONO_HMSB : 'MONO_HMSB'} + +for mapping in maps.keys(): + for x in range(size): + buf[x] = 0 + fbuf = framebuf.FrameBuffer(buf, w, h, mapping) + print(maps[mapping]) + # access as buffer + print(memoryview(fbuf)[0]) + + # fill + fbuf.fill(1) + print(buf) + fbuf.fill(0) + print(buf) + + # put pixel + fbuf.pixel(0, 0, 1) + fbuf.pixel(4, 0, 1) + fbuf.pixel(0, 15, 1) + fbuf.pixel(4, 15, 1) + print(buf) + + # clear pixel + fbuf.pixel(4, 15, 0) + print(buf) + + # get pixel + print(fbuf.pixel(0, 0), fbuf.pixel(1, 1)) + + # hline + fbuf.fill(0) + fbuf.hline(0, 1, w, 1) + print('hline', buf) + + # vline + fbuf.fill(0) + fbuf.vline(1, 0, h, 1) + print('vline', buf) + + # rect + fbuf.fill(0) + fbuf.rect(1, 1, 3, 3, 1) + print('rect', buf) + + #fill rect + fbuf.fill(0) + fbuf.fill_rect(0, 0, 0, 3, 1) # zero width, no-operation + fbuf.fill_rect(1, 1, 3, 3, 1) + print('fill_rect', buf) + + # line + fbuf.fill(0) + fbuf.line(1, 1, 3, 3, 1) + print('line', buf) + + # line steep negative gradient + fbuf.fill(0) + fbuf.line(3, 3, 2, 1, 1) + print('line', buf) + + # scroll + fbuf.fill(0) + fbuf.pixel(2, 7, 1) + fbuf.scroll(0, 1) + print(buf) + fbuf.scroll(0, -2) + print(buf) + fbuf.scroll(1, 0) + print(buf) + fbuf.scroll(-1, 0) + print(buf) + fbuf.scroll(2, 2) + print(buf) + + # print text + fbuf.fill(0) + fbuf.text("hello", 0, 0, 1) + print(buf) + fbuf.text("hello", 0, 0, 0) # clear + print(buf) + + # char out of font range set to chr(127) + fbuf.text(str(chr(31)), 0, 0) + print(buf) + print() + +# test invalid constructor, and stride argument try: - fbuf = framebuf.FrameBuffer(buf, w, h, 2, framebuf.MVLSB) + fbuf = framebuf.FrameBuffer(buf, w, h, -1, w) except ValueError: - print("ValueError") + print("ValueError") # test legacy constructor fbuf = framebuf.FrameBuffer1(buf, w, h) fbuf = framebuf.FrameBuffer1(buf, w, h, w) +print(framebuf.MVLSB == framebuf.MONO_VLSB) diff --git a/tests/extmod/framebuf1.py.exp b/tests/extmod/framebuf1.py.exp index 83d775d3c..d954623de 100644 --- a/tests/extmod/framebuf1.py.exp +++ b/tests/extmod/framebuf1.py.exp @@ -1,3 +1,4 @@ +MONO_VLSB 0 bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') @@ -18,4 +19,50 @@ bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01') bytearray(b'\x00\x7f\x7f\x04\x04\x00\x00\x00\x00\x00') bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') bytearray(b'\xaaU\xaaU\xaa\x00\x00\x00\x00\x00') + +MONO_HLSB +0 +bytearray(b'\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x88\x00\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x88\x00\x00\x00\x00\x00\x00\x00\x00\x00') +1 0 +hline bytearray(b'\x00\xf8\x00\x00\x00\x00\x00\x00\x00\x00') +vline bytearray(b'@@@@@@@@@@') +rect bytearray(b'\x00pPp\x00\x00\x00\x00\x00\x00') +fill_rect bytearray(b'\x00ppp\x00\x00\x00\x00\x00\x00') +line bytearray(b'\x00@ \x10\x00\x00\x00\x00\x00\x00') +line bytearray(b'\x00 \x10\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00 \x00') +bytearray(b'\x00\x00\x00\x00\x00\x00 \x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00 \x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00') +bytearray(b'``x````\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'P\xa8P\xa8P\xa8P\xa8\x00\x00') + +MONO_HMSB +0 +bytearray(b'\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x11\x00\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x11\x00\x00\x00\x00\x00\x00\x00\x00\x00') +1 0 +hline bytearray(b'\x00\x1f\x00\x00\x00\x00\x00\x00\x00\x00') +vline bytearray(b'\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02') +rect bytearray(b'\x00\x0e\n\x0e\x00\x00\x00\x00\x00\x00') +fill_rect bytearray(b'\x00\x0e\x0e\x0e\x00\x00\x00\x00\x00\x00') +line bytearray(b'\x00\x02\x04\x08\x00\x00\x00\x00\x00\x00') +line bytearray(b'\x00\x04\x04\x08\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00') +bytearray(b'\x06\x06\x1e\x06\x06\x06\x06\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\n\x15\n\x15\n\x15\n\x15\x00\x00') + ValueError +True diff --git a/tests/extmod/framebuf4.py b/tests/extmod/framebuf4.py new file mode 100644 index 000000000..641f5bfc5 --- /dev/null +++ b/tests/extmod/framebuf4.py @@ -0,0 +1,54 @@ +try: + import framebuf +except ImportError: + print("SKIP") + import sys + sys.exit() + +def printbuf(): + print("--8<--") + for y in range(h): + print(buf[y * w // 2:(y + 1) * w // 2]) + print("-->8--") + +w = 16 +h = 8 +buf = bytearray(w * h // 2) +fbuf = framebuf.FrameBuffer(buf, w, h, framebuf.GS4_HMSB) + +# fill +fbuf.fill(0x0f) +printbuf() +fbuf.fill(0xa0) +printbuf() + +# put pixel +fbuf.pixel(0, 0, 0x01) +printbuf() +fbuf.pixel(w-1, 0, 0x02) +printbuf() +fbuf.pixel(w-1, h-1, 0x03) +printbuf() +fbuf.pixel(0, h-1, 0x04) +printbuf() + +# get pixel +print(fbuf.pixel(0, 0), fbuf.pixel(w-1, 0), fbuf.pixel(w-1, h-1), fbuf.pixel(0, h-1)) +print(fbuf.pixel(1, 0), fbuf.pixel(w-2, 0), fbuf.pixel(w-2, h-1), fbuf.pixel(1, h-1)) + +# fill rect +fbuf.fill_rect(0, 0, w, h, 0x0f) +printbuf() +fbuf.fill_rect(0, 0, w, h, 0xf0) +fbuf.fill_rect(1, 0, w//2+1, 1, 0xf1) +printbuf() +fbuf.fill_rect(1, 0, w//2+1, 1, 0x10) +fbuf.fill_rect(1, 0, w//2, 1, 0xf1) +printbuf() +fbuf.fill_rect(1, 0, w//2, 1, 0x10) +fbuf.fill_rect(0, h-4, w//2+1, 4, 0xaf) +printbuf() +fbuf.fill_rect(0, h-4, w//2+1, 4, 0xb0) +fbuf.fill_rect(0, h-4, w//2, 4, 0xaf) +printbuf() +fbuf.fill_rect(0, h-4, w//2, 4, 0xb0) diff --git a/tests/extmod/framebuf4.py.exp b/tests/extmod/framebuf4.py.exp new file mode 100644 index 000000000..0865470a0 --- /dev/null +++ b/tests/extmod/framebuf4.py.exp @@ -0,0 +1,112 @@ +--8<-- +bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') +bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') +bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') +bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') +bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') +bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') +bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') +bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') +-->8-- +--8<-- +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +-->8-- +--8<-- +bytearray(b'\x10\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +-->8-- +--8<-- +bytearray(b'\x10\x00\x00\x00\x00\x00\x00\x02') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +-->8-- +--8<-- +bytearray(b'\x10\x00\x00\x00\x00\x00\x00\x02') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x03') +-->8-- +--8<-- +bytearray(b'\x10\x00\x00\x00\x00\x00\x00\x02') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'@\x00\x00\x00\x00\x00\x00\x03') +-->8-- +1 2 3 4 +0 0 0 0 +--8<-- +bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') +bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') +bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') +bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') +bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') +bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') +bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') +bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff') +-->8-- +--8<-- +bytearray(b'\x01\x11\x11\x11\x11\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +-->8-- +--8<-- +bytearray(b'\x01\x11\x11\x11\x10\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +-->8-- +--8<-- +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\xff\xff\xff\xff\xf0\x00\x00\x00') +bytearray(b'\xff\xff\xff\xff\xf0\x00\x00\x00') +bytearray(b'\xff\xff\xff\xff\xf0\x00\x00\x00') +bytearray(b'\xff\xff\xff\xff\xf0\x00\x00\x00') +-->8-- +--8<-- +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\xff\xff\xff\xff\x00\x00\x00\x00') +bytearray(b'\xff\xff\xff\xff\x00\x00\x00\x00') +bytearray(b'\xff\xff\xff\xff\x00\x00\x00\x00') +bytearray(b'\xff\xff\xff\xff\x00\x00\x00\x00') +-->8-- diff --git a/tests/extmod/machine1.py b/tests/extmod/machine1.py index 433a18037..e0c561168 100644 --- a/tests/extmod/machine1.py +++ b/tests/extmod/machine1.py @@ -5,7 +5,8 @@ try: import umachine as machine except ImportError: import machine -except ImportError: + machine.mem8 +except: print("SKIP") import sys sys.exit() diff --git a/tests/extmod/machine_pulse.py b/tests/extmod/machine_pulse.py index b6e126435..6491b5409 100644 --- a/tests/extmod/machine_pulse.py +++ b/tests/extmod/machine_pulse.py @@ -43,12 +43,5 @@ t = machine.time_pulse_us(p, 0) print(type(t)) p = ConstPin(0) -try: - machine.time_pulse_us(p, 1, 10) -except OSError: - print("OSError") - -try: - machine.time_pulse_us(p, 0, 10) -except OSError: - print("OSError") +print(machine.time_pulse_us(p, 1, 10)) +print(machine.time_pulse_us(p, 0, 10)) diff --git a/tests/extmod/machine_pulse.py.exp b/tests/extmod/machine_pulse.py.exp index f9a474218..20d4c1043 100644 --- a/tests/extmod/machine_pulse.py.exp +++ b/tests/extmod/machine_pulse.py.exp @@ -5,5 +5,5 @@ value: 1 value: 0 value: 1 <class 'int'> -OSError -OSError +-2 +-1 diff --git a/tests/extmod/machine_signal.py b/tests/extmod/machine_signal.py new file mode 100644 index 000000000..96b8f43c7 --- /dev/null +++ b/tests/extmod/machine_signal.py @@ -0,0 +1,40 @@ +# test machine.Signal class + +try: + import umachine as machine +except ImportError: + import machine +try: + machine.PinBase + machine.Signal +except AttributeError: + print("SKIP") + import sys + sys.exit() + +class Pin(machine.PinBase): + def __init__(self): + self.v = 0 + + def value(self, v=None): + if v is None: + return self.v + else: + self.v = int(v) + + +# test non-inverted +p = Pin() +s = machine.Signal(p) +s.value(0) +print(p.value(), s.value()) +s.value(1) +print(p.value(), s.value()) + +# test inverted, and using on/off methods +p = Pin() +s = machine.Signal(p, invert=True) +s.off() +print(p.value(), s.value()) +s.on() +print(p.value(), s.value()) diff --git a/tests/extmod/machine_signal.py.exp b/tests/extmod/machine_signal.py.exp new file mode 100644 index 000000000..7e9dd6796 --- /dev/null +++ b/tests/extmod/machine_signal.py.exp @@ -0,0 +1,4 @@ +0 0 +1 1 +1 0 +0 1 diff --git a/tests/extmod/ubinascii_a2b_base64.py b/tests/extmod/ubinascii_a2b_base64.py index 97c451950..58eb0b50b 100644 --- a/tests/extmod/ubinascii_a2b_base64.py +++ b/tests/extmod/ubinascii_a2b_base64.py @@ -1,7 +1,12 @@ try: - import ubinascii as binascii + try: + import ubinascii as binascii + except ImportError: + import binascii except ImportError: - import binascii + import sys + print("SKIP") + sys.exit() print(binascii.a2b_base64(b'')) print(binascii.a2b_base64(b'Zg==')) diff --git a/tests/extmod/ubinascii_b2a_base64.py b/tests/extmod/ubinascii_b2a_base64.py index fdcaf32dd..1c0c30311 100644 --- a/tests/extmod/ubinascii_b2a_base64.py +++ b/tests/extmod/ubinascii_b2a_base64.py @@ -1,7 +1,12 @@ try: - import ubinascii as binascii + try: + import ubinascii as binascii + except ImportError: + import binascii except ImportError: - import binascii + import sys + print("SKIP") + sys.exit() print(binascii.b2a_base64(b'')) print(binascii.b2a_base64(b'f')) diff --git a/tests/extmod/ubinascii_crc32.py b/tests/extmod/ubinascii_crc32.py index 2c4017751..b82c44d6b 100644 --- a/tests/extmod/ubinascii_crc32.py +++ b/tests/extmod/ubinascii_crc32.py @@ -1,7 +1,13 @@ try: - import ubinascii as binascii + try: + import ubinascii as binascii + except ImportError: + import binascii except ImportError: - import binascii + import sys + print("SKIP") + sys.exit() + try: binascii.crc32 except AttributeError: diff --git a/tests/extmod/ubinascii_hexlify.py b/tests/extmod/ubinascii_hexlify.py index 14c37cb4b..5d70bda96 100644 --- a/tests/extmod/ubinascii_hexlify.py +++ b/tests/extmod/ubinascii_hexlify.py @@ -1,7 +1,12 @@ try: - import ubinascii as binascii + try: + import ubinascii as binascii + except ImportError: + import binascii except ImportError: - import binascii + import sys + print("SKIP") + sys.exit() print(binascii.hexlify(b'\x00\x01\x02\x03\x04\x05\x06\x07')) print(binascii.hexlify(b'\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f')) diff --git a/tests/extmod/ubinascii_micropython.py b/tests/extmod/ubinascii_micropython.py index d68da3205..96f566bd1 100644 --- a/tests/extmod/ubinascii_micropython.py +++ b/tests/extmod/ubinascii_micropython.py @@ -1,7 +1,12 @@ try: - import ubinascii as binascii + try: + import ubinascii as binascii + except ImportError: + import binascii except ImportError: - import binascii + import sys + print("SKIP") + sys.exit() # two arguments supported in uPy but not CPython a = binascii.hexlify(b'123', ':') diff --git a/tests/extmod/ubinascii_unhexlify.py b/tests/extmod/ubinascii_unhexlify.py index 99c2c0208..e669789ba 100644 --- a/tests/extmod/ubinascii_unhexlify.py +++ b/tests/extmod/ubinascii_unhexlify.py @@ -1,7 +1,12 @@ try: - import ubinascii as binascii + try: + import ubinascii as binascii + except ImportError: + import binascii except ImportError: - import binascii + import sys + print("SKIP") + sys.exit() print(binascii.unhexlify(b'0001020304050607')) print(binascii.unhexlify(b'08090a0b0c0d0e0f')) diff --git a/tests/extmod/uctypes_32bit_intbig.py b/tests/extmod/uctypes_32bit_intbig.py new file mode 100644 index 000000000..a082dc370 --- /dev/null +++ b/tests/extmod/uctypes_32bit_intbig.py @@ -0,0 +1,54 @@ +# This test checks previously known problem values for 32-bit ports. +# It's less useful for 64-bit ports. +try: + import uctypes +except ImportError: + import sys + print("SKIP") + sys.exit() + +buf = b"12345678abcd" +struct = uctypes.struct( + uctypes.addressof(buf), + {"f32": uctypes.UINT32 | 0, "f64": uctypes.UINT64 | 4}, + uctypes.LITTLE_ENDIAN +) + +struct.f32 = 0x7fffffff +print(buf) + +struct.f32 = 0x80000000 +print(buf) + +struct.f32 = 0xff010203 +print(buf) + +struct.f64 = 0x80000000 +print(buf) + +struct.f64 = 0x80000000 * 2 +print(buf) + +print("=") + +buf = b"12345678abcd" +struct = uctypes.struct( + uctypes.addressof(buf), + {"f32": uctypes.UINT32 | 0, "f64": uctypes.UINT64 | 4}, + uctypes.BIG_ENDIAN +) + +struct.f32 = 0x7fffffff +print(buf) + +struct.f32 = 0x80000000 +print(buf) + +struct.f32 = 0xff010203 +print(buf) + +struct.f64 = 0x80000000 +print(buf) + +struct.f64 = 0x80000000 * 2 +print(buf) diff --git a/tests/extmod/uctypes_32bit_intbig.py.exp b/tests/extmod/uctypes_32bit_intbig.py.exp new file mode 100644 index 000000000..d1fc1fe35 --- /dev/null +++ b/tests/extmod/uctypes_32bit_intbig.py.exp @@ -0,0 +1,11 @@ +b'\xff\xff\xff\x7f5678abcd' +b'\x00\x00\x00\x805678abcd' +b'\x03\x02\x01\xff5678abcd' +b'\x03\x02\x01\xff\x00\x00\x00\x80\x00\x00\x00\x00' +b'\x03\x02\x01\xff\x00\x00\x00\x00\x01\x00\x00\x00' += +b'\x7f\xff\xff\xff5678abcd' +b'\x80\x00\x00\x005678abcd' +b'\xff\x01\x02\x035678abcd' +b'\xff\x01\x02\x03\x00\x00\x00\x00\x80\x00\x00\x00' +b'\xff\x01\x02\x03\x00\x00\x00\x01\x00\x00\x00\x00' diff --git a/tests/extmod/uctypes_array_assign_le.py b/tests/extmod/uctypes_array_assign_le.py index 18d63f8bf..bae467d09 100644 --- a/tests/extmod/uctypes_array_assign_le.py +++ b/tests/extmod/uctypes_array_assign_le.py @@ -1,4 +1,9 @@ -import uctypes +try: + import uctypes +except ImportError: + import sys + print("SKIP") + sys.exit() desc = { # arr is array at offset 0, of UINT8 elements, array size is 2 diff --git a/tests/extmod/uctypes_array_assign_native_le.py b/tests/extmod/uctypes_array_assign_native_le.py index 632c4d252..f0ecc0dad 100644 --- a/tests/extmod/uctypes_array_assign_native_le.py +++ b/tests/extmod/uctypes_array_assign_native_le.py @@ -1,5 +1,9 @@ import sys -import uctypes +try: + import uctypes +except ImportError: + print("SKIP") + sys.exit() if sys.byteorder != "little": print("SKIP") @@ -66,16 +70,6 @@ S.arr10[0] = 0x11223344 print(hex(S.arr10[0])) assert hex(S.arr10[0]) == "0x11223344" -# assign int64 -S.arr11[0] = 0x11223344 -print(hex(S.arr11[0])) -assert hex(S.arr11[0]) == "0x11223344" - -# assign uint64 -S.arr12[0] = 0x11223344 -print(hex(S.arr12[0])) -assert hex(S.arr12[0]) == "0x11223344" - # index out of range try: print(S.arr8[2]) diff --git a/tests/extmod/uctypes_array_assign_native_le.py.exp b/tests/extmod/uctypes_array_assign_native_le.py.exp index 4efcdec66..9d67b1c77 100644 --- a/tests/extmod/uctypes_array_assign_native_le.py.exp +++ b/tests/extmod/uctypes_array_assign_native_le.py.exp @@ -6,8 +6,6 @@ True 0x11 0x1122 0x11223344 -0x11223344 -0x11223344 IndexError TypeError TypeError diff --git a/tests/extmod/uctypes_array_assign_native_le_intbig.py b/tests/extmod/uctypes_array_assign_native_le_intbig.py new file mode 100644 index 000000000..f29a3b66e --- /dev/null +++ b/tests/extmod/uctypes_array_assign_native_le_intbig.py @@ -0,0 +1,43 @@ +import sys +try: + import uctypes +except ImportError: + print("SKIP") + sys.exit() + +if sys.byteorder != "little": + print("SKIP") + sys.exit() + +desc = { + # arr is array at offset 0, of UINT8 elements, array size is 2 + "arr": (uctypes.ARRAY | 0, uctypes.UINT8 | 2), + # arr2 is array at offset 0, size 2, of structures defined recursively + "arr2": (uctypes.ARRAY | 0, 2, {"b": uctypes.UINT8 | 0}), + "arr3": (uctypes.ARRAY | 2, uctypes.UINT16 | 2), + + # aligned + "arr5": (uctypes.ARRAY | 0, uctypes.UINT32 | 1), + "arr7": (uctypes.ARRAY | 0, 1, {"l": uctypes.UINT32 | 0}), + + "arr8": (uctypes.ARRAY | 0, uctypes.INT8 | 1), + "arr9": (uctypes.ARRAY | 0, uctypes.INT16 | 1), + "arr10": (uctypes.ARRAY | 0, uctypes.INT32 | 1), + "arr11": (uctypes.ARRAY | 0, uctypes.INT64 | 1), + "arr12": (uctypes.ARRAY | 0, uctypes.UINT64| 1), + "arr13": (uctypes.ARRAY | 1, 1, {"l": {}}), +} + +data = bytearray(8) + +S = uctypes.struct(uctypes.addressof(data), desc) + +# assign int64 +S.arr11[0] = 0x11223344 +print(hex(S.arr11[0])) +assert hex(S.arr11[0]) == "0x11223344" + +# assign uint64 +S.arr12[0] = 0x11223344 +print(hex(S.arr12[0])) +assert hex(S.arr12[0]) == "0x11223344" diff --git a/tests/extmod/uctypes_array_assign_native_le_intbig.py.exp b/tests/extmod/uctypes_array_assign_native_le_intbig.py.exp new file mode 100644 index 000000000..0394e9ae1 --- /dev/null +++ b/tests/extmod/uctypes_array_assign_native_le_intbig.py.exp @@ -0,0 +1,2 @@ +0x11223344 +0x11223344 diff --git a/tests/extmod/uctypes_bytearray.py b/tests/extmod/uctypes_bytearray.py index 7294b7ea4..bf7845ab2 100644 --- a/tests/extmod/uctypes_bytearray.py +++ b/tests/extmod/uctypes_bytearray.py @@ -1,4 +1,9 @@ -import uctypes +try: + import uctypes +except ImportError: + import sys + print("SKIP") + sys.exit() desc = { "arr": (uctypes.ARRAY | 0, uctypes.UINT8 | 2), diff --git a/tests/extmod/uctypes_le.py b/tests/extmod/uctypes_le.py index 5ae410b01..829beda58 100644 --- a/tests/extmod/uctypes_le.py +++ b/tests/extmod/uctypes_le.py @@ -1,4 +1,9 @@ -import uctypes +try: + import uctypes +except ImportError: + import sys + print("SKIP") + sys.exit() desc = { "s0": uctypes.UINT16 | 0, diff --git a/tests/extmod/uctypes_le_float.py b/tests/extmod/uctypes_le_float.py index c85b75f36..a61305ba8 100644 --- a/tests/extmod/uctypes_le_float.py +++ b/tests/extmod/uctypes_le_float.py @@ -1,4 +1,9 @@ -import uctypes +try: + import uctypes +except ImportError: + import sys + print("SKIP") + sys.exit() desc = { "f32": uctypes.FLOAT32 | 0, diff --git a/tests/extmod/uctypes_native_float.py b/tests/extmod/uctypes_native_float.py index 89aac8bf3..80cb54383 100644 --- a/tests/extmod/uctypes_native_float.py +++ b/tests/extmod/uctypes_native_float.py @@ -1,4 +1,9 @@ -import uctypes +try: + import uctypes +except ImportError: + import sys + print("SKIP") + sys.exit() desc = { "f32": uctypes.FLOAT32 | 0, diff --git a/tests/extmod/uctypes_native_le.py b/tests/extmod/uctypes_native_le.py index ef0f9f5e9..5900224d4 100644 --- a/tests/extmod/uctypes_native_le.py +++ b/tests/extmod/uctypes_native_le.py @@ -2,7 +2,11 @@ # Codepaths for packed vs native structures are different. This test only works # on little-endian machine (no matter if 32 or 64 bit). import sys -import uctypes +try: + import uctypes +except ImportError: + print("SKIP") + sys.exit() if sys.byteorder != "little": print("SKIP") diff --git a/tests/extmod/uctypes_print.py b/tests/extmod/uctypes_print.py index 71981ce7e..76a009dc7 100644 --- a/tests/extmod/uctypes_print.py +++ b/tests/extmod/uctypes_print.py @@ -1,6 +1,10 @@ # test printing of uctypes objects - -import uctypes +try: + import uctypes +except ImportError: + import sys + print("SKIP") + sys.exit() # we use an address of "0" because we just want to print something deterministic # and don't actually need to set/get any values in the struct diff --git a/tests/extmod/uctypes_ptr_le.py b/tests/extmod/uctypes_ptr_le.py index d0216dfb8..e8a6243ce 100644 --- a/tests/extmod/uctypes_ptr_le.py +++ b/tests/extmod/uctypes_ptr_le.py @@ -1,5 +1,9 @@ import sys -import uctypes +try: + import uctypes +except ImportError: + print("SKIP") + sys.exit() if sys.byteorder != "little": print("SKIP") diff --git a/tests/extmod/uctypes_ptr_native_le.py b/tests/extmod/uctypes_ptr_native_le.py index 6f011c3c2..9b016c04d 100644 --- a/tests/extmod/uctypes_ptr_native_le.py +++ b/tests/extmod/uctypes_ptr_native_le.py @@ -1,5 +1,9 @@ import sys -import uctypes +try: + import uctypes +except ImportError: + print("SKIP") + sys.exit() if sys.byteorder != "little": print("SKIP") diff --git a/tests/extmod/uctypes_sizeof.py b/tests/extmod/uctypes_sizeof.py index fcfd8ecd7..266cd0694 100644 --- a/tests/extmod/uctypes_sizeof.py +++ b/tests/extmod/uctypes_sizeof.py @@ -1,4 +1,9 @@ -import uctypes +try: + import uctypes +except ImportError: + import sys + print("SKIP") + sys.exit() desc = { # arr is array at offset 0, of UINT8 elements, array size is 2 diff --git a/tests/extmod/uctypes_sizeof_native.py b/tests/extmod/uctypes_sizeof_native.py index f830a1f85..f676c8c6d 100644 --- a/tests/extmod/uctypes_sizeof_native.py +++ b/tests/extmod/uctypes_sizeof_native.py @@ -1,4 +1,9 @@ -import uctypes +try: + import uctypes +except ImportError: + import sys + print("SKIP") + sys.exit() S1 = {} assert uctypes.sizeof(S1) == 0 diff --git a/tests/extmod/uheapq1.py b/tests/extmod/uheapq1.py index e71f817ef..4b0e5de57 100644 --- a/tests/extmod/uheapq1.py +++ b/tests/extmod/uheapq1.py @@ -1,7 +1,12 @@ try: import uheapq as heapq except: - import heapq + try: + import heapq + except ImportError: + import sys + print("SKIP") + sys.exit() try: heapq.heappop([]) diff --git a/tests/extmod/ujson_dumps.py b/tests/extmod/ujson_dumps.py index c0ee60d73..4a02f5170 100644 --- a/tests/extmod/ujson_dumps.py +++ b/tests/extmod/ujson_dumps.py @@ -1,7 +1,12 @@ try: import ujson as json except ImportError: - import json + try: + import json + except ImportError: + import sys + print("SKIP") + sys.exit() print(json.dumps(False)) print(json.dumps(True)) diff --git a/tests/extmod/ujson_dumps_extra.py b/tests/extmod/ujson_dumps_extra.py index 0e593c3e9..a52e8224c 100644 --- a/tests/extmod/ujson_dumps_extra.py +++ b/tests/extmod/ujson_dumps_extra.py @@ -1,5 +1,10 @@ # test uPy ujson behaviour that's not valid in CPy -import ujson +try: + import ujson +except ImportError: + import sys + print("SKIP") + sys.exit() print(ujson.dumps(b'1234')) diff --git a/tests/extmod/ujson_dumps_float.py b/tests/extmod/ujson_dumps_float.py index f6ba5f113..d949ea6dd 100644 --- a/tests/extmod/ujson_dumps_float.py +++ b/tests/extmod/ujson_dumps_float.py @@ -1,6 +1,11 @@ try: import ujson as json except ImportError: - import json + try: + import json + except ImportError: + import sys + print("SKIP") + sys.exit() print(json.dumps(1.2)) diff --git a/tests/extmod/ujson_load.py b/tests/extmod/ujson_load.py index bf484a207..901132a5f 100644 --- a/tests/extmod/ujson_load.py +++ b/tests/extmod/ujson_load.py @@ -2,8 +2,13 @@ try: from uio import StringIO import ujson as json except: - from io import StringIO - import json + try: + from io import StringIO + import json + except ImportError: + import sys + print("SKIP") + sys.exit() print(json.load(StringIO('null'))) print(json.load(StringIO('"abc\\u0064e"'))) diff --git a/tests/extmod/ujson_loads.py b/tests/extmod/ujson_loads.py index 37576e6ae..b2e18e3af 100644 --- a/tests/extmod/ujson_loads.py +++ b/tests/extmod/ujson_loads.py @@ -1,7 +1,12 @@ try: import ujson as json -except: - import json +except ImportError: + try: + import json + except ImportError: + import sys + print("SKIP") + sys.exit() def my_print(o): if isinstance(o, dict): diff --git a/tests/extmod/ujson_loads_float.py b/tests/extmod/ujson_loads_float.py index f5e754608..b20a412ff 100644 --- a/tests/extmod/ujson_loads_float.py +++ b/tests/extmod/ujson_loads_float.py @@ -1,7 +1,12 @@ try: import ujson as json -except: - import json +except ImportError: + try: + import json + except ImportError: + import sys + print("SKIP") + sys.exit() def my_print(o): print('%.3f' % o) diff --git a/tests/extmod/urandom_basic.py b/tests/extmod/urandom_basic.py index bf00035bd..885b8517f 100644 --- a/tests/extmod/urandom_basic.py +++ b/tests/extmod/urandom_basic.py @@ -1,7 +1,12 @@ try: import urandom as random except ImportError: - import random + try: + import random + except ImportError: + import sys + print("SKIP") + sys.exit() # check getrandbits returns a value within the bit range for b in (1, 2, 3, 4, 16, 32): diff --git a/tests/extmod/urandom_extra.py b/tests/extmod/urandom_extra.py index 004fb10cc..925dd0dbc 100644 --- a/tests/extmod/urandom_extra.py +++ b/tests/extmod/urandom_extra.py @@ -1,7 +1,12 @@ try: import urandom as random except ImportError: - import random + try: + import random + except ImportError: + import sys + print("SKIP") + sys.exit() try: random.randint diff --git a/tests/extmod/ure1.py b/tests/extmod/ure1.py index aeadf4e5c..a867f1751 100644 --- a/tests/extmod/ure1.py +++ b/tests/extmod/ure1.py @@ -1,7 +1,12 @@ try: import ure as re except ImportError: - import re + try: + import re + except ImportError: + import sys + print("SKIP") + sys.exit() r = re.compile(".+") m = r.match("abc") @@ -11,6 +16,10 @@ try: except IndexError: print("IndexError") +# conversion of re and match to string +str(r) +str(m) + r = re.compile("(.+)1") m = r.match("xyz781") print(m.group(0)) @@ -63,6 +72,11 @@ m = re.match('^ab$', 'ab'); print(m.group(0)) m = re.match('a|b', 'b'); print(m.group(0)) m = re.match('a|b|c', 'c'); print(m.group(0)) +# Case where anchors fail to match +r = re.compile("^b|b$") +m = r.search("abc") +print(m) + try: re.compile("*") except: diff --git a/tests/extmod/ure_debug.py b/tests/extmod/ure_debug.py new file mode 100644 index 000000000..252df21e3 --- /dev/null +++ b/tests/extmod/ure_debug.py @@ -0,0 +1,9 @@ +# test printing debugging info when compiling +try: + import ure +except ImportError: + import sys + print("SKIP") + sys.exit() + +ure.compile('^a|b[0-9]\w$', ure.DEBUG) diff --git a/tests/extmod/ure_debug.py.exp b/tests/extmod/ure_debug.py.exp new file mode 100644 index 000000000..45f5e20f6 --- /dev/null +++ b/tests/extmod/ure_debug.py.exp @@ -0,0 +1,15 @@ + 0: rsplit 5 (3) + 2: any + 3: jmp 0 (-5) + 5: save 0 + 7: split 14 (5) + 9: assert bol +10: char a +12: jmp 23 (9) +14: char b +16: class 1 0x30-0x39 +20: namedclass w +22: assert eol +23: save 1 +25: match +Bytes: 26, insts: 14 diff --git a/tests/extmod/ure_error.py b/tests/extmod/ure_error.py index 1e9f66a9e..3f16f9158 100644 --- a/tests/extmod/ure_error.py +++ b/tests/extmod/ure_error.py @@ -2,8 +2,13 @@ try: import ure as re -except: - import re +except ImportError: + try: + import re + except ImportError: + import sys + print("SKIP") + sys.exit() def test_re(r): try: diff --git a/tests/extmod/ure_group.py b/tests/extmod/ure_group.py index 8078a0a85..98aae2a73 100644 --- a/tests/extmod/ure_group.py +++ b/tests/extmod/ure_group.py @@ -2,8 +2,13 @@ try: import ure as re -except: - import re +except ImportError: + try: + import re + except ImportError: + import sys + print("SKIP") + sys.exit() def print_groups(match): print('----') diff --git a/tests/extmod/ure_namedclass.py b/tests/extmod/ure_namedclass.py index 25f425ce7..e233f17c8 100644 --- a/tests/extmod/ure_namedclass.py +++ b/tests/extmod/ure_namedclass.py @@ -2,8 +2,13 @@ try: import ure as re -except: - import re +except ImportError: + try: + import re + except ImportError: + import sys + print("SKIP") + sys.exit() def print_groups(match): print('----') diff --git a/tests/extmod/ure_split.py b/tests/extmod/ure_split.py index 620fd9052..1e411c27c 100644 --- a/tests/extmod/ure_split.py +++ b/tests/extmod/ure_split.py @@ -1,7 +1,12 @@ try: import ure as re except ImportError: - import re + try: + import re + except ImportError: + import sys + print("SKIP") + sys.exit() r = re.compile(" ") s = r.split("a b c foobar") diff --git a/tests/extmod/ure_split_empty.py b/tests/extmod/ure_split_empty.py index 6f31e6dc6..ad6334eba 100644 --- a/tests/extmod/ure_split_empty.py +++ b/tests/extmod/ure_split_empty.py @@ -4,7 +4,12 @@ # behaviour will change in a future version. MicroPython just stops # splitting as soon as an empty match is found. -import ure as re +try: + import ure as re +except ImportError: + import sys + print("SKIP") + sys.exit() r = re.compile(" *") s = r.split("a b c foobar") diff --git a/tests/extmod/ure_split_notimpl.py b/tests/extmod/ure_split_notimpl.py new file mode 100644 index 000000000..eca3ea512 --- /dev/null +++ b/tests/extmod/ure_split_notimpl.py @@ -0,0 +1,12 @@ +try: + import ure as re +except ImportError: + import sys + print("SKIP") + sys.exit() + +r = re.compile('( )') +try: + s = r.split("a b c foobar") +except NotImplementedError: + print('NotImplementedError') diff --git a/tests/extmod/ure_split_notimpl.py.exp b/tests/extmod/ure_split_notimpl.py.exp new file mode 100644 index 000000000..437f61670 --- /dev/null +++ b/tests/extmod/ure_split_notimpl.py.exp @@ -0,0 +1 @@ +NotImplementedError diff --git a/tests/extmod/ussl_basic.py b/tests/extmod/ussl_basic.py new file mode 100644 index 000000000..e9d435bca --- /dev/null +++ b/tests/extmod/ussl_basic.py @@ -0,0 +1,52 @@ +# very basic test of ssl module, just to test the methods exist + +try: + import uio as io + import ussl as ssl +except ImportError: + print("SKIP") + import sys + sys.exit() + +# create in client mode +try: + ss = ssl.wrap_socket(io.BytesIO()) +except OSError as er: + print('wrap_socket:', repr(er)) + +# create in server mode (can use this object for further tests) +socket = io.BytesIO() +ss = ssl.wrap_socket(socket, server_side=1) + +# print +print(repr(ss)[:12]) + +# setblocking +try: + ss.setblocking(False) +except NotImplementedError: + print('setblocking: NotImplementedError') +ss.setblocking(True) + +# write +print(ss.write(b'aaaa')) + +# read (underlying socket has no data) +print(ss.read(8)) + +# read (underlying socket has data, but it's bad data) +socket.write(b'aaaaaaaaaaaaaaaa') +socket.seek(0) +try: + ss.read(8) +except OSError as er: + print('read:', repr(er)) + +# close +ss.close() + +# write on closed socket +try: + ss.write(b'aaaa') +except OSError as er: + print('write:', repr(er)) diff --git a/tests/extmod/ussl_basic.py.exp b/tests/extmod/ussl_basic.py.exp new file mode 100644 index 000000000..b4dd03860 --- /dev/null +++ b/tests/extmod/ussl_basic.py.exp @@ -0,0 +1,8 @@ +ssl_handshake_status: -256 +wrap_socket: OSError(5,) +<_SSLSocket +setblocking: NotImplementedError +4 +b'' +read: OSError(-261,) +write: OSError(-256,) diff --git a/tests/extmod/utimeq1.py b/tests/extmod/utimeq1.py index 9af723674..68d69e25e 100644 --- a/tests/extmod/utimeq1.py +++ b/tests/extmod/utimeq1.py @@ -34,6 +34,41 @@ try: except IndexError: pass +# unsupported unary op +try: + ~h + assert False +except TypeError: + pass + +# pushing on full queue +h = utimeq(1) +h.push(1, 0, 0) +try: + h.push(2, 0, 0) + assert False +except IndexError: + pass + +# popping into invalid type +try: + h.pop([]) + assert False +except TypeError: + pass + +# length +assert len(h) == 1 + +# peektime +assert h.peektime() == 1 + +# peektime with empty queue +try: + utimeq(1).peektime() + assert False +except IndexError: + pass def pop_all(h): l = [] diff --git a/tests/extmod/uzlib_decompio.py b/tests/extmod/uzlib_decompio.py index 75a6df0ca..6f07c048c 100644 --- a/tests/extmod/uzlib_decompio.py +++ b/tests/extmod/uzlib_decompio.py @@ -1,8 +1,10 @@ try: - import zlib -except ImportError: import uzlib as zlib -import uio as io + import uio as io +except ImportError: + import sys + print("SKIP") + sys.exit() # Raw DEFLATE bitstream diff --git a/tests/extmod/uzlib_decompio_gz.py b/tests/extmod/uzlib_decompio_gz.py index c7aac04e8..7572e9693 100644 --- a/tests/extmod/uzlib_decompio_gz.py +++ b/tests/extmod/uzlib_decompio_gz.py @@ -1,8 +1,10 @@ try: - import zlib -except ImportError: import uzlib as zlib -import uio as io + import uio as io +except ImportError: + import sys + print("SKIP") + sys.exit() # gzip bitstream @@ -18,6 +20,16 @@ print(inp.read(1)) print(inp.read()) print(buf.seek(0, 1)) +# Check FHCRC field +buf = io.BytesIO(b'\x1f\x8b\x08\x02\x99\x0c\xe5W\x00\x03\x00\x00\xcbH\xcd\xc9\xc9\x07\x00\x86\xa6\x106\x05\x00\x00\x00') +inp = zlib.DecompIO(buf, 16 + 8) +print(inp.read()) + +# Check FEXTRA field +buf = io.BytesIO(b'\x1f\x8b\x08\x04\x99\x0c\xe5W\x00\x03\x01\x00X\xcbH\xcd\xc9\xc9\x07\x00\x86\xa6\x106\x05\x00\x00\x00') +inp = zlib.DecompIO(buf, 16 + 8) +print(inp.read()) + # broken header buf = io.BytesIO(b'\x1f\x8c\x08\x08\x99\x0c\xe5W\x00\x03hello\x00\xcbH\xcd\xc9\xc9\x07\x00\x86\xa6\x106\x05\x00\x00\x00') try: diff --git a/tests/extmod/uzlib_decompio_gz.py.exp b/tests/extmod/uzlib_decompio_gz.py.exp index 2330580f8..20a30c82a 100644 --- a/tests/extmod/uzlib_decompio_gz.py.exp +++ b/tests/extmod/uzlib_decompio_gz.py.exp @@ -7,5 +7,7 @@ b'lo' b'' b'' 31 +b'hello' +b'hello' ValueError OSError(22,) diff --git a/tests/extmod/uzlib_decompress.py b/tests/extmod/uzlib_decompress.py index 6892808cb..10121ee7e 100644 --- a/tests/extmod/uzlib_decompress.py +++ b/tests/extmod/uzlib_decompress.py @@ -1,7 +1,12 @@ try: import zlib except ImportError: - import uzlib as zlib + try: + import uzlib as zlib + except ImportError: + import sys + print("SKIP") + sys.exit() PATTERNS = [ # Packed results produced by CPy's zlib.compress() diff --git a/tests/extmod/vfs_basic.py b/tests/extmod/vfs_basic.py new file mode 100644 index 000000000..a3b2f3c29 --- /dev/null +++ b/tests/extmod/vfs_basic.py @@ -0,0 +1,147 @@ +# test VFS functionality without any particular filesystem type + +try: + try: + import uos_vfs as uos + open = uos.vfs_open + except ImportError: + import uos + uos.mount +except (ImportError, AttributeError): + print("SKIP") + import sys + sys.exit() + + +class Filesystem: + def __init__(self, id): + self.id = id + def mount(self, readonly, mkfs): + print(self.id, 'mount', readonly, mkfs) + def umount(self): + print(self.id, 'umount') + def ilistdir(self, dir): + print(self.id, 'ilistdir', dir) + return iter([('a%d' % self.id, 0, 0)]) + def chdir(self, dir): + print(self.id, 'chdir', dir) + def getcwd(self): + print(self.id, 'getcwd') + return 'dir%d' % self.id + def mkdir(self, path): + print(self.id, 'mkdir', path) + def remove(self, path): + print(self.id, 'remove', path) + def rename(self, old_path, new_path): + print(self.id, 'rename', old_path, new_path) + def rmdir(self, path): + print(self.id, 'rmdir', path) + def stat(self, path): + print(self.id, 'stat', path) + return (self.id,) + def statvfs(self, path): + print(self.id, 'statvfs', path) + return (self.id,) + def open(self, file, mode): + print(self.id, 'open', file, mode) + + +# first we umount any existing mount points the target may have +try: + uos.umount('/') +except OSError: + pass +for path in uos.listdir('/'): + uos.umount('/' + path) + +# stat root dir +print(uos.stat('/')) + +# getcwd when in root dir +print(uos.getcwd()) + +# basic mounting and listdir +uos.mount(Filesystem(1), '/test_mnt') +print(uos.listdir()) + +# ilistdir +i = uos.ilistdir() +print(next(i)) +try: + next(i) +except StopIteration: + print('StopIteration') +try: + next(i) +except StopIteration: + print('StopIteration') + +# referencing the mount point in different ways +print(uos.listdir('test_mnt')) +print(uos.listdir('/test_mnt')) + +# mounting another filesystem +uos.mount(Filesystem(2), '/test_mnt2', readonly=True) +print(uos.listdir()) +print(uos.listdir('/test_mnt2')) + +# mounting over an existing mount point +try: + uos.mount(Filesystem(3), '/test_mnt2') +except OSError: + print('OSError') + +# mkdir of a mount point +try: + uos.mkdir('/test_mnt') +except OSError: + print('OSError') + +# rename across a filesystem +try: + uos.rename('/test_mnt/a', '/test_mnt2/b') +except OSError: + print('OSError') + +# delegating to mounted filesystem +uos.chdir('test_mnt') +print(uos.listdir()) +print(uos.getcwd()) +uos.mkdir('test_dir') +uos.remove('test_file') +uos.rename('test_file', 'test_file2') +uos.rmdir('test_dir') +print(uos.stat('test_file')) +print(uos.statvfs('/test_mnt')) +open('test_file') +open('test_file', 'wb') + +# umount +uos.umount('/test_mnt') +uos.umount('/test_mnt2') + +# umount a non-existent mount point +try: + uos.umount('/test_mnt') +except OSError: + print('OSError') + +# root dir +uos.mount(Filesystem(3), '/') +print(uos.listdir()) +open('test') + +uos.mount(Filesystem(4), '/mnt') +print(uos.listdir()) +print(uos.listdir('/mnt')) +uos.chdir('/mnt') +print(uos.listdir()) + +# chdir to a subdir within root-mounted vfs, and then listdir +uos.chdir('/subdir') +print(uos.listdir()) +uos.chdir('/') + +uos.umount('/') +print(uos.listdir('/')) +uos.umount('/mnt') diff --git a/tests/extmod/vfs_basic.py.exp b/tests/extmod/vfs_basic.py.exp new file mode 100644 index 000000000..8a23aa8ae --- /dev/null +++ b/tests/extmod/vfs_basic.py.exp @@ -0,0 +1,56 @@ +(16384, 0, 0, 0, 0, 0, 0, 0, 0, 0) +/ +1 mount False False +['test_mnt'] +('test_mnt', 16384, 0) +StopIteration +StopIteration +1 ilistdir / +['a1'] +1 ilistdir / +['a1'] +2 mount True False +['test_mnt', 'test_mnt2'] +2 ilistdir / +['a2'] +3 mount False False +OSError +OSError +OSError +1 chdir / +1 ilistdir +['a1'] +1 getcwd +/test_mntdir1 +1 mkdir test_dir +1 remove test_file +1 rename test_file test_file2 +1 rmdir test_dir +1 stat test_file +(1,) +1 statvfs / +(1,) +1 open test_file r +1 open test_file wb +1 umount +2 umount +OSError +3 mount False False +3 ilistdir / +['a3'] +3 open test r +4 mount False False +3 ilistdir / +['mnt', 'a3'] +4 ilistdir / +['a4'] +4 chdir / +4 ilistdir +['a4'] +3 chdir /subdir +3 ilistdir +['a3'] +3 chdir / +3 umount +['mnt'] +4 umount diff --git a/tests/extmod/vfs_fat_fileio.py.exp b/tests/extmod/vfs_fat_fileio.py.exp deleted file mode 100644 index a09442ae8..000000000 --- a/tests/extmod/vfs_fat_fileio.py.exp +++ /dev/null @@ -1,25 +0,0 @@ -<io.TextIOWrapper > -True -True -True -True -hello!world! -12 -h -e -True -d -hello!world! -True -True -True -True -True -b'data in file' -True -['sub_file.txt', 'file.txt'] -['foo_file.txt', 'foo_dir', 'moved-to-root.txt'] -['foo_file.txt', 'foo_dir', 'moved-to-root.txt'] -new text -['moved-to-root.txt'] -ENOSPC: True diff --git a/tests/extmod/vfs_fat_fileio1.py b/tests/extmod/vfs_fat_fileio1.py new file mode 100644 index 000000000..9036df7a5 --- /dev/null +++ b/tests/extmod/vfs_fat_fileio1.py @@ -0,0 +1,118 @@ +import sys +try: + import uerrno + try: + import uos_vfs as uos + open = uos.vfs_open + except ImportError: + import uos +except ImportError: + print("SKIP") + sys.exit() + +try: + uos.VfsFat +except AttributeError: + print("SKIP") + sys.exit() + + +class RAMFS: + + SEC_SIZE = 512 + + def __init__(self, blocks): + self.data = bytearray(blocks * self.SEC_SIZE) + + def readblocks(self, n, buf): + #print("readblocks(%s, %x(%d))" % (n, id(buf), len(buf))) + for i in range(len(buf)): + buf[i] = self.data[n * self.SEC_SIZE + i] + + def writeblocks(self, n, buf): + #print("writeblocks(%s, %x)" % (n, id(buf))) + for i in range(len(buf)): + self.data[n * self.SEC_SIZE + i] = buf[i] + + def ioctl(self, op, arg): + #print("ioctl(%d, %r)" % (op, arg)) + if op == 4: # BP_IOCTL_SEC_COUNT + return len(self.data) // self.SEC_SIZE + if op == 5: # BP_IOCTL_SEC_SIZE + return self.SEC_SIZE + + +try: + bdev = RAMFS(50) +except MemoryError: + print("SKIP") + sys.exit() + +uos.VfsFat.mkfs(bdev) +vfs = uos.VfsFat(bdev) +uos.mount(vfs, '/ramdisk') +uos.chdir('/ramdisk') + +# file IO +f = open("foo_file.txt", "w") +print(str(f)[:17], str(f)[-1:]) +f.write("hello!") +f.flush() +f.close() +f.close() # allowed +try: + f.write("world!") +except OSError as e: + print(e.args[0] == uerrno.EINVAL) + +try: + f.read() +except OSError as e: + print(e.args[0] == uerrno.EINVAL) + +try: + f.flush() +except OSError as e: + print(e.args[0] == uerrno.EINVAL) + +try: + open("foo_file.txt", "x") +except OSError as e: + print(e.args[0] == uerrno.EEXIST) + +with open("foo_file.txt", "a") as f: + f.write("world!") + +with open("foo_file.txt") as f2: + print(f2.read()) + print(f2.tell()) + + f2.seek(0, 0) # SEEK_SET + print(f2.read(1)) + + f2.seek(0, 1) # SEEK_CUR + print(f2.read(1)) + try: + f2.seek(1, 1) # SEEK_END + except OSError as e: + print(e.args[0] == uerrno.EOPNOTSUPP) + + f2.seek(-2, 2) # SEEK_END + print(f2.read(1)) + +# using constructor of FileIO type to open a file +# no longer working with new VFS sub-system +#FileIO = type(f) +#with FileIO("/ramdisk/foo_file.txt") as f: +# print(f.read()) + +# dirs +vfs.mkdir("foo_dir") + +try: + vfs.rmdir("foo_file.txt") +except OSError as e: + print(e.args[0] == 20) # uerrno.ENOTDIR + +vfs.remove("foo_file.txt") +print(list(vfs.ilistdir())) diff --git a/tests/extmod/vfs_fat_fileio1.py.exp b/tests/extmod/vfs_fat_fileio1.py.exp new file mode 100644 index 000000000..d777585cf --- /dev/null +++ b/tests/extmod/vfs_fat_fileio1.py.exp @@ -0,0 +1,13 @@ +<io.TextIOWrapper > +True +True +True +True +hello!world! +12 +h +e +True +d +True +[('foo_dir', 16384, 0)] diff --git a/tests/extmod/vfs_fat_fileio.py b/tests/extmod/vfs_fat_fileio2.py index f050d94e2..b2a0ba70f 100644 --- a/tests/extmod/vfs_fat_fileio.py +++ b/tests/extmod/vfs_fat_fileio2.py @@ -1,6 +1,15 @@ import sys -import uos -import uerrno +try: + import uerrno + try: + import uos_vfs as uos + open = uos.vfs_open + except ImportError: + import uos +except ImportError: + print("SKIP") + sys.exit() + try: uos.VfsFat except AttributeError: @@ -34,73 +43,15 @@ class RAMFS: try: - bdev = RAMFS(48) + bdev = RAMFS(50) except MemoryError: print("SKIP") sys.exit() uos.VfsFat.mkfs(bdev) -vfs = uos.VfsFat(bdev, "/ramdisk") - -# file IO -f = vfs.open("foo_file.txt", "w") -print(str(f)[:17], str(f)[-1:]) -f.write("hello!") -f.flush() -f.close() -f.close() # allowed -try: - f.write("world!") -except OSError as e: - print(e.args[0] == uerrno.EINVAL) - -try: - f.read() -except OSError as e: - print(e.args[0] == uerrno.EINVAL) - -try: - f.flush() -except OSError as e: - print(e.args[0] == uerrno.EINVAL) - -try: - vfs.open("foo_file.txt", "x") -except OSError as e: - print(e.args[0] == uerrno.EEXIST) - -with vfs.open("foo_file.txt", "a") as f: - f.write("world!") - -with vfs.open("foo_file.txt") as f2: - print(f2.read()) - print(f2.tell()) - - f2.seek(0, 0) # SEEK_SET - print(f2.read(1)) - - f2.seek(0, 1) # SEEK_CUR - print(f2.read(1)) - try: - f2.seek(1, 1) # SEEK_END - except OSError as e: - print(e.args[0] == uerrno.EOPNOTSUPP) - - f2.seek(-2, 2) # SEEK_END - print(f2.read(1)) - -# using constructor of FileIO type to open a file -FileIO = type(f) -with FileIO("foo_file.txt") as f: - print(f.read()) - -# dirs -vfs.mkdir("foo_dir") - -try: - vfs.rmdir("foo_file.txt") -except OSError as e: - print(e.args[0] == 20) # uerrno.ENOTDIR +vfs = uos.VfsFat(bdev) +uos.mount(vfs, '/ramdisk') +uos.chdir('/ramdisk') try: vfs.mkdir("foo_dir") @@ -118,18 +69,18 @@ except OSError as e: print(e.args[0] == uerrno.ENOENT) try: - vfs.rename("foo_dir", "/null") + vfs.rename("foo_dir", "/null/file") except OSError as e: - print(e.args[0] == uerrno.ENODEV) + print(e.args[0] == uerrno.ENOENT) # file in dir -with vfs.open("foo_dir/file-in-dir.txt", "w+t") as f: +with open("foo_dir/file-in-dir.txt", "w+t") as f: f.write("data in file") -with vfs.open("foo_dir/file-in-dir.txt", "r+b") as f: +with open("foo_dir/file-in-dir.txt", "r+b") as f: print(f.read()) -with vfs.open("foo_dir/sub_file.txt", "w") as f: +with open("foo_dir/sub_file.txt", "w") as f: f.write("subdir file") # directory not empty @@ -139,31 +90,30 @@ except OSError as e: print(e.args[0] == uerrno.EACCES) # trim full path -vfs.rename("foo_dir/file-in-dir.txt", "/ramdisk/foo_dir/file.txt") -print(vfs.listdir("foo_dir")) +vfs.rename("foo_dir/file-in-dir.txt", "foo_dir/file.txt") +print(list(vfs.ilistdir("foo_dir"))) vfs.rename("foo_dir/file.txt", "moved-to-root.txt") -print(vfs.listdir()) +print(list(vfs.ilistdir())) # check that renaming to existing file will overwrite it -with vfs.open("temp", "w") as f: +with open("temp", "w") as f: f.write("new text") vfs.rename("temp", "moved-to-root.txt") -print(vfs.listdir()) -with vfs.open("moved-to-root.txt") as f: +print(list(vfs.ilistdir())) +with open("moved-to-root.txt") as f: print(f.read()) # valid removes vfs.remove("foo_dir/sub_file.txt") -vfs.remove("foo_file.txt") vfs.rmdir("foo_dir") -print(vfs.listdir()) +print(list(vfs.ilistdir())) # disk full try: bsize = vfs.statvfs("/ramdisk")[0] free = vfs.statvfs("/ramdisk")[2] + 1 - f = vfs.open("large_file.txt", "wb") + f = open("large_file.txt", "wb") f.write(bytearray(bsize * free)) except OSError as e: print("ENOSPC:", e.args[0] == 28) # uerrno.ENOSPC diff --git a/tests/extmod/vfs_fat_fileio2.py.exp b/tests/extmod/vfs_fat_fileio2.py.exp new file mode 100644 index 000000000..118dee26b --- /dev/null +++ b/tests/extmod/vfs_fat_fileio2.py.exp @@ -0,0 +1,11 @@ +True +True +True +b'data in file' +True +[('sub_file.txt', 32768, 0), ('file.txt', 32768, 0)] +[('foo_dir', 16384, 0), ('moved-to-root.txt', 32768, 0)] +[('foo_dir', 16384, 0), ('moved-to-root.txt', 32768, 0)] +new text +[('moved-to-root.txt', 32768, 0)] +ENOSPC: True diff --git a/tests/extmod/vfs_fat_fsusermount.py b/tests/extmod/vfs_fat_fsusermount.py deleted file mode 100644 index 7326172ee..000000000 --- a/tests/extmod/vfs_fat_fsusermount.py +++ /dev/null @@ -1,96 +0,0 @@ -import sys -import uos -import uerrno -try: - uos.VfsFat -except AttributeError: - print("SKIP") - sys.exit() - - -class RAMFS: - - SEC_SIZE = 512 - - def __init__(self, blocks): - self.data = bytearray(blocks * self.SEC_SIZE) - - def readblocks(self, n, buf): - #print("readblocks(%s, %x(%d))" % (n, id(buf), len(buf))) - for i in range(len(buf)): - buf[i] = self.data[n * self.SEC_SIZE + i] - - def writeblocks(self, n, buf): - #print("writeblocks(%s, %x)" % (n, id(buf))) - for i in range(len(buf)): - self.data[n * self.SEC_SIZE + i] = buf[i] - - def ioctl(self, op, arg): - #print("ioctl(%d, %r)" % (op, arg)) - if op == 4: # BP_IOCTL_SEC_COUNT - return len(self.data) // self.SEC_SIZE - if op == 5: # BP_IOCTL_SEC_SIZE - return self.SEC_SIZE - - -try: - bdev = RAMFS(48) -except MemoryError: - print("SKIP") - sys.exit() - -# can't mkfs readonly device -try: - uos.vfs_mkfs(bdev, "/ramdisk", readonly=True) -except OSError as e: - print(e) - -# mount before mkfs -try: - uos.vfs_mount(bdev, "/ramdisk") -except OSError as e: - print(e) - -# invalid umount -try: - uos.vfs_umount("/ramdisk") -except OSError as e: - print(e.args[0] == uerrno.EINVAL) - -try: - uos.vfs_mount(None, "/ramdisk") -except OSError as e: - print(e) - -try: - uos.vfs_mkfs(None, "/ramdisk") -except OSError as e: - print(e) - -# valid mkfs/mount -uos.vfs_mkfs(bdev, "/ramdisk") -uos.vfs_mount(bdev, "/ramdisk") - -# umount by path -uos.vfs_umount("/ramdisk") - -# readonly mount -uos.vfs_mount(bdev, "/ramdisk", readonly=True) -vfs = uos.VfsFat(bdev, "/ramdisk") -try: - f = vfs.open("file.txt", "w") -except OSError as e: - print("EROFS:", e.args[0] == 30) # uerrno.EROFS - -# device is None == umount -uos.vfs_mount(None, "/ramdisk") - -# max mounted devices -dev = [] -try: - for i in range(0,4): - dev.append(RAMFS(48)) - uos.vfs_mkfs(dev[i], "/ramdisk" + str(i)) - uos.vfs_mount(dev[i], "/ramdisk" + str(i)) -except OSError as e: - print(e) diff --git a/tests/extmod/vfs_fat_fsusermount.py.exp b/tests/extmod/vfs_fat_fsusermount.py.exp deleted file mode 100644 index 3b30688dd..000000000 --- a/tests/extmod/vfs_fat_fsusermount.py.exp +++ /dev/null @@ -1,7 +0,0 @@ -can't mkfs -can't mount -True -can't umount -can't umount -EROFS: True -too many devices mounted diff --git a/tests/extmod/vfs_fat_more.py b/tests/extmod/vfs_fat_more.py new file mode 100644 index 000000000..dacb21553 --- /dev/null +++ b/tests/extmod/vfs_fat_more.py @@ -0,0 +1,117 @@ +import sys +import uerrno +try: + try: + import uos_vfs as uos + open = uos.vfs_open + except ImportError: + import uos +except ImportError: + print("SKIP") + sys.exit() + +try: + uos.VfsFat +except AttributeError: + print("SKIP") + sys.exit() + + +class RAMFS: + + SEC_SIZE = 512 + + def __init__(self, blocks): + self.data = bytearray(blocks * self.SEC_SIZE) + + def readblocks(self, n, buf): + #print("readblocks(%s, %x(%d))" % (n, id(buf), len(buf))) + for i in range(len(buf)): + buf[i] = self.data[n * self.SEC_SIZE + i] + + def writeblocks(self, n, buf): + #print("writeblocks(%s, %x)" % (n, id(buf))) + for i in range(len(buf)): + self.data[n * self.SEC_SIZE + i] = buf[i] + + def ioctl(self, op, arg): + #print("ioctl(%d, %r)" % (op, arg)) + if op == 4: # BP_IOCTL_SEC_COUNT + return len(self.data) // self.SEC_SIZE + if op == 5: # BP_IOCTL_SEC_SIZE + return self.SEC_SIZE + + +try: + bdev = RAMFS(50) + bdev2 = RAMFS(50) +except MemoryError: + print("SKIP") + sys.exit() + +# first we umount any existing mount points the target may have +try: + uos.umount('/') +except OSError: + pass +for path in uos.listdir('/'): + uos.umount('/' + path) + +uos.VfsFat.mkfs(bdev) +uos.mount(bdev, '/') + +print(uos.getcwd()) + +f = open('test.txt', 'w') +f.write('hello') +f.close() + +print(uos.listdir()) +print(uos.listdir('/')) +print(uos.stat('')[:-3]) +print(uos.stat('/')[:-3]) +print(uos.stat('test.txt')[:-3]) +print(uos.stat('/test.txt')[:-3]) + +f = open('/test.txt') +print(f.read()) +f.close() + +uos.rename('test.txt', 'test2.txt') +print(uos.listdir()) +uos.rename('test2.txt', '/test3.txt') +print(uos.listdir()) +uos.rename('/test3.txt', 'test4.txt') +print(uos.listdir()) +uos.rename('/test4.txt', '/test5.txt') +print(uos.listdir()) + +uos.mkdir('dir') +print(uos.listdir()) +uos.mkdir('/dir2') +print(uos.listdir()) +uos.mkdir('dir/subdir') +print(uos.listdir('dir')) +for exist in ('', '/', 'dir', '/dir', 'dir/subdir'): + try: + uos.mkdir(exist) + except OSError as er: + print('mkdir OSError', er.args[0] == 17) # EEXIST + +uos.chdir('/') +print(uos.stat('test5.txt')[:-3]) + +uos.VfsFat.mkfs(bdev2) +uos.mount(bdev2, '/sys') +print(uos.listdir()) +print(uos.listdir('sys')) +print(uos.listdir('/sys')) + +uos.rmdir('dir2') +uos.remove('test5.txt') +print(uos.listdir()) + +uos.umount('/') +print(uos.getcwd()) +print(uos.listdir()) +print(uos.listdir('sys')) diff --git a/tests/extmod/vfs_fat_more.py.exp b/tests/extmod/vfs_fat_more.py.exp new file mode 100644 index 000000000..aaca3cc75 --- /dev/null +++ b/tests/extmod/vfs_fat_more.py.exp @@ -0,0 +1,28 @@ +/ +['test.txt'] +['test.txt'] +(16384, 0, 0, 0, 0, 0, 0) +(16384, 0, 0, 0, 0, 0, 0) +(32768, 0, 0, 0, 0, 0, 5) +(32768, 0, 0, 0, 0, 0, 5) +hello +['test2.txt'] +['test3.txt'] +['test4.txt'] +['test5.txt'] +['test5.txt', 'dir'] +['test5.txt', 'dir', 'dir2'] +['subdir'] +mkdir OSError True +mkdir OSError True +mkdir OSError True +mkdir OSError True +mkdir OSError True +(32768, 0, 0, 0, 0, 0, 5) +['sys', 'test5.txt', 'dir', 'dir2'] +[] +[] +['sys', 'dir'] +/ +['sys'] +[] diff --git a/tests/extmod/vfs_fat_oldproto.py b/tests/extmod/vfs_fat_oldproto.py index 73983567d..3e66758c3 100644 --- a/tests/extmod/vfs_fat_oldproto.py +++ b/tests/extmod/vfs_fat_oldproto.py @@ -1,10 +1,16 @@ import sys -import uos -import uerrno +try: + import uerrno + try: + import uos_vfs as uos + except ImportError: + import uos +except ImportError: + print("SKIP") + sys.exit() + try: uos.VfsFat - uos.vfs_mkfs - uos.vfs_mount except AttributeError: print("SKIP") sys.exit() @@ -34,30 +40,23 @@ class RAMFS_OLD: try: - bdev = RAMFS_OLD(48) + bdev = RAMFS_OLD(50) except MemoryError: print("SKIP") sys.exit() -uos.vfs_mkfs(bdev, "/ramdisk") -uos.vfs_mount(bdev, "/ramdisk") +uos.VfsFat.mkfs(bdev) +vfs = uos.VfsFat(bdev) +uos.mount(vfs, "/ramdisk") # file io -vfs = uos.VfsFat(bdev, "/ramdisk") with vfs.open("file.txt", "w") as f: f.write("hello!") -print(vfs.listdir()) +print(list(vfs.ilistdir())) with vfs.open("file.txt", "r") as f: print(f.read()) vfs.remove("file.txt") -print(vfs.listdir()) - -# umount by device -uos.vfs_umount(bdev) -try: - vfs.listdir() -except OSError as e: - print(e.args[0] == uerrno.ENODEV) +print(list(vfs.ilistdir())) diff --git a/tests/extmod/vfs_fat_oldproto.py.exp b/tests/extmod/vfs_fat_oldproto.py.exp index 4120c277a..ab8338cbb 100644 --- a/tests/extmod/vfs_fat_oldproto.py.exp +++ b/tests/extmod/vfs_fat_oldproto.py.exp @@ -1,4 +1,3 @@ -['file.txt'] +[('file.txt', 32768, 0)] hello! [] -True diff --git a/tests/extmod/vfs_fat_ramdisk.py b/tests/extmod/vfs_fat_ramdisk.py index 184672ff1..fe72a8bef 100644 --- a/tests/extmod/vfs_fat_ramdisk.py +++ b/tests/extmod/vfs_fat_ramdisk.py @@ -1,6 +1,14 @@ import sys -import uos -import uerrno +try: + import uerrno + try: + import uos_vfs as uos + except ImportError: + import uos +except ImportError: + print("SKIP") + sys.exit() + try: uos.VfsFat except AttributeError: @@ -34,7 +42,7 @@ class RAMFS: try: - bdev = RAMFS(48) + bdev = RAMFS(50) except MemoryError: print("SKIP") sys.exit() @@ -44,12 +52,8 @@ uos.VfsFat.mkfs(bdev) print(b"FOO_FILETXT" not in bdev.data) print(b"hello!" not in bdev.data) -vfs = uos.VfsFat(bdev, "/ramdisk") - -try: - vfs.statvfs("/null") -except OSError as e: - print(e.args[0] == uerrno.ENODEV) +vfs = uos.VfsFat(bdev) +uos.mount(vfs, "/ramdisk") print("statvfs:", vfs.statvfs("/ramdisk")) print("getcwd:", vfs.getcwd()) @@ -61,11 +65,10 @@ except OSError as e: with vfs.open("foo_file.txt", "w") as f: f.write("hello!") -print(vfs.listdir()) +print(list(vfs.ilistdir())) print("stat root:", vfs.stat("/")) -print("stat disk:", vfs.stat("/ramdisk/")) -print("stat file:", vfs.stat("foo_file.txt")) +print("stat file:", vfs.stat("foo_file.txt")[:-3]) # timestamps differ across runs print(b"FOO_FILETXT" in bdev.data) print(b"hello!" in bdev.data) @@ -73,7 +76,7 @@ print(b"hello!" in bdev.data) vfs.mkdir("foo_dir") vfs.chdir("foo_dir") print("getcwd:", vfs.getcwd()) -print(vfs.listdir()) +print(list(vfs.ilistdir())) with vfs.open("sub_file.txt", "w") as f: f.write("subdir file") @@ -86,16 +89,13 @@ except OSError as e: vfs.chdir("..") print("getcwd:", vfs.getcwd()) -vfs.umount() -try: - vfs.listdir() -except OSError as e: - print(e.args[0] == uerrno.ENODEV) +uos.umount(vfs) +vfs = uos.VfsFat(bdev) +print(list(vfs.ilistdir(b""))) + +# list a non-existent directory try: - vfs.getcwd() + vfs.ilistdir(b"no_exist") except OSError as e: - print(e.args[0] == uerrno.ENODEV) - -vfs = uos.VfsFat(bdev, "/ramdisk") -print(vfs.listdir(b"")) + print('ENOENT:', e.args[0] == uerrno.ENOENT) diff --git a/tests/extmod/vfs_fat_ramdisk.py.exp b/tests/extmod/vfs_fat_ramdisk.py.exp index eaf637199..ccd0f7134 100644 --- a/tests/extmod/vfs_fat_ramdisk.py.exp +++ b/tests/extmod/vfs_fat_ramdisk.py.exp @@ -1,19 +1,16 @@ True True +statvfs: (512, 512, 16, 16, 16, 0, 0, 0, 0, 255) +getcwd: / True -statvfs: (512, 512, 14, 14, 14, 0, 0, 0, 0, 255) -getcwd: /ramdisk -True -['foo_file.txt'] +[('foo_file.txt', 32768, 0)] stat root: (16384, 0, 0, 0, 0, 0, 0, 0, 0, 0) -stat disk: (16384, 0, 0, 0, 0, 0, 0, 0, 0, 0) -stat file: (32768, 0, 0, 0, 0, 0, 6, -631238400, -631238400, -631238400) +stat file: (32768, 0, 0, 0, 0, 0, 6) True True -getcwd: /ramdisk/foo_dir +getcwd: /foo_dir [] True -getcwd: /ramdisk -True -True -[b'foo_file.txt', b'foo_dir'] +getcwd: / +[(b'foo_file.txt', 32768, 0), (b'foo_dir', 16384, 0)] +ENOENT: True diff --git a/tests/extmod/websocket_basic.py b/tests/extmod/websocket_basic.py new file mode 100644 index 000000000..770836c8e --- /dev/null +++ b/tests/extmod/websocket_basic.py @@ -0,0 +1,61 @@ +try: + import uio + import uerrno + import websocket +except ImportError: + import sys + print("SKIP") + sys.exit() + +# put raw data in the stream and do a websocket read +def ws_read(msg, sz): + ws = websocket.websocket(uio.BytesIO(msg)) + return ws.read(sz) + +# do a websocket write and then return the raw data from the stream +def ws_write(msg, sz): + s = uio.BytesIO() + ws = websocket.websocket(s) + ws.write(msg) + s.seek(0) + return s.read(sz) + +# basic frame +print(ws_read(b"\x81\x04ping", 4)) +print(ws_read(b"\x80\x04ping", 4)) # FRAME_CONT +print(ws_write(b"pong", 6)) + +# split frames are not supported +# print(ws_read(b"\x01\x04ping", 4)) + +# extended payloads +print(ws_read(b'\x81~\x00\x80' + b'ping' * 32, 128)) +print(ws_write(b"pong" * 32, 132)) + +# mask (returned data will be 'mask' ^ 'mask') +print(ws_read(b"\x81\x84maskmask", 4)) + +# close control frame +s = uio.BytesIO(b'\x88\x00') # FRAME_CLOSE +ws = websocket.websocket(s) +print(ws.read(1)) +s.seek(2) +print(s.read(4)) + +# misc control frames +print(ws_read(b"\x89\x00\x81\x04ping", 4)) # FRAME_PING +print(ws_read(b"\x8a\x00\x81\x04pong", 4)) # FRAME_PONG + +# close method +ws = websocket.websocket(uio.BytesIO()) +ws.close() + +# ioctl +ws = websocket.websocket(uio.BytesIO()) +print(ws.ioctl(8)) # GET_DATA_OPTS +print(ws.ioctl(9, 2)) # SET_DATA_OPTS +print(ws.ioctl(9)) +try: + ws.ioctl(-1) +except OSError as e: + print("ioctl: EINVAL:", e.args[0] == uerrno.EINVAL) diff --git a/tests/extmod/websocket_basic.py.exp b/tests/extmod/websocket_basic.py.exp new file mode 100644 index 000000000..2d7657b53 --- /dev/null +++ b/tests/extmod/websocket_basic.py.exp @@ -0,0 +1,14 @@ +b'ping' +b'ping' +b'\x81\x04pong' +b'pingpingpingpingpingpingpingpingpingpingpingpingpingpingpingpingpingpingpingpingpingpingpingpingpingpingpingpingpingpingpingping' +b'\x81~\x00\x80pongpongpongpongpongpongpongpongpongpongpongpongpongpongpongpongpongpongpongpongpongpongpongpongpongpongpongpongpongpongpongpong' +b'\x00\x00\x00\x00' +b'' +b'\x81\x02\x88\x00' +b'ping' +b'pong' +0 +1 +2 +ioctl: EINVAL: True diff --git a/tests/feature_check/async_check.py b/tests/feature_check/async_check.py new file mode 100644 index 000000000..0f6361cd1 --- /dev/null +++ b/tests/feature_check/async_check.py @@ -0,0 +1,3 @@ +# check if async/await keywords are supported +async def foo(): + await 1 diff --git a/tests/feature_check/async_check.py.exp b/tests/feature_check/async_check.py.exp new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/feature_check/async_check.py.exp diff --git a/tests/feature_check/const.py b/tests/feature_check/const.py new file mode 100644 index 000000000..db32e8c69 --- /dev/null +++ b/tests/feature_check/const.py @@ -0,0 +1 @@ +x = const(1) diff --git a/tests/feature_check/const.py.exp b/tests/feature_check/const.py.exp new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/feature_check/const.py.exp diff --git a/tests/feature_check/int_big.py b/tests/feature_check/int_big.py new file mode 100644 index 000000000..f30285a98 --- /dev/null +++ b/tests/feature_check/int_big.py @@ -0,0 +1,2 @@ +# Check whether arbitrary-precision integers (MPZ) are supported +print(1000000000000000000000000000000000000000000000) diff --git a/tests/feature_check/int_big.py.exp b/tests/feature_check/int_big.py.exp new file mode 100644 index 000000000..9dfe3354d --- /dev/null +++ b/tests/feature_check/int_big.py.exp @@ -0,0 +1 @@ +1000000000000000000000000000000000000000000000 diff --git a/tests/float/array_construct.py b/tests/float/array_construct.py index a25cc72c8..7e01fd476 100644 --- a/tests/float/array_construct.py +++ b/tests/float/array_construct.py @@ -1,6 +1,11 @@ # test construction of array from array with float type -from array import array +try: + from array import array +except ImportError: + import sys + print("SKIP") + sys.exit() print(array('f', array('h', [1, 2]))) print(array('d', array('f', [1, 2]))) diff --git a/tests/float/builtin_float_hash.py b/tests/float/builtin_float_hash.py new file mode 100644 index 000000000..ba6b63907 --- /dev/null +++ b/tests/float/builtin_float_hash.py @@ -0,0 +1,22 @@ +# test builtin hash function with float args + +# these should hash to an integer with a specific value +for val in ( + '0.0', + '1.0', + '2.0', + '-12.0', + '12345.0', + ): + print(val, hash(float(val))) + +# just check that these values are hashable +for val in ( + '0.1', + '-0.1', + '10.3', + 'inf', + '-inf', + 'nan', + ): + print(val, type(hash(float(val)))) diff --git a/tests/float/builtin_float_minmax.py b/tests/float/builtin_float_minmax.py index ce45a768a..42cfa6382 100644 --- a/tests/float/builtin_float_minmax.py +++ b/tests/float/builtin_float_minmax.py @@ -1,4 +1,11 @@ # test builtin min and max functions with float args +try: + min + max +except: + import sys + print("SKIP") + sys.exit() print(min(0,1.0)) print(min(1.0,0)) diff --git a/tests/float/builtin_float_round.py b/tests/float/builtin_float_round.py index de72514db..63cb39aa3 100644 --- a/tests/float/builtin_float_round.py +++ b/tests/float/builtin_float_round.py @@ -15,3 +15,10 @@ for i in range(11): # test second arg for i in range(-1, 3): print(round(1.47, i)) + +# test inf and nan +for val in (float('inf'), float('nan')): + try: + round(val) + except (ValueError, OverflowError) as e: + print(type(e)) diff --git a/tests/float/builtin_float_round_intbig.py b/tests/float/builtin_float_round_intbig.py new file mode 100644 index 000000000..2083e3ea3 --- /dev/null +++ b/tests/float/builtin_float_round_intbig.py @@ -0,0 +1,4 @@ +# test round() with floats that return large integers + +for x in (-1e25, 1e25): + print('%.3g' % round(x)) diff --git a/tests/float/bytearray_construct.py b/tests/float/bytearray_construct.py index f72926635..db946a99d 100644 --- a/tests/float/bytearray_construct.py +++ b/tests/float/bytearray_construct.py @@ -1,5 +1,10 @@ # test construction of bytearray from array with float type -from array import array +try: + from array import array +except ImportError: + import sys + print("SKIP") + sys.exit() print(bytearray(array('f', [1, 2.3]))) diff --git a/tests/float/bytes_construct.py b/tests/float/bytes_construct.py index 0a57e08a2..8664d7296 100644 --- a/tests/float/bytes_construct.py +++ b/tests/float/bytes_construct.py @@ -1,5 +1,10 @@ # test construction of bytearray from array with float type -from array import array +try: + from array import array +except ImportError: + import sys + print("SKIP") + sys.exit() print(bytes(array('f', [1, 2.3]))) diff --git a/tests/float/complex1.py b/tests/float/complex1.py index 027d12583..a6038de04 100644 --- a/tests/float/complex1.py +++ b/tests/float/complex1.py @@ -28,6 +28,7 @@ print(1j / 2) print((1j / 2j).real) print(1j / (1 + 2j)) ans = 0j ** 0; print("%.5g %.5g" % (ans.real, ans.imag)) +ans = 0j ** 1; print("%.5g %.5g" % (ans.real, ans.imag)) ans = 0j ** 0j; print("%.5g %.5g" % (ans.real, ans.imag)) ans = 1j ** 2.5; print("%.5g %.5g" % (ans.real, ans.imag)) ans = 1j ** 2.5j; print("%.5g %.5g" % (ans.real, ans.imag)) @@ -40,6 +41,10 @@ print(1j == 1j) print(abs(1j)) print("%.5g" % abs(1j + 2)) +# builtin hash +print(hash(1 + 0j)) +print(type(hash(1j))) + # float on lhs should delegate to complex print(1.2 + 3j) @@ -48,8 +53,11 @@ print(float('nan') * 1j) print(float('inf') * (1 + 1j)) print(float('-inf') * (1 + 1j)) -# convert bignum to complex on rhs -ans = 1j + (1 << 70); print("%.5g %.5g" % (ans.real, ans.imag)) +# can't assign to attributes +try: + (1j).imag = 0 +except AttributeError: + print('AttributeError') # can't convert rhs to complex try: @@ -89,6 +97,10 @@ except ZeroDivisionError: # zero division via power try: + 0j ** -1 +except ZeroDivisionError: + print("ZeroDivisionError") +try: 0j ** 1j except ZeroDivisionError: print("ZeroDivisionError") diff --git a/tests/float/complex1_intbig.py b/tests/float/complex1_intbig.py new file mode 100644 index 000000000..ed2390bba --- /dev/null +++ b/tests/float/complex1_intbig.py @@ -0,0 +1,4 @@ +# test basic complex number functionality + +# convert bignum to complex on rhs +ans = 1j + (1 << 70); print("%.5g %.5g" % (ans.real, ans.imag)) diff --git a/tests/float/float1.py b/tests/float/float1.py index 0e115032b..93f6f014c 100644 --- a/tests/float/float1.py +++ b/tests/float/float1.py @@ -75,6 +75,11 @@ try: except ZeroDivisionError: print("ZeroDivisionError") +try: + 0.0 ** -1 +except ZeroDivisionError: + print("ZeroDivisionError") + # unsupported unary ops try: diff --git a/tests/float/float2int_doubleprec.py b/tests/float/float2int_doubleprec_intbig.py index acdc8c69c..de2137d66 100644 --- a/tests/float/float2int_doubleprec.py +++ b/tests/float/float2int_doubleprec_intbig.py @@ -5,21 +5,29 @@ try: except: import struct +import sys +maxsize_bits = 0 +maxsize = sys.maxsize +while maxsize: + maxsize >>= 1 + maxsize_bits += 1 + # work out configuration values -is_64bit = struct.calcsize("P") == 8 +is_64bit = maxsize_bits > 32 # 0 = none, 1 = long long, 2 = mpz -try: - dummy = 0x7fffffffffffffff - try: - if (0xffffffffffffffff + 1) > 0: - ll_type = 2 - else: - ll_type = 1 - except: - # in case the sum in the if statement above changes to raising an exception on overflow +ll_type = None +if is_64bit: + if maxsize_bits < 63: + ll_type = 0 +else: + if maxsize_bits < 31: + ll_type = 0 +if ll_type is None: + one = 1 + if one << 65 < one << 62: ll_type = 1 -except: - ll_type = 0 + else: + ll_type = 2 # This case occurs with time.time() values if ll_type != 0: diff --git a/tests/float/float2int_fp30.py b/tests/float/float2int_fp30_intbig.py index bad9c31e9..fbb94a4cc 100644 --- a/tests/float/float2int_fp30.py +++ b/tests/float/float2int_fp30_intbig.py @@ -5,21 +5,29 @@ try: except: import struct +import sys +maxsize_bits = 0 +maxsize = sys.maxsize +while maxsize: + maxsize >>= 1 + maxsize_bits += 1 + # work out configuration values -is_64bit = struct.calcsize("P") == 8 +is_64bit = maxsize_bits > 32 # 0 = none, 1 = long long, 2 = mpz -try: - dummy = 0x7fffffffffffffff - try: - if (0xffffffffffffffff + 1) > 0: - ll_type = 2 - else: - ll_type = 1 - except: - # in case the sum in the if statement above changes to raising an exception on overflow +ll_type = None +if is_64bit: + if maxsize_bits < 63: + ll_type = 0 +else: + if maxsize_bits < 31: + ll_type = 0 +if ll_type is None: + one = 1 + if one << 65 < one << 62: ll_type = 1 -except: - ll_type = 0 + else: + ll_type = 2 # basic conversion print(int(14187744.)) diff --git a/tests/float/float2int.py b/tests/float/float2int_intbig.py index da530cee6..3596d2f73 100644 --- a/tests/float/float2int.py +++ b/tests/float/float2int_intbig.py @@ -5,21 +5,31 @@ try: except: import struct +import sys + +maxsize_bits = 0 +maxsize = sys.maxsize +while maxsize: + maxsize >>= 1 + maxsize_bits += 1 + # work out configuration values -is_64bit = struct.calcsize("P") == 8 +is_64bit = maxsize_bits > 32 # 0 = none, 1 = long long, 2 = mpz -try: - dummy = 0x7fffffffffffffff - try: - if (0xffffffffffffffff + 1) > 0: - ll_type = 2 - else: - ll_type = 1 - except: - # in case the sum in the if statement above changes to raising an exception on overflow +ll_type = None +if is_64bit: + if maxsize_bits < 63: + ll_type = 0 +else: + if maxsize_bits < 31: + ll_type = 0 +if ll_type is None: + one = 1 + if one << 65 < one << 62: ll_type = 1 -except: - ll_type = 0 + else: + ll_type = 2 + # basic conversion print(int(14187745.)) diff --git a/tests/float/float_array.py b/tests/float/float_array.py index 033877db3..8bc963444 100644 --- a/tests/float/float_array.py +++ b/tests/float/float_array.py @@ -1,4 +1,9 @@ -from array import array +try: + from array import array +except ImportError: + import sys + print("SKIP") + sys.exit() def test(a): print(a) diff --git a/tests/float/float_struct.py b/tests/float/float_struct.py index e55890a2c..a36ccce38 100644 --- a/tests/float/float_struct.py +++ b/tests/float/float_struct.py @@ -1,9 +1,13 @@ # test struct package with floats - try: - import ustruct as struct -except: - import struct + try: + import ustruct as struct + except: + import struct +except ImportError: + import sys + print("SKIP") + sys.exit() i = 1. + 1/2 # TODO: it looks like '=' format modifier is not yet supported diff --git a/tests/float/int_divzero.py b/tests/float/int_divzero.py index b037dd8c7..b311a1dbc 100644 --- a/tests/float/int_divzero.py +++ b/tests/float/int_divzero.py @@ -2,3 +2,8 @@ try: 1 / 0 except ZeroDivisionError: print("ZeroDivisionError") + +try: + 0 ** -1 +except ZeroDivisionError: + print("ZeroDivisionError") diff --git a/tests/float/math_fun_int.py b/tests/float/math_fun_int.py new file mode 100644 index 000000000..ee54f0995 --- /dev/null +++ b/tests/float/math_fun_int.py @@ -0,0 +1,15 @@ +# test the math functions that return ints + +try: + import math +except ImportError: + print("SKIP") + import sys + sys.exit() + +for fun in (math.ceil, math.floor, math.trunc): + for x in (-1.6, -0.2, 0, 0.6, 1.4, float('inf'), float('nan')): + try: + print(fun(x)) + except (ValueError, OverflowError) as e: + print(type(e)) diff --git a/tests/float/math_fun_intbig.py b/tests/float/math_fun_intbig.py new file mode 100644 index 000000000..962c10daa --- /dev/null +++ b/tests/float/math_fun_intbig.py @@ -0,0 +1,12 @@ +# test the math functions that return ints, with very large results + +try: + import math +except ImportError: + print("SKIP") + import sys + sys.exit() + +for fun in (math.ceil, math.floor, math.trunc): + for x in (-1e25, 1e25): + print('%.3g' % fun(x)) diff --git a/tests/float/string_format_modulo2.py b/tests/float/string_format_modulo2.py index d35f2a2c0..f6b1ae537 100644 --- a/tests/float/string_format_modulo2.py +++ b/tests/float/string_format_modulo2.py @@ -18,7 +18,7 @@ def test(num, num_str): # check pure zero test(0.0, '0.0') -# check most powers of 10, making sure to include exponents with 3 digits -for e in range(-101, 102): +# check some powers of 10, making sure to include exponents with 3 digits +for e in range(-8, 8): num = pow(10, e) test(num, '1e%d' % e) diff --git a/tests/float/string_format_modulo2_intbig.py b/tests/float/string_format_modulo2_intbig.py new file mode 100644 index 000000000..9992ba65d --- /dev/null +++ b/tests/float/string_format_modulo2_intbig.py @@ -0,0 +1,21 @@ +# test formatting floats with large precision, that it doesn't overflow the buffer + +def test(num, num_str): + if num == float('inf') or num == 0.0 and num_str != '0.0': + # skip numbers that overflow or underflow the FP precision + return + for kind in ('e', 'f', 'g'): + # check precision either side of the size of the buffer (32 bytes) + for prec in range(23, 36, 2): + fmt = '%.' + '%d' % prec + kind + s = fmt % num + check = abs(float(s) - num) + if num > 1: + check /= num + if check > 1e-6: + 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 range(-101, 102): + num = pow(10, e) + test(num, '1e%d' % e) diff --git a/tests/import/import_pkg7.py b/tests/import/import_pkg7.py index be8564ef6..e1463ebbf 100644 --- a/tests/import/import_pkg7.py +++ b/tests/import/import_pkg7.py @@ -1,2 +1,2 @@ -# This tests ... relative imports as used in pkg7 +# This tests ... relative imports as used in pkg7 and imports beyond package root import pkg7.subpkg1.subpkg2.mod3 diff --git a/tests/import/import_pkg8.py b/tests/import/import_pkg8.py new file mode 100644 index 000000000..4c1e832f2 --- /dev/null +++ b/tests/import/import_pkg8.py @@ -0,0 +1,2 @@ +# import with no __init__.py files +import pkg8.mod diff --git a/tests/import/pkg7/subpkg1/subpkg2/mod3.py b/tests/import/pkg7/subpkg1/subpkg2/mod3.py index b85b34e60..7ed69bdee 100644 --- a/tests/import/pkg7/subpkg1/subpkg2/mod3.py +++ b/tests/import/pkg7/subpkg1/subpkg2/mod3.py @@ -2,3 +2,10 @@ from ... import mod1 from ...mod2 import bar print(mod1.foo) print(bar) + +# when attempting relative import beyond top-level package uPy raises ImportError +# whereas CPython raises a ValueError +try: + from .... import mod1 +except ValueError: + print('ValueError') diff --git a/tests/import/pkg8/mod.py b/tests/import/pkg8/mod.py new file mode 100644 index 000000000..b98f02ce6 --- /dev/null +++ b/tests/import/pkg8/mod.py @@ -0,0 +1 @@ +print('foo') diff --git a/tests/io/buffered_writer.py b/tests/io/buffered_writer.py index afeaa839c..bb7b4e8db 100644 --- a/tests/io/buffered_writer.py +++ b/tests/io/buffered_writer.py @@ -20,3 +20,9 @@ buf.flush() print(bts.getvalue()) buf.flush() print(bts.getvalue()) + +# special case when alloc is a factor of total buffer length +bts = io.BytesIO() +buf = io.BufferedWriter(bts, 1) +buf.write(b"foo") +print(bts.getvalue()) diff --git a/tests/io/buffered_writer.py.exp b/tests/io/buffered_writer.py.exp index 1309487e1..d086935a9 100644 --- a/tests/io/buffered_writer.py.exp +++ b/tests/io/buffered_writer.py.exp @@ -2,3 +2,4 @@ b'' b'foobarfo' b'foobarfoobar' b'foobarfoobar' +b'foo' diff --git a/tests/io/bytesio_ext.py b/tests/io/bytesio_ext.py index e827d1409..e454b2fd9 100644 --- a/tests/io/bytesio_ext.py +++ b/tests/io/bytesio_ext.py @@ -4,6 +4,10 @@ try: except ImportError: import io +a = io.BytesIO(b"foobar") +a.seek(10) +print(a.read(10)) + a = io.BytesIO() print(a.seek(8)) a.write(b"123") diff --git a/tests/io/resource_stream.py b/tests/io/resource_stream.py new file mode 100644 index 000000000..86975f118 --- /dev/null +++ b/tests/io/resource_stream.py @@ -0,0 +1,15 @@ +import uio +import sys + +try: + uio.resource_stream +except AttributeError: + print('SKIP') + sys.exit() + +buf = uio.resource_stream("data", "file2") +print(buf.read()) + +# resource_stream(None, ...) look ups from current dir, hence sys.path[0] hack +buf = uio.resource_stream(None, sys.path[0] + "/data/file2") +print(buf.read()) diff --git a/tests/io/resource_stream.py.exp b/tests/io/resource_stream.py.exp new file mode 100644 index 000000000..75404a347 --- /dev/null +++ b/tests/io/resource_stream.py.exp @@ -0,0 +1,2 @@ +1234 +1234 diff --git a/tests/micropython/const_intbig.py b/tests/micropython/const_intbig.py new file mode 100644 index 000000000..e74902652 --- /dev/null +++ b/tests/micropython/const_intbig.py @@ -0,0 +1,13 @@ +# test constant optimisation, with consts that are bignums + +from micropython import const + +# check we can make consts from bignums +Z1 = const(0xffffffff) +Z2 = const(0xffffffffffffffff) +print(hex(Z1), hex(Z2)) + +# check arithmetic with bignum +Z3 = const(Z1 + Z2) +Z4 = const((1 << 100) + Z1) +print(hex(Z3), hex(Z4)) diff --git a/tests/micropython/const_intbig.py.exp b/tests/micropython/const_intbig.py.exp new file mode 100644 index 000000000..137f86cf8 --- /dev/null +++ b/tests/micropython/const_intbig.py.exp @@ -0,0 +1,2 @@ +0xffffffff 0xffffffffffffffff +0x100000000fffffffe 0x100000000000000000ffffffff diff --git a/tests/micropython/heapalloc_bytesio.py b/tests/micropython/heapalloc_bytesio.py new file mode 100644 index 000000000..2a8d50abe --- /dev/null +++ b/tests/micropython/heapalloc_bytesio.py @@ -0,0 +1,19 @@ +try: + import uio +except ImportError: + import sys + print("SKIP") + sys.exit() + +import micropython + +data = b"1234" * 16 +buf = uio.BytesIO(64) + +micropython.heap_lock() + +buf.write(data) + +micropython.heap_unlock() + +print(buf.getvalue()) diff --git a/tests/micropython/heapalloc_bytesio.py.exp b/tests/micropython/heapalloc_bytesio.py.exp new file mode 100644 index 000000000..675761c2b --- /dev/null +++ b/tests/micropython/heapalloc_bytesio.py.exp @@ -0,0 +1 @@ +b'1234123412341234123412341234123412341234123412341234123412341234' diff --git a/tests/micropython/heapalloc_exc_raise.py b/tests/micropython/heapalloc_exc_raise.py new file mode 100644 index 000000000..d60e14ce5 --- /dev/null +++ b/tests/micropython/heapalloc_exc_raise.py @@ -0,0 +1,23 @@ +# Test that we can raise and catch (preallocated) exception +# without memory allocation. +import micropython + +e = ValueError("error") + +def func(): + try: + # This works as is because traceback is not allocated + # if not possible (heap is locked, no memory). If heap + # is not locked, this would allocate a traceback entry. + # To avoid that, traceback should be warmed up (by raising + # it once after creation) and then cleared before each + # raise with: + # e.__traceback__ = None + raise e + except Exception as e2: + print(e2) + +micropython.heap_lock() +func() +print("ok") +micropython.heap_unlock() diff --git a/tests/micropython/heapalloc_exc_raise.py.exp b/tests/micropython/heapalloc_exc_raise.py.exp new file mode 100644 index 000000000..1e9edc75d --- /dev/null +++ b/tests/micropython/heapalloc_exc_raise.py.exp @@ -0,0 +1,2 @@ +error +ok diff --git a/tests/micropython/heapalloc_int_from_bytes.py b/tests/micropython/heapalloc_int_from_bytes.py new file mode 100644 index 000000000..5fe50443a --- /dev/null +++ b/tests/micropython/heapalloc_int_from_bytes.py @@ -0,0 +1,9 @@ +# Test that int.from_bytes() for small number of bytes generates +# small int. +import micropython + +micropython.heap_lock() +print(int.from_bytes(b"1", "little")) +print(int.from_bytes(b"12", "little")) +print(int.from_bytes(b"2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", "little")) +micropython.heap_unlock() diff --git a/tests/micropython/heapalloc_int_from_bytes.py.exp b/tests/micropython/heapalloc_int_from_bytes.py.exp new file mode 100644 index 000000000..5ac6a573f --- /dev/null +++ b/tests/micropython/heapalloc_int_from_bytes.py.exp @@ -0,0 +1,3 @@ +49 +12849 +50 diff --git a/tests/micropython/heapalloc_iter.py b/tests/micropython/heapalloc_iter.py new file mode 100644 index 000000000..45d3519e4 --- /dev/null +++ b/tests/micropython/heapalloc_iter.py @@ -0,0 +1,70 @@ +# test that iterating doesn't use the heap +try: + import array +except ImportError: + import sys + print("SKIP") + sys.exit() + +try: + from micropython import heap_lock, heap_unlock +except (ImportError, AttributeError): + heap_lock = heap_unlock = lambda:0 + +def do_iter(l): + for i in l: + print(i) + +def gen_func(): + yield 1 + yield 2 + +# pre-create collections to iterate over +ba = bytearray(b'123') +ar = array.array('H', (123, 456)) +t = (1, 2, 3) +l = [1, 2] +d = {1:2} +s = set((1,)) +fs = frozenset((1,)) +g1 = (100 + x for x in range(2)) +g2 = gen_func() + +# test containment (both success and failure) with the heap locked +heap_lock() +print(49 in b'123', 255 in b'123') +print(1 in t, -1 in t) +print(1 in l, -1 in l) +print(1 in d, -1 in d) +print(1 in s, -1 in s) +heap_unlock() + +# test unpacking with the heap locked +unp0 = unp1 = unp2 = None # preallocate slots for globals +heap_lock() +unp0, unp1, unp2 = t +print(unp0, unp1, unp2) +heap_unlock() + +# test certain builtins with the heap locked +heap_lock() +print(all(t)) +print(any(t)) +print(min(t)) +print(max(t)) +print(sum(t)) +heap_unlock() + +# test iterating over collections with the heap locked +heap_lock() +do_iter(b'123') +do_iter(ba) +do_iter(ar) +do_iter(t) +do_iter(l) +do_iter(d) +do_iter(s) +do_iter(fs) +do_iter(g1) +do_iter(g2) +heap_unlock() diff --git a/tests/micropython/heapalloc_str.py b/tests/micropython/heapalloc_str.py new file mode 100644 index 000000000..39aa56ccd --- /dev/null +++ b/tests/micropython/heapalloc_str.py @@ -0,0 +1,18 @@ +# String operations which don't require allocation +import micropython + +micropython.heap_lock() + +# Concatenating empty string returns original string +b"" + b"" +b"" + b"1" +b"2" + b"" + +"" + "" +"" + "1" +"2" + "" + +# If no replacements done, returns original string +"foo".replace(",", "_") + +micropython.heap_unlock() diff --git a/tests/micropython/heapalloc_str.py.exp b/tests/micropython/heapalloc_str.py.exp new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/micropython/heapalloc_str.py.exp diff --git a/tests/micropython/heapalloc_super.py b/tests/micropython/heapalloc_super.py new file mode 100644 index 000000000..1cf5293d2 --- /dev/null +++ b/tests/micropython/heapalloc_super.py @@ -0,0 +1,17 @@ +# test super() operations which don't require allocation +import micropython + +class A: + def foo(self): + print('A foo') + return 42 +class B(A): + def foo(self): + print('B foo') + print(super().foo()) + +b = B() + +micropython.heap_lock() +b.foo() +micropython.heap_unlock() diff --git a/tests/micropython/heapalloc_super.py.exp b/tests/micropython/heapalloc_super.py.exp new file mode 100644 index 000000000..5dabd0c7c --- /dev/null +++ b/tests/micropython/heapalloc_super.py.exp @@ -0,0 +1,3 @@ +B foo +A foo +42 diff --git a/tests/micropython/heapalloc_traceback.py b/tests/micropython/heapalloc_traceback.py index 808df0225..b3795293f 100644 --- a/tests/micropython/heapalloc_traceback.py +++ b/tests/micropython/heapalloc_traceback.py @@ -2,7 +2,12 @@ import micropython import sys -import uio +try: + import uio +except ImportError: + import sys + print("SKIP") + sys.exit() # preallocate exception instance with some room for a traceback global_exc = StopIteration() diff --git a/tests/micropython/heapalloc_traceback.py.exp b/tests/micropython/heapalloc_traceback.py.exp index 9ba10948d..facd0af13 100644 --- a/tests/micropython/heapalloc_traceback.py.exp +++ b/tests/micropython/heapalloc_traceback.py.exp @@ -1,5 +1,5 @@ StopIteration Traceback (most recent call last): - File , line 18, in test + File , line 23, in test StopIteration: diff --git a/tests/micropython/kbd_intr.py b/tests/micropython/kbd_intr.py new file mode 100644 index 000000000..a7ce7464b --- /dev/null +++ b/tests/micropython/kbd_intr.py @@ -0,0 +1,13 @@ +# test the micropython.kbd_intr() function + +import micropython + +try: + micropython.kbd_intr +except AttributeError: + print('SKIP') + import sys + sys.exit() + +# just check we can actually call it +micropython.kbd_intr(3) diff --git a/tests/micropython/kbd_intr.py.exp b/tests/micropython/kbd_intr.py.exp new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/micropython/kbd_intr.py.exp diff --git a/tests/micropython/native_const.py b/tests/micropython/native_const_intbig.py index 611b39d8f..611b39d8f 100644 --- a/tests/micropython/native_const.py +++ b/tests/micropython/native_const_intbig.py diff --git a/tests/micropython/native_const.py.exp b/tests/micropython/native_const_intbig.py.exp index 1d52d220f..1d52d220f 100644 --- a/tests/micropython/native_const.py.exp +++ b/tests/micropython/native_const_intbig.py.exp diff --git a/tests/micropython/opt_level.py b/tests/micropython/opt_level.py index 4e2f2f4ea..5a10047f0 100644 --- a/tests/micropython/opt_level.py +++ b/tests/micropython/opt_level.py @@ -12,3 +12,8 @@ exec('print(__debug__)') micropython.opt_level(1) exec('print(__debug__)') exec('assert 0') + +# check that level 3 doesn't store line numbers +# the expected output is that any line is printed as "line 1" +micropython.opt_level(3) +exec('try:\n xyz\nexcept NameError as er:\n import sys\n sys.print_exception(er)') diff --git a/tests/micropython/opt_level.py.exp b/tests/micropython/opt_level.py.exp index 74b3dd74e..9b1bb4d24 100644 --- a/tests/micropython/opt_level.py.exp +++ b/tests/micropython/opt_level.py.exp @@ -2,3 +2,6 @@ 1 True False +Traceback (most recent call last): + File "<string>", line 1, in <module> +NameError: name 'xyz' is not defined diff --git a/tests/micropython/schedule.py b/tests/micropython/schedule.py new file mode 100644 index 000000000..3d584eea4 --- /dev/null +++ b/tests/micropython/schedule.py @@ -0,0 +1,61 @@ +# test micropython.schedule() function + +import micropython + +try: + micropython.schedule +except AttributeError: + print('SKIP') + import sys + sys.exit() + +# Basic test of scheduling a function. + +def callback(arg): + global done + print(arg) + done = True + +done = False +micropython.schedule(callback, 1) +while not done: + pass + +# Test that callbacks can be scheduled from within a callback, but +# that they don't execute until the outer callback is finished. + +def callback_inner(arg): + global done + print('inner') + done += 1 + +def callback_outer(arg): + global done + micropython.schedule(callback_inner, 0) + # need a loop so that the VM can check for pending events + for i in range(2): + pass + print('outer') + done += 1 + +done = 0 +micropython.schedule(callback_outer, 0) +while done != 2: + pass + +# Test that scheduling too many callbacks leads to an exception. To do this we +# must schedule from within a callback to guarantee that the scheduler is locked. + +def callback(arg): + global done + try: + for i in range(100): + micropython.schedule(lambda x:x, None) + except RuntimeError: + print('RuntimeError') + done = True + +done = False +micropython.schedule(callback, None) +while not done: + pass diff --git a/tests/micropython/schedule.py.exp b/tests/micropython/schedule.py.exp new file mode 100644 index 000000000..c4a3e1227 --- /dev/null +++ b/tests/micropython/schedule.py.exp @@ -0,0 +1,4 @@ +1 +outer +inner +RuntimeError diff --git a/tests/micropython/viper_error.py b/tests/micropython/viper_error.py index 116bd4ea0..847257285 100644 --- a/tests/micropython/viper_error.py +++ b/tests/micropython/viper_error.py @@ -3,13 +3,19 @@ def test(code): try: exec(code) - except (SyntaxError, ViperTypeError) as e: + except (SyntaxError, ViperTypeError, NotImplementedError) as e: print(repr(e)) # viper: annotations must be identifiers test("@micropython.viper\ndef f(a:1): pass") test("@micropython.viper\ndef f() -> 1: pass") +# unknown type +test("@micropython.viper\ndef f(x:unknown_type): pass") + +# too many arguments +test("@micropython.viper\ndef f(a, b, c, d, e): pass") + # local used before type known test(""" @micropython.viper @@ -49,6 +55,9 @@ test("@micropython.viper\ndef f(): 1[x]") # can't store test("@micropython.viper\ndef f(): 1[0] = 1") test("@micropython.viper\ndef f(): 1[x] = 1") +test("@micropython.viper\ndef f(x:int): x[0] = x") +test("@micropython.viper\ndef f(x:ptr32): x[0] = None") +test("@micropython.viper\ndef f(x:ptr32): x[x] = None") # must raise an object test("@micropython.viper\ndef f(): raise 1") @@ -57,3 +66,16 @@ test("@micropython.viper\ndef f(): raise 1") test("@micropython.viper\ndef f(x:int): +x") test("@micropython.viper\ndef f(x:int): -x") test("@micropython.viper\ndef f(x:int): ~x") + +# binary op not implemented +test("@micropython.viper\ndef f(x:int): res = x in x") + +# yield (from) not implemented +test("@micropython.viper\ndef f(): yield") +test("@micropython.viper\ndef f(): yield from f") + +# passing a ptr to a Python function not implemented +test("@micropython.viper\ndef f(): print(ptr(1))") + +# cast of a casting identifier not implemented +test("@micropython.viper\ndef f(): int(int)") diff --git a/tests/micropython/viper_error.py.exp b/tests/micropython/viper_error.py.exp index 1afcd4bdb..96be5a590 100644 --- a/tests/micropython/viper_error.py.exp +++ b/tests/micropython/viper_error.py.exp @@ -1,5 +1,7 @@ SyntaxError('parameter annotation must be an identifier',) SyntaxError('return annotation must be an identifier',) +ViperTypeError("unknown type 'unknown_type'",) +ViperTypeError("Viper functions don't currently support more than 4 arguments",) ViperTypeError("local 'x' used before type known",) ViperTypeError("local 'x' has type 'int' but source is 'object'",) ViperTypeError("can't implicitly convert 'ptr' to 'bool'",) @@ -9,7 +11,15 @@ ViperTypeError("can't load from 'int'",) ViperTypeError("can't load from 'int'",) ViperTypeError("can't store to 'int'",) ViperTypeError("can't store to 'int'",) +ViperTypeError("can't store to 'int'",) +ViperTypeError("can't store 'None'",) +ViperTypeError("can't store 'None'",) ViperTypeError('must raise an object',) ViperTypeError('unary op __pos__ not implemented',) ViperTypeError('unary op __neg__ not implemented',) ViperTypeError('unary op __invert__ not implemented',) +ViperTypeError('binary op __contains__ not implemented',) +NotImplementedError('native yield',) +NotImplementedError('native yield from',) +NotImplementedError('conversion to object',) +NotImplementedError('casting',) diff --git a/tests/micropython/viper_misc.py b/tests/micropython/viper_misc.py index 8bf6cc638..021e03f2c 100644 --- a/tests/micropython/viper_misc.py +++ b/tests/micropython/viper_misc.py @@ -50,13 +50,6 @@ def viper_no_annotation(x, y): return x * y print(viper_no_annotation(4, 5)) -# unsigned ints -@micropython.viper -def viper_uint() -> uint: - return uint(-1) -import sys -print(viper_uint() == (sys.maxsize << 1 | 1)) - # a for loop @micropython.viper def viper_for(a:int, b:int) -> int: diff --git a/tests/micropython/viper_misc.py.exp b/tests/micropython/viper_misc.py.exp index 4800050d1..e4462771b 100644 --- a/tests/micropython/viper_misc.py.exp +++ b/tests/micropython/viper_misc.py.exp @@ -5,7 +5,6 @@ Ellipsis 6 7 20 -True 49994955 1 1 1 3 diff --git a/tests/micropython/viper_misc_intbig.py b/tests/micropython/viper_misc_intbig.py new file mode 100644 index 000000000..e036435c7 --- /dev/null +++ b/tests/micropython/viper_misc_intbig.py @@ -0,0 +1,8 @@ +import micropython + +# unsigned ints +@micropython.viper +def viper_uint() -> uint: + return uint(-1) +import sys +print(viper_uint() == (sys.maxsize << 1 | 1)) diff --git a/tests/micropython/viper_misc_intbig.py.exp b/tests/micropython/viper_misc_intbig.py.exp new file mode 100644 index 000000000..0ca95142b --- /dev/null +++ b/tests/micropython/viper_misc_intbig.py.exp @@ -0,0 +1 @@ +True diff --git a/tests/misc/non_compliant.py b/tests/misc/non_compliant.py index e8ec74b5d..31074ab01 100644 --- a/tests/misc/non_compliant.py +++ b/tests/misc/non_compliant.py @@ -1,7 +1,12 @@ # tests for things that are not implemented, or have non-compliant behaviour -import array -import ustruct +try: + import array + import ustruct +except ImportError: + import sys + print("SKIP") + sys.exit() # when super can't find self try: @@ -124,3 +129,11 @@ try: bytearray(4)[0:1] = [1, 2] except NotImplementedError: print('NotImplementedError') + +# can't assign attributes to a function +def f(): + pass +try: + f.x = 1 +except AttributeError: + print('AttributeError') diff --git a/tests/misc/non_compliant.py.exp b/tests/misc/non_compliant.py.exp index caa5c4569..ba5590acc 100644 --- a/tests/misc/non_compliant.py.exp +++ b/tests/misc/non_compliant.py.exp @@ -19,3 +19,4 @@ NotImplementedError b'\x01\x02' b'\x01\x00' NotImplementedError +AttributeError diff --git a/tests/misc/print_exception.py b/tests/misc/print_exception.py index 9baac713e..b833a7981 100644 --- a/tests/misc/print_exception.py +++ b/tests/misc/print_exception.py @@ -1,8 +1,13 @@ +import sys try: - import uio as io + try: + import uio as io + except ImportError: + import io except ImportError: - import io -import sys + print("SKIP") + sys.exit() + if hasattr(sys, 'print_exception'): print_exception = sys.print_exception else: @@ -41,3 +46,13 @@ try: except Exception as e: print('caught') print_exc(e) + +# Here we have a function with lots of bytecode generated for a single source-line, and +# there is an error right at the end of the bytecode. It should report the correct line. +def f(): + f([1, 2], [1, 2], [1, 2], {1:1, 1:1, 1:1, 1:1, 1:1, 1:1, 1:X}) + return 1 +try: + f() +except Exception as e: + print_exc(e) diff --git a/tests/misc/recursive_data.py b/tests/misc/recursive_data.py index 0de93acb8..383018945 100644 --- a/tests/misc/recursive_data.py +++ b/tests/misc/recursive_data.py @@ -1,5 +1,10 @@ # This tests that printing recursive data structure doesn't lead to segfault. -import uio as io +try: + import uio as io +except ImportError: + import sys + print("SKIP") + sys.exit() l = [1, 2, 3, None] l[-1] = l diff --git a/tests/misc/recursive_iternext.py b/tests/misc/recursive_iternext.py index 025fa425b..d90f17716 100644 --- a/tests/misc/recursive_iternext.py +++ b/tests/misc/recursive_iternext.py @@ -1,4 +1,14 @@ # This tests that recursion with iternext doesn't lead to segfault. +try: + enumerate + filter + map + max + zip +except: + import sys + print("SKIP") + sys.exit() # We need to pick an N that is large enough to hit the recursion # limit, but not too large that we run out of heap memory. diff --git a/tests/pyb/adc.py b/tests/pyb/adc.py index 6508d7e24..362ca326d 100644 --- a/tests/pyb/adc.py +++ b/tests/pyb/adc.py @@ -9,9 +9,12 @@ print(adc) val = adc.read() assert val < 500 +# timer for read_timed +tim = pyb.Timer(5, freq=500) + # read into bytearray buf = bytearray(50) -adc.read_timed(buf, 500) +adc.read_timed(buf, tim) print(len(buf)) for i in buf: assert i < 500 @@ -19,12 +22,12 @@ for i in buf: # read into arrays with different element sizes import array ar = array.array('h', 25 * [0]) -adc.read_timed(ar, 500) +adc.read_timed(ar, tim) print(len(ar)) for i in buf: assert i < 500 ar = array.array('i', 30 * [0]) -adc.read_timed(ar, 500) +adc.read_timed(ar, tim) print(len(ar)) for i in buf: assert i < 500 diff --git a/tests/pyb/can.py b/tests/pyb/can.py index 594d1d509..617eb7ccc 100644 --- a/tests/pyb/can.py +++ b/tests/pyb/can.py @@ -1,4 +1,10 @@ -from pyb import CAN +try: + from pyb import CAN +except ImportError: + print('SKIP') + import sys + sys.exit() + import pyb # test we can correctly create by id or name diff --git a/tests/pyb/dac.py b/tests/pyb/dac.py index 884ec5829..942f30354 100644 --- a/tests/pyb/dac.py +++ b/tests/pyb/dac.py @@ -1,5 +1,10 @@ import pyb +if not hasattr(pyb, 'DAC'): + print('SKIP') + import sys + sys.exit() + dac = pyb.DAC(1) print(dac) dac.noise(100) diff --git a/tests/pyb/extint.py b/tests/pyb/extint.py index a8ba484b1..ae98ccd5a 100644 --- a/tests/pyb/extint.py +++ b/tests/pyb/extint.py @@ -1,7 +1,7 @@ import pyb # test basic functionality -ext = pyb.ExtInt('X1', pyb.ExtInt.IRQ_RISING, pyb.Pin.PULL_DOWN, lambda l:print('line:', l)) +ext = pyb.ExtInt('Y1', pyb.ExtInt.IRQ_RISING, pyb.Pin.PULL_DOWN, lambda l:print('line:', l)) ext.disable() ext.enable() print(ext.line()) diff --git a/tests/pyb/extint.py.exp b/tests/pyb/extint.py.exp index daed01c7f..1f9da9844 100644 --- a/tests/pyb/extint.py.exp +++ b/tests/pyb/extint.py.exp @@ -1,3 +1,3 @@ -0 -line: 0 -line: 0 +6 +line: 6 +line: 6 diff --git a/tests/pyb/pin.py b/tests/pyb/pin.py index b3eb87b60..9b3788343 100644 --- a/tests/pyb/pin.py +++ b/tests/pyb/pin.py @@ -1,14 +1,14 @@ from pyb import Pin -p = Pin('X1', Pin.IN) +p = Pin('Y1', Pin.IN) print(p) print(p.name()) print(p.pin()) print(p.port()) -p = Pin('X1', Pin.IN, Pin.PULL_UP) -p = Pin('X1', Pin.IN, pull=Pin.PULL_UP) -p = Pin('X1', mode=Pin.IN, pull=Pin.PULL_UP) +p = Pin('Y1', Pin.IN, Pin.PULL_UP) +p = Pin('Y1', Pin.IN, pull=Pin.PULL_UP) +p = Pin('Y1', mode=Pin.IN, pull=Pin.PULL_UP) print(p) print(p.value()) diff --git a/tests/pyb/pin.py.exp b/tests/pyb/pin.py.exp index 599374600..f2f7038fd 100644 --- a/tests/pyb/pin.py.exp +++ b/tests/pyb/pin.py.exp @@ -1,10 +1,10 @@ -Pin(Pin.cpu.A0, mode=Pin.IN) -A0 -0 -0 -Pin(Pin.cpu.A0, mode=Pin.IN, pull=Pin.PULL_UP) +Pin(Pin.cpu.C6, mode=Pin.IN) +C6 +6 +2 +Pin(Pin.cpu.C6, mode=Pin.IN, pull=Pin.PULL_UP) 1 -Pin(Pin.cpu.A0, mode=Pin.IN, pull=Pin.PULL_DOWN) +Pin(Pin.cpu.C6, mode=Pin.IN, pull=Pin.PULL_DOWN) 0 0 1 diff --git a/tests/pyb/pyb1.py b/tests/pyb/pyb1.py index 0087ec050..184acbdc4 100644 --- a/tests/pyb/pyb1.py +++ b/tests/pyb/pyb1.py @@ -27,16 +27,15 @@ print((pyb.millis() - start) // 5) # should print 3 pyb.disable_irq() pyb.enable_irq() -print(pyb.freq()) - print(pyb.have_cdc()) pyb.hid((0, 0, 0, 0)) # won't do anything -pyb.rng() - pyb.sync() print(len(pyb.unique_id())) pyb.wfi() + +pyb.fault_debug(True) +pyb.fault_debug(False) diff --git a/tests/pyb/pyb1.py.exp b/tests/pyb/pyb1.py.exp index 84034d683..5816ea967 100644 --- a/tests/pyb/pyb1.py.exp +++ b/tests/pyb/pyb1.py.exp @@ -1,5 +1,4 @@ 3 3 -(168000000, 168000000, 42000000, 84000000) True 12 diff --git a/tests/pyb/pyb_f405.py b/tests/pyb/pyb_f405.py new file mode 100644 index 000000000..3c81fe109 --- /dev/null +++ b/tests/pyb/pyb_f405.py @@ -0,0 +1,11 @@ +# test pyb module on F405 MCUs + +import os, pyb + +if not 'STM32F405' in os.uname().machine: + print('SKIP') + import sys + sys.exit() + +print(pyb.freq()) +print(type(pyb.rng())) diff --git a/tests/pyb/pyb_f405.py.exp b/tests/pyb/pyb_f405.py.exp new file mode 100644 index 000000000..a90aa0268 --- /dev/null +++ b/tests/pyb/pyb_f405.py.exp @@ -0,0 +1,2 @@ +(168000000, 168000000, 42000000, 84000000) +<class 'int'> diff --git a/tests/pyb/pyb_f411.py b/tests/pyb/pyb_f411.py new file mode 100644 index 000000000..328653965 --- /dev/null +++ b/tests/pyb/pyb_f411.py @@ -0,0 +1,10 @@ +# test pyb module on F411 MCUs + +import os, pyb + +if not 'STM32F411' in os.uname().machine: + print('SKIP') + import sys + sys.exit() + +print(pyb.freq()) diff --git a/tests/pyb/pyb_f411.py.exp b/tests/pyb/pyb_f411.py.exp new file mode 100644 index 000000000..79e0a1062 --- /dev/null +++ b/tests/pyb/pyb_f411.py.exp @@ -0,0 +1 @@ +(96000000, 96000000, 24000000, 48000000) diff --git a/tests/pyb/rtc.py b/tests/pyb/rtc.py index 300c95634..844526b4b 100644 --- a/tests/pyb/rtc.py +++ b/tests/pyb/rtc.py @@ -7,7 +7,7 @@ print(rtc) # make sure that 1 second passes correctly rtc.datetime((2014, 1, 1, 1, 0, 0, 0, 0)) -pyb.delay(1001) +pyb.delay(1002) print(rtc.datetime()[:7]) def set_and_print(datetime): diff --git a/tests/run-tests b/tests/run-tests index 91282667d..f24fc0961 100755 --- a/tests/run-tests +++ b/tests/run-tests @@ -23,7 +23,6 @@ MPYCROSS = os.getenv('MICROPY_MPYCROSS', '../mpy-cross/mpy-cross') # Set PYTHONIOENCODING so that CPython will use utf-8 on systems which set another encoding in the locale os.environ['PYTHONIOENCODING'] = 'utf-8' -os.environ['MICROPYPATH'] = '' def rm_f(fname): if os.path.exists(fname): @@ -50,15 +49,15 @@ def convert_regex_escapes(line): return bytes(''.join(cs), 'utf8') -def run_micropython(pyb, args, test_file): - special_tests = ('micropython/meminfo.py', 'basics/bytes_compare3.py', 'thread/thread_exc2.py') - is_special = False +def run_micropython(pyb, args, test_file, is_special=False): + special_tests = ('micropython/meminfo.py', 'basics/bytes_compare3.py', 'basics/builtin_help.py', 'thread/thread_exc2.py') if pyb is None: # run on PC if test_file.startswith(('cmdline/', 'feature_check/')) or test_file in special_tests: # special handling for tests of the unix cmdline program is_special = True + if is_special: # check for any cmdline options needed for this test args = [MICROPYTHON] with open(test_file, 'rb') as f: @@ -145,6 +144,10 @@ def run_micropython(pyb, args, test_file): # canonical form for all ports/platforms is to use \n for end-of-line output_mupy = output_mupy.replace(b'\r\n', b'\n') + # don't try to convert the output if we should skip this test + if output_mupy in (b'SKIP\n', b'CRASH'): + return output_mupy + if is_special or test_file in special_tests: # convert parts of the output that are not stable across runs with open(test_file + '.exp', 'rb') as f: @@ -186,7 +189,12 @@ def run_micropython(pyb, args, test_file): return output_mupy -def run_tests(pyb, tests, args): + +def run_feature_check(pyb, args, base_path, test_file): + return run_micropython(pyb, args, base_path + "/feature_check/" + test_file, is_special=True) + + +def run_tests(pyb, tests, args, base_path="."): test_count = 0 testcase_count = 0 passed_count = 0 @@ -195,27 +203,45 @@ def run_tests(pyb, tests, args): skip_tests = set() skip_native = False + skip_int_big = False skip_set_type = False + skip_async = False + skip_const = False # Check if micropython.native is supported, and skip such tests if it's not - native = run_micropython(pyb, args, 'feature_check/native_check.py') + native = run_feature_check(pyb, args, base_path, 'native_check.py') if native == b'CRASH': skip_native = True + # Check if arbitrary-precision integers are supported, and skip such tests if it's not + native = run_feature_check(pyb, args, base_path, 'int_big.py') + if native != b'1000000000000000000000000000000000000000000000\n': + skip_int_big = True + # Check if set type (and set literals) is supported, and skip such tests if it's not - native = run_micropython(pyb, args, 'feature_check/set_check.py') + native = run_feature_check(pyb, args, base_path, 'set_check.py') if native == b'CRASH': skip_set_type = True + # Check if async/await keywords are supported, and skip such tests if it's not + native = run_feature_check(pyb, args, base_path, 'async_check.py') + if native == b'CRASH': + skip_async = True + + # Check if const keyword (MicroPython extension) is supported, and skip such tests if it's not + native = run_feature_check(pyb, args, base_path, 'const.py') + if native == b'CRASH': + skip_const = True + # Check if emacs repl is supported, and skip such tests if it's not - t = run_micropython(pyb, args, 'feature_check/repl_emacs_check.py') + t = run_feature_check(pyb, args, base_path, 'repl_emacs_check.py') if not 'True' in str(t, 'ascii'): skip_tests.add('cmdline/repl_emacs_keys.py') - upy_byteorder = run_micropython(pyb, args, 'feature_check/byteorder.py') - has_complex = run_micropython(pyb, args, 'feature_check/complex.py') == b'complex\n' - has_coverage = run_micropython(pyb, args, 'feature_check/coverage.py') == b'coverage\n' - cpy_byteorder = subprocess.check_output([CPYTHON3, 'feature_check/byteorder.py']) + upy_byteorder = run_feature_check(pyb, args, base_path, 'byteorder.py') + has_complex = run_feature_check(pyb, args, base_path, 'complex.py') == b'complex\n' + has_coverage = run_feature_check(pyb, args, base_path, 'coverage.py') == b'coverage\n' + cpy_byteorder = subprocess.check_output([CPYTHON3, base_path + '/feature_check/byteorder.py']) skip_endian = (upy_byteorder != cpy_byteorder) # Some tests shouldn't be run under Travis CI @@ -228,6 +254,7 @@ def run_tests(pyb, tests, args): if not has_complex: skip_tests.add('float/complex1.py') + skip_tests.add('float/complex1_intbig.py') skip_tests.add('float/int_big_float.py') skip_tests.add('float/true_value.py') skip_tests.add('float/types.py') @@ -246,7 +273,7 @@ def run_tests(pyb, tests, args): if pyb is not None: skip_tests.add('basics/exception_chain.py') # warning is not printed skip_tests.add('float/float_divmod.py') # tested by float/float_divmod_relaxed.py instead - skip_tests.add('float/float2int_doubleprec.py') # requires double precision floating point to work + skip_tests.add('float/float2int_doubleprec_intbig.py') # requires double precision floating point to work skip_tests.add('micropython/meminfo.py') # output is very different to PC output skip_tests.add('extmod/machine_mem.py') # raw memory access not supported @@ -264,11 +291,14 @@ def run_tests(pyb, tests, args): skip_tests.add('extmod/urandom_basic.py') # requires urandom skip_tests.add('extmod/urandom_extra.py') # requires urandom elif args.target == 'esp8266': - skip_tests.add('float/float2int.py') # requires at least fp32, there's float2int_fp30.py instead + skip_tests.add('float/float2int_intbig.py') # requires at least fp32, there's float2int_fp30_intbig.py instead skip_tests.add('float/string_format.py') # requires at least fp32, there's string_format_fp30.py instead skip_tests.add('float/bytes_construct.py') # requires fp32 skip_tests.add('float/bytearray_construct.py') # requires fp32 skip_tests.add('misc/rge_sm.py') # too large + elif args.target == 'minimal': + skip_tests.add('misc/rge_sm.py') # too large + skip_tests.add('micropython/opt_level.py') # don't assume line numbers are stored # Some tests are known to fail on 64-bit machines if pyb is None and platform.architecture()[0] == '64bit': @@ -281,7 +311,7 @@ def run_tests(pyb, tests, args): # Some tests are known to fail with native emitter # Remove them from the below when they work if args.emit == 'native': - skip_tests.update({'basics/%s.py' % t for t in 'gen_yield_from gen_yield_from_close gen_yield_from_ducktype gen_yield_from_exc gen_yield_from_iter gen_yield_from_send gen_yield_from_stopped gen_yield_from_throw gen_yield_from_throw2 generator1 generator2 generator_args generator_close generator_closure generator_exc generator_return generator_send'.split()}) # require yield + skip_tests.update({'basics/%s.py' % t for t in 'gen_yield_from gen_yield_from_close gen_yield_from_ducktype gen_yield_from_exc gen_yield_from_iter gen_yield_from_send gen_yield_from_stopped gen_yield_from_throw gen_yield_from_throw2 gen_yield_from_throw3 generator1 generator2 generator_args generator_close generator_closure generator_exc generator_return generator_send'.split()}) # require yield skip_tests.update({'basics/%s.py' % t for t in 'bytes_gen class_store_class globals_del string_join'.split()}) # require yield skip_tests.update({'basics/async_%s.py' % t for t in 'def await await2 for for2 with with2'.split()}) # require yield skip_tests.update({'basics/%s.py' % t for t in 'try_reraise try_reraise2'.split()}) # require raise_varargs @@ -303,6 +333,8 @@ def run_tests(pyb, tests, args): skip_tests.add('misc/print_exception.py') # because native doesn't have proper traceback info skip_tests.add('misc/sys_exc_info.py') # sys.exc_info() is not supported for native skip_tests.add('micropython/heapalloc_traceback.py') # because native doesn't have proper traceback info + skip_tests.add('micropython/heapalloc_iter.py') # requires generators + skip_tests.add('micropython/schedule.py') # native code doesn't check pending events for test_file in tests: test_file = test_file.replace('\\', '/') @@ -310,12 +342,18 @@ def run_tests(pyb, tests, args): test_name = os.path.splitext(test_basename)[0] is_native = test_name.startswith("native_") or test_name.startswith("viper_") is_endian = test_name.endswith("_endian") - is_set_type = test_name.startswith("set_") + is_int_big = test_name.startswith("int_big") or test_name.endswith("_intbig") + is_set_type = test_name.startswith("set_") or test_name.startswith("frozenset") + is_async = test_name.startswith("async_") + is_const = test_name.startswith("const") skip_it = test_file in skip_tests skip_it |= skip_native and is_native skip_it |= skip_endian and is_endian + skip_it |= skip_int_big and is_int_big skip_it |= skip_set_type and is_set_type + skip_it |= skip_async and is_async + skip_it |= skip_const and is_const if skip_it: print("skip ", test_file) @@ -396,10 +434,11 @@ def main(): cmd_parser.add_argument('--emit', default='bytecode', help='MicroPython emitter to use (bytecode or native)') cmd_parser.add_argument('--heapsize', help='heapsize to use (use default if not specified)') cmd_parser.add_argument('--via-mpy', action='store_true', help='compile .py files to .mpy first') + cmd_parser.add_argument('--keep-path', action='store_true', help='do not clear MICROPYPATH when running tests') cmd_parser.add_argument('files', nargs='*', help='input test files') args = cmd_parser.parse_args() - EXTERNAL_TARGETS = ('pyboard', 'wipy', 'esp8266') + EXTERNAL_TARGETS = ('pyboard', 'wipy', 'esp8266', 'minimal') if args.target in EXTERNAL_TARGETS: import pyboard pyb = pyboard.Pyboard(args.device, args.baudrate, args.user, args.password) @@ -414,7 +453,7 @@ def main(): if args.target == 'pyboard': # run pyboard tests test_dirs = ('basics', 'micropython', 'float', 'misc', 'stress', 'extmod', 'pyb', 'pybnative', 'inlineasm') - elif args.target == 'esp8266': + elif args.target in ('esp8266', 'minimal'): test_dirs = ('basics', 'micropython', 'float', 'misc', 'extmod') elif args.target == 'wipy': # run WiPy tests @@ -430,7 +469,18 @@ def main(): # tests explicitly given tests = args.files - if not run_tests(pyb, tests, args): + if not args.keep_path: + # clear search path to make sure tests use only builtin modules + os.environ['MICROPYPATH'] = '' + + # Even if we run completely different tests in a different directory, + # we need to access feature_check's from the same directory as the + # run-tests script itself. + base_path = os.path.dirname(sys.argv[0]) or "." + res = run_tests(pyb, tests, args, base_path) + if pyb: + pyb.close() + if not res: sys.exit(1) if __name__ == "__main__": diff --git a/tests/thread/stress_create.py b/tests/thread/stress_create.py new file mode 100644 index 000000000..2399746cc --- /dev/null +++ b/tests/thread/stress_create.py @@ -0,0 +1,22 @@ +# stress test for creating many threads + +try: + import utime as time +except ImportError: + import time +import _thread + +def thread_entry(n): + pass + +thread_num = 0 +while thread_num < 500: + try: + _thread.start_new_thread(thread_entry, (thread_num,)) + thread_num += 1 + except MemoryError: + pass + +# wait for the last threads to terminate +time.sleep(1) +print('done') diff --git a/tests/thread/stress_heap.py b/tests/thread/stress_heap.py index ac3ebe049..5482a9ac6 100644 --- a/tests/thread/stress_heap.py +++ b/tests/thread/stress_heap.py @@ -3,6 +3,10 @@ # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd +try: + import utime as time +except ImportError: + import time import _thread def last(l): @@ -37,6 +41,6 @@ n_finished = 0 for i in range(n_thread): _thread.start_new_thread(thread_entry, (10000,)) -# busy wait for threads to finish +# wait for threads to finish while n_finished < n_thread: - pass + time.sleep(1) diff --git a/tests/thread/thread_exc2.py.exp b/tests/thread/thread_exc2.py.exp index 584bfab4d..cc7a20aa2 100644 --- a/tests/thread/thread_exc2.py.exp +++ b/tests/thread/thread_exc2.py.exp @@ -1,5 +1,5 @@ Unhandled exception in thread started by <function thread_entry at 0x\[0-9a-f\]\+> Traceback (most recent call last): - File "thread/thread_exc2.py", line 6, in thread_entry + File \.\+, line 6, in thread_entry ValueError: done diff --git a/tests/thread/thread_lock4.py b/tests/thread/thread_lock4.py index d77aa24ee..2f9d42d6b 100644 --- a/tests/thread/thread_lock4.py +++ b/tests/thread/thread_lock4.py @@ -2,6 +2,10 @@ # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd +try: + import utime as time +except ImportError: + import time import _thread def fac(n): @@ -39,6 +43,7 @@ while True: with jobs_lock: if len(output) == n_jobs: break + time.sleep(1) # sort and print the results output.sort(key=lambda x: x[0]) diff --git a/tests/thread/thread_qstr1.py b/tests/thread/thread_qstr1.py index c0256316e..f4136d964 100644 --- a/tests/thread/thread_qstr1.py +++ b/tests/thread/thread_qstr1.py @@ -2,6 +2,10 @@ # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd +try: + import utime as time +except ImportError: + import time import _thread # function to check the interned string @@ -28,8 +32,8 @@ n_qstr_per_thread = 100 # make 1000 for a more stressful test (uses more heap) for i in range(n_thread): _thread.start_new_thread(th, (i * n_qstr_per_thread, n_qstr_per_thread)) -# busy wait for threads to finish +# wait for threads to finish while n_finished < n_thread: - pass + time.sleep(1) print('pass') diff --git a/tests/thread/thread_stacksize1.py b/tests/thread/thread_stacksize1.py index e62899631..62b6e5e40 100644 --- a/tests/thread/thread_stacksize1.py +++ b/tests/thread/thread_stacksize1.py @@ -38,6 +38,9 @@ _thread.stack_size(sz) for i in range(n_thread): _thread.start_new_thread(thread_entry, ()) +# reset stack size to default (for subsequent scripts on baremetal) +_thread.stack_size() + # busy wait for threads to finish while n_finished < n_thread: pass diff --git a/tests/unix/extra_coverage.py b/tests/unix/extra_coverage.py index f2b40282b..870e7d5f2 100644 --- a/tests/unix/extra_coverage.py +++ b/tests/unix/extra_coverage.py @@ -5,15 +5,52 @@ except NameError: import sys sys.exit() +import uerrno +import uio + data = extra_coverage() # test hashing of str/bytes that have an invalid hash -print(data) +print(data[0], data[1]) print(hash(data[0])) print(hash(data[1])) print(hash(bytes(data[0], 'utf8'))) print(hash(str(data[1], 'utf8'))) +# test streams +stream = data[2] # has set_error and set_buf. Write always returns error +stream.set_error(uerrno.EAGAIN) # non-blocking error +print(stream.read()) # read all encounters non-blocking error +print(stream.read(1)) # read 1 byte encounters non-blocking error +print(stream.readline()) # readline encounters non-blocking error +print(stream.readinto(bytearray(10))) # readinto encounters non-blocking error +print(stream.write(b'1')) # write encounters non-blocking error +print(stream.write1(b'1')) # write1 encounters non-blocking error +stream.set_buf(b'123') +print(stream.read(4)) # read encounters non-blocking error after successful reads +stream.set_buf(b'123') +print(stream.read1(4)) # read1 encounters non-blocking error after successful reads +stream.set_buf(b'123') +print(stream.readline(4)) # readline encounters non-blocking error after successful reads +try: + print(stream.ioctl(0, 0)) # ioctl encounters non-blocking error; raises OSError +except OSError: + print('OSError') +stream.set_error(0) +print(stream.ioctl(0, bytearray(10))) # successful ioctl call + +stream2 = data[3] # is textio and sets .write = NULL +try: + print(stream2.write(b'1')) # attempt to call NULL implementation +except OSError: + print('OSError') +print(stream2.read(1)) # read 1 byte encounters non-blocking error with textio stream + +# test BufferedWriter with stream errors +stream.set_error(uerrno.EAGAIN) +buf = uio.BufferedWriter(stream, 8) +print(buf.write(bytearray(16))) + # test basic import of frozen scripts import frzstr1 import frzmpy1 @@ -29,3 +66,9 @@ from frzstr_pkg2.mod import Foo print(Foo.x) from frzmpy_pkg2.mod import Foo print(Foo.x) + +# test raising exception in frozen script +try: + import frzmpy2 +except ZeroDivisionError: + print('ZeroDivisionError') diff --git a/tests/unix/extra_coverage.py.exp b/tests/unix/extra_coverage.py.exp index d3d725211..416993887 100644 --- a/tests/unix/extra_coverage.py.exp +++ b/tests/unix/extra_coverage.py.exp @@ -43,11 +43,39 @@ Warning: test ? +1e+00 +1e+00 -('0123456789', b'0123456789') +# binary +122 +456 +# scheduler +sched(0)=1 +sched(1)=1 +sched(2)=1 +sched(3)=1 +sched(4)=0 +unlocked +3 +2 +1 +0 +0123456789 b'0123456789' 7300 7300 7300 7300 +None +None +None +None +None +None +b'123' +b'123' +b'123' +OSError +0 +OSError +None +None frzstr1 frzmpy1 frzstr_pkg1.__init__ @@ -58,3 +86,4 @@ frzstr_pkg2.mod 1 frzmpy_pkg2.mod 1 +ZeroDivisionError |