def __init__(self): super(Context, self).__init__() self.include_dirs = [] self._build_env_prepared = False self._sdk_dir = None self._ndk_dir = None self._android_api = None self._ndk_api = None self.ndk = None self.toolchain_prefix = None self.toolchain_version = None self.local_recipes = None self.copy_libs = False # this list should contain all Archs, it is pruned later self.archs = ( ArchARM(self), ArchARMv7_a(self), Archx86(self), Archx86_64(self), ArchAarch_64(self), ) self.root_dir = realpath(dirname(__file__)) # remove the most obvious flags that can break the compilation self.env.pop("LDFLAGS", None) self.env.pop("ARCHFLAGS", None) self.env.pop("CFLAGS", None) self.python_recipe = None # Set by TargetPythonRecipe
def test_bootstrap_strip( self, mock_find_executable, mock_ensure_dir, mock_sh_command, mock_sh_print, ): mock_find_executable.return_value = "arm-linux-androideabi-gcc" # 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("arm-linux-androideabi-strip") # check that the other mocks we made are actually called mock_ensure_dir.assert_called() mock_sh_print.assert_called()
def test_bootstrap_strip( self, mock_find_executable, mock_glob, 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/{system().lower()}-x86_64/bin/clang", ) mock_glob.return_value = [ os.path.join(self.ctx._ndk_dir, "toolchains", "llvm") ] # 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("arm-linux-androideabi-strip") # check that the other mocks we made are actually called mock_ensure_dir.assert_called() mock_sh_print.assert_called()
def __init__(self): super(Context, self).__init__() self.include_dirs = [] self._build_env_prepared = False self._sdk_dir = None self._ndk_dir = None self._android_api = None self._ndk_ver = None self.toolchain_prefix = None self.toolchain_version = None self.local_recipes = None # root of the toolchain self.setup_dirs() # this list should contain all Archs, it is pruned later self.archs = (ArchARM(self), ArchARMv7_a(self), Archx86(self)) ensure_dir(join(self.build_dir, 'bootstrap_builds')) ensure_dir(join(self.build_dir, 'other_builds')) # other_builds: where everything else is built # remove the most obvious flags that can break the compilation self.env.pop("LDFLAGS", None) self.env.pop("ARCHFLAGS", None) self.env.pop("CFLAGS", None)
def test_arch_armv7a(self, mock_ensure_dir, mock_find_executable, mock_glob): """ Test that class :class:`~pythonforandroid.archs.ArchARMv7_a` returns some expected attributes and environment variables. .. note:: Here we mock the same functions than :meth:`TestArchARM.test_arch_arm` plus `glob`, so we make sure that the glob result is the expected even if the folder doesn't exist, which is probably the case. This has to be done because here we tests the `get_env` with clang """ mock_find_executable.return_value = self.expected_compiler mock_ensure_dir.return_value = True mock_glob.return_value = ["llvm"] arch = ArchARMv7_a(self.ctx) self.assertEqual(arch.arch, "armeabi-v7a") self.assertEqual(arch.__str__(), "armeabi-v7a") self.assertEqual(arch.toolchain_prefix, "arm-linux-androideabi") self.assertEqual(arch.command_prefix, "arm-linux-androideabi") self.assertEqual(arch.target, "armv7a-linux-androideabi21") self.assertEqual(arch.platform_dir, "arch-arm") env = arch.get_env() # check glob and find_executable calls self.assertEqual(mock_glob.call_count, 4) for glob_call, kw in mock_glob.call_args_list: self.assertEqual( glob_call[0], "{ndk_dir}/toolchains/llvm*".format(ndk_dir=self.ctx._ndk_dir), ) mock_find_executable.assert_called_once_with(self.expected_compiler, path=environ["PATH"]) # check clang build_platform = "{system}-{machine}".format( system=os.uname()[0], machine=os.uname()[-1]).lower() self.assertEqual( env["CC"].split()[0], "{ndk_dir}/toolchains/llvm/prebuilt/" "{build_platform}/bin/clang".format(ndk_dir=self.ctx._ndk_dir, build_platform=build_platform), ) self.assertEqual( env["CXX"].split()[0], "{ndk_dir}/toolchains/llvm/prebuilt/" "{build_platform}/bin/clang++".format( ndk_dir=self.ctx._ndk_dir, build_platform=build_platform), ) # For armeabi-v7a we expect some extra cflags self.assertIn( " -march=armv7-a -mfloat-abi=softfp -mfpu=vfp -mthumb", env["CFLAGS"], )
def setUp(self): """ Setups recipe and context. """ self.context = Context() self.context.ndk_api = 21 self.context.android_api = 27 self.arch = ArchARMv7_a(self.context) self.recipe = Recipe.get_recipe('gevent', self.context)
def setUp(self): """ Setups recipe and context. """ self.context = Context() self.arch = ArchARMv7_a(self.context) self.recipe = Recipe.get_recipe('reportlab', self.context) self.recipe.ctx = self.context self.bootstrap = None recipe_build_order, python_modules, bootstrap = \ get_recipe_order_and_bootstrap( self.context, [self.recipe.name], self.bootstrap) self.context.recipe_build_order = recipe_build_order self.context.python_modules = python_modules self.context.setup_dirs(tempfile.gettempdir()) self.bootstrap = bootstrap self.recipe_dir = self.recipe.get_build_dir(self.arch.arch) ensure_dir(self.recipe_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), 2) for i, lib in enumerate(mock_glob.return_value): self.assertEqual( mock_shprint.call_args_list[i], mock.call(sh.cp, "-a", lib, 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()
def test_run_distribute( self, mock_sh_cp, mock_sh_rm, mock_listdir, mock_chdir, mock_ensure_dir, mock_strip_libraries, mock_create_python_bundle, 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.run_distribute`. Here we mock any file/dir operation that it could slow down our tests, and there is a lot to mock, because the `run_distribute` 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 .run_distribute` - :meth:`~pythonforandroid.bootstraps.service_only .ServiceOnlyBootstrap.run_distribute` - :meth:`~pythonforandroid.bootstraps.webview.WebViewBootstrap .run_distribute` - :meth:`~pythonforandroid.bootstraps.empty.EmptyBootstrap. run_distribute` 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) 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_modules = ["requests"] self.ctx.archs = [ArchARMv7_a(self.ctx)] bs.run_distribute() 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() mock_create_python_bundle.assert_called()