|
6 | 6 | from backports import tempfile
|
7 | 7 | from pythonforandroid.build import Context
|
8 | 8 | from pythonforandroid.recipe import Recipe, import_recipe
|
| 9 | +from pythonforandroid.archs import ArchAarch_64 |
| 10 | +from pythonforandroid.bootstrap import Bootstrap |
| 11 | +from test_bootstrap import BaseClassSetupBootstrap |
9 | 12 |
|
10 | 13 |
|
11 | 14 | def patch_logger(level):
|
@@ -122,3 +125,120 @@ def test_download(self):
|
122 | 125 | 'Downloading test_recipe from '
|
123 | 126 | 'https://www.python.org/ftp/python/3.7.4/Python-3.7.4.tgz')]
|
124 | 127 | assert m_touch.call_count == 1
|
| 128 | + |
| 129 | + |
| 130 | +class TesSTLRecipe(BaseClassSetupBootstrap, unittest.TestCase): |
| 131 | + def setUp(self): |
| 132 | + """ |
| 133 | + Initialize a Context with a Bootstrap and a Distribution to properly |
| 134 | + test a recipe which depends on android's STL library, to do so we reuse |
| 135 | + `BaseClassSetupBootstrap` |
| 136 | + """ |
| 137 | + super(TesSTLRecipe, self).setUp() |
| 138 | + self.ctx.bootstrap = Bootstrap().get_bootstrap('sdl2', self.ctx) |
| 139 | + self.setUp_distribution_with_bootstrap(self.ctx.bootstrap) |
| 140 | + self.ctx.python_recipe = Recipe.get_recipe('python3', self.ctx) |
| 141 | + |
| 142 | + def test_get_stl_lib_dir(self): |
| 143 | + """ |
| 144 | + Test that :meth:`~pythonforandroid.recipe.STLRecipe.get_stl_lib_dir` |
| 145 | + returns the expected path for the stl library |
| 146 | + """ |
| 147 | + arch = ArchAarch_64(self.ctx) |
| 148 | + recipe = Recipe.get_recipe('icu', self.ctx) |
| 149 | + self.assertTrue(recipe.need_stl_shared) |
| 150 | + self.assertEqual( |
| 151 | + recipe.get_stl_lib_dir(arch), |
| 152 | + os.path.join( |
| 153 | + self.ctx.ndk_dir, |
| 154 | + 'sources/cxx-stl/llvm-libc++/libs/{arch}'.format( |
| 155 | + arch=arch.arch |
| 156 | + ), |
| 157 | + ), |
| 158 | + ) |
| 159 | + |
| 160 | + @mock.patch('pythonforandroid.archs.find_executable') |
| 161 | + @mock.patch('pythonforandroid.build.ensure_dir') |
| 162 | + def test_get_recipe_env_with( |
| 163 | + self, mock_ensure_dir, mock_find_executable |
| 164 | + ): |
| 165 | + """ |
| 166 | + Test that :meth:`~pythonforandroid.recipe.STLRecipe.get_recipe_env` |
| 167 | + returns some expected keys and values. |
| 168 | +
|
| 169 | + .. note:: We don't check all the env variables, only those one specific |
| 170 | + of :class:`~pythonforandroid.recipe.STLRecipe`, the others |
| 171 | + should be tested in the proper test. |
| 172 | + """ |
| 173 | + expected_compiler = 'aarch64-linux-android-gcc' |
| 174 | + mock_find_executable.return_value = expected_compiler |
| 175 | + mock_ensure_dir.return_value = True |
| 176 | + |
| 177 | + arch = ArchAarch_64(self.ctx) |
| 178 | + recipe = Recipe.get_recipe('icu', self.ctx) |
| 179 | + assert recipe.need_stl_shared, True |
| 180 | + env = recipe.get_recipe_env(arch) |
| 181 | + # check `find_executable` calls |
| 182 | + mock_find_executable.assert_called_once_with( |
| 183 | + expected_compiler, path=os.environ['PATH'] |
| 184 | + ) |
| 185 | + self.assertIsInstance(env, dict) |
| 186 | + |
| 187 | + # check `CPPFLAGS` |
| 188 | + expected_cppflags = { |
| 189 | + '-I{stl_include}'.format(stl_include=recipe.stl_include_dir) |
| 190 | + } |
| 191 | + self.assertIn('CPPFLAGS', env) |
| 192 | + for flags in expected_cppflags: |
| 193 | + self.assertIn(flags, env['CPPFLAGS']) |
| 194 | + |
| 195 | + # check `LIBS` |
| 196 | + self.assertIn('LDFLAGS', env) |
| 197 | + self.assertIn('-L' + recipe.get_stl_lib_dir(arch), env['LDFLAGS']) |
| 198 | + self.assertIn('LIBS', env) |
| 199 | + self.assertIn('-lc++_shared', env['LIBS']) |
| 200 | + |
| 201 | + # check `CXXFLAGS` and `CXX` |
| 202 | + for flag in {'CXXFLAGS', 'CXX'}: |
| 203 | + self.assertIn(flag, env) |
| 204 | + self.assertIn('-frtti -fexceptions', env[flag]) |
| 205 | + |
| 206 | + @mock.patch('pythonforandroid.recipe.Recipe.install_libs') |
| 207 | + @mock.patch('pythonforandroid.recipe.isfile') |
| 208 | + @mock.patch('pythonforandroid.build.ensure_dir') |
| 209 | + def test_install_stl_lib( |
| 210 | + self, mock_ensure_dir, mock_isfile, mock_install_lib |
| 211 | + ): |
| 212 | + """ |
| 213 | + Test that :meth:`~pythonforandroid.recipe.STLRecipe.install_stl_lib`, |
| 214 | + calls the method :meth:`~pythonforandroid.recipe.Recipe.install_libs` |
| 215 | + with the proper arguments: a subclass of |
| 216 | + :class:`~pythonforandroid.archs.Arch` and our stl lib |
| 217 | + (:attr:`~pythonforandroid.recipe.STLRecipe.stl_lib_name`) |
| 218 | + """ |
| 219 | + mock_ensure_dir.return_value = True |
| 220 | + mock_isfile.return_value = False |
| 221 | + mock_install_lib.return_value = True |
| 222 | + |
| 223 | + arch = ArchAarch_64(self.ctx) |
| 224 | + recipe = Recipe.get_recipe('icu', self.ctx) |
| 225 | + recipe.ctx = self.ctx |
| 226 | + assert recipe.need_stl_shared, True |
| 227 | + recipe.install_stl_lib(arch) |
| 228 | + mock_install_lib.assert_called_once_with( |
| 229 | + arch, |
| 230 | + '{ndk_dir}/sources/cxx-stl/llvm-libc++/' |
| 231 | + 'libs/{arch}/lib{stl_lib}.so'.format( |
| 232 | + ndk_dir=self.ctx.ndk_dir, |
| 233 | + arch=arch.arch, |
| 234 | + stl_lib=recipe.stl_lib_name, |
| 235 | + ), |
| 236 | + ) |
| 237 | + |
| 238 | + @mock.patch('pythonforandroid.recipe.Recipe.install_stl_lib') |
| 239 | + def test_postarch_build(self, mock_install_stl_lib): |
| 240 | + arch = ArchAarch_64(self.ctx) |
| 241 | + recipe = Recipe.get_recipe('icu', self.ctx) |
| 242 | + assert recipe.need_stl_shared, True |
| 243 | + recipe.postbuild_arch(arch) |
| 244 | + mock_install_stl_lib.assert_called_once_with(arch) |
0 commit comments