diff -Nru click-reviewers-tools-0.19/bin/click-check-lint click-reviewers-tools-0.19/bin/click-check-lint
--- click-reviewers-tools-0.19/bin/click-check-lint 2014-10-15 09:06:00.000000000 +0000
+++ click-reviewers-tools-0.19/bin/click-check-lint 2014-11-21 15:31:17.000000000 +0000
@@ -16,6 +16,7 @@
# along with this program. If not, see .
from __future__ import print_function
+import json
import sys
import clickreviews.cr_common as cr_common
@@ -25,7 +26,14 @@
if len(sys.argv) < 2:
cr_common.error("Must give path to click package")
- review = cr_lint.ClickReviewLint(sys.argv[1])
+ # extract args
+ fn = sys.argv[1]
+ if len(sys.argv) > 2:
+ overrides = json.loads(sys.argv[2])
+ else:
+ overrides = None
+
+ review = cr_lint.ClickReviewLint(fn, overrides=overrides)
review.do_checks()
rc = review.do_report()
sys.exit(rc)
diff -Nru click-reviewers-tools-0.19/bin/click-check-security click-reviewers-tools-0.19/bin/click-check-security
--- click-reviewers-tools-0.19/bin/click-check-security 2014-10-15 09:06:00.000000000 +0000
+++ click-reviewers-tools-0.19/bin/click-check-security 2014-11-21 15:31:17.000000000 +0000
@@ -16,6 +16,7 @@
# along with this program. If not, see .
from __future__ import print_function
+import json
import sys
import clickreviews.cr_common as cr_common
@@ -25,7 +26,14 @@
if len(sys.argv) < 2:
cr_common.error("Must give path to click package")
- review = cr_security.ClickReviewSecurity(sys.argv[1])
+ # extract args
+ fn = sys.argv[1]
+ if len(sys.argv) > 2:
+ overrides = json.loads(sys.argv[2])
+ else:
+ overrides = None
+
+ review = cr_security.ClickReviewSecurity(fn, overrides=overrides)
review.do_checks()
rc = review.do_report()
sys.exit(rc)
diff -Nru click-reviewers-tools-0.19/bin/clickreviews/cr_desktop.py click-reviewers-tools-0.19/bin/clickreviews/cr_desktop.py
--- click-reviewers-tools-0.19/bin/clickreviews/cr_desktop.py 2014-10-15 09:06:00.000000000 +0000
+++ click-reviewers-tools-0.19/bin/clickreviews/cr_desktop.py 2014-11-21 15:31:17.000000000 +0000
@@ -54,6 +54,15 @@
# msg("Skipped missing desktop hook for account-qml-plugin"
# " '%s'" % app)
continue
+ elif 'systemd' in self.manifest['hooks'][app]:
+ # msg("Skipped missing desktop hook for systemd"
+ # " '%s'" % app)
+ continue
+ elif 'framework' in self.manifest['hooks'][app]:
+ # TODO: verify this is the long term hook name
+ # msg("Skipped missing desktop hook for framework"
+ # " '%s'" % app)
+ continue
else:
error("could not find desktop hook for '%s'" % app)
if not isinstance(self.manifest['hooks'][app]['desktop'], str):
@@ -327,19 +336,39 @@
s = 'OK'
found_url_patterns = False
found_model_search_path = False
+ found_named_webapp = False
+ urls = []
for i in de.getExec().split():
if i.startswith('--webappUrlPatterns'):
found_url_patterns = True
if i.startswith('--webappModelSearchPath'):
found_model_search_path = True
- if found_url_patterns and found_model_search_path:
- t = 'error'
- s = "should not specify --webappUrlPatterns when using " + \
- "--webappModelSearchPath"
- elif not found_url_patterns and not found_model_search_path:
- t = 'error'
- s = "must specify one of --webappUrlPatterns or " + \
- "--webappModelSearchPath"
+ if i.startswith('--webapp='):
+ found_model_search_path = True
+ if not i.startswith('--'):
+ urls.append(i)
+ is_launching_local_app = True
+ for url in urls:
+ parts = urlsplit(url)
+ if parts.scheme in ['http', 'https']:
+ is_launching_local_app = False
+ break
+ if is_launching_local_app and \
+ (found_url_patterns or found_model_search_path
+ or found_named_webapp):
+ t = 'error'
+ s = "should not specify --webappUrlPatterns, " + \
+ "--webappModelSearchPath or --webapp= when " + \
+ "running local application"
+ elif not is_launching_local_app:
+ if found_url_patterns and found_model_search_path:
+ t = 'error'
+ s = "should not specify --webappUrlPatterns when using " + \
+ "--webappModelSearchPath"
+ elif not found_url_patterns and not found_model_search_path:
+ t = 'error'
+ s = "must specify one of --webappUrlPatterns or " + \
+ "--webappModelSearchPath"
self._add_result(t, n, s)
def _check_patterns(self, app, patterns, args):
diff -Nru click-reviewers-tools-0.19/bin/clickreviews/cr_lint.py click-reviewers-tools-0.19/bin/clickreviews/cr_lint.py
--- click-reviewers-tools-0.19/bin/clickreviews/cr_lint.py 2014-10-15 09:06:00.000000000 +0000
+++ click-reviewers-tools-0.19/bin/clickreviews/cr_lint.py 2014-11-21 15:31:17.000000000 +0000
@@ -31,7 +31,7 @@
class ClickReviewLint(ClickReview):
'''This class represents click lint reviews'''
- def __init__(self, fn):
+ def __init__(self, fn, overrides=None):
'''Set up the class.'''
ClickReview.__init__(self, fn, "lint")
self.control_files = dict()
@@ -67,10 +67,17 @@
self.is_core_scope = (self.click_pkgname.startswith('com.ubuntu.scopes.')
and self.email ==
'ubuntu-devel-discuss@lists.ubuntu.com')
+ # "core snappy" is not necessarily a word we use right now, but
+ # we want to special case scopes which are written through our
+ # vetted development process.
+ self.is_core_snappy = (self.click_pkgname.startswith('com.ubuntu.snappy.')
+ and self.email ==
+ 'ubuntu-devel-discuss@lists.ubuntu.com')
else:
self.email = None
self.is_core_app = False
self.is_core_scope = False
+ self.is_core_snappy = False
self._list_all_compiled_binaries()
@@ -87,6 +94,9 @@
'urls']
self.redflagged_hooks = ['pay-ui']
+ if overrides is None:
+ overrides = {}
+ self.overrides = overrides
def _list_control_files(self):
'''List all control files with their full path.'''
@@ -589,6 +599,9 @@
elif self.is_core_scope:
t = 'info'
s = "OK ('com.ubuntu.scopes' uses '%s' as email)" % self.email
+ elif self.is_core_snappy:
+ t = 'info'
+ s = "OK ('com.ubuntu.snappy' uses '%s' as email)" % self.email
else:
t = 'error'
s = "email=%s does not match package domain=%s " \
@@ -641,9 +654,8 @@
'''Check framework()'''
n = 'framework'
l = "http://askubuntu.com/questions/460512/what-framework-should-i-use-in-my-manifest-file"
- local_copy = os.path.join(os.path.dirname(__file__),
- '../data/frameworks.json')
- frameworks = Frameworks(local_copy)
+ framework_overrides = self.overrides.get('framework', {})
+ frameworks = Frameworks(overrides=framework_overrides)
if self.manifest['framework'] in frameworks.AVAILABLE_FRAMEWORKS:
t = 'info'
s = 'OK'
diff -Nru click-reviewers-tools-0.19/bin/clickreviews/cr_scope.py click-reviewers-tools-0.19/bin/clickreviews/cr_scope.py
--- click-reviewers-tools-0.19/bin/clickreviews/cr_scope.py 2014-10-15 09:06:00.000000000 +0000
+++ click-reviewers-tools-0.19/bin/clickreviews/cr_scope.py 2014-11-21 15:31:17.000000000 +0000
@@ -17,8 +17,10 @@
from __future__ import print_function
from clickreviews.cr_common import ClickReview, error, msg
+import codecs
import configparser
import os
+import re
KNOWN_SECTIONS = set(["ScopeConfig", "Appearance"])
@@ -57,8 +59,8 @@
error("Could not find scope INI file '%s'" % ini_fn_bn)
try:
d["scope_config"] = configparser.ConfigParser()
- d["scope_config"].read(ini_fn)
- except Exception:
+ d["scope_config"].read_file(codecs.open(ini_fn, "r", "utf8"))
+ except Exception as e:
error("scope config unparseable: %s (%s)" % (ini_fn_bn, str(e)))
d["dir"] = fn
@@ -104,6 +106,9 @@
'resultsttltype',
'scoperunner',
'searchhint']
+ translated = ['description',
+ 'displayname',
+ 'searchhint']
missing = []
t = 'info'
@@ -128,9 +133,12 @@
n = 'ini_%s_scope_unknown_fields' % (app)
s = 'OK'
unknown = []
- for f in self.scopes[app]["scope_config"]['ScopeConfig'].keys():
- if f.lower() not in required and f.lower() not in optional:
- unknown.append(f.lower())
+ for i in self.scopes[app]["scope_config"]['ScopeConfig'].keys():
+ f = i.lower()
+ if f not in required and f not in optional and \
+ (f.split("[")[0] not in translated or not
+ re.search(r'.*\[[a-z][a-z](_[a-z][a-z])?\]$', f)):
+ unknown.append(f)
if len(unknown) == 1:
t = 'warn'
diff -Nru click-reviewers-tools-0.19/bin/clickreviews/cr_security.py click-reviewers-tools-0.19/bin/clickreviews/cr_security.py
--- click-reviewers-tools-0.19/bin/clickreviews/cr_security.py 2014-10-15 09:06:00.000000000 +0000
+++ click-reviewers-tools-0.19/bin/clickreviews/cr_security.py 2014-11-21 15:31:17.000000000 +0000
@@ -25,7 +25,7 @@
class ClickReviewSecurity(ClickReview):
'''This class represents click lint reviews'''
- def __init__(self, fn):
+ def __init__(self, fn, overrides=None):
ClickReview.__init__(self, fn, "security")
local_copy = os.path.join(os.path.dirname(__file__),
@@ -78,10 +78,21 @@
# framework policy is based on major framework version. In 13.10, there
# was only 'ubuntu-sdk-13.10', but in 14.04, there will be several,
# like 'ubuntu-sdk-14.04-html5', 'ubuntu-sdk-14.04-platform', etc
- self.major_framework_policy = {'ubuntu-sdk-13.10': 1.0,
- 'ubuntu-sdk-14.04': 1.1,
- 'ubuntu-sdk-14.10': 1.2,
- }
+ self.major_framework_policy = {
+ 'ubuntu-sdk-13.10': {
+ 'policy_version': 1.0,
+ },
+ 'ubuntu-sdk-14.04': {
+ 'policy_version': 1.1,
+ },
+ 'ubuntu-sdk-14.10': {
+ 'policy_version': 1.2,
+ },
+ }
+ if overrides is None:
+ overrides = {}
+ framework_overrides = overrides.get('framework', {})
+ self._override_framework_policies(framework_overrides)
self.security_manifests = dict()
self.security_apps = []
@@ -102,6 +113,23 @@
self._extract_security_manifest(app)
self.security_apps.append(app)
+ def _override_framework_policies(self, overrides):
+ # override major framework policies
+ self.major_framework_policy.update(overrides)
+
+ # override apparmor policies
+ for name, data in overrides.items():
+ vendor = data.get('policy_vendor')
+ version = str(data.get('policy_version'))
+
+ if vendor not in self.aa_policy:
+ self.aa_policy[vendor] = {}
+
+ if version not in self.aa_policy[vendor]:
+ # just ensure the version is defined
+ # TODO: add support to override templates and policy groups
+ self.aa_policy[vendor][version] = {}
+
def _extract_security_manifest(self, app):
'''Extract security manifest and verify it has the expected
structure'''
@@ -269,15 +297,15 @@
n = 'policy_version_matches_framework (%s)' % (f)
s = "OK"
found_major = False
- for k in self.major_framework_policy.keys():
+ for name, data in self.major_framework_policy.items():
# TODO: use libclick when it is available
- if not self.manifest['framework'].startswith(k):
+ if not self.manifest['framework'].startswith(name):
continue
found_major = True
- if m['policy_version'] != self.major_framework_policy[k]:
+ if m['policy_version'] != data['policy_version']:
t = 'error'
s = '%s != %s (%s)' % (str(m['policy_version']),
- self.major_framework_policy[k],
+ data['policy_version'],
self.manifest['framework'])
if not found_major:
t = 'error'
diff -Nru click-reviewers-tools-0.19/bin/clickreviews/frameworks.py click-reviewers-tools-0.19/bin/clickreviews/frameworks.py
--- click-reviewers-tools-0.19/bin/clickreviews/frameworks.py 2014-10-15 09:06:00.000000000 +0000
+++ click-reviewers-tools-0.19/bin/clickreviews/frameworks.py 2014-11-21 15:31:17.000000000 +0000
@@ -32,15 +32,21 @@
OBSOLETE_FRAMEWORKS = []
AVAILABLE_FRAMEWORKS = []
- def __init__(self, local_copy_fn=None):
+ def __init__(self, overrides=None):
self.FRAMEWORKS = clickreviews.remote.read_cr_file(USER_DATA_FILE,
- FRAMEWORKS_DATA_URL,
- local_copy_fn)
+ FRAMEWORKS_DATA_URL)
+ if overrides is not None:
+ self.FRAMEWORKS.update(overrides)
- for k, v in self.FRAMEWORKS.items():
- if v == 'deprecated':
- self.DEPRECATED_FRAMEWORKS.append(k)
- elif v == 'obsolete':
- self.OBSOLETE_FRAMEWORKS.append(k)
- elif v == 'available':
- self.AVAILABLE_FRAMEWORKS.append(k)
+ for name, data in self.FRAMEWORKS.items():
+ if type(data) is dict:
+ state = data.get('state')
+ else:
+ state = data
+
+ if state == 'deprecated':
+ self.DEPRECATED_FRAMEWORKS.append(name)
+ elif state == 'obsolete':
+ self.OBSOLETE_FRAMEWORKS.append(name)
+ elif state == 'available':
+ self.AVAILABLE_FRAMEWORKS.append(name)
diff -Nru click-reviewers-tools-0.19/bin/clickreviews/remote.py click-reviewers-tools-0.19/bin/clickreviews/remote.py
--- click-reviewers-tools-0.19/bin/clickreviews/remote.py 2014-10-15 09:06:00.000000000 +0000
+++ click-reviewers-tools-0.19/bin/clickreviews/remote.py 2014-11-21 15:31:17.000000000 +0000
@@ -28,7 +28,7 @@
def _update_is_necessary(fn):
return (not os.path.exists(fn)) or \
- (time.time() - os.path.getctime(fn) >= UPDATE_INTERVAL)
+ (time.time() - os.path.getmtime(fn) >= UPDATE_INTERVAL)
def _update_is_possible(url):
diff -Nru click-reviewers-tools-0.19/bin/clickreviews/tests/test_cr_desktop.py click-reviewers-tools-0.19/bin/clickreviews/tests/test_cr_desktop.py
--- click-reviewers-tools-0.19/bin/clickreviews/tests/test_cr_desktop.py 2014-10-15 09:06:00.000000000 +0000
+++ click-reviewers-tools-0.19/bin/clickreviews/tests/test_cr_desktop.py 2014-11-21 15:31:17.000000000 +0000
@@ -713,3 +713,57 @@
r = c.click_report
expected_counts = {'info': None, 'warn': 1, 'error': 0}
self.check_results(r, expected_counts)
+
+ def test_check_desktop_exec_webbrowser_local_app(self):
+ '''Test test_check_desktop_exec_webbrowser_local_app() local app'''
+ c = ClickReviewDesktop(self.test_name)
+ ex = "webapp-container ./www/index.html"
+ self.set_test_desktop(self.default_appname,
+ "Exec",
+ ex)
+ c.check_desktop_exec_webapp_args()
+ r = c.click_report
+ expected_counts = {'info': None, 'warn': 0, 'error': 0}
+ self.check_results(r, expected_counts)
+
+ def test_check_desktop_exec_webbrowser_local_pattern(self):
+ '''Test test_check_desktop_exec_webbrowser_local_pattern() invalid pattern'''
+ c = ClickReviewDesktop(self.test_name)
+ ex = "webapp-container " + \
+ "--webappUrlPatterns=https?://mobile.twitter.com/* " + \
+ "./www/index.html"
+ self.set_test_desktop(self.default_appname,
+ "Exec",
+ ex)
+ c.check_desktop_exec_webapp_args()
+ r = c.click_report
+ expected_counts = {'info': None, 'warn': 0, 'error': 1}
+ self.check_results(r, expected_counts)
+
+ def test_check_desktop_exec_webbrowser_local_webapp(self):
+ '''Test test_check_desktop_exec_webbrowser_local_webapp() invalid webapp cli'''
+ c = ClickReviewDesktop(self.test_name)
+ ex = "webapp-container " + \
+ "--webapp=DEADBEEF " + \
+ "./www/index.html"
+ self.set_test_desktop(self.default_appname,
+ "Exec",
+ ex)
+ c.check_desktop_exec_webapp_args()
+ r = c.click_report
+ expected_counts = {'info': None, 'warn': 0, 'error': 1}
+ self.check_results(r, expected_counts)
+
+ def test_check_desktop_exec_webbrowser_local_model(self):
+ '''Test test_check_desktop_exec_webbrowser_local_model() invalid model'''
+ c = ClickReviewDesktop(self.test_name)
+ ex = "webapp-container " + \
+ "--webappModelSearchPath=. " + \
+ "./www/index.html"
+ self.set_test_desktop(self.default_appname,
+ "Exec",
+ ex)
+ c.check_desktop_exec_webapp_args()
+ r = c.click_report
+ expected_counts = {'info': None, 'warn': 0, 'error': 1}
+ self.check_results(r, expected_counts)
diff -Nru click-reviewers-tools-0.19/bin/clickreviews/tests/test_cr_lint.py click-reviewers-tools-0.19/bin/clickreviews/tests/test_cr_lint.py
--- click-reviewers-tools-0.19/bin/clickreviews/tests/test_cr_lint.py 2014-10-15 09:06:00.000000000 +0000
+++ click-reviewers-tools-0.19/bin/clickreviews/tests/test_cr_lint.py 2014-11-21 15:31:17.000000000 +0000
@@ -18,6 +18,7 @@
from clickreviews.cr_lint import ClickReviewLint
from clickreviews.cr_lint import MINIMUM_CLICK_FRAMEWORK_VERSION
+from clickreviews.frameworks import FRAMEWORKS_DATA_URL, USER_DATA_FILE
import clickreviews.cr_tests as cr_tests
@@ -29,6 +30,21 @@
cr_tests.mock_patch()
super()
+ def patch_frameworks(self):
+ def _mock_frameworks(self, overrides=None):
+ self.FRAMEWORKS = {
+ 'ubuntu-sdk-14.10-qml-dev2': 'available',
+ 'ubuntu-sdk-13.10': 'deprecated',
+ 'ubuntu-sdk-14.10-qml-dev1': 'obsolete',
+ }
+ self.AVAILABLE_FRAMEWORKS = ['ubuntu-sdk-14.10-qml-dev2']
+ self.OBSOLETE_FRAMEWORKS = ['ubuntu-sdk-14.10-qml-dev1']
+ self.DEPRECATED_FRAMEWORKS = ['ubuntu-sdk-13.10']
+ p = patch('clickreviews.frameworks.Frameworks.__init__',
+ _mock_frameworks)
+ p.start()
+ self.addCleanup(p.stop)
+
def test_check_architecture(self):
'''Test check_architecture()'''
c = ClickReviewLint(self.test_name)
@@ -554,7 +570,7 @@
self.check_results(r, expected_counts)
def test_check_maintainer_email_special(self):
- '''Test check_maintainer() - ubuntu-devel-discuss@lists.ubuntu.com'''
+ '''Test check_maintainer() - ubuntu-devel-discuss@ - app'''
self.set_test_control("Package", "com.canonical.app")
self.set_test_manifest("maintainer",
"Ubuntu Core Developers "
@@ -575,7 +591,7 @@
self.check_results(r, expected=expected)
def test_check_maintainer_email_special2(self):
- '''Test check_maintainer() - ubuntu-devel-discuss@lists.ubuntu.com'''
+ '''Test check_maintainer() - ubuntu-devel-discuss@ - scope'''
self.set_test_control("Package", "com.ubuntu.scopes.youtube")
self.set_test_manifest("maintainer",
"Ubuntu Core Developers "
@@ -595,6 +611,27 @@
"'ubuntu-devel-discuss@lists.ubuntu.com' as email)"}
self.check_results(r, expected=expected)
+ def test_check_maintainer_email_special3(self):
+ '''Test check_maintainer() - ubuntu-devel-discuss@ - snappy'''
+ self.set_test_control("Package", "com.ubuntu.snappy.foo")
+ self.set_test_manifest("maintainer",
+ "Ubuntu Core Developers "
+ "")
+ c = ClickReviewLint(self.test_name)
+ c.check_maintainer()
+ r = c.click_report
+ expected_counts = {'info': None, 'warn': 0, 'error': 0}
+ self.check_results(r, expected_counts)
+
+ expected = dict()
+ expected['info'] = dict()
+ expected['warn'] = dict()
+ expected['error'] = dict()
+ expected['info']['lint_maintainer_domain'] = \
+ {"text": "OK ('com.ubuntu.snappy' uses "
+ "'ubuntu-devel-discuss@lists.ubuntu.com' as email)"}
+ self.check_results(r, expected=expected)
+
def test_check_icon(self):
'''Test check_icon()'''
self.set_test_manifest("icon", "someicon")
@@ -682,15 +719,33 @@
def test_check_framework(self):
'''Test check_framework()'''
+ self.patch_frameworks()
+ self.set_test_manifest("framework", "ubuntu-sdk-14.10-qml-dev2")
+ c = ClickReviewLint(self.test_name)
+ c.check_framework()
+ r = c.click_report
+ expected_counts = {'info': 1, 'warn': 0, 'error': 0}
+ self.check_results(r, expected_counts)
+
+ @patch('clickreviews.remote.read_cr_file')
+ def test_check_framework_fetches_remote_data(self, mock_read_cr_file):
+ '''Test check_framework()'''
+ mock_read_cr_file.return_value = {
+ 'ubuntu-sdk-14.10-qml-dev2': 'available',
+ }
self.set_test_manifest("framework", "ubuntu-sdk-14.10-qml-dev2")
c = ClickReviewLint(self.test_name)
c.check_framework()
r = c.click_report
expected_counts = {'info': 1, 'warn': 0, 'error': 0}
self.check_results(r, expected_counts)
+ # ensure no local fn is provided when reading frameworks
+ mock_read_cr_file.assert_called_once_with(
+ USER_DATA_FILE, FRAMEWORKS_DATA_URL)
def test_check_framework_bad(self):
'''Test check_framework() - bad'''
+ self.patch_frameworks()
self.set_test_manifest("framework", "nonexistent")
c = ClickReviewLint(self.test_name)
c.check_framework()
@@ -700,6 +755,7 @@
def test_check_framework_deprecated(self):
'''Test check_framework() - deprecated'''
+ self.patch_frameworks()
self.set_test_manifest("framework", "ubuntu-sdk-13.10")
c = ClickReviewLint(self.test_name)
c.check_framework()
@@ -709,6 +765,7 @@
def test_check_framework_obsolete(self):
'''Test check_framework() - obsolete'''
+ self.patch_frameworks()
self.set_test_manifest("framework", "ubuntu-sdk-14.10-qml-dev1")
c = ClickReviewLint(self.test_name)
c.check_framework()
@@ -716,6 +773,34 @@
expected_counts = {'info': None, 'warn': 0, 'error': 1}
self.check_results(r, expected_counts)
+ @patch('clickreviews.remote.read_cr_file')
+ def test_check_framework_with_overrides(self, mock_read_cr_file):
+ '''Test check_framework() - using overrides'''
+ mock_read_cr_file.return_value = {
+ 'ubuntu-sdk-14.10-qml-dev2': 'available',
+ }
+ self.set_test_manifest("framework", "nonexistent")
+ overrides = {'framework': {'nonexistent': {'state': 'available'}}}
+ c = ClickReviewLint(self.test_name, overrides=overrides)
+ c.check_framework()
+ r = c.click_report
+ expected_counts = {'info': 1, 'warn': 0, 'error': 0}
+ self.check_results(r, expected_counts)
+
+ @patch('clickreviews.remote.read_cr_file')
+ def test_check_framework_with_malformed_overrides(self, mock_read_cr_file):
+ '''Test check_framework() - using overrides'''
+ mock_read_cr_file.return_value = {
+ 'ubuntu-sdk-14.10-qml-dev2': 'available',
+ }
+ self.set_test_manifest("framework", "nonexistent")
+ overrides = {'nonexistent': {'state': 'available'}}
+ c = ClickReviewLint(self.test_name, overrides=overrides)
+ c.check_framework()
+ r = c.click_report
+ expected_counts = {'info': 0, 'warn': 0, 'error': 1}
+ self.check_results(r, expected_counts)
+
def test_check_hooks(self):
'''Test check_hooks()'''
self.set_test_manifest("framework", "ubuntu-sdk-13.10")
diff -Nru click-reviewers-tools-0.19/bin/clickreviews/tests/test_cr_scope.py click-reviewers-tools-0.19/bin/clickreviews/tests/test_cr_scope.py
--- click-reviewers-tools-0.19/bin/clickreviews/tests/test_cr_scope.py 2014-10-15 09:06:00.000000000 +0000
+++ click-reviewers-tools-0.19/bin/clickreviews/tests/test_cr_scope.py 2014-11-21 15:31:17.000000000 +0000
@@ -123,6 +123,45 @@
expected_counts = {'info': None, 'warn': 0, 'error': 1}
self.check_results(r, expected_counts)
+ def test_check_scope_ini_translated_field(self):
+ '''Test check_scope_ini() - translated field - es'''
+ config = self._stub_config()
+ config['searchhint[es]'] = "foo"
+ scope = self._create_scope(config)
+
+ self.set_test_scope(self.default_appname, scope)
+ c = ClickReviewScope(self.test_name)
+ c.check_scope_ini()
+ r = c.click_report
+ expected_counts = {'info': None, 'warn': 0, 'error': 0}
+ self.check_results(r, expected_counts)
+
+ def test_check_scope_ini_translated_field2(self):
+ '''Test check_scope_ini() - translated field - pt_br'''
+ config = self._stub_config()
+ config['searchhint[pt_br]'] = "foo"
+ scope = self._create_scope(config)
+
+ self.set_test_scope(self.default_appname, scope)
+ c = ClickReviewScope(self.test_name)
+ c.check_scope_ini()
+ r = c.click_report
+ expected_counts = {'info': None, 'warn': 0, 'error': 0}
+ self.check_results(r, expected_counts)
+
+ def test_check_scope_ini_bad_translated_field(self):
+ '''Test check_scope_ini() - bad translated field'''
+ config = self._stub_config()
+ config['searchhint[ba;r]'] = "foo"
+ scope = self._create_scope(config)
+
+ self.set_test_scope(self.default_appname, scope)
+ c = ClickReviewScope(self.test_name)
+ c.check_scope_ini()
+ r = c.click_report
+ expected_counts = {'info': None, 'warn': 1, 'error': 0}
+ self.check_results(r, expected_counts)
+
def test_check_scope_ini_nonexistent_field(self):
'''Test check_scope_ini() - non-existent field'''
config = self._stub_config()
diff -Nru click-reviewers-tools-0.19/bin/clickreviews/tests/test_cr_security.py click-reviewers-tools-0.19/bin/clickreviews/tests/test_cr_security.py
--- click-reviewers-tools-0.19/bin/clickreviews/tests/test_cr_security.py 2014-10-15 09:06:00.000000000 +0000
+++ click-reviewers-tools-0.19/bin/clickreviews/tests/test_cr_security.py 2014-11-21 15:31:17.000000000 +0000
@@ -136,7 +136,7 @@
policy_version = 0
for k in tmp.major_framework_policy.keys():
if f.startswith(k):
- policy_version = tmp.major_framework_policy[k]
+ policy_version = tmp.major_framework_policy[k]['policy_version']
self.set_test_security_manifest(self.default_appname,
"policy_version",
policy_version)
@@ -209,6 +209,36 @@
{"text": "Invalid framework 'nonexistent'"}
self.check_results(report, expected=expected)
+ def test_check_policy_version_framework_with_overrides(self):
+ '''Test check_policy_version() - override framework (nonexistent)'''
+ self.set_test_manifest("framework", "nonexistent")
+ self.set_test_security_manifest(self.default_appname,
+ "policy_version", 1.3)
+ overrides = {'framework': {'nonexistent': {'state': 'available',
+ 'policy_vendor': 'ubuntu',
+ 'policy_version': 1.3}}}
+ c = ClickReviewSecurity(self.test_name, overrides=overrides)
+ c.check_policy_version()
+ report = c.click_report
+
+ expected_counts = {'info': 3, 'warn': 0, 'error': 0}
+ self.check_results(report, expected_counts)
+
+ def test_check_policy_version_framework_with_malformed_overrides(self):
+ '''Test check_policy_version() - incorrectly override framework'''
+ self.set_test_manifest("framework", "nonexistent")
+ self.set_test_security_manifest(self.default_appname,
+ "policy_version", 1.3)
+ overrides = {'nonexistent': {'state': 'available',
+ 'policy_vendor': 'ubuntu',
+ 'policy_version': 1.3}}
+ c = ClickReviewSecurity(self.test_name, overrides=overrides)
+ c.check_policy_version()
+ report = c.click_report
+
+ expected_counts = {'info': 1, 'warn': 0, 'error': 2}
+ self.check_results(report, expected_counts)
+
def test_check_policy_vendor_unspecified(self):
'''Test check_policy_vendor() - unspecified'''
c = ClickReviewSecurity(self.test_name)
diff -Nru click-reviewers-tools-0.19/bin/clickreviews/tests/test_remote.py click-reviewers-tools-0.19/bin/clickreviews/tests/test_remote.py
--- click-reviewers-tools-0.19/bin/clickreviews/tests/test_remote.py 1970-01-01 00:00:00.000000000 +0000
+++ click-reviewers-tools-0.19/bin/clickreviews/tests/test_remote.py 2014-11-21 15:31:17.000000000 +0000
@@ -0,0 +1,38 @@
+import time
+from unittest import TestCase
+from unittest.mock import patch
+
+from clickreviews.remote import UPDATE_INTERVAL, _update_is_necessary
+
+
+class RemoteTestCase(TestCase):
+ def patch_path(self):
+ p = patch('clickreviews.remote.os.path')
+ self.mock_path = p.start()
+ self.addCleanup(p.stop)
+
+ def patch_time(self, now):
+ p = patch('clickreviews.remote.time.time')
+ self.mock_time = p.start()
+ self.mock_time.return_value = now
+ self.addCleanup(p.stop)
+
+ def test_no_update_needed(self):
+ now = time.time()
+ self.patch_time(now)
+ self.patch_path()
+
+ # last update was 10 seconds ago
+ self.mock_path.getmtime.return_value = now - 10
+
+ self.assertFalse(_update_is_necessary('some-file'))
+
+ def test_update_needed(self):
+ now = time.time()
+ self.patch_time(now)
+ self.patch_path()
+
+ # last update was UPDATE_INTERVAL + 10 seconds ago
+ self.mock_path.getmtime.return_value = now - UPDATE_INTERVAL - 10
+
+ self.assertTrue(_update_is_necessary('some-file'))
diff -Nru click-reviewers-tools-0.19/clickreviews/cr_desktop.py click-reviewers-tools-0.19/clickreviews/cr_desktop.py
--- click-reviewers-tools-0.19/clickreviews/cr_desktop.py 2014-10-15 09:06:00.000000000 +0000
+++ click-reviewers-tools-0.19/clickreviews/cr_desktop.py 2014-11-21 15:31:17.000000000 +0000
@@ -54,6 +54,15 @@
# msg("Skipped missing desktop hook for account-qml-plugin"
# " '%s'" % app)
continue
+ elif 'systemd' in self.manifest['hooks'][app]:
+ # msg("Skipped missing desktop hook for systemd"
+ # " '%s'" % app)
+ continue
+ elif 'framework' in self.manifest['hooks'][app]:
+ # TODO: verify this is the long term hook name
+ # msg("Skipped missing desktop hook for framework"
+ # " '%s'" % app)
+ continue
else:
error("could not find desktop hook for '%s'" % app)
if not isinstance(self.manifest['hooks'][app]['desktop'], str):
@@ -327,19 +336,39 @@
s = 'OK'
found_url_patterns = False
found_model_search_path = False
+ found_named_webapp = False
+ urls = []
for i in de.getExec().split():
if i.startswith('--webappUrlPatterns'):
found_url_patterns = True
if i.startswith('--webappModelSearchPath'):
found_model_search_path = True
- if found_url_patterns and found_model_search_path:
- t = 'error'
- s = "should not specify --webappUrlPatterns when using " + \
- "--webappModelSearchPath"
- elif not found_url_patterns and not found_model_search_path:
- t = 'error'
- s = "must specify one of --webappUrlPatterns or " + \
- "--webappModelSearchPath"
+ if i.startswith('--webapp='):
+ found_model_search_path = True
+ if not i.startswith('--'):
+ urls.append(i)
+ is_launching_local_app = True
+ for url in urls:
+ parts = urlsplit(url)
+ if parts.scheme in ['http', 'https']:
+ is_launching_local_app = False
+ break
+ if is_launching_local_app and \
+ (found_url_patterns or found_model_search_path
+ or found_named_webapp):
+ t = 'error'
+ s = "should not specify --webappUrlPatterns, " + \
+ "--webappModelSearchPath or --webapp= when " + \
+ "running local application"
+ elif not is_launching_local_app:
+ if found_url_patterns and found_model_search_path:
+ t = 'error'
+ s = "should not specify --webappUrlPatterns when using " + \
+ "--webappModelSearchPath"
+ elif not found_url_patterns and not found_model_search_path:
+ t = 'error'
+ s = "must specify one of --webappUrlPatterns or " + \
+ "--webappModelSearchPath"
self._add_result(t, n, s)
def _check_patterns(self, app, patterns, args):
diff -Nru click-reviewers-tools-0.19/clickreviews/cr_lint.py click-reviewers-tools-0.19/clickreviews/cr_lint.py
--- click-reviewers-tools-0.19/clickreviews/cr_lint.py 2014-10-15 09:06:00.000000000 +0000
+++ click-reviewers-tools-0.19/clickreviews/cr_lint.py 2014-11-21 15:31:17.000000000 +0000
@@ -31,7 +31,7 @@
class ClickReviewLint(ClickReview):
'''This class represents click lint reviews'''
- def __init__(self, fn):
+ def __init__(self, fn, overrides=None):
'''Set up the class.'''
ClickReview.__init__(self, fn, "lint")
self.control_files = dict()
@@ -67,10 +67,17 @@
self.is_core_scope = (self.click_pkgname.startswith('com.ubuntu.scopes.')
and self.email ==
'ubuntu-devel-discuss@lists.ubuntu.com')
+ # "core snappy" is not necessarily a word we use right now, but
+ # we want to special case scopes which are written through our
+ # vetted development process.
+ self.is_core_snappy = (self.click_pkgname.startswith('com.ubuntu.snappy.')
+ and self.email ==
+ 'ubuntu-devel-discuss@lists.ubuntu.com')
else:
self.email = None
self.is_core_app = False
self.is_core_scope = False
+ self.is_core_snappy = False
self._list_all_compiled_binaries()
@@ -87,6 +94,9 @@
'urls']
self.redflagged_hooks = ['pay-ui']
+ if overrides is None:
+ overrides = {}
+ self.overrides = overrides
def _list_control_files(self):
'''List all control files with their full path.'''
@@ -589,6 +599,9 @@
elif self.is_core_scope:
t = 'info'
s = "OK ('com.ubuntu.scopes' uses '%s' as email)" % self.email
+ elif self.is_core_snappy:
+ t = 'info'
+ s = "OK ('com.ubuntu.snappy' uses '%s' as email)" % self.email
else:
t = 'error'
s = "email=%s does not match package domain=%s " \
@@ -641,9 +654,8 @@
'''Check framework()'''
n = 'framework'
l = "http://askubuntu.com/questions/460512/what-framework-should-i-use-in-my-manifest-file"
- local_copy = os.path.join(os.path.dirname(__file__),
- '../data/frameworks.json')
- frameworks = Frameworks(local_copy)
+ framework_overrides = self.overrides.get('framework', {})
+ frameworks = Frameworks(overrides=framework_overrides)
if self.manifest['framework'] in frameworks.AVAILABLE_FRAMEWORKS:
t = 'info'
s = 'OK'
diff -Nru click-reviewers-tools-0.19/clickreviews/cr_scope.py click-reviewers-tools-0.19/clickreviews/cr_scope.py
--- click-reviewers-tools-0.19/clickreviews/cr_scope.py 2014-10-15 09:06:00.000000000 +0000
+++ click-reviewers-tools-0.19/clickreviews/cr_scope.py 2014-11-21 15:31:17.000000000 +0000
@@ -17,8 +17,10 @@
from __future__ import print_function
from clickreviews.cr_common import ClickReview, error, msg
+import codecs
import configparser
import os
+import re
KNOWN_SECTIONS = set(["ScopeConfig", "Appearance"])
@@ -57,8 +59,8 @@
error("Could not find scope INI file '%s'" % ini_fn_bn)
try:
d["scope_config"] = configparser.ConfigParser()
- d["scope_config"].read(ini_fn)
- except Exception:
+ d["scope_config"].read_file(codecs.open(ini_fn, "r", "utf8"))
+ except Exception as e:
error("scope config unparseable: %s (%s)" % (ini_fn_bn, str(e)))
d["dir"] = fn
@@ -104,6 +106,9 @@
'resultsttltype',
'scoperunner',
'searchhint']
+ translated = ['description',
+ 'displayname',
+ 'searchhint']
missing = []
t = 'info'
@@ -128,9 +133,12 @@
n = 'ini_%s_scope_unknown_fields' % (app)
s = 'OK'
unknown = []
- for f in self.scopes[app]["scope_config"]['ScopeConfig'].keys():
- if f.lower() not in required and f.lower() not in optional:
- unknown.append(f.lower())
+ for i in self.scopes[app]["scope_config"]['ScopeConfig'].keys():
+ f = i.lower()
+ if f not in required and f not in optional and \
+ (f.split("[")[0] not in translated or not
+ re.search(r'.*\[[a-z][a-z](_[a-z][a-z])?\]$', f)):
+ unknown.append(f)
if len(unknown) == 1:
t = 'warn'
diff -Nru click-reviewers-tools-0.19/clickreviews/cr_security.py click-reviewers-tools-0.19/clickreviews/cr_security.py
--- click-reviewers-tools-0.19/clickreviews/cr_security.py 2014-10-15 09:06:00.000000000 +0000
+++ click-reviewers-tools-0.19/clickreviews/cr_security.py 2014-11-21 15:31:17.000000000 +0000
@@ -25,7 +25,7 @@
class ClickReviewSecurity(ClickReview):
'''This class represents click lint reviews'''
- def __init__(self, fn):
+ def __init__(self, fn, overrides=None):
ClickReview.__init__(self, fn, "security")
local_copy = os.path.join(os.path.dirname(__file__),
@@ -78,10 +78,21 @@
# framework policy is based on major framework version. In 13.10, there
# was only 'ubuntu-sdk-13.10', but in 14.04, there will be several,
# like 'ubuntu-sdk-14.04-html5', 'ubuntu-sdk-14.04-platform', etc
- self.major_framework_policy = {'ubuntu-sdk-13.10': 1.0,
- 'ubuntu-sdk-14.04': 1.1,
- 'ubuntu-sdk-14.10': 1.2,
- }
+ self.major_framework_policy = {
+ 'ubuntu-sdk-13.10': {
+ 'policy_version': 1.0,
+ },
+ 'ubuntu-sdk-14.04': {
+ 'policy_version': 1.1,
+ },
+ 'ubuntu-sdk-14.10': {
+ 'policy_version': 1.2,
+ },
+ }
+ if overrides is None:
+ overrides = {}
+ framework_overrides = overrides.get('framework', {})
+ self._override_framework_policies(framework_overrides)
self.security_manifests = dict()
self.security_apps = []
@@ -102,6 +113,23 @@
self._extract_security_manifest(app)
self.security_apps.append(app)
+ def _override_framework_policies(self, overrides):
+ # override major framework policies
+ self.major_framework_policy.update(overrides)
+
+ # override apparmor policies
+ for name, data in overrides.items():
+ vendor = data.get('policy_vendor')
+ version = str(data.get('policy_version'))
+
+ if vendor not in self.aa_policy:
+ self.aa_policy[vendor] = {}
+
+ if version not in self.aa_policy[vendor]:
+ # just ensure the version is defined
+ # TODO: add support to override templates and policy groups
+ self.aa_policy[vendor][version] = {}
+
def _extract_security_manifest(self, app):
'''Extract security manifest and verify it has the expected
structure'''
@@ -269,15 +297,15 @@
n = 'policy_version_matches_framework (%s)' % (f)
s = "OK"
found_major = False
- for k in self.major_framework_policy.keys():
+ for name, data in self.major_framework_policy.items():
# TODO: use libclick when it is available
- if not self.manifest['framework'].startswith(k):
+ if not self.manifest['framework'].startswith(name):
continue
found_major = True
- if m['policy_version'] != self.major_framework_policy[k]:
+ if m['policy_version'] != data['policy_version']:
t = 'error'
s = '%s != %s (%s)' % (str(m['policy_version']),
- self.major_framework_policy[k],
+ data['policy_version'],
self.manifest['framework'])
if not found_major:
t = 'error'
diff -Nru click-reviewers-tools-0.19/clickreviews/frameworks.py click-reviewers-tools-0.19/clickreviews/frameworks.py
--- click-reviewers-tools-0.19/clickreviews/frameworks.py 2014-10-15 09:06:00.000000000 +0000
+++ click-reviewers-tools-0.19/clickreviews/frameworks.py 2014-11-21 15:31:17.000000000 +0000
@@ -32,15 +32,21 @@
OBSOLETE_FRAMEWORKS = []
AVAILABLE_FRAMEWORKS = []
- def __init__(self, local_copy_fn=None):
+ def __init__(self, overrides=None):
self.FRAMEWORKS = clickreviews.remote.read_cr_file(USER_DATA_FILE,
- FRAMEWORKS_DATA_URL,
- local_copy_fn)
+ FRAMEWORKS_DATA_URL)
+ if overrides is not None:
+ self.FRAMEWORKS.update(overrides)
- for k, v in self.FRAMEWORKS.items():
- if v == 'deprecated':
- self.DEPRECATED_FRAMEWORKS.append(k)
- elif v == 'obsolete':
- self.OBSOLETE_FRAMEWORKS.append(k)
- elif v == 'available':
- self.AVAILABLE_FRAMEWORKS.append(k)
+ for name, data in self.FRAMEWORKS.items():
+ if type(data) is dict:
+ state = data.get('state')
+ else:
+ state = data
+
+ if state == 'deprecated':
+ self.DEPRECATED_FRAMEWORKS.append(name)
+ elif state == 'obsolete':
+ self.OBSOLETE_FRAMEWORKS.append(name)
+ elif state == 'available':
+ self.AVAILABLE_FRAMEWORKS.append(name)
diff -Nru click-reviewers-tools-0.19/clickreviews/remote.py click-reviewers-tools-0.19/clickreviews/remote.py
--- click-reviewers-tools-0.19/clickreviews/remote.py 2014-10-15 09:06:00.000000000 +0000
+++ click-reviewers-tools-0.19/clickreviews/remote.py 2014-11-21 15:31:17.000000000 +0000
@@ -28,7 +28,7 @@
def _update_is_necessary(fn):
return (not os.path.exists(fn)) or \
- (time.time() - os.path.getctime(fn) >= UPDATE_INTERVAL)
+ (time.time() - os.path.getmtime(fn) >= UPDATE_INTERVAL)
def _update_is_possible(url):
diff -Nru click-reviewers-tools-0.19/clickreviews/tests/test_cr_desktop.py click-reviewers-tools-0.19/clickreviews/tests/test_cr_desktop.py
--- click-reviewers-tools-0.19/clickreviews/tests/test_cr_desktop.py 2014-10-15 09:06:00.000000000 +0000
+++ click-reviewers-tools-0.19/clickreviews/tests/test_cr_desktop.py 2014-11-21 15:31:17.000000000 +0000
@@ -713,3 +713,57 @@
r = c.click_report
expected_counts = {'info': None, 'warn': 1, 'error': 0}
self.check_results(r, expected_counts)
+
+ def test_check_desktop_exec_webbrowser_local_app(self):
+ '''Test test_check_desktop_exec_webbrowser_local_app() local app'''
+ c = ClickReviewDesktop(self.test_name)
+ ex = "webapp-container ./www/index.html"
+ self.set_test_desktop(self.default_appname,
+ "Exec",
+ ex)
+ c.check_desktop_exec_webapp_args()
+ r = c.click_report
+ expected_counts = {'info': None, 'warn': 0, 'error': 0}
+ self.check_results(r, expected_counts)
+
+ def test_check_desktop_exec_webbrowser_local_pattern(self):
+ '''Test test_check_desktop_exec_webbrowser_local_pattern() invalid pattern'''
+ c = ClickReviewDesktop(self.test_name)
+ ex = "webapp-container " + \
+ "--webappUrlPatterns=https?://mobile.twitter.com/* " + \
+ "./www/index.html"
+ self.set_test_desktop(self.default_appname,
+ "Exec",
+ ex)
+ c.check_desktop_exec_webapp_args()
+ r = c.click_report
+ expected_counts = {'info': None, 'warn': 0, 'error': 1}
+ self.check_results(r, expected_counts)
+
+ def test_check_desktop_exec_webbrowser_local_webapp(self):
+ '''Test test_check_desktop_exec_webbrowser_local_webapp() invalid webapp cli'''
+ c = ClickReviewDesktop(self.test_name)
+ ex = "webapp-container " + \
+ "--webapp=DEADBEEF " + \
+ "./www/index.html"
+ self.set_test_desktop(self.default_appname,
+ "Exec",
+ ex)
+ c.check_desktop_exec_webapp_args()
+ r = c.click_report
+ expected_counts = {'info': None, 'warn': 0, 'error': 1}
+ self.check_results(r, expected_counts)
+
+ def test_check_desktop_exec_webbrowser_local_model(self):
+ '''Test test_check_desktop_exec_webbrowser_local_model() invalid model'''
+ c = ClickReviewDesktop(self.test_name)
+ ex = "webapp-container " + \
+ "--webappModelSearchPath=. " + \
+ "./www/index.html"
+ self.set_test_desktop(self.default_appname,
+ "Exec",
+ ex)
+ c.check_desktop_exec_webapp_args()
+ r = c.click_report
+ expected_counts = {'info': None, 'warn': 0, 'error': 1}
+ self.check_results(r, expected_counts)
diff -Nru click-reviewers-tools-0.19/clickreviews/tests/test_cr_lint.py click-reviewers-tools-0.19/clickreviews/tests/test_cr_lint.py
--- click-reviewers-tools-0.19/clickreviews/tests/test_cr_lint.py 2014-10-15 09:06:00.000000000 +0000
+++ click-reviewers-tools-0.19/clickreviews/tests/test_cr_lint.py 2014-11-21 15:31:17.000000000 +0000
@@ -18,6 +18,7 @@
from clickreviews.cr_lint import ClickReviewLint
from clickreviews.cr_lint import MINIMUM_CLICK_FRAMEWORK_VERSION
+from clickreviews.frameworks import FRAMEWORKS_DATA_URL, USER_DATA_FILE
import clickreviews.cr_tests as cr_tests
@@ -29,6 +30,21 @@
cr_tests.mock_patch()
super()
+ def patch_frameworks(self):
+ def _mock_frameworks(self, overrides=None):
+ self.FRAMEWORKS = {
+ 'ubuntu-sdk-14.10-qml-dev2': 'available',
+ 'ubuntu-sdk-13.10': 'deprecated',
+ 'ubuntu-sdk-14.10-qml-dev1': 'obsolete',
+ }
+ self.AVAILABLE_FRAMEWORKS = ['ubuntu-sdk-14.10-qml-dev2']
+ self.OBSOLETE_FRAMEWORKS = ['ubuntu-sdk-14.10-qml-dev1']
+ self.DEPRECATED_FRAMEWORKS = ['ubuntu-sdk-13.10']
+ p = patch('clickreviews.frameworks.Frameworks.__init__',
+ _mock_frameworks)
+ p.start()
+ self.addCleanup(p.stop)
+
def test_check_architecture(self):
'''Test check_architecture()'''
c = ClickReviewLint(self.test_name)
@@ -554,7 +570,7 @@
self.check_results(r, expected_counts)
def test_check_maintainer_email_special(self):
- '''Test check_maintainer() - ubuntu-devel-discuss@lists.ubuntu.com'''
+ '''Test check_maintainer() - ubuntu-devel-discuss@ - app'''
self.set_test_control("Package", "com.canonical.app")
self.set_test_manifest("maintainer",
"Ubuntu Core Developers "
@@ -575,7 +591,7 @@
self.check_results(r, expected=expected)
def test_check_maintainer_email_special2(self):
- '''Test check_maintainer() - ubuntu-devel-discuss@lists.ubuntu.com'''
+ '''Test check_maintainer() - ubuntu-devel-discuss@ - scope'''
self.set_test_control("Package", "com.ubuntu.scopes.youtube")
self.set_test_manifest("maintainer",
"Ubuntu Core Developers "
@@ -595,6 +611,27 @@
"'ubuntu-devel-discuss@lists.ubuntu.com' as email)"}
self.check_results(r, expected=expected)
+ def test_check_maintainer_email_special3(self):
+ '''Test check_maintainer() - ubuntu-devel-discuss@ - snappy'''
+ self.set_test_control("Package", "com.ubuntu.snappy.foo")
+ self.set_test_manifest("maintainer",
+ "Ubuntu Core Developers "
+ "")
+ c = ClickReviewLint(self.test_name)
+ c.check_maintainer()
+ r = c.click_report
+ expected_counts = {'info': None, 'warn': 0, 'error': 0}
+ self.check_results(r, expected_counts)
+
+ expected = dict()
+ expected['info'] = dict()
+ expected['warn'] = dict()
+ expected['error'] = dict()
+ expected['info']['lint_maintainer_domain'] = \
+ {"text": "OK ('com.ubuntu.snappy' uses "
+ "'ubuntu-devel-discuss@lists.ubuntu.com' as email)"}
+ self.check_results(r, expected=expected)
+
def test_check_icon(self):
'''Test check_icon()'''
self.set_test_manifest("icon", "someicon")
@@ -682,15 +719,33 @@
def test_check_framework(self):
'''Test check_framework()'''
+ self.patch_frameworks()
+ self.set_test_manifest("framework", "ubuntu-sdk-14.10-qml-dev2")
+ c = ClickReviewLint(self.test_name)
+ c.check_framework()
+ r = c.click_report
+ expected_counts = {'info': 1, 'warn': 0, 'error': 0}
+ self.check_results(r, expected_counts)
+
+ @patch('clickreviews.remote.read_cr_file')
+ def test_check_framework_fetches_remote_data(self, mock_read_cr_file):
+ '''Test check_framework()'''
+ mock_read_cr_file.return_value = {
+ 'ubuntu-sdk-14.10-qml-dev2': 'available',
+ }
self.set_test_manifest("framework", "ubuntu-sdk-14.10-qml-dev2")
c = ClickReviewLint(self.test_name)
c.check_framework()
r = c.click_report
expected_counts = {'info': 1, 'warn': 0, 'error': 0}
self.check_results(r, expected_counts)
+ # ensure no local fn is provided when reading frameworks
+ mock_read_cr_file.assert_called_once_with(
+ USER_DATA_FILE, FRAMEWORKS_DATA_URL)
def test_check_framework_bad(self):
'''Test check_framework() - bad'''
+ self.patch_frameworks()
self.set_test_manifest("framework", "nonexistent")
c = ClickReviewLint(self.test_name)
c.check_framework()
@@ -700,6 +755,7 @@
def test_check_framework_deprecated(self):
'''Test check_framework() - deprecated'''
+ self.patch_frameworks()
self.set_test_manifest("framework", "ubuntu-sdk-13.10")
c = ClickReviewLint(self.test_name)
c.check_framework()
@@ -709,6 +765,7 @@
def test_check_framework_obsolete(self):
'''Test check_framework() - obsolete'''
+ self.patch_frameworks()
self.set_test_manifest("framework", "ubuntu-sdk-14.10-qml-dev1")
c = ClickReviewLint(self.test_name)
c.check_framework()
@@ -716,6 +773,34 @@
expected_counts = {'info': None, 'warn': 0, 'error': 1}
self.check_results(r, expected_counts)
+ @patch('clickreviews.remote.read_cr_file')
+ def test_check_framework_with_overrides(self, mock_read_cr_file):
+ '''Test check_framework() - using overrides'''
+ mock_read_cr_file.return_value = {
+ 'ubuntu-sdk-14.10-qml-dev2': 'available',
+ }
+ self.set_test_manifest("framework", "nonexistent")
+ overrides = {'framework': {'nonexistent': {'state': 'available'}}}
+ c = ClickReviewLint(self.test_name, overrides=overrides)
+ c.check_framework()
+ r = c.click_report
+ expected_counts = {'info': 1, 'warn': 0, 'error': 0}
+ self.check_results(r, expected_counts)
+
+ @patch('clickreviews.remote.read_cr_file')
+ def test_check_framework_with_malformed_overrides(self, mock_read_cr_file):
+ '''Test check_framework() - using overrides'''
+ mock_read_cr_file.return_value = {
+ 'ubuntu-sdk-14.10-qml-dev2': 'available',
+ }
+ self.set_test_manifest("framework", "nonexistent")
+ overrides = {'nonexistent': {'state': 'available'}}
+ c = ClickReviewLint(self.test_name, overrides=overrides)
+ c.check_framework()
+ r = c.click_report
+ expected_counts = {'info': 0, 'warn': 0, 'error': 1}
+ self.check_results(r, expected_counts)
+
def test_check_hooks(self):
'''Test check_hooks()'''
self.set_test_manifest("framework", "ubuntu-sdk-13.10")
diff -Nru click-reviewers-tools-0.19/clickreviews/tests/test_cr_scope.py click-reviewers-tools-0.19/clickreviews/tests/test_cr_scope.py
--- click-reviewers-tools-0.19/clickreviews/tests/test_cr_scope.py 2014-10-15 09:06:00.000000000 +0000
+++ click-reviewers-tools-0.19/clickreviews/tests/test_cr_scope.py 2014-11-21 15:31:17.000000000 +0000
@@ -123,6 +123,45 @@
expected_counts = {'info': None, 'warn': 0, 'error': 1}
self.check_results(r, expected_counts)
+ def test_check_scope_ini_translated_field(self):
+ '''Test check_scope_ini() - translated field - es'''
+ config = self._stub_config()
+ config['searchhint[es]'] = "foo"
+ scope = self._create_scope(config)
+
+ self.set_test_scope(self.default_appname, scope)
+ c = ClickReviewScope(self.test_name)
+ c.check_scope_ini()
+ r = c.click_report
+ expected_counts = {'info': None, 'warn': 0, 'error': 0}
+ self.check_results(r, expected_counts)
+
+ def test_check_scope_ini_translated_field2(self):
+ '''Test check_scope_ini() - translated field - pt_br'''
+ config = self._stub_config()
+ config['searchhint[pt_br]'] = "foo"
+ scope = self._create_scope(config)
+
+ self.set_test_scope(self.default_appname, scope)
+ c = ClickReviewScope(self.test_name)
+ c.check_scope_ini()
+ r = c.click_report
+ expected_counts = {'info': None, 'warn': 0, 'error': 0}
+ self.check_results(r, expected_counts)
+
+ def test_check_scope_ini_bad_translated_field(self):
+ '''Test check_scope_ini() - bad translated field'''
+ config = self._stub_config()
+ config['searchhint[ba;r]'] = "foo"
+ scope = self._create_scope(config)
+
+ self.set_test_scope(self.default_appname, scope)
+ c = ClickReviewScope(self.test_name)
+ c.check_scope_ini()
+ r = c.click_report
+ expected_counts = {'info': None, 'warn': 1, 'error': 0}
+ self.check_results(r, expected_counts)
+
def test_check_scope_ini_nonexistent_field(self):
'''Test check_scope_ini() - non-existent field'''
config = self._stub_config()
diff -Nru click-reviewers-tools-0.19/clickreviews/tests/test_cr_security.py click-reviewers-tools-0.19/clickreviews/tests/test_cr_security.py
--- click-reviewers-tools-0.19/clickreviews/tests/test_cr_security.py 2014-10-15 09:06:00.000000000 +0000
+++ click-reviewers-tools-0.19/clickreviews/tests/test_cr_security.py 2014-11-21 15:31:17.000000000 +0000
@@ -136,7 +136,7 @@
policy_version = 0
for k in tmp.major_framework_policy.keys():
if f.startswith(k):
- policy_version = tmp.major_framework_policy[k]
+ policy_version = tmp.major_framework_policy[k]['policy_version']
self.set_test_security_manifest(self.default_appname,
"policy_version",
policy_version)
@@ -209,6 +209,36 @@
{"text": "Invalid framework 'nonexistent'"}
self.check_results(report, expected=expected)
+ def test_check_policy_version_framework_with_overrides(self):
+ '''Test check_policy_version() - override framework (nonexistent)'''
+ self.set_test_manifest("framework", "nonexistent")
+ self.set_test_security_manifest(self.default_appname,
+ "policy_version", 1.3)
+ overrides = {'framework': {'nonexistent': {'state': 'available',
+ 'policy_vendor': 'ubuntu',
+ 'policy_version': 1.3}}}
+ c = ClickReviewSecurity(self.test_name, overrides=overrides)
+ c.check_policy_version()
+ report = c.click_report
+
+ expected_counts = {'info': 3, 'warn': 0, 'error': 0}
+ self.check_results(report, expected_counts)
+
+ def test_check_policy_version_framework_with_malformed_overrides(self):
+ '''Test check_policy_version() - incorrectly override framework'''
+ self.set_test_manifest("framework", "nonexistent")
+ self.set_test_security_manifest(self.default_appname,
+ "policy_version", 1.3)
+ overrides = {'nonexistent': {'state': 'available',
+ 'policy_vendor': 'ubuntu',
+ 'policy_version': 1.3}}
+ c = ClickReviewSecurity(self.test_name, overrides=overrides)
+ c.check_policy_version()
+ report = c.click_report
+
+ expected_counts = {'info': 1, 'warn': 0, 'error': 2}
+ self.check_results(report, expected_counts)
+
def test_check_policy_vendor_unspecified(self):
'''Test check_policy_vendor() - unspecified'''
c = ClickReviewSecurity(self.test_name)
diff -Nru click-reviewers-tools-0.19/clickreviews/tests/test_remote.py click-reviewers-tools-0.19/clickreviews/tests/test_remote.py
--- click-reviewers-tools-0.19/clickreviews/tests/test_remote.py 1970-01-01 00:00:00.000000000 +0000
+++ click-reviewers-tools-0.19/clickreviews/tests/test_remote.py 2014-11-21 15:31:17.000000000 +0000
@@ -0,0 +1,38 @@
+import time
+from unittest import TestCase
+from unittest.mock import patch
+
+from clickreviews.remote import UPDATE_INTERVAL, _update_is_necessary
+
+
+class RemoteTestCase(TestCase):
+ def patch_path(self):
+ p = patch('clickreviews.remote.os.path')
+ self.mock_path = p.start()
+ self.addCleanup(p.stop)
+
+ def patch_time(self, now):
+ p = patch('clickreviews.remote.time.time')
+ self.mock_time = p.start()
+ self.mock_time.return_value = now
+ self.addCleanup(p.stop)
+
+ def test_no_update_needed(self):
+ now = time.time()
+ self.patch_time(now)
+ self.patch_path()
+
+ # last update was 10 seconds ago
+ self.mock_path.getmtime.return_value = now - 10
+
+ self.assertFalse(_update_is_necessary('some-file'))
+
+ def test_update_needed(self):
+ now = time.time()
+ self.patch_time(now)
+ self.patch_path()
+
+ # last update was UPDATE_INTERVAL + 10 seconds ago
+ self.mock_path.getmtime.return_value = now - UPDATE_INTERVAL - 10
+
+ self.assertTrue(_update_is_necessary('some-file'))
diff -Nru click-reviewers-tools-0.19/data/frameworks.json click-reviewers-tools-0.19/data/frameworks.json
--- click-reviewers-tools-0.19/data/frameworks.json 2014-10-15 09:06:00.000000000 +0000
+++ click-reviewers-tools-0.19/data/frameworks.json 1970-01-01 00:00:00.000000000 +0000
@@ -1,23 +0,0 @@
-{
- "ubuntu-sdk-13.10": "deprecated",
- "ubuntu-sdk-14.04-html": "available",
- "ubuntu-sdk-14.04-qml-dev1": "deprecated",
- "ubuntu-sdk-14.10-qml-dev3": "available",
- "ubuntu-sdk-14.10-papi-dev3": "available",
- "ubuntu-sdk-14.04-html-dev1": "deprecated",
- "ubuntu-sdk-14.10-papi-dev1": "obsolete",
- "ubuntu-sdk-14.04-papi-dev1": "deprecated",
- "ubuntu-sdk-14.10-dev2": "available",
- "ubuntu-sdk-14.04": "available",
- "ubuntu-sdk-14.10-dev3": "available",
- "ubuntu-sdk-14.10-qml-dev1": "obsolete",
- "ubuntu-sdk-14.04-dev1": "deprecated",
- "ubuntu-sdk-14.10-dev1": "obsolete",
- "ubuntu-sdk-14.04-papi": "available",
- "ubuntu-sdk-14.04-qml": "available",
- "ubuntu-sdk-14.10-papi-dev2": "available",
- "ubuntu-sdk-14.10-html-dev3": "available",
- "ubuntu-sdk-14.10-html-dev2": "available",
- "ubuntu-sdk-14.10-html-dev1": "obsolete",
- "ubuntu-sdk-14.10-qml-dev2": "available"
-}
diff -Nru click-reviewers-tools-0.19/debian/bzr-builder.manifest click-reviewers-tools-0.19/debian/bzr-builder.manifest
--- click-reviewers-tools-0.19/debian/bzr-builder.manifest 2014-10-15 09:06:00.000000000 +0000
+++ click-reviewers-tools-0.19/debian/bzr-builder.manifest 2014-11-21 15:31:17.000000000 +0000
@@ -1,2 +1,2 @@
-# bzr-builder format 0.3 deb-version {debupstream}-0~281
-lp:click-reviewers-tools revid:daniel.holbach@canonical.com-20141015084712-ezies2zzr9klz234
+# bzr-builder format 0.3 deb-version {debupstream}-0~300
+lp:click-reviewers-tools revid:jamie@ubuntu.com-20141121140457-0n9802z9wrcv3pcm
diff -Nru click-reviewers-tools-0.19/debian/changelog click-reviewers-tools-0.19/debian/changelog
--- click-reviewers-tools-0.19/debian/changelog 2014-10-15 09:06:00.000000000 +0000
+++ click-reviewers-tools-0.19/debian/changelog 2014-11-21 15:31:17.000000000 +0000
@@ -1,14 +1,27 @@
-click-reviewers-tools (0.19-0~281~ubuntu14.04.1) trusty; urgency=low
+click-reviewers-tools (0.19-0~300~ubuntu14.04.1) trusty; urgency=low
* Auto build.
- -- Daniel Holbach Wed, 15 Oct 2014 09:06:00 +0000
+ -- Daniel Holbach Fri, 21 Nov 2014 15:31:17 +0000
click-reviewers-tools (0.19) UNRELEASED; urgency=medium
- *
+ [ Ricardo Kirkner ]
+ * fetch framework data before running framework related checks
+ * use mtime instead of ctime to check remote file freshness
+ * allow specifying overrides for framework checks
+ * handle case when overrides data is malformed
+
+ [ Alexandre Abreu ]
+ * add support for local html5 app launch mode for webapp-container
+ (LP: #1388988)
+
+ [ Jamie Strandboge ]
+ * open scopes .ini file as utf8 (LP: #1371692)
+ * allow for translatable fields in the scopes .ini file (LP: #1392133)
+ * don't require desktop hook with systemd or framework
- -- Daniel Holbach Wed, 15 Oct 2014 10:46:59 +0200
+ -- Jamie Strandboge Thu, 13 Nov 2014 15:00:07 -0600
click-reviewers-tools (0.18) utopic; urgency=medium
diff -Nru click-reviewers-tools-0.19/debian/rules click-reviewers-tools-0.19/debian/rules
--- click-reviewers-tools-0.19/debian/rules 2014-10-15 09:06:00.000000000 +0000
+++ click-reviewers-tools-0.19/debian/rules 2014-11-21 15:31:17.000000000 +0000
@@ -18,7 +18,6 @@
rm -rf build *.egg-info .pybuild
find -name \*.pyc -print0 | xargs -0r rm -f
find -name __pycache__ -print0 | xargs -0r rm -rf
- -$(shell python3 ./bin/update-frameworks ./data/frameworks.json)
-$(shell python3 ./bin/update-apparmor-policy ./data/apparmor-easyprof-ubuntu.json)
override_dh_auto_build: