1
0
Fork 0
mirror of https://github.com/mozilla/pdf.js.git synced 2025-04-20 15:18:08 +02:00

Use test.py for unit tests too.

This commit is contained in:
Brendan Dahl 2012-04-19 12:32:24 -07:00
parent cec7a92a99
commit e18a2c512e
17 changed files with 1115 additions and 658 deletions

View file

@ -39,9 +39,13 @@ class TestOptions(OptionParser):
default=False)
self.add_option("--port", action="store", dest="port", type="int",
help="The port the HTTP server should listen on.", default=8080)
self.add_option("--unitTest", action="store_true", dest="unitTest",
help="Run the unit tests.", default=False)
self.set_usage(USAGE_EXAMPLE)
def verifyOptions(self, options):
if options.reftest and options.unitTest:
self.error("--reftest and --unitTest must not be specified at the same time.")
if options.masterMode and options.manifestFile:
self.error("--masterMode and --manifestFile must not be specified at the same time.")
if not options.manifestFile:
@ -50,6 +54,7 @@ class TestOptions(OptionParser):
print "Warning: ignoring browser argument since manifest file was also supplied"
if not options.browser and not options.browserManifestFile:
print "Starting server on port %s." % options.port
return options
def prompt(question):
@ -86,6 +91,13 @@ class State:
eqLog = None
lastPost = { }
class UnitTestState:
browsers = [ ]
browsersRunning = 0
lastPost = { }
numErrors = 0
numRun = 0
class Result:
def __init__(self, snapshot, failure, page):
self.snapshot = snapshot
@ -95,8 +107,7 @@ class Result:
class TestServer(SocketServer.TCPServer):
allow_reuse_address = True
class PDFTestHandler(BaseHTTPRequestHandler):
class TestHandlerBase(BaseHTTPRequestHandler):
# Disable annoying noise by default
def log_request(code=0, size=0):
if VERBOSE:
@ -110,34 +121,6 @@ class PDFTestHandler(BaseHTTPRequestHandler):
with open(path, "rb") as f:
self.wfile.write(f.read())
def sendIndex(self, path, query):
if not path.endswith("/"):
# we need trailing slash
self.send_response(301)
redirectLocation = path + "/"
if query:
redirectLocation += "?" + query
self.send_header("Location", redirectLocation)
self.end_headers()
return
self.send_response(200)
self.send_header("Content-Type", "text/html")
self.end_headers()
if query == "frame":
self.wfile.write("<html><frameset cols=*,200><frame name=pdf>" +
"<frame src='" + path + "'></frameset></html>")
return
location = os.path.abspath(os.path.realpath(DOC_ROOT + os.sep + path))
self.wfile.write("<html><body><h1>PDFs of " + path + "</h1>\n")
for filename in os.listdir(location):
if filename.lower().endswith('.pdf'):
self.wfile.write("<a href='/web/viewer.html?file=" +
urllib.quote_plus(path + filename, '/') + "' target=pdf>" +
filename + "</a><br>\n")
self.wfile.write("</body></html>")
def do_GET(self):
url = urlparse(self.path)
# Ignore query string
@ -168,6 +151,70 @@ class PDFTestHandler(BaseHTTPRequestHandler):
self.sendFile(path, ext)
class UnitTestHandler(TestHandlerBase):
def sendIndex(self, path, query):
print "send index"
def do_POST(self):
numBytes = int(self.headers['Content-Length'])
self.send_response(200)
self.send_header('Content-Type', 'text/plain')
self.end_headers()
url = urlparse(self.path)
result = json.loads(self.rfile.read(numBytes))
browser = result['browser']
UnitTestState.lastPost[browser] = int(time.time())
if url.path == "/tellMeToQuit":
tellAppToQuit(url.path, url.query)
UnitTestState.browsersRunning -= 1
UnitTestState.lastPost[browser] = None
return
elif url.path == '/info':
print result['message']
elif url.path == '/submit_task_results':
status, description = result['status'], result['description']
UnitTestState.numRun += 1
if status == 'TEST-UNEXPECTED-FAIL':
UnitTestState.numErrors += 1
message = status + ' | ' + description + ' | in ' + browser
if 'error' in result:
message += ' | ' + result['error']
print message
else:
print 'Error: uknown action' + url.path
class PDFTestHandler(TestHandlerBase):
def sendIndex(self, path, query):
if not path.endswith("/"):
# we need trailing slash
self.send_response(301)
redirectLocation = path + "/"
if query:
redirectLocation += "?" + query
self.send_header("Location", redirectLocation)
self.end_headers()
return
self.send_response(200)
self.send_header("Content-Type", "text/html")
self.end_headers()
if query == "frame":
self.wfile.write("<html><frameset cols=*,200><frame name=pdf>" +
"<frame src='" + path + "'></frameset></html>")
return
location = os.path.abspath(os.path.realpath(DOC_ROOT + os.sep + path))
self.wfile.write("<html><body><h1>PDFs of " + path + "</h1>\n")
for filename in os.listdir(location):
if filename.lower().endswith('.pdf'):
self.wfile.write("<a href='/web/viewer.html?file=" +
urllib.quote_plus(path + filename, '/') + "' target=pdf>" +
filename + "</a><br>\n")
self.wfile.write("</body></html>")
def do_POST(self):
numBytes = int(self.headers['Content-Length'])
@ -354,6 +401,17 @@ def verifyPDFs(manifestList):
error = True
return not error
def getTestBrowsers(options):
testBrowsers = []
if options.browserManifestFile:
testBrowsers = makeBrowserCommands(options.browserManifestFile)
elif options.browser:
testBrowsers = [makeBrowserCommand({"path":options.browser, "name":None})]
if options.browserManifestFile or options.browser:
assert len(testBrowsers) > 0
return testBrowsers
def setUp(options):
# Only serve files from a pdf.js clone
assert not GIT_CLONE_CHECK or os.path.isfile('../src/pdf.js') and os.path.isdir('../.git')
@ -366,14 +424,7 @@ def setUp(options):
assert not os.path.isdir(TMPDIR)
testBrowsers = []
if options.browserManifestFile:
testBrowsers = makeBrowserCommands(options.browserManifestFile)
elif options.browser:
testBrowsers = [makeBrowserCommand({"path":options.browser, "name":None})]
if options.browserManifestFile or options.browser:
assert len(testBrowsers) > 0
testBrowsers = getTestBrowsers(options)
with open(options.manifestFile) as mf:
manifestList = json.load(mf)
@ -398,13 +449,23 @@ def setUp(options):
return testBrowsers
def startBrowsers(browsers, options):
def setUpUnitTests(options):
# Only serve files from a pdf.js clone
assert not GIT_CLONE_CHECK or os.path.isfile('../src/pdf.js') and os.path.isdir('../.git')
testBrowsers = getTestBrowsers(options)
UnitTestState.browsersRunning = len(testBrowsers)
for b in testBrowsers:
UnitTestState.lastPost[b.name] = int(time.time())
return testBrowsers
def startBrowsers(browsers, options, path):
for b in browsers:
b.setup()
print 'Launching', b.name
host = 'http://%s:%s' % (SERVER_HOST, options.port)
path = '/test/test_slave.html?'
qs = 'browser='+ urllib.quote(b.name) +'&manifestFile='+ urllib.quote(options.manifestFile)
qs = '?browser='+ urllib.quote(b.name) +'&manifestFile='+ urllib.quote(options.manifestFile)
qs += '&path=' + b.path
b.start(host + path + qs)
@ -576,7 +637,7 @@ def startReftest(browser, options):
def runTests(options, browsers):
t1 = time.time()
try:
startBrowsers(browsers, options)
startBrowsers(browsers, options, '/test/test_slave.html')
while not State.done:
for b in State.lastPost:
if State.remaining[b] > 0 and int(time.time()) - State.lastPost[b] > BROWSER_TIMEOUT:
@ -598,6 +659,30 @@ def runTests(options, browsers):
print "\nStarting reftest harness to examine %d eq test failures." % State.numEqFailures
startReftest(browsers[0], options)
def runUnitTests(options, browsers):
t1 = time.time()
try:
startBrowsers(browsers, options, '/test/unit/unit_test.html')
while UnitTestState.browsersRunning > 0:
for b in UnitTestState.lastPost:
if UnitTestState.lastPost[b] != None and int(time.time()) - UnitTestState.lastPost[b] > BROWSER_TIMEOUT:
print 'TEST-UNEXPECTED-FAIL | test failed', b, "has not responded in", BROWSER_TIMEOUT, "s"
UnitTestState.lastPost[b] = None
UnitTestState.browsersRunning -= 1
UnitTestState.numErrors += 1
time.sleep(1)
print ''
print 'Ran', UnitTestState.numRun, 'tests'
if UnitTestState.numErrors > 0:
print 'OHNOES! Some tests failed!'
print ' ', UnitTestState.numErrors, 'of', UnitTestState.numRun, 'failed'
else:
print 'All unit tests passed.'
finally:
teardownBrowsers(browsers)
t2 = time.time()
print "Unit test Runtime was", int(t2 - t1), "seconds"
def main():
optionParser = TestOptions()
options, args = optionParser.parse_args()
@ -605,23 +690,33 @@ def main():
if options == None:
sys.exit(1)
httpd = TestServer((SERVER_HOST, options.port), PDFTestHandler)
httpd.masterMode = options.masterMode
httpd_thread = threading.Thread(target=httpd.serve_forever)
httpd_thread.setDaemon(True)
httpd_thread.start()
if options.unitTest:
httpd = TestServer((SERVER_HOST, options.port), UnitTestHandler)
httpd_thread = threading.Thread(target=httpd.serve_forever)
httpd_thread.setDaemon(True)
httpd_thread.start()
browsers = setUp(options)
if len(browsers) > 0:
runTests(options, browsers)
browsers = setUpUnitTests(options)
if len(browsers) > 0:
runUnitTests(options, browsers)
else:
# just run the server
print "Running HTTP server. Press Ctrl-C to quit."
try:
while True:
time.sleep(1)
except (KeyboardInterrupt):
print "\nExiting."
httpd = TestServer((SERVER_HOST, options.port), PDFTestHandler)
httpd.masterMode = options.masterMode
httpd_thread = threading.Thread(target=httpd.serve_forever)
httpd_thread.setDaemon(True)
httpd_thread.start()
browsers = setUp(options)
if len(browsers) > 0:
runTests(options, browsers)
else:
# just run the server
print "Running HTTP server. Press Ctrl-C to quit."
try:
while True:
time.sleep(1)
except (KeyboardInterrupt):
print "\nExiting."
if __name__ == '__main__':
main()

