tests/cpydiff: Add initial set of tests for uPy-CPython differences.
These tests are intended to fail, as they provide a programatic record of differences between uPy and CPython. They also contain a special comment at the start of the file which has meta-data describing the difference, including known causes and known workarounds.
This commit is contained in:
parent
89267886cc
commit
86c7507233
10
tests/cpydiff/core_arguments.py
Normal file
10
tests/cpydiff/core_arguments.py
Normal file
@ -0,0 +1,10 @@
|
||||
"""
|
||||
categories: Core
|
||||
description: Error messages may display incorrect argument counts
|
||||
cause: Unknown
|
||||
workaround: Unknown
|
||||
"""
|
||||
try:
|
||||
[].append()
|
||||
except Exception as e:
|
||||
print(e)
|
16
tests/cpydiff/core_class_delnotimpl.py
Normal file
16
tests/cpydiff/core_class_delnotimpl.py
Normal file
@ -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()
|
13
tests/cpydiff/core_class_superaslocal.py
Normal file
13
tests/cpydiff/core_class_superaslocal.py
Normal file
@ -0,0 +1,13 @@
|
||||
"""
|
||||
categories: Core,Classes
|
||||
description: Bug when using "super" as a local
|
||||
cause: Unknown
|
||||
workaround: Unknown
|
||||
"""
|
||||
class A:
|
||||
def foo(self):
|
||||
super = [1]
|
||||
super.pop()
|
||||
print(super)
|
||||
|
||||
A().foo()
|
27
tests/cpydiff/core_class_supermultiple.py
Normal file
27
tests/cpydiff/core_class_supermultiple.py
Normal file
@ -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()
|
18
tests/cpydiff/core_class_superproperty.py
Normal file
18
tests/cpydiff/core_class_superproperty.py
Normal file
@ -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)
|
11
tests/cpydiff/core_function_instancevar.py
Normal file
11
tests/cpydiff/core_function_instancevar.py
Normal file
@ -0,0 +1,11 @@
|
||||
"""
|
||||
categories: Core,Functions
|
||||
description: Assign instance variable to function
|
||||
cause: Unknown
|
||||
workaround: Unknown
|
||||
"""
|
||||
def f():
|
||||
pass
|
||||
|
||||
f.x = 0
|
||||
print(f.x)
|
7
tests/cpydiff/core_function_unpacking.py
Normal file
7
tests/cpydiff/core_function_unpacking.py
Normal file
@ -0,0 +1,7 @@
|
||||
"""
|
||||
categories: Core,Functions
|
||||
description: Unpacking function arguments in non-last position gives incorrect result
|
||||
cause: Unknown
|
||||
workaround: Unknown
|
||||
"""
|
||||
print(*(1, 2), 3)
|
24
tests/cpydiff/core_generator_noexit.py
Normal file
24
tests/cpydiff/core_generator_noexit.py
Normal file
@ -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()
|
17
tests/cpydiff/core_import_prereg.py
Normal file
17
tests/cpydiff/core_import_prereg.py
Normal file
@ -0,0 +1,17 @@
|
||||
"""
|
||||
categories: Core,import
|
||||
description: Failed to load modules are still registered as loaded
|
||||
cause: Unknown
|
||||
workaround: Unknown
|
||||
"""
|
||||
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)
|
15
tests/cpydiff/core_mro.py
Normal file
15
tests/cpydiff/core_mro.py
Normal file
@ -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)
|
0
tests/cpydiff/modules/__init__.py
Normal file
0
tests/cpydiff/modules/__init__.py
Normal file
2
tests/cpydiff/modules/foo.py
Normal file
2
tests/cpydiff/modules/foo.py
Normal file
@ -0,0 +1,2 @@
|
||||
print('foo')
|
||||
xxx
|
8
tests/cpydiff/modules_array_containment.py
Normal file
8
tests/cpydiff/modules_array_containment.py
Normal file
@ -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'))
|
10
tests/cpydiff/modules_array_deletion.py
Normal file
10
tests/cpydiff/modules_array_deletion.py
Normal file
@ -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)
|
9
tests/cpydiff/modules_array_subscrstep.py
Normal file
9
tests/cpydiff/modules_array_subscrstep.py
Normal file
@ -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])
|
9
tests/cpydiff/modules_deque.py
Normal file
9
tests/cpydiff/modules_deque.py
Normal file
@ -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)
|
14
tests/cpydiff/modules_json_nonserializable.py
Normal file
14
tests/cpydiff/modules_json_nonserializable.py
Normal file
@ -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')
|
12
tests/cpydiff/modules_struct_fewargs.py
Normal file
12
tests/cpydiff/modules_struct_fewargs.py
Normal file
@ -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')
|
12
tests/cpydiff/modules_struct_manyargs.py
Normal file
12
tests/cpydiff/modules_struct_manyargs.py
Normal file
@ -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')
|
9
tests/cpydiff/modules_sys_stdassign.py
Normal file
9
tests/cpydiff/modules_sys_stdassign.py
Normal file
@ -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)
|
18
tests/cpydiff/syntax_spaces.py
Normal file
18
tests/cpydiff/syntax_spaces.py
Normal file
@ -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')
|
7
tests/cpydiff/syntax_unicode_nameesc.py
Normal file
7
tests/cpydiff/syntax_unicode_nameesc.py
Normal file
@ -0,0 +1,7 @@
|
||||
"""
|
||||
categories: Syntax,Unicode
|
||||
description: Unicode name escapes are not implemented
|
||||
cause: Unknown
|
||||
workaround: Unknown
|
||||
"""
|
||||
print("\N{LATIN SMALL LETTER A}")
|
9
tests/cpydiff/types_bytearray_sliceassign.py
Normal file
9
tests/cpydiff/types_bytearray_sliceassign.py
Normal file
@ -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)
|
7
tests/cpydiff/types_bytes_keywords.py
Normal file
7
tests/cpydiff/types_bytes_keywords.py
Normal file
@ -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'))
|
7
tests/cpydiff/types_bytes_subscrstep.py
Normal file
7
tests/cpydiff/types_bytes_subscrstep.py
Normal file
@ -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])
|
10
tests/cpydiff/types_exception_chaining.py
Normal file
10
tests/cpydiff/types_exception_chaining.py
Normal file
@ -0,0 +1,10 @@
|
||||
"""
|
||||
categories: Types,Exception
|
||||
description: Exception chaining not implemented
|
||||
cause: Unknown
|
||||
workaround: Unknown
|
||||
"""
|
||||
try:
|
||||
raise TypeError
|
||||
except TypeError:
|
||||
raise ValueError
|
9
tests/cpydiff/types_exception_instancevar.py
Normal file
9
tests/cpydiff/types_exception_instancevar.py
Normal file
@ -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)
|
12
tests/cpydiff/types_exception_loops.py
Normal file
12
tests/cpydiff/types_exception_loops.py
Normal file
@ -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
|
11
tests/cpydiff/types_exception_subclassinit.py
Normal file
11
tests/cpydiff/types_exception_subclassinit.py
Normal file
@ -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()
|
9
tests/cpydiff/types_float_rounding.py
Normal file
9
tests/cpydiff/types_float_rounding.py
Normal file
@ -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)
|
11
tests/cpydiff/types_int_subclassconv.py
Normal file
11
tests/cpydiff/types_int_subclassconv.py
Normal file
@ -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)
|
10
tests/cpydiff/types_int_tobytesfloat.py
Normal file
10
tests/cpydiff/types_int_tobytesfloat.py
Normal file
@ -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)
|
9
tests/cpydiff/types_list_delete_subscrstep.py
Normal file
9
tests/cpydiff/types_list_delete_subscrstep.py
Normal file
@ -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)
|
9
tests/cpydiff/types_list_store_subscrstep.py
Normal file
9
tests/cpydiff/types_list_store_subscrstep.py
Normal file
@ -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)
|
11
tests/cpydiff/types_str_decodeerror.py
Normal file
11
tests/cpydiff/types_str_decodeerror.py
Normal file
@ -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')
|
7
tests/cpydiff/types_str_endswith.py
Normal file
7
tests/cpydiff/types_str_endswith.py
Normal file
@ -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))
|
7
tests/cpydiff/types_str_formatsubscr.py
Normal file
7
tests/cpydiff/types_str_formatsubscr.py
Normal file
@ -0,0 +1,7 @@
|
||||
"""
|
||||
categories: Types,str
|
||||
description: Attributes/subscr not implemented
|
||||
cause: Unknown
|
||||
workaround: Unknown
|
||||
"""
|
||||
print('{a[0]}'.format(a=[1, 2]))
|
7
tests/cpydiff/types_str_keywords.py
Normal file
7
tests/cpydiff/types_str_keywords.py
Normal file
@ -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'))
|
7
tests/cpydiff/types_str_rsplitnone.py
Normal file
7
tests/cpydiff/types_str_rsplitnone.py
Normal file
@ -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))
|
11
tests/cpydiff/types_str_subclassequality.py
Normal file
11
tests/cpydiff/types_str_subclassequality.py
Normal file
@ -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')
|
7
tests/cpydiff/types_str_subscrstep.py
Normal file
7
tests/cpydiff/types_str_subscrstep.py
Normal file
@ -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])
|
7
tests/cpydiff/types_tuple_subscrstep.py
Normal file
7
tests/cpydiff/types_tuple_subscrstep.py
Normal file
@ -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])
|
Loading…
Reference in New Issue
Block a user