diff --git a/tests/test_common.py b/tests/test_common.py index 293d69ec..51d9a02a 100755 --- a/tests/test_common.py +++ b/tests/test_common.py @@ -4,7 +4,6 @@ import difflib import git import glob import importlib -import inspect import json import logging import os @@ -29,7 +28,7 @@ import fdroidserver import fdroidserver.signindex import fdroidserver.common import fdroidserver.metadata -from .shared_test_code import TmpCwd, mkdtemp +from .shared_test_code import TmpCwd, mkdtemp, mkdir_testfiles from fdroidserver.common import ANTIFEATURES_CONFIG_NAME, CATEGORIES_CONFIG_NAME from fdroidserver._yaml import yaml, yaml_dumper, config_dump from fdroidserver.exception import FDroidException, VCSException,\ @@ -53,9 +52,6 @@ class SetUpTearDownMixin: logging.basicConfig(level=logging.DEBUG) logger = logging.getLogger('androguard.axml') logger.setLevel(logging.INFO) # tame the axml debug messages - self.tmpdir = os.path.abspath(os.path.join(basedir, '..', '.testfiles')) - if not os.path.exists(self.tmpdir): - os.makedirs(self.tmpdir) os.chdir(basedir) self.verbose = '-v' in sys.argv or '--verbose' in sys.argv @@ -66,16 +62,14 @@ class SetUpTearDownMixin: fdroidserver.common.options = None fdroidserver.metadata.srclibs = None - self._td = mkdtemp() - self.testdir = self._td.name + self.testdir = mkdir_testfiles(basedir, self) def tearDown(self): fdroidserver.common.config = None fdroidserver.common.options = None os.chdir(basedir) - self._td.cleanup() - if os.path.exists(self.tmpdir): - shutil.rmtree(self.tmpdir) + if os.path.exists(self.testdir): + shutil.rmtree(self.testdir) class CommonTest(SetUpTearDownMixin, unittest.TestCase): @@ -178,7 +172,7 @@ class CommonTest(SetUpTearDownMixin, unittest.TestCase): print('no build-tools found: ' + build_tools) def test_find_java_root_path(self): - os.chdir(self.tmpdir) + os.chdir(self.testdir) all_pathlists = [ ( @@ -310,11 +304,11 @@ class CommonTest(SetUpTearDownMixin, unittest.TestCase): shutil.copytree( os.path.join(basedir, 'source-files'), - os.path.join(self.tmpdir, 'source-files'), + os.path.join(self.testdir, 'source-files'), ) fdroidclient_testdir = os.path.join( - self.tmpdir, 'source-files', 'fdroid', 'fdroidclient' + self.testdir, 'source-files', 'fdroid', 'fdroidclient' ) config = dict() @@ -425,7 +419,7 @@ class CommonTest(SetUpTearDownMixin, unittest.TestCase): def test_prepare_sources_refresh(self): _mock_common_module_options_instance() packageName = 'org.fdroid.ci.test.app' - os.chdir(self.tmpdir) + os.chdir(self.testdir) os.mkdir('build') os.mkdir('metadata') @@ -443,7 +437,7 @@ class CommonTest(SetUpTearDownMixin, unittest.TestCase): with open(os.path.join('metadata', packageName + '.yml'), 'w') as fp: yaml_dumper.dump(metadata, fp) - gitrepo = os.path.join(self.tmpdir, 'build', packageName) + gitrepo = os.path.join(self.testdir, 'build', packageName) vcs0 = fdroidserver.common.getvcs('git', git_url, gitrepo) vcs0.gotorevision('0.3', refresh=True) vcs1 = fdroidserver.common.getvcs('git', git_url, gitrepo) @@ -512,18 +506,15 @@ class CommonTest(SetUpTearDownMixin, unittest.TestCase): fdroidserver.signindex.config = config sourcedir = os.path.join(basedir, 'signindex') - with tempfile.TemporaryDirectory( - prefix=inspect.currentframe().f_code.co_name, dir=self.tmpdir - ) as testsdir: - for f in ('testy.jar', 'guardianproject.jar'): - sourcefile = os.path.join(sourcedir, f) - testfile = os.path.join(testsdir, f) - shutil.copy(sourcefile, testsdir) - fdroidserver.signindex.sign_jar(testfile, use_old_algs=True) - # these should be resigned, and therefore different - self.assertNotEqual( - open(sourcefile, 'rb').read(), open(testfile, 'rb').read() - ) + for f in ('testy.jar', 'guardianproject.jar'): + sourcefile = os.path.join(sourcedir, f) + testfile = os.path.join(self.testdir, f) + shutil.copy(sourcefile, self.testdir) + fdroidserver.signindex.sign_jar(testfile, use_old_algs=True) + # these should be resigned, and therefore different + self.assertNotEqual( + open(sourcefile, 'rb').read(), open(testfile, 'rb').read() + ) def test_verify_apk_signature(self): _mock_common_module_options_instance() @@ -622,7 +613,7 @@ class CommonTest(SetUpTearDownMixin, unittest.TestCase): shutil.copy(sourceapk, copyapk) self.assertTrue(fdroidserver.common.verify_apk_signature(copyapk)) self.assertIsNone( - fdroidserver.common.verify_apks(sourceapk, copyapk, self.tmpdir) + fdroidserver.common.verify_apks(sourceapk, copyapk, self.testdir) ) unsignedapk = os.path.join(self.testdir, 'urzip-unsigned.apk') @@ -632,7 +623,7 @@ class CommonTest(SetUpTearDownMixin, unittest.TestCase): if not info.filename.startswith('META-INF/'): testapk.writestr(info, apk.read(info.filename)) self.assertIsNone( - fdroidserver.common.verify_apks(sourceapk, unsignedapk, self.tmpdir) + fdroidserver.common.verify_apks(sourceapk, unsignedapk, self.testdir) ) twosigapk = os.path.join(self.testdir, 'urzip-twosig.apk') @@ -645,7 +636,7 @@ class CommonTest(SetUpTearDownMixin, unittest.TestCase): testapk.writestr(info.filename, otherapk.read(info.filename)) otherapk.close() self.assertFalse(fdroidserver.common.verify_apk_signature(twosigapk)) - self.assertIsNone(fdroidserver.common.verify_apks(sourceapk, twosigapk, self.tmpdir)) + self.assertIsNone(fdroidserver.common.verify_apks(sourceapk, twosigapk, self.testdir)) def test_get_certificate_with_chain_sandisk(self): """Test that APK signatures with a cert chain are parsed like apksigner. @@ -825,14 +816,14 @@ class CommonTest(SetUpTearDownMixin, unittest.TestCase): def test_find_apksigner_config_overrides(self): """apksigner should come from config before any auto-detection""" - os.chdir(self.tmpdir) - android_home = os.path.join(self.tmpdir, 'ANDROID_HOME') + os.chdir(self.testdir) + android_home = os.path.join(self.testdir, 'ANDROID_HOME') do_not_use = os.path.join(android_home, 'build-tools', '30.0.3', 'apksigner') os.makedirs(os.path.dirname(do_not_use)) with open(do_not_use, 'w') as fp: fp.write('#!/bin/sh\ndate\n') os.chmod(do_not_use, 0o0755) # nosec B103 - apksigner = os.path.join(self.tmpdir, 'apksigner') + apksigner = os.path.join(self.testdir, 'apksigner') config = {'apksigner': apksigner} with mock.patch.dict(os.environ, clear=True): os.environ['ANDROID_HOME'] = android_home @@ -842,13 +833,13 @@ class CommonTest(SetUpTearDownMixin, unittest.TestCase): def test_find_apksigner_prefer_path(self): """apksigner should come from PATH before ANDROID_HOME""" - os.chdir(self.tmpdir) - apksigner = os.path.join(self.tmpdir, 'apksigner') + os.chdir(self.testdir) + apksigner = os.path.join(self.testdir, 'apksigner') with open(apksigner, 'w') as fp: fp.write('#!/bin/sh\ndate\n') os.chmod(apksigner, 0o0755) # nosec B103 - android_home = os.path.join(self.tmpdir, 'ANDROID_HOME') + android_home = os.path.join(self.testdir, 'ANDROID_HOME') do_not_use = os.path.join(android_home, 'build-tools', '30.0.3', 'apksigner') os.makedirs(os.path.dirname(do_not_use)) with open(do_not_use, 'w') as fp: @@ -864,8 +855,8 @@ class CommonTest(SetUpTearDownMixin, unittest.TestCase): def test_find_apksigner_prefer_newest(self): """apksigner should be the newest available in ANDROID_HOME""" - os.chdir(self.tmpdir) - android_home = os.path.join(self.tmpdir, 'ANDROID_HOME') + os.chdir(self.testdir) + android_home = os.path.join(self.testdir, 'ANDROID_HOME') apksigner = os.path.join(android_home, 'build-tools', '30.0.3', 'apksigner') os.makedirs(os.path.dirname(apksigner)) @@ -887,7 +878,7 @@ class CommonTest(SetUpTearDownMixin, unittest.TestCase): def test_find_apksigner_system_package_android_home(self): """Test that apksigner v30 or newer is found""" - os.chdir(self.tmpdir) + os.chdir(self.testdir) android_home = os.getenv('ANDROID_HOME') if not android_home or not os.path.isdir(android_home): self.skipTest('SKIPPING since ANDROID_HOME (%s) is not a dir!' % android_home) @@ -1049,7 +1040,7 @@ class CommonTest(SetUpTearDownMixin, unittest.TestCase): fdroidserver.common.config = config fdroidserver.signindex.config = config - os.chdir(self.tmpdir) + os.chdir(self.testdir) os.mkdir('unsigned') os.mkdir('repo') @@ -1129,8 +1120,8 @@ class CommonTest(SetUpTearDownMixin, unittest.TestCase): """get_apk_id should never return None on error, only raise exceptions""" with self.assertRaises(KeyError): fdroidserver.common.get_apk_id('Norway_bouvet_europe_2.obf.zip') - shutil.copy('Norway_bouvet_europe_2.obf.zip', self.tmpdir) - os.chdir(self.tmpdir) + shutil.copy('Norway_bouvet_europe_2.obf.zip', self.testdir) + os.chdir(self.testdir) with ZipFile('Norway_bouvet_europe_2.obf.zip', 'a') as zipfp: zipfp.writestr('AndroidManifest.xml', 'not a manifest') with self.assertRaises(KeyError): @@ -1147,7 +1138,7 @@ class CommonTest(SetUpTearDownMixin, unittest.TestCase): ) def test_get_apk_id_bad_zip(self): - os.chdir(self.tmpdir) + os.chdir(self.testdir) badzip = 'badzip.apk' with open(badzip, 'w') as fp: fp.write('not a ZIP') @@ -1563,9 +1554,9 @@ class CommonTest(SetUpTearDownMixin, unittest.TestCase): def test_remove_signing_keys(self): shutil.copytree( os.path.join(basedir, 'source-files'), - os.path.join(self.tmpdir, 'source-files'), + os.path.join(self.testdir, 'source-files'), ) - os.chdir(self.tmpdir) + os.chdir(self.testdir) with_signingConfigs = [ 'source-files/com.seafile.seadroid2/app/build.gradle', 'source-files/eu.siacs.conversations/build.gradle', @@ -1734,11 +1725,11 @@ class CommonTest(SetUpTearDownMixin, unittest.TestCase): self.assertEqual(f.read(), mocklogcontent) def test_deploy_status_json(self): - os.chdir(self.tmpdir) + os.chdir(self.testdir) fakesubcommand = 'fakesubcommand' fake_timestamp = 1234567890 fakeserver = 'example.com:/var/www/fbot/' - expected_dir = os.path.join(self.tmpdir, fakeserver.replace(':', ''), 'repo', 'status') + expected_dir = os.path.join(self.testdir, fakeserver.replace(':', ''), 'repo', 'status') fdroidserver.common.options = mock.Mock() fdroidserver.common.config = {} @@ -1746,7 +1737,7 @@ class CommonTest(SetUpTearDownMixin, unittest.TestCase): fdroidserver.common.config['identity_file'] = 'ssh/id_rsa' def assert_subprocess_call(cmd): - dest_path = os.path.join(self.tmpdir, cmd[-1].replace(':', '')) + dest_path = os.path.join(self.testdir, cmd[-1].replace(':', '')) if not os.path.exists(dest_path): os.makedirs(dest_path) return subprocess.run(cmd[:-1] + [dest_path]).returncode @@ -1902,14 +1893,14 @@ class CommonTest(SetUpTearDownMixin, unittest.TestCase): def test_with_no_config(self): """It should set defaults if no config file is found""" - os.chdir(self.tmpdir) + os.chdir(self.testdir) self.assertFalse(os.path.exists(fdroidserver.common.CONFIG_FILE)) config = fdroidserver.common.read_config() self.assertIsNotNone(config.get('char_limits')) def test_with_zero_size_config(self): """It should set defaults if config file has nothing in it""" - os.chdir(self.tmpdir) + os.chdir(self.testdir) fdroidserver.common.write_config_file('') self.assertTrue(os.path.exists(fdroidserver.common.CONFIG_FILE)) config = fdroidserver.common.read_config() @@ -1917,7 +1908,7 @@ class CommonTest(SetUpTearDownMixin, unittest.TestCase): def test_with_config_yml(self): """Make sure it is possible to use config.yml alone.""" - os.chdir(self.tmpdir) + os.chdir(self.testdir) fdroidserver.common.write_config_file('apksigner: yml') self.assertTrue(os.path.exists(fdroidserver.common.CONFIG_FILE)) config = fdroidserver.common.read_config() @@ -1925,7 +1916,7 @@ class CommonTest(SetUpTearDownMixin, unittest.TestCase): def test_with_config_yml_utf8(self): """Make sure it is possible to use config.yml in UTF-8 encoding.""" - os.chdir(self.tmpdir) + os.chdir(self.testdir) teststr = '/πÇÇ现代通用字-български-عربي1/ö/yml' fdroidserver.common.write_config_file('apksigner: ' + teststr) self.assertTrue(os.path.exists(fdroidserver.common.CONFIG_FILE)) @@ -1934,7 +1925,7 @@ class CommonTest(SetUpTearDownMixin, unittest.TestCase): def test_with_config_yml_utf8_as_ascii(self): """Make sure it is possible to use config.yml Unicode encoded as ASCII.""" - os.chdir(self.tmpdir) + os.chdir(self.testdir) teststr = '/πÇÇ现代通用字-български-عربي1/ö/yml' with open(fdroidserver.common.CONFIG_FILE, 'w', encoding='utf-8') as fp: config_dump({'apksigner': teststr}, fp) @@ -1944,7 +1935,7 @@ class CommonTest(SetUpTearDownMixin, unittest.TestCase): def test_with_config_yml_with_env_var(self): """Make sure it is possible to use config.yml alone.""" - os.chdir(self.tmpdir) + os.chdir(self.testdir) with mock.patch.dict(os.environ): os.environ['SECRET'] = 'mysecretpassword' # nosec B105 fdroidserver.common.write_config_file("""keypass: {'env': 'SECRET'}\n""") @@ -1953,20 +1944,20 @@ class CommonTest(SetUpTearDownMixin, unittest.TestCase): self.assertEqual(os.getenv('SECRET', 'fail'), config.get('keypass')) def test_with_config_yml_is_dict(self): - os.chdir(self.tmpdir) + os.chdir(self.testdir) Path(fdroidserver.common.CONFIG_FILE).write_text('apksigner = /bin/apksigner') with self.assertRaises(TypeError): fdroidserver.common.read_config() def test_with_config_yml_is_not_mixed_type(self): - os.chdir(self.tmpdir) + os.chdir(self.testdir) Path(fdroidserver.common.CONFIG_FILE).write_text('k: v\napksigner = /bin/apk') with self.assertRaises(ruamel.yaml.scanner.ScannerError): fdroidserver.common.read_config() def test_config_repo_url(self): """repo_url ends in /repo, archive_url ends in /archive.""" - os.chdir(self.tmpdir) + os.chdir(self.testdir) fdroidserver.common.write_config_file( textwrap.dedent( """\ @@ -1985,34 +1976,34 @@ class CommonTest(SetUpTearDownMixin, unittest.TestCase): def test_config_repo_url_extra_slash(self): """repo_url ends in /repo, archive_url ends in /archive.""" - os.chdir(self.tmpdir) + os.chdir(self.testdir) fdroidserver.common.write_config_file('repo_url: https://MyFirstFDroidRepo.org/fdroid/repo/') with self.assertRaises(FDroidException): fdroidserver.common.read_config() def test_config_repo_url_not_repo(self): """repo_url ends in /repo, archive_url ends in /archive.""" - os.chdir(self.tmpdir) + os.chdir(self.testdir) fdroidserver.common.write_config_file('repo_url: https://MyFirstFDroidRepo.org/fdroid/foo') with self.assertRaises(FDroidException): fdroidserver.common.read_config() def test_config_archive_url_extra_slash(self): """repo_url ends in /repo, archive_url ends in /archive.""" - os.chdir(self.tmpdir) + os.chdir(self.testdir) fdroidserver.common.write_config_file('archive_url: https://MyFirstFDroidRepo.org/fdroid/archive/') with self.assertRaises(FDroidException): fdroidserver.common.read_config() def test_config_archive_url_not_repo(self): """repo_url ends in /repo, archive_url ends in /archive.""" - os.chdir(self.tmpdir) + os.chdir(self.testdir) fdroidserver.common.write_config_file('archive_url: https://MyFirstFDroidRepo.org/fdroid/foo') with self.assertRaises(FDroidException): fdroidserver.common.read_config() def test_write_to_config_yml(self): - os.chdir(self.tmpdir) + os.chdir(self.testdir) fdroidserver.common.write_config_file('apksigner: yml') os.chmod(fdroidserver.common.CONFIG_FILE, 0o0600) self.assertTrue(os.path.exists(fdroidserver.common.CONFIG_FILE)) @@ -2025,7 +2016,7 @@ class CommonTest(SetUpTearDownMixin, unittest.TestCase): self.assertEqual('mysecretpassword', config['keypass']) def test_config_dict_with_int_keys(self): - os.chdir(self.tmpdir) + os.chdir(self.testdir) fdroidserver.common.write_config_file( textwrap.dedent( """ @@ -2138,7 +2129,7 @@ class CommonTest(SetUpTearDownMixin, unittest.TestCase): ) def test_setup_status_output(self): - os.chdir(self.tmpdir) + os.chdir(self.testdir) start_timestamp = time.gmtime() subcommand = 'test' @@ -2154,9 +2145,9 @@ class CommonTest(SetUpTearDownMixin, unittest.TestCase): self.assertEqual(subcommand, data['subcommand']) def test_setup_status_output_in_git_repo(self): - os.chdir(self.tmpdir) + os.chdir(self.testdir) logging.getLogger('git.cmd').setLevel(logging.INFO) - git_repo = git.Repo.init(self.tmpdir) + git_repo = git.Repo.init(self.testdir) file_in_git = 'README.md' with open(file_in_git, 'w') as fp: fp.write('this is just a test') @@ -2410,40 +2401,40 @@ class CommonTest(SetUpTearDownMixin, unittest.TestCase): @unittest.skip("This test downloads and unzips a 1GB file.") def test_install_ndk(self): """NDK r10e is a special case since its missing source.properties""" - config = {'sdk_path': self.tmpdir} + config = {'sdk_path': self.testdir} fdroidserver.common.config = config fdroidserver.common._install_ndk('r10e') - r10e = os.path.join(self.tmpdir, 'ndk', 'r10e') + r10e = os.path.join(self.testdir, 'ndk', 'r10e') self.assertEqual('r10e', fdroidserver.common.get_ndk_version(r10e)) fdroidserver.common.fill_config_defaults(config) self.assertEqual({'r10e': r10e}, config['ndk_paths']) def test_fill_config_defaults(self): """Test the auto-detection of NDKs installed in standard paths""" - ndk_bundle = os.path.join(self.tmpdir, 'ndk-bundle') + ndk_bundle = os.path.join(self.testdir, 'ndk-bundle') os.makedirs(ndk_bundle) with open(os.path.join(ndk_bundle, 'source.properties'), 'w') as fp: fp.write('Pkg.Desc = Android NDK\nPkg.Revision = 17.2.4988734\n') - config = {'sdk_path': self.tmpdir} + config = {'sdk_path': self.testdir} fdroidserver.common.fill_config_defaults(config) self.assertEqual({'17.2.4988734': ndk_bundle}, config['ndk_paths']) - r21e = os.path.join(self.tmpdir, 'ndk', '21.4.7075529') + r21e = os.path.join(self.testdir, 'ndk', '21.4.7075529') os.makedirs(r21e) with open(os.path.join(r21e, 'source.properties'), 'w') as fp: fp.write('Pkg.Desc = Android NDK\nPkg.Revision = 21.4.7075529\n') - config = {'sdk_path': self.tmpdir} + config = {'sdk_path': self.testdir} fdroidserver.common.fill_config_defaults(config) self.assertEqual( {'17.2.4988734': ndk_bundle, '21.4.7075529': r21e}, config['ndk_paths'], ) - r10e = os.path.join(self.tmpdir, 'ndk', 'r10e') + r10e = os.path.join(self.testdir, 'ndk', 'r10e') os.makedirs(r10e) with open(os.path.join(r10e, 'RELEASE.TXT'), 'w') as fp: fp.write('r10e-rc4 (64-bit)\n') - config = {'sdk_path': self.tmpdir} + config = {'sdk_path': self.testdir} fdroidserver.common.fill_config_defaults(config) self.assertEqual( {'r10e': r10e, '17.2.4988734': ndk_bundle, '21.4.7075529': r21e}, @@ -2453,7 +2444,7 @@ class CommonTest(SetUpTearDownMixin, unittest.TestCase): @unittest.skipIf(not os.path.isdir('/usr/lib/jvm/default-java'), 'uses Debian path') def test_fill_config_defaults_java(self): """Test the auto-detection of Java installed in standard paths""" - config = {'sdk_path': self.tmpdir} + config = {'sdk_path': self.testdir} fdroidserver.common.fill_config_defaults(config) java_paths = [] # use presence of javac to make sure its JDK not just JRE @@ -2640,7 +2631,7 @@ class CommonTest(SetUpTearDownMixin, unittest.TestCase): self.assertFalse(is_repo_file(d), d + ' not repo file') def test_get_apksigner_smartcardoptions(self): - os.chdir(self.tmpdir) + os.chdir(self.testdir) with open(fdroidserver.common.CONFIG_FILE, 'w', encoding='utf-8') as fp: d = { 'smartcardoptions': '-storetype PKCS11' @@ -2668,7 +2659,7 @@ class CommonTest(SetUpTearDownMixin, unittest.TestCase): ) def test_get_smartcardoptions_list(self): - os.chdir(self.tmpdir) + os.chdir(self.testdir) fdroidserver.common.write_config_file( textwrap.dedent( """ @@ -2702,7 +2693,7 @@ class CommonTest(SetUpTearDownMixin, unittest.TestCase): ) def test_get_smartcardoptions_spaces(self): - os.chdir(self.tmpdir) + os.chdir(self.testdir) fdroidserver.common.write_config_file( textwrap.dedent( """