2011-12-06 00:19:57 +04:00
|
|
|
import logging
|
2010-08-03 02:35:00 +04:00
|
|
|
import os
|
2011-12-06 00:19:57 +04:00
|
|
|
import signal
|
2012-05-31 01:06:38 +04:00
|
|
|
from zipfile import BadZipfile
|
|
|
|
from zlib import error as zlib_error
|
2010-08-03 02:35:00 +04:00
|
|
|
|
2012-08-07 03:38:01 +04:00
|
|
|
import testcases
|
2012-08-02 02:43:36 +04:00
|
|
|
from .webapp import detect_webapp
|
2012-08-06 22:30:31 +04:00
|
|
|
from .zip import ZipPackage
|
2010-12-01 03:23:52 +03:00
|
|
|
|
|
|
|
from constants import *
|
2010-08-03 02:35:00 +04:00
|
|
|
|
2011-12-06 00:19:57 +04:00
|
|
|
log = logging.getLogger()
|
|
|
|
|
|
|
|
|
2011-12-21 04:50:26 +04:00
|
|
|
class ValidationTimeout(Exception):
|
|
|
|
|
|
|
|
def __init__(self, timeout):
|
|
|
|
self.timeout = timeout
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return "Validation timeout after %d seconds" % self.timeout
|
|
|
|
|
|
|
|
|
2012-08-06 22:30:31 +04:00
|
|
|
def prepare_package(err, path, timeout=None):
|
2011-12-06 01:46:46 +04:00
|
|
|
"""Prepares a file-based package for validation.
|
|
|
|
|
|
|
|
timeout is the number of seconds before validation is aborted.
|
2011-12-28 01:04:41 +04:00
|
|
|
If timeout is -1 then no timeout checking code will run.
|
2011-12-06 01:46:46 +04:00
|
|
|
"""
|
2011-12-06 00:58:09 +04:00
|
|
|
if not timeout:
|
2012-08-07 00:27:56 +04:00
|
|
|
timeout = DEFAULT_TIMEOUT # seconds
|
2010-08-03 02:35:00 +04:00
|
|
|
|
|
|
|
# Test that the package actually exists. I consider this Tier 0
|
|
|
|
# since we may not even be dealing with a real file.
|
2012-08-06 22:30:31 +04:00
|
|
|
if not os.path.isfile(path):
|
2012-08-07 00:27:56 +04:00
|
|
|
return err.error(
|
2012-08-06 22:30:31 +04:00
|
|
|
err_id=("main", "prepare_package", "not_found"),
|
|
|
|
error="The package could not be found")
|
2010-08-03 02:35:00 +04:00
|
|
|
|
|
|
|
# Pop the package extension.
|
|
|
|
package_extension = os.path.splitext(path)[1]
|
|
|
|
package_extension = package_extension.lower()
|
|
|
|
|
2012-08-06 22:30:31 +04:00
|
|
|
if package_extension == ".webapp":
|
2012-08-07 00:27:56 +04:00
|
|
|
detect_webapp(err, path)
|
|
|
|
return err
|
2010-08-03 02:35:00 +04:00
|
|
|
|
2011-12-06 01:46:46 +04:00
|
|
|
validation_state = {'complete': False}
|
2011-12-06 00:58:09 +04:00
|
|
|
def timeout_handler(signum, frame):
|
2011-12-06 01:46:46 +04:00
|
|
|
if validation_state['complete']:
|
2011-12-06 00:58:09 +04:00
|
|
|
# There is no need for a timeout. This might be the result of
|
|
|
|
# sequential validators, like in the test suite.
|
2012-08-07 00:27:56 +04:00
|
|
|
return err
|
2011-12-21 04:50:26 +04:00
|
|
|
ex = ValidationTimeout(timeout)
|
2013-07-11 19:40:04 +04:00
|
|
|
log.error("%s; Package: %s" % (str(ex), path), exc_info=True)
|
2011-12-21 04:50:26 +04:00
|
|
|
raise ex
|
2011-12-06 00:58:09 +04:00
|
|
|
|
2012-08-06 22:30:31 +04:00
|
|
|
with open(path, "rb") as package:
|
|
|
|
if timeout != -1:
|
|
|
|
signal.signal(signal.SIGALRM, timeout_handler)
|
|
|
|
signal.setitimer(signal.ITIMER_REAL, timeout)
|
2012-08-07 00:27:56 +04:00
|
|
|
test_package(err, package, path)
|
2012-08-06 22:30:31 +04:00
|
|
|
|
2011-12-06 01:46:46 +04:00
|
|
|
validation_state['complete'] = True
|
2010-08-03 02:35:00 +04:00
|
|
|
|
2012-08-07 00:27:56 +04:00
|
|
|
return err
|
2011-07-21 22:13:45 +04:00
|
|
|
|
|
|
|
|
2013-05-24 01:58:02 +04:00
|
|
|
def write_zip_error(err):
|
|
|
|
return err.error(
|
|
|
|
err_id=("submain", "badzipfile"),
|
|
|
|
error="Corrupt ZIP file",
|
|
|
|
description="We were unable to decompress all or part of the zip "
|
|
|
|
"file.")
|
|
|
|
|
|
|
|
|
2012-08-06 22:30:31 +04:00
|
|
|
def test_package(err, file_, name):
|
2012-08-07 02:53:10 +04:00
|
|
|
"""Begins tests for the package."""
|
2011-03-08 09:12:49 +03:00
|
|
|
|
2012-08-06 22:30:31 +04:00
|
|
|
# Load up a new instance of a package.
|
2011-05-24 02:12:14 +04:00
|
|
|
try:
|
2012-08-06 22:30:31 +04:00
|
|
|
package = ZipPackage(file_, mode="r", name=name)
|
2012-05-31 01:06:38 +04:00
|
|
|
except IOError:
|
2010-08-11 02:43:16 +04:00
|
|
|
# Die on this one because the file won't open.
|
2012-08-06 22:30:31 +04:00
|
|
|
return err.error(
|
|
|
|
err_id=("main", "test_package", "unopenable"),
|
|
|
|
error="The package could not be opened.")
|
2012-05-31 01:06:38 +04:00
|
|
|
except (BadZipfile, zlib_error):
|
|
|
|
# Die if the zip file is corrupt.
|
2013-05-24 01:58:02 +04:00
|
|
|
return write_zip_error(err)
|
2011-03-08 09:12:49 +03:00
|
|
|
|
2011-12-21 04:50:26 +04:00
|
|
|
try:
|
2012-08-06 22:30:31 +04:00
|
|
|
output = test_inner_package(err, package)
|
2011-12-21 04:50:26 +04:00
|
|
|
except ValidationTimeout as ex:
|
|
|
|
err.error(
|
2012-08-07 00:27:56 +04:00
|
|
|
err_id=("main", "test_package", "timeout"),
|
|
|
|
error="Validation timed out",
|
|
|
|
description=["The validation process took too long to complete. "
|
2013-02-05 08:26:05 +04:00
|
|
|
"Contact an Firefox Marketplace reviewer for more "
|
2012-08-07 00:27:56 +04:00
|
|
|
"information.", str(ex)])
|
2011-12-21 04:50:26 +04:00
|
|
|
output = None
|
|
|
|
|
|
|
|
return output
|
2010-08-03 02:35:00 +04:00
|
|
|
|
2011-03-08 09:12:49 +03:00
|
|
|
|
2012-08-06 22:30:31 +04:00
|
|
|
def test_inner_package(err, package):
|
2012-08-07 00:27:56 +04:00
|
|
|
"""Tests a package's inner content."""
|
2011-03-08 09:12:49 +03:00
|
|
|
|
2010-08-03 02:35:00 +04:00
|
|
|
# Iterate through each tier.
|
2012-08-07 03:38:01 +04:00
|
|
|
for tier in sorted(testcases._get_tiers()):
|
2010-10-22 04:46:47 +04:00
|
|
|
|
2011-04-23 08:30:31 +04:00
|
|
|
# Let the error bundler know what tier we're on.
|
2011-02-07 04:00:34 +03:00
|
|
|
err.set_tier(tier)
|
2010-10-22 04:46:47 +04:00
|
|
|
|
2011-04-23 08:30:31 +04:00
|
|
|
# Iterate through each test of our detected type.
|
2013-05-24 01:58:02 +04:00
|
|
|
try:
|
|
|
|
for test in testcases._get_tests(tier):
|
|
|
|
test(err, package)
|
|
|
|
except (BadZipfile, zlib_error):
|
|
|
|
write_zip_error(err)
|
2011-03-08 09:12:49 +03:00
|
|
|
|
2010-08-10 00:25:54 +04:00
|
|
|
# Return any errors at the end of the tier if undetermined.
|
2011-01-11 22:52:47 +03:00
|
|
|
if err.failed(fail_on_warnings=False) and not err.determined:
|
2010-08-18 04:27:37 +04:00
|
|
|
err.unfinished = True
|
2011-05-28 02:42:33 +04:00
|
|
|
err.discard_unused_messages(ending_tier=tier)
|
2010-08-03 02:35:00 +04:00
|
|
|
return err
|
2011-03-08 09:12:49 +03:00
|
|
|
|
2010-08-03 02:35:00 +04:00
|
|
|
# Return the results.
|
2010-10-10 13:18:03 +04:00
|
|
|
return err
|