View file

@ -1,116 +0,0 @@
# Create temporary profile directory name.
TEMP_PROFILE:=$(shell echo `pwd`)/test_reports/temp_profile
# These are the Firefox command line arguments.
FIREFOX_ARGS:=-no-remote -profile $(TEMP_PROFILE)
# These are the Chrome command line arguments.
CHROME_ARGS:=--user-data-dir=$(TEMP_PROFILE) --no-first-run --disable-sync
# Unit test uses the manifest from ref test to determine which browsers will
# be used for running the unit tests.
MANIFEST:=../resources/browser_manifests/browser_manifest.json
# This is a helper command to separate multiple browsers to their own lines
# for an easier sed operation.
SPLIT_LINES:=sed 's|,|,@|g' | tr '@' '\n'
# This is a helper command to join multiple lines together.
JOIN_LINES:=tr -d '\n'
# Fetch the paths to browsers that are going to be used in testing.
# For OS X the path to the binary needs to be added.
# Add the browser arguments for each browser.
# Create random profile directory for each browser.
BROWSERS_PATHS:=$(shell echo `\
sed -n 's|.*"path":\(.*\)|\1,|p' $(MANIFEST) | \
$(JOIN_LINES) \
`)
# The browser_manifest.json file has only the app directory for mac browsers.
# The absolute path to the browser binary needs to be used.
BROWSERS_PATHS_WITH_MAC_CORRECTION:=$(shell echo '$(BROWSERS_PATHS)' | \
$(SPLIT_LINES) | \
sed 's|\(Aurora\.app\)|\1/Contents/MacOS/firefox-bin|' | \
sed 's|\(Firefox.*\.app\)|\1/Contents/MacOS/firefox-bin|' | \
sed 's|\(Google Chrome\.app\)|\1/Contents/MacOS/Google Chrome|' | \
$(JOIN_LINES) \
)
# Replace " with @@@@ so that echoing do not destroy the quotation marks.
QUOTATION_MARK:=\"
SUBSTITUTE_FOR_QUOTATION_MARK:=@@@@
# Each of the browser can have their own separate arguments.
BROWSERS_WITH_ARGUMENTS:=$(shell echo '$(BROWSERS_PATHS_WITH_MAC_CORRECTION)' | \
$(SPLIT_LINES) | \
sed "s|\(irefox.*\)\($(QUOTATION_MARK)\),|\1;$(FIREFOX_ARGS)\2,|" | \
sed "s|\(hrome.*\)\($(QUOTATION_MARK)\),|\1;$(CHROME_ARGS)\2,|" | \
$(JOIN_LINES) \
)
# A temporary profile directory is needed for each of the browser. In this way
# a unit test run will not disturb the main browsing session of the user. The
# $RANDOM shell variable is used to generate non-conflicting temporary
# directories.
BROWSERS_WITH_UKNOWN_RANDOM_PROFILE_PATHS:=$(shell echo '$(BROWSERS_WITH_ARGUMENTS)' | \
$(SPLIT_LINES) | \
sed 's|\(temp_profile\)|\1_$$RANDOM$$RANDOM|' | \
sed "s|$(QUOTATION_MARK)|$(SUBSTITUTE_FOR_QUOTATION_MARK)|g" | \
$(JOIN_LINES) \
)
# Echo the variable so that the unknown random directories become known.
# Replace @@@@ with " so that jsTestDriver will work properly.
BROWSERS:=$(shell echo "$(BROWSERS_WITH_UKNOWN_RANDOM_PROFILE_PATHS)" | \
sed "s|$(SUBSTITUTE_FOR_QUOTATION_MARK)|$(QUOTATION_MARK)|g" \
)
# Get the known random directories for browsers. This information will be used
# to create the profile directories beforehand. Create also the dummy temp
# profile directory so that the mkdir command would not fail for browsers that
# do not need it.
PROFILES:=$(TEMP_PROFILE) $(shell echo '$(BROWSERS)' | \
$(SPLIT_LINES) | \
sed -n "s|.*\( $(TEMP_PROFILE)_[0-9]\+\).*|\1|p" | \
$(JOIN_LINES) \
)
# This is the command to invoke the unit test.
PROG:=java \
-Xms512m \
-Xmx1024m \
-jar ../../external/jsTestDriver/JsTestDriver-1.3.3d.jar \
--config ./jsTestDriver.conf \
--reset \
--port 4224 \
--browser $(BROWSERS) \
--tests all \
--testOutput ./test_reports/
# This default rule runs the unit tests with the constructed command.
test:
@mkdir -p $(PROFILES)
$(PROG)
@rm -rf $(PROFILES)
# In case this Makefile needs to be debugged then this rule will provide all
# the information from intermediate steps.
debug:
@echo 'Debug browsers paths: $(BROWSERS_PATHS)'
@echo
@echo 'Debug browsers paths with mac correction: $(BROWSERS_PATHS_WITH_MAC_CORRECTION)'
@echo
@echo 'Debug browsers with arguments: $(BROWSERS_WITH_ARGUMENTS)'
@echo
@echo 'Debug browsers random profile paths: $(BROWSERS_WITH_UKNOWN_RANDOM_PROFILE_PATHS)'
@echo
@echo 'Debug browsers: $(BROWSERS)'
@echo
@echo 'Debug profiles: $(PROFILES)'
@echo
@echo 'Command to be run: $(PROG)'
@echo
.phony:: test

