def test_pack_initrd_modules(self): self.options.kernel_initrd_modules = ["squashfs", "vfat"] plugin = kernel.KernelPlugin("test-part", self.options, self.project) # Fake some assets plugin.kernel_release = "4.4" modules_path = os.path.join(plugin.installdir, "lib", "modules", "4.4") initrd_modules_staging_path = os.path.join("staging", "lib", "modules", "4.4") os.makedirs(modules_path) open(os.path.join(modules_path, "modules.dep"), "w").close() open(os.path.join(modules_path, "modules.dep.bin"), "w").close() os.makedirs(initrd_modules_staging_path) open(os.path.join(plugin.installdir, "initrd-4.4.img"), "w").close() with mock.patch.object(plugin, "_unpack_generic_initrd") as m_unpack: m_unpack.return_value = "staging" plugin._make_initrd() modprobe_cmd = [ "modprobe", "-n", "--show-depends", "-d", plugin.installdir, "-S", "4.4", ] self.run_output_mock.assert_has_calls( [mock.call(modprobe_cmd + ["squashfs"], env=mock.ANY)] ) self.run_output_mock.assert_has_calls( [mock.call(modprobe_cmd + ["vfat"], env=mock.ANY)] )
def test_build_with_missing_kernel_fails(self): self.options.kconfigfile = "config" with open(self.options.kconfigfile, "w") as f: f.write("ACCEPT=y\n") plugin = kernel.KernelPlugin("test-part", self.options, self.project) self._simulate_build( plugin.sourcedir, plugin.builddir, plugin.installdir, do_kernel=False ) raised = self.assertRaises(ValueError, plugin.build) self.assertThat( str(raised), Equals( "kernel build did not output a vmlinux binary in top level " "dir, expected {!r}".format( os.path.join( plugin.builddir, "arch", self.project.kernel_arch, "boot", "bzImage", ) ) ), )
def test_build_with_defconfig_and_kconfigs(self): self.options.kdefconfig = ["defconfig"] self.options.kconfigs = ["SOMETHING=y", "ACCEPT=n"] plugin = kernel.KernelPlugin("test-part", self.options, self.project) config_file = os.path.join(plugin.builddir, ".config") def fake_defconfig(*args, **kwargs): if os.path.exists(config_file): return with open(config_file, "w") as f: f.write("ACCEPT=y\n") self.run_mock.side_effect = fake_defconfig self._simulate_build(plugin.sourcedir, plugin.builddir, plugin.installdir) plugin.build() self._assert_generic_check_call( plugin.builddir, plugin.installdir, plugin.os_snap ) self.assertThat(self.run_mock.call_count, Equals(3)) self.run_mock.assert_has_calls( [ mock.call(["make", "-j1", "defconfig"]), mock.call(["make", "-j2", "bzImage", "modules"]), mock.call( [ "make", "-j2", "CONFIG_PREFIX={}".format(plugin.installdir), "modules_install", "INSTALL_MOD_PATH={}".format(plugin.installdir), "firmware_install", "INSTALL_FW_PATH={}".format( os.path.join(plugin.installdir, "lib", "firmware") ), ] ), ] ) self.assertTrue(os.path.exists(config_file)) with open(config_file) as f: config_contents = f.read() expected_config = """SOMETHING=y ACCEPT=n ACCEPT=y SOMETHING=y ACCEPT=n """ self.assertThat(config_contents, Equals(expected_config)) self._assert_common_assets(plugin.installdir)
def test_build_with_kconfigfile_and_firmware(self): self.options.kconfigfile = "config" with open(self.options.kconfigfile, "w") as f: f.write("ACCEPT=y\n") self.options.kernel_initrd_firmware = [ "lib/firmware/fake-fw-dir", "lib/firmware/fake-fw.bin", ] plugin = kernel.KernelPlugin("test-part", self.options, self.project) self._simulate_build(plugin.sourcedir, plugin.builddir, plugin.installdir) def fake_unpack(*args, **kwargs): modules_dir = os.path.join( plugin.builddir, "initrd-staging", "lib", "modules", "4.4.2" ) if os.path.exists(modules_dir): return os.makedirs(modules_dir) self.check_call_mock.side_effect = fake_unpack plugin.build() self._assert_generic_check_call( plugin.builddir, plugin.installdir, plugin.os_snap ) self.assertThat(self.run_mock.call_count, Equals(2)) self.run_mock.assert_has_calls( [ mock.call(["make", "-j2", "bzImage", "modules"]), mock.call( [ "make", "-j2", "CONFIG_PREFIX={}".format(plugin.installdir), "modules_install", "INSTALL_MOD_PATH={}".format(plugin.installdir), "firmware_install", "INSTALL_FW_PATH={}".format( os.path.join(plugin.installdir, "lib", "firmware") ), ] ), ] ) config_file = os.path.join(plugin.builddir, ".config") self.assertTrue(os.path.exists(config_file)) with open(config_file) as f: config_contents = f.read() self.assertThat(config_contents, Equals("ACCEPT=y\n")) self._assert_common_assets(plugin.installdir) self.assertTrue( os.path.exists(os.path.join(plugin.installdir, "firmware", "fake-fw-dir")) )
def test_kernel_image_target_non_existent(self): class Options: build_parameters = [] kconfigfile = None kdefconfig = [] kconfigs = [] kernel_with_firmware = True kernel_initrd_modules = [] kernel_initrd_firmware = [] kernel_device_trees = [] kernel_initrd_compression = "gz" project = snapcraft.project.Project( target_deb_arch="arm64", snapcraft_yaml_file_path=self.make_snapcraft_yaml( textwrap.dedent( """\ name: test-snap base: core16 """ ) ), ) plugin = kernel.KernelPlugin("test-part", self.options, project) self.assertThat(plugin.make_targets, Equals(["bzImage", "modules", "dtbs"]))
def test_build_with_kconfigfile_and_no_firmware(self): self.options.kconfigfile = "config" with open(self.options.kconfigfile, "w") as f: f.write("ACCEPT=y\n") self.options.kernel_with_firmware = False plugin = kernel.KernelPlugin("test-part", self.options, self.project) self._simulate_build( plugin.sourcedir, plugin.builddir, plugin.installdir, do_dtbs=True, do_firmware=False, ) plugin.build() self._assert_generic_check_call(plugin.builddir, plugin.installdir, plugin.os_snap) self.assertThat(self.run_mock.call_count, Equals(2)) self.run_mock.assert_has_calls([ mock.call(["make", "-j2", "bzImage", "modules"]), mock.call([ "make", "-j2", "CONFIG_PREFIX={}".format(plugin.installdir), "modules_install", "INSTALL_MOD_PATH={}".format(plugin.installdir), ]), ]) config_file = os.path.join(plugin.builddir, ".config") self.assertTrue(os.path.exists(config_file))
def test_override_cross_compile_empty(self): project = snapcraft.project.Project( target_deb_arch="arm64", snapcraft_yaml_file_path=self.make_snapcraft_yaml( textwrap.dedent( """\ name: test-snap base: core16 """ ) ), ) plugin = kernel.KernelPlugin("test-part", self.options, project) self.useFixture(fixtures.EnvironmentVariable("CROSS_COMPILE", "")) plugin.enable_cross_compilation() self.assertThat( plugin.make_cmd, Equals( [ "make", "-j2", "ARCH=arm64", "CROSS_COMPILE=aarch64-linux-gnu-", "PATH={}:/usr/{}/bin".format( os.environ.copy().get("PATH", ""), "aarch64-linux-gnu" ), ] ), )
def test_kernel_image_target_as_string(self): self.options.kernel_image_target = "Image" project = snapcraft.project.Project(target_deb_arch="arm64") project._snap_meta = meta.snap.Snap(name="test-snap", base="core18") plugin = kernel.KernelPlugin("test-part", self.options, project) self.assertThat(plugin.make_targets, Equals(["Image", "modules", "dtbs"]))
def test_unpack_unsupported_initrd_type(self): def check_call_effect(*args, **kwargs): if "unsquashfs" not in args[0]: raise subprocess.CalledProcessError(1, args) self.check_call_mock.side_effect = check_call_effect plugin = kernel.KernelPlugin("test-part", self.options, self.project) self.assertRaises(RuntimeError, plugin._unpack_generic_initrd)
def test_pull(self, download_mock): plugin = kernel.KernelPlugin("test-part", self.options, self.project) plugin.pull() download_mock.assert_called_once_with( "core", risk="stable", track=None, download_path=plugin.os_snap, arch=self.project.deb_arch, except_hash="", )
def test_unpack_lzma_initrd(self): plugin = kernel.KernelPlugin("test-part", self.options, self.project) plugin._unpack_generic_initrd() self.check_call_mock.assert_has_calls([ mock.call( "cat temporary-directory/squashfs-root/boot/" "initrd.img-core | xz -dc | cpio -i", cwd=os.path.join(plugin.builddir, "initrd-staging"), shell=True, ) ])
def test_build_with_kconfigfile_and_dtbs(self): self.options.kconfigfile = "config" with open(self.options.kconfigfile, "w") as f: f.write("ACCEPT=y\n") self.options.kernel_device_trees = ["fake-dtb"] plugin = kernel.KernelPlugin("test-part", self.options, self.project) self._simulate_build( plugin.sourcedir, plugin.builddir, plugin.installdir, do_dtbs=True ) plugin.build() self._assert_generic_check_call( plugin.builddir, plugin.installdir, plugin.os_snap ) self.assertThat(self.run_mock.call_count, Equals(2)) self.run_mock.assert_has_calls( [ mock.call(["make", "-j2", "bzImage", "modules", "fake-dtb.dtb"]), mock.call( [ "make", "-j2", "CONFIG_PREFIX={}".format(plugin.installdir), "modules_install", "INSTALL_MOD_PATH={}".format(plugin.installdir), "firmware_install", "INSTALL_FW_PATH={}".format( os.path.join(plugin.installdir, "lib", "firmware") ), ] ), ] ) config_file = os.path.join(plugin.builddir, ".config") self.assertTrue(os.path.exists(config_file)) with open(config_file) as f: config_contents = f.read() self.assertThat(config_contents, Equals("ACCEPT=y\n")) self._assert_common_assets(plugin.installdir) self.assertTrue( os.path.exists(os.path.join(plugin.installdir, "dtbs", "fake-dtb.dtb")) )
def test_default(self): project = snapcraft.project.Project( target_deb_arch=self.deb_arch, snapcraft_yaml_file_path=self.make_snapcraft_yaml( textwrap.dedent( """\ name: test-snap base: core16 """ ) ), ) plugin = kernel.KernelPlugin("test-part", self.options, project) self.assertThat(plugin.kernel_image_target, Equals(self.expected))
def test_build_with_kconfigfile_and_dtbs_not_found(self): self.options.kconfigfile = "config" with open(self.options.kconfigfile, "w") as f: f.write("ACCEPT=y\n") self.options.kernel_device_trees = ["fake-dtb"] plugin = kernel.KernelPlugin("test-part", self.options, self.project) self._simulate_build(plugin.sourcedir, plugin.builddir, plugin.installdir) raised = self.assertRaises(RuntimeError, plugin.build) self.assertThat( str(raised), Equals("No match for dtb 'fake-dtb.dtb' was found") )
def test_kernel_image_target_as_string(self): self.options.kernel_image_target = "Image" project = snapcraft.project.Project( target_deb_arch="arm64", snapcraft_yaml_file_path=self.make_snapcraft_yaml( textwrap.dedent( """\ name: test-snap base: core16 """ ) ), ) plugin = kernel.KernelPlugin("test-part", self.options, project) self.assertThat(plugin.make_targets, Equals(["Image", "modules", "dtbs"]))
def test_build_with_missing_system_map_fails(self): self.options.kconfigfile = "config" with open(self.options.kconfigfile, "w") as f: f.write("ACCEPT=y\n") plugin = kernel.KernelPlugin("test-part", self.options, self.project) self._simulate_build( plugin.sourcedir, plugin.builddir, plugin.installdir, do_system_map=False ) raised = self.assertRaises(ValueError, plugin.build) self.assertThat( str(raised), Equals("kernel build did not output a System.map in top level dir"), )
def test_check_initrd(self): fake_logger = fixtures.FakeLogger(level=logging.WARNING) self.useFixture(fake_logger) self.options.kconfigfile = "config" self.options.kernel_initrd_modules = ["my-fake-module"] with open(self.options.kconfigfile, "w") as f: f.write("ACCEPT=y\n") plugin = kernel.KernelPlugin("test-part", self.options, self.project) self._simulate_build(plugin.sourcedir, plugin.builddir, plugin.installdir) builtin, modules = plugin._do_parse_config(self.options.kconfigfile) plugin._do_check_initrd(builtin, modules) for module in kernel.required_boot: self.assertIn("CONFIG_{}".format(module.upper()), fake_logger.output)
def test_enable_cross_compilation(self): project = snapcraft.project.Project(target_deb_arch="arm64") project._snap_meta = meta.snap.Snap(name="test-snap", base="core18") plugin = kernel.KernelPlugin("test-part", self.options, project) plugin.enable_cross_compilation() self.assertThat( plugin.make_cmd, Equals([ "make", "-j2", "ARCH=arm64", "CROSS_COMPILE=aarch64-linux-gnu-", "PATH={}:/usr/{}/bin".format(os.environ.copy().get("PATH", ""), "aarch64-linux-gnu"), ]), )
def test_unpack_gzip_initrd(self): def check_call_effect(*args, **kwargs): if "xz" in args[0]: raise subprocess.CalledProcessError(1, args) self.check_call_mock.side_effect = check_call_effect plugin = kernel.KernelPlugin("test-part", self.options, self.project) plugin._unpack_generic_initrd() self.check_call_mock.assert_has_calls([ mock.call( "cat temporary-directory/squashfs-root/boot/" "initrd.img-core | gzip -dc | cpio -i", cwd=os.path.join(plugin.builddir, "initrd-staging"), shell=True, ) ])
def test_kernel_image_target_non_existent(self): class Options: build_parameters = [] kconfigfile = None kdefconfig = [] kconfigs = [] kernel_with_firmware = True kernel_initrd_modules = [] kernel_initrd_firmware = [] kernel_device_trees = [] kernel_initrd_compression = "gz" project = snapcraft.project.Project(target_deb_arch="arm64") project._snap_meta = meta.snap.Snap(name="test-snap", base="core18") plugin = kernel.KernelPlugin("test-part", self.options, project) self.assertThat(plugin.make_targets, Equals(["bzImage", "modules", "dtbs"]))
def test_target(deb_arch, expected_target): class Options: build_parameters = [] kconfigfile = None kdefconfig = [] kconfigs = [] kernel_image_target = "" kernel_with_firmware = True kernel_initrd_modules = [] kernel_initrd_firmware = [] kernel_device_trees = [] kernel_initrd_compression = "gz" project = snapcraft.project.Project(target_deb_arch=deb_arch) project._snap_meta = meta.snap.Snap(name="test-snap", base="core18") plugin = kernel.KernelPlugin("test-part", Options(), project) assert plugin.kernel_image_target == expected_target
def test_check_config(self): fake_logger = fixtures.FakeLogger(level=logging.WARNING) self.useFixture(fake_logger) self.options.kconfigfile = "config" with open(self.options.kconfigfile, "w") as f: f.write("ACCEPT=y\n") plugin = kernel.KernelPlugin("test-part", self.options, self.project) self._simulate_build(plugin.sourcedir, plugin.builddir, plugin.installdir) builtin, modules = plugin._do_parse_config(self.options.kconfigfile) plugin._do_check_config(builtin, modules) required_opts = (kernel.required_generic + kernel.required_security + kernel.required_snappy + kernel.required_systemd) for warn in required_opts: self.assertIn("CONFIG_{}".format(warn), fake_logger.output)
def test_build_with_missing_kernel_release_fails(self): self.options.kconfigfile = "config" with open(self.options.kconfigfile, "w") as f: f.write("ACCEPT=y\n") plugin = kernel.KernelPlugin("test-part", self.options, self.project) self._simulate_build(plugin.sourcedir, plugin.builddir, plugin.installdir, do_release=False) raised = self.assertRaises(ValueError, plugin.build) self.assertThat( str(raised), Equals("No kernel release version info found at {!r}".format( os.path.join(plugin.builddir, "include", "config", "kernel.release"))), )
def test_build_with_kconfigflavour(self): arch = self.project.deb_arch branch = "master" flavour = "vanilla" self.options.kconfigflavour = flavour plugin = kernel.KernelPlugin("test-part", self.options, self.project) self._simulate_build(plugin.sourcedir, plugin.builddir, plugin.installdir) debiandir = os.path.join(plugin.sourcedir, "debian") os.mkdir(debiandir) with open(os.path.join(debiandir, "debian.env"), "w") as f: f.write("DEBIAN=debian.{}".format(branch)) os.mkdir(os.path.join(plugin.sourcedir, "debian.{}".format(branch))) basedir = os.path.join(plugin.sourcedir, "debian.{}".format(branch), "config") archdir = os.path.join( plugin.sourcedir, "debian.{}".format(branch), "config", arch ) os.mkdir(basedir) os.mkdir(archdir) commoncfg = os.path.join(basedir, "config.common.ports") ubuntucfg = os.path.join(basedir, "config.common.ubuntu") archcfg = os.path.join(archdir, "config.common.{}".format(arch)) flavourcfg = os.path.join(archdir, "config.flavour.{}".format(flavour)) with open(commoncfg, "w") as f: f.write("ACCEPT=y\n") with open(ubuntucfg, "w") as f: f.write("ACCEPT=m\n") with open(archcfg, "w") as f: f.write("ACCEPT=y\n") with open(flavourcfg, "w") as f: f.write("# ACCEPT is not set\n") plugin.build() self._assert_generic_check_call( plugin.builddir, plugin.installdir, plugin.os_snap ) self.assertThat(self.run_mock.call_count, Equals(2)) self.run_mock.assert_has_calls( [ mock.call(["make", "-j2", "bzImage", "modules"]), mock.call( [ "make", "-j2", "CONFIG_PREFIX={}".format(plugin.installdir), "modules_install", "INSTALL_MOD_PATH={}".format(plugin.installdir), "firmware_install", "INSTALL_FW_PATH={}".format( os.path.join(plugin.installdir, "lib", "firmware") ), ] ), ] ) config_file = os.path.join(plugin.builddir, ".config") self.assertTrue(os.path.exists(config_file)) self.assertThat( config_file, FileContains( dedent( """\ ACCEPT=y ACCEPT=m ACCEPT=y # ACCEPT is not set """ ) ), ) self._assert_common_assets(plugin.installdir)
def test_build_with_kconfigfile_and_modules(self): self.options.kconfigfile = "config" with open(self.options.kconfigfile, "w") as f: f.write("ACCEPT=y\n") self.options.kernel_initrd_modules = ["my-fake-module"] plugin = kernel.KernelPlugin("test-part", self.options, self.project) self._simulate_build(plugin.sourcedir, plugin.builddir, plugin.installdir) def fake_unpack(*args, **kwargs): modules_dir = os.path.join( plugin.builddir, "initrd-staging", "lib", "modules", "4.4.2" ) if os.path.exists(modules_dir): return os.makedirs(modules_dir) self.check_call_mock.side_effect = fake_unpack def fake_output(*args, **kwargs): if args[0][:3] == ["modprobe", "-n", "--show-depends"]: module_path = os.path.join( plugin.installdir, "lib", "modules", "4.4.2", "some-module.ko" ) open(module_path, "w").close() return "insmod {} enable_fbdev=1\n".format(module_path) else: raise Exception(args[0]) self.run_output_mock.side_effect = fake_output # Set a path that doesn't contain '/sbin' so we can verify that it's # added to the modprobe call. self.useFixture(fixtures.EnvironmentVariable("PATH", "/usr/bin")) plugin.build() self._assert_generic_check_call( plugin.builddir, plugin.installdir, plugin.os_snap ) self.assertThat(self.run_mock.call_count, Equals(2)) self.run_mock.assert_has_calls( [ mock.call(["make", "-j2", "bzImage", "modules"]), mock.call( [ "make", "-j2", "CONFIG_PREFIX={}".format(plugin.installdir), "modules_install", "INSTALL_MOD_PATH={}".format(plugin.installdir), "firmware_install", "INSTALL_FW_PATH={}".format( os.path.join(plugin.installdir, "lib", "firmware") ), ] ), ] ) class _check_env: def __init__(self, test): self.test = test def __eq__(self, other): self.test.assertThat(other, Contains("PATH")) paths = other["PATH"].split(":") self.test.assertThat(paths, Contains("/sbin")) return True self.assertThat(self.run_output_mock.call_count, Equals(1)) self.run_output_mock.assert_has_calls( [ mock.call( [ "modprobe", "-n", "--show-depends", "-d", plugin.installdir, "-S", "4.4.2", "my-fake-module", ], env=_check_env(self), ) ] ) config_file = os.path.join(plugin.builddir, ".config") self.assertTrue(os.path.exists(config_file)) with open(config_file) as f: config_contents = f.read() self.assertThat(config_contents, Equals("ACCEPT=y\n")) self._assert_common_assets(plugin.installdir)
def test_build_verbose_with_kconfigfile(self): fake_logger = fixtures.FakeLogger(level=logging.DEBUG) self.useFixture(fake_logger) self.options.kconfigfile = "config" with open(self.options.kconfigfile, "w") as f: f.write("ACCEPT=y\n") plugin = kernel.KernelPlugin("test-part", self.options, self.project) self._simulate_build(plugin.sourcedir, plugin.builddir, plugin.installdir) plugin.build() self.assertThat(self.check_call_mock.call_count, Equals(4)) self.check_call_mock.assert_has_calls( [ mock.call( 'yes "" | make -j2 V=1 oldconfig', shell=True, cwd=plugin.builddir ), mock.call( ["unsquashfs", plugin.os_snap, "boot"], cwd="temporary-directory" ), mock.call( "cat temporary-directory/squashfs-root/boot/" "initrd.img-core | xz -dc | cpio -i", cwd=os.path.join(plugin.builddir, "initrd-staging"), shell=True, ), mock.call( "find . | cpio --create --format=newc | " "gzip > {}".format( os.path.join(plugin.installdir, "initrd-4.4.2.img") ), cwd=os.path.join(plugin.builddir, "initrd-staging"), shell=True, ), ] ) self.assertThat(self.run_mock.call_count, Equals(2)) self.run_mock.assert_has_calls( [ mock.call(["make", "-j2", "V=1", "bzImage", "modules"]), mock.call( [ "make", "-j2", "V=1", "CONFIG_PREFIX={}".format(plugin.installdir), "modules_install", "INSTALL_MOD_PATH={}".format(plugin.installdir), "firmware_install", "INSTALL_FW_PATH={}".format( os.path.join(plugin.installdir, "lib", "firmware") ), ] ), ] ) config_file = os.path.join(plugin.builddir, ".config") self.assertTrue(os.path.exists(config_file)) with open(config_file) as f: config_contents = f.read() self.assertThat(config_contents, Equals("ACCEPT=y\n")) self._assert_common_assets(plugin.installdir)
def test_default(self): plugin = kernel.KernelPlugin("test-part", self.options, self.project) self.assertThat(plugin.kernel_image_target, Equals(self.expected))