calibre/src/duktape/tests.py

206 lines
6.0 KiB
Python

import os
import sys
import tempfile
import unittest
from threading import Event, Thread
import dukpy
undefined, JSError, Context = dukpy.undefined, dukpy.JSError, dukpy.Context
class ContextTests(unittest.TestCase):
def setUp(self):
self.ctx = Context()
self.g = self.ctx.g
def test_create_context(self):
pass
def test_create_new_global_env(self):
new = self.ctx.new_global_env()
# The new context should have a distinct global object
self.g.a = 1
self.assertIs(new.g.a, undefined)
def test_eval(self):
pass
def test_eval_file(self):
pass
def test_undefined(self):
self.assertEqual(repr(undefined), 'undefined')
def test_roundtrip(self):
self.g.g = self.ctx.eval('function f() {return 1;}; f')
self.assertEqual(self.g.g.name, 'f')
self.g.a = self.ctx.eval('[1,2,3]')
self.assertEqual(self.g.a[2], 3)
class ValueTests(unittest.TestCase):
def setUp(self):
self.ctx = Context()
self.g = self.ctx.g
def test_simple(self):
for value in [undefined, None, True, False]:
self.g.value = value
self.assertIs(self.g.value, value)
for value in ["foo", 42, 3.141592, 3.141592e20]:
self.g.value = value
self.assertEqual(self.g.value, value)
def test_object(self):
self.g.value = {}
self.assertEqual(dict(self.g.value), {})
self.g.value = {'a': 1}
self.assertEqual(dict(self.g.value), {'a': 1})
self.g.value = {'a': {'b': 2}}
self.assertEqual(dict(self.g.value.a), {'b': 2})
def test_array(self):
self.g.value = []
self.assertEqual(list(self.g.value), [])
self.g.value = [0, 1, 2]
self.assertEqual(self.g.value[0], 0)
self.assertEqual(self.g.value[1], 1)
self.assertEqual(self.g.value[2], 2)
self.assertEqual(self.g.value[3], undefined)
self.assertEqual(list(self.g.value), [0, 1, 2])
self.assertEqual(len(self.g.value), 3)
self.g.value[1] = 9
self.assertEqual(self.g.value[0], 0)
self.assertEqual(self.g.value[1], 9)
self.assertEqual(self.g.value[2], 2)
self.assertEqual(self.g.value[3], undefined)
self.assertEqual(list(self.g.value), [0, 9, 2])
self.assertEqual(len(self.g.value), 3)
def test_callable(self):
def f(x):
return x * x
num = sys.getrefcount(f)
self.g.func = f
self.assertEqual(sys.getrefcount(f), num + 1)
self.assertEqual(self.g.func(123), 15129)
self.g.func = undefined
self.assertEqual(sys.getrefcount(f), num)
a = 13450234
def rval():
return a
num = sys.getrefcount(a)
self.g.func = rval
self.assertEqual(self.g.eval('func()'), a)
self.assertEqual(sys.getrefcount(a), num)
def bad():
raise Exception('testing a python exception xyz')
self.g.func = bad
val = self.g.eval('try{func();}catch(err) {err.message}')
self.assertTrue('testing a python exception xyz' in val)
self.assertTrue('bad at 0x' in val)
def test_proxy(self):
self.g.obj1 = {'a': 42}
self.g.obj2 = self.g.obj1
self.assertEqual(self.g.obj1.a, self.g.obj2.a)
self.ctx.eval('function f() {nonexistent()}')
try:
self.g.f()
self.assert_('No error raised for bad function')
except JSError as e:
e = e.args[0]
self.assertEqual('ReferenceError', e['name'])
self.assertIn('nonexistent', e['message'])
class EvalTests(unittest.TestCase):
def setUp(self):
self.ctx = Context()
self.g = self.ctx.g
with tempfile.NamedTemporaryFile(
prefix='dukpy-test-', suffix='.js', delete=False) as fobj:
fobj.write(b'1+1')
self.testfile = fobj.name
def tearDown(self):
os.remove(self.testfile)
def test_eval_invalid_args(self):
with self.assertRaises(TypeError):
self.ctx.eval()
with self.assertRaises(TypeError):
self.ctx.eval(123)
def test_eval(self):
self.assertEqual(self.ctx.eval("1+1"), 2)
def test_eval_kwargs(self):
self.assertEqual(self.ctx.eval(code="1+1"), 2)
def test_eval_errors(self):
try:
self.ctx.eval('1+/1')
self.assert_('No error raised for malformed js')
except JSError as e:
e = e.args[0]
self.assertEqual('SyntaxError', e['name'])
self.assertEqual('<eval>', e['fileName'])
self.assertEqual(1, e['lineNumber'])
self.assertIn('line 1', e['message'])
try:
self.ctx.eval('\na()', fname='xxx')
self.assert_('No error raised for malformed js')
except JSError as e:
e = e.args[0]
self.assertEqual('ReferenceError', e['name'])
self.assertEqual('xxx', e['fileName'])
self.assertEqual(2, e['lineNumber'])
def test_eval_multithreading(self):
ev = Event()
self.ctx.g.func = ev.wait
t = Thread(target=self.ctx.eval, args=('func()',))
t.daemon = True
t.start()
t.join(0.01)
self.assertTrue(t.is_alive())
ev.set()
t.join(1)
self.assertFalse(t.is_alive())
def test_eval_noreturn(self):
self.assertIsNone(self.ctx.eval("1+1", noreturn=True))
def test_eval_file_invalid_args(self):
with self.assertRaises(TypeError):
self.ctx.eval_file()
with self.assertRaises(TypeError):
self.ctx.eval_file(123)
def test_eval_file(self):
self.assertEqual(self.ctx.eval_file(self.testfile), 2)
def test_eval_file_kwargs(self):
self.assertEqual(self.ctx.eval_file(path=self.testfile), 2)
def test_eval_file_noreturn(self):
self.assertIsNone(self.ctx.eval_file(self.testfile, noreturn=True))