mirror of https://github.com/pyodide/pyodide.git
Use multi-line code snippets in tests
This commit is contained in:
parent
8c27b0b44b
commit
d869ac5bfc
|
@ -4,6 +4,7 @@ Various common utilities for testing.
|
|||
|
||||
import atexit
|
||||
import multiprocessing
|
||||
import textwrap
|
||||
import os
|
||||
import pathlib
|
||||
import queue
|
||||
|
@ -73,10 +74,16 @@ class SeleniumWrapper:
|
|||
self.driver.execute_script("window.logs = []")
|
||||
|
||||
def run(self, code):
|
||||
if isinstance(code, str) and code.startswith('\n'):
|
||||
# we have a multiline string, fix indentation
|
||||
code = textwrap.dedent(code)
|
||||
return self.run_js(
|
||||
'return pyodide.runPython({!r})'.format(code))
|
||||
|
||||
def run_js(self, code):
|
||||
if isinstance(code, str) and code.startswith('\n'):
|
||||
# we have a multiline string, fix indentation
|
||||
code = textwrap.dedent(code)
|
||||
catch = f"""
|
||||
Error.stackTraceLimit = Infinity;
|
||||
try {{ {code} }}
|
||||
|
|
|
@ -43,16 +43,21 @@ def test_python2js(selenium):
|
|||
'(x.length === 5) && '
|
||||
'(x[0] === 98)')
|
||||
assert selenium.run_js(
|
||||
'let x = pyodide.runPython("[1, 2, 3]");\n'
|
||||
'return (x instanceof window.Array) && (x.length === 3) && '
|
||||
'(x[0] == 1) && (x[1] == 2) && (x[2] == 3)')
|
||||
"""
|
||||
let x = pyodide.runPython("[1, 2, 3]");
|
||||
return ((x instanceof window.Array) && (x.length === 3) &&
|
||||
(x[0] == 1) && (x[1] == 2) && (x[2] == 3))
|
||||
""")
|
||||
assert selenium.run_js(
|
||||
'let x = pyodide.runPython("{42: 64}");\n'
|
||||
'return (typeof x === "object") && '
|
||||
'(x[42] === 64)')
|
||||
"""
|
||||
let x = pyodide.runPython("{42: 64}");
|
||||
return (typeof x === "object") && (x[42] === 64)
|
||||
""")
|
||||
assert selenium.run_js(
|
||||
'let x = pyodide.runPython("open(\'/foo.txt\', \'wb\')")\n'
|
||||
'return (x.tell() === 0)\n')
|
||||
"""
|
||||
let x = pyodide.runPython("open('/foo.txt', 'wb')")
|
||||
return (x.tell() === 0)
|
||||
""")
|
||||
|
||||
|
||||
def test_pythonexc2js(selenium):
|
||||
|
@ -66,17 +71,19 @@ def test_pythonexc2js(selenium):
|
|||
|
||||
def test_js2python(selenium):
|
||||
selenium.run_js(
|
||||
'window.jsstring = "碘化物";\n'
|
||||
'window.jsnumber0 = 42;\n'
|
||||
'window.jsnumber1 = 42.5;\n'
|
||||
'window.jsundefined = undefined;\n'
|
||||
'window.jsnull = null;\n'
|
||||
'window.jstrue = true;\n'
|
||||
'window.jsfalse = false;\n'
|
||||
'window.jspython = pyodide.pyimport("open");\n'
|
||||
'window.jsbytes = new Uint8Array([1, 2, 3]);\n'
|
||||
'window.jsfloats = new Float32Array([1, 2, 3]);\n'
|
||||
'window.jsobject = new XMLHttpRequest();\n'
|
||||
"""
|
||||
window.jsstring = "碘化物";
|
||||
window.jsnumber0 = 42;
|
||||
window.jsnumber1 = 42.5;
|
||||
window.jsundefined = undefined;
|
||||
window.jsnull = null;
|
||||
window.jstrue = true;
|
||||
window.jsfalse = false;
|
||||
window.jspython = pyodide.pyimport("open");
|
||||
window.jsbytes = new Uint8Array([1, 2, 3]);
|
||||
window.jsfloats = new Float32Array([1, 2, 3]);
|
||||
window.jsobject = new XMLHttpRequest();
|
||||
"""
|
||||
)
|
||||
assert selenium.run(
|
||||
'from js import jsstring\n'
|
||||
|
@ -100,70 +107,84 @@ def test_js2python(selenium):
|
|||
'from js import jspython\n'
|
||||
'jspython is open')
|
||||
assert selenium.run(
|
||||
'from js import jsbytes\n'
|
||||
'(jsbytes.tolist() == [1, 2, 3]) '
|
||||
'and (jsbytes.tobytes() == b"\x01\x02\x03")')
|
||||
"""
|
||||
from js import jsbytes
|
||||
((jsbytes.tolist() == [1, 2, 3])
|
||||
and (jsbytes.tobytes() == b"\x01\x02\x03"))
|
||||
""")
|
||||
assert selenium.run(
|
||||
'from js import jsfloats\n'
|
||||
'import struct\n'
|
||||
'expected = struct.pack("fff", 1, 2, 3)\n'
|
||||
'(jsfloats.tolist() == [1, 2, 3]) '
|
||||
'and (jsfloats.tobytes() == expected)')
|
||||
"""
|
||||
from js import jsfloats
|
||||
import struct
|
||||
expected = struct.pack("fff", 1, 2, 3)
|
||||
(jsfloats.tolist() == [1, 2, 3]) and (jsfloats.tobytes() == expected)
|
||||
""")
|
||||
assert selenium.run(
|
||||
'from js import jsobject\n'
|
||||
'str(jsobject) == "[object XMLHttpRequest]"')
|
||||
|
||||
|
||||
def test_typed_arrays(selenium):
|
||||
for wasm_heap in (False, True):
|
||||
for (jstype, pytype) in (
|
||||
('Int8Array', 'b'),
|
||||
('Uint8Array', 'B'),
|
||||
('Uint8ClampedArray', 'B'),
|
||||
('Int16Array', 'h'),
|
||||
('Uint16Array', 'H'),
|
||||
('Int32Array', 'i'),
|
||||
('Uint32Array', 'I'),
|
||||
('Float32Array', 'f'),
|
||||
('Float64Array', 'd')):
|
||||
print(wasm_heap, jstype, pytype)
|
||||
if not wasm_heap:
|
||||
selenium.run_js(
|
||||
f'window.array = new {jstype}([1, 2, 3, 4]);\n')
|
||||
else:
|
||||
selenium.run_js(
|
||||
'var buffer = pyodide._malloc('
|
||||
f'4 * {jstype}.BYTES_PER_ELEMENT);\n'
|
||||
f'window.array = new {jstype}('
|
||||
'pyodide.HEAPU8.buffer, buffer, 4);\n'
|
||||
'window.array[0] = 1;\n'
|
||||
'window.array[1] = 2;\n'
|
||||
'window.array[2] = 3;\n'
|
||||
'window.array[3] = 4;\n')
|
||||
assert selenium.run(
|
||||
'from js import array\n'
|
||||
'import struct\n'
|
||||
f'expected = struct.pack("{pytype*4}", 1, 2, 3, 4)\n'
|
||||
'print(array.format, array.tolist(), array.tobytes())\n'
|
||||
f'array.format == "{pytype}" '
|
||||
'and array.tolist() == [1, 2, 3, 4] '
|
||||
'and array.tobytes() == expected '
|
||||
f'and array.obj._has_bytes() is {not wasm_heap}')
|
||||
@pytest.mark.parametrize('wasm_heap', (False, True))
|
||||
@pytest.mark.parametrize(
|
||||
'jstype, pytype',
|
||||
(
|
||||
('Int8Array', 'b'),
|
||||
('Uint8Array', 'B'),
|
||||
('Uint8ClampedArray', 'B'),
|
||||
('Int16Array', 'h'),
|
||||
('Uint16Array', 'H'),
|
||||
('Int32Array', 'i'),
|
||||
('Uint32Array', 'I'),
|
||||
('Float32Array', 'f'),
|
||||
('Float64Array', 'd')))
|
||||
def test_typed_arrays(selenium, wasm_heap, jstype, pytype):
|
||||
if not wasm_heap:
|
||||
selenium.run_js(
|
||||
f'window.array = new {jstype}([1, 2, 3, 4]);\n')
|
||||
else:
|
||||
selenium.run_js(
|
||||
f"""
|
||||
var buffer = pyodide._malloc(
|
||||
4 * {jstype}.BYTES_PER_ELEMENT);
|
||||
window.array = new {jstype}(
|
||||
pyodide.HEAPU8.buffer, buffer, 4);
|
||||
window.array[0] = 1;
|
||||
window.array[1] = 2;
|
||||
window.array[2] = 3;
|
||||
window.array[3] = 4;
|
||||
""")
|
||||
assert selenium.run(
|
||||
f"""
|
||||
from js import array
|
||||
import struct
|
||||
expected = struct.pack("{pytype*4}", 1, 2, 3, 4)
|
||||
print(array.format, array.tolist(), array.tobytes())
|
||||
((array.format == "{pytype}")
|
||||
and array.tolist() == [1, 2, 3, 4]
|
||||
and array.tobytes() == expected
|
||||
and array.obj._has_bytes() is {not wasm_heap})
|
||||
""")
|
||||
|
||||
|
||||
def test_import_js(selenium):
|
||||
result = selenium.run(
|
||||
"from js import window\nwindow.title = 'Foo'\nwindow.title")
|
||||
"""
|
||||
from js import window
|
||||
window.title = 'Foo'
|
||||
window.title
|
||||
""")
|
||||
assert result == 'Foo'
|
||||
|
||||
|
||||
def test_pyproxy(selenium):
|
||||
selenium.run(
|
||||
"class Foo:\n"
|
||||
" bar = 42\n"
|
||||
" def get_value(self, value):\n"
|
||||
" return value * 64\n"
|
||||
"f = Foo()\n"
|
||||
"""
|
||||
class Foo:
|
||||
bar = 42
|
||||
def get_value(self, value):
|
||||
return value * 64
|
||||
f = Foo()
|
||||
"""
|
||||
)
|
||||
assert selenium.run_js("return pyodide.pyimport('f').get_value(2)") == 128
|
||||
assert selenium.run_js("return pyodide.pyimport('f').bar") == 42
|
||||
|
@ -188,18 +209,22 @@ def test_pyproxy(selenium):
|
|||
|
||||
def test_pyproxy_destroy(selenium):
|
||||
selenium.run(
|
||||
"class Foo:\n"
|
||||
" bar = 42\n"
|
||||
" def get_value(self, value):\n"
|
||||
" return value * 64\n"
|
||||
"f = Foo()\n"
|
||||
"""
|
||||
class Foo:
|
||||
bar = 42
|
||||
def get_value(self, value):
|
||||
return value * 64
|
||||
f = Foo()
|
||||
"""
|
||||
)
|
||||
try:
|
||||
selenium.run_js(
|
||||
"let f = pyodide.pyimport('f');\n"
|
||||
"console.assert(f.get_value(1) === 64);\n"
|
||||
"f.destroy();\n"
|
||||
"f.get_value();\n")
|
||||
"""
|
||||
let f = pyodide.pyimport('f');
|
||||
console.assert(f.get_value(1) === 64);
|
||||
f.destroy();
|
||||
f.get_value();
|
||||
""")
|
||||
except selenium.JavascriptException as e:
|
||||
assert 'Object has already been destroyed' in str(e)
|
||||
else:
|
||||
|
@ -208,10 +233,11 @@ def test_pyproxy_destroy(selenium):
|
|||
|
||||
def test_jsproxy(selenium):
|
||||
assert selenium.run(
|
||||
"from js import document\n"
|
||||
"el = document.createElement('div')\n"
|
||||
"document.body.appendChild(el)\n"
|
||||
"document.body.children.length\n"
|
||||
"""
|
||||
from js import document
|
||||
el = document.createElement('div')
|
||||
document.body.appendChild(el)
|
||||
document.body.children.length"""
|
||||
) == 1
|
||||
assert selenium.run(
|
||||
"document.body.children[0].tagName") == 'DIV'
|
||||
|
@ -229,50 +255,59 @@ def test_jsproxy(selenium):
|
|||
"from js import ImageData\n"
|
||||
"ImageData.typeof") == 'function'
|
||||
selenium.run_js(
|
||||
"class Point {\n"
|
||||
" constructor(x, y) {\n"
|
||||
" this.x = x;\n"
|
||||
" this.y = y;\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"window.TEST = new Point(42, 43);")
|
||||
"""
|
||||
class Point {
|
||||
constructor(x, y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
}
|
||||
window.TEST = new Point(42, 43);""")
|
||||
assert selenium.run(
|
||||
"from js import TEST\n"
|
||||
"del TEST.y\n"
|
||||
"TEST.y\n") is None
|
||||
"""
|
||||
from js import TEST
|
||||
del TEST.y
|
||||
TEST.y""") is None
|
||||
selenium.run_js(
|
||||
"class Point {\n"
|
||||
" constructor(x, y) {\n"
|
||||
" this.x = x;\n"
|
||||
" this.y = y;\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"window.TEST = new Point(42, 43);")
|
||||
"""
|
||||
class Point {
|
||||
constructor(x, y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
}
|
||||
window.TEST = new Point(42, 43);""")
|
||||
assert selenium.run(
|
||||
"from js import TEST\n"
|
||||
"del TEST['y']\n"
|
||||
"TEST['y']\n") is None
|
||||
"""
|
||||
from js import TEST
|
||||
del TEST['y']
|
||||
TEST['y']""") is None
|
||||
assert selenium.run(
|
||||
"from js import TEST\n"
|
||||
"TEST == TEST\n")
|
||||
"""
|
||||
from js import TEST
|
||||
TEST == TEST
|
||||
""")
|
||||
assert selenium.run(
|
||||
"from js import TEST\n"
|
||||
"TEST != 'foo'\n")
|
||||
"""
|
||||
from js import TEST
|
||||
TEST != 'foo'
|
||||
""")
|
||||
|
||||
|
||||
def test_jsproxy_iter(selenium):
|
||||
selenium.run_js(
|
||||
"function makeIterator(array) {\n"
|
||||
" var nextIndex = 0;\n"
|
||||
" return {\n"
|
||||
" next: function() {\n"
|
||||
" return nextIndex < array.length ?\n"
|
||||
" {value: array[nextIndex++], done: false} :\n"
|
||||
" {done: true};\n"
|
||||
" }\n"
|
||||
" };\n"
|
||||
"}\n"
|
||||
"window.ITER = makeIterator([1, 2, 3]);")
|
||||
"""
|
||||
function makeIterator(array) {
|
||||
var nextIndex = 0;
|
||||
return {
|
||||
next: function() {
|
||||
return nextIndex < array.length ?
|
||||
{value: array[nextIndex++], done: false} :
|
||||
{done: true};
|
||||
}
|
||||
};
|
||||
}
|
||||
window.ITER = makeIterator([1, 2, 3]);""")
|
||||
assert selenium.run(
|
||||
"from js import ITER\n"
|
||||
"list(ITER)") == [1, 2, 3]
|
||||
|
@ -280,8 +315,10 @@ def test_jsproxy_iter(selenium):
|
|||
|
||||
def test_open_url(selenium):
|
||||
assert selenium.run(
|
||||
"import pyodide\n"
|
||||
"pyodide.open_url('test_data.txt').read()\n") == 'HELLO\n'
|
||||
"""
|
||||
import pyodide
|
||||
pyodide.open_url('test_data.txt').read()
|
||||
""") == 'HELLO\n'
|
||||
|
||||
|
||||
def test_run_core_python_test(python_test, selenium, request):
|
||||
|
@ -296,13 +333,14 @@ def test_run_core_python_test(python_test, selenium, request):
|
|||
selenium.load_package('test')
|
||||
try:
|
||||
selenium.run(
|
||||
"from test.libregrtest import main\n"
|
||||
"try:\n"
|
||||
" main(['{}'], verbose=True, verbose3=True)\n"
|
||||
"except SystemExit as e:\n"
|
||||
" if e.code != 0:\n"
|
||||
" raise RuntimeError(f'Failed with code: {{e.code}}')\n"
|
||||
.format(name))
|
||||
"""
|
||||
from test.libregrtest import main
|
||||
try:
|
||||
main(['{}'], verbose=True, verbose3=True)
|
||||
except SystemExit as e:
|
||||
if e.code != 0:
|
||||
raise RuntimeError(f'Failed with code: {{e.code}}')
|
||||
""".format(name))
|
||||
except selenium.JavascriptException as e:
|
||||
print(selenium.logs)
|
||||
raise
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
def test_pytest(selenium):
|
||||
selenium.load_package('pytest')
|
||||
selenium.load_package('numpy')
|
||||
selenium.load_package('nose')
|
||||
selenium.run('from pathlib import Path')
|
||||
selenium.run('import os')
|
||||
selenium.run('import numpy')
|
||||
selenium.run('base_dir = Path(numpy.__file__).parent / "core" / "tests"')
|
||||
selenium.run("import pytest;"
|
||||
"pytest.main([base_dir / 'test_api.py'])")
|
||||
selenium.load_package(['pytest', 'numpy', 'nose'])
|
||||
|
||||
selenium.run(
|
||||
"""
|
||||
from pathlib import Path
|
||||
import os
|
||||
import numpy
|
||||
import pytest
|
||||
|
||||
base_dir = Path(numpy.__file__).parent / "core" / "tests"
|
||||
""")
|
||||
|
||||
selenium.run("pytest.main([base_dir / 'test_api.py'])")
|
||||
|
||||
logs = '\n'.join(selenium.logs)
|
||||
assert 'INTERNALERROR' not in logs
|
||||
|
|
Loading…
Reference in New Issue