diff -Nru click-0.4.31.3/click/commands/build.py click-0.4.32.1/click/commands/build.py --- click-0.4.31.3/click/commands/build.py 2014-08-22 17:18:22.000000000 +0000 +++ click-0.4.32.1/click/commands/build.py 2014-09-09 10:00:56.000000000 +0000 @@ -20,7 +20,9 @@ from optparse import OptionParser import os import sys +import subprocess +from gi.repository import Click from click.build import ClickBuildError, ClickBuilder @@ -29,6 +31,9 @@ parser.add_option( "-m", "--manifest", metavar="PATH", default="manifest.json", help="read package manifest from PATH (default: manifest.json)") + parser.add_option( + "--no-validate", action="store_false", default=True, dest="validate", + help="Don't run click-reviewers-tools check on resulting .click") options, args = parser.parse_args(argv) if len(args) < 1: parser.error("need directory") @@ -48,5 +53,20 @@ except ClickBuildError as e: print(e, file=sys.stderr) return 1 + if options.validate and Click.find_on_path('click-review'): + print("Now executing: click-review %s" % path) + try: + subprocess.check_call(['click-review', path]) + except subprocess.CalledProcessError: + # qtcreator-plugin-ubuntu relies on return code 0 + # to establish if a .click package has been built + # at all. + # + # If we want to distinguish between + # - click build failed + # - click build succeeded, but validation failed + # both tools will have to learn this at the same + # time. + pass print("Successfully built package in '%s'." % path) return 0 diff -Nru click-0.4.31.3/click/install.py click-0.4.32.1/click/install.py --- click-0.4.31.3/click/install.py 2014-08-22 17:18:55.000000000 +0000 +++ click-0.4.32.1/click/install.py 2014-09-09 10:00:56.000000000 +0000 @@ -177,6 +177,15 @@ logging.warning( "debsig-verify not available; cannot check signatures") + # fail early if the file cannot be opened + try: + with closing(DebFile(filename=path)) as package: + pass + except Exception as e: + raise ClickInstallerError("Failed to read %s: %s" % ( + path, str(e))) + + # then perform the audit with closing(DebFile(filename=path)) as package: control_fields = package.control.debcontrol() Binary files /tmp/7smmRgueLl/click-0.4.31.3/click/tests/integration/data/evil-keyring/pubring.gpg and /tmp/tBwn8h0cNR/click-0.4.32.1/click/tests/integration/data/evil-keyring/pubring.gpg differ Binary files /tmp/7smmRgueLl/click-0.4.31.3/click/tests/integration/data/evil-keyring/secring.gpg and /tmp/tBwn8h0cNR/click-0.4.32.1/click/tests/integration/data/evil-keyring/secring.gpg differ Binary files /tmp/7smmRgueLl/click-0.4.31.3/click/tests/integration/data/evil-keyring/trustdb.gpg and /tmp/tBwn8h0cNR/click-0.4.32.1/click/tests/integration/data/evil-keyring/trustdb.gpg differ Binary files /tmp/7smmRgueLl/click-0.4.31.3/click/tests/integration/data/origin-keyring/pubring.gpg and /tmp/tBwn8h0cNR/click-0.4.32.1/click/tests/integration/data/origin-keyring/pubring.gpg differ Binary files /tmp/7smmRgueLl/click-0.4.31.3/click/tests/integration/data/origin-keyring/secring.gpg and /tmp/tBwn8h0cNR/click-0.4.32.1/click/tests/integration/data/origin-keyring/secring.gpg differ Binary files /tmp/7smmRgueLl/click-0.4.31.3/click/tests/integration/data/origin-keyring/trustdb.gpg and /tmp/tBwn8h0cNR/click-0.4.32.1/click/tests/integration/data/origin-keyring/trustdb.gpg differ diff -Nru click-0.4.31.3/click/tests/integration/helpers.py click-0.4.32.1/click/tests/integration/helpers.py --- click-0.4.31.3/click/tests/integration/helpers.py 1970-01-01 00:00:00.000000000 +0000 +++ click-0.4.32.1/click/tests/integration/helpers.py 2014-09-09 10:00:56.000000000 +0000 @@ -0,0 +1,124 @@ +# Copyright (C) 2014 Canonical Ltd. +# Author: Michael Vogt + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +"""Integration tests helper for the click CLI interface.""" + +import contextlib +import glob +import json +import os +import random +import shutil +import string +import subprocess +import tempfile +import unittest + + +def require_root(): + if os.getuid() != 0: + raise unittest.SkipTest("This test needs to run as root") + + +def require_network(): + try: + if subprocess.call(["ping", "-c1", "archive.ubuntu.com"]) != 0: + raise unittest.SkipTest("Need network") + except Exception: + pass + + +@contextlib.contextmanager +def chdir(target): + curdir = os.getcwd() + os.chdir(target) + try: + yield + finally: + os.chdir(curdir) + + +def cmdline_for_user(username): + """Helper to get the click commandline for the given username""" + if username == "@all": + user = "--all-users" + else: + user = "--user=%s" % username + return user + + +class ClickTestCase(unittest.TestCase): + + @classmethod + def setUpClass(cls): + if "TEST_INTEGRATION" not in os.environ: + raise unittest.SkipTest("Skipping integration tests") + cls.click_binary = os.environ.get("CLICK_BINARY", "/usr/bin/click") + + def setUp(self): + super(ClickTestCase, self).setUp() + self.temp_dir = tempfile.mkdtemp() + + def tearDown(self): + super(ClickTestCase, self).tearDown() + # we force the cleanup before removing the tempdir so that stuff + # in temp_dir is still available + self.doCleanups() + shutil.rmtree(self.temp_dir) + + def click_install(self, path_to_click, click_name, username, + allow_unauthenticated=True): + cmd = [self.click_binary, "install", cmdline_for_user(username)] + if allow_unauthenticated: + cmd.append("--allow-unauthenticated") + cmd.append(path_to_click) + subprocess.check_call(cmd) + self.addCleanup(self.click_unregister, click_name, username) + + def click_unregister(self, click_name, username): + subprocess.check_call( + [self.click_binary, "unregister", cmdline_for_user(username), + click_name]) + + def _create_manifest(self, target, name, version, framework, hooks={}): + with open(target, "w") as f: + json.dump({ + 'name': name, + 'version': str(version), + 'maintainer': 'Foo Bar ', + 'title': 'test title', + 'framework': framework, + 'hooks': hooks, + }, f) + + def _make_click(self, name=None, version=1.0, + framework="ubuntu-sdk-13.10", hooks={}): + if name is None: + name = "com.example.%s" % "".join( + random.choice(string.ascii_lowercase) for i in range(10)) + tmpdir = tempfile.mkdtemp() + self.addCleanup(lambda: shutil.rmtree(tmpdir)) + clickdir = os.path.join(tmpdir, name) + os.makedirs(clickdir) + self._create_manifest(os.path.join(clickdir, "manifest.json"), + name, version, framework, hooks) + with open(os.path.join(clickdir, "README"), "w") as f: + f.write("hello world!") + with chdir(tmpdir), open(os.devnull, "w") as devnull: + subprocess.call( + [self.click_binary, "build", clickdir], stdout=devnull) + generated_clicks = glob.glob(os.path.join(tmpdir, "*.click")) + self.assertEqual(len(generated_clicks), 1) + return generated_clicks[0] diff -Nru click-0.4.31.3/click/tests/integration/test_build_core_apps.py click-0.4.32.1/click/tests/integration/test_build_core_apps.py --- click-0.4.31.3/click/tests/integration/test_build_core_apps.py 1970-01-01 00:00:00.000000000 +0000 +++ click-0.4.32.1/click/tests/integration/test_build_core_apps.py 2014-09-09 10:00:56.000000000 +0000 @@ -0,0 +1,124 @@ +# Copyright (C) 2014 Canonical Ltd. +# Author: Michael Vogt + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +"""Integration tests for the click chroot feature.""" + +from glob import glob +import json +import os +import shutil +import subprocess + +from six import with_metaclass + +from .helpers import ( + chdir, + require_network, + require_root, + ClickTestCase, +) + +# the branches we want to testbuild +TEST_BUILD_BRANCHES = [ + "lp:camera-app", + "lp:notes-app", +] + +# command to "configure" +CORE_APP_CONFIGURE_CMD = [ + "cmake", "..", "-DCLICK_MODE=on", "-DINSTALL_TESTS=off"] + +# command to make install +CLICK_TARGET_DIR = "click-package" +CORE_APP_MAKE_CMD = [ + "make", "DESTDIR=%s" % CLICK_TARGET_DIR, "install"] + + +def find_manifest(start_dir): + """Find a click manifest.json{,.in} under the given directory""" + for path, dirs, files in os.walk(start_dir): + for needle in ["manifest.json", "manifest.json.in"]: + if needle in files: + return os.path.join(path, needle) + return None + + +class AddBranchTestFunctions(type): + """Metaclass that creates one test for each branch""" + def __new__(cls, name, bases, dct): + for branch in TEST_BUILD_BRANCHES: + name = "test_build_%s" % branch.split(":")[1].replace("-", "_") + dct[name] = lambda self: self._testbuild_branch(branch) + return type.__new__(cls, name, bases, dct) + + +class TestBuildCoreApps(with_metaclass(AddBranchTestFunctions, ClickTestCase)): + + @classmethod + def setUpClass(cls): + super(TestBuildCoreApps, cls).setUpClass() + require_root() + require_network() + + def _run_in_chroot(self, cmd): + """Run the given cmd in a click chroot""" + return subprocess.check_call(self.chroot_cmd + ["run"] + cmd) + + def _set_arch_and_framework_from_manifest(self, manifest): + with open(manifest) as f: + data = json.load(f) + self.arch = data["architecture"] + self.framework = data["framework"] + + @property + def chroot_cmd(self): + return [ + self.click_binary, "chroot", "-a", self.arch, "-f", self.framework] + + def _ensure_click_chroot(self): + if subprocess.call(self.chroot_cmd + ["exists"]) != 0: + subprocess.check_call(self.chroot_cmd + ["create"]) + + def configure(self): + self._run_in_chroot(CORE_APP_CONFIGURE_CMD) + + def make(self): + self._run_in_chroot(CORE_APP_MAKE_CMD) + + def create_click(self): + subprocess.check_call( + [self.click_binary, "build", CLICK_TARGET_DIR]) + # we expect exactly one click + self.assertEqual(len(glob("*.click")), 1) + + def _testbuild_branch(self, branch): + # get and parse + branch_dir = branch[len("lp:"):] + build_dir = os.path.join(branch_dir, "build-tree") + if os.path.exists(branch_dir): + subprocess.check_call(["bzr", "pull"], cwd=branch_dir) + else: + subprocess.check_call(["bzr", "branch", branch]) + manifest = find_manifest(branch_dir) + # build it + self._set_arch_and_framework_from_manifest(manifest) + if os.path.exists(build_dir): + shutil.rmtree(build_dir) + os.makedirs(build_dir) + with chdir(build_dir): + self._ensure_click_chroot() + self.configure() + self.make() + self.create_click() diff -Nru click-0.4.31.3/click/tests/integration/test_build.py click-0.4.32.1/click/tests/integration/test_build.py --- click-0.4.31.3/click/tests/integration/test_build.py 1970-01-01 00:00:00.000000000 +0000 +++ click-0.4.32.1/click/tests/integration/test_build.py 2014-09-09 10:00:20.000000000 +0000 @@ -0,0 +1,26 @@ +# Copyright (C) 2014 Canonical Ltd. +# Author: Michael Vogt + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +"""Integration tests for the click CLI build command.""" + +import os + +from .helpers import ClickTestCase + + +class TestBuild(ClickTestCase): + def test_build(self): + path_to_click = self._make_click() + self.assertTrue(os.path.exists(path_to_click)) diff -Nru click-0.4.31.3/click/tests/integration/test_buildsource.py click-0.4.32.1/click/tests/integration/test_buildsource.py --- click-0.4.31.3/click/tests/integration/test_buildsource.py 1970-01-01 00:00:00.000000000 +0000 +++ click-0.4.32.1/click/tests/integration/test_buildsource.py 2014-09-09 10:00:20.000000000 +0000 @@ -0,0 +1,51 @@ +# Copyright (C) 2014 Canonical Ltd. +# Author: Michael Vogt + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +"""Integration tests for the click CLI buildsource command.""" + +import os +import shutil +import subprocess +import tarfile +import tempfile + +from .helpers import ( + chdir, + ClickTestCase, +) + + +class TestBuildSource(ClickTestCase): + + def test_buildsource(self): + temp_dir = tempfile.mkdtemp() + self.addCleanup(shutil.rmtree, temp_dir) + with chdir(temp_dir): + with open(os.path.join(temp_dir, "README"), "w") as f: + f.write("I'm a source package") + os.mkdir(os.path.join(temp_dir, ".git")) + os.mkdir(os.path.join(temp_dir, ".bzr")) + os.mkdir(os.path.join(temp_dir, ".normal")) + self._create_manifest(os.path.join(temp_dir, "manifest.json"), + "srcfoo", "1.2", "ubuntu-sdk-13.10") + subprocess.check_call( + [self.click_binary, "buildsource", temp_dir], + universal_newlines=True) + # ensure we have the content we expect + source_file = "srcfoo_1.2.tar.gz" + tar = tarfile.open(source_file) + self.assertEqual( + sorted(tar.getnames()), + sorted([".", "./.normal", "./manifest.json", "./README"])) diff -Nru click-0.4.31.3/click/tests/integration/test_chroot.py click-0.4.32.1/click/tests/integration/test_chroot.py --- click-0.4.31.3/click/tests/integration/test_chroot.py 1970-01-01 00:00:00.000000000 +0000 +++ click-0.4.32.1/click/tests/integration/test_chroot.py 2014-09-09 10:00:56.000000000 +0000 @@ -0,0 +1,78 @@ +# Copyright (C) 2014 Canonical Ltd. +# Author: Michael Vogt + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +"""Integration tests for the click chroot feature.""" + +import subprocess + +from .helpers import ( + require_network, + require_root, + ClickTestCase, +) + + +class TestChroot(ClickTestCase): + + @classmethod + def setUpClass(cls): + super(TestChroot, cls).setUpClass() + require_root() + require_network() + cls.arch = subprocess.check_output( + ["dpkg", "--print-architecture"], universal_newlines=True).strip() + subprocess.check_call([ + cls.click_binary, + "chroot", "-a", cls.arch, + "create"]) + + @classmethod + def tearDownClass(cls): + subprocess.check_call([ + cls.click_binary, + "chroot", "-a", cls.arch, + "destroy"]) + + def test_upgrade(self): + subprocess.check_call([ + self.click_binary, "chroot", "-a", self.arch, + "upgrade"]) + + def test_install(self): + subprocess.check_call([ + self.click_binary, "chroot", "-a", self.arch, + "install", "apt-utils"]) + + def test_run(self): + output = subprocess.check_output([ + self.click_binary, "chroot", "-a", self.arch, + "run", "echo", "hello world"], universal_newlines=True) + self.assertEqual(output, "hello world\n") + + def test_maint(self): + output = subprocess.check_output([ + self.click_binary, "chroot", "-a", self.arch, + "maint", "id"], universal_newlines=True) + self.assertEqual(output, "uid=0(root) gid=0(root) groups=0(root)\n") + + def test_exists_ok(self): + subprocess.check_call([ + self.click_binary, "chroot", "-a", self.arch, "exists"]) + + def test_exists_no(self): + with self.assertRaises(subprocess.CalledProcessError): + subprocess.check_call([ + self.click_binary, + "chroot", "-a", "arch-that-does-not-exist"]) diff -Nru click-0.4.31.3/click/tests/integration/test_contents.py click-0.4.32.1/click/tests/integration/test_contents.py --- click-0.4.31.3/click/tests/integration/test_contents.py 1970-01-01 00:00:00.000000000 +0000 +++ click-0.4.32.1/click/tests/integration/test_contents.py 2014-09-09 10:00:56.000000000 +0000 @@ -0,0 +1,33 @@ +# Copyright (C) 2014 Canonical Ltd. +# Author: Michael Vogt + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +"""Integration tests for the click CLI contents command.""" + +import re +import subprocess + +from .helpers import ClickTestCase + + +class TestContents(ClickTestCase): + def test_contents(self): + name = "com.example.contents" + path_to_click = self._make_click(name) + output = subprocess.check_output([ + self.click_binary, "contents", path_to_click], + universal_newlines=True) + self.assertTrue(re.search( + r'-rw-r[-w]-r-- root/root\s+[0-9]+\s+[0-9-]+ [0-9:]+ ./README', + output)) diff -Nru click-0.4.31.3/click/tests/integration/test_frameworks.py click-0.4.32.1/click/tests/integration/test_frameworks.py --- click-0.4.31.3/click/tests/integration/test_frameworks.py 1970-01-01 00:00:00.000000000 +0000 +++ click-0.4.32.1/click/tests/integration/test_frameworks.py 2014-09-09 10:00:56.000000000 +0000 @@ -0,0 +1,34 @@ +# Copyright (C) 2014 Canonical Ltd. +# Author: Michael Vogt + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +"""Integration tests for the click CLI frameworks command.""" + +import os +import subprocess + +from .helpers import ClickTestCase + + +class TestFrameworks(ClickTestCase): + def setUp(self): + super(TestFrameworks, self).setUp() + if (not os.path.exists("/usr/share/click/frameworks") or + not os.listdir("/usr/share/click/frameworks")): + self.skipTest("Please install ubuntu-sdk-libs") + + def test_framework_list(self): + output = subprocess.check_output([ + self.click_binary, "framework", "list"], universal_newlines=True) + self.assertTrue("ubuntu-sdk-" in output) diff -Nru click-0.4.31.3/click/tests/integration/test_hook.py click-0.4.32.1/click/tests/integration/test_hook.py --- click-0.4.31.3/click/tests/integration/test_hook.py 1970-01-01 00:00:00.000000000 +0000 +++ click-0.4.32.1/click/tests/integration/test_hook.py 2014-09-09 10:00:56.000000000 +0000 @@ -0,0 +1,80 @@ +# Copyright (C) 2014 Canonical Ltd. +# Author: Michael Vogt + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +"""Integration tests for the click hook feature.""" + +import os +import subprocess +from textwrap import dedent + +from .helpers import ( + ClickTestCase, + require_root, +) + + +class TestHook(ClickTestCase): + + @classmethod + def setUpClass(cls): + super(TestHook, cls).setUpClass() + require_root() + + def _make_hook(self, name): + hook_fname = "/usr/share/click/hooks/%s.hook" % name + canary_fname = os.path.join(self.temp_dir, "canary.sh") + canary_log = os.path.join(self.temp_dir, "canary.log") + with open(hook_fname, "w") as f: + f.write(dedent("""\ + Pattern: ${home}/${id}.test-hook + User-Level: yes + Exec: %s + Hook-Name: %s + """ % (canary_fname, name))) + with open(canary_fname, "w") as f: + f.write(dedent("""\ + #!/bin/sh + echo "i-hook-you-up" >> %s + """ % canary_log)) + os.chmod(canary_fname, 0o755) + return hook_fname, canary_log + + def test_hook_install_user(self): + # build/install the hook + hook_name = "clicktesthook" + hook_file, hook_log = self._make_hook(hook_name) + self.addCleanup(os.unlink, hook_file) + subprocess.check_call( + [self.click_binary, "hook", "install", hook_name]) + self.addCleanup( + subprocess.check_call, [self.click_binary, "hook", "remove", + hook_name]) + # make click that uses the hook + hooks = {'app1': {hook_name: 'README'}} + click_pkg_name = "com.example.hook-1" + click_pkg = self._make_click( + click_pkg_name, framework="", hooks=hooks) + user = os.environ.get("USER", "root") + self.click_install(click_pkg, click_pkg_name, user) + # ensure we have the hook + generated_hook_file = os.path.expanduser( + "~/com.example.hook-1_app1_1.0.test-hook") + self.assertTrue(os.path.exists(generated_hook_file)) + self.assertEqual( + os.path.realpath(generated_hook_file), + "/opt/click.ubuntu.com/com.example.hook-1/1.0/README") + with open(hook_log) as f: + hook_log_content = f.read().strip() + self.assertEqual("i-hook-you-up", hook_log_content) diff -Nru click-0.4.31.3/click/tests/integration/test_info.py click-0.4.32.1/click/tests/integration/test_info.py --- click-0.4.31.3/click/tests/integration/test_info.py 1970-01-01 00:00:00.000000000 +0000 +++ click-0.4.32.1/click/tests/integration/test_info.py 2014-09-09 10:00:56.000000000 +0000 @@ -0,0 +1,57 @@ +# Copyright (C) 2014 Canonical Ltd. +# Author: Michael Vogt + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +"""Integration tests for the click CLI info command.""" + +import json +import os +import subprocess + +from .helpers import ClickTestCase + + +class TestInfo(ClickTestCase): + def test_info_from_path(self): + name = "com.example.foo" + path_to_click = self._make_click(name) + output = subprocess.check_output([ + self.click_binary, "info", path_to_click], universal_newlines=True) + self.assertEqual(name, json.loads(output)["name"]) + + + def test_info_installed_click(self): + name = "com.example.foo" + user = os.environ.get("USER", "root") + path_to_click = self._make_click(name, framework="") + self.click_install(path_to_click, name, user) + output = subprocess.check_output([ + self.click_binary, "info", name], universal_newlines=True) + self.assertEqual(json.loads(output)["name"], name) + + def test_info_file_in_package(self): + name = "org.example.info" + version = "1.0" + click_pkg = self._make_click(name=name, version=version, framework="") + subprocess.check_call( + [self.click_binary, "install", "--allow-unauthenticated", + "--all-users", click_pkg]) + self.addCleanup( + subprocess.check_call, + [self.click_binary, "unregister", "--all-users", name]) + output = subprocess.check_output( + [self.click_binary, "info", + "/opt/click.ubuntu.com/%s/%s/README" % (name, version)], + universal_newlines=True) + self.assertEqual(name, json.loads(output)["name"]) diff -Nru click-0.4.31.3/click/tests/integration/test_install.py click-0.4.32.1/click/tests/integration/test_install.py --- click-0.4.31.3/click/tests/integration/test_install.py 1970-01-01 00:00:00.000000000 +0000 +++ click-0.4.32.1/click/tests/integration/test_install.py 2014-09-09 10:00:56.000000000 +0000 @@ -0,0 +1,118 @@ +# Copyright (C) 2014 Canonical Ltd. +# Author: Michael Vogt + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +"""Integration tests for the click install feature.""" + +import subprocess + +from .helpers import ( + require_root, + ClickTestCase, +) + + +def add_user(name): + subprocess.check_call(["useradd", name]) + return name + + +def del_user(name): + subprocess.check_call(["userdel", "-r", name]) + + +class TestClickInstall(ClickTestCase): + + @classmethod + def setUpClass(cls): + super(TestClickInstall, cls).setUpClass() + require_root() + cls.USER_1 = add_user("click-test-user-1") + cls.USER_2 = add_user("click-test-user-2") + + @classmethod + def tearDownClass(cls): + super(TestClickInstall, cls).tearDownClass() + del_user(cls.USER_1) + del_user(cls.USER_2) + + def test_install_for_single_user(self): + name = "foo-1" + click_pkg = self._make_click(name=name, framework="") + # install it + self.click_install(click_pkg, name, self.USER_1) + # ensure that user-1 has it + output = subprocess.check_output([ + "sudo", "-u", self.USER_1, + self.click_binary, "list"], universal_newlines=True) + self.assertEqual(output, "%s\t1.0\n" % name) + # but not user-2 + output = subprocess.check_output([ + "sudo", "-u", self.USER_2, + self.click_binary, "list"], universal_newlines=True) + self.assertEqual(output, "") + # and that we can see it with the --user option + output = subprocess.check_output( + [self.click_binary, "list", "--user=%s" % self.USER_1], + universal_newlines=True) + self.assertEqual(output, "%s\t1.0\n" % name) + + def test_install_for_single_user_and_register(self): + name = "foo-1" + click_pkg = self._make_click(name=name, framework="") + self.click_install(click_pkg, name, self.USER_1) + # not available for user2 + output = subprocess.check_output([ + "sudo", "-u", self.USER_2, + self.click_binary, "list"], universal_newlines=True) + self.assertEqual(output, "") + # register it + subprocess.check_call( + [self.click_binary, "register", "--user=%s" % self.USER_2, + name, "1.0", ]) + self.addCleanup(self.click_unregister, name, self.USER_2) + # and ensure its available for user2 + output = subprocess.check_output([ + "sudo", "-u", self.USER_2, + self.click_binary, "list"], universal_newlines=True) + self.assertEqual(output, "%s\t1.0\n" % name) + + def test_install_for_all_users(self): + name = "foo-2" + click_pkg = self._make_click(name=name, framework="") + self.click_install(click_pkg, name, "@all") + # ensure all users see it + for user in (self.USER_1, self.USER_2): + output = subprocess.check_output( + ["sudo", "-u", user, self.click_binary, "list"], + universal_newlines=True) + self.assertEqual(output, "%s\t1.0\n" % name) + + def test_pkgdir_after_install(self): + name = "foo-3" + click_pkg = self._make_click(name=name, version="1.2", framework="") + self.click_install(click_pkg, name, "@all") + # from the path + output = subprocess.check_output( + [self.click_binary, "pkgdir", + "/opt/click.ubuntu.com/%s/1.2/README" % name], + universal_newlines=True).strip() + self.assertEqual(output, "/opt/click.ubuntu.com/%s/1.2" % name) + # now test from the click package name + output = subprocess.check_output( + [self.click_binary, "pkgdir", name], + universal_newlines=True).strip() + # note that this is different from above + self.assertEqual( + output, "/opt/click.ubuntu.com/.click/users/@all/%s" % name) diff -Nru click-0.4.31.3/click/tests/integration/test_list.py click-0.4.32.1/click/tests/integration/test_list.py --- click-0.4.31.3/click/tests/integration/test_list.py 1970-01-01 00:00:00.000000000 +0000 +++ click-0.4.32.1/click/tests/integration/test_list.py 2014-09-09 10:00:56.000000000 +0000 @@ -0,0 +1,33 @@ +# Copyright (C) 2014 Canonical Ltd. +# Author: Michael Vogt + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +"""Integration tests for the click CLI list command.""" + +import os +import subprocess + +from .helpers import ClickTestCase + + +class TestList(ClickTestCase): + def test_list_simple(self): + name = "com.ubuntu.verify-ok" + path_to_click = self._make_click(name, framework="") + user = os.environ.get("USER", "root") + self.click_install(path_to_click, name, user) + output = subprocess.check_output( + [self.click_binary, "list", "--user=%s" % user], + universal_newlines=True) + self.assertIn(name, output) diff -Nru click-0.4.31.3/click/tests/integration/test_signatures.py click-0.4.32.1/click/tests/integration/test_signatures.py --- click-0.4.31.3/click/tests/integration/test_signatures.py 1970-01-01 00:00:00.000000000 +0000 +++ click-0.4.32.1/click/tests/integration/test_signatures.py 2014-09-09 10:00:56.000000000 +0000 @@ -0,0 +1,364 @@ +# Copyright (C) 2014 Canonical Ltd. +# Author: Michael Vogt + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +"""Integration tests for the click signature checking.""" + +import copy +import os +import shutil +import subprocess +import tarfile +from textwrap import dedent + +from .helpers import ( + require_root, + ClickTestCase, +) + + +def makedirs(path): + try: + os.makedirs(path) + except OSError: + pass + + +def get_keyid_from_gpghome(gpg_home): + """Return the public keyid of a given gpg home dir""" + output = subprocess.check_output( + ["gpg", "--home", gpg_home, "--list-keys", "--with-colons"], + universal_newlines=True) + for line in output.splitlines(): + if not line.startswith("pub:"): + continue + return line.split(":")[4] + raise ValueError("Cannot find public key in output: '%s'" % output) + + +class Debsigs: + """Tiny wrapper around the debsigs CLI""" + def __init__(self, gpghome, keyid): + self.keyid = keyid + self.gpghome = gpghome + self.policy = "/etc/debsig/policies/%s/generic.pol" % self.keyid + + def sign(self, filepath, signature_type="origin"): + """Sign the click at filepath""" + env = copy.copy(os.environ) + env["GNUPGHOME"] = os.path.abspath(self.gpghome) + subprocess.check_call( + ["debsigs", + "--sign=%s" % signature_type, + "--default-key=%s" % self.keyid, + filepath], env=env) + + def install_signature_policy(self): + """Install/update the system-wide signature policy""" + xmls = dedent("""\ + + + + + + + + + + + + + + """.format(keyid=self.keyid, filename="origin.pub")) + makedirs(os.path.dirname(self.policy)) + with open(self.policy, "w") as f: + f.write(xmls) + self.pubkey_path = ( + "/usr/share/debsig/keyrings/%s/origin.pub" % self.keyid) + makedirs(os.path.dirname(self.pubkey_path)) + shutil.copy( + os.path.join(self.gpghome, "pubring.gpg"), self.pubkey_path) + + def uninstall_signature_policy(self): + # FIXME: update debsig-verify so that it can work from a different + # root than "/" so that the tests do not have to use the + # system root + os.remove(self.policy) + os.remove(self.pubkey_path) + + +class ClickSignaturesTestCase(ClickTestCase): + + @classmethod + def setUpClass(cls): + super(ClickSignaturesTestCase, cls).setUpClass() + require_root() + + def assertClickNoSignatureError(self, cmd_args): + with self.assertRaises(subprocess.CalledProcessError) as cm: + output = subprocess.check_output( + [self.click_binary] + cmd_args, + stderr=subprocess.STDOUT, universal_newlines=True) + output = cm.exception.output + expected_error_message = ("debsig: Origin Signature check failed. " + "This deb might not be signed.") + self.assertIn(expected_error_message, output) + + def assertClickInvalidSignatureError(self, cmd_args): + with self.assertRaises(subprocess.CalledProcessError) as cm: + output = subprocess.check_output( + [self.click_binary] + cmd_args, + stderr=subprocess.STDOUT, universal_newlines=True) + print(output) + + output = cm.exception.output + expected_error_message = "Signature verification error: " + self.assertIn(expected_error_message, output) + + +class TestSignatureVerificationNoSignature(ClickSignaturesTestCase): + + @classmethod + def setUpClass(cls): + super(TestSignatureVerificationNoSignature, cls).setUpClass() + require_root() + + def test_debsig_verify_no_sig(self): + name = "org.example.debsig-no-sig" + path_to_click = self._make_click(name, framework="") + self.assertClickNoSignatureError(["verify", path_to_click]) + + def test_debsig_install_no_sig(self): + name = "org.example.debsig-no-sig" + path_to_click = self._make_click(name, framework="") + self.assertClickNoSignatureError(["install", path_to_click]) + + def test_debsig_install_can_install_with_sig_override(self): + name = "org.example.debsig-no-sig" + path_to_click = self._make_click(name, framework="") + user = os.environ.get("USER", "root") + subprocess.check_call( + [self.click_binary, "install", + "--allow-unauthenticated", "--user=%s" % user, + path_to_click]) + self.addCleanup( + subprocess.call, [self.click_binary, "unregister", + "--user=%s" % user, name]) + + +class TestSignatureVerification(ClickSignaturesTestCase): + + @classmethod + def setUpClass(cls): + super(TestSignatureVerification, cls).setUpClass() + require_root() + + def setUp(self): + super(TestSignatureVerification, self).setUp() + self.user = os.environ.get("USER", "root") + # the valid origin keyring + self.datadir = os.path.join(os.path.dirname(__file__), "data") + origin_keyring_dir = os.path.abspath( + os.path.join(self.datadir, "origin-keyring")) + keyid = get_keyid_from_gpghome(origin_keyring_dir) + self.debsigs = Debsigs(origin_keyring_dir, keyid) + self.debsigs.install_signature_policy() + + def tearDown(self): + self.debsigs.uninstall_signature_policy() + + def test_debsig_install_valid_signature(self): + name = "org.example.debsig-valid-sig" + path_to_click = self._make_click(name, framework="") + self.debsigs.sign(path_to_click) + subprocess.check_call( + [self.click_binary, "install", + "--user=%s" % self.user, + path_to_click]) + self.addCleanup( + subprocess.call, [self.click_binary, "unregister", + "--user=%s" % self.user, name]) + output = subprocess.check_output( + [self.click_binary, "list", "--user=%s" % self.user], + universal_newlines=True) + self.assertIn(name, output) + + def test_debsig_install_signature_not_in_keyring(self): + name = "org.example.debsig-no-keyring-sig" + path_to_click = self._make_click(name, framework="") + evil_keyring_dir = os.path.join(self.datadir, "evil-keyring") + keyid = get_keyid_from_gpghome(evil_keyring_dir) + debsig_bad = Debsigs(evil_keyring_dir, keyid) + debsig_bad.sign(path_to_click) + # and ensure its really not there + self.assertClickInvalidSignatureError(["install", path_to_click]) + output = subprocess.check_output( + [self.click_binary, "list", "--user=%s" % self.user], + universal_newlines=True) + self.assertNotIn(name, output) + + def test_debsig_install_not_a_signature(self): + name = "org.example.debsig-invalid-sig" + path_to_click = self._make_click(name, framework="") + invalid_sig = os.path.join(self.temp_dir, "_gpgorigin") + with open(invalid_sig, "w") as f: + f.write("no-valid-signature") + # add a invalid sig + subprocess.check_call(["ar", "-r", path_to_click, invalid_sig]) + self.assertClickInvalidSignatureError(["install", path_to_click]) + output = subprocess.check_output( + [self.click_binary, "list", "--user=%s" % self.user], + universal_newlines=True) + self.assertNotIn(name, output) + + def test_debsig_install_signature_altered_click(self): + def modify_ar_member(member): + subprocess.check_call( + ["ar", "-x", path_to_click, "control.tar.gz"], + cwd=self.temp_dir) + altered_member = os.path.join(self.temp_dir, member) + with open(altered_member, "ba") as f: + f.write(b"\0") + subprocess.check_call(["ar", "-r", path_to_click, altered_member]) + + # ensure that all members we care about are checked by debsig-verify + for member in ["control.tar.gz", "data.tar.gz", "debian-binary"]: + name = "org.example.debsig-altered-click" + path_to_click = self._make_click(name, framework="") + self.debsigs.sign(path_to_click) + modify_ar_member(member) + self.assertClickInvalidSignatureError(["install", path_to_click]) + output = subprocess.check_output( + [self.click_binary, "list", "--user=%s" % self.user], + universal_newlines=True) + self.assertNotIn(name, output) + + def make_nasty_data_tar(self, compression): + new_data_tar = os.path.join(self.temp_dir, "data.tar." + compression) + evilfile = os.path.join(self.temp_dir, "README.evil") + with open(evilfile, "w") as f: + f.write("I am a nasty README") + with tarfile.open(new_data_tar, "w:"+compression) as tar: + tar.add(evilfile) + return new_data_tar + + def test_debsig_install_signature_injected_data_tar(self): + name = "org.example.debsig-injected-data-click" + path_to_click = self._make_click(name, framework="") + self.debsigs.sign(path_to_click) + new_data = self.make_nasty_data_tar("bz2") + # insert before the real data.tar.gz and ensure this is caught + # NOTE: that right now this will not be caught by debsig-verify + # but later in audit() by debian.debfile.DebFile() + subprocess.check_call(["ar", + "-r", + "-b", "data.tar.gz", + path_to_click, + new_data]) + output = subprocess.check_output( + ["ar", "-t", path_to_click], universal_newlines=True) + self.assertEqual(output.splitlines(), + ["debian-binary", + "_click-binary", + "control.tar.gz", + "data.tar.bz2", + "data.tar.gz", + "_gpgorigin"]) + with self.assertRaises(subprocess.CalledProcessError): + output = subprocess.check_output( + [self.click_binary, "install", path_to_click], + stderr=subprocess.STDOUT, universal_newlines=True) + output = subprocess.check_output( + [self.click_binary, "list", "--user=%s" % self.user], + universal_newlines=True) + self.assertNotIn(name, output) + + def test_debsig_install_signature_replaced_data_tar(self): + name = "org.example.debsig-replaced-data-click" + path_to_click = self._make_click(name, framework="") + self.debsigs.sign(path_to_click) + new_data = self.make_nasty_data_tar("bz2") + # replace data.tar.gz with data.tar.bz2 and ensure this is caught + subprocess.check_call(["ar", + "-d", + path_to_click, + "data.tar.gz", + ]) + subprocess.check_call(["ar", + "-r", + path_to_click, + new_data]) + output = subprocess.check_output( + ["ar", "-t", path_to_click], universal_newlines=True) + self.assertEqual(output.splitlines(), + ["debian-binary", + "_click-binary", + "control.tar.gz", + "_gpgorigin", + "data.tar.bz2", + ]) + with self.assertRaises(subprocess.CalledProcessError) as cm: + output = subprocess.check_output( + [self.click_binary, "install", path_to_click], + stderr=subprocess.STDOUT, universal_newlines=True) + self.assertIn("Signature verification error", cm.exception.output) + output = subprocess.check_output( + [self.click_binary, "list", "--user=%s" % self.user], + universal_newlines=True) + self.assertNotIn(name, output) + + def test_debsig_install_signature_prepend_sig(self): + # this test is probably not really needed, it tries to trick + # the system by prepending a valid signature that is not + # in the keyring. But given that debsig-verify only reads + # the first packet of any given _gpg$foo signature it's + # equivalent to test_debsig_install_signature_not_in_keyring test + name = "org.example.debsig-replaced-data-prepend-sig-click" + path_to_click = self._make_click(name, framework="") + self.debsigs.sign(path_to_click) + new_data = self.make_nasty_data_tar("gz") + # replace data.tar.gz + subprocess.check_call(["ar", + "-r", + path_to_click, + new_data, + ]) + # get previous good _gpgorigin for the old data + subprocess.check_call( + ["ar", "-x", path_to_click, "_gpgorigin"], cwd=self.temp_dir) + with open(os.path.join(self.temp_dir, "_gpgorigin"), "br") as f: + good_gpg_origin = f.read() + # and append a valid signature from a non-keyring key + evil_keyring_dir = os.path.join(self.datadir, "evil-keyring") + debsig_bad = Debsigs(evil_keyring_dir, "18B38B9AC1B67A0D") + debsig_bad.sign(path_to_click) + subprocess.check_call( + ["ar", "-x", path_to_click, "_gpgorigin"], cwd=self.temp_dir) + with open(os.path.join(self.temp_dir, "_gpgorigin"), "br") as f: + evil_gpg_origin = f.read() + with open(os.path.join(self.temp_dir, "_gpgorigin"), "wb") as f: + f.write(evil_gpg_origin) + f.write(good_gpg_origin) + subprocess.check_call( + ["ar", "-r", path_to_click, "_gpgorigin"], cwd=self.temp_dir) + # now ensure that the verification fails as well + with self.assertRaises(subprocess.CalledProcessError) as cm: + output = subprocess.check_output( + [self.click_binary, "install", path_to_click], + stderr=subprocess.STDOUT, universal_newlines=True) + self.assertIn("Signature verification error", cm.exception.output) + output = subprocess.check_output( + [self.click_binary, "list", "--user=%s" % self.user], + universal_newlines=True) + self.assertNotIn(name, output) diff -Nru click-0.4.31.3/click/tests/integration/test_verify.py click-0.4.32.1/click/tests/integration/test_verify.py --- click-0.4.31.3/click/tests/integration/test_verify.py 1970-01-01 00:00:00.000000000 +0000 +++ click-0.4.32.1/click/tests/integration/test_verify.py 2014-09-09 10:00:56.000000000 +0000 @@ -0,0 +1,72 @@ +# Copyright (C) 2014 Canonical Ltd. +# Author: Michael Vogt + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +"""Integration tests for the click CLI verify command.""" + +import os +import subprocess + +from .helpers import ClickTestCase + + +class TestVerify(ClickTestCase): + def test_verify_force_missing_framework_ok(self): + name = "com.example.verify-missing-framework" + path_to_click = self._make_click(name) + output = subprocess.check_output([ + self.click_binary, "verify", + "--force-missing-framework", + "--allow-unauthenticated", + path_to_click], universal_newlines=True) + self.assertEqual(output, "") + + def test_verify_force_ok(self): + name = "com.example.verify-ok" + path_to_click = self._make_click(name, framework="") + output = subprocess.check_output([ + self.click_binary, "verify", "--allow-unauthenticated", + path_to_click], universal_newlines=True) + self.assertEqual(output, "") + + def test_verify_missing_framework(self): + name = "com.example.verify-really-missing-framework" + path_to_click = self._make_click(name, framework="missing") + with self.assertRaises(subprocess.CalledProcessError) as cm: + subprocess.check_output( + [self.click_binary, "verify", + "--allow-unauthenticated", + path_to_click], + universal_newlines=True, stderr=subprocess.STDOUT) + expected_error = ( + 'click.framework.ClickFrameworkInvalid: Framework ' + '"missing" not present on system (use ' + '--force-missing-framework option to override)') + self.assertIn(expected_error, cm.exception.output) + + def test_verify_no_click_but_invalid(self): + name = "com.example.verify-no-click" + path_to_click = os.path.join(self.temp_dir, name+".click") + with open(path_to_click, "w") as f: + f.write("something-that-is-not-a-click") + with self.assertRaises(subprocess.CalledProcessError) as cm: + subprocess.check_output( + [self.click_binary, "verify", "--allow-unauthenticated", + path_to_click], + universal_newlines=True, stderr=subprocess.STDOUT) + expected_error = ( + 'click.install.DebsigVerifyError: Signature verification error: ' + 'debsig: %s does not appear to be a deb format package' + ) % path_to_click + self.assertIn(expected_error, cm.exception.output) diff -Nru click-0.4.31.3/click/tests/test_build.py click-0.4.32.1/click/tests/test_build.py --- click-0.4.31.3/click/tests/test_build.py 2014-08-22 17:18:22.000000000 +0000 +++ click-0.4.32.1/click/tests/test_build.py 2014-09-09 10:00:56.000000000 +0000 @@ -63,14 +63,14 @@ with mkfile(manifest_path) as manifest: print(dedent("""\ { - "name": "com.ubuntu.test", + "name": "com.example.test", "version": "1.0", "maintainer": "Foo Bar ", "title": "test title", "framework": "ubuntu-sdk-13.10" }"""), file=manifest) self.builder.read_manifest(manifest_path) - self.assertEqual("com.ubuntu.test", self.builder.name) + self.assertEqual("com.example.test", self.builder.name) self.assertEqual("1.0", self.builder.version) self.assertEqual("Foo Bar ", self.builder.maintainer) self.assertEqual("test title", self.builder.title) @@ -90,7 +90,7 @@ with mkfile(manifest_path) as manifest: print(dedent("""\ { - "name": "com.ubuntu.test", + "name": "com.example.test", "version": "%s", "maintainer": "Foo Bar ", "title": "test title", @@ -106,7 +106,7 @@ # The comma after the "name" entry is intentionally missing. print(dedent("""\ { - "name": "com.ubuntu.test" + "name": "com.example.test" "version": "1.0" }"""), file=manifest) self.assertRaises( @@ -136,7 +136,7 @@ f.write("test /toplevel\n") with mkfile(os.path.join(scratch, "manifest.json")) as f: json.dump({ - "name": "com.ubuntu.test", + "name": "com.example.test", "version": "1.0", "maintainer": "Foo Bar ", "title": "test title", @@ -146,11 +146,11 @@ # build() overrides this back to 0o644 os.fchmod(f.fileno(), 0o600) self.builder.add_file(scratch, "/") - path = os.path.join(self.temp_dir, "com.ubuntu.test_1.0_all.click") + path = os.path.join(self.temp_dir, "com.example.test_1.0_all.click") self.assertEqual(path, self.builder.build(self.temp_dir)) self.assertTrue(os.path.exists(path)) for key, value in ( - ("Package", "com.ubuntu.test"), + ("Package", "com.example.test"), ("Version", "1.0"), ("Click-Version", "0.4"), ("Architecture", "all"), @@ -212,7 +212,7 @@ touch(os.path.join(scratch, ".click", "evil-file")) with mkfile(os.path.join(scratch, "manifest.json")) as f: json.dump({ - "name": "com.ubuntu.test", + "name": "com.example.test", "version": "1.0", "maintainer": "Foo Bar ", "title": "test title", @@ -231,7 +231,7 @@ scratch = os.path.join(self.temp_dir, "scratch") with mkfile(os.path.join(scratch, "manifest.json")) as f: json.dump({ - "name": "com.ubuntu.test", + "name": "com.example.test", "version": "1.0", "maintainer": "Foo Bar ", "title": "test title", @@ -239,7 +239,7 @@ "framework": "ubuntu-sdk-13.10", }, f) self.builder.add_file(scratch, "/") - path = os.path.join(self.temp_dir, "com.ubuntu.test_1.0_multi.click") + path = os.path.join(self.temp_dir, "com.example.test_1.0_multi.click") self.assertEqual(path, self.builder.build(self.temp_dir)) self.assertTrue(os.path.exists(path)) self.assertEqual("multi", self.extract_field(path, "Architecture")) @@ -260,7 +260,7 @@ scratch = os.path.join(self.temp_dir, "scratch") with mkfile(os.path.join(scratch, "manifest.json")) as f: json.dump({ - "name": "com.ubuntu.test", + "name": "com.example.test", "version": "1.0", "maintainer": "Foo Bar ", "title": "test title", @@ -322,7 +322,7 @@ touch(os.path.join(scratch, ".git", "config")) with mkfile(os.path.join(scratch, "manifest.json")) as f: json.dump({ - "name": "com.ubuntu.test", + "name": "com.example.test", "version": "1.0", "maintainer": "Foo Bar ", "title": "test title", @@ -332,7 +332,7 @@ # build() overrides this back to 0o644 os.fchmod(f.fileno(), 0o600) self.builder.add_file(scratch, "./") - path = os.path.join(self.temp_dir, "com.ubuntu.test_1.0.tar.gz") + path = os.path.join(self.temp_dir, "com.example.test_1.0.tar.gz") self.assertEqual(path, self.builder.build(self.temp_dir)) self.assertTrue(os.path.exists(path)) with tarfile.open(path, mode="r:gz") as tar: diff -Nru click-0.4.31.3/debian/changelog click-0.4.32.1/debian/changelog --- click-0.4.31.3/debian/changelog 2014-08-25 19:25:22.000000000 +0000 +++ click-0.4.32.1/debian/changelog 2014-09-09 10:02:01.000000000 +0000 @@ -1,3 +1,30 @@ +click (0.4.32.1) utopic; urgency=low + + [ Michael Vogt ] + * fix autopkgtest failure found in 0.4.32 + + -- Ubuntu daily release Tue, 09 Sep 2014 10:02:00 +0000 + +click (0.4.32) utopic; urgency=medium + + [ Daniel Holbach ] + * Run click-review after a successful build of a click package. Offer + --no-validate as an option. + + [ Colin Watson ] + * Move integration tests to a location where they won't end up being + installed into inappropriate places on the system module path + (LP: #1337696). + * Use six.with_metaclass for TestBuildCoreApps, so that it doesn't make + pyflakes angry when running tests under Python 2. + + [ Michael Vogt ] + * Add more integration tests for "click {list,register,verify,info}". + * Only install trusted click packages by default. To override you + can run "pkcon --allow-untrusted" (LP: #1360582) + + -- Ubuntu daily release Mon, 08 Sep 2014 09:50:43 +0000 + click (0.4.31.3) utopic; urgency=medium * Reinstate most of 0.4.31.2; instead, just always pass diff -Nru click-0.4.31.3/debian/control click-0.4.32.1/debian/control --- click-0.4.31.3/debian/control 2014-08-22 17:19:03.000000000 +0000 +++ click-0.4.32.1/debian/control 2014-09-09 10:01:59.000000000 +0000 @@ -3,7 +3,7 @@ Priority: optional Maintainer: Colin Watson Standards-Version: 3.9.5 -Build-Depends: debhelper (>= 9~), dh-autoreconf, intltool, python3:any (>= 3.2), python3-all:any, python3-setuptools, python3-apt, python3-debian, python3-gi, python3:any (>= 3.3) | python3-mock, pep8, python3-pep8, pyflakes, python3-sphinx, pkg-config, valac, gobject-introspection (>= 0.6.7), libgirepository1.0-dev (>= 0.6.7), libglib2.0-dev (>= 2.34), gir1.2-glib-2.0, libjson-glib-dev (>= 0.10), libgee-0.8-dev, libpackagekit-glib2-dev (>= 0.7.2), python3-coverage +Build-Depends: debhelper (>= 9~), dh-autoreconf, intltool, python3:any (>= 3.2), python3-all:any, python3-setuptools, python3-apt, python3-debian, python3-gi, python3:any (>= 3.3) | python3-mock, pep8, python3-pep8, pyflakes, python3-sphinx, pkg-config, valac, gobject-introspection (>= 0.6.7), libgirepository1.0-dev (>= 0.6.7), libglib2.0-dev (>= 2.34), gir1.2-glib-2.0, libjson-glib-dev (>= 0.10), libgee-0.8-dev, libpackagekit-glib2-dev (>= 0.7.2), python3-coverage, python3-six Vcs-Bzr: https://code.launchpad.net/~ubuntu-managed-branches/click/click Vcs-Browser: http://bazaar.launchpad.net/~ubuntu-managed-branches/click/click/files X-Auto-Uploader: no-rewrite-version @@ -16,6 +16,7 @@ Pre-Depends: ${misc:Pre-Depends} Depends: ${shlibs:Depends}, ${misc:Depends}, ${python3:Depends}, python3-click (= ${binary:Version}), adduser Recommends: click-apparmor, ubuntu-app-launch-tools | upstart-app-launch-tools +Suggests: click-reviewers-tools (>= 0.9) Conflicts: click-package Replaces: click-package Provides: click-package diff -Nru click-0.4.31.3/debian/tests/control click-0.4.32.1/debian/tests/control --- click-0.4.31.3/debian/tests/control 2014-08-22 17:18:55.000000000 +0000 +++ click-0.4.32.1/debian/tests/control 2014-09-09 10:00:56.000000000 +0000 @@ -1,3 +1,3 @@ Tests: run-tests.sh -Depends: @, iputils-ping, click-dev, schroot, debootstrap, sudo, bzr, debsigs, debsig-verify +Depends: @, @builddeps@, iputils-ping, click-dev, schroot, debootstrap, sudo, bzr, debsigs, debsig-verify, python3-six Restrictions: needs-root allow-stderr diff -Nru click-0.4.31.3/debian/tests/run-tests.sh click-0.4.32.1/debian/tests/run-tests.sh --- click-0.4.31.3/debian/tests/run-tests.sh 2014-08-22 17:18:22.000000000 +0000 +++ click-0.4.32.1/debian/tests/run-tests.sh 2014-09-09 10:00:56.000000000 +0000 @@ -2,4 +2,11 @@ set -e -python3 -m unittest discover tests.integration +# some files like config.py are generated from config.py.in +./autogen.sh +./configure --prefix=/usr \ + --sysconfdir=/etc \ + --with-systemdsystemunitdir=/lib/systemd/system \ + --with-systemduserunitdir=/usr/lib/systemd/user + +TEST_INTEGRATION=1 python3 -m unittest discover -vv click.tests.integration diff -Nru click-0.4.31.3/doc/manpage.rst click-0.4.32.1/doc/manpage.rst --- click-0.4.31.3/doc/manpage.rst 2014-08-22 17:18:22.000000000 +0000 +++ click-0.4.32.1/doc/manpage.rst 2014-09-09 10:00:56.000000000 +0000 @@ -73,6 +73,8 @@ -m PATH, --manifest=PATH Read package manifest from PATH (default: ``manifest.json``). +--no-validate Don't run checks from click-reviewers-tools on + the resulting .click file. click buildsource DIRECTORY --------------------------- diff -Nru click-0.4.31.3/pk-plugin/pk-plugin-click.c click-0.4.32.1/pk-plugin/pk-plugin-click.c --- click-0.4.31.3/pk-plugin/pk-plugin-click.c 2014-08-25 19:23:40.000000000 +0000 +++ click-0.4.32.1/pk-plugin/pk-plugin-click.c 2014-09-09 10:00:56.000000000 +0000 @@ -519,7 +519,10 @@ i = 0; argv[i++] = g_strdup ("click"); argv[i++] = g_strdup ("install"); - argv[i++] = g_strdup ("--allow-unauthenticated"); + if (!pk_bitfield_contain (pk_transaction_get_transaction_flags (transaction), + PK_TRANSACTION_FLAG_ENUM_ONLY_TRUSTED)) { + argv[i++] = g_strdup ("--allow-unauthenticated"); + } username = click_get_username_for_uid (pk_transaction_get_uid (transaction)); if (username) Binary files /tmp/7smmRgueLl/click-0.4.31.3/tests/integration/data/evil-keyring/pubring.gpg and /tmp/tBwn8h0cNR/click-0.4.32.1/tests/integration/data/evil-keyring/pubring.gpg differ Binary files /tmp/7smmRgueLl/click-0.4.31.3/tests/integration/data/evil-keyring/secring.gpg and /tmp/tBwn8h0cNR/click-0.4.32.1/tests/integration/data/evil-keyring/secring.gpg differ Binary files /tmp/7smmRgueLl/click-0.4.31.3/tests/integration/data/evil-keyring/trustdb.gpg and /tmp/tBwn8h0cNR/click-0.4.32.1/tests/integration/data/evil-keyring/trustdb.gpg differ Binary files /tmp/7smmRgueLl/click-0.4.31.3/tests/integration/data/origin-keyring/pubring.gpg and /tmp/tBwn8h0cNR/click-0.4.32.1/tests/integration/data/origin-keyring/pubring.gpg differ Binary files /tmp/7smmRgueLl/click-0.4.31.3/tests/integration/data/origin-keyring/secring.gpg and /tmp/tBwn8h0cNR/click-0.4.32.1/tests/integration/data/origin-keyring/secring.gpg differ Binary files /tmp/7smmRgueLl/click-0.4.31.3/tests/integration/data/origin-keyring/trustdb.gpg and /tmp/tBwn8h0cNR/click-0.4.32.1/tests/integration/data/origin-keyring/trustdb.gpg differ diff -Nru click-0.4.31.3/tests/integration/helpers.py click-0.4.32.1/tests/integration/helpers.py --- click-0.4.31.3/tests/integration/helpers.py 2014-08-22 17:18:22.000000000 +0000 +++ click-0.4.32.1/tests/integration/helpers.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,95 +0,0 @@ -# Copyright (C) 2014 Canonical Ltd. -# Author: Michael Vogt - -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; version 3 of the License. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -"""Integration tests helper for the click CLI interface.""" - -import contextlib -import glob -import json -import os -import random -import shutil -import string -import subprocess -import tempfile -import unittest - - -def is_root(): - return os.getuid() == 0 - - -def has_network(): - return subprocess.call( - ["ping", "-c1", "archive.ubuntu.com"]) == 0 - - -@contextlib.contextmanager -def chdir(target): - curdir = os.getcwd() - os.chdir(target) - try: - yield - finally: - os.chdir(curdir) - - -class ClickTestCase(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.click_binary = os.environ.get("CLICK_BINARY", "/usr/bin/click") - - def setUp(self): - super(ClickTestCase, self).setUp() - self.temp_dir = tempfile.mkdtemp() - - def tearDown(self): - super(ClickTestCase, self).tearDown() - # we force the cleanup before removing the tempdir so that stuff - # in temp_dir is still available - self.doCleanups() - shutil.rmtree(self.temp_dir) - - def _create_manifest(self, target, name, version, framework, hooks={}): - with open(target, "w") as f: - json.dump({ - 'name': name, - 'version': str(version), - 'maintainer': 'Foo Bar ', - 'title': 'test title', - 'framework': framework, - 'hooks': hooks, - }, f) - - def _make_click(self, name=None, version=1.0, - framework="ubuntu-sdk-13.10", hooks={}): - if name is None: - name = "com.ubuntu.%s" % "".join( - random.choice(string.ascii_lowercase) for i in range(10)) - tmpdir = tempfile.mkdtemp() - self.addCleanup(lambda: shutil.rmtree(tmpdir)) - clickdir = os.path.join(tmpdir, name) - os.makedirs(clickdir) - self._create_manifest(os.path.join(clickdir, "manifest.json"), - name, version, framework, hooks) - with open(os.path.join(clickdir, "README"), "w") as f: - f.write("hello world!") - with chdir(tmpdir), open(os.devnull, "w") as devnull: - subprocess.call( - [self.click_binary, "build", clickdir], stdout=devnull) - generated_clicks = glob.glob(os.path.join(tmpdir, "*.click")) - self.assertEqual(len(generated_clicks), 1) - return generated_clicks[0] diff -Nru click-0.4.31.3/tests/integration/test_build_core_apps.py click-0.4.32.1/tests/integration/test_build_core_apps.py --- click-0.4.31.3/tests/integration/test_build_core_apps.py 2014-08-22 17:18:22.000000000 +0000 +++ click-0.4.32.1/tests/integration/test_build_core_apps.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,119 +0,0 @@ -# Copyright (C) 2014 Canonical Ltd. -# Author: Michael Vogt - -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; version 3 of the License. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -"""Integration tests for the click chroot feature.""" - -from glob import glob -import json -import os -import shutil -import subprocess -import unittest - -from .helpers import ( - chdir, - has_network, - is_root, - ClickTestCase, -) - -# the branches we want to testbuild -TEST_BUILD_BRANCHES = [ - "lp:camera-app", - "lp:notes-app", -] - -# command to "configure" -CORE_APP_CONFIGURE_CMD = [ - "cmake", "..", "-DCLICK_MODE=on", "-DINSTALL_TESTS=off"] - -# command to make install -CLICK_TARGET_DIR = "click-package" -CORE_APP_MAKE_CMD = [ - "make", "DESTDIR=%s" % CLICK_TARGET_DIR, "install"] - - -def find_manifest(start_dir): - """Find a click manifest.json{,.in} under the given directory""" - for path, dirs, files in os.walk(start_dir): - for needle in ["manifest.json", "manifest.json.in"]: - if needle in files: - return os.path.join(path, needle) - return None - - -class AddBranchTestFunctions(type): - """Metaclass that creates one test for each branch""" - def __new__(cls, name, bases, dct): - for branch in TEST_BUILD_BRANCHES: - name = "test_build_%s" % branch.split(":")[1].replace("-", "_") - dct[name] = lambda self: self._testbuild_branch(branch) - return type.__new__(cls, name, bases, dct) - - -@unittest.skipIf(not is_root(), "This tests needs to run as root") -@unittest.skipIf(not has_network(), "Need network") -class TestBuildCoreApps(ClickTestCase, metaclass=AddBranchTestFunctions): - - def _run_in_chroot(self, cmd): - """Run the given cmd in a click chroot""" - return subprocess.check_call(self.chroot_cmd + ["run"] + cmd) - - def _set_arch_and_framework_from_manifest(self, manifest): - with open(manifest) as f: - data = json.load(f) - self.arch = data["architecture"] - self.framework = data["framework"] - - @property - def chroot_cmd(self): - return [ - self.click_binary, "chroot", "-a", self.arch, "-f", self.framework] - - def _ensure_click_chroot(self): - if subprocess.call(self.chroot_cmd + ["exists"]) != 0: - subprocess.check_call(self.chroot_cmd + ["create"]) - - def configure(self): - self._run_in_chroot(CORE_APP_CONFIGURE_CMD) - - def make(self): - self._run_in_chroot(CORE_APP_MAKE_CMD) - - def create_click(self): - subprocess.check_call( - [self.click_binary, "build", CLICK_TARGET_DIR]) - # we expect exactly one click - self.assertEqual(len(glob("*.click")), 1) - - def _testbuild_branch(self, branch): - # get and parse - branch_dir = branch[len("lp:"):] - build_dir = os.path.join(branch_dir, "build-tree") - if os.path.exists(branch_dir): - subprocess.check_call(["bzr", "pull"], cwd=branch_dir) - else: - subprocess.check_call(["bzr", "branch", branch]) - manifest = find_manifest(branch_dir) - # build it - self._set_arch_and_framework_from_manifest(manifest) - if os.path.exists(build_dir): - shutil.rmtree(build_dir) - os.makedirs(build_dir) - with chdir(build_dir): - self._ensure_click_chroot() - self.configure() - self.make() - self.create_click() diff -Nru click-0.4.31.3/tests/integration/test_build.py click-0.4.32.1/tests/integration/test_build.py --- click-0.4.31.3/tests/integration/test_build.py 2014-08-22 17:18:22.000000000 +0000 +++ click-0.4.32.1/tests/integration/test_build.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -# Copyright (C) 2014 Canonical Ltd. -# Author: Michael Vogt - -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; version 3 of the License. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -"""Integration tests for the click CLI build command.""" - -import os - -from .helpers import ClickTestCase - - -class TestBuild(ClickTestCase): - def test_build(self): - path_to_click = self._make_click() - self.assertTrue(os.path.exists(path_to_click)) diff -Nru click-0.4.31.3/tests/integration/test_buildsource.py click-0.4.32.1/tests/integration/test_buildsource.py --- click-0.4.31.3/tests/integration/test_buildsource.py 2014-08-22 17:18:22.000000000 +0000 +++ click-0.4.32.1/tests/integration/test_buildsource.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -# Copyright (C) 2014 Canonical Ltd. -# Author: Michael Vogt - -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; version 3 of the License. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -"""Integration tests for the click CLI buildsource command.""" - -import os -import shutil -import subprocess -import tarfile -import tempfile - -from .helpers import ( - chdir, - ClickTestCase, -) - - -class TestBuildSource(ClickTestCase): - - def test_buildsource(self): - temp_dir = tempfile.mkdtemp() - self.addCleanup(shutil.rmtree, temp_dir) - with chdir(temp_dir): - with open(os.path.join(temp_dir, "README"), "w") as f: - f.write("I'm a source package") - os.mkdir(os.path.join(temp_dir, ".git")) - os.mkdir(os.path.join(temp_dir, ".bzr")) - os.mkdir(os.path.join(temp_dir, ".normal")) - self._create_manifest(os.path.join(temp_dir, "manifest.json"), - "srcfoo", "1.2", "ubuntu-sdk-13.10") - subprocess.check_call( - [self.click_binary, "buildsource", temp_dir], - universal_newlines=True) - # ensure we have the content we expect - source_file = "srcfoo_1.2.tar.gz" - tar = tarfile.open(source_file) - self.assertEqual( - sorted(tar.getnames()), - sorted([".", "./.normal", "./manifest.json", "./README"])) diff -Nru click-0.4.31.3/tests/integration/test_chroot.py click-0.4.32.1/tests/integration/test_chroot.py --- click-0.4.31.3/tests/integration/test_chroot.py 2014-08-22 17:18:22.000000000 +0000 +++ click-0.4.32.1/tests/integration/test_chroot.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,69 +0,0 @@ -# Copyright (C) 2014 Canonical Ltd. -# Author: Michael Vogt - -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; version 3 of the License. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -"""Integration tests for the click chroot feature.""" - -import subprocess -import unittest - -from .helpers import ( - has_network, - is_root, - ClickTestCase, -) - - -@unittest.skipIf(not is_root(), "This tests needs to run as root") -@unittest.skipIf(not has_network(), "Need network") -class TestChroot(ClickTestCase): - - @classmethod - def setUpClass(cls): - super(TestChroot, cls).setUpClass() - cls.arch = subprocess.check_output( - ["dpkg", "--print-architecture"], universal_newlines=True).strip() - subprocess.check_call([ - cls.click_binary, - "chroot", "-a", cls.arch, - "create"]) - - @classmethod - def tearDownClass(cls): - subprocess.check_call([ - cls.click_binary, - "chroot", "-a", cls.arch, - "destroy"]) - - def test_upgrade(self): - subprocess.check_call([ - self.click_binary, "chroot", "-a", self.arch, - "upgrade"]) - - def test_install(self): - subprocess.check_call([ - self.click_binary, "chroot", "-a", self.arch, - "install", "apt-utils"]) - - def test_run(self): - output = subprocess.check_output([ - self.click_binary, "chroot", "-a", self.arch, - "run", "echo", "hello world"], universal_newlines=True) - self.assertEqual(output, "hello world\n") - - def test_maint(self): - output = subprocess.check_output([ - self.click_binary, "chroot", "-a", self.arch, - "maint", "id"], universal_newlines=True) - self.assertEqual(output, "uid=0(root) gid=0(root) groups=0(root)\n") diff -Nru click-0.4.31.3/tests/integration/test_contents.py click-0.4.32.1/tests/integration/test_contents.py --- click-0.4.31.3/tests/integration/test_contents.py 2014-08-22 17:18:22.000000000 +0000 +++ click-0.4.32.1/tests/integration/test_contents.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -# Copyright (C) 2014 Canonical Ltd. -# Author: Michael Vogt - -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; version 3 of the License. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -"""Integration tests for the click CLI contents command.""" - -import re -import subprocess - -from .helpers import ClickTestCase - - -class TestContents(ClickTestCase): - def test_contents(self): - name = "com.ubuntu.contents" - path_to_click = self._make_click(name) - output = subprocess.check_output([ - self.click_binary, "contents", path_to_click], - universal_newlines=True) - self.assertTrue(re.search( - r'-rw-r[-w]-r-- root/root\s+[0-9]+\s+[0-9-]+ [0-9:]+ ./README', - output)) diff -Nru click-0.4.31.3/tests/integration/test_frameworks.py click-0.4.32.1/tests/integration/test_frameworks.py --- click-0.4.31.3/tests/integration/test_frameworks.py 2014-08-22 17:18:22.000000000 +0000 +++ click-0.4.32.1/tests/integration/test_frameworks.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,35 +0,0 @@ -# Copyright (C) 2014 Canonical Ltd. -# Author: Michael Vogt - -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; version 3 of the License. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -"""Integration tests for the click CLI frameworks command.""" - -import os -import subprocess -import unittest - -from .helpers import ( - ClickTestCase, -) - - -@unittest.skipIf( - (not os.path.exists("/usr/share/click/frameworks") or - not os.listdir("/usr/share/click/frameworks")), - "Please install ubuntu-sdk-libs") -class TestFrameworks(ClickTestCase): - def test_framework_list(self): - output = subprocess.check_output([ - self.click_binary, "framework", "list"], universal_newlines=True) - self.assertTrue("ubuntu-sdk-" in output) diff -Nru click-0.4.31.3/tests/integration/test_hook.py click-0.4.32.1/tests/integration/test_hook.py --- click-0.4.31.3/tests/integration/test_hook.py 2014-08-22 17:18:55.000000000 +0000 +++ click-0.4.32.1/tests/integration/test_hook.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,83 +0,0 @@ -# Copyright (C) 2014 Canonical Ltd. -# Author: Michael Vogt - -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; version 3 of the License. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -"""Integration tests for the click hook feature.""" - -import os -import subprocess -from textwrap import dedent -import unittest - -from .helpers import ( - is_root, - ClickTestCase, -) - - -@unittest.skipIf(not is_root(), "This tests needs to run as root") -class TestHook(ClickTestCase): - def _make_hook(self, name): - hook_fname = "/usr/share/click/hooks/%s.hook" % name - canary_fname = os.path.join(self.temp_dir, "canary.sh") - canary_log = os.path.join(self.temp_dir, "canary.log") - with open(hook_fname, "w") as f: - f.write(dedent("""\ - Pattern: ${home}/${id}.test-hook - User-Level: yes - Exec: %s - Hook-Name: %s - """ % (canary_fname, name))) - with open(canary_fname, "w") as f: - f.write(dedent("""\ - #!/bin/sh - echo "i-hook-you-up" >> %s - """ % canary_log)) - os.chmod(canary_fname, 0o755) - return hook_fname, canary_log - - def test_hook_install_user(self): - # build/install the hook - hook_name = "clicktesthook" - hook_file, hook_log = self._make_hook(hook_name) - self.addCleanup(os.unlink, hook_file) - subprocess.check_call( - [self.click_binary, "hook", "install", hook_name]) - self.addCleanup( - subprocess.check_call, [self.click_binary, "hook", "remove", - hook_name]) - # make click that uses the hook - hooks = {'app1': {hook_name: 'README'}} - click_pkg_name = "com.example.hook-1" - click_pkg = self._make_click( - click_pkg_name, framework="", hooks=hooks) - user = os.environ.get("USER", "root") - subprocess.check_call( - [self.click_binary, "install", "--allow-unauthenticated", - "--user=%s" % user, click_pkg], - universal_newlines=True) - self.addCleanup( - subprocess.check_call, - [self.click_binary, "unregister", "--user=%s" % user, - click_pkg_name]) - # ensure we have the hook - generated_hook_file = os.path.expanduser( - "~/com.example.hook-1_app1_1.0.test-hook") - self.assertTrue(os.path.exists(generated_hook_file)) - self.assertEqual( - os.path.realpath(generated_hook_file), - "/opt/click.ubuntu.com/com.example.hook-1/1.0/README") - with open(hook_log) as f: - hook_log_content = f.read().strip() - self.assertEqual("i-hook-you-up", hook_log_content) diff -Nru click-0.4.31.3/tests/integration/test_info.py click-0.4.32.1/tests/integration/test_info.py --- click-0.4.31.3/tests/integration/test_info.py 2014-08-22 17:18:55.000000000 +0000 +++ click-0.4.32.1/tests/integration/test_info.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,46 +0,0 @@ -# Copyright (C) 2014 Canonical Ltd. -# Author: Michael Vogt - -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; version 3 of the License. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -"""Integration tests for the click CLI info command.""" - -import json -import subprocess - -from .helpers import ClickTestCase - - -class TestInfo(ClickTestCase): - def test_info(self): - name = "com.ubuntu.foo" - path_to_click = self._make_click(name) - output = subprocess.check_output([ - self.click_binary, "info", path_to_click], universal_newlines=True) - self.assertEqual(name, json.loads(output)["name"]) - - def test_info_file_in_package(self): - name = "org.example.info" - version = "1.0" - click_pkg = self._make_click(name=name, version=version, framework="") - subprocess.check_call( - [self.click_binary, "install", "--allow-unauthenticated", - "--all-users", click_pkg]) - self.addCleanup( - subprocess.check_call, - [self.click_binary, "unregister", "--all-users", name]) - output = subprocess.check_output( - [self.click_binary, "info", - "/opt/click.ubuntu.com/%s/%s/README" % (name, version)], - universal_newlines=True) - self.assertEqual(name, json.loads(output)["name"]) diff -Nru click-0.4.31.3/tests/integration/test_install.py click-0.4.32.1/tests/integration/test_install.py --- click-0.4.31.3/tests/integration/test_install.py 2014-08-22 17:18:55.000000000 +0000 +++ click-0.4.32.1/tests/integration/test_install.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,116 +0,0 @@ -# Copyright (C) 2014 Canonical Ltd. -# Author: Michael Vogt - -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; version 3 of the License. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -"""Integration tests for the click install feature.""" - -import os -import subprocess -import unittest - -from .helpers import ClickTestCase - - -def add_user(name): - subprocess.check_call(["useradd", name]) - return name - - -def del_user(name): - subprocess.check_call(["userdel", "-r", name]) - - -@unittest.skipIf( - os.getuid() != 0, "This tests needs to run as root") -class TestClickInstall(ClickTestCase): - - @classmethod - def setUpClass(cls): - super(TestClickInstall, cls).setUpClass() - cls.USER_1 = add_user("click-test-user-1") - cls.USER_2 = add_user("click-test-user-2") - - @classmethod - def tearDownClass(cls): - super(TestClickInstall, cls).tearDownClass() - del_user(cls.USER_1) - del_user(cls.USER_2) - - def click_unregister(self, username, click_name): - if username == "@all": - user = "--all-users" - else: - user = "--user=%s" % username - subprocess.check_call( - [self.click_binary, "unregister", user, click_name]) - - def test_install_for_single_user(self): - click_pkg = self._make_click(name="foo-1", framework="") - # install it - subprocess.check_call([ - self.click_binary, "install", "--user=%s" % self.USER_1, - "--allow-unauthenticated", - click_pkg], universal_newlines=True) - self.addCleanup(self.click_unregister, self.USER_1, "foo-1") - # ensure that user-1 has it - output = subprocess.check_output([ - "sudo", "-u", self.USER_1, - self.click_binary, "list"], universal_newlines=True) - self.assertEqual(output, "foo-1\t1.0\n") - # but not user-2 - output = subprocess.check_output([ - "sudo", "-u", self.USER_2, - self.click_binary, "list"], universal_newlines=True) - self.assertEqual(output, "") - # and that we can see it with the --user option - output = subprocess.check_output( - [self.click_binary, "list", "--user=%s" % self.USER_1], - universal_newlines=True) - self.assertEqual(output, "foo-1\t1.0\n") - - def test_install_for_all_users(self): - click_pkg = self._make_click(name="foo-2", framework="") - # install it - subprocess.check_call( - [self.click_binary, "install", "--all-users", - "--allow-unauthenticated", click_pkg], - universal_newlines=True) - self.addCleanup(self.click_unregister, "@all", "foo-2") - # ensure all users see it - for user in (self.USER_1, self.USER_2): - output = subprocess.check_output( - ["sudo", "-u", user, self.click_binary, "list"], - universal_newlines=True) - self.assertEqual(output, "foo-2\t1.0\n") - - def test_pkgdir_after_install(self): - click_pkg = self._make_click(name="foo-2", version="1.2", framework="") - subprocess.check_call( - [self.click_binary, "install", "--all-users", - "--allow-unauthenticated", click_pkg], - universal_newlines=True) - self.addCleanup(self.click_unregister, "@all", "foo-2") - # from the path - output = subprocess.check_output( - [self.click_binary, "pkgdir", - "/opt/click.ubuntu.com/foo-2/1.2/README"], - universal_newlines=True).strip() - self.assertEqual(output, "/opt/click.ubuntu.com/foo-2/1.2") - # now test from the click package name - output = subprocess.check_output( - [self.click_binary, "pkgdir", "foo-2"], - universal_newlines=True).strip() - # note that this is different from above - self.assertEqual( - output, "/opt/click.ubuntu.com/.click/users/@all/foo-2") diff -Nru click-0.4.31.3/tests/integration/test_signatures.py click-0.4.32.1/tests/integration/test_signatures.py --- click-0.4.31.3/tests/integration/test_signatures.py 2014-08-22 17:18:55.000000000 +0000 +++ click-0.4.32.1/tests/integration/test_signatures.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,348 +0,0 @@ -# Copyright (C) 2014 Canonical Ltd. -# Author: Michael Vogt - -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; version 3 of the License. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -"""Integration tests for the click signature checking.""" - -import copy -import os -import shutil -import subprocess -import tarfile -import unittest -from textwrap import dedent - -from .helpers import ( - is_root, - ClickTestCase, -) - -def makedirs(path): - try: - os.makedirs(path) - except OSError: - pass - -def get_keyid_from_gpghome(gpg_home): - """Return the public keyid of a given gpg home dir""" - output = subprocess.check_output( - ["gpg", "--home", gpg_home, "--list-keys", "--with-colons"], - universal_newlines=True) - for line in output.splitlines(): - if not line.startswith("pub:"): - continue - return line.split(":")[4] - raise ValueError("Cannot find public key in output: '%s'" % output) - - -class Debsigs: - """Tiny wrapper around the debsigs CLI""" - def __init__(self, gpghome, keyid): - self.keyid = keyid - self.gpghome = gpghome - self.policy = "/etc/debsig/policies/%s/generic.pol" % self.keyid - - def sign(self, filepath, signature_type="origin"): - """Sign the click at filepath""" - env = copy.copy(os.environ) - env["GNUPGHOME"] = os.path.abspath(self.gpghome) - subprocess.check_call( - ["debsigs", - "--sign=%s" % signature_type, - "--default-key=%s" % self.keyid, - filepath], env=env) - - def install_signature_policy(self): - """Install/update the system-wide signature policy""" - xmls = dedent("""\ - - - - - - - - - - - - - - """.format(keyid=self.keyid, filename="origin.pub")) - makedirs(os.path.dirname(self.policy)) - with open(self.policy, "w") as f: - f.write(xmls) - self.pubkey_path = ( - "/usr/share/debsig/keyrings/%s/origin.pub" % self.keyid) - makedirs(os.path.dirname(self.pubkey_path)) - shutil.copy(os.path.join(self.gpghome, "pubring.gpg"), self.pubkey_path) - - def uninstall_signature_policy(self): - # FIXME: update debsig-verify so that it can work from a different - # root than "/" so that the tests do not have to use the - # system root - os.remove(self.policy) - os.remove(self.pubkey_path) - - -@unittest.skipIf(not is_root(), "This tests needs to run as root") -class ClickSignaturesTestCase(ClickTestCase): - def assertClickNoSignatureError(self, cmd_args): - with self.assertRaises(subprocess.CalledProcessError) as cm: - output = subprocess.check_output( - [self.click_binary] + cmd_args, - stderr=subprocess.STDOUT, universal_newlines=True) - output = cm.exception.output - expected_error_message = ("debsig: Origin Signature check failed. " - "This deb might not be signed.") - self.assertIn(expected_error_message, output) - - def assertClickInvalidSignatureError(self, cmd_args): - with self.assertRaises(subprocess.CalledProcessError) as cm: - output = subprocess.check_output( - [self.click_binary] + cmd_args, - stderr=subprocess.STDOUT, universal_newlines=True) - print(output) - - output = cm.exception.output - expected_error_message = "Signature verification error: " - self.assertIn(expected_error_message, output) - - -@unittest.skipIf(not is_root(), "This tests needs to run as root") -class TestSignatureVerificationNoSignature(ClickSignaturesTestCase): - def test_debsig_verify_no_sig(self): - name = "org.example.debsig-no-sig" - path_to_click = self._make_click(name, framework="") - self.assertClickNoSignatureError(["verify", path_to_click]) - - def test_debsig_install_no_sig(self): - name = "org.example.debsig-no-sig" - path_to_click = self._make_click(name, framework="") - self.assertClickNoSignatureError(["install", path_to_click]) - - def test_debsig_install_can_install_with_sig_override(self): - name = "org.example.debsig-no-sig" - path_to_click = self._make_click(name, framework="") - user = os.environ.get("USER", "root") - subprocess.check_call( - [self.click_binary, "install", - "--allow-unauthenticated", "--user=%s" % user, - path_to_click]) - self.addCleanup( - subprocess.call, [self.click_binary, "unregister", - "--user=%s" % user, name]) - - -@unittest.skipIf(not is_root(), "This tests needs to run as root") -class TestSignatureVerification(ClickSignaturesTestCase): - def setUp(self): - super(TestSignatureVerification, self).setUp() - self.user = os.environ.get("USER", "root") - # the valid origin keyring - self.datadir = os.path.join(os.path.dirname(__file__), "data") - origin_keyring_dir = os.path.abspath( - os.path.join(self.datadir, "origin-keyring")) - keyid = get_keyid_from_gpghome(origin_keyring_dir) - self.debsigs = Debsigs(origin_keyring_dir, keyid) - self.debsigs.install_signature_policy() - - def tearDown(self): - self.debsigs.uninstall_signature_policy() - - def test_debsig_install_valid_signature(self): - name = "org.example.debsig-valid-sig" - path_to_click = self._make_click(name, framework="") - self.debsigs.sign(path_to_click) - subprocess.check_call( - [self.click_binary, "install", - "--user=%s" % self.user, - path_to_click]) - self.addCleanup( - subprocess.call, [self.click_binary, "unregister", - "--user=%s" % self.user, name]) - output = subprocess.check_output( - [self.click_binary, "list", "--user=%s" % self.user], - universal_newlines=True) - self.assertIn(name, output) - - def test_debsig_install_signature_not_in_keyring(self): - name = "org.example.debsig-no-keyring-sig" - path_to_click = self._make_click(name, framework="") - evil_keyring_dir = os.path.join(self.datadir, "evil-keyring") - keyid = get_keyid_from_gpghome(evil_keyring_dir) - debsig_bad = Debsigs(evil_keyring_dir, keyid) - debsig_bad.sign(path_to_click) - # and ensure its really not there - self.assertClickInvalidSignatureError(["install", path_to_click]) - output = subprocess.check_output( - [self.click_binary, "list", "--user=%s" % self.user], - universal_newlines=True) - self.assertNotIn(name, output) - - def test_debsig_install_not_a_signature(self): - name = "org.example.debsig-invalid-sig" - path_to_click = self._make_click(name, framework="") - invalid_sig = os.path.join(self.temp_dir, "_gpgorigin") - with open(invalid_sig, "w") as f: - f.write("no-valid-signature") - # add a invalid sig - subprocess.check_call(["ar", "-r", path_to_click, invalid_sig]) - self.assertClickInvalidSignatureError(["install", path_to_click]) - output = subprocess.check_output( - [self.click_binary, "list", "--user=%s" % self.user], - universal_newlines=True) - self.assertNotIn(name, output) - - def test_debsig_install_signature_altered_click(self): - def modify_ar_member(member): - subprocess.check_call( - ["ar", "-x", path_to_click, "control.tar.gz"], - cwd=self.temp_dir) - altered_member = os.path.join(self.temp_dir, member) - with open(altered_member, "ba") as f: - f.write(b"\0") - subprocess.check_call(["ar", "-r", path_to_click, altered_member]) - - # ensure that all members we care about are checked by debsig-verify - for member in ["control.tar.gz", "data.tar.gz", "debian-binary"]: - name = "org.example.debsig-altered-click" - path_to_click = self._make_click(name, framework="") - self.debsigs.sign(path_to_click) - modify_ar_member(member) - self.assertClickInvalidSignatureError(["install", path_to_click]) - output = subprocess.check_output( - [self.click_binary, "list", "--user=%s" % self.user], - universal_newlines=True) - self.assertNotIn(name, output) - - def make_nasty_data_tar(self, compression): - new_data_tar = os.path.join(self.temp_dir, "data.tar." + compression) - evilfile = os.path.join(self.temp_dir, "README.evil") - with open(evilfile, "w") as f: - f.write("I am a nasty README") - with tarfile.open(new_data_tar, "w:"+compression) as tar: - tar.add(evilfile) - return new_data_tar - - def test_debsig_install_signature_injected_data_tar(self): - name = "org.example.debsig-injected-data-click" - path_to_click = self._make_click(name, framework="") - self.debsigs.sign(path_to_click) - new_data = self.make_nasty_data_tar("bz2") - # insert before the real data.tar.gz and ensure this is caught - # NOTE: that right now this will not be caught by debsig-verify - # but later in audit() by debian.debfile.DebFile() - subprocess.check_call(["ar", - "-r", - "-b", "data.tar.gz", - path_to_click, - new_data]) - output = subprocess.check_output( - ["ar", "-t", path_to_click], universal_newlines=True) - self.assertEqual(output.splitlines(), - ["debian-binary", - "_click-binary", - "control.tar.gz", - "data.tar.bz2", - "data.tar.gz", - "_gpgorigin"]) - with self.assertRaises(subprocess.CalledProcessError): - output = subprocess.check_output( - [self.click_binary, "install", path_to_click], - stderr=subprocess.STDOUT, universal_newlines=True) - output = subprocess.check_output( - [self.click_binary, "list", "--user=%s" % self.user], - universal_newlines=True) - self.assertNotIn(name, output) - - def test_debsig_install_signature_replaced_data_tar(self): - name = "org.example.debsig-replaced-data-click" - path_to_click = self._make_click(name, framework="") - self.debsigs.sign(path_to_click) - new_data = self.make_nasty_data_tar("bz2") - # replace data.tar.gz with data.tar.bz2 and ensure this is caught - subprocess.check_call(["ar", - "-d", - path_to_click, - "data.tar.gz", - ]) - subprocess.check_call(["ar", - "-r", - path_to_click, - new_data]) - output = subprocess.check_output( - ["ar", "-t", path_to_click], universal_newlines=True) - self.assertEqual(output.splitlines(), - ["debian-binary", - "_click-binary", - "control.tar.gz", - "_gpgorigin", - "data.tar.bz2", - ]) - with self.assertRaises(subprocess.CalledProcessError) as cm: - output = subprocess.check_output( - [self.click_binary, "install", path_to_click], - stderr=subprocess.STDOUT, universal_newlines=True) - self.assertIn("Signature verification error", cm.exception.output) - output = subprocess.check_output( - [self.click_binary, "list", "--user=%s" % self.user], - universal_newlines=True) - self.assertNotIn(name, output) - - def test_debsig_install_signature_prepend_sig(self): - # this test is probably not really needed, it tries to trick - # the system by prepending a valid signature that is not - # in the keyring. But given that debsig-verify only reads - # the first packet of any given _gpg$foo signature its - # equivalent to test_debsig_install_signature_not_in_keyring test - name = "org.example.debsig-replaced-data-prepend-sig-click" - path_to_click = self._make_click(name, framework="") - self.debsigs.sign(path_to_click) - new_data = self.make_nasty_data_tar("gz") - # replace data.tar.gz - subprocess.check_call(["ar", - "-r", - path_to_click, - new_data, - ]) - # get previous good _gpgorigin for the old data - subprocess.check_call( - ["ar", "-x", path_to_click, "_gpgorigin"], cwd=self.temp_dir) - with open(os.path.join(self.temp_dir, "_gpgorigin"), "br") as f: - good_gpg_origin = f.read() - # and append a valid signature from a non-keyring key - evil_keyring_dir = os.path.join(self.datadir, "evil-keyring") - debsig_bad = Debsigs(evil_keyring_dir, "18B38B9AC1B67A0D") - debsig_bad.sign(path_to_click) - subprocess.check_call( - ["ar", "-x", path_to_click, "_gpgorigin"], cwd=self.temp_dir) - with open(os.path.join(self.temp_dir, "_gpgorigin"), "br") as f: - evil_gpg_origin = f.read() - with open(os.path.join(self.temp_dir, "_gpgorigin"), "wb") as f: - f.write(evil_gpg_origin) - f.write(good_gpg_origin) - subprocess.check_call( - ["ar", "-r", path_to_click, "_gpgorigin"], cwd=self.temp_dir) - # now ensure that the verification fails as well - with self.assertRaises(subprocess.CalledProcessError) as cm: - output = subprocess.check_output( - [self.click_binary, "install", path_to_click], - stderr=subprocess.STDOUT, universal_newlines=True) - self.assertIn("Signature verification error", cm.exception.output) - output = subprocess.check_output( - [self.click_binary, "list", "--user=%s" % self.user], - universal_newlines=True) - self.assertNotIn(name, output) - diff -Nru click-0.4.31.3/tests/integration/test_verify.py click-0.4.32.1/tests/integration/test_verify.py --- click-0.4.31.3/tests/integration/test_verify.py 2014-08-22 17:18:55.000000000 +0000 +++ click-0.4.32.1/tests/integration/test_verify.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -# Copyright (C) 2014 Canonical Ltd. -# Author: Michael Vogt - -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; version 3 of the License. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -"""Integration tests for the click CLI verify command.""" - -import subprocess - -from .helpers import ClickTestCase - - -class TestVerify(ClickTestCase): - def test_verify_ok(self): - name = "com.example.verify-ok" - path_to_click = self._make_click(name) - output = subprocess.check_output([ - self.click_binary, "verify", - "--force-missing-framework", - "--allow-unauthenticated", - path_to_click], universal_newlines=True) - self.assertEqual(output, "")