From d869ac5bfcf1b886611fc84d0cdf4497bad2ce79 Mon Sep 17 00:00:00 2001 From: Roman Yurchak Date: Fri, 7 Sep 2018 14:01:58 +0200 Subject: [PATCH] Use multi-line code snippets in tests --- test/conftest.py | 7 ++ test/test_python.py | 288 ++++++++++++++++++++++++------------------- test/test_testing.py | 23 ++-- 3 files changed, 184 insertions(+), 134 deletions(-) diff --git a/test/conftest.py b/test/conftest.py index 9abca9395..970cc329f 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -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} }} diff --git a/test/test_python.py b/test/test_python.py index 8d11a5cb9..c4000ad3e 100644 --- a/test/test_python.py +++ b/test/test_python.py @@ -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 diff --git a/test/test_testing.py b/test/test_testing.py index 0808403f7..07b9b958a 100644 --- a/test/test_testing.py +++ b/test/test_testing.py @@ -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