Merge lp:~jdstrand/click-reviewers-tools/lint-snapv2 into lp:click-reviewers-tools
- lint-snapv2
- Merge into trunk
| Status: | Merged |
|---|---|
| Merged at revision: | 575 |
| Proposed branch: | lp:~jdstrand/click-reviewers-tools/lint-snapv2 |
| Merge into: | lp:click-reviewers-tools |
| Prerequisite: | lp:~jdstrand/click-reviewers-tools/initial-snapv2 |
| Diff against target: |
4475 lines (+3980/-171) 15 files modified
.bzrignore (+2/-0) Makefile (+7/-0) README (+1/-0) bin/click-review (+4/-3) bin/snap-check-lint (+24/-0) check-names.list (+63/-0) clickreviews/common.py (+89/-0) clickreviews/cr_lint.py (+9/-50) clickreviews/cr_tests.py (+1/-34) clickreviews/sr_common.py (+10/-2) clickreviews/sr_lint.py (+1203/-0) clickreviews/sr_tests.py (+20/-36) clickreviews/tests/test_cr_lint.py (+2/-2) clickreviews/tests/test_sr_lint.py (+2396/-0) clickreviews/tests/utils.py (+149/-44) |
| To merge this branch: | bzr merge lp:~jdstrand/click-reviewers-tools/lint-snapv2 |
| Related bugs: |
| Reviewer | Review Type | Date Requested | Status |
|---|---|---|---|
| Daniel Holbach (community) | 2016-02-10 | Approve on 2016-02-15 | |
|
Review via email:
|
|||
Commit Message
Description of the Change
add lint checks for snap.yaml
- add sr_lint.py. This adds complete snap.yaml checks. A few lint checks were dropped over cr_common.py, but these will be added in a future commit
- add clickreviews/
- add bin/snap-check-lint
- update README for the above
- add coverage and coverage-report targets
- bin/click-review: make module sections more descriptive
- bin/click-review: rename click_fn variable as pkg_fn
Testing:
# click (same as prerequisite refactor branch)
PYTHONPATH=./ ./bin/click-review -v ../rottentomato
120
# snap v1 (same as prerequisite refactor branch)
$ PYTHONPATH=./ ./bin/click-review -v ../ufw-
264
# snap v2 (these aren't all the tests since this is a simple snap, but does show the lint tests are being run)
$ PYTHONPATH=./ ./bin/click-review -v ../snappy-
26
| Jamie Strandboge (jdstrand) wrote : | # |
| Jamie Strandboge (jdstrand) wrote : | # |
With r597, we should have complete snap.yaml checks and all missing TODOs checks are present. The lint checks are now on par with existing click and snap v1 checks. The testsuite covers all the checks and there is 100% coverage for these lint checks.
Next up, sr_security.py which will be in another MP.
| Daniel Holbach (dholbach) wrote : | # |
This by and large looks good to me. I'm no expert though on the specific checks required for snapv2 - would you like another review from somebody on the snappy team for this?
| Jamie Strandboge (jdstrand) wrote : | # |
I don't think that is required (they are quite busy)-- I'm going to run the tests through the existing snaps and I followed doc/meta.md for these. Anything that isn't right can just be a bug that I'll fix.
Preview Diff
| 1 | === modified file '.bzrignore' |
| 2 | --- .bzrignore 2013-09-26 12:41:57 +0000 |
| 3 | +++ .bzrignore 2016-02-11 18:32:45 +0000 |
| 4 | @@ -9,3 +9,5 @@ |
| 5 | debian/click-reviewers-tools.substvars |
| 6 | debian/files |
| 7 | debian/tmp |
| 8 | +.coverage |
| 9 | +check-names.list.orig |
| 10 | |
| 11 | === modified file 'Makefile' |
| 12 | --- Makefile 2015-10-26 22:00:58 +0000 |
| 13 | +++ Makefile 2016-02-11 18:32:45 +0000 |
| 14 | @@ -7,6 +7,12 @@ |
| 15 | test: |
| 16 | ./run-tests |
| 17 | |
| 18 | +coverage: |
| 19 | + python3 -m coverage run ./run-tests |
| 20 | + |
| 21 | +coverage-report: |
| 22 | + python3 -m coverage report --show-missing --omit="*skeleton*,*/dist-packages/*" |
| 23 | + |
| 24 | syntax-check: clean |
| 25 | ./run-pyflakes |
| 26 | ./run-pep8 |
| 27 | @@ -23,6 +29,7 @@ |
| 28 | |
| 29 | clean: |
| 30 | rm -rf ./clickreviews/__pycache__ ./clickreviews/tests/__pycache__ |
| 31 | + rm -rf ./.coverage |
| 32 | |
| 33 | .PHONY: check-names.list |
| 34 | check-names.list: |
| 35 | |
| 36 | === modified file 'README' |
| 37 | --- README 2016-02-10 19:32:10 +0000 |
| 38 | +++ README 2016-02-11 18:32:45 +0000 |
| 39 | @@ -14,6 +14,7 @@ |
| 40 | - bin/click-run-checks: all tests |
| 41 | |
| 42 | Runnable snap v2 tests: |
| 43 | +- bin/snap-check-lint: lint tests |
| 44 | - bin/snap-run-checks: all tests |
| 45 | |
| 46 | This gives an alternate view on bin/click-run-checks: |
| 47 | |
| 48 | === modified file 'bin/click-review' |
| 49 | --- bin/click-review 2016-02-09 21:45:25 +0000 |
| 50 | +++ bin/click-review 2016-02-11 18:32:45 +0000 |
| 51 | @@ -32,7 +32,7 @@ |
| 52 | |
| 53 | def __init__(self, args): |
| 54 | self.args = args |
| 55 | - self.click_fn = self.args.filename |
| 56 | + self.pkg_fn = self.args.filename |
| 57 | self.modules = modules.get_modules() |
| 58 | |
| 59 | def _sumarise_results(self): |
| 60 | @@ -86,8 +86,9 @@ |
| 61 | # review.do_checks() |
| 62 | # rc = review.do_report() |
| 63 | # |
| 64 | - section = module.replace('cr_', '') |
| 65 | - review = modules.init_main_class(module, self.click_fn) |
| 66 | + section = module.replace('cr_', 'click,snap.v1_') |
| 67 | + section = section.replace('sr_', 'snap.v2_') |
| 68 | + review = modules.init_main_class(module, self.pkg_fn) |
| 69 | if review: |
| 70 | review.do_checks() |
| 71 | self.results[section] = review.click_report |
| 72 | |
| 73 | === added file 'bin/snap-check-lint' |
| 74 | --- bin/snap-check-lint 1970-01-01 00:00:00 +0000 |
| 75 | +++ bin/snap-check-lint 2016-02-11 18:32:45 +0000 |
| 76 | @@ -0,0 +1,24 @@ |
| 77 | +#!/usr/bin/python3 |
| 78 | +'''snap-check-lint: perform snap lint checks''' |
| 79 | +# |
| 80 | +# Copyright (C) 2013-2016 Canonical Ltd. |
| 81 | +# |
| 82 | +# This program is free software: you can redistribute it and/or modify |
| 83 | +# it under the terms of the GNU General Public License as published by |
| 84 | +# the Free Software Foundation; version 3 of the License. |
| 85 | +# |
| 86 | +# This program is distributed in the hope that it will be useful, |
| 87 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 88 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 89 | +# GNU General Public License for more details. |
| 90 | +# |
| 91 | +# You should have received a copy of the GNU General Public License |
| 92 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 93 | + |
| 94 | +from __future__ import print_function |
| 95 | + |
| 96 | +import clickreviews.common as common |
| 97 | +import clickreviews.sr_lint as sr_lint |
| 98 | + |
| 99 | +if __name__ == "__main__": |
| 100 | + common.run_check(sr_lint.SnapReviewLint) |
| 101 | |
| 102 | === modified file 'check-names.list' |
| 103 | --- check-names.list 2016-02-09 21:45:25 +0000 |
| 104 | +++ check-names.list 2016-02-11 18:32:45 +0000 |
| 105 | @@ -94,6 +94,69 @@ |
| 106 | lint:snappy_type_valid| |
| 107 | lint:snappy_unknown| |
| 108 | lint:snappy_version_valid| |
| 109 | +lint-snap-v2:apps| |
| 110 | +lint-snap-v2:apps_entry| |
| 111 | +lint-snap-v2:apps_present| |
| 112 | +lint-snap-v2:apps_required| |
| 113 | +lint-snap-v2:apps_unknown| |
| 114 | +lint-snap-v2:architecture_specified_needed| |
| 115 | +lint-snap-v2:architecture_valid| |
| 116 | +lint-snap-v2:attributes| |
| 117 | +lint-snap-v2:bus-name| |
| 118 | +lint-snap-v2:bus-name_framework| |
| 119 | +lint-snap-v2:bus-name|http://dbus.freedesktop.org/doc/dbus-specification.html |
| 120 | +lint-snap-v2:bus-name_matches_name| |
| 121 | +lint-snap-v2:command| |
| 122 | +lint-snap-v2:config_hook_executable| |
| 123 | +lint-snap-v2:daemon| |
| 124 | +lint-snap-v2:daemon_required| |
| 125 | +lint-snap-v2:description| |
| 126 | +lint-snap-v2:description_present| |
| 127 | +lint-snap-v2:external_symlinks| |
| 128 | +lint-snap-v2:frameworks|http://askubuntu.com/questions/460512/what-framework-should-i-use-in-my-manifest-file |
| 129 | +lint-snap-v2:icon_absolute_path| |
| 130 | +lint-snap-v2:icon_empty| |
| 131 | +lint-snap-v2:icon_exists| |
| 132 | +lint-snap-v2:icon_present| |
| 133 | +lint-snap-v2:is_squashfs| |
| 134 | +lint-snap-v2:license-agreement| |
| 135 | +lint-snap-v2:license-agreement_present| |
| 136 | +lint-snap-v2:license-version| |
| 137 | +lint-snap-v2:license-version_present| |
| 138 | +lint-snap-v2:listen-stream| |
| 139 | +lint-snap-v2:listen-stream_matches_name| |
| 140 | +lint-snap-v2:migration-skill| |
| 141 | +lint-snap-v2:name_valid| |
| 142 | +lint-snap-v2:nonexistent| |
| 143 | +lint-snap-v2:ports| |
| 144 | +lint-snap-v2:ports_ext1_format| |
| 145 | +lint-snap-v2:ports_ext2_format| |
| 146 | +lint-snap-v2:ports_int1_format| |
| 147 | +lint-snap-v2:ports_unknown_key| |
| 148 | +lint-snap-v2:ports_unknown_subkey| |
| 149 | +lint-snap-v2:poststop| |
| 150 | +lint-snap-v2:restart-condition| |
| 151 | +lint-snap-v2:snap_type_redflag|https://developer.ubuntu.com/en/snappy/guides/frameworks/ |
| 152 | +lint-snap-v2:snap_type_valid| |
| 153 | +lint-snap-v2:socket| |
| 154 | +lint-snap-v2:socket-group| |
| 155 | +lint-snap-v2:socket-group_matches_name| |
| 156 | +lint-snap-v2:socket-group_reserved| |
| 157 | +lint-snap-v2:socket-user| |
| 158 | +lint-snap-v2:socket-user_matches_name| |
| 159 | +lint-snap-v2:socket-user_reserved| |
| 160 | +lint-snap-v2:stop| |
| 161 | +lint-snap-v2:stop-timeout| |
| 162 | +lint-snap-v2:stop-timeout_range| |
| 163 | +lint-snap-v2:summary| |
| 164 | +lint-snap-v2:summary_present| |
| 165 | +lint-snap-v2:type| |
| 166 | +lint-snap-v2:unknown_field| |
| 167 | +lint-snap-v2:uses| |
| 168 | +lint-snap-v2:uses_slot_reference| |
| 169 | +lint-snap-v2:valid_contents_for_architecture| |
| 170 | +lint-snap-v2:vcs_files| |
| 171 | +lint-snap-v2:version_valid| |
| 172 | online_accounts:account-application_hook| |
| 173 | online_accounts:account-application_id| |
| 174 | online_accounts:account-application_root| |
| 175 | |
| 176 | === modified file 'clickreviews/common.py' |
| 177 | --- clickreviews/common.py 2016-02-09 21:45:25 +0000 |
| 178 | +++ clickreviews/common.py 2016-02-11 18:32:45 +0000 |
| 179 | @@ -33,6 +33,7 @@ |
| 180 | DEBUGGING = False |
| 181 | UNPACK_DIR = None |
| 182 | RAW_UNPACK_DIR = None |
| 183 | +MKSQUASHFS_OPTS = ['-noappend', '-comp', 'xz', '-all-root'] |
| 184 | |
| 185 | |
| 186 | def cleanup_unpack(): |
| 187 | @@ -512,3 +513,91 @@ |
| 188 | recursive_rm(unpack_dir) |
| 189 | |
| 190 | return (pkgtype, pkgver) |
| 191 | + |
| 192 | + |
| 193 | +def find_external_symlinks(unpack_dir, pkg_files): |
| 194 | + '''Check if symlinks in the package go out to the system.''' |
| 195 | + common = '(-[0-9.]+)?\.so(\.[0-9.]+)?' |
| 196 | + libc6_libs = ['ld-*.so', |
| 197 | + 'libanl', |
| 198 | + 'libBrokenLocale', |
| 199 | + 'libc', |
| 200 | + 'libcidn', |
| 201 | + 'libcrypt', |
| 202 | + 'libdl', |
| 203 | + 'libmemusage', |
| 204 | + 'libm', |
| 205 | + 'libnsl', |
| 206 | + 'libnss_compat', |
| 207 | + 'libnss_dns', |
| 208 | + 'libnss_files', |
| 209 | + 'libnss_hesiod', |
| 210 | + 'libnss_nisplus', |
| 211 | + 'libnss_nis', |
| 212 | + 'libpcprofile', |
| 213 | + 'libpthread', |
| 214 | + 'libresolv', |
| 215 | + 'librt', |
| 216 | + 'libSegFault', |
| 217 | + 'libthread_db', |
| 218 | + 'libutil', |
| 219 | + ] |
| 220 | + libc6_pats = [] |
| 221 | + for lib in libc6_libs: |
| 222 | + libc6_pats.append(re.compile(r'%s%s' % (lib, common))) |
| 223 | + libc6_pats.append(re.compile(r'ld-*.so$')) |
| 224 | + libc6_pats.append(re.compile(r'ld-linux-*.so\.[0-9.]+$')) |
| 225 | + |
| 226 | + def _in_patterns(pats, f): |
| 227 | + for pat in pats: |
| 228 | + if pat.search(f): |
| 229 | + return True |
| 230 | + return False |
| 231 | + |
| 232 | + external_symlinks = list(filter(lambda link: not |
| 233 | + os.path.realpath(link).startswith( |
| 234 | + unpack_dir) and |
| 235 | + not _in_patterns(libc6_pats, |
| 236 | + os.path.basename(link)), |
| 237 | + pkg_files)) |
| 238 | + |
| 239 | + return external_symlinks |
| 240 | + |
| 241 | + |
| 242 | +# check_results(report, expected_counts, expected) |
| 243 | +# Verify exact counts of types |
| 244 | +# expected_counts={'info': 1, 'warn': 0, 'error': 0} |
| 245 | +# self.check_results(report, expected_counts) |
| 246 | +# Verify counts of warn and error types |
| 247 | +# expected_counts={'info': None, 'warn': 0, 'error': 0} |
| 248 | +# self.check_results(report, expected_counts) |
| 249 | +# Verify exact messages: |
| 250 | +# expected = dict() |
| 251 | +# expected['info'] = dict() |
| 252 | +# expected['warn'] = dict() |
| 253 | +# expected['warn']['skeleton_baz'] = "TODO" |
| 254 | +# expected['error'] = dict() |
| 255 | +# self.check_results(r, expected=expected) |
| 256 | + |
| 257 | + |
| 258 | +def check_results(testobj, report, |
| 259 | + expected_counts={'info': 1, 'warn': 0, 'error': 0}, |
| 260 | + expected=None): |
| 261 | + if expected is not None: |
| 262 | + for t in expected.keys(): |
| 263 | + for r in expected[t]: |
| 264 | + testobj.assertTrue(r in report[t], |
| 265 | + "Could not find '%s' (%s) in:\n%s" % |
| 266 | + (r, t, json.dumps(report, indent=2))) |
| 267 | + for k in expected[t][r]: |
| 268 | + testobj.assertTrue(k in report[t][r], |
| 269 | + "Could not find '%s' (%s) in:\n%s" % |
| 270 | + (k, r, json.dumps(report, indent=2))) |
| 271 | + testobj.assertEqual(expected[t][r][k], report[t][r][k]) |
| 272 | + else: |
| 273 | + for k in expected_counts.keys(): |
| 274 | + if expected_counts[k] is None: |
| 275 | + continue |
| 276 | + testobj.assertEqual(len(report[k]), expected_counts[k], |
| 277 | + "(%s not equal)\n%s" % |
| 278 | + (k, json.dumps(report, indent=2))) |
| 279 | |
| 280 | === modified file 'clickreviews/cr_lint.py' |
| 281 | --- clickreviews/cr_lint.py 2016-02-10 19:29:39 +0000 |
| 282 | +++ clickreviews/cr_lint.py 2016-02-11 18:32:45 +0000 |
| 283 | @@ -27,13 +27,14 @@ |
| 284 | from clickreviews.cr_common import ( |
| 285 | ClickReview, |
| 286 | ) |
| 287 | - |
| 288 | from clickreviews.common import ( |
| 289 | open_file_read, |
| 290 | cmd, |
| 291 | error, |
| 292 | ) |
| 293 | - |
| 294 | +from clickreviews.common import ( |
| 295 | + find_external_symlinks, |
| 296 | +) |
| 297 | |
| 298 | CONTROL_FILE_NAMES = ["control", "manifest", "preinst"] |
| 299 | MINIMUM_CLICK_FRAMEWORK_VERSION = "0.4" |
| 300 | @@ -538,61 +539,19 @@ |
| 301 | '''Check if symlinks in the click package go out to the system.''' |
| 302 | if not self.is_click and not self.is_snap1: |
| 303 | return |
| 304 | - if self.is_snap1 and self.pkg_yaml['type'] not in ['app', 'framework']: |
| 305 | + |
| 306 | + if self.is_snap1 and 'type' in self.snap_yaml and \ |
| 307 | + self.snap_yaml['type'] not in ['app', 'framework']: |
| 308 | return |
| 309 | |
| 310 | t = 'info' |
| 311 | n = self._get_check_name('external_symlinks') |
| 312 | s = 'OK' |
| 313 | |
| 314 | - common = '(-[0-9.]+)?\.so(\.[0-9.]+)?' |
| 315 | - libc6_libs = ['ld-*.so', |
| 316 | - 'libanl', |
| 317 | - 'libBrokenLocale', |
| 318 | - 'libc', |
| 319 | - 'libcidn', |
| 320 | - 'libcrypt', |
| 321 | - 'libdl', |
| 322 | - 'libmemusage', |
| 323 | - 'libm', |
| 324 | - 'libnsl', |
| 325 | - 'libnss_compat', |
| 326 | - 'libnss_dns', |
| 327 | - 'libnss_files', |
| 328 | - 'libnss_hesiod', |
| 329 | - 'libnss_nisplus', |
| 330 | - 'libnss_nis', |
| 331 | - 'libpcprofile', |
| 332 | - 'libpthread', |
| 333 | - 'libresolv', |
| 334 | - 'librt', |
| 335 | - 'libSegFault', |
| 336 | - 'libthread_db', |
| 337 | - 'libutil', |
| 338 | - ] |
| 339 | - libc6_pats = [] |
| 340 | - for lib in libc6_libs: |
| 341 | - libc6_pats.append(re.compile(r'%s%s' % (lib, common))) |
| 342 | - libc6_pats.append(re.compile(r'ld-*.so$')) |
| 343 | - libc6_pats.append(re.compile(r'ld-linux-*.so\.[0-9.]+$')) |
| 344 | - |
| 345 | - def _in_patterns(pats, f): |
| 346 | - for pat in pats: |
| 347 | - if pat.search(f): |
| 348 | - return True |
| 349 | - return False |
| 350 | - |
| 351 | - external_symlinks = list(filter(lambda link: not |
| 352 | - os.path.realpath(link).startswith( |
| 353 | - self.unpack_dir) and |
| 354 | - not _in_patterns(libc6_pats, |
| 355 | - os.path.basename(link)), |
| 356 | - self.pkg_files)) |
| 357 | - |
| 358 | - if external_symlinks: |
| 359 | + links = find_external_symlinks(self.unpack_dir, self.pkg_files) |
| 360 | + if len(links) > 0: |
| 361 | t = 'error' |
| 362 | - s = 'package contains external symlinks: %s' % \ |
| 363 | - ', '.join(external_symlinks) |
| 364 | + s = 'package contains external symlinks: %s' % ', '.join(links) |
| 365 | self._add_result(t, n, s) |
| 366 | |
| 367 | def check_pkgname(self): |
| 368 | |
| 369 | === modified file 'clickreviews/cr_scope.py' (properties changed: +x to -x) |
| 370 | === modified file 'clickreviews/cr_tests.py' |
| 371 | --- clickreviews/cr_tests.py 2016-02-09 22:26:36 +0000 |
| 372 | +++ clickreviews/cr_tests.py 2016-02-11 18:32:45 +0000 |
| 373 | @@ -713,43 +713,10 @@ |
| 374 | self.test_control['Version'], |
| 375 | self.test_control['Architecture']) |
| 376 | |
| 377 | - # |
| 378 | - # check_results(report, expected_counts, expected) |
| 379 | - # Verify exact counts of types |
| 380 | - # expected_counts={'info': 1, 'warn': 0, 'error': 0} |
| 381 | - # self.check_results(report, expected_counts) |
| 382 | - # Verify counts of warn and error types |
| 383 | - # expected_counts={'info': None, 'warn': 0, 'error': 0} |
| 384 | - # self.check_results(report, expected_counts) |
| 385 | - # Verify exact messages: |
| 386 | - # expected = dict() |
| 387 | - # expected['info'] = dict() |
| 388 | - # expected['warn'] = dict() |
| 389 | - # expected['warn']['skeleton_baz'] = "TODO" |
| 390 | - # expected['error'] = dict() |
| 391 | - # self.check_results(r, expected=expected) |
| 392 | - # |
| 393 | def check_results(self, report, |
| 394 | expected_counts={'info': 1, 'warn': 0, 'error': 0}, |
| 395 | expected=None): |
| 396 | - if expected is not None: |
| 397 | - for t in expected.keys(): |
| 398 | - for r in expected[t]: |
| 399 | - self.assertTrue(r in report[t], |
| 400 | - "Could not find '%s' (%s) in:\n%s" % |
| 401 | - (r, t, json.dumps(report, indent=2))) |
| 402 | - for k in expected[t][r]: |
| 403 | - self.assertTrue(k in report[t][r], |
| 404 | - "Could not find '%s' (%s) in:\n%s" % |
| 405 | - (k, r, json.dumps(report, indent=2))) |
| 406 | - self.assertEqual(expected[t][r][k], report[t][r][k]) |
| 407 | - else: |
| 408 | - for k in expected_counts.keys(): |
| 409 | - if expected_counts[k] is None: |
| 410 | - continue |
| 411 | - self.assertEqual(len(report[k]), expected_counts[k], |
| 412 | - "(%s not equal)\n%s" % |
| 413 | - (k, json.dumps(report, indent=2))) |
| 414 | + common.check_results(self, report, expected_counts, expected) |
| 415 | |
| 416 | def check_manual_review(self, report, check_name, |
| 417 | result_type='error', manual_review=True): |
| 418 | |
| 419 | === added directory 'clickreviews/data' |
| 420 | === added file 'clickreviews/data/icon.png' |
| 421 | Binary files clickreviews/data/icon.png 1970-01-01 00:00:00 +0000 and clickreviews/data/icon.png 2016-02-11 18:32:45 +0000 differ |
| 422 | === modified file 'clickreviews/sr_common.py' |
| 423 | --- clickreviews/sr_common.py 2016-02-10 19:32:10 +0000 |
| 424 | +++ clickreviews/sr_common.py 2016-02-11 18:32:45 +0000 |
| 425 | @@ -92,7 +92,7 @@ |
| 426 | if snap_yaml: |
| 427 | try: |
| 428 | self.snap_yaml = yaml.safe_load(snap_yaml) |
| 429 | - except Exception: |
| 430 | + except Exception: # pragma: nocover |
| 431 | error("Could not load snap.yaml. Is it properly formatted?") |
| 432 | |
| 433 | # default to 'app' |
| 434 | @@ -108,13 +108,21 @@ |
| 435 | if 'type' in self.snap_yaml and self.snap_yaml['type'] == 'gadget': |
| 436 | self.is_snap_gadget = True |
| 437 | |
| 438 | - def _extract_snap_yaml(self): |
| 439 | + # Since coverage is looked at via the testsuite and the testsuite mocks |
| 440 | + # this out, don't cover this |
| 441 | + def _extract_snap_yaml(self): # pragma: nocover |
| 442 | '''Extract and read the snappy 16.04 snap.yaml''' |
| 443 | y = os.path.join(self.unpack_dir, "meta/snap.yaml") |
| 444 | if not os.path.isfile(y): |
| 445 | return None # snappy packaging is still optional |
| 446 | return open_file_read(y) |
| 447 | |
| 448 | + # Since coverage is looked at via the testsuite and the testsuite mocks |
| 449 | + # this out, don't cover this |
| 450 | + def _get_unpack_dir(self): # pragma: nocover |
| 451 | + '''Get unpack directory''' |
| 452 | + return self.unpack_dir |
| 453 | + |
| 454 | def _verify_pkgname(self, n): |
| 455 | '''Verify package name''' |
| 456 | pat = re.compile(r'^[a-z0-9][a-z0-9+-]+$') |
| 457 | |
| 458 | === added file 'clickreviews/sr_lint.py' |
| 459 | --- clickreviews/sr_lint.py 1970-01-01 00:00:00 +0000 |
| 460 | +++ clickreviews/sr_lint.py 2016-02-11 18:32:45 +0000 |
| 461 | @@ -0,0 +1,1203 @@ |
| 462 | +'''sr_lint.py: lint checks''' |
| 463 | +# |
| 464 | +# Copyright (C) 2013-2016 Canonical Ltd. |
| 465 | +# |
| 466 | +# This program is free software: you can redistribute it and/or modify |
| 467 | +# it under the terms of the GNU General Public License as published by |
| 468 | +# the Free Software Foundation; version 3 of the License. |
| 469 | +# |
| 470 | +# This program is distributed in the hope that it will be useful, |
| 471 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 472 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 473 | +# GNU General Public License for more details. |
| 474 | +# |
| 475 | +# You should have received a copy of the GNU General Public License |
| 476 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 477 | + |
| 478 | +from __future__ import print_function |
| 479 | +from clickreviews.frameworks import Frameworks |
| 480 | +from clickreviews.sr_common import ( |
| 481 | + SnapReview, |
| 482 | +) |
| 483 | +from clickreviews.common import ( |
| 484 | + find_external_symlinks, |
| 485 | +) |
| 486 | +import glob |
| 487 | +import os |
| 488 | +import re |
| 489 | + |
| 490 | + |
| 491 | +class SnapReviewLint(SnapReview): |
| 492 | + '''This class represents snap lint reviews''' |
| 493 | + |
| 494 | + def __init__(self, fn, overrides=None): |
| 495 | + '''Set up the class.''' |
| 496 | + SnapReview.__init__(self, fn, "lint-snap-v2", overrides=overrides) |
| 497 | + if not self.is_snap2: |
| 498 | + return |
| 499 | + |
| 500 | + self.valid_compiled_architectures = ['armhf', |
| 501 | + 'i386', |
| 502 | + 'amd64', |
| 503 | + 'arm64', |
| 504 | + ] |
| 505 | + self.valid_architectures = ['all'] + self.valid_compiled_architectures |
| 506 | + self.vcs_files = ['.bzr*', |
| 507 | + # '.excludes', # autogenerated by SDK |
| 508 | + '.git*', |
| 509 | + '.idea', |
| 510 | + '.svn*', |
| 511 | + '.hg', |
| 512 | + '.project', |
| 513 | + 'CVS*', |
| 514 | + 'RCS*' |
| 515 | + ] |
| 516 | + |
| 517 | + self._list_all_compiled_binaries() |
| 518 | + |
| 519 | + # Valid values for 'type' in packaging yaml |
| 520 | + # - app |
| 521 | + # - framework |
| 522 | + # - kernel |
| 523 | + # - gadget |
| 524 | + # - os |
| 525 | + self.valid_snap_types = ['app', |
| 526 | + 'framework', |
| 527 | + 'kernel', |
| 528 | + 'gadget', |
| 529 | + 'os', |
| 530 | + ] |
| 531 | + self.redflagged_snap_types = ['framework', |
| 532 | + 'kernel', |
| 533 | + 'gadget', |
| 534 | + 'os', |
| 535 | + ] |
| 536 | + |
| 537 | + def check_architectures(self): |
| 538 | + '''Check architectures in snap.yaml is valid''' |
| 539 | + if not self.is_snap2: |
| 540 | + return |
| 541 | + |
| 542 | + t = 'info' |
| 543 | + n = self._get_check_name('architecture_valid') |
| 544 | + s = 'OK' |
| 545 | + |
| 546 | + key = 'architectures' |
| 547 | + if key not in self.snap_yaml: |
| 548 | + s = 'OK (%s not specified)' % key |
| 549 | + self._add_result(t, n, s) |
| 550 | + return |
| 551 | + |
| 552 | + if not isinstance(self.snap_yaml[key], list): |
| 553 | + t = 'error' |
| 554 | + s = "invalid %s entry: %s (not a list)" % (key, |
| 555 | + self.snap_yaml[key]) |
| 556 | + else: |
| 557 | + bad_archs = [] |
| 558 | + for arch in self.snap_yaml[key]: |
| 559 | + if arch not in self.valid_architectures: |
| 560 | + bad_archs.append(arch) |
| 561 | + if len(bad_archs) > 0: |
| 562 | + t = 'error' |
| 563 | + s = "invalid multi architecture: %s" % ",".join(bad_archs) |
| 564 | + self._add_result(t, n, s) |
| 565 | + |
| 566 | + def check_description(self): |
| 567 | + '''Check description''' |
| 568 | + if not self.is_snap2: |
| 569 | + return |
| 570 | + |
| 571 | + key = 'description' |
| 572 | + |
| 573 | + t = 'info' |
| 574 | + n = self._get_check_name('%s_present' % key) |
| 575 | + s = 'OK' |
| 576 | + if key not in self.snap_yaml: |
| 577 | + s = 'OK (optional %s field not specified)' % key |
| 578 | + self._add_result(t, n, s) |
| 579 | + return |
| 580 | + self._add_result(t, n, s) |
| 581 | + |
| 582 | + t = 'info' |
| 583 | + n = self._get_check_name(key) |
| 584 | + s = 'OK' |
| 585 | + if not isinstance(self.snap_yaml[key], str): |
| 586 | + t = 'error' |
| 587 | + s = "invalid %s entry: %s (not a str)" % (key, self.snap_yaml[key]) |
| 588 | + self._add_result(t, n, s) |
| 589 | + return |
| 590 | + elif len(self.snap_yaml[key]) < 1: |
| 591 | + t = 'error' |
| 592 | + s = "invalid %s entry (empty)" % (key) |
| 593 | + elif len(self.snap_yaml[key]) < len(self.snap_yaml['name']): |
| 594 | + t = 'info' |
| 595 | + s = "%s is too short: '%s'" % (key, self.snap_yaml[key]) |
| 596 | + self._add_result(t, n, s) |
| 597 | + |
| 598 | + def check_frameworks(self): |
| 599 | + '''Check framework''' |
| 600 | + if not self.is_snap2: |
| 601 | + return |
| 602 | + |
| 603 | + key = 'frameworks' |
| 604 | + |
| 605 | + t = 'info' |
| 606 | + n = self._get_check_name(key) |
| 607 | + l = "http://askubuntu.com/questions/460512/what-framework-should-i-use-in-my-manifest-file" |
| 608 | + |
| 609 | + if key not in self.snap_yaml: |
| 610 | + s = 'OK (%s not specified)' % key |
| 611 | + self._add_result(t, n, s) |
| 612 | + return |
| 613 | + |
| 614 | + if not isinstance(self.snap_yaml[key], list): |
| 615 | + t = 'error' |
| 616 | + s = "invalid %s entry: %s (not a list)" % (key, |
| 617 | + self.snap_yaml[key]) |
| 618 | + self._add_result(t, n, s) |
| 619 | + return |
| 620 | + elif len(self.snap_yaml[key]) < 1: |
| 621 | + t = 'error' |
| 622 | + s = "invalid %s entry (empty)" % (key) |
| 623 | + self._add_result(t, n, s) |
| 624 | + return |
| 625 | + |
| 626 | + framework_overrides = self.overrides.get('framework', {}) |
| 627 | + frameworks = Frameworks(overrides=framework_overrides) |
| 628 | + |
| 629 | + for framework in self.snap_yaml[key]: |
| 630 | + if framework in frameworks.AVAILABLE_FRAMEWORKS: |
| 631 | + t = 'info' |
| 632 | + s = 'OK' |
| 633 | + self._add_result(t, n, s) |
| 634 | + # If it's an available framework, we're done checking |
| 635 | + return |
| 636 | + elif framework in frameworks.DEPRECATED_FRAMEWORKS: |
| 637 | + t = 'warn' |
| 638 | + s = "'%s' is deprecated. Please use a newer framework" % \ |
| 639 | + framework |
| 640 | + self._add_result(t, n, s, l) |
| 641 | + return |
| 642 | + elif framework in frameworks.OBSOLETE_FRAMEWORKS: |
| 643 | + t = 'error' |
| 644 | + s = "'%s' is obsolete. Please use a newer framework" % \ |
| 645 | + framework |
| 646 | + self._add_result(t, n, s, l) |
| 647 | + return |
| 648 | + else: |
| 649 | + # None of the above checks triggered, this is an unknown |
| 650 | + # framework |
| 651 | + t = 'error' |
| 652 | + s = "'%s' is not a supported framework" % \ |
| 653 | + framework |
| 654 | + self._add_result(t, n, s, l) |
| 655 | + |
| 656 | + # TODO: verify this is a field |
| 657 | + def check_license_agreement(self): |
| 658 | + '''Check license-agreement''' |
| 659 | + if not self.is_snap2: |
| 660 | + return |
| 661 | + |
| 662 | + key = 'license-agreement' |
| 663 | + |
| 664 | + t = 'info' |
| 665 | + n = self._get_check_name('%s_present' % key) |
| 666 | + s = 'OK' |
| 667 | + if key not in self.snap_yaml: |
| 668 | + s = 'OK (optional %s field not specified)' % key |
| 669 | + self._add_result(t, n, s) |
| 670 | + return |
| 671 | + self._add_result(t, n, s) |
| 672 | + |
| 673 | + t = 'info' |
| 674 | + n = self._get_check_name(key) |
| 675 | + s = 'OK' |
| 676 | + if not isinstance(self.snap_yaml[key], str): |
| 677 | + t = 'error' |
| 678 | + s = "invalid %s entry: %s (not a str)" % (key, self.snap_yaml[key]) |
| 679 | + self._add_result(t, n, s) |
| 680 | + return |
| 681 | + elif len(self.snap_yaml[key]) < 1: |
| 682 | + t = 'error' |
| 683 | + s = "invalid %s entry (empty)" % (key) |
| 684 | + self._add_result(t, n, s) |
| 685 | + return |
| 686 | + self._add_result(t, n, s) |
| 687 | + |
| 688 | + def check_license_version(self): |
| 689 | + '''license-version''' |
| 690 | + if not self.is_snap2: |
| 691 | + return |
| 692 | + |
| 693 | + key = 'license-version' |
| 694 | + t = 'info' |
| 695 | + n = self._get_check_name('%s_present' % key) |
| 696 | + s = 'OK' |
| 697 | + if key not in self.snap_yaml: |
| 698 | + s = 'OK (optional %s field not specified)' % key |
| 699 | + self._add_result(t, n, s) |
| 700 | + return |
| 701 | + self._add_result(t, n, s) |
| 702 | + |
| 703 | + t = 'info' |
| 704 | + n = self._get_check_name(key) |
| 705 | + s = 'OK' |
| 706 | + if not isinstance(self.snap_yaml[key], str): |
| 707 | + t = 'error' |
| 708 | + s = "invalid %s entry: %s (not a str)" % (key, self.snap_yaml[key]) |
| 709 | + self._add_result(t, n, s) |
| 710 | + return |
| 711 | + elif len(self.snap_yaml[key]) < 1: |
| 712 | + t = 'error' |
| 713 | + s = "invalid %s entry (empty)" % (key) |
| 714 | + self._add_result(t, n, s) |
| 715 | + return |
| 716 | + self._add_result(t, n, s) |
| 717 | + |
| 718 | + def check_name(self): |
| 719 | + '''Check package name''' |
| 720 | + if not self.is_snap2: |
| 721 | + return |
| 722 | + |
| 723 | + t = 'info' |
| 724 | + n = self._get_check_name('name_valid') |
| 725 | + s = 'OK' |
| 726 | + if 'name' not in self.snap_yaml: |
| 727 | + t = 'error' |
| 728 | + s = "could not find 'name' in yaml" |
| 729 | + elif not isinstance(self.snap_yaml['name'], str): |
| 730 | + t = 'error' |
| 731 | + s = "malformed 'name': %s (not a str)" % (self.snap_yaml['name']) |
| 732 | + elif not self._verify_pkgname(self.snap_yaml['name']): |
| 733 | + t = 'error' |
| 734 | + s = "malformed 'name': '%s'" % self.snap_yaml['name'] |
| 735 | + self._add_result(t, n, s) |
| 736 | + |
| 737 | + def check_summary(self): |
| 738 | + '''Check summary''' |
| 739 | + if not self.is_snap2: |
| 740 | + return |
| 741 | + |
| 742 | + key = 'summary' |
| 743 | + |
| 744 | + t = 'info' |
| 745 | + n = self._get_check_name('%s_present' % key) |
| 746 | + s = 'OK' |
| 747 | + if key not in self.snap_yaml: |
| 748 | + s = 'OK (optional %s field not specified)' % key |
| 749 | + self._add_result(t, n, s) |
| 750 | + return |
| 751 | + self._add_result(t, n, s) |
| 752 | + |
| 753 | + t = 'info' |
| 754 | + n = self._get_check_name(key) |
| 755 | + s = 'OK' |
| 756 | + if not isinstance(self.snap_yaml[key], str): |
| 757 | + t = 'error' |
| 758 | + s = "invalid %s entry: %s (not a str)" % (key, self.snap_yaml[key]) |
| 759 | + self._add_result(t, n, s) |
| 760 | + return |
| 761 | + elif len(self.snap_yaml[key]) < 1: |
| 762 | + t = 'error' |
| 763 | + s = "invalid %s entry (empty)" % (key) |
| 764 | + elif len(self.snap_yaml[key]) < len(self.snap_yaml['name']): |
| 765 | + t = 'info' |
| 766 | + s = "%s is too short: '%s'" % (key, self.snap_yaml[key]) |
| 767 | + self._add_result(t, n, s) |
| 768 | + |
| 769 | + def check_type(self): |
| 770 | + '''Check type''' |
| 771 | + if not self.is_snap2 or 'type' not in self.snap_yaml: |
| 772 | + return |
| 773 | + |
| 774 | + t = 'info' |
| 775 | + n = self._get_check_name('snap_type_valid') |
| 776 | + s = 'OK' |
| 777 | + if self.snap_yaml['type'] not in self.valid_snap_types: |
| 778 | + t = 'error' |
| 779 | + s = "unknown 'type': '%s'" % self.snap_yaml['type'] |
| 780 | + self._add_result(t, n, s) |
| 781 | + |
| 782 | + def check_type_redflagged(self): |
| 783 | + '''Check if type is redflagged''' |
| 784 | + if not self.is_snap2 or 'type' not in self.snap_yaml: |
| 785 | + return |
| 786 | + |
| 787 | + t = 'info' |
| 788 | + n = self._get_check_name('snap_type_redflag') |
| 789 | + s = "OK" |
| 790 | + l = None |
| 791 | + manual_review = False |
| 792 | + if self.snap_yaml['type'] in self.redflagged_snap_types: |
| 793 | + t = 'error' |
| 794 | + s = "(NEEDS REVIEW) type '%s' not allowed" % self.snap_yaml['type'] |
| 795 | + manual_review = True |
| 796 | + if self.snap_yaml['type'] == "framework": |
| 797 | + l = "https://developer.ubuntu.com/en/snappy/guides/frameworks/" |
| 798 | + self._add_result(t, n, s, link=l, manual_review=manual_review) |
| 799 | + |
| 800 | + def check_version(self): |
| 801 | + '''Check package version''' |
| 802 | + if not self.is_snap2: |
| 803 | + return |
| 804 | + |
| 805 | + t = 'info' |
| 806 | + n = self._get_check_name('version_valid') |
| 807 | + s = 'OK' |
| 808 | + if 'version' not in self.snap_yaml: |
| 809 | + t = 'error' |
| 810 | + s = "could not find 'version' in yaml" |
| 811 | + elif not self._verify_pkgversion(self.snap_yaml['version']): |
| 812 | + t = 'error' |
| 813 | + s = "malformed 'version': '%s'" % self.snap_yaml['version'] |
| 814 | + self._add_result(t, n, s) |
| 815 | + |
| 816 | + def check_config(self): |
| 817 | + '''Check config''' |
| 818 | + if not self.is_snap2: |
| 819 | + return |
| 820 | + |
| 821 | + fn = os.path.join(self._get_unpack_dir(), 'meta/hooks/config') |
| 822 | + if fn not in self.pkg_files: |
| 823 | + return |
| 824 | + |
| 825 | + t = 'info' |
| 826 | + n = self._get_check_name('config_hook_executable') |
| 827 | + s = 'OK' |
| 828 | + if not self._check_innerpath_executable(fn): |
| 829 | + t = 'error' |
| 830 | + s = 'meta/hooks/config is not executable' |
| 831 | + self._add_result(t, n, s) |
| 832 | + |
| 833 | + def check_icon(self): |
| 834 | + '''Check icon''' |
| 835 | + # see docs/meta.md and docs/gadget.md |
| 836 | + if not self.is_snap2 or 'icon' not in self.snap_yaml: |
| 837 | + return |
| 838 | + |
| 839 | + t = 'info' |
| 840 | + n = self._get_check_name('icon_present') |
| 841 | + s = 'OK' |
| 842 | + if 'type' in self.snap_yaml and self.snap_yaml['type'] != "gadget": |
| 843 | + t = 'warn' |
| 844 | + s = 'icon only used with gadget snaps' |
| 845 | + self._add_result(t, n, s) |
| 846 | + return |
| 847 | + self._add_result(t, n, s) |
| 848 | + |
| 849 | + t = 'info' |
| 850 | + n = self._get_check_name('icon_empty') |
| 851 | + s = 'OK' |
| 852 | + if len(self.snap_yaml['icon']) == 0: |
| 853 | + t = 'error' |
| 854 | + s = "icon entry is empty" |
| 855 | + self._add_result(t, n, s) |
| 856 | + return |
| 857 | + self._add_result(t, n, s) |
| 858 | + |
| 859 | + t = 'info' |
| 860 | + n = self._get_check_name('icon_absolute_path') |
| 861 | + s = 'OK' |
| 862 | + if self.snap_yaml['icon'].startswith('/'): |
| 863 | + t = 'error' |
| 864 | + s = "icon entry '%s' should not specify absolute path" % \ |
| 865 | + self.snap_yaml['icon'] |
| 866 | + self._add_result(t, n, s) |
| 867 | + |
| 868 | + t = 'info' |
| 869 | + n = self._get_check_name('icon_exists') |
| 870 | + s = 'OK' |
| 871 | + fn = self._path_join(self._get_unpack_dir(), self.snap_yaml['icon']) |
| 872 | + if fn not in self.pkg_files: |
| 873 | + t = 'error' |
| 874 | + s = "icon entry '%s' does not exist" % self.snap_yaml['icon'] |
| 875 | + self._add_result(t, n, s) |
| 876 | + |
| 877 | + def check_unknown_entries(self): |
| 878 | + '''Check for any unknown fields''' |
| 879 | + if not self.is_snap2: |
| 880 | + return |
| 881 | + |
| 882 | + t = 'info' |
| 883 | + n = self._get_check_name('unknown_field') |
| 884 | + s = 'OK' |
| 885 | + unknown = [] |
| 886 | + for f in self.snap_yaml: |
| 887 | + if f not in self.snappy_required + self.snappy_optional: |
| 888 | + unknown.append(f) |
| 889 | + if len(unknown) > 0: |
| 890 | + t = 'warn' |
| 891 | + s = "unknown entries in snap.yaml: '%s'" % \ |
| 892 | + (",".join(sorted(unknown))) |
| 893 | + self._add_result(t, n, s) |
| 894 | + |
| 895 | + def check_is_squashfs(self): |
| 896 | + '''Check snapfs''' |
| 897 | + if not self.is_snap2: |
| 898 | + return |
| 899 | + |
| 900 | + # Manual review until have squashfs tests |
| 901 | + t = 'error' |
| 902 | + n = self._get_check_name('is_squashfs') |
| 903 | + s = "(NEEDS REVIEW) squashfs pkg" |
| 904 | + manual_review = True |
| 905 | + self._add_result(t, n, s, manual_review=manual_review) |
| 906 | + |
| 907 | + def check_apps(self): |
| 908 | + '''Check apps''' |
| 909 | + if not self.is_snap2: |
| 910 | + return |
| 911 | + |
| 912 | + key = 'apps' |
| 913 | + |
| 914 | + t = 'info' |
| 915 | + n = self._get_check_name('%s_present' % key) |
| 916 | + s = 'OK' |
| 917 | + if key not in self.snap_yaml: |
| 918 | + s = 'OK (optional %s field not specified)' % key |
| 919 | + self._add_result(t, n, s) |
| 920 | + return |
| 921 | + self._add_result(t, n, s) |
| 922 | + |
| 923 | + t = 'info' |
| 924 | + n = self._get_check_name(key) |
| 925 | + s = 'OK' |
| 926 | + if not isinstance(self.snap_yaml[key], dict): |
| 927 | + t = 'error' |
| 928 | + s = "invalid %s entry: %s (not a dict)" % (key, |
| 929 | + self.snap_yaml[key]) |
| 930 | + self._add_result(t, n, s) |
| 931 | + return |
| 932 | + elif len(self.snap_yaml[key].keys()) < 1: |
| 933 | + t = 'error' |
| 934 | + s = "invalid %s entry (empty)" % (key) |
| 935 | + self._add_result(t, n, s) |
| 936 | + return |
| 937 | + self._add_result(t, n, s) |
| 938 | + |
| 939 | + for app in self.snap_yaml[key]: |
| 940 | + t = 'info' |
| 941 | + n = self._get_check_name('%s_entry' % key, app=app) |
| 942 | + s = 'OK' |
| 943 | + |
| 944 | + if not isinstance(self.snap_yaml[key][app], dict): |
| 945 | + t = 'error' |
| 946 | + s = "invalid entry: %s (not a dict)" % ( |
| 947 | + self.snap_yaml[key][app]) |
| 948 | + self._add_result(t, n, s) |
| 949 | + continue |
| 950 | + elif len(self.snap_yaml[key][app].keys()) < 1: |
| 951 | + t = 'error' |
| 952 | + s = "invalid entry for '%s' (empty)" % (app) |
| 953 | + self._add_result(t, n, s) |
| 954 | + continue |
| 955 | + self._add_result(t, n, s) |
| 956 | + |
| 957 | + for field in self.apps_required: |
| 958 | + t = 'info' |
| 959 | + n = self._get_check_name('%s_required' % key, app=app) |
| 960 | + s = 'OK' |
| 961 | + if field not in self.snap_yaml[key][app]: |
| 962 | + t = 'error' |
| 963 | + s = "required field '%s' not specified" % field |
| 964 | + self._add_result(t, n, s) |
| 965 | + |
| 966 | + t = 'info' |
| 967 | + n = self._get_check_name('%s_unknown' % key, app=app) |
| 968 | + s = 'OK' |
| 969 | + unknown = [] |
| 970 | + for field in self.snap_yaml[key][app]: |
| 971 | + if field not in self.apps_required + self.apps_optional: |
| 972 | + unknown.append(field) |
| 973 | + if len(unknown) > 0: |
| 974 | + t = 'warn' |
| 975 | + s = "unknown fields: '%s'" % (",".join(sorted(unknown))) |
| 976 | + self._add_result(t, n, s) |
| 977 | + |
| 978 | + def _verify_value_is_file(self, app, key): |
| 979 | + t = 'info' |
| 980 | + n = self._get_check_name('%s' % key, app=app) |
| 981 | + s = 'OK' |
| 982 | + if not isinstance(self.snap_yaml['apps'][app][key], str): |
| 983 | + t = 'error' |
| 984 | + s = "%s '%s' (not a str)" % (key, |
| 985 | + self.snap_yaml['apps'][app][key]) |
| 986 | + self._add_result(t, n, s) |
| 987 | + elif len(self.snap_yaml['apps'][app][key]) < 1: |
| 988 | + t = 'error' |
| 989 | + s = "invalid %s (empty)" % (key) |
| 990 | + self._add_result(t, n, s) |
| 991 | + else: |
| 992 | + fn = self._path_join(self._get_unpack_dir(), |
| 993 | + self.snap_yaml['apps'][app][key]) |
| 994 | + if fn not in self.pkg_files: |
| 995 | + t = 'error' |
| 996 | + s = "%s does not exist" % ( |
| 997 | + self.snap_yaml['apps'][app][key]) |
| 998 | + self._add_result(t, n, s) |
| 999 | + |
| 1000 | + def check_apps_command(self): |
| 1001 | + '''Check apps - command''' |
| 1002 | + if not self.is_snap2 or 'apps' not in self.snap_yaml: |
| 1003 | + return |
| 1004 | + |
| 1005 | + for app in self.snap_yaml['apps']: |
| 1006 | + key = 'command' |
| 1007 | + if key not in self.snap_yaml['apps'][app]: |
| 1008 | + # We check for required elsewhere |
| 1009 | + continue |
| 1010 | + |
| 1011 | + self._verify_value_is_file(app, key) |
| 1012 | + |
| 1013 | + def check_apps_stop(self): |
| 1014 | + '''Check apps - stop''' |
| 1015 | + if not self.is_snap2 or 'apps' not in self.snap_yaml: |
| 1016 | + return |
| 1017 | + |
| 1018 | + for app in self.snap_yaml['apps']: |
| 1019 | + key = 'stop' |
| 1020 | + if key not in self.snap_yaml['apps'][app]: |
| 1021 | + # We check for required elsewhere |
| 1022 | + continue |
| 1023 | + |
| 1024 | + self._verify_value_is_file(app, key) |
| 1025 | + |
| 1026 | + def check_apps_poststop(self): |
| 1027 | + '''Check apps - poststop''' |
| 1028 | + if not self.is_snap2 or 'apps' not in self.snap_yaml: |
| 1029 | + return |
| 1030 | + |
| 1031 | + for app in self.snap_yaml['apps']: |
| 1032 | + key = 'poststop' |
| 1033 | + if key not in self.snap_yaml['apps'][app]: |
| 1034 | + # We check for required elsewhere |
| 1035 | + continue |
| 1036 | + |
| 1037 | + self._verify_value_is_file(app, key) |
| 1038 | + |
| 1039 | + def check_apps_stop_timeout(self): |
| 1040 | + '''Check apps - stop-timeout''' |
| 1041 | + if not self.is_snap2 or 'apps' not in self.snap_yaml: |
| 1042 | + return |
| 1043 | + |
| 1044 | + for app in self.snap_yaml['apps']: |
| 1045 | + key = 'stop-timeout' |
| 1046 | + if key not in self.snap_yaml['apps'][app]: |
| 1047 | + # We check for required elsewhere |
| 1048 | + continue |
| 1049 | + |
| 1050 | + t = 'info' |
| 1051 | + n = self._get_check_name('%s' % key, app=app) |
| 1052 | + s = "OK" |
| 1053 | + if not isinstance(self.snap_yaml['apps'][app][key], int) and \ |
| 1054 | + not isinstance(self.snap_yaml['apps'][app][key], str): |
| 1055 | + t = 'error' |
| 1056 | + s = "'%s' is not a string or integer" % key |
| 1057 | + elif not re.search(r'[0-9]+[ms]?$', |
| 1058 | + str(self.snap_yaml['apps'][app][key])): |
| 1059 | + t = 'error' |
| 1060 | + s = "'%s' is not of form NN[ms] (%s)" % \ |
| 1061 | + (self.snap_yaml['apps'][app][key], key) |
| 1062 | + self._add_result(t, n, s) |
| 1063 | + |
| 1064 | + if t == 'error': |
| 1065 | + continue |
| 1066 | + |
| 1067 | + t = 'info' |
| 1068 | + n = self._get_check_name('%s_range' % key, app=app) |
| 1069 | + s = "OK" |
| 1070 | + st = int(str(self.snap_yaml['apps'][app][key]).rstrip(r'[ms]')) |
| 1071 | + if st < 0 or st > 60: |
| 1072 | + t = 'error' |
| 1073 | + s = "stop-timeout '%d' out of range (0-60)" % \ |
| 1074 | + self.snap_yaml['apps'][app][key] |
| 1075 | + self._add_result(t, n, s) |
| 1076 | + |
| 1077 | + def _verify_valid_values(self, app, key, valid): |
| 1078 | + '''Verify valid values for key in app''' |
| 1079 | + t = 'info' |
| 1080 | + n = self._get_check_name('%s' % key, app=app) |
| 1081 | + s = 'OK' |
| 1082 | + if not isinstance(self.snap_yaml['apps'][app][key], str): |
| 1083 | + t = 'error' |
| 1084 | + s = "%s '%s' (not a str)" % (key, |
| 1085 | + self.snap_yaml['apps'][app][key]) |
| 1086 | + self._add_result(t, n, s) |
| 1087 | + elif len(self.snap_yaml['apps'][app][key]) < 1: |
| 1088 | + t = 'error' |
| 1089 | + s = "invalid %s (empty)" % (key) |
| 1090 | + self._add_result(t, n, s) |
| 1091 | + elif self.snap_yaml['apps'][app][key] not in valid: |
| 1092 | + t = 'error' |
| 1093 | + s = "invalid %s: '%s'" % (key, self.snap_yaml['apps'][app][key]) |
| 1094 | + self._add_result(t, n, s) |
| 1095 | + |
| 1096 | + def check_apps_daemon(self): |
| 1097 | + '''Check apps - daemon''' |
| 1098 | + if not self.is_snap2 or 'apps' not in self.snap_yaml: |
| 1099 | + return |
| 1100 | + |
| 1101 | + valid = ["simple", |
| 1102 | + "forking", |
| 1103 | + "oneshot", |
| 1104 | + "dbus", |
| 1105 | + ] |
| 1106 | + |
| 1107 | + for app in self.snap_yaml['apps']: |
| 1108 | + key = 'daemon' |
| 1109 | + if key not in self.snap_yaml['apps'][app]: |
| 1110 | + # We check for required elsewhere |
| 1111 | + continue |
| 1112 | + |
| 1113 | + self._verify_valid_values(app, key, valid) |
| 1114 | + |
| 1115 | + def check_apps_nondaemon(self): |
| 1116 | + '''Check apps - non-daemon''' |
| 1117 | + if not self.is_snap2 or 'apps' not in self.snap_yaml: |
| 1118 | + return |
| 1119 | + |
| 1120 | + # Certain options require 'daemon' so list the keys that are shared |
| 1121 | + # by services and binaries |
| 1122 | + ok_keys = ['command', 'uses'] |
| 1123 | + |
| 1124 | + for app in self.snap_yaml['apps']: |
| 1125 | + needs_daemon = [] |
| 1126 | + for key in self.snap_yaml['apps'][app]: |
| 1127 | + if key not in self.apps_optional or \ |
| 1128 | + key == 'daemon' or \ |
| 1129 | + key in ok_keys or \ |
| 1130 | + 'daemon' in self.snap_yaml['apps'][app]: |
| 1131 | + continue |
| 1132 | + needs_daemon.append(key) |
| 1133 | + |
| 1134 | + t = 'info' |
| 1135 | + n = self._get_check_name('daemon_required', app=app) |
| 1136 | + s = "OK" |
| 1137 | + if len(needs_daemon) > 0: |
| 1138 | + t = 'error' |
| 1139 | + s = "'%s' must be used with 'daemon'" % ",".join(needs_daemon) |
| 1140 | + self._add_result(t, n, s) |
| 1141 | + |
| 1142 | + def check_apps_restart_condition(self): |
| 1143 | + '''Check apps - restart-condition''' |
| 1144 | + if not self.is_snap2 or 'apps' not in self.snap_yaml: |
| 1145 | + return |
| 1146 | + |
| 1147 | + valid = ["always", |
| 1148 | + "never", |
| 1149 | + "on-abnormal", |
| 1150 | + "on-abort", |
| 1151 | + "on-failure", |
| 1152 | + "on-success", |
| 1153 | + ] |
| 1154 | + |
| 1155 | + for app in self.snap_yaml['apps']: |
| 1156 | + key = 'restart-condition' |
| 1157 | + if key not in self.snap_yaml['apps'][app]: |
| 1158 | + # We check for required elsewhere |
| 1159 | + continue |
| 1160 | + |
| 1161 | + self._verify_valid_values(app, key, valid) |
| 1162 | + |
| 1163 | + def check_apps_busname(self): |
| 1164 | + '''Check apps - bus-name''' |
| 1165 | + if not self.is_snap2 or 'apps' not in self.snap_yaml: |
| 1166 | + return |
| 1167 | + |
| 1168 | + for app in self.snap_yaml['apps']: |
| 1169 | + key = 'bus-name' |
| 1170 | + if key not in self.snap_yaml['apps'][app]: |
| 1171 | + # We check for required elsewhere |
| 1172 | + continue |
| 1173 | + |
| 1174 | + t = 'info' |
| 1175 | + n = self._get_check_name('%s_framework' % key, app=app) |
| 1176 | + s = 'OK' |
| 1177 | + if 'type' in self.snap_yaml and \ |
| 1178 | + self.snap_yaml['type'] != 'framework': |
| 1179 | + t = 'error' |
| 1180 | + s = "Use of bus-name requires package be of 'type: framework'" |
| 1181 | + self._add_result(t, n, s) |
| 1182 | + |
| 1183 | + t = 'info' |
| 1184 | + n = self._get_check_name('%s' % key, app=app) |
| 1185 | + s = 'OK' |
| 1186 | + l = None |
| 1187 | + if not isinstance(self.snap_yaml['apps'][app][key], str): |
| 1188 | + t = 'error' |
| 1189 | + s = "%s '%s' (not a str)" % (key, |
| 1190 | + self.snap_yaml['apps'][app][key]) |
| 1191 | + elif len(self.snap_yaml['apps'][app][key]) < 1: |
| 1192 | + t = 'error' |
| 1193 | + s = "invalid %s (empty)" % (key) |
| 1194 | + elif not re.search( |
| 1195 | + r'^[A-Za-z0-9][A-Za-z0-9_-]*(\.[A-Za-z0-9][A-Za-z0-9_-]*)+$', |
| 1196 | + self.snap_yaml['apps'][app][key]): |
| 1197 | + t = 'error' |
| 1198 | + l = 'http://dbus.freedesktop.org/doc/dbus-specification.html' |
| 1199 | + s = "'%s' is not of form '^[A-Za-z0-9][A-Za-z0-9_-]*(\\.[A-Za-z0-9][A-Za-z0-9_-]*)+$'" % \ |
| 1200 | + (self.snap_yaml['apps'][app][key]) |
| 1201 | + self._add_result(t, n, s, l) |
| 1202 | + if t == 'error': |
| 1203 | + continue |
| 1204 | + |
| 1205 | + t = 'info' |
| 1206 | + n = self._get_check_name('%s_matches_name' % key, app=app) |
| 1207 | + s = 'OK' |
| 1208 | + suggested = [self.snap_yaml['name'], |
| 1209 | + "%s.%s" % (self.snap_yaml['name'], app) |
| 1210 | + ] |
| 1211 | + found = False |
| 1212 | + for name in suggested: |
| 1213 | + if self.snap_yaml['apps'][app][key].endswith(name): |
| 1214 | + found = True |
| 1215 | + break |
| 1216 | + if not found: |
| 1217 | + t = 'error' |
| 1218 | + s = "'%s' doesn't end with one of: %s" % \ |
| 1219 | + (self.snap_yaml['apps'][app][key], ", ".join(suggested)) |
| 1220 | + self._add_result(t, n, s) |
| 1221 | + |
| 1222 | + def check_apps_ports(self): |
| 1223 | + '''Check apps - ports''' |
| 1224 | + if not self.is_snap2 or 'apps' not in self.snap_yaml: |
| 1225 | + return |
| 1226 | + |
| 1227 | + valid_keys = ['internal', 'external'] |
| 1228 | + valid_subkeys = ['port', 'negotiable'] |
| 1229 | + for app in self.snap_yaml['apps']: |
| 1230 | + if 'ports' not in self.snap_yaml['apps'][app]: |
| 1231 | + # We check for required elsewhere |
| 1232 | + continue |
| 1233 | + |
| 1234 | + t = 'info' |
| 1235 | + n = self._get_check_name('ports', app=app) |
| 1236 | + s = 'OK' |
| 1237 | + l = None |
| 1238 | + if not isinstance(self.snap_yaml['apps'][app]['ports'], dict): |
| 1239 | + t = 'error' |
| 1240 | + s = "ports '%s' (not a dict)" % ( |
| 1241 | + self.snap_yaml['apps'][app]['ports']) |
| 1242 | + elif len(self.snap_yaml['apps'][app]['ports'].keys()) < 1: |
| 1243 | + t = 'error' |
| 1244 | + s = "'ports' must contain 'internal' and/or 'external'" |
| 1245 | + self._add_result(t, n, s, l) |
| 1246 | + if t == 'error': |
| 1247 | + continue |
| 1248 | + |
| 1249 | + # unknown |
| 1250 | + unknown = [] |
| 1251 | + for key in self.snap_yaml['apps'][app]['ports']: |
| 1252 | + if key not in valid_keys: |
| 1253 | + unknown.append(key) |
| 1254 | + if len(unknown) > 0: |
| 1255 | + t = 'error' |
| 1256 | + n = self._get_check_name('ports_unknown_key', extra=key, |
| 1257 | + app=app) |
| 1258 | + s = "Unknown '%s' for ports" % (",".join(unknown)) |
| 1259 | + self._add_result(t, n, s) |
| 1260 | + |
| 1261 | + port_pat = re.compile(r'^[0-9]+/[a-z0-9\-]+$') |
| 1262 | + for key in valid_keys: |
| 1263 | + if key not in self.snap_yaml['apps'][app]['ports']: |
| 1264 | + continue |
| 1265 | + |
| 1266 | + if len(self.snap_yaml['apps'][app]['ports'][key].keys()) < 1: |
| 1267 | + t = 'error' |
| 1268 | + n = self._get_check_name('ports', extra=key, app=app) |
| 1269 | + s = 'Could not find any %s ports' % key |
| 1270 | + self._add_result(t, n, s) |
| 1271 | + continue |
| 1272 | + |
| 1273 | + for tagname in self.snap_yaml['apps'][app]['ports'][key]: |
| 1274 | + entry = self.snap_yaml['apps'][app]['ports'][key][tagname] |
| 1275 | + if len(entry.keys()) < 1 or ('negotiable' not in entry and |
| 1276 | + 'port' not in entry): |
| 1277 | + t = 'error' |
| 1278 | + n = self._get_check_name('ports', extra=key, app=app) |
| 1279 | + s = "Could not find 'port' or 'negotiable' in '%s'" % \ |
| 1280 | + tagname |
| 1281 | + self._add_result(t, n, s) |
| 1282 | + continue |
| 1283 | + |
| 1284 | + # unknown |
| 1285 | + unknown = [] |
| 1286 | + for subkey in entry: |
| 1287 | + if subkey not in valid_subkeys: |
| 1288 | + unknown.append(subkey) |
| 1289 | + if len(unknown) > 0: |
| 1290 | + t = 'error' |
| 1291 | + n = self._get_check_name('ports_unknown_subkey', |
| 1292 | + extra=key, app=app) |
| 1293 | + s = "Unknown '%s' for %s" % (",".join(unknown), |
| 1294 | + tagname) |
| 1295 | + self._add_result(t, n, s) |
| 1296 | + |
| 1297 | + # port |
| 1298 | + subkey = 'port' |
| 1299 | + t = 'info' |
| 1300 | + n = self._get_check_name('ports_%s_format' % tagname, |
| 1301 | + extra=subkey) |
| 1302 | + s = 'OK' |
| 1303 | + if subkey not in entry: |
| 1304 | + s = 'OK (skipped, not found)' |
| 1305 | + elif not isinstance(entry[subkey], str): |
| 1306 | + t = 'error' |
| 1307 | + s = "invalid entry: %s (not a str)" % (entry[subkey]) |
| 1308 | + else: |
| 1309 | + tmp = entry[subkey].split('/') |
| 1310 | + if not port_pat.search(entry[subkey]) or \ |
| 1311 | + int(tmp[0]) < 1 or int(tmp[0]) > 65535: |
| 1312 | + t = 'error' |
| 1313 | + s = "'%s' should be of form " % entry[subkey] + \ |
| 1314 | + "'port/protocol' where port is an integer " + \ |
| 1315 | + "(1-65535) and protocol is found in " + \ |
| 1316 | + "/etc/protocols" |
| 1317 | + self._add_result(t, n, s) |
| 1318 | + |
| 1319 | + # negotiable |
| 1320 | + subkey = 'negotiable' |
| 1321 | + t = 'info' |
| 1322 | + n = self._get_check_name('ports_%s_format' % tagname, |
| 1323 | + extra=subkey) |
| 1324 | + s = 'OK' |
| 1325 | + if subkey not in entry: |
| 1326 | + s = 'OK (skipped, not found)' |
| 1327 | + elif not isinstance(entry[subkey], bool): |
| 1328 | + t = 'error' |
| 1329 | + s = "'%s: %s' should be either 'yes' or 'no'" % \ |
| 1330 | + (subkey, entry[subkey]) |
| 1331 | + self._add_result(t, n, s) |
| 1332 | + |
| 1333 | + def check_apps_socket(self): |
| 1334 | + '''Check apps - socket''' |
| 1335 | + if not self.is_snap2 or 'apps' not in self.snap_yaml: |
| 1336 | + return |
| 1337 | + |
| 1338 | + for app in self.snap_yaml['apps']: |
| 1339 | + key = 'socket' |
| 1340 | + if key not in self.snap_yaml['apps'][app]: |
| 1341 | + # We check for required elsewhere |
| 1342 | + continue |
| 1343 | + |
| 1344 | + t = 'info' |
| 1345 | + n = self._get_check_name(key, app=app) |
| 1346 | + s = 'OK' |
| 1347 | + if not isinstance(self.snap_yaml['apps'][app][key], bool): |
| 1348 | + t = 'error' |
| 1349 | + s = "'%s: %s' should be either 'yes' or 'no'" % ( |
| 1350 | + key, self.snap_yaml['apps'][app][key]) |
| 1351 | + elif 'listen-stream' not in self.snap_yaml['apps'][app]: |
| 1352 | + t = 'error' |
| 1353 | + s = "'socket' specified without 'listen-stream'" |
| 1354 | + self._add_result(t, n, s) |
| 1355 | + |
| 1356 | + def check_apps_listen_stream(self): |
| 1357 | + '''Check apps - listen-stream''' |
| 1358 | + if not self.is_snap2 or 'apps' not in self.snap_yaml: |
| 1359 | + return |
| 1360 | + |
| 1361 | + for app in self.snap_yaml['apps']: |
| 1362 | + key = 'listen-stream' |
| 1363 | + if key not in self.snap_yaml['apps'][app]: |
| 1364 | + # We check for required elsewhere |
| 1365 | + continue |
| 1366 | + |
| 1367 | + t = 'info' |
| 1368 | + n = self._get_check_name(key, app=app) |
| 1369 | + s = 'OK' |
| 1370 | + if not isinstance(self.snap_yaml['apps'][app][key], str): |
| 1371 | + t = 'error' |
| 1372 | + s = "invalid entry: %s (not a str)" % ( |
| 1373 | + self.snap_yaml['apps'][app][key]) |
| 1374 | + elif len(self.snap_yaml['apps'][app][key]) == 0: |
| 1375 | + t = 'error' |
| 1376 | + s = "'%s' is empty" % key |
| 1377 | + self._add_result(t, n, s) |
| 1378 | + if t == 'error': |
| 1379 | + continue |
| 1380 | + |
| 1381 | + t = 'info' |
| 1382 | + n = self._get_check_name('%s_matches_name' % key, app=app) |
| 1383 | + s = 'OK' |
| 1384 | + sock = self.snap_yaml['apps'][app][key] |
| 1385 | + pkgname = self.snap_yaml['name'] |
| 1386 | + if sock.startswith('@'): |
| 1387 | + if sock != '@%s' % pkgname and \ |
| 1388 | + not sock.startswith('@%s_' % pkgname): |
| 1389 | + t = 'error' |
| 1390 | + s = ("abstract socket '%s' is neither '%s' nor starts " |
| 1391 | + "with '%s'" % (sock, '@%s' % pkgname, |
| 1392 | + '@%s_' % pkgname)) |
| 1393 | + elif sock.startswith('/'): |
| 1394 | + found = False |
| 1395 | + for path in ["/tmp/", |
| 1396 | + "/var/lib/snaps/%s/" % pkgname, |
| 1397 | + "/var/lib/snaps/%s." % pkgname, |
| 1398 | + "/run/shm/snaps/%s/" % pkgname, |
| 1399 | + "/run/shm/snaps/%s." % pkgname]: |
| 1400 | + if sock.startswith(path): |
| 1401 | + found = True |
| 1402 | + break |
| 1403 | + if not found: |
| 1404 | + t = 'error' |
| 1405 | + s = ("named socket '%s' should be in a writable " |
| 1406 | + "app-specific area or /tmp" % sock) |
| 1407 | + else: |
| 1408 | + t = 'error' |
| 1409 | + s = ("'%s' does not specify an abstract socket (starts " |
| 1410 | + "with '@') or absolute filename" % (sock)) |
| 1411 | + self._add_result(t, n, s) |
| 1412 | + |
| 1413 | + def _verify_valid_socket(self, app, key): |
| 1414 | + '''Verify valid values for socket key''' |
| 1415 | + t = 'info' |
| 1416 | + n = self._get_check_name(key, app=app) |
| 1417 | + s = 'OK' |
| 1418 | + if not isinstance(self.snap_yaml['apps'][app][key], str): |
| 1419 | + t = 'error' |
| 1420 | + s = "invalid entry: %s (not a str)" % ( |
| 1421 | + self.snap_yaml['apps'][app][key]) |
| 1422 | + elif len(self.snap_yaml['apps'][app][key]) == 0: |
| 1423 | + t = 'error' |
| 1424 | + s = "'%s' is empty" % key |
| 1425 | + elif 'listen-stream' not in self.snap_yaml['apps'][app]: |
| 1426 | + t = 'error' |
| 1427 | + s = "'%s' specified without 'listen-stream'" % key |
| 1428 | + self._add_result(t, n, s) |
| 1429 | + if t == 'error': |
| 1430 | + return |
| 1431 | + |
| 1432 | + t = 'error' |
| 1433 | + n = self._get_check_name('%s_reserved' % key, app=app) |
| 1434 | + s = "'%s' should not be used until snappy supports per-app users" \ |
| 1435 | + % key |
| 1436 | + self._add_result(t, n, s) |
| 1437 | + |
| 1438 | + t = 'info' |
| 1439 | + n = self._get_check_name("%s_matches_name" % key, app=app) |
| 1440 | + s = 'OK' |
| 1441 | + if self.snap_yaml['apps'][app][key] != self.snap_yaml['name']: |
| 1442 | + t = 'error' |
| 1443 | + s = "'%s' != '%s'" % (self.snap_yaml['apps'][app][key], |
| 1444 | + self.snap_yaml['name']) |
| 1445 | + self._add_result(t, n, s) |
| 1446 | + |
| 1447 | + def check_apps_socket_user(self): |
| 1448 | + '''Check apps - socket-user''' |
| 1449 | + if not self.is_snap2 or 'apps' not in self.snap_yaml: |
| 1450 | + return |
| 1451 | + |
| 1452 | + for app in self.snap_yaml['apps']: |
| 1453 | + key = 'socket-user' |
| 1454 | + if key not in self.snap_yaml['apps'][app]: |
| 1455 | + # We check for required elsewhere |
| 1456 | + continue |
| 1457 | + |
| 1458 | + self._verify_valid_socket(app, key) |
| 1459 | + |
| 1460 | + def check_apps_socket_group(self): |
| 1461 | + '''Check apps - socket-group''' |
| 1462 | + if not self.is_snap2 or 'apps' not in self.snap_yaml: |
| 1463 | + return |
| 1464 | + |
| 1465 | + for app in self.snap_yaml['apps']: |
| 1466 | + key = 'socket-group' |
| 1467 | + if key not in self.snap_yaml['apps'][app]: |
| 1468 | + # We check for required elsewhere |
| 1469 | + continue |
| 1470 | + |
| 1471 | + self._verify_valid_socket(app, key) |
| 1472 | + |
| 1473 | + def check_uses(self): |
| 1474 | + '''Check uses''' |
| 1475 | + if not self.is_snap2 or 'uses' not in self.snap_yaml: |
| 1476 | + return |
| 1477 | + |
| 1478 | + for slot in self.snap_yaml['uses']: |
| 1479 | + # If the 'type' name is the same as the 'slot' name, then 'type' |
| 1480 | + # is optional since the type name and the slot name are the same |
| 1481 | + skill_type = slot |
| 1482 | + if 'type' in self.snap_yaml['uses'][slot]: |
| 1483 | + skill_type = self.snap_yaml['uses'][slot]['type'] |
| 1484 | + |
| 1485 | + key = 'type' |
| 1486 | + t = 'info' |
| 1487 | + n = self._get_check_name(key, extra=slot) |
| 1488 | + s = 'OK' |
| 1489 | + if not isinstance(self.snap_yaml['uses'][slot][key], str): |
| 1490 | + t = 'error' |
| 1491 | + s = "invalid %s: %s (not a str)" % \ |
| 1492 | + (key, self.snap_yaml['uses'][slot][key]) |
| 1493 | + elif len(self.snap_yaml['uses'][slot][key]) == 0: |
| 1494 | + t = 'error' |
| 1495 | + s = "'%s' is empty" % key |
| 1496 | + self._add_result(t, n, s) |
| 1497 | + if t == 'error': |
| 1498 | + continue |
| 1499 | + |
| 1500 | + t = 'info' |
| 1501 | + n = self._get_check_name(skill_type, extra=slot) |
| 1502 | + s = 'OK' |
| 1503 | + if skill_type not in self.skill_types: |
| 1504 | + t = 'error' |
| 1505 | + s = "unknown skill type '%s'" % skill_type |
| 1506 | + self._add_result(t, n, s) |
| 1507 | + if t == 'error': |
| 1508 | + continue |
| 1509 | + |
| 1510 | + min = 1 |
| 1511 | + if 'type' in self.snap_yaml['uses'][slot]: |
| 1512 | + min = 2 |
| 1513 | + t = 'info' |
| 1514 | + n = self._get_check_name('attributes') |
| 1515 | + s = 'OK' |
| 1516 | + if len(self.snap_yaml['uses'][slot]) < min: |
| 1517 | + t = 'error' |
| 1518 | + s = "'%s' has no attributes" % slot |
| 1519 | + self._add_result(t, n, s) |
| 1520 | + if t == 'error': |
| 1521 | + continue |
| 1522 | + |
| 1523 | + for attrib in self.snap_yaml['uses'][slot]: |
| 1524 | + if attrib == 'type': |
| 1525 | + continue |
| 1526 | + t = 'info' |
| 1527 | + n = self._get_check_name('attributes', app=slot, extra=attrib) |
| 1528 | + s = "OK" |
| 1529 | + if attrib not in self.skill_types[skill_type]: |
| 1530 | + t = 'error' |
| 1531 | + s = "unknown attribute '%s' for type '%s'" % (attrib, |
| 1532 | + skill_type) |
| 1533 | + elif not isinstance(self.snap_yaml['uses'][slot][attrib], |
| 1534 | + type(self.skill_types[skill_type][attrib])): |
| 1535 | + t = 'error' |
| 1536 | + s = "'%s' is not '%s'" % \ |
| 1537 | + (attrib, |
| 1538 | + type(self.skill_types[skill_type][attrib]).__name__) |
| 1539 | + self._add_result(t, n, s) |
| 1540 | + |
| 1541 | + def check_apps_uses(self): |
| 1542 | + '''Check uses''' |
| 1543 | + if not self.is_snap2 or 'apps' not in self.snap_yaml: |
| 1544 | + return |
| 1545 | + |
| 1546 | + for app in self.snap_yaml['apps']: |
| 1547 | + key = 'uses' |
| 1548 | + if key not in self.snap_yaml['apps'][app]: |
| 1549 | + continue |
| 1550 | + |
| 1551 | + t = 'info' |
| 1552 | + n = self._get_check_name(key, app=app) |
| 1553 | + s = "OK" |
| 1554 | + if not isinstance(self.snap_yaml['apps'][app][key], list): |
| 1555 | + t = 'error' |
| 1556 | + s = "invalid '%s' entry: '%s' (not a list)" % ( |
| 1557 | + key, self.snap_yaml['apps'][app][key]) |
| 1558 | + elif len(self.snap_yaml['apps'][app][key]) < 1: |
| 1559 | + t = 'error' |
| 1560 | + s = "invalid %s entry (empty)" % (key) |
| 1561 | + self._add_result(t, n, s) |
| 1562 | + if t == 'error': |
| 1563 | + continue |
| 1564 | + |
| 1565 | + # The skill referenced in the app's 'uses' field can either be a |
| 1566 | + # known skill type (when the type name and the name of the skill is |
| 1567 | + # the same) or can reference a name in the snap's toplevel 'uses' |
| 1568 | + # mapping |
| 1569 | + for slot_ref in self.snap_yaml['apps'][app][key]: |
| 1570 | + t = 'info' |
| 1571 | + n = self._get_check_name('uses_slot_reference', |
| 1572 | + app=app, |
| 1573 | + extra=slot_ref) |
| 1574 | + s = "OK" |
| 1575 | + if not isinstance(slot_ref, str): |
| 1576 | + t = 'error' |
| 1577 | + s = "invalid slot skill name reference: '%s' (not a str)" \ |
| 1578 | + % slot_ref |
| 1579 | + elif slot_ref not in self.skill_types and \ |
| 1580 | + 'uses' not in self.snap_yaml or \ |
| 1581 | + slot_ref not in self.snap_yaml['uses']: |
| 1582 | + t = 'error' |
| 1583 | + s = "unknown slot skill name reference '%s'" % slot_ref |
| 1584 | + self._add_result(t, n, s) |
| 1585 | + |
| 1586 | + def check_external_symlinks(self): |
| 1587 | + '''Check snap for external symlinks''' |
| 1588 | + if not self.is_snap2: |
| 1589 | + return |
| 1590 | + |
| 1591 | + if 'type' in self.snap_yaml and \ |
| 1592 | + self.snap_yaml['type'] not in ['app', 'framework']: |
| 1593 | + return |
| 1594 | + |
| 1595 | + t = 'info' |
| 1596 | + n = self._get_check_name('external_symlinks') |
| 1597 | + s = 'OK' |
| 1598 | + links = find_external_symlinks(self._get_unpack_dir(), self.pkg_files) |
| 1599 | + if len(links) > 0: |
| 1600 | + t = 'error' |
| 1601 | + s = 'package contains external symlinks: %s' % ', '.join(links) |
| 1602 | + self._add_result(t, n, s) |
| 1603 | + |
| 1604 | + def check_architecture_all(self): |
| 1605 | + '''Check if actually architecture all''' |
| 1606 | + if not self.is_snap2: |
| 1607 | + return |
| 1608 | + |
| 1609 | + if 'architectures' in self.snap_yaml and \ |
| 1610 | + 'all' not in self.snap_yaml['architectures']: |
| 1611 | + return |
| 1612 | + |
| 1613 | + t = 'info' |
| 1614 | + n = self._get_check_name('valid_contents_for_architecture') |
| 1615 | + s = 'OK' |
| 1616 | + |
| 1617 | + # look for compiled code |
| 1618 | + x_binaries = [] |
| 1619 | + for i in self.pkg_bin_files: |
| 1620 | + x_binaries.append(os.path.relpath(i, self._get_unpack_dir())) |
| 1621 | + if len(x_binaries) > 0: |
| 1622 | + t = 'error' |
| 1623 | + s = "found binaries for architecture 'all': %s" % \ |
| 1624 | + ", ".join(x_binaries) |
| 1625 | + self._add_result(t, n, s) |
| 1626 | + |
| 1627 | + def check_architecture_specified_needed(self): |
| 1628 | + '''Check if the specified architecture is actually needed''' |
| 1629 | + if not self.is_snap2: |
| 1630 | + return |
| 1631 | + |
| 1632 | + if 'architectures' in self.snap_yaml and \ |
| 1633 | + 'all' in self.snap_yaml['architectures']: |
| 1634 | + return |
| 1635 | + |
| 1636 | + for arch in self.snap_yaml['architectures']: |
| 1637 | + t = 'info' |
| 1638 | + n = self._get_check_name('architecture_specified_needed', |
| 1639 | + extra=arch) |
| 1640 | + s = 'OK' |
| 1641 | + if len(self.pkg_bin_files) == 0: |
| 1642 | + t = 'warn' |
| 1643 | + s = "Could not find compiled binaries for architecture '%s'" \ |
| 1644 | + % arch |
| 1645 | + self._add_result(t, n, s) |
| 1646 | + |
| 1647 | + def check_vcs(self): |
| 1648 | + '''Check for VCS files in the package''' |
| 1649 | + if not self.is_snap2: |
| 1650 | + return |
| 1651 | + |
| 1652 | + t = 'info' |
| 1653 | + n = self._get_check_name('vcs_files') |
| 1654 | + s = 'OK' |
| 1655 | + found = [] |
| 1656 | + for d in self.vcs_files: |
| 1657 | + entries = glob.glob("%s/%s" % (self._get_unpack_dir(), d)) |
| 1658 | + if len(entries) > 0: |
| 1659 | + for i in entries: |
| 1660 | + found.append(os.path.relpath(i, self.unpack_dir)) |
| 1661 | + if len(found) > 0: |
| 1662 | + t = 'warn' |
| 1663 | + s = 'found VCS files in package: %s' % ", ".join(found) |
| 1664 | + self._add_result(t, n, s) |
| 1665 | |
| 1666 | === modified file 'clickreviews/sr_tests.py' |
| 1667 | --- clickreviews/sr_tests.py 2016-02-10 19:32:10 +0000 |
| 1668 | +++ clickreviews/sr_tests.py 2016-02-11 18:32:45 +0000 |
| 1669 | @@ -15,17 +15,20 @@ |
| 1670 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 1671 | |
| 1672 | import io |
| 1673 | -import json |
| 1674 | import os |
| 1675 | import yaml |
| 1676 | |
| 1677 | from unittest.mock import patch |
| 1678 | from unittest import TestCase |
| 1679 | +from clickreviews.common import ( |
| 1680 | + check_results as common_check_results |
| 1681 | +) |
| 1682 | |
| 1683 | # These should be set in the test cases |
| 1684 | TEST_SNAP_YAML = "" |
| 1685 | TEST_PKGFMT_TYPE = "snap" |
| 1686 | TEST_PKGFMT_VERSION = "16.04" |
| 1687 | +TEST_UNPACK_DIR = "/fake" |
| 1688 | |
| 1689 | |
| 1690 | # |
| 1691 | @@ -81,6 +84,11 @@ |
| 1692 | return (TEST_PKGFMT_TYPE, ver) |
| 1693 | |
| 1694 | |
| 1695 | +def __get_unpack_dir(self): |
| 1696 | + '''Pretend we found the unpack dir''' |
| 1697 | + return TEST_UNPACK_DIR |
| 1698 | + |
| 1699 | + |
| 1700 | def create_patches(): |
| 1701 | # http://docs.python.org/3.4/library/unittest.mock-examples.html |
| 1702 | # Mock patching. Don't use decorators but instead patch in setUp() of the |
| 1703 | @@ -116,6 +124,10 @@ |
| 1704 | 'clickreviews.common.Review._check_innerpath_executable', |
| 1705 | _check_innerpath_executable)) |
| 1706 | |
| 1707 | + # sr_common |
| 1708 | + patches.append(patch('clickreviews.sr_common.SnapReview._get_unpack_dir', |
| 1709 | + __get_unpack_dir)) |
| 1710 | + |
| 1711 | # pkgfmt |
| 1712 | patches.append(patch("clickreviews.sr_common.SnapReview._pkgfmt_type", |
| 1713 | _pkgfmt_type)) |
| 1714 | @@ -133,7 +145,6 @@ |
| 1715 | self._reset_test_data() |
| 1716 | |
| 1717 | def _reset_test_data(self): |
| 1718 | - # dictionary representing DEBIAN/control |
| 1719 | self.test_snap_yaml = dict() |
| 1720 | self.set_test_pkgfmt("snap", "16.04") |
| 1721 | |
| 1722 | @@ -162,43 +173,10 @@ |
| 1723 | self.test_snap_yaml["version"], |
| 1724 | self.test_snap_yaml["architectures"][0]) |
| 1725 | |
| 1726 | - # |
| 1727 | - # check_results(report, expected_counts, expected) |
| 1728 | - # Verify exact counts of types |
| 1729 | - # expected_counts={'info': 1, 'warn': 0, 'error': 0} |
| 1730 | - # self.check_results(report, expected_counts) |
| 1731 | - # Verify counts of warn and error types |
| 1732 | - # expected_counts={'info': None, 'warn': 0, 'error': 0} |
| 1733 | - # self.check_results(report, expected_counts) |
| 1734 | - # Verify exact messages: |
| 1735 | - # expected = dict() |
| 1736 | - # expected['info'] = dict() |
| 1737 | - # expected['warn'] = dict() |
| 1738 | - # expected['warn']['skeleton_baz'] = "TODO" |
| 1739 | - # expected['error'] = dict() |
| 1740 | - # self.check_results(r, expected=expected) |
| 1741 | - # |
| 1742 | def check_results(self, report, |
| 1743 | expected_counts={'info': 1, 'warn': 0, 'error': 0}, |
| 1744 | expected=None): |
| 1745 | - if expected is not None: |
| 1746 | - for t in expected.keys(): |
| 1747 | - for r in expected[t]: |
| 1748 | - self.assertTrue(r in report[t], |
| 1749 | - "Could not find '%s' (%s) in:\n%s" % |
| 1750 | - (r, t, json.dumps(report, indent=2))) |
| 1751 | - for k in expected[t][r]: |
| 1752 | - self.assertTrue(k in report[t][r], |
| 1753 | - "Could not find '%s' (%s) in:\n%s" % |
| 1754 | - (k, r, json.dumps(report, indent=2))) |
| 1755 | - self.assertEqual(expected[t][r][k], report[t][r][k]) |
| 1756 | - else: |
| 1757 | - for k in expected_counts.keys(): |
| 1758 | - if expected_counts[k] is None: |
| 1759 | - continue |
| 1760 | - self.assertEqual(len(report[k]), expected_counts[k], |
| 1761 | - "(%s not equal)\n%s" % |
| 1762 | - (k, json.dumps(report, indent=2))) |
| 1763 | + common_check_results(self, report, expected_counts, expected) |
| 1764 | |
| 1765 | def check_manual_review(self, report, check_name, |
| 1766 | result_type='error', manual_review=True): |
| 1767 | @@ -221,6 +199,10 @@ |
| 1768 | TEST_PKGFMT_TYPE = t |
| 1769 | TEST_PKGFMT_VERSION = v |
| 1770 | |
| 1771 | + def set_test_unpack_dir(self, d): |
| 1772 | + global TEST_UNPACK_DIR |
| 1773 | + TEST_UNPACK_DIR = d |
| 1774 | + |
| 1775 | def setUp(self): |
| 1776 | '''Make sure our patches are applied everywhere''' |
| 1777 | patches = create_patches() |
| 1778 | @@ -236,5 +218,7 @@ |
| 1779 | TEST_PKGFMT_TYPE = "snap" |
| 1780 | global TEST_PKGFMT_VERSION |
| 1781 | TEST_PKGFMT_VERSION = "16.04" |
| 1782 | + global TEST_UNPACK_DIR |
| 1783 | + TEST_UNPACK_DIR = "/fake" |
| 1784 | |
| 1785 | self._reset_test_data() |
| 1786 | |
| 1787 | === modified file 'clickreviews/tests/test_cr_lint.py' |
| 1788 | --- clickreviews/tests/test_cr_lint.py 2016-02-09 21:45:25 +0000 |
| 1789 | +++ clickreviews/tests/test_cr_lint.py 2016-02-11 18:32:45 +0000 |
| 1790 | @@ -1940,8 +1940,8 @@ |
| 1791 | return tmp_dir |
| 1792 | |
| 1793 | def test_check_dot_click_root(self): |
| 1794 | - package = utils.make_package(extra_files=['.click/'], |
| 1795 | - output_dir=self.mkdtemp()) |
| 1796 | + package = utils.make_click(extra_files=['.click/'], |
| 1797 | + output_dir=self.mkdtemp()) |
| 1798 | c = ClickReviewLint(package) |
| 1799 | |
| 1800 | c.check_dot_click() |
| 1801 | |
| 1802 | === added file 'clickreviews/tests/test_sr_lint.py' |
| 1803 | --- clickreviews/tests/test_sr_lint.py 1970-01-01 00:00:00 +0000 |
| 1804 | +++ clickreviews/tests/test_sr_lint.py 2016-02-11 18:32:45 +0000 |
| 1805 | @@ -0,0 +1,2396 @@ |
| 1806 | +'''test_sr_lint.py: tests for the sr_lint module''' |
| 1807 | +# |
| 1808 | +# Copyright (C) 2013-2016 Canonical Ltd. |
| 1809 | +# |
| 1810 | +# This program is free software: you can redistribute it and/or modify |
| 1811 | +# it under the terms of the GNU General Public License as published by |
| 1812 | +# the Free Software Foundation; version 3 of the License. |
| 1813 | +# |
| 1814 | +# This program is distributed in the hope that it will be useful, |
| 1815 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 1816 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 1817 | +# GNU General Public License for more details. |
| 1818 | +# |
| 1819 | +# You should have received a copy of the GNU General Public License |
| 1820 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 1821 | + |
| 1822 | +from unittest.mock import patch |
| 1823 | +from unittest import TestCase |
| 1824 | +import os |
| 1825 | +import shutil |
| 1826 | +import tempfile |
| 1827 | + |
| 1828 | +from clickreviews.common import cleanup_unpack |
| 1829 | +from clickreviews.common import check_results as common_check_results |
| 1830 | +from clickreviews.sr_lint import SnapReviewLint |
| 1831 | +import clickreviews.sr_tests as sr_tests |
| 1832 | +from clickreviews.tests import utils |
| 1833 | + |
| 1834 | + |
| 1835 | +class TestSnapReviewLint(sr_tests.TestSnapReview): |
| 1836 | + """Tests for the lint review tool.""" |
| 1837 | + def setUp(self): |
| 1838 | + '''Make sure we are snap v2''' |
| 1839 | + super().setUp() |
| 1840 | + self.set_test_pkgfmt("snap", "16.04") |
| 1841 | + |
| 1842 | + def _create_ports(self): |
| 1843 | + ports = {'internal': {'int1': {"port": '8081/tcp', "negotiable": True}}, |
| 1844 | + 'external': {'ext1': {"port": '80/tcp', "negotiable": False}, |
| 1845 | + 'ext2': {"port": '88/udp'} |
| 1846 | + } |
| 1847 | + } |
| 1848 | + return ports |
| 1849 | + |
| 1850 | + def _create_top_uses(self): |
| 1851 | + uses = {'skill-caps': {'type': 'migration-skill', |
| 1852 | + 'caps': ['network-client']}, |
| 1853 | + 'skill-override': {'type': 'migration-skill', |
| 1854 | + 'security-override': {"read_path": "/foo/", |
| 1855 | + "seccomp": "abc"}}, |
| 1856 | + 'skill-policy': {'type': 'migration-skill', |
| 1857 | + 'security-policy': {"apparmor": "meta/aa", |
| 1858 | + "seccomp": "meta/sc"}}, |
| 1859 | + 'skill-template': {'type': 'migration-skill', |
| 1860 | + 'security-template': "unconfined"} |
| 1861 | + } |
| 1862 | + return uses |
| 1863 | + |
| 1864 | + def _create_apps_uses(self): |
| 1865 | + uses = {'app1': {'uses': ['skill-caps']}, |
| 1866 | + 'app2': {'uses': ['skill-caps', 'skill-template']}, |
| 1867 | + 'app3': {'uses': ['skill-template', 'skill-override']}, |
| 1868 | + 'app4': {'uses': ['skill-policy']}, |
| 1869 | + } |
| 1870 | + return uses |
| 1871 | + |
| 1872 | + def patch_frameworks(self): |
| 1873 | + def _mock_frameworks(self, overrides=None): |
| 1874 | + self.FRAMEWORKS = { |
| 1875 | + 'docker-1.3': 'obsolete', |
| 1876 | + 'docker': 'available', |
| 1877 | + 'hello-dbus-fwk': 'available', |
| 1878 | + 'some-fwk': 'deprecated', |
| 1879 | + } |
| 1880 | + self.AVAILABLE_FRAMEWORKS = ['docker', 'hello-dbus-fwk'] |
| 1881 | + self.OBSOLETE_FRAMEWORKS = ['docker-1.3'] |
| 1882 | + self.DEPRECATED_FRAMEWORKS = ['some-fwk'] |
| 1883 | + p = patch('clickreviews.frameworks.Frameworks.__init__', |
| 1884 | + _mock_frameworks) |
| 1885 | + p.start() |
| 1886 | + self.addCleanup(p.stop) |
| 1887 | + |
| 1888 | + def test_all_checks_as_v2(self): |
| 1889 | + '''Test snap v2 has checks''' |
| 1890 | + self.set_test_pkgfmt("snap", "16.04") |
| 1891 | + c = SnapReviewLint(self.test_name) |
| 1892 | + c.do_checks() |
| 1893 | + sum = 0 |
| 1894 | + for i in c.click_report: |
| 1895 | + sum += len(c.click_report[i]) |
| 1896 | + self.assertTrue(sum != 0) |
| 1897 | + |
| 1898 | + def test_all_checks_as_v1(self): |
| 1899 | + '''Test snap v1 has no checks''' |
| 1900 | + self.set_test_pkgfmt("snap", "15.04") |
| 1901 | + c = SnapReviewLint(self.test_name) |
| 1902 | + c.do_checks() |
| 1903 | + sum = 0 |
| 1904 | + for i in c.click_report: |
| 1905 | + sum += len(c.click_report[i]) |
| 1906 | + self.assertTrue(sum == 0) |
| 1907 | + |
| 1908 | + def test_all_checks_as_click(self): |
| 1909 | + '''Test click format has no checks''' |
| 1910 | + self.set_test_pkgfmt("click", "0.4") |
| 1911 | + c = SnapReviewLint(self.test_name) |
| 1912 | + c.do_checks() |
| 1913 | + sum = 0 |
| 1914 | + for i in c.click_report: |
| 1915 | + sum += len(c.click_report[i]) |
| 1916 | + self.assertTrue(sum == 0) |
| 1917 | + |
| 1918 | + def test_check_frameworks_none(self): |
| 1919 | + '''Test check_frameworks() - none''' |
| 1920 | + self.patch_frameworks() |
| 1921 | + self.set_test_snap_yaml("frameworks", None) |
| 1922 | + c = SnapReviewLint(self.test_name) |
| 1923 | + c.check_frameworks() |
| 1924 | + r = c.click_report |
| 1925 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 1926 | + self.check_results(r, expected_counts) |
| 1927 | + |
| 1928 | + def test_check_frameworks_empty(self): |
| 1929 | + '''Test check_frameworks() - empty''' |
| 1930 | + self.patch_frameworks() |
| 1931 | + self.set_test_snap_yaml("frameworks", []) |
| 1932 | + c = SnapReviewLint(self.test_name) |
| 1933 | + c.check_frameworks() |
| 1934 | + r = c.click_report |
| 1935 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 1936 | + self.check_results(r, expected_counts) |
| 1937 | + |
| 1938 | + def test_check_frameworks_multiple(self): |
| 1939 | + '''Test check_frameworks() - multiple''' |
| 1940 | + self.patch_frameworks() |
| 1941 | + self.set_test_snap_yaml("frameworks", ['docker', 'hello-dbus-fwk']) |
| 1942 | + c = SnapReviewLint(self.test_name) |
| 1943 | + c.check_frameworks() |
| 1944 | + r = c.click_report |
| 1945 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 1946 | + self.check_results(r, expected_counts) |
| 1947 | + |
| 1948 | + def test_check_frameworks_bad(self): |
| 1949 | + '''Test check_frameworks() - bad''' |
| 1950 | + self.patch_frameworks() |
| 1951 | + self.set_test_snap_yaml("frameworks", "bad") |
| 1952 | + c = SnapReviewLint(self.test_name) |
| 1953 | + c.check_frameworks() |
| 1954 | + r = c.click_report |
| 1955 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 1956 | + self.check_results(r, expected_counts) |
| 1957 | + |
| 1958 | + def test_check_frameworks_nonexistent(self): |
| 1959 | + '''Test check_frameworks() - nonexistent''' |
| 1960 | + self.patch_frameworks() |
| 1961 | + self.set_test_snap_yaml("frameworks", ["nonexistent"]) |
| 1962 | + c = SnapReviewLint(self.test_name) |
| 1963 | + c.check_frameworks() |
| 1964 | + r = c.click_report |
| 1965 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 1966 | + self.check_results(r, expected_counts) |
| 1967 | + |
| 1968 | + def test_check_frameworks_deprecated(self): |
| 1969 | + '''Test check_frameworks() - deprecated''' |
| 1970 | + self.patch_frameworks() |
| 1971 | + self.set_test_snap_yaml("frameworks", ["some-fwk"]) |
| 1972 | + c = SnapReviewLint(self.test_name) |
| 1973 | + c.check_frameworks() |
| 1974 | + r = c.click_report |
| 1975 | + expected_counts = {'info': None, 'warn': 1, 'error': 0} |
| 1976 | + self.check_results(r, expected_counts) |
| 1977 | + |
| 1978 | + def test_check_frameworks_obsolete(self): |
| 1979 | + '''Test check_frameworks() - obsolete''' |
| 1980 | + self.patch_frameworks() |
| 1981 | + self.set_test_snap_yaml("frameworks", ["docker-1.3"]) |
| 1982 | + c = SnapReviewLint(self.test_name) |
| 1983 | + c.check_frameworks() |
| 1984 | + r = c.click_report |
| 1985 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 1986 | + self.check_results(r, expected_counts) |
| 1987 | + |
| 1988 | + def test_check_name_toplevel(self): |
| 1989 | + '''Test check_name - toplevel''' |
| 1990 | + self.set_test_snap_yaml("name", "foo") |
| 1991 | + c = SnapReviewLint(self.test_name) |
| 1992 | + c.check_name() |
| 1993 | + r = c.click_report |
| 1994 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 1995 | + self.check_results(r, expected_counts) |
| 1996 | + |
| 1997 | + def test_check_name_flat(self): |
| 1998 | + '''Test check_name - obsoleted flat''' |
| 1999 | + self.set_test_snap_yaml("name", "foo.bar") |
| 2000 | + c = SnapReviewLint(self.test_name) |
| 2001 | + c.check_name() |
| 2002 | + r = c.click_report |
| 2003 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2004 | + self.check_results(r, expected_counts) |
| 2005 | + |
| 2006 | + def test_check_name_reverse_domain(self): |
| 2007 | + '''Test check_name - obsoleted reverse domain''' |
| 2008 | + self.set_test_snap_yaml("name", "com.ubuntu.develeper.baz.foo") |
| 2009 | + c = SnapReviewLint(self.test_name) |
| 2010 | + c.check_name() |
| 2011 | + r = c.click_report |
| 2012 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2013 | + self.check_results(r, expected_counts) |
| 2014 | + |
| 2015 | + def test_check_name_bad(self): |
| 2016 | + '''Test check_name - bad''' |
| 2017 | + self.set_test_snap_yaml("name", "foo?bar") |
| 2018 | + c = SnapReviewLint(self.test_name) |
| 2019 | + c.check_name() |
| 2020 | + r = c.click_report |
| 2021 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2022 | + self.check_results(r, expected_counts) |
| 2023 | + |
| 2024 | + def test_check_name_bad2(self): |
| 2025 | + '''Test check_name - empty''' |
| 2026 | + self.set_test_snap_yaml("name", "") |
| 2027 | + c = SnapReviewLint(self.test_name) |
| 2028 | + c.check_name() |
| 2029 | + r = c.click_report |
| 2030 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2031 | + self.check_results(r, expected_counts) |
| 2032 | + |
| 2033 | + def test_check_name_bad3(self): |
| 2034 | + '''Test check_name - list''' |
| 2035 | + self.set_test_snap_yaml("name", []) |
| 2036 | + c = SnapReviewLint(self.test_name) |
| 2037 | + c.check_name() |
| 2038 | + r = c.click_report |
| 2039 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2040 | + self.check_results(r, expected_counts) |
| 2041 | + |
| 2042 | + def test_check_name_bad4(self): |
| 2043 | + '''Test check_name - dict''' |
| 2044 | + self.set_test_snap_yaml("name", {}) |
| 2045 | + c = SnapReviewLint(self.test_name) |
| 2046 | + c.check_name() |
| 2047 | + r = c.click_report |
| 2048 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2049 | + self.check_results(r, expected_counts) |
| 2050 | + |
| 2051 | + def test_check_name_missing(self): |
| 2052 | + '''Test check_name - missing''' |
| 2053 | + self.set_test_snap_yaml("name", None) |
| 2054 | + c = SnapReviewLint(self.test_name) |
| 2055 | + c.check_name() |
| 2056 | + r = c.click_report |
| 2057 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2058 | + self.check_results(r, expected_counts) |
| 2059 | + |
| 2060 | + def test_check_version(self): |
| 2061 | + '''Test check_version''' |
| 2062 | + self.set_test_snap_yaml("version", 1) |
| 2063 | + c = SnapReviewLint(self.test_name) |
| 2064 | + c.check_version() |
| 2065 | + r = c.click_report |
| 2066 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 2067 | + self.check_results(r, expected_counts) |
| 2068 | + |
| 2069 | + def test_check_version1(self): |
| 2070 | + '''Test check_version - integer''' |
| 2071 | + self.set_test_snap_yaml("version", 1) |
| 2072 | + c = SnapReviewLint(self.test_name) |
| 2073 | + c.check_version() |
| 2074 | + r = c.click_report |
| 2075 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 2076 | + self.check_results(r, expected_counts) |
| 2077 | + |
| 2078 | + def test_check_version2(self): |
| 2079 | + '''Test check_version - float''' |
| 2080 | + self.set_test_snap_yaml("version", 1.0) |
| 2081 | + c = SnapReviewLint(self.test_name) |
| 2082 | + c.check_version() |
| 2083 | + r = c.click_report |
| 2084 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 2085 | + self.check_results(r, expected_counts) |
| 2086 | + |
| 2087 | + def test_check_version3(self): |
| 2088 | + '''Test check_version - MAJOR.MINOR.MICRO''' |
| 2089 | + self.set_test_snap_yaml("version", "1.0.1") |
| 2090 | + c = SnapReviewLint(self.test_name) |
| 2091 | + c.check_version() |
| 2092 | + r = c.click_report |
| 2093 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 2094 | + self.check_results(r, expected_counts) |
| 2095 | + |
| 2096 | + def test_check_version4(self): |
| 2097 | + '''Test check_version - str''' |
| 2098 | + self.set_test_snap_yaml("version", "1.0a") |
| 2099 | + c = SnapReviewLint(self.test_name) |
| 2100 | + c.check_version() |
| 2101 | + r = c.click_report |
| 2102 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 2103 | + self.check_results(r, expected_counts) |
| 2104 | + |
| 2105 | + def test_check_version5(self): |
| 2106 | + '''Test check_version - alpha''' |
| 2107 | + self.set_test_snap_yaml("version", "a.b") |
| 2108 | + c = SnapReviewLint(self.test_name) |
| 2109 | + c.check_version() |
| 2110 | + r = c.click_report |
| 2111 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 2112 | + self.check_results(r, expected_counts) |
| 2113 | + |
| 2114 | + def test_check_version_bad(self): |
| 2115 | + '''Test check_version - bad''' |
| 2116 | + self.set_test_snap_yaml("version", "foo?bar") |
| 2117 | + c = SnapReviewLint(self.test_name) |
| 2118 | + c.check_version() |
| 2119 | + r = c.click_report |
| 2120 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2121 | + self.check_results(r, expected_counts) |
| 2122 | + |
| 2123 | + def test_check_version_bad2(self): |
| 2124 | + '''Test check_version - empty''' |
| 2125 | + self.set_test_snap_yaml("version", "") |
| 2126 | + c = SnapReviewLint(self.test_name) |
| 2127 | + c.check_version() |
| 2128 | + r = c.click_report |
| 2129 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2130 | + self.check_results(r, expected_counts) |
| 2131 | + |
| 2132 | + def test_check_version_bad3(self): |
| 2133 | + '''Test check_version - list''' |
| 2134 | + self.set_test_snap_yaml("version", []) |
| 2135 | + c = SnapReviewLint(self.test_name) |
| 2136 | + c.check_version() |
| 2137 | + r = c.click_report |
| 2138 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2139 | + self.check_results(r, expected_counts) |
| 2140 | + |
| 2141 | + def test_check_version_bad4(self): |
| 2142 | + '''Test check_version - dict''' |
| 2143 | + self.set_test_snap_yaml("version", {}) |
| 2144 | + c = SnapReviewLint(self.test_name) |
| 2145 | + c.check_version() |
| 2146 | + r = c.click_report |
| 2147 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2148 | + self.check_results(r, expected_counts) |
| 2149 | + |
| 2150 | + def test_check_version_missing(self): |
| 2151 | + '''Test check_version - missing''' |
| 2152 | + self.set_test_snap_yaml("version", None) |
| 2153 | + c = SnapReviewLint(self.test_name) |
| 2154 | + c.check_version() |
| 2155 | + r = c.click_report |
| 2156 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2157 | + self.check_results(r, expected_counts) |
| 2158 | + |
| 2159 | + def test_check_type(self): |
| 2160 | + '''Test check_type - unspecified''' |
| 2161 | + self.set_test_snap_yaml("type", None) |
| 2162 | + c = SnapReviewLint(self.test_name) |
| 2163 | + c.check_type() |
| 2164 | + r = c.click_report |
| 2165 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 2166 | + self.check_results(r, expected_counts) |
| 2167 | + |
| 2168 | + def test_check_type_app(self): |
| 2169 | + '''Test check_type - app''' |
| 2170 | + self.set_test_snap_yaml("type", "app") |
| 2171 | + c = SnapReviewLint(self.test_name) |
| 2172 | + c.check_type() |
| 2173 | + r = c.click_report |
| 2174 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 2175 | + self.check_results(r, expected_counts) |
| 2176 | + |
| 2177 | + def test_check_type_framework(self): |
| 2178 | + '''Test check_type - framework''' |
| 2179 | + self.set_test_snap_yaml("type", "framework") |
| 2180 | + c = SnapReviewLint(self.test_name) |
| 2181 | + c.check_type() |
| 2182 | + r = c.click_report |
| 2183 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 2184 | + self.check_results(r, expected_counts) |
| 2185 | + |
| 2186 | + def test_check_type_redflagged(self): |
| 2187 | + '''Test check_type_redflagged - unspecified''' |
| 2188 | + self.set_test_snap_yaml("type", None) |
| 2189 | + c = SnapReviewLint(self.test_name) |
| 2190 | + c.check_type_redflagged() |
| 2191 | + r = c.click_report |
| 2192 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 2193 | + self.check_results(r, expected_counts) |
| 2194 | + |
| 2195 | + def test_check_type_redflagged_app(self): |
| 2196 | + '''Test check_type_redflagged - app''' |
| 2197 | + self.set_test_snap_yaml("type", "app") |
| 2198 | + c = SnapReviewLint(self.test_name) |
| 2199 | + c.check_type_redflagged() |
| 2200 | + r = c.click_report |
| 2201 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 2202 | + self.check_results(r, expected_counts) |
| 2203 | + |
| 2204 | + def test_check_type_redflagged_framework(self): |
| 2205 | + '''Test check_type_redflagged - framework''' |
| 2206 | + self.set_test_snap_yaml("type", "framework") |
| 2207 | + c = SnapReviewLint(self.test_name) |
| 2208 | + c.check_type_redflagged() |
| 2209 | + r = c.click_report |
| 2210 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2211 | + self.check_results(r, expected_counts) |
| 2212 | + |
| 2213 | + def test_check_type_redflagged_gadget(self): |
| 2214 | + '''Test check_type_redflagged - gadget''' |
| 2215 | + self.set_test_snap_yaml("type", "gadget") |
| 2216 | + c = SnapReviewLint(self.test_name) |
| 2217 | + c.check_type_redflagged() |
| 2218 | + r = c.click_report |
| 2219 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2220 | + self.check_results(r, expected_counts) |
| 2221 | + |
| 2222 | + def test_check_type_redflagged_kernel(self): |
| 2223 | + '''Test check_type_redflagged - kernel''' |
| 2224 | + self.set_test_snap_yaml("type", "kernel") |
| 2225 | + c = SnapReviewLint(self.test_name) |
| 2226 | + c.check_type_redflagged() |
| 2227 | + r = c.click_report |
| 2228 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2229 | + self.check_results(r, expected_counts) |
| 2230 | + |
| 2231 | + def test_check_type_redflagged_os(self): |
| 2232 | + '''Test check_type_redflagged - os''' |
| 2233 | + self.set_test_snap_yaml("type", "os") |
| 2234 | + c = SnapReviewLint(self.test_name) |
| 2235 | + c.check_type_redflagged() |
| 2236 | + r = c.click_report |
| 2237 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2238 | + self.check_results(r, expected_counts) |
| 2239 | + |
| 2240 | + def test_check_type_unknown(self): |
| 2241 | + '''Test check_type - unknown''' |
| 2242 | + self.set_test_snap_yaml("type", "nonexistent") |
| 2243 | + c = SnapReviewLint(self.test_name) |
| 2244 | + c.check_type() |
| 2245 | + r = c.click_report |
| 2246 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2247 | + self.check_results(r, expected_counts) |
| 2248 | + |
| 2249 | + def test_check_icon(self): |
| 2250 | + '''Test check_icon()''' |
| 2251 | + self.set_test_snap_yaml("icon", "someicon") |
| 2252 | + self.set_test_snap_yaml("type", "gadget") |
| 2253 | + self.set_test_unpack_dir = "/nonexistent" |
| 2254 | + c = SnapReviewLint(self.test_name) |
| 2255 | + c.pkg_files.append(os.path.join(c._get_unpack_dir(), 'someicon')) |
| 2256 | + c.check_icon() |
| 2257 | + r = c.click_report |
| 2258 | + expected_counts = {'info': 4, 'warn': 0, 'error': 0} |
| 2259 | + self.check_results(r, expected_counts) |
| 2260 | + |
| 2261 | + def test_check_icon_no_gadget(self): |
| 2262 | + '''Test check_icon() - no gadget''' |
| 2263 | + self.set_test_snap_yaml("icon", "someicon") |
| 2264 | + self.set_test_unpack_dir = "/nonexistent" |
| 2265 | + c = SnapReviewLint(self.test_name) |
| 2266 | + c.pkg_files.append(os.path.join(c._get_unpack_dir(), 'someicon')) |
| 2267 | + c.check_icon() |
| 2268 | + r = c.click_report |
| 2269 | + expected_counts = {'info': None, 'warn': 1, 'error': 0} |
| 2270 | + self.check_results(r, expected_counts) |
| 2271 | + |
| 2272 | + def test_check_icon_unspecified(self): |
| 2273 | + '''Test check_icon() - unspecified''' |
| 2274 | + self.set_test_snap_yaml("icon", None) |
| 2275 | + self.set_test_snap_yaml("type", "gadget") |
| 2276 | + c = SnapReviewLint(self.test_name) |
| 2277 | + c.check_icon() |
| 2278 | + r = c.click_report |
| 2279 | + expected_counts = {'info': 0, 'warn': 0, 'error': 0} |
| 2280 | + self.check_results(r, expected_counts) |
| 2281 | + |
| 2282 | + def test_check_icon_empty(self): |
| 2283 | + '''Test check_icon() - empty''' |
| 2284 | + self.set_test_snap_yaml("icon", "") |
| 2285 | + self.set_test_snap_yaml("type", "gadget") |
| 2286 | + c = SnapReviewLint(self.test_name) |
| 2287 | + c.check_icon() |
| 2288 | + r = c.click_report |
| 2289 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2290 | + self.check_results(r, expected_counts) |
| 2291 | + |
| 2292 | + def test_check_icon_absolute_path(self): |
| 2293 | + '''Test check_icon() - absolute path''' |
| 2294 | + self.set_test_snap_yaml("icon", "/foo/bar/someicon") |
| 2295 | + self.set_test_snap_yaml("type", "gadget") |
| 2296 | + c = SnapReviewLint(self.test_name) |
| 2297 | + c.pkg_files.append('/foo/bar/someicon') |
| 2298 | + c.check_icon() |
| 2299 | + r = c.click_report |
| 2300 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2301 | + self.check_results(r, expected_counts) |
| 2302 | + |
| 2303 | + def test_check_icon_missing(self): |
| 2304 | + '''Test check_icon() - missing icon''' |
| 2305 | + self.set_test_snap_yaml("icon", "someicon") |
| 2306 | + self.set_test_snap_yaml("type", "gadget") |
| 2307 | + self.set_test_unpack_dir = "/nonexistent" |
| 2308 | + c = SnapReviewLint(self.test_name) |
| 2309 | + # since the icon isn't in c.pkg_files, don't add it for this test |
| 2310 | + # c.pkg_files.append(os.path.join(c._get_unpack_dir(), 'someicon')) |
| 2311 | + c.check_icon() |
| 2312 | + r = c.click_report |
| 2313 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2314 | + self.check_results(r, expected_counts) |
| 2315 | + |
| 2316 | + def test_check_architectures_bad(self): |
| 2317 | + '''Test check_architectures() - bad (dict)''' |
| 2318 | + self.set_test_snap_yaml("architectures", {}) |
| 2319 | + c = SnapReviewLint(self.test_name) |
| 2320 | + c.check_architectures() |
| 2321 | + r = c.click_report |
| 2322 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2323 | + self.check_results(r, expected_counts) |
| 2324 | + |
| 2325 | + def test_check_architectures_missing(self): |
| 2326 | + '''Test check_architectures() (missing)''' |
| 2327 | + self.set_test_snap_yaml("architectures", None) |
| 2328 | + c = SnapReviewLint(self.test_name) |
| 2329 | + c.check_architectures() |
| 2330 | + r = c.click_report |
| 2331 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 2332 | + self.check_results(r, expected_counts) |
| 2333 | + |
| 2334 | + def test_check_architectures_all(self): |
| 2335 | + '''Test check_architectures() (all)''' |
| 2336 | + self.set_test_snap_yaml("architectures", ["all"]) |
| 2337 | + c = SnapReviewLint(self.test_name) |
| 2338 | + c.check_architectures() |
| 2339 | + r = c.click_report |
| 2340 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 2341 | + self.check_results(r, expected_counts) |
| 2342 | + |
| 2343 | + def test_check_architectures_single_armhf(self): |
| 2344 | + '''Test check_architectures() (single arch, armhf)''' |
| 2345 | + self.set_test_snap_yaml("architectures", ["armhf"]) |
| 2346 | + c = SnapReviewLint(self.test_name) |
| 2347 | + c.check_architectures() |
| 2348 | + r = c.click_report |
| 2349 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 2350 | + self.check_results(r, expected_counts) |
| 2351 | + |
| 2352 | + def test_check_architectures_single_arm64(self): |
| 2353 | + '''Test check_architectures() (single arch, arm64)''' |
| 2354 | + self.set_test_snap_yaml("architectures", ["arm64"]) |
| 2355 | + c = SnapReviewLint(self.test_name) |
| 2356 | + c.check_architectures() |
| 2357 | + r = c.click_report |
| 2358 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 2359 | + self.check_results(r, expected_counts) |
| 2360 | + |
| 2361 | + def test_check_architectures_single_i386(self): |
| 2362 | + '''Test check_architectures() (single arch, i386)''' |
| 2363 | + self.set_test_snap_yaml("architectures", ["i386"]) |
| 2364 | + c = SnapReviewLint(self.test_name) |
| 2365 | + c.check_architectures() |
| 2366 | + r = c.click_report |
| 2367 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 2368 | + self.check_results(r, expected_counts) |
| 2369 | + |
| 2370 | + def test_check_architectures_single_amd64(self): |
| 2371 | + '''Test check_architectures() (single arch, amd64)''' |
| 2372 | + self.set_test_snap_yaml("architectures", ["amd64"]) |
| 2373 | + c = SnapReviewLint(self.test_name) |
| 2374 | + c.check_architectures() |
| 2375 | + r = c.click_report |
| 2376 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 2377 | + self.check_results(r, expected_counts) |
| 2378 | + |
| 2379 | + def test_check_architectures_single_nonexistent(self): |
| 2380 | + '''Test check_architectures() (single nonexistent arch)''' |
| 2381 | + self.set_test_snap_yaml("architectures", ["nonexistent"]) |
| 2382 | + c = SnapReviewLint(self.test_name) |
| 2383 | + c.check_architectures() |
| 2384 | + r = c.click_report |
| 2385 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2386 | + self.check_results(r, expected_counts) |
| 2387 | + |
| 2388 | + def test_check_snappy_valid_arch_multi(self): |
| 2389 | + '''Test check_architectures() (valid multi)''' |
| 2390 | + self.set_test_snap_yaml("architectures", ["amd64", "armhf"]) |
| 2391 | + c = SnapReviewLint(self.test_name) |
| 2392 | + c.check_architectures() |
| 2393 | + r = c.click_report |
| 2394 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 2395 | + self.check_results(r, expected_counts) |
| 2396 | + |
| 2397 | + def test_check_snappy_valid_arch_multi2(self): |
| 2398 | + '''Test check_architectures() (valid multi2)''' |
| 2399 | + self.set_test_snap_yaml("architectures", ["armhf", "arm64", "i386"]) |
| 2400 | + c = SnapReviewLint(self.test_name) |
| 2401 | + c.check_architectures() |
| 2402 | + r = c.click_report |
| 2403 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 2404 | + self.check_results(r, expected_counts) |
| 2405 | + |
| 2406 | + def test_check_unknown_entries(self): |
| 2407 | + '''Test check_unknown_entries - none''' |
| 2408 | + c = SnapReviewLint(self.test_name) |
| 2409 | + c.check_unknown_entries() |
| 2410 | + r = c.click_report |
| 2411 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 2412 | + self.check_results(r, expected_counts) |
| 2413 | + |
| 2414 | + def test_check_unknown_entries2(self): |
| 2415 | + '''Test check_unknown_entries - one''' |
| 2416 | + self.set_test_snap_yaml("nonexistent", "bar") |
| 2417 | + c = SnapReviewLint(self.test_name) |
| 2418 | + c.check_unknown_entries() |
| 2419 | + r = c.click_report |
| 2420 | + expected_counts = {'info': 0, 'warn': 1, 'error': 0} |
| 2421 | + self.check_results(r, expected_counts) |
| 2422 | + |
| 2423 | + def test_check_config(self): |
| 2424 | + '''Test check_config()''' |
| 2425 | + c = SnapReviewLint(self.test_name) |
| 2426 | + self.set_test_unpack_dir("/nonexistent") |
| 2427 | + c.pkg_files.append(os.path.join(c._get_unpack_dir(), |
| 2428 | + 'meta/hooks/config')) |
| 2429 | + c.check_config() |
| 2430 | + r = c.click_report |
| 2431 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 2432 | + self.check_results(r, expected_counts) |
| 2433 | + |
| 2434 | + def test_check_config_nonexecutable(self): |
| 2435 | + '''Test check_config() - not executable''' |
| 2436 | + c = SnapReviewLint(self.test_name) |
| 2437 | + self.set_test_unpack_dir("/nonexistent.nonexec") |
| 2438 | + c.pkg_files.append(os.path.join(c._get_unpack_dir(), |
| 2439 | + 'meta/hooks/config')) |
| 2440 | + c.check_config() |
| 2441 | + r = c.click_report |
| 2442 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2443 | + self.check_results(r, expected_counts) |
| 2444 | + |
| 2445 | + def test_check_description(self): |
| 2446 | + '''Test check_description''' |
| 2447 | + self.set_test_snap_yaml("description", "This is a test description") |
| 2448 | + c = SnapReviewLint(self.test_name) |
| 2449 | + c.check_description() |
| 2450 | + r = c.click_report |
| 2451 | + expected_counts = {'info': 2, 'warn': 0, 'error': 0} |
| 2452 | + self.check_results(r, expected_counts) |
| 2453 | + |
| 2454 | + def test_check_description_missing(self): |
| 2455 | + '''Test check_description - not present''' |
| 2456 | + self.set_test_snap_yaml("description", None) |
| 2457 | + c = SnapReviewLint(self.test_name) |
| 2458 | + c.check_description() |
| 2459 | + r = c.click_report |
| 2460 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 2461 | + self.check_results(r, expected_counts) |
| 2462 | + |
| 2463 | + def test_check_description_bad(self): |
| 2464 | + '''Test check_description - short''' |
| 2465 | + self.set_test_snap_yaml("description", "a") |
| 2466 | + c = SnapReviewLint(self.test_name) |
| 2467 | + c.check_description() |
| 2468 | + r = c.click_report |
| 2469 | + expected_counts = {'info': 2, 'warn': 0, 'error': 0} |
| 2470 | + self.check_results(r, expected_counts) |
| 2471 | + |
| 2472 | + def test_check_description_bad2(self): |
| 2473 | + '''Test check_description - empty''' |
| 2474 | + self.set_test_snap_yaml("description", "") |
| 2475 | + c = SnapReviewLint(self.test_name) |
| 2476 | + c.check_description() |
| 2477 | + r = c.click_report |
| 2478 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2479 | + self.check_results(r, expected_counts) |
| 2480 | + |
| 2481 | + def test_check_description_bad3(self): |
| 2482 | + '''Test check_description - list''' |
| 2483 | + self.set_test_snap_yaml("description", []) |
| 2484 | + c = SnapReviewLint(self.test_name) |
| 2485 | + c.check_description() |
| 2486 | + r = c.click_report |
| 2487 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2488 | + self.check_results(r, expected_counts) |
| 2489 | + |
| 2490 | + def test_check_license_agreement(self): |
| 2491 | + '''Test check_license_agreement''' |
| 2492 | + self.set_test_snap_yaml("license-agreement", |
| 2493 | + "This is a test license_agreement") |
| 2494 | + c = SnapReviewLint(self.test_name) |
| 2495 | + c.check_license_agreement() |
| 2496 | + r = c.click_report |
| 2497 | + expected_counts = {'info': 2, 'warn': 0, 'error': 0} |
| 2498 | + self.check_results(r, expected_counts) |
| 2499 | + |
| 2500 | + def test_check_license_agreement_missing(self): |
| 2501 | + '''Test check_license_agreement - not present''' |
| 2502 | + self.set_test_snap_yaml("license-agreement", None) |
| 2503 | + c = SnapReviewLint(self.test_name) |
| 2504 | + c.check_license_agreement() |
| 2505 | + r = c.click_report |
| 2506 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 2507 | + self.check_results(r, expected_counts) |
| 2508 | + |
| 2509 | + def test_check_license_agreement_bad(self): |
| 2510 | + '''Test check_license_agreement - empty''' |
| 2511 | + self.set_test_snap_yaml("license-agreement", "") |
| 2512 | + c = SnapReviewLint(self.test_name) |
| 2513 | + c.check_license_agreement() |
| 2514 | + r = c.click_report |
| 2515 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2516 | + self.check_results(r, expected_counts) |
| 2517 | + |
| 2518 | + def test_check_license_agreement_bad2(self): |
| 2519 | + '''Test check_license_agreement - list''' |
| 2520 | + self.set_test_snap_yaml("license-agreement", []) |
| 2521 | + c = SnapReviewLint(self.test_name) |
| 2522 | + c.check_license_agreement() |
| 2523 | + r = c.click_report |
| 2524 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2525 | + self.check_results(r, expected_counts) |
| 2526 | + |
| 2527 | + def test_check_license_version(self): |
| 2528 | + '''Test check_license_version''' |
| 2529 | + self.set_test_snap_yaml("license-version", |
| 2530 | + "This is a test license_version") |
| 2531 | + c = SnapReviewLint(self.test_name) |
| 2532 | + c.check_license_version() |
| 2533 | + r = c.click_report |
| 2534 | + expected_counts = {'info': 2, 'warn': 0, 'error': 0} |
| 2535 | + self.check_results(r, expected_counts) |
| 2536 | + |
| 2537 | + def test_check_license_version_missing(self): |
| 2538 | + '''Test check_license_version - not present''' |
| 2539 | + self.set_test_snap_yaml("license-version", None) |
| 2540 | + c = SnapReviewLint(self.test_name) |
| 2541 | + c.check_license_version() |
| 2542 | + r = c.click_report |
| 2543 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 2544 | + self.check_results(r, expected_counts) |
| 2545 | + |
| 2546 | + def test_check_license_version_bad(self): |
| 2547 | + '''Test check_license_version - empty''' |
| 2548 | + self.set_test_snap_yaml("license-version", "") |
| 2549 | + c = SnapReviewLint(self.test_name) |
| 2550 | + c.check_license_version() |
| 2551 | + r = c.click_report |
| 2552 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2553 | + self.check_results(r, expected_counts) |
| 2554 | + |
| 2555 | + def test_check_license_version_bad2(self): |
| 2556 | + '''Test check_license_version - list''' |
| 2557 | + self.set_test_snap_yaml("license-version", []) |
| 2558 | + c = SnapReviewLint(self.test_name) |
| 2559 | + c.check_license_version() |
| 2560 | + r = c.click_report |
| 2561 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2562 | + self.check_results(r, expected_counts) |
| 2563 | + |
| 2564 | + def test_check_summary(self): |
| 2565 | + '''Test check_summary''' |
| 2566 | + self.set_test_snap_yaml("summary", "This is a test summary") |
| 2567 | + c = SnapReviewLint(self.test_name) |
| 2568 | + c.check_summary() |
| 2569 | + r = c.click_report |
| 2570 | + expected_counts = {'info': 2, 'warn': 0, 'error': 0} |
| 2571 | + self.check_results(r, expected_counts) |
| 2572 | + |
| 2573 | + def test_check_summary_missing(self): |
| 2574 | + '''Test check_summary - not present''' |
| 2575 | + self.set_test_snap_yaml("summary", None) |
| 2576 | + c = SnapReviewLint(self.test_name) |
| 2577 | + c.check_summary() |
| 2578 | + r = c.click_report |
| 2579 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 2580 | + self.check_results(r, expected_counts) |
| 2581 | + |
| 2582 | + def test_check_summary_bad(self): |
| 2583 | + '''Test check_summary - short''' |
| 2584 | + self.set_test_snap_yaml("summary", "a") |
| 2585 | + c = SnapReviewLint(self.test_name) |
| 2586 | + c.check_summary() |
| 2587 | + r = c.click_report |
| 2588 | + expected_counts = {'info': 2, 'warn': 0, 'error': 0} |
| 2589 | + self.check_results(r, expected_counts) |
| 2590 | + |
| 2591 | + def test_check_summary_bad2(self): |
| 2592 | + '''Test check_summary - empty''' |
| 2593 | + self.set_test_snap_yaml("summary", "") |
| 2594 | + c = SnapReviewLint(self.test_name) |
| 2595 | + c.check_summary() |
| 2596 | + r = c.click_report |
| 2597 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2598 | + self.check_results(r, expected_counts) |
| 2599 | + |
| 2600 | + def test_check_summary_bad3(self): |
| 2601 | + '''Test check_summary - list''' |
| 2602 | + self.set_test_snap_yaml("summary", []) |
| 2603 | + c = SnapReviewLint(self.test_name) |
| 2604 | + c.check_summary() |
| 2605 | + r = c.click_report |
| 2606 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2607 | + self.check_results(r, expected_counts) |
| 2608 | + |
| 2609 | + def test_check_apps_one_command(self): |
| 2610 | + '''Test check_apps() - one command''' |
| 2611 | + self.set_test_snap_yaml("apps", {"foo": {"command": "bin/foo"}, |
| 2612 | + }) |
| 2613 | + c = SnapReviewLint(self.test_name) |
| 2614 | + c.check_apps() |
| 2615 | + r = c.click_report |
| 2616 | + expected_counts = {'info': 5, 'warn': 0, 'error': 0} |
| 2617 | + self.check_results(r, expected_counts) |
| 2618 | + |
| 2619 | + def test_check_apps_one_daemon(self): |
| 2620 | + '''Test check_apps() - one daemon''' |
| 2621 | + self.set_test_snap_yaml("apps", {"foo": {"command": "bin/foo", |
| 2622 | + "daemon": "single"}, |
| 2623 | + }) |
| 2624 | + c = SnapReviewLint(self.test_name) |
| 2625 | + c.check_apps() |
| 2626 | + r = c.click_report |
| 2627 | + expected_counts = {'info': 5, 'warn': 0, 'error': 0} |
| 2628 | + self.check_results(r, expected_counts) |
| 2629 | + |
| 2630 | + def test_check_apps_two_commands(self): |
| 2631 | + '''Test check_apps() - two commands''' |
| 2632 | + self.set_test_snap_yaml("apps", {"foo": {"command": "bin/foo"}, |
| 2633 | + "bar": {"command": "bin/bar"}, |
| 2634 | + }) |
| 2635 | + c = SnapReviewLint(self.test_name) |
| 2636 | + c.check_apps() |
| 2637 | + r = c.click_report |
| 2638 | + expected_counts = {'info': 8, 'warn': 0, 'error': 0} |
| 2639 | + self.check_results(r, expected_counts) |
| 2640 | + |
| 2641 | + def test_check_apps_command_plus_daemon(self): |
| 2642 | + '''Test check_apps() - command and daemon''' |
| 2643 | + self.set_test_snap_yaml("apps", {"foo": {"command": "bin/foo"}, |
| 2644 | + "bar": {"command": "bin/bar", |
| 2645 | + "daemon": "single"}, |
| 2646 | + }) |
| 2647 | + c = SnapReviewLint(self.test_name) |
| 2648 | + c.check_apps() |
| 2649 | + r = c.click_report |
| 2650 | + expected_counts = {'info': 8, 'warn': 0, 'error': 0} |
| 2651 | + self.check_results(r, expected_counts) |
| 2652 | + |
| 2653 | + def test_check_apps_two_daemons(self): |
| 2654 | + '''Test check_apps() - command and daemon''' |
| 2655 | + self.set_test_snap_yaml("apps", {"foo": {"command": "bin/foo", |
| 2656 | + "daemon": "single"}, |
| 2657 | + "bar": {"command": "bin/bar", |
| 2658 | + "daemon": "single"}, |
| 2659 | + }) |
| 2660 | + c = SnapReviewLint(self.test_name) |
| 2661 | + c.check_apps() |
| 2662 | + r = c.click_report |
| 2663 | + expected_counts = {'info': 8, 'warn': 0, 'error': 0} |
| 2664 | + self.check_results(r, expected_counts) |
| 2665 | + |
| 2666 | + def test_check_apps_missing(self): |
| 2667 | + '''Test check_apps() - missing''' |
| 2668 | + self.set_test_snap_yaml("apps", None) |
| 2669 | + c = SnapReviewLint(self.test_name) |
| 2670 | + c.check_apps() |
| 2671 | + r = c.click_report |
| 2672 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 2673 | + self.check_results(r, expected_counts) |
| 2674 | + |
| 2675 | + def test_check_apps_bad(self): |
| 2676 | + '''Test check_apps() - bad''' |
| 2677 | + self.set_test_snap_yaml("apps", []) |
| 2678 | + c = SnapReviewLint(self.test_name) |
| 2679 | + c.check_apps() |
| 2680 | + r = c.click_report |
| 2681 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2682 | + self.check_results(r, expected_counts) |
| 2683 | + |
| 2684 | + def test_check_apps_bad2(self): |
| 2685 | + '''Test check_apps() - empty''' |
| 2686 | + self.set_test_snap_yaml("apps", {}) |
| 2687 | + c = SnapReviewLint(self.test_name) |
| 2688 | + c.check_apps() |
| 2689 | + r = c.click_report |
| 2690 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2691 | + self.check_results(r, expected_counts) |
| 2692 | + |
| 2693 | + def test_check_apps_bad3(self): |
| 2694 | + '''Test check_apps() - missing command''' |
| 2695 | + self.set_test_snap_yaml("apps", {"foo": {"daemon": "single"}, |
| 2696 | + }) |
| 2697 | + c = SnapReviewLint(self.test_name) |
| 2698 | + c.check_apps() |
| 2699 | + r = c.click_report |
| 2700 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2701 | + self.check_results(r, expected_counts) |
| 2702 | + |
| 2703 | + def test_check_apps_bad4(self): |
| 2704 | + '''Test check_apps() - unknown field''' |
| 2705 | + self.set_test_snap_yaml("apps", {"foo": {"command": "bin/foo", |
| 2706 | + "nonexistent": "abc"}, |
| 2707 | + }) |
| 2708 | + c = SnapReviewLint(self.test_name) |
| 2709 | + c.check_apps() |
| 2710 | + r = c.click_report |
| 2711 | + expected_counts = {'info': None, 'warn': 1, 'error': 0} |
| 2712 | + self.check_results(r, expected_counts) |
| 2713 | + |
| 2714 | + def test_check_apps_bad5(self): |
| 2715 | + '''Test check_apps() - invalid field''' |
| 2716 | + self.set_test_snap_yaml("apps", {"foo": []}) |
| 2717 | + c = SnapReviewLint(self.test_name) |
| 2718 | + c.check_apps() |
| 2719 | + r = c.click_report |
| 2720 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2721 | + self.check_results(r, expected_counts) |
| 2722 | + |
| 2723 | + def test_check_apps_bad6(self): |
| 2724 | + '''Test check_apps() - empty fields''' |
| 2725 | + self.set_test_snap_yaml("apps", {"foo": {}}) |
| 2726 | + c = SnapReviewLint(self.test_name) |
| 2727 | + c.check_apps() |
| 2728 | + r = c.click_report |
| 2729 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2730 | + self.check_results(r, expected_counts) |
| 2731 | + |
| 2732 | + def test_check_apps_command(self): |
| 2733 | + '''Test check_apps_command()''' |
| 2734 | + cmd = "bin/foo" |
| 2735 | + self.set_test_snap_yaml("apps", {"foo": {"command": cmd}, |
| 2736 | + }) |
| 2737 | + c = SnapReviewLint(self.test_name) |
| 2738 | + c.pkg_files.append(os.path.join('/fake', cmd)) |
| 2739 | + c.check_apps_command() |
| 2740 | + r = c.click_report |
| 2741 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 2742 | + self.check_results(r, expected_counts) |
| 2743 | + |
| 2744 | + def test_check_apps_command_missing(self): |
| 2745 | + '''Test check_apps_command() - missing''' |
| 2746 | + self.set_test_snap_yaml("apps", {"foo": {}}) |
| 2747 | + c = SnapReviewLint(self.test_name) |
| 2748 | + c.check_apps_command() |
| 2749 | + r = c.click_report |
| 2750 | + expected_counts = {'info': 0, 'warn': 0, 'error': 0} |
| 2751 | + self.check_results(r, expected_counts) |
| 2752 | + |
| 2753 | + def test_check_apps_command_empty(self): |
| 2754 | + '''Test check_apps_command() - empty''' |
| 2755 | + self.set_test_snap_yaml("apps", {"foo": {"command": ""}, |
| 2756 | + }) |
| 2757 | + c = SnapReviewLint(self.test_name) |
| 2758 | + c.check_apps_command() |
| 2759 | + r = c.click_report |
| 2760 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2761 | + self.check_results(r, expected_counts) |
| 2762 | + |
| 2763 | + def test_check_apps_command_invalid(self): |
| 2764 | + '''Test check_apps_command() - list''' |
| 2765 | + self.set_test_snap_yaml("apps", {"foo": {"command": []}, |
| 2766 | + }) |
| 2767 | + c = SnapReviewLint(self.test_name) |
| 2768 | + c.check_apps_command() |
| 2769 | + r = c.click_report |
| 2770 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2771 | + self.check_results(r, expected_counts) |
| 2772 | + |
| 2773 | + def test_check_apps_command_nonexistent(self): |
| 2774 | + '''Test check_apps_command() - nonexistent''' |
| 2775 | + cmd = "bin/foo" |
| 2776 | + self.set_test_snap_yaml("apps", {"foo": {"command": cmd}, |
| 2777 | + }) |
| 2778 | + c = SnapReviewLint(self.test_name) |
| 2779 | + c.check_apps_command() |
| 2780 | + r = c.click_report |
| 2781 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2782 | + self.check_results(r, expected_counts) |
| 2783 | + |
| 2784 | + def test_check_apps_stop(self): |
| 2785 | + '''Test check_apps_stop()''' |
| 2786 | + cmd = "bin/foo" |
| 2787 | + self.set_test_snap_yaml("apps", {"foo": {"stop": cmd}, |
| 2788 | + }) |
| 2789 | + c = SnapReviewLint(self.test_name) |
| 2790 | + c.pkg_files.append(os.path.join('/fake', cmd)) |
| 2791 | + c.check_apps_stop() |
| 2792 | + r = c.click_report |
| 2793 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 2794 | + self.check_results(r, expected_counts) |
| 2795 | + |
| 2796 | + def test_check_apps_stop_missing(self): |
| 2797 | + '''Test check_apps_stop() - missing''' |
| 2798 | + self.set_test_snap_yaml("apps", {"foo": {}}) |
| 2799 | + c = SnapReviewLint(self.test_name) |
| 2800 | + c.check_apps_stop() |
| 2801 | + r = c.click_report |
| 2802 | + expected_counts = {'info': 0, 'warn': 0, 'error': 0} |
| 2803 | + self.check_results(r, expected_counts) |
| 2804 | + |
| 2805 | + def test_check_apps_stop_empty(self): |
| 2806 | + '''Test check_apps_stop() - empty''' |
| 2807 | + self.set_test_snap_yaml("apps", {"foo": {"stop": ""}, |
| 2808 | + }) |
| 2809 | + c = SnapReviewLint(self.test_name) |
| 2810 | + c.check_apps_stop() |
| 2811 | + r = c.click_report |
| 2812 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2813 | + self.check_results(r, expected_counts) |
| 2814 | + |
| 2815 | + def test_check_apps_stop_invalid(self): |
| 2816 | + '''Test check_apps_stop() - list''' |
| 2817 | + self.set_test_snap_yaml("apps", {"foo": {"stop": []}, |
| 2818 | + }) |
| 2819 | + c = SnapReviewLint(self.test_name) |
| 2820 | + c.check_apps_stop() |
| 2821 | + r = c.click_report |
| 2822 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2823 | + self.check_results(r, expected_counts) |
| 2824 | + |
| 2825 | + def test_check_apps_stop_nonexistent(self): |
| 2826 | + '''Test check_apps_stop() - nonexistent''' |
| 2827 | + cmd = "bin/foo" |
| 2828 | + self.set_test_snap_yaml("apps", {"foo": {"stop": cmd}, |
| 2829 | + }) |
| 2830 | + c = SnapReviewLint(self.test_name) |
| 2831 | + c.check_apps_stop() |
| 2832 | + r = c.click_report |
| 2833 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2834 | + self.check_results(r, expected_counts) |
| 2835 | + |
| 2836 | + def test_check_apps_poststop(self): |
| 2837 | + '''Test check_apps_poststop()''' |
| 2838 | + cmd = "bin/foo" |
| 2839 | + self.set_test_snap_yaml("apps", {"foo": {"poststop": cmd}, |
| 2840 | + }) |
| 2841 | + c = SnapReviewLint(self.test_name) |
| 2842 | + c.pkg_files.append(os.path.join('/fake', cmd)) |
| 2843 | + c.check_apps_poststop() |
| 2844 | + r = c.click_report |
| 2845 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 2846 | + self.check_results(r, expected_counts) |
| 2847 | + |
| 2848 | + def test_check_apps_poststop_missing(self): |
| 2849 | + '''Test check_apps_poststop() - missing''' |
| 2850 | + self.set_test_snap_yaml("apps", {"foo": {}}) |
| 2851 | + c = SnapReviewLint(self.test_name) |
| 2852 | + c.check_apps_poststop() |
| 2853 | + r = c.click_report |
| 2854 | + expected_counts = {'info': 0, 'warn': 0, 'error': 0} |
| 2855 | + self.check_results(r, expected_counts) |
| 2856 | + |
| 2857 | + def test_check_apps_poststop_empty(self): |
| 2858 | + '''Test check_apps_poststop() - empty''' |
| 2859 | + self.set_test_snap_yaml("apps", {"foo": {"poststop": ""}, |
| 2860 | + }) |
| 2861 | + c = SnapReviewLint(self.test_name) |
| 2862 | + c.check_apps_poststop() |
| 2863 | + r = c.click_report |
| 2864 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2865 | + self.check_results(r, expected_counts) |
| 2866 | + |
| 2867 | + def test_check_apps_poststop_invalid(self): |
| 2868 | + '''Test check_apps_poststop() - list''' |
| 2869 | + self.set_test_snap_yaml("apps", {"foo": {"poststop": []}, |
| 2870 | + }) |
| 2871 | + c = SnapReviewLint(self.test_name) |
| 2872 | + c.check_apps_poststop() |
| 2873 | + r = c.click_report |
| 2874 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2875 | + self.check_results(r, expected_counts) |
| 2876 | + |
| 2877 | + def test_check_apps_poststop_nonexistent(self): |
| 2878 | + '''Test check_apps_poststop() - nonexistent''' |
| 2879 | + cmd = "bin/foo" |
| 2880 | + self.set_test_snap_yaml("apps", {"foo": {"poststop": cmd}, |
| 2881 | + }) |
| 2882 | + c = SnapReviewLint(self.test_name) |
| 2883 | + c.check_apps_poststop() |
| 2884 | + r = c.click_report |
| 2885 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2886 | + self.check_results(r, expected_counts) |
| 2887 | + |
| 2888 | + def test_check_apps_daemon_simple(self): |
| 2889 | + '''Test check_apps_daemon() - simple''' |
| 2890 | + entry = "simple" |
| 2891 | + self.set_test_snap_yaml("apps", {"foo": {"daemon": entry}}) |
| 2892 | + c = SnapReviewLint(self.test_name) |
| 2893 | + c.check_apps_daemon() |
| 2894 | + r = c.click_report |
| 2895 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 2896 | + self.check_results(r, expected_counts) |
| 2897 | + |
| 2898 | + def test_check_apps_daemon_forking(self): |
| 2899 | + '''Test check_apps_daemon() - forking''' |
| 2900 | + entry = "forking" |
| 2901 | + self.set_test_snap_yaml("apps", {"foo": {"daemon": entry}}) |
| 2902 | + c = SnapReviewLint(self.test_name) |
| 2903 | + c.check_apps_daemon() |
| 2904 | + r = c.click_report |
| 2905 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 2906 | + self.check_results(r, expected_counts) |
| 2907 | + |
| 2908 | + def test_check_apps_daemon_oneshot(self): |
| 2909 | + '''Test check_apps_daemon() - oneshot''' |
| 2910 | + entry = "oneshot" |
| 2911 | + self.set_test_snap_yaml("apps", {"foo": {"daemon": entry}}) |
| 2912 | + c = SnapReviewLint(self.test_name) |
| 2913 | + c.check_apps_daemon() |
| 2914 | + r = c.click_report |
| 2915 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 2916 | + self.check_results(r, expected_counts) |
| 2917 | + |
| 2918 | + def test_check_apps_daemon_dbus(self): |
| 2919 | + '''Test check_apps_daemon() - dbus''' |
| 2920 | + entry = "dbus" |
| 2921 | + self.set_test_snap_yaml("apps", {"foo": {"daemon": entry}}) |
| 2922 | + c = SnapReviewLint(self.test_name) |
| 2923 | + c.check_apps_daemon() |
| 2924 | + r = c.click_report |
| 2925 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 2926 | + self.check_results(r, expected_counts) |
| 2927 | + |
| 2928 | + def test_check_apps_daemon_missing(self): |
| 2929 | + '''Test check_apps_daemon() - missing''' |
| 2930 | + self.set_test_snap_yaml("apps", {"foo": {}}) |
| 2931 | + c = SnapReviewLint(self.test_name) |
| 2932 | + c.check_apps_daemon() |
| 2933 | + r = c.click_report |
| 2934 | + expected_counts = {'info': 0, 'warn': 0, 'error': 0} |
| 2935 | + self.check_results(r, expected_counts) |
| 2936 | + |
| 2937 | + def test_check_apps_daemon_empty(self): |
| 2938 | + '''Test check_apps_daemon() - empty''' |
| 2939 | + self.set_test_snap_yaml("apps", {"foo": {"daemon": ""}, |
| 2940 | + }) |
| 2941 | + c = SnapReviewLint(self.test_name) |
| 2942 | + c.check_apps_daemon() |
| 2943 | + r = c.click_report |
| 2944 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2945 | + self.check_results(r, expected_counts) |
| 2946 | + |
| 2947 | + def test_check_apps_daemon_invalid(self): |
| 2948 | + '''Test check_apps_daemon() - list''' |
| 2949 | + self.set_test_snap_yaml("apps", {"foo": {"daemon": []}, |
| 2950 | + }) |
| 2951 | + c = SnapReviewLint(self.test_name) |
| 2952 | + c.check_apps_daemon() |
| 2953 | + r = c.click_report |
| 2954 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2955 | + self.check_results(r, expected_counts) |
| 2956 | + |
| 2957 | + def test_check_apps_daemon_nonexistent(self): |
| 2958 | + '''Test check_apps_daemon() - nonexistent''' |
| 2959 | + entry = "nonexistent" |
| 2960 | + self.set_test_snap_yaml("apps", {"foo": {"daemon": entry}}) |
| 2961 | + c = SnapReviewLint(self.test_name) |
| 2962 | + c.check_apps_daemon() |
| 2963 | + r = c.click_report |
| 2964 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 2965 | + self.check_results(r, expected_counts) |
| 2966 | + |
| 2967 | + def test_check_apps_nondaemon(self): |
| 2968 | + '''Test check_apps_nondaemon()''' |
| 2969 | + entry = "simple" |
| 2970 | + self.set_test_snap_yaml("apps", {"foo": {"daemon": entry, |
| 2971 | + "stop": "bin/bar"}}) |
| 2972 | + c = SnapReviewLint(self.test_name) |
| 2973 | + c.check_apps_nondaemon() |
| 2974 | + r = c.click_report |
| 2975 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 2976 | + self.check_results(r, expected_counts) |
| 2977 | + |
| 2978 | + def test_check_apps_nondaemon_command(self): |
| 2979 | + '''Test check_apps_nondaemon() - command''' |
| 2980 | + self.set_test_snap_yaml("apps", {"foo": {"command": "bin/bar"}}) |
| 2981 | + c = SnapReviewLint(self.test_name) |
| 2982 | + c.check_apps_nondaemon() |
| 2983 | + r = c.click_report |
| 2984 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 2985 | + self.check_results(r, expected_counts) |
| 2986 | + |
| 2987 | + def test_check_apps_nondaemon_uses(self): |
| 2988 | + '''Test check_apps_nondaemon() - uses''' |
| 2989 | + self.set_test_snap_yaml("apps", {"foo": {"command": "bin/bar", |
| 2990 | + "uses": {}}}) |
| 2991 | + c = SnapReviewLint(self.test_name) |
| 2992 | + c.check_apps_nondaemon() |
| 2993 | + r = c.click_report |
| 2994 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 2995 | + self.check_results(r, expected_counts) |
| 2996 | + |
| 2997 | + def test_check_apps_nondaemon_stop(self): |
| 2998 | + '''Test check_apps_nondaemon() - stop''' |
| 2999 | + self.set_test_snap_yaml("apps", {"foo": {"command": "bin/bar", |
| 3000 | + "stop": "bin/bar"}}) |
| 3001 | + c = SnapReviewLint(self.test_name) |
| 3002 | + c.check_apps_nondaemon() |
| 3003 | + r = c.click_report |
| 3004 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3005 | + self.check_results(r, expected_counts) |
| 3006 | + |
| 3007 | + def test_check_apps_nondaemon_stop_timeout(self): |
| 3008 | + '''Test check_apps_nondaemon() - stop-timeout''' |
| 3009 | + self.set_test_snap_yaml("apps", {"foo": {"command": "bin/bar", |
| 3010 | + "stop-timeout": 60}}) |
| 3011 | + c = SnapReviewLint(self.test_name) |
| 3012 | + c.check_apps_nondaemon() |
| 3013 | + r = c.click_report |
| 3014 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3015 | + self.check_results(r, expected_counts) |
| 3016 | + |
| 3017 | + def test_check_apps_nondaemon_restart_condition(self): |
| 3018 | + '''Test check_apps_nondaemon() - restart-condition''' |
| 3019 | + self.set_test_snap_yaml("apps", {"foo": {"command": "bin/bar", |
| 3020 | + "restart-condition": |
| 3021 | + "never"}}) |
| 3022 | + c = SnapReviewLint(self.test_name) |
| 3023 | + c.check_apps_nondaemon() |
| 3024 | + r = c.click_report |
| 3025 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3026 | + self.check_results(r, expected_counts) |
| 3027 | + |
| 3028 | + def test_check_apps_nondaemon_poststop(self): |
| 3029 | + '''Test check_apps_nondaemon() - poststop''' |
| 3030 | + self.set_test_snap_yaml("apps", {"foo": {"command": "bin/bar", |
| 3031 | + "poststop": "bin/bar"}}) |
| 3032 | + c = SnapReviewLint(self.test_name) |
| 3033 | + c.check_apps_nondaemon() |
| 3034 | + r = c.click_report |
| 3035 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3036 | + self.check_results(r, expected_counts) |
| 3037 | + |
| 3038 | + def test_check_apps_nondaemon_ports(self): |
| 3039 | + '''Test check_apps_nondaemon() - ports''' |
| 3040 | + ports = self._create_ports() |
| 3041 | + self.set_test_snap_yaml("apps", {"foo": {"command": "bin/bar", |
| 3042 | + "ports": ports}}) |
| 3043 | + c = SnapReviewLint(self.test_name) |
| 3044 | + c.check_apps_nondaemon() |
| 3045 | + r = c.click_report |
| 3046 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3047 | + self.check_results(r, expected_counts) |
| 3048 | + |
| 3049 | + def test_check_apps_nondaemon_bus_name(self): |
| 3050 | + '''Test check_apps_nondaemon() - bus-name''' |
| 3051 | + self.set_test_snap_yaml("apps", {"foo": {"command": "bin/bar", |
| 3052 | + "bus-name": "tld.foo"}}) |
| 3053 | + c = SnapReviewLint(self.test_name) |
| 3054 | + c.check_apps_nondaemon() |
| 3055 | + r = c.click_report |
| 3056 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3057 | + self.check_results(r, expected_counts) |
| 3058 | + |
| 3059 | + def test_check_apps_nondaemon_socket(self): |
| 3060 | + '''Test check_apps_nondaemon() - socket''' |
| 3061 | + self.set_test_snap_yaml("apps", {"foo": {"command": "bin/bar", |
| 3062 | + "socket": True}}) |
| 3063 | + c = SnapReviewLint(self.test_name) |
| 3064 | + c.check_apps_nondaemon() |
| 3065 | + r = c.click_report |
| 3066 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3067 | + self.check_results(r, expected_counts) |
| 3068 | + |
| 3069 | + def test_check_apps_nondaemon_listen_stream(self): |
| 3070 | + '''Test check_apps_nondaemon() - listen-stream''' |
| 3071 | + self.set_test_snap_yaml("apps", {"foo": {"command": "bin/bar", |
| 3072 | + "listen-stream": "@bar"}}) |
| 3073 | + c = SnapReviewLint(self.test_name) |
| 3074 | + c.check_apps_nondaemon() |
| 3075 | + r = c.click_report |
| 3076 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3077 | + self.check_results(r, expected_counts) |
| 3078 | + |
| 3079 | + def test_check_apps_nondaemon_socket_user(self): |
| 3080 | + '''Test check_apps_nondaemon() - socket-user''' |
| 3081 | + self.set_test_snap_yaml("apps", {"foo": {"command": "bin/bar", |
| 3082 | + "socket-user": "docker"}}) |
| 3083 | + c = SnapReviewLint(self.test_name) |
| 3084 | + c.check_apps_nondaemon() |
| 3085 | + r = c.click_report |
| 3086 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3087 | + self.check_results(r, expected_counts) |
| 3088 | + |
| 3089 | + def test_check_apps_nondaemon_socket_group(self): |
| 3090 | + '''Test check_apps_nondaemon() - socket-group''' |
| 3091 | + self.set_test_snap_yaml("apps", {"foo": {"command": "bin/bar", |
| 3092 | + "socket-group": "docker"}}) |
| 3093 | + c = SnapReviewLint(self.test_name) |
| 3094 | + c.check_apps_nondaemon() |
| 3095 | + r = c.click_report |
| 3096 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3097 | + self.check_results(r, expected_counts) |
| 3098 | + |
| 3099 | + def test_check_apps_restart_condition_always(self): |
| 3100 | + '''Test check_apps_restart-condition() - always''' |
| 3101 | + entry = "always" |
| 3102 | + self.set_test_snap_yaml("apps", {"foo": {"restart-condition": entry}}) |
| 3103 | + c = SnapReviewLint(self.test_name) |
| 3104 | + c.check_apps_restart_condition() |
| 3105 | + r = c.click_report |
| 3106 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 3107 | + self.check_results(r, expected_counts) |
| 3108 | + |
| 3109 | + def test_check_apps_restart_condition_never(self): |
| 3110 | + '''Test check_apps_restart-condition() - never''' |
| 3111 | + entry = "never" |
| 3112 | + self.set_test_snap_yaml("apps", {"foo": {"restart-condition": entry}}) |
| 3113 | + c = SnapReviewLint(self.test_name) |
| 3114 | + c.check_apps_restart_condition() |
| 3115 | + r = c.click_report |
| 3116 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 3117 | + self.check_results(r, expected_counts) |
| 3118 | + |
| 3119 | + def test_check_apps_restart_condition_on_abnormal(self): |
| 3120 | + '''Test check_apps_restart-condition() - on-abnormal''' |
| 3121 | + entry = "on-abnormal" |
| 3122 | + self.set_test_snap_yaml("apps", {"foo": {"restart-condition": entry}}) |
| 3123 | + c = SnapReviewLint(self.test_name) |
| 3124 | + c.check_apps_restart_condition() |
| 3125 | + r = c.click_report |
| 3126 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 3127 | + self.check_results(r, expected_counts) |
| 3128 | + |
| 3129 | + def test_check_apps_restart_condition_on_abort(self): |
| 3130 | + '''Test check_apps_restart-condition() - on-abort''' |
| 3131 | + entry = "on-abort" |
| 3132 | + self.set_test_snap_yaml("apps", {"foo": {"restart-condition": entry}}) |
| 3133 | + c = SnapReviewLint(self.test_name) |
| 3134 | + c.check_apps_restart_condition() |
| 3135 | + r = c.click_report |
| 3136 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 3137 | + self.check_results(r, expected_counts) |
| 3138 | + |
| 3139 | + def test_check_apps_restart_condition_on_failure(self): |
| 3140 | + '''Test check_apps_restart-condition() - on-failure''' |
| 3141 | + entry = "on-failure" |
| 3142 | + self.set_test_snap_yaml("apps", {"foo": {"restart-condition": entry}}) |
| 3143 | + c = SnapReviewLint(self.test_name) |
| 3144 | + c.check_apps_restart_condition() |
| 3145 | + r = c.click_report |
| 3146 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 3147 | + self.check_results(r, expected_counts) |
| 3148 | + |
| 3149 | + def test_check_apps_restart_condition_on_success(self): |
| 3150 | + '''Test check_apps_restart-condition() - on-success''' |
| 3151 | + entry = "on-success" |
| 3152 | + self.set_test_snap_yaml("apps", {"foo": {"restart-condition": entry}}) |
| 3153 | + c = SnapReviewLint(self.test_name) |
| 3154 | + c.check_apps_restart_condition() |
| 3155 | + r = c.click_report |
| 3156 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 3157 | + self.check_results(r, expected_counts) |
| 3158 | + |
| 3159 | + def test_check_apps_restart_condition_missing(self): |
| 3160 | + '''Test check_apps_restart-condition() - missing''' |
| 3161 | + self.set_test_snap_yaml("apps", {"foo": {}}) |
| 3162 | + c = SnapReviewLint(self.test_name) |
| 3163 | + c.check_apps_restart_condition() |
| 3164 | + r = c.click_report |
| 3165 | + expected_counts = {'info': 0, 'warn': 0, 'error': 0} |
| 3166 | + self.check_results(r, expected_counts) |
| 3167 | + |
| 3168 | + def test_check_apps_restart_condition_empty(self): |
| 3169 | + '''Test check_apps_restart-condition() - empty''' |
| 3170 | + self.set_test_snap_yaml("apps", {"foo": {"restart-condition": ""}, |
| 3171 | + }) |
| 3172 | + c = SnapReviewLint(self.test_name) |
| 3173 | + c.check_apps_restart_condition() |
| 3174 | + r = c.click_report |
| 3175 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3176 | + self.check_results(r, expected_counts) |
| 3177 | + |
| 3178 | + def test_check_apps_restart_condition_invalid(self): |
| 3179 | + '''Test check_apps_restart-condition() - list''' |
| 3180 | + self.set_test_snap_yaml("apps", {"foo": {"restart-condition": []}, |
| 3181 | + }) |
| 3182 | + c = SnapReviewLint(self.test_name) |
| 3183 | + c.check_apps_restart_condition() |
| 3184 | + r = c.click_report |
| 3185 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3186 | + self.check_results(r, expected_counts) |
| 3187 | + |
| 3188 | + def test_check_apps_restart_condition_nonexistent(self): |
| 3189 | + '''Test check_apps_restart-condition() - nonexistent''' |
| 3190 | + entry = "nonexistent" |
| 3191 | + self.set_test_snap_yaml("apps", {"foo": {"restart-condition": entry}}) |
| 3192 | + c = SnapReviewLint(self.test_name) |
| 3193 | + c.check_apps_restart_condition() |
| 3194 | + r = c.click_report |
| 3195 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3196 | + self.check_results(r, expected_counts) |
| 3197 | + |
| 3198 | + def test_check_apps_busname_pkgname(self): |
| 3199 | + '''Test check_apps_busname() - pkgname''' |
| 3200 | + name = "tld.%s" % self.test_name.split('_')[0].split('.')[0] |
| 3201 | + self.set_test_snap_yaml("apps", {"bar": {"bus-name": name}}) |
| 3202 | + self.set_test_snap_yaml("type", 'framework') |
| 3203 | + c = SnapReviewLint(self.test_name) |
| 3204 | + c.check_apps_busname() |
| 3205 | + r = c.click_report |
| 3206 | + expected_counts = {'info': 3, 'warn': 0, 'error': 0} |
| 3207 | + self.check_results(r, expected_counts) |
| 3208 | + |
| 3209 | + def test_check_apps_busname_appname(self): |
| 3210 | + '''Test check_apps_busname() - appname''' |
| 3211 | + name = "tld.%s" % self.test_name.split('_')[0].split('.')[0] |
| 3212 | + self.set_test_snap_yaml("apps", {"bar": {"bus-name": "%s.bar" % name}}) |
| 3213 | + self.set_test_snap_yaml("type", 'framework') |
| 3214 | + c = SnapReviewLint(self.test_name) |
| 3215 | + c.check_apps_busname() |
| 3216 | + r = c.click_report |
| 3217 | + expected_counts = {'info': 3, 'warn': 0, 'error': 0} |
| 3218 | + self.check_results(r, expected_counts) |
| 3219 | + |
| 3220 | + def test_check_apps_busname_missing_framework_app(self): |
| 3221 | + '''Test check_apps_busname() - missing framework (app)''' |
| 3222 | + name = "tld.%s" % self.test_name.split('_')[0].split('.')[0] |
| 3223 | + self.set_test_snap_yaml("apps", {"bar": {"bus-name": "%s.bar" % name}}) |
| 3224 | + self.set_test_snap_yaml("type", 'app') |
| 3225 | + c = SnapReviewLint(self.test_name) |
| 3226 | + c.check_apps_busname() |
| 3227 | + r = c.click_report |
| 3228 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3229 | + self.check_results(r, expected_counts) |
| 3230 | + |
| 3231 | + def test_check_apps_busname_missing_framework_gadget(self): |
| 3232 | + '''Test check_apps_busname() - missing framework (gadget)''' |
| 3233 | + name = "tld.%s" % self.test_name.split('_')[0].split('.')[0] |
| 3234 | + self.set_test_snap_yaml("apps", {"bar": {"bus-name": "%s.bar" % name}}) |
| 3235 | + self.set_test_snap_yaml("type", 'gadget') |
| 3236 | + c = SnapReviewLint(self.test_name) |
| 3237 | + c.check_apps_busname() |
| 3238 | + r = c.click_report |
| 3239 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3240 | + self.check_results(r, expected_counts) |
| 3241 | + |
| 3242 | + def test_check_apps_busname_missing_framework_kernel(self): |
| 3243 | + '''Test check_apps_busname() - missing framework (kernel)''' |
| 3244 | + name = "tld.%s" % self.test_name.split('_')[0].split('.')[0] |
| 3245 | + self.set_test_snap_yaml("apps", {"bar": {"bus-name": name}}) |
| 3246 | + self.set_test_snap_yaml("type", 'kernel') |
| 3247 | + c = SnapReviewLint(self.test_name) |
| 3248 | + c.check_apps_busname() |
| 3249 | + r = c.click_report |
| 3250 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3251 | + self.check_results(r, expected_counts) |
| 3252 | + |
| 3253 | + def test_check_apps_busname_pkgname_bad(self): |
| 3254 | + '''Test check_apps_busname() - bad pkgname''' |
| 3255 | + name = "tld.%s" % self.test_name.split('_')[0].split('.')[0] |
| 3256 | + self.set_test_snap_yaml("apps", {"bar": {"bus-name": "%s-bad" % name}}) |
| 3257 | + self.set_test_snap_yaml("type", 'framework') |
| 3258 | + c = SnapReviewLint(self.test_name) |
| 3259 | + c.check_apps_busname() |
| 3260 | + r = c.click_report |
| 3261 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3262 | + self.check_results(r, expected_counts) |
| 3263 | + |
| 3264 | + def test_check_apps_busname_appname_bad(self): |
| 3265 | + '''Test check_apps_busname() - bad appname''' |
| 3266 | + name = "tld.%s" % self.test_name.split('_')[0].split('.')[0] |
| 3267 | + self.set_test_snap_yaml("apps", {"bar": {"bus-name": |
| 3268 | + "%s.bar-bad" % name}}) |
| 3269 | + self.set_test_snap_yaml("type", 'framework') |
| 3270 | + c = SnapReviewLint(self.test_name) |
| 3271 | + c.check_apps_busname() |
| 3272 | + r = c.click_report |
| 3273 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3274 | + self.check_results(r, expected_counts) |
| 3275 | + |
| 3276 | + def test_check_apps_busname_empty(self): |
| 3277 | + '''Test check_apps_busname() - bad (empty)''' |
| 3278 | + self.set_test_snap_yaml("apps", {"bar": {"bus-name": ""}}) |
| 3279 | + self.set_test_snap_yaml("type", 'framework') |
| 3280 | + c = SnapReviewLint(self.test_name) |
| 3281 | + c.check_apps_busname() |
| 3282 | + r = c.click_report |
| 3283 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3284 | + self.check_results(r, expected_counts) |
| 3285 | + |
| 3286 | + def test_check_apps_busname_invalid(self): |
| 3287 | + '''Test check_apps_busname() - bad (invalid)''' |
| 3288 | + self.set_test_snap_yaml("apps", {"bar": {"bus-name": []}}) |
| 3289 | + self.set_test_snap_yaml("type", 'framework') |
| 3290 | + c = SnapReviewLint(self.test_name) |
| 3291 | + c.check_apps_busname() |
| 3292 | + r = c.click_report |
| 3293 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3294 | + self.check_results(r, expected_counts) |
| 3295 | + |
| 3296 | + def test_check_apps_busname_bad_regex(self): |
| 3297 | + '''Test check_apps_busname() - bad (regex)''' |
| 3298 | + self.set_test_snap_yaml("apps", {"bar": {"bus-name": "name$"}}) |
| 3299 | + self.set_test_snap_yaml("type", 'framework') |
| 3300 | + c = SnapReviewLint(self.test_name) |
| 3301 | + c.check_apps_busname() |
| 3302 | + r = c.click_report |
| 3303 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3304 | + self.check_results(r, expected_counts) |
| 3305 | + |
| 3306 | + def test_check_apps_ports(self): |
| 3307 | + '''Test check_apps_ports()''' |
| 3308 | + ports = self._create_ports() |
| 3309 | + self.set_test_snap_yaml("apps", {"bar": {"ports": ports}}) |
| 3310 | + c = SnapReviewLint(self.test_name) |
| 3311 | + c.check_apps_ports() |
| 3312 | + r = c.click_report |
| 3313 | + expected_counts = {'info': 7, 'warn': 0, 'error': 0} |
| 3314 | + self.check_results(r, expected_counts) |
| 3315 | + |
| 3316 | + def test_check_apps_ports_internal(self): |
| 3317 | + '''Test check_apps_ports() - internal''' |
| 3318 | + ports = self._create_ports() |
| 3319 | + del ports['external'] |
| 3320 | + self.set_test_snap_yaml("apps", {"bar": {"ports": ports}}) |
| 3321 | + c = SnapReviewLint(self.test_name) |
| 3322 | + c.check_apps_ports() |
| 3323 | + r = c.click_report |
| 3324 | + expected_counts = {'info': 3, 'warn': 0, 'error': 0} |
| 3325 | + self.check_results(r, expected_counts) |
| 3326 | + |
| 3327 | + def test_check_apps_ports_external(self): |
| 3328 | + '''Test check_apps_ports() - external''' |
| 3329 | + ports = self._create_ports() |
| 3330 | + del ports['internal'] |
| 3331 | + self.set_test_snap_yaml("apps", {"bar": {"ports": ports}}) |
| 3332 | + c = SnapReviewLint(self.test_name) |
| 3333 | + c.check_apps_ports() |
| 3334 | + r = c.click_report |
| 3335 | + expected_counts = {'info': 5, 'warn': 0, 'error': 0} |
| 3336 | + self.check_results(r, expected_counts) |
| 3337 | + |
| 3338 | + def test_check_apps_ports_empty(self): |
| 3339 | + '''Test check_apps_ports() - empty''' |
| 3340 | + self.set_test_snap_yaml("apps", {"bar": {"ports": {}}}) |
| 3341 | + c = SnapReviewLint(self.test_name) |
| 3342 | + c.check_apps_ports() |
| 3343 | + r = c.click_report |
| 3344 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3345 | + self.check_results(r, expected_counts) |
| 3346 | + |
| 3347 | + def test_check_apps_ports_invalid(self): |
| 3348 | + '''Test check_apps_ports() - invalid''' |
| 3349 | + self.set_test_snap_yaml("apps", {"bar": {"ports": []}}) |
| 3350 | + c = SnapReviewLint(self.test_name) |
| 3351 | + c.check_apps_ports() |
| 3352 | + r = c.click_report |
| 3353 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3354 | + self.check_results(r, expected_counts) |
| 3355 | + |
| 3356 | + def test_check_apps_ports_bad_key(self): |
| 3357 | + '''Test check_apps_ports() - bad key''' |
| 3358 | + ports = self._create_ports() |
| 3359 | + ports['xternal'] = ports['external'] |
| 3360 | + del ports['external'] |
| 3361 | + |
| 3362 | + self.set_test_snap_yaml("apps", {"bar": {"ports": ports}}) |
| 3363 | + c = SnapReviewLint(self.test_name) |
| 3364 | + c.check_apps_ports() |
| 3365 | + r = c.click_report |
| 3366 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3367 | + self.check_results(r, expected_counts) |
| 3368 | + |
| 3369 | + def test_check_apps_ports_missing_internal(self): |
| 3370 | + '''Test check_apps_ports() - missing internal''' |
| 3371 | + ports = self._create_ports() |
| 3372 | + del ports['internal']['int1'] |
| 3373 | + |
| 3374 | + self.set_test_snap_yaml("apps", {"bar": {"ports": ports}}) |
| 3375 | + c = SnapReviewLint(self.test_name) |
| 3376 | + c.check_apps_ports() |
| 3377 | + r = c.click_report |
| 3378 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3379 | + self.check_results(r, expected_counts) |
| 3380 | + |
| 3381 | + def test_check_apps_ports_missing_external(self): |
| 3382 | + '''Test check_apps_ports() - missing external''' |
| 3383 | + ports = self._create_ports() |
| 3384 | + del ports['external']['ext1'] |
| 3385 | + del ports['external']['ext2'] |
| 3386 | + |
| 3387 | + self.set_test_snap_yaml("apps", {"bar": {"ports": ports}}) |
| 3388 | + c = SnapReviewLint(self.test_name) |
| 3389 | + c.check_apps_ports() |
| 3390 | + r = c.click_report |
| 3391 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3392 | + self.check_results(r, expected_counts) |
| 3393 | + |
| 3394 | + def test_check_apps_ports_missing_external_subkey(self): |
| 3395 | + '''Test check_apps_ports() - missing external subkey''' |
| 3396 | + ports = self._create_ports() |
| 3397 | + del ports['external']['ext2']['port'] |
| 3398 | + |
| 3399 | + self.set_test_snap_yaml("apps", {"bar": {"ports": ports}}) |
| 3400 | + c = SnapReviewLint(self.test_name) |
| 3401 | + c.check_apps_ports() |
| 3402 | + r = c.click_report |
| 3403 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3404 | + self.check_results(r, expected_counts) |
| 3405 | + |
| 3406 | + def test_check_apps_ports_missing_internal_subkey(self): |
| 3407 | + '''Test check_apps_ports() - missing internal subkey''' |
| 3408 | + ports = self._create_ports() |
| 3409 | + del ports['internal']['int1']['port'] |
| 3410 | + del ports['internal']['int1']['negotiable'] |
| 3411 | + |
| 3412 | + self.set_test_snap_yaml("apps", {"bar": {"ports": ports}}) |
| 3413 | + c = SnapReviewLint(self.test_name) |
| 3414 | + c.check_apps_ports() |
| 3415 | + r = c.click_report |
| 3416 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3417 | + self.check_results(r, expected_counts) |
| 3418 | + |
| 3419 | + def test_check_apps_ports_missing_internal_port_subkey(self): |
| 3420 | + '''Test check_apps_ports() - missing internal port subkey''' |
| 3421 | + ports = self._create_ports() |
| 3422 | + del ports['internal']['int1']['port'] |
| 3423 | + |
| 3424 | + self.set_test_snap_yaml("apps", {"bar": {"ports": ports}}) |
| 3425 | + c = SnapReviewLint(self.test_name) |
| 3426 | + c.check_apps_ports() |
| 3427 | + r = c.click_report |
| 3428 | + expected_counts = {'info': 7, 'warn': 0, 'error': 0} |
| 3429 | + self.check_results(r, expected_counts) |
| 3430 | + |
| 3431 | + def test_check_apps_ports_invalid_internal_subkey(self): |
| 3432 | + '''Test check_apps_ports() - invalid internal subkey''' |
| 3433 | + ports = self._create_ports() |
| 3434 | + ports['internal']['int1']['prt'] = ports['internal']['int1']['port'] |
| 3435 | + |
| 3436 | + self.set_test_snap_yaml("apps", {"bar": {"ports": ports}}) |
| 3437 | + c = SnapReviewLint(self.test_name) |
| 3438 | + c.check_apps_ports() |
| 3439 | + r = c.click_report |
| 3440 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3441 | + self.check_results(r, expected_counts) |
| 3442 | + |
| 3443 | + def test_check_apps_ports_invalid_internal_port(self): |
| 3444 | + '''Test check_apps_ports() - invalid internal port''' |
| 3445 | + ports = self._create_ports() |
| 3446 | + ports['internal']['int1']['port'] = "bad/8080" |
| 3447 | + |
| 3448 | + self.set_test_snap_yaml("apps", {"bar": {"ports": ports}}) |
| 3449 | + c = SnapReviewLint(self.test_name) |
| 3450 | + c.check_apps_ports() |
| 3451 | + r = c.click_report |
| 3452 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3453 | + self.check_results(r, expected_counts) |
| 3454 | + |
| 3455 | + def test_check_apps_ports_invalid_external_port(self): |
| 3456 | + '''Test check_apps_ports() - invalid external port''' |
| 3457 | + ports = self._create_ports() |
| 3458 | + ports['external']['ext2']['port'] = [] |
| 3459 | + |
| 3460 | + self.set_test_snap_yaml("apps", {"bar": {"ports": ports}}) |
| 3461 | + c = SnapReviewLint(self.test_name) |
| 3462 | + c.check_apps_ports() |
| 3463 | + r = c.click_report |
| 3464 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3465 | + self.check_results(r, expected_counts) |
| 3466 | + |
| 3467 | + def test_check_apps_ports_invalid_internal_low_port(self): |
| 3468 | + '''Test check_apps_ports() - invalid internal low port''' |
| 3469 | + ports = self._create_ports() |
| 3470 | + ports['internal']['int1']['port'] = "0/tcp" |
| 3471 | + |
| 3472 | + self.set_test_snap_yaml("apps", {"bar": {"ports": ports}}) |
| 3473 | + c = SnapReviewLint(self.test_name) |
| 3474 | + c.check_apps_ports() |
| 3475 | + r = c.click_report |
| 3476 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3477 | + self.check_results(r, expected_counts) |
| 3478 | + |
| 3479 | + def test_check_apps_ports_invalid_internal_high_port(self): |
| 3480 | + '''Test check_apps_ports() - invalid internal high port''' |
| 3481 | + ports = self._create_ports() |
| 3482 | + ports['internal']['int1']['port'] = "65536/tcp" |
| 3483 | + |
| 3484 | + self.set_test_snap_yaml("apps", {"bar": {"ports": ports}}) |
| 3485 | + c = SnapReviewLint(self.test_name) |
| 3486 | + c.check_apps_ports() |
| 3487 | + r = c.click_report |
| 3488 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3489 | + self.check_results(r, expected_counts) |
| 3490 | + |
| 3491 | + def test_check_apps_ports_invalid_internal_negotiable(self): |
| 3492 | + '''Test check_apps_ports() - invalid internal negotiable''' |
| 3493 | + ports = self._create_ports() |
| 3494 | + ports['internal']['int1']['negotiable'] = -99999999 |
| 3495 | + |
| 3496 | + self.set_test_snap_yaml("apps", {"bar": {"ports": ports}}) |
| 3497 | + c = SnapReviewLint(self.test_name) |
| 3498 | + c.check_apps_ports() |
| 3499 | + r = c.click_report |
| 3500 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3501 | + self.check_results(r, expected_counts) |
| 3502 | + |
| 3503 | + def test_check_apps_ports_invalid_internal_negotiable2(self): |
| 3504 | + '''Test check_apps_ports() - invalid internal negotiable''' |
| 3505 | + ports = self._create_ports() |
| 3506 | + ports['internal']['int1']['negotiable'] = [] |
| 3507 | + |
| 3508 | + self.set_test_snap_yaml("apps", {"bar": {"ports": ports}}) |
| 3509 | + c = SnapReviewLint(self.test_name) |
| 3510 | + c.check_apps_ports() |
| 3511 | + r = c.click_report |
| 3512 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3513 | + self.check_results(r, expected_counts) |
| 3514 | + |
| 3515 | + def test_check_apps_stop_timeout(self): |
| 3516 | + '''Test check_apps_stop_timeout()''' |
| 3517 | + self.set_test_snap_yaml("apps", {"bar": {"stop-timeout": 30}}) |
| 3518 | + c = SnapReviewLint(self.test_name) |
| 3519 | + c.check_apps_stop_timeout() |
| 3520 | + r = c.click_report |
| 3521 | + expected_counts = {'info': 2, 'warn': 0, 'error': 0} |
| 3522 | + self.check_results(r, expected_counts) |
| 3523 | + |
| 3524 | + def test_check_apps_stop_timeout_nonexistent(self): |
| 3525 | + '''Test check_apps_stop_timeout_nonexistent()''' |
| 3526 | + self.set_test_snap_yaml("apps", {"bar": {}}) |
| 3527 | + c = SnapReviewLint(self.test_name) |
| 3528 | + c.check_apps_stop_timeout() |
| 3529 | + r = c.click_report |
| 3530 | + expected_counts = {'info': 0, 'warn': 0, 'error': 0} |
| 3531 | + self.check_results(r, expected_counts) |
| 3532 | + |
| 3533 | + def test_check_apps_stop_timeout_granularity(self): |
| 3534 | + '''Test check_apps_stop_timeout()''' |
| 3535 | + self.set_test_snap_yaml("apps", {"bar": {"stop-timeout": '30s'}}) |
| 3536 | + c = SnapReviewLint(self.test_name) |
| 3537 | + c.check_apps_stop_timeout() |
| 3538 | + r = c.click_report |
| 3539 | + expected_counts = {'info': 2, 'warn': 0, 'error': 0} |
| 3540 | + self.check_results(r, expected_counts) |
| 3541 | + |
| 3542 | + def test_check_apps_stop_timeout_empty(self): |
| 3543 | + '''Test check_apps_stop_timeout() - empty''' |
| 3544 | + self.set_test_snap_yaml("apps", {"bar": {"stop-timeout": ''}}) |
| 3545 | + c = SnapReviewLint(self.test_name) |
| 3546 | + c.check_apps_stop_timeout() |
| 3547 | + r = c.click_report |
| 3548 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3549 | + self.check_results(r, expected_counts) |
| 3550 | + |
| 3551 | + def test_check_apps_stop_timeout_bad(self): |
| 3552 | + '''Test check_apps_stop_timeout() - bad''' |
| 3553 | + self.set_test_snap_yaml("apps", {"bar": {"stop-timeout": 'a'}}) |
| 3554 | + c = SnapReviewLint(self.test_name) |
| 3555 | + c.check_apps_stop_timeout() |
| 3556 | + r = c.click_report |
| 3557 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3558 | + self.check_results(r, expected_counts) |
| 3559 | + |
| 3560 | + def test_check_apps_stop_timeout_bad2(self): |
| 3561 | + '''Test check_apps_stop_timeout() - bad (list)''' |
| 3562 | + self.set_test_snap_yaml("apps", {"bar": {"stop-timeout": []}}) |
| 3563 | + c = SnapReviewLint(self.test_name) |
| 3564 | + c.check_apps_stop_timeout() |
| 3565 | + r = c.click_report |
| 3566 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3567 | + self.check_results(r, expected_counts) |
| 3568 | + |
| 3569 | + def test_check_apps_stop_timeout_bad_granularity(self): |
| 3570 | + '''Test check_apps_stop_timeout() - bad with granularity''' |
| 3571 | + self.set_test_snap_yaml("apps", {"bar": {"stop-timeout": '30a'}}) |
| 3572 | + c = SnapReviewLint(self.test_name) |
| 3573 | + c.check_apps_stop_timeout() |
| 3574 | + r = c.click_report |
| 3575 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3576 | + self.check_results(r, expected_counts) |
| 3577 | + |
| 3578 | + def test_check_apps_stop_timeout_range_low(self): |
| 3579 | + '''Test check_apps_stop_timeout() - out of range (low)''' |
| 3580 | + self.set_test_snap_yaml("apps", {"bar": {"stop-timeout": -1}}) |
| 3581 | + c = SnapReviewLint(self.test_name) |
| 3582 | + c.check_apps_stop_timeout() |
| 3583 | + r = c.click_report |
| 3584 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3585 | + self.check_results(r, expected_counts) |
| 3586 | + |
| 3587 | + def test_check_apps_stop_timeout_range_high(self): |
| 3588 | + '''Test check_apps_stop_timeout() - out of range (high)''' |
| 3589 | + self.set_test_snap_yaml("apps", {"bar": {"stop-timeout": 61}}) |
| 3590 | + c = SnapReviewLint(self.test_name) |
| 3591 | + c.check_apps_stop_timeout() |
| 3592 | + r = c.click_report |
| 3593 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3594 | + self.check_results(r, expected_counts) |
| 3595 | + |
| 3596 | + def test_check_apps_socket(self): |
| 3597 | + '''Test check_apps_socket()''' |
| 3598 | + name = self.test_snap_yaml['name'] |
| 3599 | + self.set_test_snap_yaml("apps", {"bar": {"socket": True, |
| 3600 | + "listen-stream": |
| 3601 | + "@%s" % name}}) |
| 3602 | + c = SnapReviewLint(self.test_name) |
| 3603 | + c.check_apps_socket() |
| 3604 | + r = c.click_report |
| 3605 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 3606 | + self.check_results(r, expected_counts) |
| 3607 | + |
| 3608 | + def test_check_apps_listen_stream_path(self): |
| 3609 | + '''Test check_apps_listen_stream() - path''' |
| 3610 | + name = self.test_snap_yaml['name'] |
| 3611 | + self.set_test_snap_yaml("apps", {"bar": {"listen-stream": |
| 3612 | + "/tmp/%s" % name}}) |
| 3613 | + c = SnapReviewLint(self.test_name) |
| 3614 | + c.check_apps_listen_stream() |
| 3615 | + r = c.click_report |
| 3616 | + expected_counts = {'info': 2, 'warn': 0, 'error': 0} |
| 3617 | + self.check_results(r, expected_counts) |
| 3618 | + |
| 3619 | + def test_check_apps_socket_no_listen_stream(self): |
| 3620 | + '''Test check_apps_socket() - missing listen-stream''' |
| 3621 | + self.set_test_snap_yaml("apps", {"bar": {"socket": True}}) |
| 3622 | + c = SnapReviewLint(self.test_name) |
| 3623 | + c.check_apps_socket() |
| 3624 | + r = c.click_report |
| 3625 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3626 | + self.check_results(r, expected_counts) |
| 3627 | + |
| 3628 | + def test_check_apps_socket_bad(self): |
| 3629 | + '''Test check_apps_socket() - bad''' |
| 3630 | + self.set_test_snap_yaml("apps", {"bar": {"socket": ""}}) |
| 3631 | + c = SnapReviewLint(self.test_name) |
| 3632 | + c.check_apps_socket() |
| 3633 | + r = c.click_report |
| 3634 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3635 | + self.check_results(r, expected_counts) |
| 3636 | + |
| 3637 | + def test_check_apps_socket_nonexistent(self): |
| 3638 | + '''Test check_apps_socket() - nonexistent''' |
| 3639 | + self.set_test_snap_yaml("apps", {"bar": {}}) |
| 3640 | + c = SnapReviewLint(self.test_name) |
| 3641 | + c.check_apps_socket() |
| 3642 | + r = c.click_report |
| 3643 | + expected_counts = {'info': 0, 'warn': 0, 'error': 0} |
| 3644 | + self.check_results(r, expected_counts) |
| 3645 | + |
| 3646 | + def test_check_apps_listen_stream_abspkgname(self): |
| 3647 | + '''Test check_apps_listen_stream() - @pkgname''' |
| 3648 | + name = self.test_snap_yaml['name'] |
| 3649 | + self.set_test_snap_yaml("apps", {"bar": {"listen-stream": |
| 3650 | + "@%s" % name}}) |
| 3651 | + c = SnapReviewLint(self.test_name) |
| 3652 | + c.check_apps_listen_stream() |
| 3653 | + r = c.click_report |
| 3654 | + expected_counts = {'info': 2, 'warn': 0, 'error': 0} |
| 3655 | + self.check_results(r, expected_counts) |
| 3656 | + |
| 3657 | + def test_check_apps_listen_stream_abspkgname2(self): |
| 3658 | + '''Test check_apps_listen_stream() - @pkgname_''' |
| 3659 | + name = self.test_snap_yaml['name'] |
| 3660 | + self.set_test_snap_yaml("apps", {"bar": {"listen-stream": |
| 3661 | + "@%s_something" % name}}) |
| 3662 | + c = SnapReviewLint(self.test_name) |
| 3663 | + c.check_apps_listen_stream() |
| 3664 | + r = c.click_report |
| 3665 | + expected_counts = {'info': 2, 'warn': 0, 'error': 0} |
| 3666 | + self.check_results(r, expected_counts) |
| 3667 | + |
| 3668 | + def test_check_apps_listen_stream_nonexistent(self): |
| 3669 | + '''Test check_apps_listen_stream() - nonexistent''' |
| 3670 | + self.set_test_snap_yaml("apps", {"bar": {}}) |
| 3671 | + c = SnapReviewLint(self.test_name) |
| 3672 | + c.check_apps_listen_stream() |
| 3673 | + r = c.click_report |
| 3674 | + expected_counts = {'info': 0, 'warn': 0, 'error': 0} |
| 3675 | + self.check_results(r, expected_counts) |
| 3676 | + |
| 3677 | + def test_check_apps_listen_stream_bad(self): |
| 3678 | + '''Test check_apps_listen_stream() - bad (list)''' |
| 3679 | + self.set_test_snap_yaml("apps", {"bar": {"listen-stream": []}}) |
| 3680 | + c = SnapReviewLint(self.test_name) |
| 3681 | + c.check_apps_listen_stream() |
| 3682 | + r = c.click_report |
| 3683 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3684 | + self.check_results(r, expected_counts) |
| 3685 | + |
| 3686 | + def test_check_apps_listen_stream_bad_abstract(self): |
| 3687 | + '''Test check_apps_listen_stream() - bad (wrong name)''' |
| 3688 | + name = self.test_snap_yaml['name'] |
| 3689 | + self.set_test_snap_yaml("apps", {"bar": {"listen-stream": |
| 3690 | + "@%s/nomatch" % name}}) |
| 3691 | + c = SnapReviewLint(self.test_name) |
| 3692 | + c.check_apps_listen_stream() |
| 3693 | + r = c.click_report |
| 3694 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3695 | + self.check_results(r, expected_counts) |
| 3696 | + |
| 3697 | + def test_check_apps_listen_stream_bad_relative(self): |
| 3698 | + '''Test check_apps_listen_stream() - bad (not / or @)''' |
| 3699 | + name = self.test_snap_yaml['name'] |
| 3700 | + self.set_test_snap_yaml("apps", {"bar": {"listen-stream": name}}) |
| 3701 | + c = SnapReviewLint(self.test_name) |
| 3702 | + c.check_apps_listen_stream() |
| 3703 | + r = c.click_report |
| 3704 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3705 | + self.check_results(r, expected_counts) |
| 3706 | + |
| 3707 | + def test_check_apps_listen_stream_bad_path(self): |
| 3708 | + '''Test check_apps_listen_stream() - bad path''' |
| 3709 | + name = self.test_snap_yaml['name'] |
| 3710 | + self.set_test_snap_yaml("apps", {"bar": {"listen-stream": |
| 3711 | + "/var/log/%s" % name}}) |
| 3712 | + c = SnapReviewLint(self.test_name) |
| 3713 | + c.check_apps_listen_stream() |
| 3714 | + r = c.click_report |
| 3715 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3716 | + self.check_results(r, expected_counts) |
| 3717 | + |
| 3718 | + def test_check_apps_listen_stream_empty(self): |
| 3719 | + '''Test check_apps_listen_stream() - empty''' |
| 3720 | + self.set_test_snap_yaml("apps", {"bar": {"listen-stream": ""}}) |
| 3721 | + c = SnapReviewLint(self.test_name) |
| 3722 | + c.check_apps_listen_stream() |
| 3723 | + r = c.click_report |
| 3724 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3725 | + self.check_results(r, expected_counts) |
| 3726 | + |
| 3727 | + def test_check_apps_socket_user(self): |
| 3728 | + '''Test check_apps_socket_user()''' |
| 3729 | + name = self.test_snap_yaml['name'] |
| 3730 | + self.set_test_snap_yaml("apps", {"bar": {"socket-user": name, |
| 3731 | + "listen-stream": |
| 3732 | + "@%s" % name}}) |
| 3733 | + c = SnapReviewLint(self.test_name) |
| 3734 | + c.check_apps_socket_user() |
| 3735 | + r = c.click_report |
| 3736 | + expected_counts = {'info': 2, 'warn': 0, 'error': 1} |
| 3737 | + self.check_results(r, expected_counts) |
| 3738 | + |
| 3739 | + def test_check_apps_socket_user_no_listen_stream(self): |
| 3740 | + '''Test check_apps_socket_user() - missing listen-stream''' |
| 3741 | + name = self.test_snap_yaml['name'] |
| 3742 | + self.set_test_snap_yaml("apps", {"bar": {"socket-user": name}}) |
| 3743 | + c = SnapReviewLint(self.test_name) |
| 3744 | + c.check_apps_socket_user() |
| 3745 | + r = c.click_report |
| 3746 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3747 | + self.check_results(r, expected_counts) |
| 3748 | + |
| 3749 | + def test_check_apps_socket_user_bad(self): |
| 3750 | + '''Test check_apps_socket_user() - bad user''' |
| 3751 | + name = self.test_snap_yaml['name'] |
| 3752 | + self.set_test_snap_yaml("apps", {"bar": {"socket-user": name + "-no", |
| 3753 | + "listen-stream": |
| 3754 | + "@%s" % name}}) |
| 3755 | + c = SnapReviewLint(self.test_name) |
| 3756 | + c.check_apps_socket_user() |
| 3757 | + r = c.click_report |
| 3758 | + expected_counts = {'info': None, 'warn': 0, 'error': 2} |
| 3759 | + self.check_results(r, expected_counts) |
| 3760 | + |
| 3761 | + def test_check_apps_socket_user_bad2(self): |
| 3762 | + '''Test check_apps_socket_user() - bad (list)''' |
| 3763 | + name = self.test_snap_yaml['name'] |
| 3764 | + self.set_test_snap_yaml("apps", {"bar": {"socket-user": [], |
| 3765 | + "listen-stream": |
| 3766 | + "@%s" % name}}) |
| 3767 | + c = SnapReviewLint(self.test_name) |
| 3768 | + c.check_apps_socket_user() |
| 3769 | + r = c.click_report |
| 3770 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3771 | + self.check_results(r, expected_counts) |
| 3772 | + |
| 3773 | + def test_check_apps_socket_user_empty(self): |
| 3774 | + '''Test check_apps_socket_user() - empty''' |
| 3775 | + name = self.test_snap_yaml['name'] |
| 3776 | + self.set_test_snap_yaml("apps", {"bar": {"socket-user": "", |
| 3777 | + "listen-stream": |
| 3778 | + "@%s" % name}}) |
| 3779 | + c = SnapReviewLint(self.test_name) |
| 3780 | + c.check_apps_socket_user() |
| 3781 | + r = c.click_report |
| 3782 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3783 | + self.check_results(r, expected_counts) |
| 3784 | + |
| 3785 | + def test_check_apps_socket_user_nonexistent(self): |
| 3786 | + '''Test check_apps_socket_user() - nonexistent''' |
| 3787 | + self.set_test_snap_yaml("apps", {"bar": {}}) |
| 3788 | + c = SnapReviewLint(self.test_name) |
| 3789 | + c.check_apps_socket_user() |
| 3790 | + r = c.click_report |
| 3791 | + expected_counts = {'info': 0, 'warn': 0, 'error': 0} |
| 3792 | + self.check_results(r, expected_counts) |
| 3793 | + |
| 3794 | + def test_check_apps_socket_group(self): |
| 3795 | + '''Test check_apps_socket_group()''' |
| 3796 | + name = self.test_snap_yaml['name'] |
| 3797 | + self.set_test_snap_yaml("apps", {"bar": {"socket-group": name, |
| 3798 | + "listen-stream": |
| 3799 | + "@%s" % name}}) |
| 3800 | + c = SnapReviewLint(self.test_name) |
| 3801 | + c.check_apps_socket_group() |
| 3802 | + r = c.click_report |
| 3803 | + expected_counts = {'info': 2, 'warn': 0, 'error': 1} |
| 3804 | + self.check_results(r, expected_counts) |
| 3805 | + |
| 3806 | + def test_check_apps_socket_group_no_listen_stream(self): |
| 3807 | + '''Test check_apps_socket_group() - missing listen-stream''' |
| 3808 | + name = self.test_snap_yaml['name'] |
| 3809 | + self.set_test_snap_yaml("apps", {"bar": {"socket-group": name}}) |
| 3810 | + c = SnapReviewLint(self.test_name) |
| 3811 | + c.check_apps_socket_group() |
| 3812 | + r = c.click_report |
| 3813 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3814 | + self.check_results(r, expected_counts) |
| 3815 | + |
| 3816 | + def test_check_apps_socket_group_bad(self): |
| 3817 | + '''Test check_apps_socket_group() - bad group''' |
| 3818 | + name = self.test_snap_yaml['name'] |
| 3819 | + self.set_test_snap_yaml("apps", {"bar": {"socket-group": name + "-no", |
| 3820 | + "listen-stream": |
| 3821 | + "@%s" % name}}) |
| 3822 | + c = SnapReviewLint(self.test_name) |
| 3823 | + c.check_apps_socket_group() |
| 3824 | + r = c.click_report |
| 3825 | + expected_counts = {'info': None, 'warn': 0, 'error': 2} |
| 3826 | + self.check_results(r, expected_counts) |
| 3827 | + |
| 3828 | + def test_check_apps_socket_group_bad2(self): |
| 3829 | + '''Test check_apps_socket_group() - bad (list)''' |
| 3830 | + name = self.test_snap_yaml['name'] |
| 3831 | + self.set_test_snap_yaml("apps", {"bar": {"socket-group": [], |
| 3832 | + "listen-stream": |
| 3833 | + "@%s" % name}}) |
| 3834 | + c = SnapReviewLint(self.test_name) |
| 3835 | + c.check_apps_socket_group() |
| 3836 | + r = c.click_report |
| 3837 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3838 | + self.check_results(r, expected_counts) |
| 3839 | + |
| 3840 | + def test_check_apps_socket_group_empty(self): |
| 3841 | + '''Test check_apps_socket_group() - empty''' |
| 3842 | + name = self.test_snap_yaml['name'] |
| 3843 | + self.set_test_snap_yaml("apps", {"bar": {"socket-group": "", |
| 3844 | + "listen-stream": |
| 3845 | + "@%s" % name}}) |
| 3846 | + c = SnapReviewLint(self.test_name) |
| 3847 | + c.check_apps_socket_group() |
| 3848 | + r = c.click_report |
| 3849 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3850 | + self.check_results(r, expected_counts) |
| 3851 | + |
| 3852 | + def test_check_apps_socket_group_nonexistent(self): |
| 3853 | + '''Test check_apps_socket_group() - nonexistent''' |
| 3854 | + self.set_test_snap_yaml("apps", {"bar": {}}) |
| 3855 | + c = SnapReviewLint(self.test_name) |
| 3856 | + c.check_apps_socket_group() |
| 3857 | + r = c.click_report |
| 3858 | + expected_counts = {'info': 0, 'warn': 0, 'error': 0} |
| 3859 | + self.check_results(r, expected_counts) |
| 3860 | + |
| 3861 | + def test_check_uses(self): |
| 3862 | + '''Test check_uses()''' |
| 3863 | + uses = self._create_top_uses() |
| 3864 | + self.set_test_snap_yaml("uses", uses) |
| 3865 | + c = SnapReviewLint(self.test_name) |
| 3866 | + c.check_uses() |
| 3867 | + r = c.click_report |
| 3868 | + expected_counts = {'info': 13, 'warn': 0, 'error': 0} |
| 3869 | + self.check_results(r, expected_counts) |
| 3870 | + |
| 3871 | + def test_check_uses_bad_type(self): |
| 3872 | + '''Test check_uses() - bad type (list)''' |
| 3873 | + uses = {'skill-caps': {'type': [], |
| 3874 | + 'caps': ['network-client']}} |
| 3875 | + self.set_test_snap_yaml("uses", uses) |
| 3876 | + c = SnapReviewLint(self.test_name) |
| 3877 | + c.check_uses() |
| 3878 | + r = c.click_report |
| 3879 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3880 | + self.check_results(r, expected_counts) |
| 3881 | + |
| 3882 | + def test_check_uses_empty_type(self): |
| 3883 | + '''Test check_uses() - empty type''' |
| 3884 | + uses = {'skill-caps': {'type': "", |
| 3885 | + 'caps': ['network-client']}} |
| 3886 | + self.set_test_snap_yaml("uses", uses) |
| 3887 | + c = SnapReviewLint(self.test_name) |
| 3888 | + c.check_uses() |
| 3889 | + r = c.click_report |
| 3890 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3891 | + self.check_results(r, expected_counts) |
| 3892 | + |
| 3893 | + def test_check_uses_unspecified_type(self): |
| 3894 | + '''Test check_uses() - unspecified type''' |
| 3895 | + uses = {'migration-skill': {'caps': ['network-client']}} |
| 3896 | + self.set_test_snap_yaml("uses", uses) |
| 3897 | + c = SnapReviewLint(self.test_name) |
| 3898 | + c.check_uses() |
| 3899 | + r = c.click_report |
| 3900 | + expected_counts = {'info': 3, 'warn': 0, 'error': 0} |
| 3901 | + self.check_results(r, expected_counts) |
| 3902 | + |
| 3903 | + def test_check_uses_unknown_type(self): |
| 3904 | + '''Test check_uses() - type (unknown)''' |
| 3905 | + uses = {'skill-caps': {'type': 'nonexistent', |
| 3906 | + 'caps': ['network-client']}} |
| 3907 | + self.set_test_snap_yaml("uses", uses) |
| 3908 | + c = SnapReviewLint(self.test_name) |
| 3909 | + c.check_uses() |
| 3910 | + r = c.click_report |
| 3911 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3912 | + self.check_results(r, expected_counts) |
| 3913 | + |
| 3914 | + def test_check_uses_unspecified_unknown_type(self): |
| 3915 | + '''Test check_uses() - unspecified type (unknown)''' |
| 3916 | + uses = {'nonexistent': {'caps': ['network-client']}} |
| 3917 | + self.set_test_snap_yaml("uses", uses) |
| 3918 | + c = SnapReviewLint(self.test_name) |
| 3919 | + c.check_uses() |
| 3920 | + r = c.click_report |
| 3921 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3922 | + self.check_results(r, expected_counts) |
| 3923 | + |
| 3924 | + def test_check_uses_missing_attrib(self): |
| 3925 | + '''Test check_uses() - missing attrib''' |
| 3926 | + uses = {'migration-skill': {}} |
| 3927 | + self.set_test_snap_yaml("uses", uses) |
| 3928 | + c = SnapReviewLint(self.test_name) |
| 3929 | + c.check_uses() |
| 3930 | + r = c.click_report |
| 3931 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3932 | + self.check_results(r, expected_counts) |
| 3933 | + |
| 3934 | + def test_check_uses_missing_attrib_explicit_type(self): |
| 3935 | + '''Test check_uses() - missing attrib''' |
| 3936 | + uses = {'skill-caps': {'type': 'migration-skill'}} |
| 3937 | + self.set_test_snap_yaml("uses", uses) |
| 3938 | + c = SnapReviewLint(self.test_name) |
| 3939 | + c.check_uses() |
| 3940 | + r = c.click_report |
| 3941 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3942 | + self.check_results(r, expected_counts) |
| 3943 | + |
| 3944 | + def test_check_uses_unknown_attrib(self): |
| 3945 | + '''Test check_uses() - unknown attrib''' |
| 3946 | + uses = {'skill-caps': {'type': "migration-skill", |
| 3947 | + 'nonexistent': 'abc'}} |
| 3948 | + self.set_test_snap_yaml("uses", uses) |
| 3949 | + c = SnapReviewLint(self.test_name) |
| 3950 | + c.check_uses() |
| 3951 | + r = c.click_report |
| 3952 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3953 | + self.check_results(r, expected_counts) |
| 3954 | + |
| 3955 | + def test_check_uses_bad_attrib_caps(self): |
| 3956 | + '''Test check_uses() - bad attrib - caps''' |
| 3957 | + uses = {'skill-caps': {'type': "migration-skill", |
| 3958 | + 'caps': 'bad'}} |
| 3959 | + self.set_test_snap_yaml("uses", uses) |
| 3960 | + c = SnapReviewLint(self.test_name) |
| 3961 | + c.check_uses() |
| 3962 | + r = c.click_report |
| 3963 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3964 | + self.check_results(r, expected_counts) |
| 3965 | + |
| 3966 | + def test_check_uses_bad_attrib_security_override(self): |
| 3967 | + '''Test check_uses() - bad attrib - security-override''' |
| 3968 | + uses = {'skill-caps': {'type': "migration-skill", |
| 3969 | + 'security-override': 'bad'}} |
| 3970 | + self.set_test_snap_yaml("uses", uses) |
| 3971 | + c = SnapReviewLint(self.test_name) |
| 3972 | + c.check_uses() |
| 3973 | + r = c.click_report |
| 3974 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3975 | + self.check_results(r, expected_counts) |
| 3976 | + |
| 3977 | + def test_check_uses_bad_attrib_security_policy(self): |
| 3978 | + '''Test check_uses() - bad attrib - security-policy''' |
| 3979 | + uses = {'skill-caps': {'type': "migration-skill", |
| 3980 | + 'security-policy': 'bad'}} |
| 3981 | + self.set_test_snap_yaml("uses", uses) |
| 3982 | + c = SnapReviewLint(self.test_name) |
| 3983 | + c.check_uses() |
| 3984 | + r = c.click_report |
| 3985 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3986 | + self.check_results(r, expected_counts) |
| 3987 | + |
| 3988 | + def test_check_uses_bad_attrib_security_template(self): |
| 3989 | + '''Test check_uses() - bad attrib - security-template''' |
| 3990 | + uses = {'skill-caps': {'type': "migration-skill", |
| 3991 | + 'security-template': []}} |
| 3992 | + self.set_test_snap_yaml("uses", uses) |
| 3993 | + c = SnapReviewLint(self.test_name) |
| 3994 | + c.check_uses() |
| 3995 | + r = c.click_report |
| 3996 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 3997 | + self.check_results(r, expected_counts) |
| 3998 | + |
| 3999 | + def test_check_apps_uses(self): |
| 4000 | + '''Test check_apps_uses()''' |
| 4001 | + uses = self._create_top_uses() |
| 4002 | + apps_uses = self._create_apps_uses() |
| 4003 | + self.set_test_snap_yaml("uses", uses) |
| 4004 | + self.set_test_snap_yaml("apps", apps_uses) |
| 4005 | + c = SnapReviewLint(self.test_name) |
| 4006 | + c.check_apps_uses() |
| 4007 | + r = c.click_report |
| 4008 | + expected_counts = {'info': 10, 'warn': 0, 'error': 0} |
| 4009 | + self.check_results(r, expected_counts) |
| 4010 | + |
| 4011 | + def test_check_apps_no_uses(self): |
| 4012 | + '''Test check_apps_uses() - no uses''' |
| 4013 | + uses = self._create_top_uses() |
| 4014 | + apps_uses = {'bar': {'command': 'bin/bar'}} |
| 4015 | + self.set_test_snap_yaml("uses", uses) |
| 4016 | + self.set_test_snap_yaml("apps", apps_uses) |
| 4017 | + c = SnapReviewLint(self.test_name) |
| 4018 | + c.check_apps_uses() |
| 4019 | + r = c.click_report |
| 4020 | + expected_counts = {'info': 0, 'warn': 0, 'error': 0} |
| 4021 | + self.check_results(r, expected_counts) |
| 4022 | + |
| 4023 | + def test_check_apps_uses_bad(self): |
| 4024 | + '''Test check_apps_uses() - bad (dict)''' |
| 4025 | + uses = self._create_top_uses() |
| 4026 | + apps_uses = {'bar': {'uses': {}}} |
| 4027 | + self.set_test_snap_yaml("uses", uses) |
| 4028 | + self.set_test_snap_yaml("apps", apps_uses) |
| 4029 | + c = SnapReviewLint(self.test_name) |
| 4030 | + c.check_apps_uses() |
| 4031 | + r = c.click_report |
| 4032 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 4033 | + self.check_results(r, expected_counts) |
| 4034 | + |
| 4035 | + def test_check_apps_uses_empty(self): |
| 4036 | + '''Test check_apps_uses() - empty''' |
| 4037 | + uses = self._create_top_uses() |
| 4038 | + apps_uses = {'bar': {'uses': []}} |
| 4039 | + self.set_test_snap_yaml("uses", uses) |
| 4040 | + self.set_test_snap_yaml("apps", apps_uses) |
| 4041 | + c = SnapReviewLint(self.test_name) |
| 4042 | + c.check_apps_uses() |
| 4043 | + r = c.click_report |
| 4044 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 4045 | + self.check_results(r, expected_counts) |
| 4046 | + |
| 4047 | + def test_check_apps_uses_bad_entry(self): |
| 4048 | + '''Test check_apps_uses() - bad entry (dict)''' |
| 4049 | + uses = self._create_top_uses() |
| 4050 | + apps_uses = {'bar': {'uses': [{}]}} |
| 4051 | + self.set_test_snap_yaml("uses", uses) |
| 4052 | + self.set_test_snap_yaml("apps", apps_uses) |
| 4053 | + c = SnapReviewLint(self.test_name) |
| 4054 | + c.check_apps_uses() |
| 4055 | + r = c.click_report |
| 4056 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 4057 | + self.check_results(r, expected_counts) |
| 4058 | + |
| 4059 | + def test_check_apps_uses_unknown_entry(self): |
| 4060 | + '''Test check_apps_uses() - unknown''' |
| 4061 | + uses = self._create_top_uses() |
| 4062 | + apps_uses = {'bar': {'uses': ['nonexistent']}} |
| 4063 | + self.set_test_snap_yaml("uses", uses) |
| 4064 | + self.set_test_snap_yaml("apps", apps_uses) |
| 4065 | + c = SnapReviewLint(self.test_name) |
| 4066 | + c.check_apps_uses() |
| 4067 | + r = c.click_report |
| 4068 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 4069 | + self.check_results(r, expected_counts) |
| 4070 | + |
| 4071 | + |
| 4072 | +class TestSnapReviewLintNoMock(TestCase): |
| 4073 | + """Tests without mocks where they are not needed.""" |
| 4074 | + def setUp(self): |
| 4075 | + # XXX cleanup_unpack() is required because global variables |
| 4076 | + # UNPACK_DIR, RAW_UNPACK_DIR are initialised to None at module |
| 4077 | + # load time, but updated when a real (non-Mock) test runs, such as |
| 4078 | + # here. While, at the same time, two of the existing tests using |
| 4079 | + # mocks depend on both global vars being None. Ideally, those |
| 4080 | + # global vars should be refactored away. |
| 4081 | + self.addCleanup(cleanup_unpack) |
| 4082 | + super().setUp() |
| 4083 | + |
| 4084 | + def mkdtemp(self): |
| 4085 | + """Create a temp dir which is cleaned up after test.""" |
| 4086 | + tmp_dir = tempfile.mkdtemp() |
| 4087 | + self.addCleanup(shutil.rmtree, tmp_dir) |
| 4088 | + return tmp_dir |
| 4089 | + |
| 4090 | + def check_results(self, report, |
| 4091 | + expected_counts={'info': 1, 'warn': 0, 'error': 0}, |
| 4092 | + expected=None): |
| 4093 | + common_check_results(self, report, expected_counts, expected) |
| 4094 | + |
| 4095 | + def test_check_external_symlinks(self): |
| 4096 | + '''Test check_external_symlinks()''' |
| 4097 | + package = utils.make_snap2(output_dir=self.mkdtemp()) |
| 4098 | + c = SnapReviewLint(package) |
| 4099 | + c.check_external_symlinks() |
| 4100 | + r = c.click_report |
| 4101 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 4102 | + self.check_results(r, expected_counts) |
| 4103 | + |
| 4104 | + def test_check_external_symlinks_has_symlink(self): |
| 4105 | + '''Test check_external_symlinks() - has symlink''' |
| 4106 | + package = utils.make_snap2(output_dir=self.mkdtemp(), |
| 4107 | + extra_files=['/some/where,outside'] |
| 4108 | + ) |
| 4109 | + c = SnapReviewLint(package) |
| 4110 | + c.check_external_symlinks() |
| 4111 | + r = c.click_report |
| 4112 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 4113 | + self.check_results(r, expected_counts) |
| 4114 | + |
| 4115 | + def test_check_architecture_all(self): |
| 4116 | + '''Test check_architecture_all()''' |
| 4117 | + package = utils.make_snap2(output_dir=self.mkdtemp()) |
| 4118 | + c = SnapReviewLint(package) |
| 4119 | + c.check_architecture_all() |
| 4120 | + r = c.click_report |
| 4121 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 4122 | + self.check_results(r, expected_counts) |
| 4123 | + |
| 4124 | + def test_check_architecture_all_has_binary(self): |
| 4125 | + '''Test check_architecture_all() - has binary''' |
| 4126 | + package = utils.make_snap2(output_dir=self.mkdtemp(), |
| 4127 | + extra_files=['/bin/ls:ls'] |
| 4128 | + ) |
| 4129 | + c = SnapReviewLint(package) |
| 4130 | + c.check_architecture_all() |
| 4131 | + r = c.click_report |
| 4132 | + expected_counts = {'info': None, 'warn': 0, 'error': 1} |
| 4133 | + self.check_results(r, expected_counts) |
| 4134 | + |
| 4135 | + def test_check_architecture_specified_needed_has_binary(self): |
| 4136 | + '''Test check_architecture_specified_needed() - has binary''' |
| 4137 | + output_dir = self.mkdtemp() |
| 4138 | + path = os.path.join(output_dir, 'snap.yaml') |
| 4139 | + content = ''' |
| 4140 | +name: test |
| 4141 | +version: 0.1 |
| 4142 | +summary: some thing |
| 4143 | +description: some desc |
| 4144 | +architectures: [ amd64 ] |
| 4145 | +''' |
| 4146 | + with open(path, 'w') as f: |
| 4147 | + f.write(content) |
| 4148 | + |
| 4149 | + package = utils.make_snap2(output_dir=output_dir, |
| 4150 | + extra_files=['%s:meta/snap.yaml' % path, |
| 4151 | + '/bin/ls:ls' |
| 4152 | + ] |
| 4153 | + ) |
| 4154 | + c = SnapReviewLint(package) |
| 4155 | + c.check_architecture_specified_needed() |
| 4156 | + r = c.click_report |
| 4157 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 4158 | + self.check_results(r, expected_counts) |
| 4159 | + |
| 4160 | + def test_check_architecture_specified_needed(self): |
| 4161 | + '''Test check_architecture_specified_needed()''' |
| 4162 | + output_dir = self.mkdtemp() |
| 4163 | + path = os.path.join(output_dir, 'snap.yaml') |
| 4164 | + content = ''' |
| 4165 | +name: test |
| 4166 | +version: 0.1 |
| 4167 | +summary: some thing |
| 4168 | +description: some desc |
| 4169 | +architectures: [ amd64 ] |
| 4170 | +''' |
| 4171 | + with open(path, 'w') as f: |
| 4172 | + f.write(content) |
| 4173 | + |
| 4174 | + package = utils.make_snap2(output_dir=output_dir, |
| 4175 | + extra_files=['%s:meta/snap.yaml' % path] |
| 4176 | + ) |
| 4177 | + c = SnapReviewLint(package) |
| 4178 | + c.check_architecture_specified_needed() |
| 4179 | + r = c.click_report |
| 4180 | + expected_counts = {'info': None, 'warn': 1, 'error': 0} |
| 4181 | + self.check_results(r, expected_counts) |
| 4182 | + |
| 4183 | + def test_check_vcs(self): |
| 4184 | + '''Test check_vcs()''' |
| 4185 | + package = utils.make_snap2(output_dir=self.mkdtemp()) |
| 4186 | + c = SnapReviewLint(package) |
| 4187 | + c.check_vcs() |
| 4188 | + r = c.click_report |
| 4189 | + expected_counts = {'info': 1, 'warn': 0, 'error': 0} |
| 4190 | + self.check_results(r, expected_counts) |
| 4191 | + |
| 4192 | + def test_check_vcs_bzrignore(self): |
| 4193 | + '''Test check_vcs() - .bzrignore''' |
| 4194 | + package = utils.make_snap2(output_dir=self.mkdtemp(), |
| 4195 | + extra_files=['.bzrignore'] |
| 4196 | + ) |
| 4197 | + c = SnapReviewLint(package) |
| 4198 | + c.check_vcs() |
| 4199 | + r = c.click_report |
| 4200 | + expected_counts = {'info': None, 'warn': 1, 'error': 0} |
| 4201 | + self.check_results(r, expected_counts) |
| 4202 | |
| 4203 | === modified file 'clickreviews/tests/utils.py' |
| 4204 | --- clickreviews/tests/utils.py 2016-02-09 21:45:25 +0000 |
| 4205 | +++ clickreviews/tests/utils.py 2016-02-11 18:32:45 +0000 |
| 4206 | @@ -1,6 +1,6 @@ |
| 4207 | '''utils.py: test utils for click reviewer tools''' |
| 4208 | # |
| 4209 | -# Copyright (C) 2013-2015 Canonical Ltd. |
| 4210 | +# Copyright (C) 2013-2016 Canonical Ltd. |
| 4211 | # |
| 4212 | # This program is free software: you can redistribute it and/or modify |
| 4213 | # it under the terms of the GNU General Public License as published by |
| 4214 | @@ -14,7 +14,9 @@ |
| 4215 | # You should have received a copy of the GNU General Public License |
| 4216 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 4217 | |
| 4218 | -import glob |
| 4219 | +from clickreviews.common import ( |
| 4220 | + MKSQUASHFS_OPTS |
| 4221 | +) |
| 4222 | import json |
| 4223 | import os |
| 4224 | import shutil |
| 4225 | @@ -22,17 +24,44 @@ |
| 4226 | import tempfile |
| 4227 | |
| 4228 | |
| 4229 | -def make_package(name='test', pkgfmt_type='click', pkgfmt_version='0.4', |
| 4230 | - package_types=None, version='1.0', title="An application", |
| 4231 | - framework='ubuntu-sdk-15.04', extra_files=None, |
| 4232 | - output_dir=None): |
| 4233 | +def make_snap2(name='test', pkgfmt_type='snap', pkgfmt_version='16.04', |
| 4234 | + version='1.0', summary="An application", extra_files=None, |
| 4235 | + output_dir=None): |
| 4236 | + '''Return the path to a snap v2 package with the given data. |
| 4237 | + |
| 4238 | + Caller is responsible for deleting the output_dir afterwards. |
| 4239 | + ''' |
| 4240 | + assert(pkgfmt_type == "snap" and pkgfmt_version != "15.04") |
| 4241 | + |
| 4242 | + build_dir = tempfile.mkdtemp() |
| 4243 | + |
| 4244 | + try: |
| 4245 | + make_dir_structure(build_dir, pkgfmt_type=pkgfmt_type, |
| 4246 | + pkgfmt_version=pkgfmt_version, |
| 4247 | + extra_files=extra_files) |
| 4248 | + write_icon(build_dir) |
| 4249 | + description = summary |
| 4250 | + write_meta_data2(build_dir, name, version, summary, description) |
| 4251 | + pkg_path = build_package(build_dir, name, version, pkgfmt_type, |
| 4252 | + pkgfmt_version, output_dir=output_dir) |
| 4253 | + finally: |
| 4254 | + shutil.rmtree(build_dir) |
| 4255 | + |
| 4256 | + return pkg_path |
| 4257 | + |
| 4258 | + |
| 4259 | +def make_click(name='test', pkgfmt_type='click', pkgfmt_version='0.4', |
| 4260 | + package_types=None, version='1.0', title="An application", |
| 4261 | + framework='ubuntu-sdk-15.04', extra_files=None, |
| 4262 | + output_dir=None): |
| 4263 | """Return the path to a click/snap package with the given data. |
| 4264 | |
| 4265 | Caller is responsible for deleting the output_dir afterwards. |
| 4266 | """ |
| 4267 | - is_snap1 = (pkgfmt_type == "snap" and pkgfmt_version == "15.04") |
| 4268 | - # TODO: implement writing snap2 packages |
| 4269 | - # is_snap2 = (pkgfmt_type == "snap" and not pkgfmt_version == "15.04") |
| 4270 | + assert(pkgfmt_type == "click" or (pkgfmt_type == "snap" and |
| 4271 | + pkgfmt_version == "15.04")) |
| 4272 | + |
| 4273 | + is_snap1 = (pkgfmt_type == "snap") |
| 4274 | build_dir = tempfile.mkdtemp() |
| 4275 | package_types = package_types or [] |
| 4276 | |
| 4277 | @@ -42,19 +71,19 @@ |
| 4278 | extra_files=extra_files) |
| 4279 | write_icon(build_dir) |
| 4280 | |
| 4281 | - if pkgfmt_type == 'click' or pkgfmt_version == 15.04: |
| 4282 | - write_manifest(build_dir, name, version, |
| 4283 | - title, framework, package_types, |
| 4284 | - is_snap1) |
| 4285 | - write_control(build_dir, name, version, title, pkgfmt_version) |
| 4286 | - write_preinst(build_dir) |
| 4287 | - write_apparmor_profile(build_dir, name) |
| 4288 | - write_other_files(build_dir) |
| 4289 | - else: |
| 4290 | + write_manifest(build_dir, name, version, |
| 4291 | + title, framework, package_types, |
| 4292 | + is_snap1) |
| 4293 | + write_control(build_dir, name, version, title, pkgfmt_version) |
| 4294 | + write_preinst(build_dir) |
| 4295 | + write_apparmor_profile(build_dir, name) |
| 4296 | + write_other_files(build_dir) |
| 4297 | + |
| 4298 | + if pkgfmt_type == 'snap': |
| 4299 | write_meta_data(build_dir, name, version, title, framework) |
| 4300 | |
| 4301 | pkg_path = build_package(build_dir, name, version, pkgfmt_type, |
| 4302 | - output_dir=output_dir) |
| 4303 | + pkgfmt_version, output_dir=output_dir) |
| 4304 | finally: |
| 4305 | shutil.rmtree(build_dir) |
| 4306 | |
| 4307 | @@ -62,33 +91,81 @@ |
| 4308 | |
| 4309 | |
| 4310 | def make_dir_structure(path, pkgfmt_type, pkgfmt_version, extra_files=None): |
| 4311 | + '''Create the mandatory dir structure and extra_files. Format for |
| 4312 | + extra_files: |
| 4313 | + path/to/file create empty file in path |
| 4314 | + path/to/dir/ create empty dir in path |
| 4315 | + path/to/source,path/to/link create symlink in path |
| 4316 | + path/to/source:path/to/link copy source to path |
| 4317 | + |
| 4318 | + For symlink and copy, source can be an absolute path for pointing |
| 4319 | + outside of the dir (for symlinks) or copying into the package. |
| 4320 | + ''' |
| 4321 | extra_files = extra_files or [] |
| 4322 | - directories = ['meta'] |
| 4323 | + |
| 4324 | + directories = ['meta'] # write_icon() and write_manifest() assume this |
| 4325 | if pkgfmt_type == 'click' or pkgfmt_version == 15.04: |
| 4326 | directories.append('DEBIAN') |
| 4327 | |
| 4328 | - directories.extend( |
| 4329 | - [os.path.dirname(extra_file) for extra_file in extra_files]) |
| 4330 | - |
| 4331 | + # enumerate the directories to create |
| 4332 | + for extra_file in extra_files: |
| 4333 | + if ',' in extra_file: |
| 4334 | + extra = extra_file.split(',', 1)[1] |
| 4335 | + elif ':' in extra_file: |
| 4336 | + extra = extra_file.split(':', 1)[1] |
| 4337 | + else: |
| 4338 | + extra = extra_file |
| 4339 | + |
| 4340 | + if extra.startswith('/'): |
| 4341 | + extra = extra[1:] |
| 4342 | + |
| 4343 | + if extra.endswith('/'): |
| 4344 | + directories.append(extra) |
| 4345 | + else: |
| 4346 | + directories.append(os.path.dirname(extra)) |
| 4347 | + |
| 4348 | + # make the enumerated directories |
| 4349 | for directory in directories: |
| 4350 | directory = os.path.join(path, directory) |
| 4351 | if not os.path.exists(directory): |
| 4352 | os.makedirs(directory) |
| 4353 | |
| 4354 | for extra_file in extra_files: |
| 4355 | - dirname, basename = os.path.split(extra_file) |
| 4356 | + if extra_file.endswith('/'): # nothing more to do for directories |
| 4357 | + continue |
| 4358 | + |
| 4359 | + source_link = None |
| 4360 | + source_path = None |
| 4361 | + if ',' in extra_file: |
| 4362 | + (source_link, target_path) = extra_file.split(',', 1) |
| 4363 | + elif ':' in extra_file: |
| 4364 | + (source_path, target_path) = extra_file.split(':', 1) |
| 4365 | + else: |
| 4366 | + target_path = extra_file |
| 4367 | + |
| 4368 | + dirname, basename = os.path.split(target_path) |
| 4369 | if basename != '': |
| 4370 | - with open(os.path.join(path, extra_file), 'wb'): |
| 4371 | - pass |
| 4372 | + if source_path: |
| 4373 | + if not source_path.startswith('/'): |
| 4374 | + source_path = os.path.join(path, source_path) |
| 4375 | + shutil.copyfile(source_path, os.path.join(path, target_path)) |
| 4376 | + elif source_link: |
| 4377 | + cur = os.getcwd() |
| 4378 | + if target_path.startswith('/'): |
| 4379 | + target_path = os.path.join(path, target_path[1:]) |
| 4380 | + else: |
| 4381 | + os.chdir(path) |
| 4382 | + os.symlink(source_link, target_path) |
| 4383 | + os.chdir(cur) |
| 4384 | + else: |
| 4385 | + with open(os.path.join(path, target_path), 'wb'): |
| 4386 | + pass |
| 4387 | |
| 4388 | |
| 4389 | def write_icon(path): |
| 4390 | - # XXX: Update to use a test icon in the branch to guarantee an icon. |
| 4391 | - icons = glob.glob('/usr/share/icons/hicolor/256x256/apps/*.png') |
| 4392 | - if len(icons) > 0: |
| 4393 | - source_path = icons[0] |
| 4394 | - target_path = os.path.join(path, 'meta', 'icon.png') |
| 4395 | - shutil.copyfile(source_path, target_path) |
| 4396 | + source_path = os.path.join(os.getcwd(), 'clickreviews/data/icon.png') |
| 4397 | + target_path = os.path.join(path, 'meta', 'icon.png') |
| 4398 | + shutil.copyfile(source_path, target_path) |
| 4399 | |
| 4400 | |
| 4401 | def write_manifest(path, name, version, title, framework, types, is_snap): |
| 4402 | @@ -127,17 +204,37 @@ |
| 4403 | content = """architectures: |
| 4404 | icon: meta/icon.png |
| 4405 | name: {} |
| 4406 | -version: "{}", |
| 4407 | -framework: {}, |
| 4408 | +version: {} |
| 4409 | +framework: {} |
| 4410 | vendor: 'Someone <someone@example.com>', |
| 4411 | """.format(name, version, framework) |
| 4412 | |
| 4413 | - with open(yaml_path, 'w') as f: |
| 4414 | - f.write(content) |
| 4415 | + # don't overwrite 'copy' via make_dir_structure() |
| 4416 | + if not os.path.exists(yaml_path): |
| 4417 | + with open(yaml_path, 'w') as f: |
| 4418 | + f.write(content) |
| 4419 | with open(os.path.join(path, 'meta', 'readme.md'), 'w') as f: |
| 4420 | f.write(title) |
| 4421 | |
| 4422 | |
| 4423 | +def write_meta_data2(path, name, version, summary, description, yaml=None): |
| 4424 | + yaml_path = os.path.join(path, 'meta', 'snap.yaml') |
| 4425 | + if yaml: |
| 4426 | + content = yaml |
| 4427 | + else: |
| 4428 | + content = """architectures: [ all ] |
| 4429 | +name: {} |
| 4430 | +version: {} |
| 4431 | +summary: {} |
| 4432 | +description: {} |
| 4433 | +""".format(name, version, summary, description) |
| 4434 | + |
| 4435 | + # don't overwrite 'copy' via make_dir_structure() |
| 4436 | + if not os.path.exists(yaml_path): |
| 4437 | + with open(yaml_path, 'w') as f: |
| 4438 | + f.write(content) |
| 4439 | + |
| 4440 | + |
| 4441 | def write_control(path, name, version, title, pkgfmt_version): |
| 4442 | control_path = os.path.join(path, 'DEBIAN', 'control') |
| 4443 | control_content = {'Package': name, |
| 4444 | @@ -182,15 +279,23 @@ |
| 4445 | write_empty_file(os.path.join(path, 'DEBIAN', 'md5sums')) |
| 4446 | |
| 4447 | |
| 4448 | -def build_package(path, name, version, format, output_dir=None): |
| 4449 | - filename = "{}_{}_all.{}".format(name, version, format) |
| 4450 | +def build_package(path, name, version, pkgfmt_type, pkgfmt_version, |
| 4451 | + output_dir=None): |
| 4452 | + filename = "{}_{}_all.{}".format(name, version, pkgfmt_type) |
| 4453 | output_dir = output_dir or tempfile.mkdtemp() |
| 4454 | output_path = os.path.join(output_dir, filename) |
| 4455 | |
| 4456 | - # Note: We're not using 'click build' here as it corrects errors (such |
| 4457 | - # as filtering out a .click directory present in the build). We want |
| 4458 | - # to test with manually constructed, potentially tampered-with |
| 4459 | - # clicks/snaps. Ideally, we'd be using click rather than dpkg to |
| 4460 | - # construct the click without filtering any files in the build dir. |
| 4461 | - subprocess.check_call(['dpkg-deb', '-b', path, output_path]) |
| 4462 | + if pkgfmt_type == "snap" and pkgfmt_version != "15.04": |
| 4463 | + args = ['mksquashfs', path, output_path] + MKSQUASHFS_OPTS |
| 4464 | + # debugging |
| 4465 | + # subprocess.check_call(args) |
| 4466 | + # subprocess.check_call(['unsquashfs', '-lls', output_path]) |
| 4467 | + subprocess.check_call(args, stdout=open(os.devnull, 'w')) |
| 4468 | + else: # click and snap v1 |
| 4469 | + # Note: We're not using 'click build' here as it corrects errors (such |
| 4470 | + # as filtering out a .click directory present in the build). We want |
| 4471 | + # to test with manually constructed, potentially tampered-with |
| 4472 | + # clicks/snaps. Ideally, we'd be using click rather than dpkg to |
| 4473 | + # construct the click without filtering any files in the build dir. |
| 4474 | + subprocess.check_call(['dpkg-deb', '-b', path, output_path]) |
| 4475 | return output_path |

I implemented the remaining lint tests but need to update the testsuite.