import os import unittest from unittest import mock import jinja2 from pythonforandroid.build import ( Context, RECOMMENDED_TARGET_API, run_pymodules_install, ) from pythonforandroid.archs import ArchARMv7_a, ArchAarch_64 class TestBuildBasic(unittest.TestCase): def test_run_pymodules_install_optional_project_dir(self): """ Makes sure the `run_pymodules_install()` doesn't crash when the `project_dir` optional parameter is None, refs #1898 """ ctx = mock.Mock() ctx.archs = [ArchARMv7_a(ctx), ArchAarch_64(ctx)] modules = [] project_dir = None with mock.patch('pythonforandroid.build.info') as m_info: assert run_pymodules_install(ctx, ctx.archs[0], modules, project_dir) is None assert m_info.call_args_list[-1] == mock.call( 'No Python modules and no setup.py to process, skipping') def test_strip_if_with_debug_symbols(self): ctx = mock.Mock() ctx.python_recipe.major_minor_version_string = "python3.6" ctx.get_site_packages_dir.return_value = "test-doesntexist" ctx.build_dir = "nonexistant_directory" ctx.archs = ["arm64"] modules = ["mymodule"] project_dir = None with mock.patch('pythonforandroid.build.info'), \ mock.patch('sh.Command'),\ mock.patch('pythonforandroid.build.open'),\ mock.patch('pythonforandroid.build.shprint'),\ mock.patch('pythonforandroid.build.current_directory'),\ mock.patch('pythonforandroid.build.CythonRecipe') as m_CythonRecipe, \ mock.patch('pythonforandroid.build.project_has_setup_py') as m_project_has_setup_py, \ mock.patch('pythonforandroid.build.run_setuppy_install'): m_project_has_setup_py.return_value = False # Make sure it is NOT called when `with_debug_symbols` is true: ctx.with_debug_symbols = True assert run_pymodules_install(ctx, ctx.archs[0], modules, project_dir) is None assert m_CythonRecipe().strip_object_files.called is False # Make sure strip object files IS called when # `with_debug_symbols` is fasle: ctx.with_debug_symbols = False assert run_pymodules_install(ctx, ctx.archs[0], modules, project_dir) is None assert m_CythonRecipe().strip_object_files.called is True class TestTemplates(unittest.TestCase): def test_android_manifest_xml(self): args = mock.Mock() args.min_sdk_version = 12 args.build_mode = 'debug' args.native_services = ['abcd', ] args.permissions = [] args.add_activity = [] args.android_used_libs = [] args.meta_data = [] args.extra_manifest_xml = '' args.extra_manifest_application_arguments = 'android:someParameter="true" android:anotherParameter="false"' render_args = { "args": args, "service": False, "service_names": [], "android_api": 1234, "debug": "debug" in args.build_mode, "native_services": args.native_services } environment = jinja2.Environment( loader=jinja2.FileSystemLoader('pythonforandroid/bootstraps/sdl2/build/templates/') ) template = environment.get_template('AndroidManifest.tmpl.xml') xml = template.render(**render_args) assert xml.count('android:minSdkVersion="12"') == 1 assert xml.count('android:anotherParameter="false"') == 1 assert xml.count('android:someParameter="true"') == 1 assert xml.count('') == 1 assert xml.count('android:process=":service_') == 0 assert xml.count('targetSdkVersion="1234"') == 1 assert xml.count('android:debuggable="true"') == 1 assert xml.count('') == 1 # TODO: potentially some other checks to be added here to cover other "logic" (flags and loops) in the template class TestContext(unittest.TestCase): @mock.patch.dict('pythonforandroid.build.Context.env') @mock.patch('pythonforandroid.build.get_available_apis') @mock.patch('pythonforandroid.build.ensure_dir') def test_sdk_ndk_paths( self, mock_ensure_dir, mock_get_available_apis, ): mock_get_available_apis.return_value = [RECOMMENDED_TARGET_API] context = Context() context.setup_dirs(os.getcwd()) context.prepare_build_environment( user_sdk_dir='sdk', user_ndk_dir='ndk', user_android_api=None, user_ndk_api=None, ) # The context was supplied with relative SDK and NDK dirs. Check # that it resolved them to absolute paths. real_sdk_dir = os.path.join(os.getcwd(), 'sdk') real_ndk_dir = os.path.join(os.getcwd(), 'ndk') assert context.sdk_dir == real_sdk_dir assert context.ndk_dir == real_ndk_dir context_paths = context.env['PATH'].split(':') assert context_paths[0:3] == [ f'{real_ndk_dir}/toolchains/llvm/prebuilt/{context.ndk.host_tag}/bin', real_ndk_dir, f'{real_sdk_dir}/tools' ]