""" Copyright 2017 Oliver Smith This file is part of pmbootstrap. pmbootstrap 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, either version 3 of the License, or (at your option) any later version. pmbootstrap 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 pmbootstrap. If not, see . """ """ This file tests all functions from pmb.build._package. """ import os import pytest import sys # Import from parent directory sys.path.append(os.path.realpath( os.path.join(os.path.dirname(__file__) + "/.."))) import pmb.build import pmb.build._package import pmb.config import pmb.config.init import pmb.helpers.logging @pytest.fixture def args(tmpdir, request): import pmb.parse sys.argv = ["pmbootstrap", "init"] args = pmb.parse.arguments() args.log = args.work + "/log_testsuite.txt" pmb.helpers.logging.init(args) request.addfinalizer(args.logfd.close) return args def return_none(*args, **kwargs): return None def return_string(*args, **kwargs): return "some/random/path.apk" def return_true(*args, **kwargs): return True def return_false(*args, **kwargs): return False def return_fake_build_depends(*args, **kwargs): """ Fake return value for pmb.build._package.build_depends: depends: ["alpine-base"], depends_built: [] """ return (["alpine-base"], []) def args_patched(monkeypatch, argv): monkeypatch.setattr(sys, "argv", argv) return pmb.parse.arguments() def test_get_apkbuild(args): func = pmb.build._package.get_apkbuild # Valid aport pkgname = "postmarketos-base" assert func(args, pkgname, "x86_64")["pkgname"] == pkgname # Valid binary package assert func(args, "alpine-base", "x86_64") is None # Invalid package with pytest.raises(RuntimeError) as e: func(args, "invalid-package-name", "x86_64") assert "Could not find" in str(e.value) def test_check_arch(args): func = pmb.build._package.check_arch apkbuild = {"pkgname": "test"} # Arch is right apkbuild["arch"] = ["armhf"] func(args, apkbuild, "armhf") apkbuild["arch"] = ["noarch"] func(args, apkbuild, "armhf") apkbuild["arch"] = ["all"] func(args, apkbuild, "armhf") # Arch is wrong apkbuild["arch"] = ["x86_64"] with pytest.raises(RuntimeError) as e: func(args, apkbuild, "armhf") assert "Can't build" in str(e.value) def test_get_depends(monkeypatch): func = pmb.build._package.get_depends apkbuild = {"pkgname": "test", "depends": ["a"], "makedepends": ["c", "b"], "subpackages": ["d"]} # Depends + makedepends args = args_patched(monkeypatch, ["pmbootstrap", "build", "test"]) assert func(args, apkbuild) == ["a", "b", "c"] args = args_patched(monkeypatch, ["pmbootstrap", "install"]) assert func(args, apkbuild) == ["a", "b", "c"] # Ignore depends (-i) args = args_patched(monkeypatch, ["pmbootstrap", "build", "-i", "test"]) assert func(args, apkbuild) == ["b", "c"] # Package depends on its own subpackage apkbuild["makedepends"] = ["d"] args = args_patched(monkeypatch, ["pmbootstrap", "build", "test"]) assert func(args, apkbuild) == ["a"] # Package depends on itself apkbuild["makedepends"] = ["c", "b", "test"] args = args_patched(monkeypatch, ["pmbootstrap", "build", "test"]) assert func(args, apkbuild) == ["a", "b", "c"] def test_build_depends(args, monkeypatch): # Shortcut and fake apkbuild func = pmb.build._package.build_depends apkbuild = {"pkgname": "test", "depends": ["a"], "makedepends": ["b"], "subpackages": ["d"]} # No depends built (first makedepends + depends, then only makedepends) monkeypatch.setattr(pmb.build._package, "package", return_none) assert func(args, apkbuild, "armhf", True) == (["a", "b"], []) # All depends built (makedepends only) monkeypatch.setattr(pmb.build._package, "package", return_string) assert func(args, apkbuild, "armhf", False) == (["a", "b"], ["a", "b"]) def test_is_necessary_warn_depends(args, monkeypatch): # Shortcut and fake apkbuild func = pmb.build._package.is_necessary_warn_depends apkbuild = {"pkgname": "test"} # Necessary monkeypatch.setattr(pmb.build, "is_necessary", return_true) assert func(args, apkbuild, "armhf", False, []) is True # Necessary (strict=True overrides is_necessary()) monkeypatch.setattr(pmb.build, "is_necessary", return_false) assert func(args, apkbuild, "armhf", True, []) is True # Not necessary (with depends: different code path that prints a warning) assert func(args, apkbuild, "armhf", False, []) is False assert func(args, apkbuild, "armhf", False, ["first", "second"]) is False def test_init_buildenv(args, monkeypatch): # Disable effects of functions we don't want to test here monkeypatch.setattr(pmb.build._package, "build_depends", return_fake_build_depends) monkeypatch.setattr(pmb.build._package, "is_necessary_warn_depends", return_true) monkeypatch.setattr(pmb.chroot.apk, "install", return_none) monkeypatch.setattr(pmb.chroot.distccd, "start", return_none) # Shortcut and fake apkbuild func = pmb.build._package.init_buildenv apkbuild = {"pkgname": "test", "depends": ["a"], "makedepends": ["b"]} # Build is necessary (various code paths) assert func(args, apkbuild, "armhf", strict=True) is True assert func(args, apkbuild, "armhf", cross="native") is True assert func(args, apkbuild, "armhf", cross="distcc") is True # Build is not necessary (only builds dependencies) monkeypatch.setattr(pmb.build._package, "is_necessary_warn_depends", return_false) assert func(args, apkbuild, "armhf") is False def test_run_abuild(args, monkeypatch): # Disable effects of functions we don't want to test here monkeypatch.setattr(pmb.build, "copy_to_buildpath", return_none) monkeypatch.setattr(pmb.chroot, "user", return_none) # Shortcut and fake apkbuild func = pmb.build._package.run_abuild apkbuild = {"pkgname": "test", "pkgver": "1", "pkgrel": "2", "options": []} # Normal run output = "armhf/test-1-r2.apk" env = {"CARCH": "armhf"} cmd = ["CARCH=armhf", "abuild", "-d"] assert func(args, apkbuild, "armhf") == (output, cmd, env) # Force and strict cmd = ["CARCH=armhf", "abuild", "-r", "-f"] assert func(args, apkbuild, "armhf", True, True) == (output, cmd, env) # cross=native env = {"CARCH": "armhf", "CROSS_COMPILE": "armv6-alpine-linux-muslgnueabihf-", "CC": "armv6-alpine-linux-muslgnueabihf-gcc"} cmd = ["CARCH=armhf", "CROSS_COMPILE=armv6-alpine-linux-muslgnueabihf-", "CC=armv6-alpine-linux-muslgnueabihf-gcc", "abuild", "-d"] assert func(args, apkbuild, "armhf", cross="native") == (output, cmd, env) # cross=distcc env = {"CARCH": "armhf", "PATH": "/usr/lib/distcc/bin:" + pmb.config.chroot_path, "DISTCC_HOSTS": "127.0.0.1:33632"} cmd = ["CARCH=armhf", "PATH=" + "/usr/lib/distcc/bin:" + pmb.config.chroot_path, "DISTCC_HOSTS=127.0.0.1:33632", "abuild", "-d"] assert func(args, apkbuild, "armhf", cross="distcc") == (output, cmd, env) def test_finish(args, monkeypatch): # Real output path output = pmb.build.package(args, "hello-world", force=True) # Disable effects of functions we don't want to test below monkeypatch.setattr(pmb.build.buildinfo, "write", return_none) monkeypatch.setattr(pmb.chroot, "user", return_none) # Shortcut and fake apkbuild func = pmb.build._package.finish apkbuild = {} # Non-existing output path with pytest.raises(RuntimeError) as e: func(args, apkbuild, "armhf", "/invalid/path") assert "Package not found" in str(e.value) # Existing output path func(args, apkbuild, args.arch_native, output) def test_package(args): # First build assert pmb.build.package(args, "hello-world", force=True) # Package exists assert pmb.build.package(args, "hello-world") is None # Force building again assert pmb.build.package(args, "hello-world", force=True) # Build for another architecture assert pmb.build.package(args, "hello-world", "armhf", force=True) # Upstream package, for which we don't have an aport assert pmb.build.package(args, "alpine-base") is None def test_build_depends_high_level(args, monkeypatch): """ "hello-world-wrapper" depends on "hello-world". We build both, then delete "hello-world" and check that it gets rebuilt correctly again. """ # Patch pmb.build.is_necessary() to always build the hello-world package def fake_build_is_necessary(args, arch, apkbuild, apkindex_path=None): if apkbuild["pkgname"] == "hello-world": return True return pmb.build.other.is_necessary(args, arch, apkbuild, apkindex_path) monkeypatch.setattr(pmb.build, "is_necessary", fake_build_is_necessary) # Build hello-world to get its full output path output_hello = pmb.build.package(args, "hello-world") output_hello_outside = args.work + "/packages/" + output_hello assert os.path.exists(output_hello_outside) # Make sure the wrapper exists pmb.build.package(args, "hello-world-wrapper") # Remove hello-world pmb.helpers.run.root(args, ["rm", output_hello_outside]) pmb.build.index_repo(args, args.arch_native) # Ask to build the wrapper. It should not build the wrapper (it exists, not # using force), but build/update its missing dependency "hello-world" # instead. assert pmb.build.package(args, "hello-world-wrapper") is None assert os.path.exists(output_hello_outside)