blob: 2823f52da4f57b15761151bb7535b7cc20617d4d [file] [log] [blame]
# Copyright (c) 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import os
import re
import sys
import shutil
import tempfile
import unittest
from vinn import d8_runner
@unittest.skipIf(sys.platform.startswith('win'),
'd8 not yet supported on Windows.')
class D8RunnerUnittest(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.test_data_dir = os.path.abspath(
os.path.join(os.path.dirname(__file__), 'test_data'))
def GetTestFilePath(self, file_name):
return os.path.join(self.test_data_dir, file_name)
def AssertHasNamedFrame(self, func_name, file_and_linum, exception_message):
m = re.search('at %s.+\(.*%s.*\)' % (func_name, file_and_linum),
exception_message)
if not m:
sys.stderr.write('\n=============================================\n')
msg = "Expected to find %s and %s" % (func_name, file_and_linum)
sys.stderr.write('%s\n' % msg)
sys.stderr.write('=========== Begin Exception Message =========\n')
sys.stderr.write(exception_message)
sys.stderr.write('=========== End Exception Message =========\n\n')
self.fail(msg)
def AssertHasFrame(self, file_and_linum, exception_message):
m = re.search('at .*%s.*' % file_and_linum, exception_message)
if not m:
sys.stderr.write('\n=============================================\n')
msg = "Expected to find %s" % file_and_linum
sys.stderr.write('%s\n' % msg)
sys.stderr.write('=========== Begin Exception Message =========\n')
sys.stderr.write(exception_message)
sys.stderr.write('=========== End Exception Message =========\n\n')
self.fail(msg)
def testExecuteJsStringStdoutPiping(self):
tmp_dir = tempfile.mkdtemp()
try:
temp_file_name = os.path.join(tmp_dir, 'out_file')
with open(temp_file_name, 'w') as f:
d8_runner.ExcecuteJsString(
'print("Hello w0rld");\n', stdout=f)
with open(temp_file_name, 'r') as f:
self.assertEquals(f.read(), 'Hello w0rld\n')
finally:
shutil.rmtree(tmp_dir)
def testRunJsStringStdoutPiping(self):
tmp_dir = tempfile.mkdtemp()
try:
temp_file_name = os.path.join(tmp_dir, 'out_file')
with open(temp_file_name, 'w') as f:
d8_runner.RunJsString(
'print("Hello w0rld");\n', stdout=f)
with open(temp_file_name, 'r') as f:
self.assertEquals(f.read(), 'Hello w0rld\n')
finally:
shutil.rmtree(tmp_dir)
def testExecuteFileStdoutPiping(self):
file_path = self.GetTestFilePath('simple.js')
tmp_dir = tempfile.mkdtemp()
try:
temp_file_name = os.path.join(tmp_dir, 'out_file')
with open(temp_file_name, 'w') as f:
d8_runner.ExecuteFile(file_path, stdout=f)
with open(temp_file_name, 'r') as f:
self.assertEquals(f.read(), 'Hello W0rld from simple.js\n')
finally:
shutil.rmtree(tmp_dir)
def testRunFileStdoutPiping(self):
file_path = self.GetTestFilePath('simple.js')
tmp_dir = tempfile.mkdtemp()
try:
temp_file_name = os.path.join(tmp_dir, 'out_file')
with open(temp_file_name, 'w') as f:
d8_runner.RunFile(file_path, stdout=f)
with open(temp_file_name, 'r') as f:
self.assertEquals(f.read(), 'Hello W0rld from simple.js\n')
finally:
shutil.rmtree(tmp_dir)
def testSimpleJsExecution(self):
file_path = self.GetTestFilePath('print_file_content.js')
dummy_test_path = self.GetTestFilePath('dummy_test_file')
output = d8_runner.ExecuteFile(file_path, source_paths=[self.test_data_dir],
js_args=[dummy_test_path])
self.assertIn(
'This is file contains only data for testing.\n1 2 3 4', output)
def testJsFileLoadHtmlFile(self):
file_path = self.GetTestFilePath('load_simple_html.js')
output = d8_runner.ExecuteFile(file_path, source_paths=[self.test_data_dir])
expected_output = ('File foo.html is loaded\n'
'x = 1\n'
"File foo.html's second script is loaded\n"
'x = 2\n'
'load_simple_html.js is loaded\n')
self.assertEquals(output, expected_output)
def testJsFileLoadJsFile(self):
file_path = self.GetTestFilePath('load_simple_js.js')
output = d8_runner.ExecuteFile(file_path, source_paths=[self.test_data_dir])
expected_output = ('bar.js is loaded\n'
'load_simple_js.js is loaded\n')
self.assertEquals(output, expected_output)
def testHTMLFileLoadHTMLFile(self):
file_path = self.GetTestFilePath('load_simple_html.html')
output = d8_runner.ExecuteFile(
file_path, source_paths=[self.test_data_dir])
expected_output = ('File foo.html is loaded\n'
'x = 1\n'
"File foo.html's second script is loaded\n"
'x = 2\n'
'bar.js is loaded\n'
'File load_simple_html.html is loaded\n')
self.assertEquals(output, expected_output)
def testQuit0Handling(self):
file_path = self.GetTestFilePath('quit_0_test.js')
res = d8_runner.RunFile(file_path, source_paths=[self.test_data_dir])
self.assertEquals(res.returncode, 0)
def testQuit1Handling(self):
file_path = self.GetTestFilePath('quit_1_test.js')
res = d8_runner.RunFile(file_path, source_paths=[self.test_data_dir])
self.assertEquals(res.returncode, 1)
def testQuit42Handling(self):
file_path = self.GetTestFilePath('quit_42_test.js')
res = d8_runner.RunFile(file_path, source_paths=[self.test_data_dir])
self.assertEquals(res.returncode, 42)
def testQuit274Handling(self):
file_path = self.GetTestFilePath('quit_274_test.js')
res = d8_runner.RunFile(file_path, source_paths=[self.test_data_dir])
self.assertEquals(res.returncode, 238)
def testErrorStackTraceJs(self):
file_path = self.GetTestFilePath('error_stack_test.js')
# error_stack_test.js imports load_simple_html.html
# load_simple_html.html imports foo.html
# foo.html imports error.js
# error.js defines maybeRaiseException() method that can raise exception
# foo.html defines maybeRaiseExceptionInFoo() method that calls
# maybeRaiseException()
# Finally, we call maybeRaiseExceptionInFoo() error_stack_test.js
# Exception log should capture these method calls' stack trace.
with self.assertRaises(RuntimeError) as context:
d8_runner.ExecuteFile(file_path, source_paths=[self.test_data_dir])
# Assert error stack trace contain src files' info.
exception_message = context.exception.message
self.assertIn(
('error.js:7: Error: Throw ERROR\n'
" throw new Error('Throw ERROR');"), exception_message)
self.AssertHasNamedFrame('maybeRaiseException', 'error.js:7',
exception_message)
self.AssertHasNamedFrame('global.maybeRaiseExceptionInFoo', 'foo.html:34',
exception_message)
self.AssertHasFrame('error_stack_test.js:14', exception_message)
def testErrorStackTraceHTML(self):
file_path = self.GetTestFilePath('error_stack_test.html')
# error_stack_test.html imports error_stack_test.js
# error_stack_test.js imports load_simple_html.html
# load_simple_html.html imports foo.html
# foo.html imports error.js
# error.js defines maybeRaiseException() method that can raise exception
# foo.html defines maybeRaiseExceptionInFoo() method that calls
# maybeRaiseException()
# Finally, we call maybeRaiseExceptionInFoo() error_stack_test.js
# Exception log should capture these method calls' stack trace.
with self.assertRaises(RuntimeError) as context:
d8_runner.ExecuteFile(file_path, source_paths=[self.test_data_dir])
# Assert error stack trace contain src files' info.
exception_message = context.exception.message
self.assertIn(
('error.js:7: Error: Throw ERROR\n'
" throw new Error('Throw ERROR');"), exception_message)
self.AssertHasNamedFrame('maybeRaiseException', 'error.js:7',
exception_message)
self.AssertHasNamedFrame('global.maybeRaiseExceptionInFoo', 'foo.html:34',
exception_message)
self.AssertHasFrame('error_stack_test.js:14', exception_message)
self.AssertHasNamedFrame('eval', 'error_stack_test.html:22',
exception_message)
def testStackTraceOfErroWhenLoadingHTML(self):
file_path = self.GetTestFilePath('load_error.html')
with self.assertRaises(RuntimeError) as context:
d8_runner.ExecuteFile(file_path, source_paths=[self.test_data_dir])
# Assert error stack trace contain src files' info.
exception_message = context.exception.message
self.assertIn('Error: /does_not_exist.html not found', exception_message)
self.AssertHasNamedFrame('eval', 'load_error_2.html:21', exception_message)
self.AssertHasNamedFrame('eval', 'load_error.html:23', exception_message)
def testStackTraceOfErroWhenLoadingJS(self):
file_path = self.GetTestFilePath('load_js_error.html')
with self.assertRaises(RuntimeError) as context:
d8_runner.ExecuteFile(file_path, source_paths=[self.test_data_dir])
# Assert error stack trace contain src files' info.
exception_message = context.exception.message
self.assertIn('Error: /does_not_exist.js not found', exception_message)
self.AssertHasNamedFrame('eval', 'load_js_error_2.html:20',
exception_message)
self.AssertHasNamedFrame('eval', 'load_js_error.html:22',
exception_message)
def testConsolePolyfill(self):
self.assertEquals(
d8_runner.ExcecuteJsString('console.log("hello", "world");'),
'hello world\n')
self.assertEquals(
d8_runner.ExcecuteJsString('console.info("hello", "world");'),
'Info: hello world\n')
self.assertEquals(
d8_runner.ExcecuteJsString('console.warn("hello", "world");'),
'Warning: hello world\n')
self.assertEquals(
d8_runner.ExcecuteJsString('console.error("hello", "world");'),
'Error: hello world\n')
@unittest.skipIf(sys.platform.startswith('win'),
'd8 not yet supported on Windows.')
class PathUtilUnittest(unittest.TestCase):
def testPathUtil(self):
path_util_js_test = os.path.abspath(os.path.join(
os.path.dirname(__file__), 'path_utils_test.js'))
test_loading_js = """
load('%s');
load('%s');
runTests();
""" % (d8_runner._PATH_UTILS_JS_DIR, path_util_js_test)
res = d8_runner.RunJsString(test_loading_js)
self.assertEquals(res.returncode, 0)
def _GetLineNumberOfSubstring(content, substring):
""" Return the line number of |substring| in |content|."""
index = content.index(substring)
return content[:index].count('\n') + 1
def _GenerateLineByLineDiff(actual, expected):
results = []
expected_lines = expected.split('\n')
actual_lines = actual.split('\n')
max_num_lines = max(len(expected_lines), len(actual_lines))
results.append('**Actual : num lines = %i' % len(actual_lines))
results.append('**Expected : num lines = %i' % len(expected_lines))
for i in xrange(0, max_num_lines):
expected_current_line = expected_lines[i] if i < len(expected_lines) else ''
actual_current_line = actual_lines[i] if i < len(actual_lines) else ''
if actual_current_line == expected_current_line:
continue
results.append('================= Line %s ======================' % (i + 1))
results.append('**Actual : %s' % repr(actual_current_line))
results.append('**Expected : %s' % repr(expected_current_line))
return '\n'.join(results)
@unittest.skipIf(sys.platform.startswith('win'),
'd8 not yet supported on Windows.')
class HTMLGeneratorTest(unittest.TestCase):
def AssertStringEquals(self, actual, expected):
if actual != expected:
message = 'Expected %s but got %s.\n' % (repr(expected), repr(actual))
message += _GenerateLineByLineDiff(actual, expected)
self.fail(message)
def GetGeneratedJs(self, html_text):
tmp_dir = tempfile.mkdtemp()
try:
temp_file_name = os.path.join(tmp_dir, 'test.html')
with open(temp_file_name, 'w') as f:
f.write(html_text)
return d8_runner.ExcecuteJsString(
'write(generateJsFromHTML(read("%s")));' % temp_file_name)
finally:
shutil.rmtree(tmp_dir)
def testGenerateJsForD8RunnerSimpleHTMLImport(self):
html = '<link rel="import" href="/base/math.html">'
expected_js = "loadHTML('/base/math.html');"
self.AssertStringEquals(self.GetGeneratedJs(html), expected_js)
def testGenerateJSForD8RunnerImportMultilineHTMLImport(self):
html = """
<link rel="import"
href="/base/math.html">"""
expected_js = "\nloadHTML('/base/math.html');"
self.AssertStringEquals(self.GetGeneratedJs(html),
expected_js)
def testGenerateJsForD8RunnerImportSimpleScriptWithSrc(self):
html = '<script src="/base/math.js"></script>'
expected_js = "loadScript('/base/math.js');"
self.AssertStringEquals(self.GetGeneratedJs(html),
expected_js)
def testGenerateJsForD8RunnerImportMultilineScriptWithSrc(self):
html = """<script
type="text/javascript"
src="/base/math.js">
</script>"""
expected_js = """loadScript('/base/math.js');
"""
self.AssertStringEquals(self.GetGeneratedJs(html),
expected_js)
def testGenerateJsForD8RunnerWithMixedMultipleImport(self):
html = """
<link rel="import" href="/base.html"><link rel="import" href="/base64.html">
<link rel="import"
href="/base/math.html"><script
type="text/javascript"
src="/base/3d.js">
</script>
<script src="/base/math.js"></script>
<link rel="import"
href="/base/random.html">
"""
expected_js = ("""
loadHTML('/base.html');loadHTML('/base64.html');
loadHTML('/base/math.html');
loadScript('/base/3d.js');
""" + """
loadScript('/base/math.js');
loadHTML('/base/random.html');""")
self.AssertStringEquals(self.GetGeneratedJs(html),
expected_js)
def testGenerateJsForD8RunnerImportWithSimpleContent(self):
html = """<script>
var html_lines = [
'<script>',
'< /script>',
];
</script>
"""
expected_js = """
var html_lines = [
'<script>',
'< /script>',
];
"""
self.AssertStringEquals(self.GetGeneratedJs(html),
expected_js)
def testGenerateJsForD8RunnerImportWithEscapedScriptTag(self):
html = """<script>
var s = ("<") + "<\/script>";
var x = 100;
</script>
"""
expected_js = """
var s = ("<") + "<\/script>";
var x = 100;
"""
self.AssertStringEquals(self.GetGeneratedJs(html),
expected_js)
def testGenerateJsForD8RunnerImportWithSrcAndSimpleContent(self):
html = """<script
src="/base.js">var html_lines = [
'<script>',
'< /script>',
];
</script>
"""
expected_js = """loadScript('/base.js');
var html_lines = [
'<script>',
'< /script>',
];
"""
self.AssertStringEquals(self.GetGeneratedJs(html),
expected_js)
def testGenerateJsForD8RunnerImportComplex(self):
html = """<!DOCTYPE html>
<!--
Copyright (c) 2014 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
<link rel="import" href="/base/math.html"><script>var x = 1;</script>
<script src="/base/computer.js">
var linux = os.system; // line number of this is 9
</script>
<link rel="import" href="/base/physics.html">
<script>
var html_lines = [
'<script>',
'< /script>',
];
function foo() {
var y = [
1,
2, // line number of this is 21
3,
4
];
}
</script>
<link rel="import" href="/base/this_is_line_28.html">
<script>
var i = '<link rel="import" href="/base/math.html">';
</script>
"""
expected_js = """
loadHTML('/base/math.html');var x = 1;
loadScript('/base/computer.js');
var linux = os.system; // line number of this is 9
""" + """
loadHTML('/base/physics.html');
var html_lines = [
'<script>',
'< /script>',
];
function foo() {
var y = [
1,
2, // line number of this is 21
3,
4
];
}
""" + """
loadHTML('/base/this_is_line_28.html');
var i = '<link rel="import" href="/base/math.html">';
"""
generated_js = self.GetGeneratedJs(html)
self.AssertStringEquals(
_GetLineNumberOfSubstring(generated_js, '// line number of this is 9'),
9)
self.AssertStringEquals(
_GetLineNumberOfSubstring(generated_js, '// line number of this is 21'),
21)
self.AssertStringEquals(
_GetLineNumberOfSubstring(generated_js, 'this_is_line_28.html'),
28)
self.AssertStringEquals(generated_js, expected_js)