659 lines
25 KiB
Python
659 lines
25 KiB
Python
|
|
import os
|
|
import sh
|
|
import unittest
|
|
|
|
from unittest import mock
|
|
|
|
from pythonforandroid.bootstrap import (
|
|
_cmp_bootstraps_by_priority, Bootstrap, expand_dependencies,
|
|
)
|
|
from pythonforandroid.distribution import Distribution
|
|
from pythonforandroid.recipe import Recipe
|
|
from pythonforandroid.archs import ArchARMv7_a
|
|
from pythonforandroid.build import Context
|
|
from pythonforandroid.util import BuildInterruptingException
|
|
from pythonforandroid.androidndk import AndroidNDK
|
|
|
|
from test_graph import get_fake_recipe
|
|
|
|
|
|
class BaseClassSetupBootstrap(object):
|
|
"""
|
|
An class object which is intended to be used as a base class to configure
|
|
an inherited class of `unittest.TestCase`. This class will override the
|
|
`setUp` and `tearDown` methods.
|
|
"""
|
|
|
|
TEST_ARCH = 'armeabi-v7a'
|
|
|
|
def setUp(self):
|
|
Recipe.recipes = {} # clear Recipe class cache
|
|
self.ctx = Context()
|
|
self.ctx.ndk_api = 21
|
|
self.ctx.android_api = 27
|
|
self.ctx._sdk_dir = "/opt/android/android-sdk"
|
|
self.ctx._ndk_dir = "/opt/android/android-ndk"
|
|
self.ctx.ndk = AndroidNDK(self.ctx._ndk_dir)
|
|
self.ctx.setup_dirs(os.getcwd())
|
|
self.ctx.recipe_build_order = [
|
|
"hostpython3",
|
|
"python3",
|
|
"sdl2",
|
|
"kivy",
|
|
]
|
|
|
|
def setUp_distribution_with_bootstrap(self, bs):
|
|
"""
|
|
Extend the setUp by configuring a distribution, because some test
|
|
needs a distribution to be set to be properly tested
|
|
"""
|
|
self.ctx.bootstrap = bs
|
|
self.ctx.bootstrap.distribution = Distribution.get_distribution(
|
|
self.ctx, name="test_prj",
|
|
recipes=["python3", "kivy"],
|
|
archs=[self.TEST_ARCH],
|
|
)
|
|
|
|
def tearDown(self):
|
|
"""
|
|
Extend the `tearDown` by configuring a distribution, because some test
|
|
needs a distribution to be set to be properly tested
|
|
"""
|
|
self.ctx.bootstrap = None
|
|
|
|
|
|
class TestBootstrapBasic(BaseClassSetupBootstrap, unittest.TestCase):
|
|
"""
|
|
An inherited class of `BaseClassSetupBootstrap` and `unittest.TestCase`
|
|
which will be used to perform tests for the methods/attributes shared
|
|
between all bootstraps which inherits from class
|
|
:class:`~pythonforandroid.bootstrap.Bootstrap`.
|
|
"""
|
|
|
|
def test_attributes(self):
|
|
"""A test which will initialize a bootstrap and will check if the
|
|
values are the expected.
|
|
"""
|
|
bs = Bootstrap().get_bootstrap("sdl2", self.ctx)
|
|
self.assertEqual(bs.name, "sdl2")
|
|
self.assertEqual(bs.jni_dir, "sdl2/jni")
|
|
self.assertEqual(bs.get_build_dir_name(), "sdl2")
|
|
|
|
# bs.dist_dir should raise an error if there is no distribution to query
|
|
bs.distribution = None
|
|
with self.assertRaises(BuildInterruptingException):
|
|
bs.dist_dir
|
|
|
|
# test dist_dir success
|
|
self.setUp_distribution_with_bootstrap(bs)
|
|
expected_folder_name = 'test_prj'
|
|
self.assertTrue(
|
|
bs.dist_dir.endswith(f"dists/{expected_folder_name}"))
|
|
|
|
def test_build_dist_dirs(self):
|
|
"""A test which will initialize a bootstrap and will check if the
|
|
directories we set has the values that we expect. Here we test methods:
|
|
|
|
- :meth:`~pythonforandroid.bootstrap.Bootstrap.get_build_dir`
|
|
- :meth:`~pythonforandroid.bootstrap.Bootstrap.get_dist_dir`
|
|
- :meth:`~pythonforandroid.bootstrap.Bootstrap.get_common_dir`
|
|
"""
|
|
bs = Bootstrap.get_bootstrap("sdl2", self.ctx)
|
|
|
|
self.assertTrue(
|
|
bs.get_build_dir().endswith("build/bootstrap_builds/sdl2")
|
|
)
|
|
self.assertTrue(bs.get_dist_dir("test_prj").endswith("dists/test_prj"))
|
|
|
|
def test__cmp_bootstraps_by_priority(self):
|
|
# Test service_only has higher priority than sdl2:
|
|
# (higher priority = smaller number/comes first)
|
|
self.assertTrue(_cmp_bootstraps_by_priority(
|
|
Bootstrap.get_bootstrap("service_only", self.ctx),
|
|
Bootstrap.get_bootstrap("sdl2", self.ctx)
|
|
) < 0)
|
|
|
|
# Test a random bootstrap is always lower priority than sdl2:
|
|
class _FakeBootstrap(object):
|
|
def __init__(self, name):
|
|
self.name = name
|
|
bs1 = _FakeBootstrap("alpha")
|
|
bs2 = _FakeBootstrap("zeta")
|
|
self.assertTrue(_cmp_bootstraps_by_priority(
|
|
bs1,
|
|
Bootstrap.get_bootstrap("sdl2", self.ctx)
|
|
) > 0)
|
|
self.assertTrue(_cmp_bootstraps_by_priority(
|
|
bs2,
|
|
Bootstrap.get_bootstrap("sdl2", self.ctx)
|
|
) > 0)
|
|
|
|
# Test bootstraps that aren't otherwise recognized are ranked
|
|
# alphabetically:
|
|
self.assertTrue(_cmp_bootstraps_by_priority(
|
|
bs2,
|
|
bs1,
|
|
) > 0)
|
|
self.assertTrue(_cmp_bootstraps_by_priority(
|
|
bs1,
|
|
bs2,
|
|
) < 0)
|
|
|
|
def test_all_bootstraps(self):
|
|
"""A test which will initialize a bootstrap and will check if the
|
|
method :meth:`~pythonforandroid.bootstrap.Bootstrap.all_bootstraps `
|
|
returns the expected values, which should be: `empty", `service_only`,
|
|
`webview` and `sdl2`
|
|
"""
|
|
expected_bootstraps = {"empty", "service_only", "service_library", "webview", "sdl2"}
|
|
set_of_bootstraps = Bootstrap.all_bootstraps()
|
|
self.assertEqual(
|
|
expected_bootstraps, expected_bootstraps & set_of_bootstraps
|
|
)
|
|
self.assertEqual(len(expected_bootstraps), len(set_of_bootstraps))
|
|
|
|
def test_expand_dependencies(self):
|
|
# Test dependency expansion of a recipe with no alternatives:
|
|
expanded_result_1 = expand_dependencies(["pysdl2"], self.ctx)
|
|
self.assertTrue(
|
|
{"sdl2", "pysdl2", "python3"} in
|
|
[set(s) for s in expanded_result_1]
|
|
)
|
|
|
|
# Test expansion of a single element but as tuple:
|
|
expanded_result_1 = expand_dependencies([("pysdl2",)], self.ctx)
|
|
self.assertTrue(
|
|
{"sdl2", "pysdl2", "python3"} in
|
|
[set(s) for s in expanded_result_1]
|
|
)
|
|
|
|
# Test all alternatives are listed (they won't have dependencies
|
|
# expanded since expand_dependencies() is too simplistic):
|
|
expanded_result_2 = expand_dependencies([("pysdl2", "kivy")], self.ctx)
|
|
self.assertEqual([["pysdl2"], ["kivy"]], expanded_result_2)
|
|
|
|
def test_expand_dependencies_with_pure_python_package(self):
|
|
"""Check that `expanded_dependencies`, with a pure python package as
|
|
one of the dependencies, returns a list of dependencies
|
|
"""
|
|
expanded_result = expand_dependencies(
|
|
["python3", "kivy", "peewee"], self.ctx
|
|
)
|
|
# we expect to one results for python3
|
|
self.assertEqual(len(expanded_result), 1)
|
|
self.assertIsInstance(expanded_result, list)
|
|
for i in expanded_result:
|
|
self.assertIsInstance(i, list)
|
|
|
|
def test_get_bootstraps_from_recipes(self):
|
|
"""A test which will initialize a bootstrap and will check if the
|
|
method :meth:`~pythonforandroid.bootstrap.Bootstrap.
|
|
get_bootstraps_from_recipes` returns the expected values
|
|
"""
|
|
|
|
import pythonforandroid.recipe
|
|
original_get_recipe = pythonforandroid.recipe.Recipe.get_recipe
|
|
|
|
# Test that SDL2 works with kivy:
|
|
recipes_sdl2 = {"sdl2", "python3", "kivy"}
|
|
bs = Bootstrap.get_bootstrap_from_recipes(recipes_sdl2, self.ctx)
|
|
self.assertEqual(bs.name, "sdl2")
|
|
|
|
# Test that pysdl2 or kivy alone will also yield SDL2 (dependency):
|
|
recipes_pysdl2_only = {"pysdl2"}
|
|
bs = Bootstrap.get_bootstrap_from_recipes(
|
|
recipes_pysdl2_only, self.ctx
|
|
)
|
|
self.assertEqual(bs.name, "sdl2")
|
|
recipes_kivy_only = {"kivy"}
|
|
bs = Bootstrap.get_bootstrap_from_recipes(
|
|
recipes_kivy_only, self.ctx
|
|
)
|
|
self.assertEqual(bs.name, "sdl2")
|
|
|
|
with mock.patch("pythonforandroid.recipe.Recipe.get_recipe") as \
|
|
mock_get_recipe:
|
|
# Test that something conflicting with sdl2 won't give sdl2:
|
|
def _add_sdl2_conflicting_recipe(name, ctx):
|
|
if name == "conflictswithsdl2":
|
|
if name not in pythonforandroid.recipe.Recipe.recipes:
|
|
pythonforandroid.recipe.Recipe.recipes[name] = (
|
|
get_fake_recipe("sdl2", conflicts=["sdl2"])
|
|
)
|
|
return original_get_recipe(name, ctx)
|
|
mock_get_recipe.side_effect = _add_sdl2_conflicting_recipe
|
|
recipes_with_sdl2_conflict = {"python3", "conflictswithsdl2"}
|
|
bs = Bootstrap.get_bootstrap_from_recipes(
|
|
recipes_with_sdl2_conflict, self.ctx
|
|
)
|
|
self.assertNotEqual(bs.name, "sdl2")
|
|
|
|
# Test using flask will default to webview:
|
|
recipes_with_flask = {"python3", "flask"}
|
|
bs = Bootstrap.get_bootstrap_from_recipes(
|
|
recipes_with_flask, self.ctx
|
|
)
|
|
self.assertEqual(bs.name, "webview")
|
|
|
|
# Test using random packages will default to service_only:
|
|
recipes_with_no_sdl2_or_web = {"python3", "numpy"}
|
|
bs = Bootstrap.get_bootstrap_from_recipes(
|
|
recipes_with_no_sdl2_or_web, self.ctx
|
|
)
|
|
self.assertEqual(bs.name, "service_only")
|
|
|
|
@mock.patch("pythonforandroid.bootstrap.ensure_dir")
|
|
def test_prepare_dist_dir(self, mock_ensure_dir):
|
|
"""A test which will initialize a bootstrap and will check if the
|
|
method :meth:`~pythonforandroid.bootstrap.Bootstrap.prepare_dist_dir`
|
|
successfully calls once the method `endure_dir`
|
|
"""
|
|
bs = Bootstrap().get_bootstrap("sdl2", self.ctx)
|
|
|
|
bs.prepare_dist_dir()
|
|
mock_ensure_dir.assert_called_once()
|
|
|
|
@mock.patch("pythonforandroid.bootstrap.open", create=True)
|
|
@mock.patch("pythonforandroid.util.chdir")
|
|
@mock.patch("pythonforandroid.bootstrap.shutil.copy")
|
|
@mock.patch("pythonforandroid.bootstrap.os.makedirs")
|
|
def test_bootstrap_prepare_build_dir(
|
|
self, mock_os_makedirs, mock_shutil_copy, mock_chdir, mock_open
|
|
):
|
|
"""A test which will initialize a bootstrap and will check if the
|
|
method :meth:`~pythonforandroid.bootstrap.Bootstrap.prepare_build_dir`
|
|
successfully calls the methods that we need to prepare a build dir.
|
|
"""
|
|
|
|
# prepare bootstrap
|
|
bs = Bootstrap().get_bootstrap("service_only", self.ctx)
|
|
self.ctx.bootstrap = bs
|
|
|
|
# test that prepare_build_dir runs (notice that we mock
|
|
# any file/dir creation so we can speed up the tests)
|
|
bs.prepare_build_dir()
|
|
|
|
# make sure that the open command has been called only once
|
|
mock_open.assert_called_once_with("project.properties", "w")
|
|
|
|
# check that the other mocks we made are actually called
|
|
mock_os_makedirs.assert_called()
|
|
mock_shutil_copy.assert_called()
|
|
mock_chdir.assert_called()
|
|
|
|
@mock.patch("pythonforandroid.bootstrap.os.path.isfile")
|
|
@mock.patch("pythonforandroid.bootstrap.os.path.exists")
|
|
@mock.patch("pythonforandroid.bootstrap.os.unlink")
|
|
@mock.patch("pythonforandroid.bootstrap.open", create=True)
|
|
@mock.patch("pythonforandroid.util.chdir")
|
|
@mock.patch("pythonforandroid.bootstrap.listdir")
|
|
def test_bootstrap_prepare_build_dir_with_java_src(
|
|
self,
|
|
mock_listdir,
|
|
mock_chdir,
|
|
mock_open,
|
|
mock_os_unlink,
|
|
mock_os_path_exists,
|
|
mock_os_path_isfile,
|
|
):
|
|
"""A test which will initialize a bootstrap and will check perform
|
|
another test for method
|
|
:meth:`~pythonforandroid.bootstrap.Bootstrap.prepare_build_dir`. In
|
|
here we will simulate that we have `with_java_src` set to some value.
|
|
"""
|
|
self.ctx.symlink_bootstrap_files = True
|
|
mock_listdir.return_value = [
|
|
"jnius",
|
|
"kivy",
|
|
"Kivy-1.11.0.dev0-py3.7.egg-info",
|
|
"pyjnius-1.2.1.dev0-py3.7.egg",
|
|
]
|
|
|
|
# prepare bootstrap
|
|
bs = Bootstrap().get_bootstrap("sdl2", self.ctx)
|
|
self.ctx.bootstrap = bs
|
|
|
|
# test that prepare_build_dir runs (notice that we mock
|
|
# any file/dir creation so we can speed up the tests)
|
|
bs.prepare_build_dir()
|
|
# make sure that the open command has been called only once
|
|
mock_open.assert_called_with("project.properties", "w")
|
|
|
|
# check that the other mocks we made are actually called
|
|
mock_chdir.assert_called()
|
|
mock_os_unlink.assert_called()
|
|
mock_os_path_exists.assert_called()
|
|
mock_os_path_isfile.assert_called()
|
|
|
|
|
|
class GenericBootstrapTest(BaseClassSetupBootstrap):
|
|
"""
|
|
An inherited class of `BaseClassSetupBootstrap` which will extends his
|
|
functionality by adding some generic bootstrap tests, so this way we can
|
|
test all our sub modules of :mod:`~pythonforandroid.bootstraps` from within
|
|
this module.
|
|
|
|
.. warning:: This is supposed to be used as a base class, so please, don't
|
|
use this directly.
|
|
"""
|
|
|
|
@property
|
|
def bootstrap_name(self):
|
|
"""Subclasses must have property 'bootstrap_name'. It should be the
|
|
name of the bootstrap to test"""
|
|
raise NotImplementedError("Not implemented in GenericBootstrapTest")
|
|
|
|
@mock.patch("pythonforandroid.bootstraps.service_only.open", create=True)
|
|
@mock.patch("pythonforandroid.bootstraps.webview.open", create=True)
|
|
@mock.patch("pythonforandroid.bootstraps.sdl2.open", create=True)
|
|
@mock.patch("pythonforandroid.distribution.open", create=True)
|
|
@mock.patch("pythonforandroid.bootstrap.Bootstrap.strip_libraries")
|
|
@mock.patch("pythonforandroid.util.exists")
|
|
@mock.patch("pythonforandroid.util.chdir")
|
|
@mock.patch("pythonforandroid.bootstrap.listdir")
|
|
@mock.patch("pythonforandroid.bootstrap.sh.rm")
|
|
@mock.patch("pythonforandroid.bootstrap.sh.cp")
|
|
def test_assemble_distribution(
|
|
self,
|
|
mock_sh_cp,
|
|
mock_sh_rm,
|
|
mock_listdir,
|
|
mock_chdir,
|
|
mock_ensure_dir,
|
|
mock_strip_libraries,
|
|
mock_open_dist_files,
|
|
mock_open_sdl2_files,
|
|
mock_open_webview_files,
|
|
mock_open_service_only_files,
|
|
):
|
|
"""
|
|
A test for any overwritten method of
|
|
`~pythonforandroid.bootstrap.Bootstrap.assemble_distribution`. Here we mock
|
|
any file/dir operation that it could slow down our tests, and there is
|
|
a lot to mock, because the `assemble_distribution` method it should take care
|
|
of prepare all compiled files to generate the final `apk`. The targets
|
|
of this test will be:
|
|
|
|
- :meth:`~pythonforandroid.bootstraps.sdl2.BootstrapSdl2
|
|
.assemble_distribution`
|
|
- :meth:`~pythonforandroid.bootstraps.service_only
|
|
.ServiceOnlyBootstrap.assemble_distribution`
|
|
- :meth:`~pythonforandroid.bootstraps.webview.WebViewBootstrap
|
|
.assemble_distribution`
|
|
- :meth:`~pythonforandroid.bootstraps.empty.EmptyBootstrap.
|
|
assemble_distribution`
|
|
|
|
Here we will tests all those methods that are specific for each class.
|
|
"""
|
|
# prepare bootstrap and distribution
|
|
bs = Bootstrap.get_bootstrap(self.bootstrap_name, self.ctx)
|
|
self.assertNotEqual(bs.ctx, None)
|
|
bs.build_dir = bs.get_build_dir()
|
|
self.setUp_distribution_with_bootstrap(bs)
|
|
|
|
self.ctx.hostpython = "/some/fake/hostpython3"
|
|
self.ctx.python_recipe = Recipe.get_recipe("python3", self.ctx)
|
|
self.ctx.python_recipe.create_python_bundle = mock.MagicMock()
|
|
self.ctx.python_modules = ["requests"]
|
|
self.ctx.archs = [ArchARMv7_a(self.ctx)]
|
|
self.ctx.bootstrap = bs
|
|
|
|
bs.assemble_distribution()
|
|
|
|
mock_open_dist_files.assert_called_once_with("dist_info.json", "w")
|
|
mock_open_bootstraps = {
|
|
"sdl2": mock_open_sdl2_files,
|
|
"webview": mock_open_webview_files,
|
|
"service_only": mock_open_service_only_files,
|
|
}
|
|
expected_open_calls = {
|
|
"sdl2": [
|
|
mock.call("local.properties", "w"),
|
|
mock.call("blacklist.txt", "a"),
|
|
],
|
|
"webview": [mock.call("local.properties", "w")],
|
|
"service_only": [mock.call("local.properties", "w")],
|
|
}
|
|
mock_open_bs = mock_open_bootstraps[self.bootstrap_name]
|
|
# test that the expected calls has been called
|
|
for expected_call in expected_open_calls[self.bootstrap_name]:
|
|
self.assertIn(expected_call, mock_open_bs.call_args_list)
|
|
# test that the write function has been called with the expected args
|
|
self.assertIn(
|
|
mock.call().__enter__().write("sdk.dir=/opt/android/android-sdk"),
|
|
mock_open_bs.mock_calls,
|
|
)
|
|
if self.bootstrap_name == "sdl2":
|
|
self.assertIn(
|
|
mock.call()
|
|
.__enter__()
|
|
.write("\nsqlite3/*\nlib-dynload/_sqlite3.so\n"),
|
|
mock_open_bs.mock_calls,
|
|
)
|
|
|
|
# check that the other mocks we made are actually called
|
|
mock_sh_rm.assert_called()
|
|
mock_sh_cp.assert_called()
|
|
mock_chdir.assert_called()
|
|
mock_listdir.assert_called()
|
|
mock_strip_libraries.assert_called()
|
|
expected__python_bundle = os.path.join(
|
|
self.ctx.dist_dir,
|
|
self.ctx.bootstrap.distribution.name,
|
|
f"_python_bundle__{self.TEST_ARCH}",
|
|
"_python_bundle",
|
|
)
|
|
self.assertIn(
|
|
mock.call(expected__python_bundle, self.ctx.archs[0]),
|
|
self.ctx.python_recipe.create_python_bundle.call_args_list,
|
|
)
|
|
|
|
@mock.patch("pythonforandroid.bootstrap.shprint")
|
|
@mock.patch("pythonforandroid.bootstrap.glob.glob")
|
|
@mock.patch("pythonforandroid.bootstrap.ensure_dir")
|
|
@mock.patch("pythonforandroid.build.ensure_dir")
|
|
def test_distribute_methods(
|
|
self, mock_build_dir, mock_bs_dir, mock_glob, mock_shprint
|
|
):
|
|
# prepare arch, bootstrap and distribution
|
|
arch = ArchARMv7_a(self.ctx)
|
|
bs = Bootstrap().get_bootstrap(self.bootstrap_name, self.ctx)
|
|
self.setUp_distribution_with_bootstrap(bs)
|
|
|
|
# a convenient method to reset mocks in one shot
|
|
def reset_mocks():
|
|
mock_glob.reset_mock()
|
|
mock_shprint.reset_mock()
|
|
mock_build_dir.reset_mock()
|
|
mock_bs_dir.reset_mock()
|
|
|
|
# test distribute_libs
|
|
mock_glob.return_value = [
|
|
"/fake_dir/libsqlite3.so",
|
|
"/fake_dir/libpng16.so",
|
|
]
|
|
bs.distribute_libs(arch, [self.ctx.get_libs_dir(arch.arch)])
|
|
libs_dir = os.path.join("libs", arch.arch)
|
|
# we expect two calls to glob/copy command via shprint
|
|
self.assertEqual(len(mock_glob.call_args_list), 2)
|
|
self.assertEqual(len(mock_shprint.call_args_list), 1)
|
|
self.assertEqual(
|
|
mock_shprint.call_args_list,
|
|
[mock.call(sh.cp, "-a", *mock_glob.return_value, libs_dir)]
|
|
)
|
|
mock_build_dir.assert_called()
|
|
mock_bs_dir.assert_called_once_with(libs_dir)
|
|
reset_mocks()
|
|
|
|
# test distribute_javaclasses
|
|
mock_glob.return_value = ["/fakedir/java_file.java"]
|
|
bs.distribute_javaclasses(self.ctx.javaclass_dir)
|
|
mock_glob.assert_called_once_with(self.ctx.javaclass_dir)
|
|
mock_build_dir.assert_called_with(self.ctx.javaclass_dir)
|
|
mock_bs_dir.assert_called_once_with("src")
|
|
self.assertEqual(
|
|
mock_shprint.call_args,
|
|
mock.call(sh.cp, "-a", "/fakedir/java_file.java", "src"),
|
|
)
|
|
reset_mocks()
|
|
|
|
# test distribute_aars
|
|
mock_glob.return_value = ["/fakedir/file.aar"]
|
|
bs.distribute_aars(arch)
|
|
mock_build_dir.assert_called_with(self.ctx.aars_dir)
|
|
# We expect three calls to shprint: unzip, cp, cp
|
|
zip_call, kw = mock_shprint.call_args_list[0]
|
|
self.assertEqual(zip_call[0], sh.unzip)
|
|
self.assertEqual(zip_call[2], "/fakedir/file.aar")
|
|
cp_java_call, kw = mock_shprint.call_args_list[1]
|
|
self.assertEqual(cp_java_call[0], sh.cp)
|
|
self.assertTrue(cp_java_call[2].endswith("classes.jar"))
|
|
self.assertEqual(cp_java_call[3], "libs/file.jar")
|
|
cp_libs_call, kw = mock_shprint.call_args_list[2]
|
|
self.assertEqual(cp_libs_call[0], sh.cp)
|
|
self.assertEqual(cp_libs_call[2], "/fakedir/file.aar")
|
|
self.assertEqual(cp_libs_call[3], libs_dir)
|
|
mock_bs_dir.assert_has_calls([mock.call("libs"), mock.call(libs_dir)])
|
|
mock_glob.assert_called()
|
|
|
|
@mock.patch("pythonforandroid.bootstrap.shprint")
|
|
@mock.patch("pythonforandroid.bootstrap.sh.Command")
|
|
@mock.patch("pythonforandroid.build.ensure_dir")
|
|
@mock.patch("pythonforandroid.archs.find_executable")
|
|
def test_bootstrap_strip(
|
|
self,
|
|
mock_find_executable,
|
|
mock_ensure_dir,
|
|
mock_sh_command,
|
|
mock_sh_print,
|
|
):
|
|
mock_find_executable.return_value = os.path.join(
|
|
self.ctx._ndk_dir,
|
|
f"toolchains/llvm/prebuilt/{self.ctx.ndk.host_tag}/bin/clang",
|
|
)
|
|
# prepare arch, bootstrap, distribution and PythonRecipe
|
|
arch = ArchARMv7_a(self.ctx)
|
|
bs = Bootstrap().get_bootstrap(self.bootstrap_name, self.ctx)
|
|
self.setUp_distribution_with_bootstrap(bs)
|
|
self.ctx.python_recipe = Recipe.get_recipe("python3", self.ctx)
|
|
|
|
# test that strip_libraries runs with a fake distribution
|
|
bs.strip_libraries(arch)
|
|
|
|
mock_find_executable.assert_called_once()
|
|
self.assertEqual(
|
|
mock_find_executable.call_args[0][0],
|
|
mock_find_executable.return_value,
|
|
)
|
|
mock_sh_command.assert_called_once_with(
|
|
os.path.join(
|
|
self.ctx._ndk_dir,
|
|
f"toolchains/llvm/prebuilt/{self.ctx.ndk.host_tag}/bin",
|
|
"llvm-strip",
|
|
)
|
|
)
|
|
# check that the other mocks we made are actually called
|
|
mock_ensure_dir.assert_called()
|
|
mock_sh_print.assert_called()
|
|
|
|
@mock.patch("pythonforandroid.bootstrap.listdir")
|
|
@mock.patch("pythonforandroid.bootstrap.sh.rm")
|
|
@mock.patch("pythonforandroid.bootstrap.sh.mv")
|
|
@mock.patch("pythonforandroid.bootstrap.isdir")
|
|
def test_bootstrap_fry_eggs(
|
|
self, mock_isdir, mock_sh_mv, mock_sh_rm, mock_listdir
|
|
):
|
|
mock_listdir.return_value = [
|
|
"jnius",
|
|
"kivy",
|
|
"Kivy-1.11.0.dev0-py3.7.egg-info",
|
|
"pyjnius-1.2.1.dev0-py3.7.egg",
|
|
]
|
|
|
|
# prepare bootstrap, context and distribution
|
|
bs = Bootstrap().get_bootstrap(self.bootstrap_name, self.ctx)
|
|
self.setUp_distribution_with_bootstrap(bs)
|
|
|
|
# test that fry_eggs runs with a fake distribution
|
|
site_packages = os.path.join(
|
|
bs.dist_dir, "_python_bundle", "_python_bundle"
|
|
)
|
|
bs.fry_eggs(site_packages)
|
|
|
|
mock_listdir.assert_has_calls(
|
|
[
|
|
mock.call(site_packages),
|
|
mock.call(
|
|
os.path.join(site_packages, "pyjnius-1.2.1.dev0-py3.7.egg")
|
|
),
|
|
]
|
|
)
|
|
self.assertEqual(
|
|
mock_sh_rm.call_args[0][1], "pyjnius-1.2.1.dev0-py3.7.egg"
|
|
)
|
|
# check that the other mocks we made are actually called
|
|
mock_isdir.assert_called()
|
|
mock_sh_mv.assert_called()
|
|
|
|
|
|
class TestBootstrapSdl2(GenericBootstrapTest, unittest.TestCase):
|
|
"""
|
|
An inherited class of `GenericBootstrapTest` and `unittest.TestCase` which
|
|
will be used to perform tests for
|
|
:class:`~pythonforandroid.bootstraps.sdl2.BootstrapSdl2`.
|
|
"""
|
|
|
|
@property
|
|
def bootstrap_name(self):
|
|
return "sdl2"
|
|
|
|
|
|
class TestBootstrapServiceOnly(GenericBootstrapTest, unittest.TestCase):
|
|
"""
|
|
An inherited class of `GenericBootstrapTest` and `unittest.TestCase` which
|
|
will be used to perform tests for
|
|
:class:`~pythonforandroid.bootstraps.service_only.ServiceOnlyBootstrap`.
|
|
"""
|
|
|
|
@property
|
|
def bootstrap_name(self):
|
|
return "service_only"
|
|
|
|
|
|
class TestBootstrapWebview(GenericBootstrapTest, unittest.TestCase):
|
|
"""
|
|
An inherited class of `GenericBootstrapTest` and `unittest.TestCase` which
|
|
will be used to perform tests for
|
|
:class:`~pythonforandroid.bootstraps.webview.WebViewBootstrap`.
|
|
"""
|
|
|
|
@property
|
|
def bootstrap_name(self):
|
|
return "webview"
|
|
|
|
|
|
class TestBootstrapEmpty(GenericBootstrapTest, unittest.TestCase):
|
|
"""
|
|
An inherited class of `GenericBootstrapTest` and `unittest.TestCase` which
|
|
will be used to perform tests for
|
|
:class:`~pythonforandroid.bootstraps.empty.EmptyBootstrap`.
|
|
|
|
.. note:: here will test most of the base class methods, because we only
|
|
overwrite :meth:`~pythonforandroid.bootstraps.empty.
|
|
EmptyBootstrap.assemble_distribution`
|
|
"""
|
|
|
|
@property
|
|
def bootstrap_name(self):
|
|
return "empty"
|
|
|
|
def test_assemble_distribution(self, *args):
|
|
# prepare bootstrap
|
|
bs = Bootstrap().get_bootstrap(self.bootstrap_name, self.ctx)
|
|
self.ctx.bootstrap = bs
|
|
|
|
# test dist_dir error
|
|
with self.assertRaises(SystemExit) as e:
|
|
bs.assemble_distribution()
|
|
self.assertEqual(e.exception.args[0], 1)
|