Commit af569129 authored by Michael Droettboom's avatar Michael Droettboom Committed by GitHub

Merge pull request #146 from rth/multi-line-code-snippets

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