View file

@ -6,11 +6,11 @@
describe('api', function() {
// TODO run with worker enabled
PDFJS.disableWorker = true;
var basicApiUrl = '/basicapi.pdf';
var basicApiUrl = '../pdfs/basicapi.pdf';
function waitsForPromise(promise) {
waitsFor(function() {
return promise.isResolved || promise.isRejected;
}, 250);
}, 1000);
}
function expectAfterPromise(promise, successCallback) {
waitsForPromise(promise);
@ -25,8 +25,6 @@ describe('api', function() {
describe('PDFJS', function() {
describe('getDocument', function() {
it('creates pdf doc from URL', function() {
console.log('what is');
debugger;
var promise = PDFJS.getDocument(basicApiUrl);
expectAfterPromise(promise, function(data) {
expect(true).toEqual(true);

View file

@ -1,39 +0,0 @@
server: http://localhost:4224
basepath: ..
load:
- ../external/jasmine/jasmine.js
- ../external/jasmineAdapter/JasmineAdapter.js
- ../src/obj.js
- ../src/core.js
- ../src/util.js
- ../src/api.js
- ../src/canvas.js
- ../src/obj.js
- ../src/function.js
- ../src/charsets.js
- ../src/cidmaps.js
- ../src/colorspace.js
- ../src/crypto.js
- ../src/evaluator.js
- ../src/fonts.js
- ../src/glyphlist.js
- ../src/image.js
- ../src/metrics.js
- ../src/parser.js
- ../src/pattern.js
- ../src/stream.js
- ../src/worker.js
- ../src/bidi.js
- ../src/metadata.js
- ../external/jpgjs/jpg.js
- unit/obj_spec.js
- unit/font_spec.js
- unit/function_spec.js
- unit/crypto_spec.js
- unit/stream_spec.js
- unit/api_spec.js
gateway:
- {matcher: "*.pdf", server: "http://localhost:8888/test/pdfs/"}

View file

@ -4,7 +4,21 @@
'use strict';
describe('stream', function() {
beforeEach(function() {
this.addMatchers({
toMatchTypedArray: function(expected) {
var actual = this.actual;
if (actual.length != expected.length)
return false;
for (var i = 0, ii = expected.length; i < ii; i++) {
var a = actual[i], b = expected[i];
if (a !== b)
return false;
}
return true;
}
});
});
describe('PredictorStream', function() {
it('should decode simple predictor data', function() {
var dict = new Dict();
@ -18,7 +32,7 @@ describe('stream', function() {
var predictor = new PredictorStream(input, dict);
var result = predictor.getBytes(6);
expect(result).toEqual(new Uint8Array([100, 3, 101, 2, 102, 1]));
expect(result).toMatchTypedArray(new Uint8Array([100, 3, 101, 2, 102, 1]));
});
});
});

View file

@ -1,3 +0,0 @@
TEST*
temp*

71
test/unit/testreporter.js Normal file
View file

@ -0,0 +1,71 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
var TestReporter = function(browser, appPath) {
function send(action, json) {
var r = new XMLHttpRequest();
// (The POST URI is ignored atm.)
r.open('POST', action, true);
r.setRequestHeader('Content-Type', 'application/json');
r.onreadystatechange = function sendTaskResultOnreadystatechange(e) {
if (r.readyState == 4) {
// Retry until successful
if (r.status !== 200)
send(action, json);
}
};
json['browser'] = browser;
r.send(JSON.stringify(json));
}
function sendInfo(message) {
send('/info', {message: message});
}
function sendResult(status, description, error) {
var message = {
status: status,
description: description
};
if (typeof error !== 'undefined')
message['error'] = error;
send('/submit_task_results', message);
}
function sendQuitRequest() {
send('/tellMeToQuit?path=' + escape(appPath), {});
}
this.now = function() {
return new Date().getTime();
};
this.reportRunnerStarting = function() {
this.runnerStartTime = this.now();
sendInfo('Started unit tests for ' + browser + '.');
};
this.reportSpecStarting = function() { };
this.reportSpecResults = function(spec) {
var results = spec.results();
if (results.skipped) {
sendResult('TEST-SKIPPED', results.description);
} else if (results.passed()) {
sendResult('TEST-PASSED', results.description);
} else {
var failedMessages = '';
var items = results.getItems();
for (var i = 0, ii = items.length; i < ii; i++)
if (!items[i].passed())
failedMessages += items[i].message + ' ';
sendResult('TEST-UNEXPECTED-FAIL', results.description, failedMessages);
}
};
this.reportSuiteResults = function(suite) { };
this.reportRunnerResults = function(runner) {
sendQuitRequest();
};
};

94
test/unit/unit_test.html Normal file
View file

@ -0,0 +1,94 @@
<!DOCTYPE html>
<html>
<head>
<title>pdf.js unit test</title>
<link rel="shortcut icon" type="image/png" href="../../external/jasmine/jasmine_favicon.png">
<link rel="stylesheet" type="text/css" href="../../external/jasmine/jasmine.css">
<script type="text/javascript" src="../../external/jasmine/jasmine.js"></script>
<script type="text/javascript" src="../../external/jasmine/jasmine-html.js"></script>
<script type="text/javascript" src="testreporter.js"></script>
<!-- include source files here... -->
<script type="text/javascript" src="../../src/core.js"></script>
<script type="text/javascript" src="../../src/api.js"></script>
<script type="text/javascript" src="../../src/util.js"></script>
<script type="text/javascript" src="../../src/canvas.js"></script>
<script type="text/javascript" src="../../src/obj.js"></script>
<script type="text/javascript" src="../../src/function.js"></script>
<script type="text/javascript" src="../../src/charsets.js"></script>
<script type="text/javascript" src="../../src/cidmaps.js"></script>
<script type="text/javascript" src="../../src/colorspace.js"></script>
<script type="text/javascript" src="../../src/crypto.js"></script>
<script type="text/javascript" src="../../src/evaluator.js"></script>
<script type="text/javascript" src="../../src/fonts.js"></script>
<script type="text/javascript" src="../../src/glyphlist.js"></script>
<script type="text/javascript" src="../../src/image.js"></script>
<script type="text/javascript" src="../../src/metrics.js"></script>
<script type="text/javascript" src="../../src/parser.js"></script>
<script type="text/javascript" src="../../src/pattern.js"></script>
<script type="text/javascript" src="../../src/stream.js"></script>
<script type="text/javascript" src="../../src/worker.js"></script>
<script type="text/javascript" src="../../src/metadata.js"></script>
<script type="text/javascript" src="../../external/jpgjs/jpg.js"></script>
<script type="text/javascript">PDFJS.workerSrc = '../../src/worker_loader.js';</script>
<!-- include spec files here... -->
<script type="text/javascript" src="obj_spec.js"></script>
<script type="text/javascript" src="font_spec.js"></script>
<script type="text/javascript" src="function_spec.js"></script>
<script type="text/javascript" src="crypto_spec.js"></script>
<script type="text/javascript" src="stream_spec.js"></script>
<script type="text/javascript" src="api_spec.js"></script>
<script type="text/javascript">
'use strict';
(function pdfJsUnitTest() {
function queryParams() {
var qs = window.location.search.substring(1);
var kvs = qs.split('&');
var params = { };
for (var i = 0; i < kvs.length; ++i) {
var kv = kvs[i].split('=');
params[unescape(kv[0])] = unescape(kv[1]);
}
return params;
}
var jasmineEnv = jasmine.getEnv();
jasmineEnv.updateInterval = 1000;
var trivialReporter = new jasmine.TrivialReporter();
jasmineEnv.addReporter(trivialReporter);
var params = queryParams();
if (params['browser']) {
var testReporter = new TestReporter(params['browser'], params['path']);
jasmineEnv.addReporter(testReporter);
}
jasmineEnv.specFilter = function pdfJsUnitTestSpecFilter(spec) {
return trivialReporter.specFilter(spec);
};
var currentWindowOnload = window.onload;
window.onload = function pdfJsUnitTestOnload() {
if (currentWindowOnload) {
currentWindowOnload();
}
execJasmine();
};
function execJasmine() {
jasmineEnv.execute();
}
})();
</script>
</head>
<body>
</body>
</html>