pmbootstrap-meow/test/test_questions.py
Oliver Smith ad5a0d4294
Make proprietary drivers optional (1/2): pmbootstrap changes (#1254)
Here are the changes necessary in pmbootstrap to make proprietary
software installed onto the device (firmware and userspace drivers)
optional (#756). To full close the issue, we need to apply this concept
to all device packages we already have in a follow-up PR.

Changes:
* New config file options nonfree_firmware and nonfree_userland, which
  we ask for during "pmbootstrap init" if there are non-free components
  for the selected device.
* We find that out by checking the APKBUILD's subpakages: The non-free
  packages are called $pkgname-nonfree-firmware and
  $pkgname-nonfree-userland.
* During "pmbootstrap init" we also show the pkgdesc of these
  subpackages. Parsing that is implemented in
  pmb.parse._apkbuild.subpkgdesc(). It was not implemented as part of
  the regular APKBUILD parsing, as this would need a change in the
  output format, and it is a lot *less* code if done like in this
  commit.
* pmb/parse/apkbuild.py was renamed to _apkbuild.py, and
  pmb/install/install.py to _install.py: needed to call the function in
  the usual way (e.g. pmb.parse.apkbuild()) but still being able to
  test the individual functions from these files in the test suite.
  We did the same thing for pmb/build/_package.py already.
* Install: New function get_nonfree_packages() returns the non-free
  packages that will be installed, based on the user's choice in
  "pmbootstrap init" and on the subpackages the device has.
* Added test cases and test data (APKBUILDs) for all new code,
  refactored test/test_questions.py to have multiple functions for
  testing the various questions / question types from
  "pmbootstrap init" instead of having it all in one big function.
  This allows to use another aport folder for testing the new
  non-free related questions in init.
2018-02-24 21:49:10 +00:00

221 lines
7.5 KiB
Python

"""
Copyright 2018 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 <http://www.gnu.org/licenses/>.
"""
import logging
import os
import pytest
import sys
# Import from parent directory
pmb_src = os.path.realpath(os.path.join(os.path.dirname(__file__) + "/.."))
sys.path.append(pmb_src)
import pmb.aportgen.device
import pmb.config
import pmb.config.init
import pmb.helpers.logging
@pytest.fixture
def args(tmpdir, request):
import pmb.parse
sys.argv = ["pmbootstrap.py", "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 fake_answers(monkeypatch, answers):
"""
Patch pmb.helpers.cli.ask() function to return defined answers instead of
asking the user for an answer.
:param answers: list of answer strings, e.g. ["y", "n", "invalid-device"].
In this example, the first question is answered with "y",
the second question with "n" and so on.
"""
def fake_ask(args, question="Continue?", choices=["y", "n"], default="n",
lowercase_answer=True, validation_regex=None):
answer = answers.pop(0)
logging.info("pmb.helpers.cli.ask() fake answer: " + answer)
return answer
monkeypatch.setattr(pmb.helpers.cli, "ask", fake_ask)
def test_fake_answers_selftest(monkeypatch):
fake_answers(monkeypatch, ["first", "second"])
assert pmb.helpers.cli.ask(args) == "first"
assert pmb.helpers.cli.ask(args) == "second"
def test_questions_booleans(args, monkeypatch):
functions = [pmb.aportgen.device.ask_for_keyboard,
pmb.aportgen.device.ask_for_external_storage]
for func in functions:
fake_answers(monkeypatch, ["y", "n"])
assert func(args) is True
assert func(args) is False
def test_questions_strings(args, monkeypatch):
functions = [pmb.aportgen.device.ask_for_manufacturer,
pmb.aportgen.device.ask_for_name]
for func in functions:
fake_answers(monkeypatch, ["Simple string answer"])
assert func(args) == "Simple string answer"
def test_questions_arch(args, monkeypatch):
fake_answers(monkeypatch, ["invalid_arch", "aarch64"])
assert pmb.aportgen.device.ask_for_architecture(args) == "aarch64"
def test_questions_bootimg(args, monkeypatch):
func = pmb.aportgen.device.ask_for_bootimg
fake_answers(monkeypatch, ["invalid_path", ""])
assert func(args) is None
bootimg_path = pmb_src + "/test/testdata/bootimg/normal-boot.img"
fake_answers(monkeypatch, [bootimg_path])
output = {"base": "0x80000000",
"kernel_offset": "0x00008000",
"ramdisk_offset": "0x04000000",
"second_offset": "0x00f00000",
"tags_offset": "0x0e000000",
"pagesize": "2048",
"cmdline": "bootopt=64S3,32S1,32S1",
"qcdt": "false"}
assert func(args) == output
def test_questions_device(args, monkeypatch):
# Prepare args
args.aports = pmb_src + "/test/testdata/init_questions_device/aports"
args.device = "lg-mako"
args.nonfree_firmware = True
args.nonfree_userland = False
# Do not generate aports
def fake_generate(args, pkgname):
return
monkeypatch.setattr(pmb.aportgen, "generate", fake_generate)
# Existing device (without non-free components so we have defaults there)
func = pmb.config.init.ask_for_device
nonfree = {"firmware": True, "userland": False}
fake_answers(monkeypatch, ["lg-mako"])
assert func(args) == ("lg-mako", True, nonfree)
# Non-existing device, go back, existing device
fake_answers(monkeypatch, ["whoops-typo", "n", "lg-mako"])
assert func(args) == ("lg-mako", True, nonfree)
# New device
fake_answers(monkeypatch, ["new-device", "y"])
assert func(args) == ("new-device", False, nonfree)
def test_questions_device_nonfree(args, monkeypatch):
# Prepare args
args.aports = pmb_src + "/test/testdata/init_questions_device/aports"
args.nonfree_firmware = False
args.nonfree_userland = False
# APKBUILD with firmware and userland (all yes)
func = pmb.config.init.ask_for_device_nonfree
device = "nonfree-firmware-and-userland"
fake_answers(monkeypatch, ["y", "y"])
nonfree = {"firmware": True, "userland": True}
assert func(args, device) == nonfree
# APKBUILD with firmware and userland (all no)
fake_answers(monkeypatch, ["n", "n"])
nonfree = {"firmware": False, "userland": False}
assert func(args, device) == nonfree
# APKBUILD with firmware only
func = pmb.config.init.ask_for_device_nonfree
device = "nonfree-firmware"
fake_answers(monkeypatch, ["y"])
nonfree = {"firmware": True, "userland": False}
assert func(args, device) == nonfree
# APKBUILD with userland only
func = pmb.config.init.ask_for_device_nonfree
device = "nonfree-userland"
fake_answers(monkeypatch, ["y"])
nonfree = {"firmware": False, "userland": True}
assert func(args, device) == nonfree
def test_questions_flash_methods(args, monkeypatch):
func = pmb.aportgen.device.ask_for_flash_method
fake_answers(monkeypatch, ["invalid_flash_method", "fastboot"])
assert func(args) == "fastboot"
fake_answers(monkeypatch, ["0xffff"])
assert func(args) == "0xffff"
fake_answers(monkeypatch, ["heimdall", "invalid_type", "isorec"])
assert func(args) == "heimdall-isorec"
fake_answers(monkeypatch, ["heimdall", "bootimg"])
assert func(args) == "heimdall-bootimg"
def test_questions_keymaps(args, monkeypatch):
func = pmb.config.init.ask_for_keymaps
fake_answers(monkeypatch, ["invalid_keymap", "us/rx51_us"])
assert func(args, "nokia-n900") == "us/rx51_us"
assert func(args, "lg-mako") == ""
def test_questions_qemu_native_mesa(args, monkeypatch):
func = pmb.config.init.ask_for_qemu_native_mesa_driver
fake_answers(monkeypatch, ["invalid_driver", "dri-swrast"])
assert func(args, "qemu-amd64", "x86_64") == "dri-swrast"
assert func(args, "qemu-aarch64", "x86_64") is None
def test_questions_ui(args, monkeypatch):
fake_answers(monkeypatch, ["invalid_UI", "weston"])
assert pmb.config.init.ask_for_ui(args) == "weston"
def test_questions_work_path(args, monkeypatch, tmpdir):
tmpdir = str(tmpdir)
fake_answers(monkeypatch, ["/dev/null", os.path.dirname(__file__),
pmb.config.pmb_src, tmpdir])
assert pmb.config.init.ask_for_work_path(args) == tmpdir
def test_questions_build_options(args, monkeypatch):
func = pmb.config.init.ask_for_build_options
cfg = {"pmbootstrap": {}}
# Skip changing anything
fake_answers(monkeypatch, ["n"])
func(args, cfg)
assert cfg == {"pmbootstrap": {}}
# Answer everything
fake_answers(monkeypatch, ["y", "5", "2G", "n"])
func(args, cfg)
assert cfg == {"pmbootstrap": {"jobs": "5",
"ccache_size": "2G"}}