diff --git a/pmb/challenge/__init__.py b/pmb/challenge/__init__.py
index a218f26f..92e45710 100644
--- a/pmb/challenge/__init__.py
+++ b/pmb/challenge/__init__.py
@@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License
along with pmbootstrap. If not, see .
"""
# Exported functions
-from pmb.challenge.apk import apk
+from pmb.challenge.apk_file import apk
from pmb.challenge.apkindex import apkindex
from pmb.challenge.build import build
from pmb.challenge.frontend import frontend
diff --git a/pmb/challenge/apk_file.py b/pmb/challenge/apk_file.py
new file mode 100644
index 00000000..f05fa2ad
--- /dev/null
+++ b/pmb/challenge/apk_file.py
@@ -0,0 +1,126 @@
+"""
+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 .
+"""
+import logging
+import os
+import tarfile
+import tempfile
+import filecmp
+import shutil
+
+
+def contents_diff(tar_a, tar_b, member_a, member_b, name):
+ # Extract both files
+ tars = [tar_a, tar_b]
+ members = [member_a, member_b]
+ temp_files = []
+ for i in range(2):
+ handle, path = tempfile.mkstemp("pmbootstrap")
+ handle = open(handle, "wb")
+ shutil.copyfileobj(tars[i].extractfile(members[i]), handle)
+ handle.close()
+ temp_files.append(path)
+
+ # Compare and delete
+ equal = filecmp.cmp(temp_files[0], temp_files[1], shallow=False)
+ for temp_file in temp_files:
+ os.remove(temp_file)
+ if equal:
+ logging.debug("=> OK!")
+ else:
+ raise RuntimeError("File '" + name + "' is different!")
+
+
+def contents_without_signature(tar, tar_name):
+ """
+ The signature file name is always different.
+ This function raises an exception, when the number of signature
+ files in the archive is not 1.
+ :returns: a sorted list of all filenames inside the tar archive,
+ except for the signature file.
+ """
+ names = tar.getnames()
+ found = False
+ ret = []
+ for name in names:
+ if name.startswith(".SIGN.RSA."):
+ if found:
+ raise RuntimeError("More than one signature file found"
+ " inside " + tar_name + ": " +
+ str(names))
+ else:
+ found = True
+ else:
+ ret.append(name)
+
+ if not found:
+ raise RuntimeError("No signature file found inside " +
+ tar_name + ": " + str(names))
+ return sorted(ret)
+
+
+def apk(args, apk_a, apk_b, stop_after_first_error=False):
+ with tarfile.open(apk_a, "r:gz") as tar_a:
+ with tarfile.open(apk_b, "r:gz") as tar_b:
+ # List of files must be the same
+ list_a = contents_without_signature(tar_a, apk_a)
+ list_b = contents_without_signature(tar_b, apk_b)
+ if list_a != list_b:
+ logging.info("Files in " + apk_a + ":" + str(list_a))
+ logging.info("Files in " + apk_b + ":" + str(list_b))
+ raise RuntimeError(
+ "Both APKs do not contain the same file names!")
+
+ # Iterate through the list
+ success = True
+ for name in list_a:
+ try:
+ logging.debug("Compare: " + name)
+ if name == ".PKGINFO":
+ logging.debug(
+ "=> Skipping: expected to be different")
+ continue
+
+ # Get members
+ member_a = tar_a.getmember(name)
+ member_b = tar_b.getmember(name)
+ if member_a.type != member_b.type:
+ raise RuntimeError(
+ "Entry '" + name + "' has a different type!")
+
+ if member_a.isdir():
+ logging.debug("=> Skipping: directory")
+ elif member_a.isfile():
+ contents_diff(tar_a, tar_b, member_a, member_b, name)
+ elif member_a.issym() or member_a.islnk():
+ if member_a.linkname == member_b.linkname:
+ logging.debug(
+ "=> Both link to " + member_a.linkname)
+ else:
+ raise RuntimeError(
+ "Link " + name + " has a different target!")
+ else:
+ raise RuntimeError(
+ "Can't diff '" + name + "', unsupported type!")
+ except Exception as e:
+ logging.info("CHALLENGE FAILED for " + name + ":" + str(e))
+ success = False
+ if stop_after_first_error:
+ raise
+ if not success:
+ raise RuntimeError("Challenge failed (see errors above)")
diff --git a/pmb/challenge/build.py b/pmb/challenge/build.py
index b9ff352f..3fa2bdf9 100644
--- a/pmb/challenge/build.py
+++ b/pmb/challenge/build.py
@@ -23,7 +23,7 @@ import pmb.build
import pmb.parse.apkbuild
import pmb.parse.other
import pmb.helpers.repo
-import pmb.challenge.apk
+import pmb.challenge
def build(args, apk_path):
diff --git a/pmb/chroot/other.py b/pmb/chroot/other.py
index 1f734657..b54a9dc6 100644
--- a/pmb/chroot/other.py
+++ b/pmb/chroot/other.py
@@ -38,3 +38,17 @@ def kernel_flavor_autodetect(args, suffix):
"""
pmb.chroot.apk.install(args, ["device-" + args.device], suffix)
return kernel_flavors_installed(args, suffix)[0]
+
+
+def tempfolder(args, path, suffix="native"):
+ """
+ Create a temporary folder inside the chroot, that belongs to "user".
+ The folder gets deleted, if it already exists.
+
+ :param path: of the temporary folder inside the chroot
+ :returns: the path
+ """
+ if os.path.exists(args.work + "/chroot_" + suffix + path):
+ pmb.chroot.root(args, ["rm", "-r", path])
+ pmb.chroot.user(args, ["mkdir", "-p", path])
+ return path
diff --git a/pmb/chroot/zap.py b/pmb/chroot/zap.py
index 7c9264e1..b87dc3a8 100644
--- a/pmb/chroot/zap.py
+++ b/pmb/chroot/zap.py
@@ -27,7 +27,7 @@ def zap(args):
pmb.chroot.shutdown(args)
patterns = [
"chroot_native",
- "chroot_buildroot_" + args.deviceinfo["arch"],
+ "chroot_buildroot_*",
"chroot_rootfs_" + args.device,
]
diff --git a/test/test_apk_static.py b/test/test_apk_static.py
index 22215e7d..49f9a296 100644
--- a/test/test_apk_static.py
+++ b/test/test_apk_static.py
@@ -42,15 +42,15 @@ def args(request):
def test_read_signature_info(args):
# Tempfolder inside chroot for fake apk files
tmp_path = "/tmp/test_read_signature_info"
- tmp_path_chroot = args.work + "/chroot_native" + tmp_path
- if os.path.exists(tmp_path_chroot):
+ tmp_path_outside = args.work + "/chroot_native" + tmp_path
+ if os.path.exists(tmp_path_outside):
pmb.chroot.root(args, ["rm", "-r", tmp_path])
pmb.chroot.user(args, ["mkdir", "-p", tmp_path])
# No signature found
pmb.chroot.user(args, ["tar", "-czf", tmp_path + "/no_sig.apk",
"/etc/issue"])
- with tarfile.open(tmp_path_chroot + "/no_sig.apk", "r:gz") as tar:
+ with tarfile.open(tmp_path_outside + "/no_sig.apk", "r:gz") as tar:
with pytest.raises(RuntimeError) as e:
pmb.chroot.apk_static.read_signature_info(tar)
assert "Could not find signature" in str(e.value)
@@ -62,7 +62,7 @@ def test_read_signature_info(args):
pmb.chroot.user(args, ["tar", "-czf", tmp_path + "/invalid_sig.apk",
"sbin/apk.static.SIGN.RSA.invalid.pub"],
working_dir=tmp_path)
- with tarfile.open(tmp_path_chroot + "/invalid_sig.apk", "r:gz") as tar:
+ with tarfile.open(tmp_path_outside + "/invalid_sig.apk", "r:gz") as tar:
with pytest.raises(RuntimeError) as e:
pmb.chroot.apk_static.read_signature_info(tar)
assert "Invalid signature key" in str(e.value)
@@ -75,7 +75,7 @@ def test_read_signature_info(args):
tmp_path + "/" + path_archive])
pmb.chroot.user(args, ["tar", "-czf", tmp_path + "/realistic_name_sig.apk",
path_archive], working_dir=tmp_path)
- with tarfile.open(tmp_path_chroot + "/realistic_name_sig.apk", "r:gz") as tar:
+ with tarfile.open(tmp_path_outside + "/realistic_name_sig.apk", "r:gz") as tar:
sigfilename, sigkey_path = pmb.chroot.apk_static.read_signature_info(
tar)
assert sigfilename == path_archive
diff --git a/test/test_challenge_apk.py b/test/test_challenge_apk.py
new file mode 100644
index 00000000..e7792da2
--- /dev/null
+++ b/test/test_challenge_apk.py
@@ -0,0 +1,270 @@
+"""
+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 .
+"""
+import os
+import sys
+import pytest
+import tarfile
+
+# Import from parent directory
+sys.path.append(os.path.abspath(
+ os.path.join(os.path.dirname(__file__) + "/..")))
+import pmb.challenge.apk_file
+import pmb.config
+import pmb.chroot.other
+
+
+@pytest.fixture
+def args(request):
+ import pmb.parse
+ sys.argv = ["pmbootstrap.py", "chroot"]
+ args = pmb.parse.arguments()
+ setattr(args, "logfd", open("/dev/null", "a+"))
+ request.addfinalizer(args.logfd.close)
+ return args
+
+
+def test_apk_challenge_contents_diff(args):
+ """
+ Create two tar files, which contain a file with the same name.
+ The content of that file is different.
+ """
+ # Tempfolder inside chroot for fake apk files
+ temp_path = pmb.chroot.other.tempfolder(
+ args, "/tmp/test_apk_challenge_contents_diff")
+ temp_path_outside = args.work + "/chroot_native" + temp_path
+
+ # First file
+ name = "testfile"
+ apk_a = temp_path_outside + "/a.apk"
+ pmb.chroot.user(args, ["cp", "/etc/inittab", temp_path + "/" + name])
+ pmb.chroot.user(args, ["tar", "-czf", "a.apk", name],
+ working_dir=temp_path)
+
+ # Second file
+ apk_b = temp_path_outside + "/b.apk"
+ pmb.chroot.user(args, ["cp", "/etc/abuild.conf", temp_path + "/" + name])
+ pmb.chroot.user(args, ["tar", "-czf", "b.apk", name],
+ working_dir=temp_path)
+
+ # Compare OK
+ with tarfile.open(apk_a, "r:gz") as tar_a:
+ member_a = tar_a.getmember(name)
+ pmb.challenge.apk_file.contents_diff(
+ tar_a, tar_a, member_a, member_a, name)
+
+ # Compare NOK
+ with tarfile.open(apk_b, "r:gz") as tar_b:
+ member_b = tar_b.getmember(name)
+ with pytest.raises(RuntimeError) as e:
+ pmb.challenge.apk_file.contents_diff(tar_a, tar_b, member_a,
+ member_b, name)
+ assert str(e.value).endswith(" is different!")
+
+
+def test_apk_challenge_contents_without_signature(args):
+ # Tempfolder inside chroot for fake apk files
+ temp_path = pmb.chroot.other.tempfolder(
+ args, "/tmp/test_apk_challenge_nosig")
+ temp_path_outside = args.work + "/chroot_native" + temp_path
+
+ # Create three archives
+ contents = {
+ "no_sig.apk": ["other_file"],
+ "one_sig.apk": [".SIGN.RSA.first", "other_file"],
+ "two_sig.apk": [".SIGN.RSA.first", ".SIGN.RSA.second"],
+ }
+ for apk, files in contents.items():
+ for file in files:
+ pmb.chroot.user(args, ["touch", temp_path + "/" + file])
+ pmb.chroot.user(args, ["tar", "-czf", apk] +
+ files, working_dir=temp_path)
+
+ # No signature
+ with tarfile.open(temp_path_outside + "/no_sig.apk", "r:gz") as tar:
+ with pytest.raises(RuntimeError) as e:
+ pmb.challenge.apk_file.contents_without_signature(tar, "a.apk")
+ assert str(e.value).startswith("No signature file found")
+
+ # One signature
+ with tarfile.open(temp_path_outside + "/one_sig.apk", "r:gz") as tar:
+ contents = pmb.challenge.apk_file.contents_without_signature(
+ tar, "a.apk")
+ assert contents == ["other_file"]
+
+ # More than one signature
+ with tarfile.open(temp_path_outside + "/two_sig.apk", "r:gz") as tar:
+ with pytest.raises(RuntimeError) as e:
+ pmb.challenge.apk_file.contents_without_signature(tar, "a.apk")
+ assert str(e.value).startswith("More than one signature")
+
+
+def test_apk_challenge_different_files_inside_archive(args):
+ # Tempfolder inside chroot for fake apk files
+ temp_path = pmb.chroot.other.tempfolder(args, "/tmp/test_apk_challenge")
+ temp_path_outside = args.work + "/chroot_native" + temp_path
+
+ # Create fake apks
+ contents = {
+ "a.apk": [".SIGN.RSA.first", "first_file", "second_file"],
+ "b.apk": [".SIGN.RSA.second", "first_file"],
+ }
+ for apk, files in contents.items():
+ for file in files:
+ pmb.chroot.user(args, ["touch", temp_path + "/" + file])
+ pmb.chroot.user(args, ["tar", "-czf", apk] +
+ files, working_dir=temp_path)
+
+ # Challenge both files
+ with pytest.raises(RuntimeError) as e:
+ pmb.challenge.apk(args, temp_path_outside + "/a.apk",
+ temp_path_outside + "/b.apk")
+ assert "do not contain the same file names" in str(e.value)
+
+
+def test_apk_challenge_entry_has_a_different_type(args):
+ # Tempfolder inside chroot for fake apk files
+ temp_path = pmb.chroot.other.tempfolder(args, "/tmp/test_apk_challenge")
+ temp_path_outside = args.work + "/chroot_native" + temp_path
+
+ # Create fake apks
+ contents = {
+ "a.apk": [".SIGN.RSA.first", ".APKINDEX", "different_type"],
+ "b.apk": [".SIGN.RSA.second", ".APKINDEX", "different_type"],
+ }
+ for apk, files in contents.items():
+ for file in files:
+ if file == "different_type" and apk == "b.apk":
+ pmb.chroot.user(args, ["rm", temp_path + "/" + file])
+ pmb.chroot.user(args, ["mkdir", temp_path + "/" + file])
+ else:
+ pmb.chroot.user(args, ["touch", temp_path + "/" + file])
+ pmb.chroot.user(args, ["tar", "-czf", apk] +
+ files, working_dir=temp_path)
+
+ # Exact error (with stop_after_first_error)
+ with pytest.raises(RuntimeError) as e:
+ pmb.challenge.apk(args, temp_path_outside + "/a.apk",
+ temp_path_outside + "/b.apk", stop_after_first_error=True)
+ assert "has a different type!" in str(e.value)
+
+ # Generic error
+ with pytest.raises(RuntimeError) as e:
+ pmb.challenge.apk(args, temp_path_outside + "/a.apk",
+ temp_path_outside + "/b.apk")
+ assert "Challenge failed"
+
+
+def test_apk_challenge_file_has_different_content(args):
+ # Tempfolder inside chroot for fake apk files
+ temp_path = pmb.chroot.other.tempfolder(args, "/tmp/test_apk_challenge")
+ temp_path_outside = args.work + "/chroot_native" + temp_path
+
+ # Create fake apks
+ contents = {
+ "a.apk": [".SIGN.RSA.first", ".APKINDEX", "different_content"],
+ "b.apk": [".SIGN.RSA.second", ".APKINDEX", "different_content"],
+ }
+ for apk, files in contents.items():
+ for file in files:
+ if file == "different_content" and apk == "b.apk":
+ pmb.chroot.user(
+ args, [
+ "cp", "/etc/hostname", temp_path + "/" + file])
+ else:
+ pmb.chroot.user(args, ["touch", temp_path + "/" + file])
+ pmb.chroot.user(args, ["tar", "-czf", apk] +
+ files, working_dir=temp_path)
+
+ # Exact error (with stop_after_first_error)
+ with pytest.raises(RuntimeError) as e:
+ pmb.challenge.apk(args, temp_path_outside + "/a.apk",
+ temp_path_outside + "/b.apk", stop_after_first_error=True)
+ assert str(e.value).endswith("is different!")
+
+ # Generic error
+ with pytest.raises(RuntimeError) as e:
+ pmb.challenge.apk(args, temp_path_outside + "/a.apk",
+ temp_path_outside + "/b.apk")
+ assert "Challenge failed"
+
+
+def test_apk_challenge_different_link_target(args):
+ # Tempfolder inside chroot for fake apk files
+ temp_path = pmb.chroot.other.tempfolder(args, "/tmp/test_apk_challenge")
+ temp_path_outside = args.work + "/chroot_native" + temp_path
+
+ # Create fake apks
+ contents = {
+ "a.apk": [".SIGN.RSA.first", ".APKINDEX", "link_same", "link_different"],
+ "b.apk": [".SIGN.RSA.second", ".APKINDEX", "link_same", "link_different"],
+ }
+ for apk, files in contents.items():
+ for file in files:
+ if file.startswith("link_"):
+ if file == "link_different" and apk == "b.apk":
+ pmb.chroot.user(args, ["ln", "-sf", "/different_target",
+ temp_path + "/" + file])
+ else:
+ pmb.chroot.user(args, ["ln", "-sf", "/some_link_target",
+ temp_path + "/" + file])
+ else:
+ pmb.chroot.user(args, ["touch", temp_path + "/" + file])
+ pmb.chroot.user(args, ["tar", "-czf", apk] +
+ files, working_dir=temp_path)
+
+ # Exact error (with stop_after_first_error)
+ with pytest.raises(RuntimeError) as e:
+ pmb.challenge.apk(args, temp_path_outside + "/a.apk",
+ temp_path_outside + "/b.apk", stop_after_first_error=True)
+ assert str(e.value).endswith("has a different target!")
+
+ # Generic error
+ with pytest.raises(RuntimeError) as e:
+ pmb.challenge.apk(args, temp_path_outside + "/a.apk",
+ temp_path_outside + "/b.apk")
+ assert "Challenge failed"
+
+
+def test_apk_challenge_unsupported_type(args):
+ # Tempfolder inside chroot for fake apk files
+ temp_path = pmb.chroot.other.tempfolder(args, "/tmp/test_apk_challenge")
+ temp_path_outside = args.work + "/chroot_native" + temp_path
+
+ # Create fake apk with a FIFO (-> unsupported type)
+ apk = "test.apk"
+ content = [".SIGN.RSA.first", ".APKINDEX", "fifo"]
+ for file in content:
+ if file == "fifo":
+ pmb.chroot.user(args, ["mkfifo", temp_path + "/" + file])
+ else:
+ pmb.chroot.user(args, ["touch", temp_path + "/" + file])
+ pmb.chroot.user(args, ["tar", "-czf", apk] +
+ content, working_dir=temp_path)
+
+ # Exact error (with stop_after_first_error)
+ with pytest.raises(RuntimeError) as e:
+ pmb.challenge.apk(args, temp_path_outside + "/test.apk",
+ temp_path_outside + "/test.apk", stop_after_first_error=True)
+ assert str(e.value).endswith("unsupported type!")
+
+ # Generic error
+ with pytest.raises(RuntimeError) as e:
+ pmb.challenge.apk(args, temp_path_outside + "/test.apk",
+ temp_path_outside + "/test.apk")
+ assert "Challenge failed"
diff --git a/test/test_challenge_apkindex.py b/test/test_challenge_apkindex.py
new file mode 100644
index 00000000..12039352
--- /dev/null
+++ b/test/test_challenge_apkindex.py
@@ -0,0 +1,87 @@
+"""
+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 .
+"""
+import os
+import sys
+import pytest
+
+# Import from parent directory
+sys.path.append(os.path.abspath(
+ os.path.join(os.path.dirname(__file__) + "/..")))
+import pmb.challenge.apkindex
+import pmb.config
+
+
+@pytest.fixture
+def args(request, tmpdir):
+ import pmb.parse
+ sys.argv = ["pmbootstrap.py", "chroot"]
+ args = pmb.parse.arguments()
+ setattr(args, "logfd", open("/dev/null", "a+"))
+ request.addfinalizer(args.logfd.close)
+
+ # Create an empty APKINDEX.tar.gz file, so we can use its path and
+ # timestamp to put test information in the cache.
+ path_apkindex = str(tmpdir) + "/APKINDEX.tar.gz"
+ open(path_apkindex, "a").close()
+ lastmod = os.path.getmtime(path_apkindex)
+ args.cache["apkindex"][path_apkindex] = {"lastmod": lastmod, "ret": {}}
+
+ return args
+
+
+def test_challenge_apkindex_extra_file(args):
+ """
+ Create an extra file, that is not mentioned in the APKINDEX cache.
+ """
+ path_apkindex = list(args.cache["apkindex"].keys())[0]
+ tmpdir = os.path.dirname(path_apkindex)
+ open(tmpdir + "/invalid-extra-file.apk", "a").close()
+
+ with pytest.raises(RuntimeError) as e:
+ pmb.challenge.apkindex(args, path_apkindex)
+ assert "Unexpected file" in str(e.value)
+
+
+def test_challenge_apkindex_file_does_not_exist(args):
+ """
+ Add an entry to the APKINDEX cache, that does not exist on disk.
+ """
+ path_apkindex = list(args.cache["apkindex"].keys())[0]
+ args.cache["apkindex"][path_apkindex]["ret"] = {
+ "hello-world": {"pkgname": "hello-world", "version": "1-r2"}
+ }
+
+ with pytest.raises(RuntimeError) as e:
+ pmb.challenge.apkindex(args, path_apkindex)
+ assert str(e.value).startswith("Could not find file 'hello-world")
+
+
+def test_challenge_apkindex_ok(args):
+ """
+ Metion one file in the APKINDEX cache, and create it on disk. The challenge
+ should go through without an exception.
+ """
+ path_apkindex = list(args.cache["apkindex"].keys())[0]
+ args.cache["apkindex"][path_apkindex]["ret"] = {
+ "hello-world": {"pkgname": "hello-world", "version": "1-r2"}
+ }
+ tmpdir = os.path.dirname(path_apkindex)
+ open(tmpdir + "/hello-world-1-r2.apk", "a").close()
+
+ pmb.challenge.apkindex(args, path_apkindex)
diff --git a/test/test_challenge_build.py b/test/test_challenge_build.py
new file mode 100644
index 00000000..c6d9c136
--- /dev/null
+++ b/test/test_challenge_build.py
@@ -0,0 +1,67 @@
+"""
+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 .
+"""
+import os
+import sys
+import pytest
+
+# Import from parent directory
+sys.path.append(os.path.abspath(
+ os.path.join(os.path.dirname(__file__) + "/..")))
+import pmb.build.package
+import pmb.challenge.build
+import pmb.parse
+import pmb.config
+
+
+@pytest.fixture
+def args(request, tmpdir):
+ import pmb.parse
+ sys.argv = ["pmbootstrap.py", "chroot"]
+ args = pmb.parse.arguments()
+ setattr(args, "logfd", open("/dev/null", "a+"))
+ request.addfinalizer(args.logfd.close)
+ return args
+
+
+def test_challenge_build(args):
+ # Build the "hello-world" package
+ pkgname = "hello-world"
+ pmb.build.package(args, pkgname, None, force=True, buildinfo=True)
+
+ # Copy it to a temporary path
+ apkbuild = pmb.parse.apkbuild(args.aports + "/" + pkgname + "/APKBUILD")
+ version = apkbuild["pkgver"] + "-r" + apkbuild["pkgrel"]
+ temp_path = pmb.chroot.other.tempfolder(args, "/tmp/test_challenge_build/" +
+ args.arch_native)
+ apk_path = ("/home/user/packages/user/" + args.arch_native + "/" + pkgname +
+ "-" + version + ".apk")
+ pmb.chroot.user(args, ["cp", apk_path, apk_path +
+ ".buildinfo.json", temp_path])
+
+ # Challenge, output changes into a file
+ setattr(args, "output_repo_changes", args.work + "/chroot_native/tmp/"
+ "test_challenge_build_output.txt")
+ pmb.challenge.build(args, args.work + "/chroot_native/" + temp_path + "/" +
+ os.path.basename(apk_path))
+
+ # Verify the output textfile
+ with open(args.output_repo_changes, "r") as handle:
+ lines = handle.readlines()
+ assert lines == [args.arch_native + "/APKINDEX.tar.gz\n",
+ args.arch_native + "/" + pkgname + "-" + version + ".apk\n"]