~kyrofa/click/xenial-package-rename

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# Copyright (C) 2014 Canonical Ltd.
# Author: Michael Vogt <michael.vogt@ubuntu.com>

# 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 <http://www.gnu.org/licenses/>.

"""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"]

# architectures with native- or cross-compiling support for armhf
ALLOW_ARCHITECTURES = ["amd64", "arm64", "armhf", "i386"]


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):
        system_arch = subprocess.check_output(
            ["dpkg", "--print-architecture"], universal_newlines=True).strip()
        if system_arch not in ALLOW_ARCHITECTURES:
            self.skipTest("%s has no armhf build support" % system_arch)
        # 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()