Permalink
Browse files

Got validation flow up and running

  • Loading branch information...
1 parent 54adc76 commit dd4a9c253af3ba6bae11b9979f8425951ea92a41 @mattbasta committed Aug 6, 2012
View
@@ -84,7 +84,7 @@ your environment.
Run the validator as follows ::
- python app-validator <path to app> [-o <output type>] [-v] [--boring] [--selfhosted] [--determined]
+ python app-validator <path to app> [-o <output type>] [-v] [--boring] [--selfhosted]
The path to the XPI should point to an XPI file.
@@ -97,10 +97,6 @@ The path to the XPI should point to an XPI file.
--selfhosted Disables messages that are specific to add-ons hosted on
AMO.
--boring Disables colorful shell output.
---determined Continue validating the remaining tiers of an add-on if one
- tier has failed. Certain high-tiered tests may
- inadvertently fail when this option is enabled for badly
- malformed add-ons.
Output Type:
============
View
@@ -1,6 +1,6 @@
#!/usr/bin/env python
-import validator.main
+import appvalidator.main
if __name__ == '__main__':
- validator.main.main()
+ appvalidator.main.main()
@@ -5,40 +5,17 @@
# Package type constants.
PACKAGE_ANY = 0
-PACKAGE_EXTENSION = 1
-PACKAGE_THEME = 2
-PACKAGE_DICTIONARY = 3
-PACKAGE_LANGPACK = 4
-PACKAGE_SEARCHPROV = 5
-PACKAGE_MULTI = 1 # A multi extension is an extension
-PACKAGE_SUBPACKAGE = 7
PACKAGE_WEBAPP = 8
-
-# Application GUIDs
-FIREFOX_GUID = "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"
-MOZILLA_GUID = "{86c18b42-e466-45a9-ae7a-9b95ba6f5640}"
-THUNDERBIRD_GUID = "{3550f703-e582-4d05-9a08-453d09bdfdc6}"
-SUNBIRD_GUID = "{718e30fb-e89b-41dd-9da7-e25a45638b28}"
-SEAMONKEY_GUID = "{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}"
-FENNEC_GUID = "{a23983c0-fd0e-11dc-95ff-0800200c9a66}"
-ANDROID_GUID = "{aa3c5121-dab2-40e2-81ca-7ea25febc110}"
-
-APPLICATIONS = {
- FIREFOX_GUID: "firefox",
- MOZILLA_GUID: "mozilla",
- THUNDERBIRD_GUID: "thunderbird",
- SUNBIRD_GUID: "sunbird",
- SEAMONKEY_GUID: "seamonkey",
- FENNEC_GUID: "fennec",
- ANDROID_GUID: "android",
-}
+PACKAGE_PACKAGED_WEBAPP = 9
SPIDERMONKEY_INSTALLATION = os.environ.get("SPIDERMONKEY_INSTALLATION")
DEFAULT_WEBAPP_MRKT_URLS = ["https://marketplace.mozilla.org",
"https://marketplace-dev.allizom.org"]
BUGZILLA_BUG = "https://bugzilla.mozilla.org/show_bug.cgi?id=%d"
+DEFAULT_TIMEOUT = 60
+
# Graciously provided by @kumar in bug 614574
if (not SPIDERMONKEY_INSTALLATION or
not os.path.exists(SPIDERMONKEY_INSTALLATION)):
@@ -60,4 +37,3 @@
from constants_local import *
except ImportError:
pass
-
View
@@ -5,7 +5,7 @@
import zipfile
from StringIO import StringIO
-from .validate import validate
+from .validate import validate_app, validate_packaged_app
from constants import *
@@ -38,11 +38,6 @@ def main():
const=True,
help="""Activating this flag will remove color
support from the terminal.""")
- parser.add_argument("--determined",
- action="store_const",
- const=True,
- help="""This flag will continue running tests in
- successive tests even if a lower tier fails.""")
parser.add_argument("--selfhosted",
action="store_const",
const=True,
@@ -56,26 +51,14 @@ def main():
args = parser.parse_args()
- # We want to make sure that the output is expected. Parse out the expected
- # type for the add-on and pass it in for validation.
- if args.type not in expectations:
- # Fail if the user provided invalid input.
- print "Given expectation (%s) not valid. See --help for details" % \
- args.type
- sys.exit(1)
-
try:
timeout = int(args.timeout)
except ValueError:
print "Invalid timeout. Integer expected."
sys.exit(1)
- expectation = expectations[args.type]
- error_bundle = validate(args.package,
- format=None,
- determined=args.determined,
- listed=not args.selfhosted,
- timeout=timeout)
+ error_bundle = validate_packaged_app(
+ args.package, listed=not args.selfhosted, format=None, timeout=timeout)
# Print the output of the tests based on the requested format.
if args.output == "text":
@@ -10,16 +10,6 @@
from constants import *
-types = {0: "Unknown",
- 1: "Extension/Multi-Extension",
- 2: "Theme",
- 3: "Dictionary",
- 4: "Language Pack",
- 5: "Search Provider"}
-
-assumed_extensions = {"jar": PACKAGE_THEME,
- "xml": PACKAGE_SEARCHPROV}
-
log = logging.getLogger()
@@ -39,29 +29,30 @@ def prepare_package(err, path, timeout=None):
If timeout is -1 then no timeout checking code will run.
"""
if not timeout:
- timeout = 60 # seconds
+ timeout = DEFAULT_TIMEOUT # seconds
# Test that the package actually exists. I consider this Tier 0
# since we may not even be dealing with a real file.
if not os.path.isfile(path):
- err.error(
+ return err.error(
err_id=("main", "prepare_package", "not_found"),
error="The package could not be found")
- return
# Pop the package extension.
package_extension = os.path.splitext(path)[1]
package_extension = package_extension.lower()
if package_extension == ".webapp":
- return test_webapp(err, path)
+ detect_webapp(err, path)
+ err.set_type(PACKAGE_WEBAPP)
+ return err
validation_state = {'complete': False}
def timeout_handler(signum, frame):
if validation_state['complete']:
# There is no need for a timeout. This might be the result of
# sequential validators, like in the test suite.
- return
+ return err
ex = ValidationTimeout(timeout)
log.error("%s; Package: %s" % (str(ex), path))
raise ex
@@ -70,18 +61,11 @@ def timeout_handler(signum, frame):
if timeout != -1:
signal.signal(signal.SIGALRM, timeout_handler)
signal.setitimer(signal.ITIMER_REAL, timeout)
- output = test_package(err, package, path)
+ test_package(err, package, path)
validation_state['complete'] = True
- return output
-
-
-def test_webapp(err, package):
- "Tests the package to see if it is a webapp."
-
- detect_webapp(err, package)
- err.set_type(PACKAGE_WEBAPP)
+ return err
def test_package(err, file_, name):
@@ -98,27 +82,26 @@ def test_package(err, file_, name):
except (BadZipfile, zlib_error):
# Die if the zip file is corrupt.
return err.error(
- err_id=("submain", "_load_install_rdf", "badzipfile"),
- error="Corrupt ZIP file",
- description="We were unable to decompress the zip file.")
+ err_id=("submain", "_load_install_rdf", "badzipfile"),
+ error="Corrupt ZIP file",
+ description="We were unable to decompress the zip file.")
try:
output = test_inner_package(err, package)
except ValidationTimeout as ex:
err.error(
- err_id=("main", "test_package", "timeout"),
- error="Validation timed out",
- description=["The validation process took too long to "
- "complete. Contact an addons.mozilla.org editor "
- "for more information.",
- str(ex)])
+ err_id=("main", "test_package", "timeout"),
+ error="Validation timed out",
+ description=["The validation process took too long to complete. "
+ "Contact an addons.mozilla.org editor for more "
+ "information.", str(ex)])
output = None
return output
def test_inner_package(err, package):
- "Tests a package's inner content."
+ """Tests a package's inner content."""
# Iterate through each tier.
for tier in sorted(decorator.get_tiers()):
@@ -6,7 +6,7 @@
import spidermonkey
import instanceactions
import instanceproperties
-from appvalidator.constants import BUGZILLA_BUG, FENNEC_GUID, FIREFOX_GUID
+from appvalidator.constants import BUGZILLA_BUG
from jstypes import *
@@ -1,8 +1,5 @@
from fnmatch import fnmatch as fnm
-from ..constants import (FIREFOX_GUID, FENNEC_GUID,
- THUNDERBIRD_GUID as TB_GUID, ANDROID_GUID,
- PACKAGE_DICTIONARY, )
from .. import decorator
# Detect blacklisted files based on their extension.
@@ -5,7 +5,7 @@
import javascript.traverser as traverser
from javascript.spidermonkey import get_tree, JSReflectException
-from appvalidator.constants import PACKAGE_THEME, SPIDERMONKEY_INSTALLATION
+from appvalidator.constants import SPIDERMONKEY_INSTALLATION
from ..contextgenerator import ContextGenerator
from ..textfilter import *
@@ -16,4 +16,3 @@ def filter_ascii(text):
if isinstance(text, list):
return [filter_ascii(x) for x in text]
return "".join((x if is_standard_ascii(x) else "?") for x in text)
-
@@ -23,11 +23,6 @@ def validate_app(data, listed=True, market_urls=None):
- App validation is always determined because there is only one tier.
- Spidermonkey paths are not accepted by this function because we don't
perform JavaScript validation on webapps.
- - We don't accept a flag for compatibility because there are no
- compatibility tests for apps, nor will there likely ever be. The same
- goes for associated parameters (i.e.: for_appversions).
- - `approved_applications` is not set because apps are not bound to
- individual Mozilla apps.
"""
bundle = ErrorBundle(listed=listed, determined=True)
@@ -38,6 +33,33 @@ def validate_app(data, listed=True, market_urls=None):
return format_result(bundle, "json")
+def validate_packaged_app(path, listed=True, format="json", market_urls=None,
+ timeout=None):
+ """
+ A handy function for validating apps.
+
+ `path`:
+ The path to the packaged app.
+ `listed`:
+ Whether the app is headed for the app marketplace.
+ `format`:
+ The output format to return the results in.
+ `market_urls`:
+ A list of URLs to use when validating the `installs_allowed_from`
+ field of the manifest. Does not apply if `listed` is not set to `True`.
+ `timeout`:
+ The amount of time (in seconds) that the validation process may take.
+ When this value is `None`, timeouts are disabled.
+ """
+ bundle = ErrorBundle(listed=listed)
+
+ # Set the market URLs.
+ set_market_urls(market_urls)
+
+ submain.prepare_package(bundle, path, timeout)
+ return format_result(bundle, format)
+
+
def format_result(bundle, format):
# Write the results to the pipe
formats = {"json": lambda b: b.render_json()}
View
@@ -15,15 +15,14 @@ class ZipPackage(object):
worry about things like zip files or IO.
"""
- def __init__(self, package, mode="r", name=None, subpackage=False):
+ def __init__(self, package, mode="r", name=None):
"Create a new managed XPI package"
self.zf = ZipFile(package, mode=mode)
# Store away the filename for future use.
self.filename = name or package
self.extension = self.filename.split(".")[-1]
- self.subpackage = subpackage
self.contents_cache = None
View
@@ -40,7 +40,7 @@ def reset(self):
"""
self.err = None
- def setup_err(self, for_appversions=None):
+ def setup_err(self):
"""
Instantiate the error bundle object. Use the `instant` parameter to
have it output errors as they're generated. `for_appversions` may be set
@@ -120,12 +120,11 @@ def namelist(self):
class MockXPI:
- def __init__(self, data=None, subpackage=False):
+ def __init__(self, data=None):
if not data:
data = {}
self.zf = MockZipFile()
self.data = data
- self.subpackage = subpackage
self.filename = "mock_xpi.xpi"
def test(self):
@@ -136,10 +135,8 @@ def info(self, name):
"extension": name.lower().split(".")[-1]}
def __iter__(self):
- def i():
- for name in self.data.keys():
- yield name
- return i()
+ for name in self.data.keys():
+ yield name
def __contains__(self, name):
return name in self.data
Oops, something went wrong.

0 comments on commit dd4a9c2

Please sign in to comment.