Refactor TestCase files into python modules

Convert all TestCase files into standard python modules to be run and
discovered by unittest.
This commit is contained in:
SilentGhost 2024-11-19 20:36:41 +01:00 committed by Hans-Christoph Steiner
parent 4d6682bc70
commit 7ff32bc4b0
34 changed files with 471 additions and 1260 deletions

View File

@ -252,7 +252,6 @@ lint_format_bandit_checks:
setup.py setup.py
fdroidserver/*.py fdroidserver/*.py
tests/*.py tests/*.py
tests/*.TestCase
|| set_error || set_error
- shellcheck --exclude SC2046,SC2090 --severity=warning --color tests/run-tests - shellcheck --exclude SC2046,SC2090 --severity=warning --color tests/run-tests
|| set_error || set_error
@ -619,10 +618,10 @@ Windows:
- python -m pip install --upgrade babel pip setuptools - python -m pip install --upgrade babel pip setuptools
- python -m pip install -e . - python -m pip install -e .
- $files = @(Get-ChildItem tests\*.TestCase) - $files = @(Get-ChildItem tests\test_*.py)
- foreach ($f in $files) { - foreach ($f in $files) {
write-output $f; write-output $f;
python $f; python -m unittest $f;
if( $LASTEXITCODE -eq 0 ) { if( $LASTEXITCODE -eq 0 ) {
write-output "SUCCESS $f"; write-output "SUCCESS $f";
} else { } else {
@ -631,15 +630,16 @@ Windows:
} }
# these are the tests that must pass # these are the tests that must pass
- python tests\checkupdates.TestCase - python -m unittest -k
- python tests\exception.TestCase checkupdates
- python tests\import_subcommand.TestCase exception
- python tests\init.TestCase import_subcommand
- python tests\lint.TestCase test_lint
- python tests\main.TestCase test_metadata
- python tests\metadata.TestCase test_rewritemeta
- python tests\rewritemeta.TestCase test_vcs
- python tests\vcs.TestCase tests.test_init
tests.test_main
after_script: after_script:
- Copy-Item C:\ProgramData\chocolatey\logs\chocolatey.log - Copy-Item C:\ProgramData\chocolatey\logs\chocolatey.log
artifacts: artifacts:

View File

@ -50,7 +50,6 @@ include README.md
include tests/aosp_testkey_debug.keystore include tests/aosp_testkey_debug.keystore
include tests/apk.embedded_1.apk include tests/apk.embedded_1.apk
include tests/bad-unicode-*.apk include tests/bad-unicode-*.apk
include tests/build.TestCase
include tests/build-tools/17.0.0/aapt-output-com.moez.QKSMS_182.txt include tests/build-tools/17.0.0/aapt-output-com.moez.QKSMS_182.txt
include tests/build-tools/17.0.0/aapt-output-com.politedroid_3.txt include tests/build-tools/17.0.0/aapt-output-com.politedroid_3.txt
include tests/build-tools/17.0.0/aapt-output-com.politedroid_4.txt include tests/build-tools/17.0.0/aapt-output-com.politedroid_4.txt
@ -547,9 +546,7 @@ include tests/build-tools/28.0.3/aapt-output-obb.main.twoversions_1101617.txt
include tests/build-tools/28.0.3/aapt-output-souch.smsbypass_9.txt include tests/build-tools/28.0.3/aapt-output-souch.smsbypass_9.txt
include tests/build-tools/generate.sh include tests/build-tools/generate.sh
include tests/check-fdroid-apk include tests/check-fdroid-apk
include tests/checkupdates.TestCase
include tests/com.fake.IpaApp_1000000000001.ipa include tests/com.fake.IpaApp_1000000000001.ipa
include tests/common.TestCase
include tests/config.py include tests/config.py
include tests/config/antiFeatures.yml include tests/config/antiFeatures.yml
include tests/config/categories.yml include tests/config/categories.yml
@ -569,10 +566,8 @@ include tests/config/ic_antifeature_upstreamnonfree.xml
include tests/config/ro/antiFeatures.yml include tests/config/ro/antiFeatures.yml
include tests/config/zh-rCN/antiFeatures.yml include tests/config/zh-rCN/antiFeatures.yml
include tests/corrupt-featureGraphic.png include tests/corrupt-featureGraphic.png
include tests/deploy.TestCase
include tests/dummy-keystore.jks include tests/dummy-keystore.jks
include tests/dump_internal_metadata_format.py include tests/dump_internal_metadata_format.py
include tests/exception.TestCase
include tests/extra/manual-vmtools-test.py include tests/extra/manual-vmtools-test.py
include tests/funding-usernames.yaml include tests/funding-usernames.yaml
include tests/get_android_tools_versions/android-ndk-r10e/RELEASE.TXT include tests/get_android_tools_versions/android-ndk-r10e/RELEASE.TXT
@ -591,10 +586,6 @@ include tests/gnupghome/secring.gpg
include tests/gnupghome/trustdb.gpg include tests/gnupghome/trustdb.gpg
include tests/gradle-maven-blocks.yaml include tests/gradle-maven-blocks.yaml
include tests/gradle-release-checksums.py include tests/gradle-release-checksums.py
include tests/import_subcommand.TestCase
include tests/index.TestCase
include tests/init.TestCase
include tests/install.TestCase
include tests/IsMD5Disabled.java include tests/IsMD5Disabled.java
include tests/issue-1128-min-sdk-30-poc.apk include tests/issue-1128-min-sdk-30-poc.apk
include tests/issue-1128-poc1.apk include tests/issue-1128-poc1.apk
@ -604,8 +595,6 @@ include tests/issue-1128-poc3b.apk
include tests/janus.apk include tests/janus.apk
include tests/keystore.jks include tests/keystore.jks
include tests/key-tricks.py include tests/key-tricks.py
include tests/lint.TestCase
include tests/main.TestCase
include tests/metadata/apk/info.guardianproject.urzip.yaml include tests/metadata/apk/info.guardianproject.urzip.yaml
include tests/metadata/apk/org.dyndns.fules.ck.yaml include tests/metadata/apk/org.dyndns.fules.ck.yaml
include tests/metadata/app.with.special.build.params.yml include tests/metadata/app.with.special.build.params.yml
@ -660,10 +649,7 @@ include tests/metadata-rewrite-yml/app.with.special.build.params.yml
include tests/metadata-rewrite-yml/fake.ota.update.yml include tests/metadata-rewrite-yml/fake.ota.update.yml
include tests/metadata-rewrite-yml/org.fdroid.fdroid.yml include tests/metadata-rewrite-yml/org.fdroid.fdroid.yml
include tests/metadata/souch.smsbypass.yml include tests/metadata/souch.smsbypass.yml
include tests/metadata.TestCase
include tests/minimal_targetsdk_30_unsigned.apk include tests/minimal_targetsdk_30_unsigned.apk
include tests/net.TestCase
include tests/nightly.TestCase
include tests/Norway_bouvet_europe_2.obf.zip include tests/Norway_bouvet_europe_2.obf.zip
include tests/no_targetsdk_minsdk1_unsigned.apk include tests/no_targetsdk_minsdk1_unsigned.apk
include tests/no_targetsdk_minsdk30_unsigned.apk include tests/no_targetsdk_minsdk30_unsigned.apk
@ -674,7 +660,6 @@ include tests/org.bitbucket.tickytacky.mirrormirror_3.apk
include tests/org.bitbucket.tickytacky.mirrormirror_4.apk include tests/org.bitbucket.tickytacky.mirrormirror_4.apk
include tests/org.dyndns.fules.ck_20.apk include tests/org.dyndns.fules.ck_20.apk
include tests/org.sajeg.fallingblocks_3.apk include tests/org.sajeg.fallingblocks_3.apk
include tests/publish.TestCase
include tests/repo/com.example.test.helloworld_1.apk include tests/repo/com.example.test.helloworld_1.apk
include tests/repo/com.politedroid_3.apk include tests/repo/com.politedroid_3.apk
include tests/repo/com.politedroid_4.apk include tests/repo/com.politedroid_4.apk
@ -732,13 +717,9 @@ include tests/repo/patch.1619.obb.mainpatch.current.obb
include tests/repo/souch.smsbypass_9.apk include tests/repo/souch.smsbypass_9.apk
include tests/repo/urzip-*.apk include tests/repo/urzip-*.apk
include tests/repo/v1.v2.sig_1020.apk include tests/repo/v1.v2.sig_1020.apk
include tests/rewritemeta.TestCase
include tests/run-tests include tests/run-tests
include tests/SANAPPSI.RSA include tests/SANAPPSI.RSA
include tests/SANAPPSI.SF include tests/SANAPPSI.SF
include tests/scanner.TestCase
include tests/signatures.TestCase
include tests/signindex.TestCase
include tests/signindex/guardianproject.jar include tests/signindex/guardianproject.jar
include tests/signindex/guardianproject-v1.jar include tests/signindex/guardianproject-v1.jar
include tests/signindex/testy.jar include tests/signindex/testy.jar
@ -864,7 +845,27 @@ include tests/source-files/yuriykulikov/AlarmClock/gradle/wrapper/gradle-wrapper
include tests/source-files/Zillode/syncthing-silk/build.gradle include tests/source-files/Zillode/syncthing-silk/build.gradle
include tests/SpeedoMeterApp.main_1.apk include tests/SpeedoMeterApp.main_1.apk
include tests/testcommon.py include tests/testcommon.py
include tests/test_build.py
include tests/test_checkupdates.py
include tests/test_common.py
include tests/test_deploy.py
include tests/test_exception.py
include tests/test_gradlew-fdroid include tests/test_gradlew-fdroid
include tests/test_import_subcommand.py
include tests/test_index.py
include tests/test_init.py
include tests/test_install.py
include tests/test_lint.py
include tests/test_main.py
include tests/test_metadata.py
include tests/test_nightly.py
include tests/test_publish.py
include tests/test_rewritemeta.py
include tests/test_scanner.py
include tests/test_signatures.py
include tests/test_signindex.py
include tests/test_update.py
include tests/test_vcs.py
include tests/triple-t-2/build/org.piwigo.android/app/build.gradle include tests/triple-t-2/build/org.piwigo.android/app/build.gradle
include tests/triple-t-2/build/org.piwigo.android/app/.gitignore include tests/triple-t-2/build/org.piwigo.android/app/.gitignore
include tests/triple-t-2/build/org.piwigo.android/app/src/debug/res/values/constants.xml include tests/triple-t-2/build/org.piwigo.android/app/src/debug/res/values/constants.xml
@ -921,7 +922,6 @@ include tests/triple-t-multiple/build/ch.admin.bag.covidcertificate.wallet/verif
include tests/triple-t-multiple/build/ch.admin.bag.covidcertificate.wallet/wallet/src/main/play/listings/en-US/title.txt include tests/triple-t-multiple/build/ch.admin.bag.covidcertificate.wallet/wallet/src/main/play/listings/en-US/title.txt
include tests/triple-t-multiple/metadata/ch.admin.bag.covidcertificate.verifier.yml include tests/triple-t-multiple/metadata/ch.admin.bag.covidcertificate.verifier.yml
include tests/triple-t-multiple/metadata/ch.admin.bag.covidcertificate.wallet.yml include tests/triple-t-multiple/metadata/ch.admin.bag.covidcertificate.wallet.yml
include tests/update.TestCase
include tests/urzip.apk include tests/urzip.apk
include tests/urzip-badcert.apk include tests/urzip-badcert.apk
include tests/urzip-badsig.apk include tests/urzip-badsig.apk
@ -931,4 +931,3 @@ include tests/v2.only.sig_2.apk
include tests/valid-package-names/random-package-names include tests/valid-package-names/random-package-names
include tests/valid-package-names/RandomPackageNames.java include tests/valid-package-names/RandomPackageNames.java
include tests/valid-package-names/test.py include tests/valid-package-names/test.py
include tests/vcs.TestCase

View File

@ -53,13 +53,13 @@ To run the full test suite:
tests/run-tests tests/run-tests
To run the tests for individual Python modules, see the _.TestCase_ files, e.g.: To run the tests for individual Python modules, see the `tests/test_*.py` files, e.g.:
tests/metadata.TestCase python -m unittest tests/test_metadata.py
It is also possible to run individual tests: It is also possible to run individual tests:
tests/metadata.TestCase MetadataTest.test_rewrite_yaml_special_build_params python -m unittest tests.test_metadata.MetadataTest.test_rewrite_yaml_special_build_params
There is a growing test suite that has good coverage on a number of key parts of There is a growing test suite that has good coverage on a number of key parts of
this code base. It does not yet cover all the code, and there are some parts this code base. It does not yet cover all the code, and there are some parts

View File

@ -9,7 +9,7 @@ exec 1>&2
files=`git diff-index --cached HEAD 2>&1 | sed 's/^:.* //' | uniq | cut -b100-500` files=`git diff-index --cached HEAD 2>&1 | sed 's/^:.* //' | uniq | cut -b100-500`
if [ -z "$files" ]; then if [ -z "$files" ]; then
PY_FILES="fdroid makebuildserver setup.py fdroidserver/*.py examples/*.py tests/*-release-checksums.py" PY_FILES="fdroid makebuildserver setup.py fdroidserver/*.py examples/*.py tests/*-release-checksums.py"
PY_TEST_FILES="tests/*.TestCase" PY_TEST_FILES="tests/test_*.py"
SH_FILES="hooks/pre-commit" SH_FILES="hooks/pre-commit"
BASH_FILES="gradlew-fdroid jenkins-build-all jenkins-setup-build-environment jenkins-test completion/bash-completion buildserver/provision-*" BASH_FILES="gradlew-fdroid jenkins-build-all jenkins-setup-build-environment jenkins-test completion/bash-completion buildserver/provision-*"
RB_FILES="buildserver/Vagrantfile" RB_FILES="buildserver/Vagrantfile"
@ -27,12 +27,12 @@ else
for f in $files; do for f in $files; do
test -e $f || continue test -e $f || continue
case $f in case $f in
test_*.py)
PY_TEST_FILES+=" $f"
;;
*.py) *.py)
PY_FILES+=" $f" PY_FILES+=" $f"
;; ;;
*.TestCase)
PY_TEST_FILES+=" $f"
;;
*.rb) *.rb)
RB_FILES+=" $f" RB_FILES+=" $f"
;; ;;

View File

@ -20,7 +20,7 @@ ignore = "E123,E203,E402,E501,W503"
[tool.black] [tool.black]
skip-string-normalization = true skip-string-normalization = true
target-version = ["py38"] target-version = ["py38"]
include = '(^fdroid|\.pyi?|\.TestCase)$' include = '(^fdroid|\.pyi?)$'
# These files will never be included in black runs. To run black on # These files will never be included in black runs. To run black on
# one of thes files, remove it from this list. # one of thes files, remove it from this list.
force-exclude = '''( force-exclude = '''(
@ -49,10 +49,10 @@ force-exclude = '''(
| tests/gradle-release-checksums\.py | tests/gradle-release-checksums\.py
| tests/openssl-version-check-test\.py | tests/openssl-version-check-test\.py
| tests/valid-package-names/test\.py | tests/valid-package-names/test\.py
| tests/common\.TestCase | tests/test_common\.py
| tests/publish\.TestCase | tests/test_publish\.py
| tests/signatures\.TestCase | tests/test_signatures\.py
| tests/update\.TestCase | tests/test_update\.py
)$''' )$'''

0
tests/__init__.py Normal file
View File

View File

@ -1,91 +0,0 @@
#!/usr/bin/env python3
# http://www.drdobbs.com/testing/unit-testing-with-python/240165163
import inspect
import logging
import os
import shutil
import sys
import unittest
localmodule = os.path.realpath(
os.path.join(os.path.dirname(inspect.getfile(inspect.currentframe())), '..')
)
print('localmodule: ' + localmodule)
if localmodule not in sys.path:
sys.path.insert(0, localmodule)
import fdroidserver.init
from testcommon import mkdtemp, parse_args_for_test
class InitTest(unittest.TestCase):
'''fdroidserver/init.py'''
def setUp(self):
logging.basicConfig(level=logging.DEBUG)
self.basedir = os.path.join(localmodule, 'tests')
fdroidserver.common.config = None
fdroidserver.init.config = None
self._td = mkdtemp()
self.testdir = self._td.name
def tearDown(self):
self._td.cleanup()
os.chdir(self.basedir)
def test_disable_in_config(self):
os.chdir(self.testdir)
with open('config.yml', 'w') as fp:
fp.write('keystore: NONE\n')
fp.write('keypass: mysupersecrets\n')
os.chmod('config.yml', 0o600)
config = fdroidserver.common.read_config()
self.assertEqual('NONE', config['keystore'])
self.assertEqual('mysupersecrets', config['keypass'])
fdroidserver.init.disable_in_config('keypass', 'comment')
with open(fp.name) as fp:
self.assertTrue('#keypass:' in fp.read())
fdroidserver.common.config = None
config = fdroidserver.common.read_config()
self.assertIsNone(config.get('keypass'))
@unittest.skipIf(os.name == 'nt', "calling main() like this hangs on Windows")
def test_main_in_empty_dir(self):
"""Test that `fdroid init` will find apksigner and add it to the config"""
os.chdir(self.testdir)
shutil.copy(os.path.join(self.basedir, 'keystore.jks'), self.testdir)
bindir = os.path.join(os.getcwd(), 'bin')
os.mkdir(bindir)
apksigner = os.path.join(bindir, 'apksigner')
open(apksigner, 'w').close()
os.chmod(apksigner, 0o755)
os.environ['PATH'] = bindir
sys.argv = ['fdroid init', '--keystore', 'keystore.jks', '--repo-keyalias=sova']
fdroidserver.init.main()
self.assertEqual(apksigner, fdroidserver.init.config.get('apksigner'))
if __name__ == "__main__":
os.chdir(os.path.dirname(__file__))
import argparse
parser = argparse.ArgumentParser()
parser.add_argument(
"-v",
"--verbose",
action="store_true",
default=False,
help="Spew out even more information than normal",
)
fdroidserver.init.options = parse_args_for_test(parser, sys.argv)
newSuite = unittest.TestSuite()
newSuite.addTest(unittest.makeSuite(InitTest))
unittest.main(failfast=False)

View File

@ -170,15 +170,7 @@ test -x ./hooks/pre-commit && ./hooks/pre-commit
#------------------------------------------------------------------------------# #------------------------------------------------------------------------------#
echo_header "run unit tests" echo_header "run unit tests"
cd $WORKSPACE/tests python3 -m unittest -v
for testcase in $WORKSPACE/tests/*.TestCase; do
if [ $(uname) != "Linux" ] && [ $testcase == $WORKSPACE/tests/nightly.TestCase ]; then
echo "skipping nightly.TestCase, it currently only works GNU/Linux"
continue
fi
$testcase
done
#------------------------------------------------------------------------------# #------------------------------------------------------------------------------#
echo_header "print fdroid version" echo_header "print fdroid version"

View File

@ -1,22 +1,17 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import inspect
import os import os
import shutil import shutil
import sys
import unittest import unittest
from pathlib import Path
from unittest import mock from unittest import mock
localmodule = os.path.realpath(
os.path.join(os.path.dirname(inspect.getfile(inspect.currentframe())), '..')
)
print('localmodule: ' + localmodule)
if localmodule not in sys.path:
sys.path.insert(0, localmodule)
import fdroidserver import fdroidserver
from fdroidserver import common, signindex from fdroidserver import common, signindex
from testcommon import GP_FINGERPRINT, mkdtemp from .testcommon import GP_FINGERPRINT, mkdtemp
basedir = Path(__file__).parent
class ApiTest(unittest.TestCase): class ApiTest(unittest.TestCase):
@ -29,8 +24,7 @@ class ApiTest(unittest.TestCase):
""" """
def setUp(self): def setUp(self):
self.basedir = os.path.join(localmodule, 'tests') os.chdir(basedir)
os.chdir(self.basedir)
self._td = mkdtemp() self._td = mkdtemp()
self.testdir = self._td.name self.testdir = self._td.name
@ -89,10 +83,10 @@ class ApiTest(unittest.TestCase):
self.testdir, 'repo', os.path.basename(mirrors[0]['url']) self.testdir, 'repo', os.path.basename(mirrors[0]['url'])
) )
os.chdir(self.testdir) os.chdir(self.testdir)
signindex.config['keystore'] = os.path.join(self.basedir, 'keystore.jks') signindex.config['keystore'] = os.path.join(basedir, 'keystore.jks')
os.mkdir('repo') os.mkdir('repo')
shutil.copy(os.path.join(self.basedir, 'repo', 'entry.json'), 'repo') shutil.copy(basedir / 'repo' / 'entry.json', 'repo')
shutil.copy(os.path.join(self.basedir, 'repo', 'index-v2.json'), 'repo') shutil.copy(basedir / 'repo' / 'index-v2.json', 'repo')
signindex.sign_index('repo', 'entry.json') signindex.sign_index('repo', 'entry.json')
repo_url = 'https://fake.url/fdroid/repo' repo_url = 'https://fake.url/fdroid/repo'
entry_url = 'https://fake.url/fdroid/repo/entry.jar' entry_url = 'https://fake.url/fdroid/repo/entry.jar'
@ -107,9 +101,3 @@ class ApiTest(unittest.TestCase):
self.assertEqual( self.assertEqual(
'My First F-Droid Repo Demo', data['repo']['name']['en-US'] 'My First F-Droid Repo Demo', data['repo']['name']['en-US']
) )
if __name__ == "__main__":
newSuite = unittest.TestSuite()
newSuite.addTest(unittest.makeSuite(ApiTest))
unittest.main(failfast=False)

View File

@ -1,12 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# http://www.drdobbs.com/testing/unit-testing-with-python/240165163
import inspect
import logging
import os import os
import shutil import shutil
import sys
import tempfile import tempfile
import textwrap import textwrap
import unittest import unittest
@ -14,21 +9,10 @@ import yaml
from pathlib import Path from pathlib import Path
from unittest import mock from unittest import mock
localmodule = os.path.realpath( from .testcommon import TmpCwd, mkdtemp
os.path.join(os.path.dirname(inspect.getfile(inspect.currentframe())), '..')
)
print('localmodule: ' + localmodule)
if localmodule not in sys.path:
sys.path.insert(0, localmodule)
from testcommon import TmpCwd
import fdroidserver.build import fdroidserver.build
import fdroidserver.common import fdroidserver.common
import fdroidserver.metadata
import fdroidserver.scanner
import fdroidserver.vmtools
from testcommon import mkdtemp, parse_args_for_test
class FakeProcess: class FakeProcess:
@ -47,8 +31,7 @@ class BuildTest(unittest.TestCase):
'''fdroidserver/build.py''' '''fdroidserver/build.py'''
def setUp(self): def setUp(self):
logging.basicConfig(level=logging.DEBUG) self.basedir = str(Path(__file__).parent)
self.basedir = os.path.join(localmodule, 'tests')
os.chdir(self.basedir) os.chdir(self.basedir)
fdroidserver.common.config = None fdroidserver.common.config = None
fdroidserver.build.config = None fdroidserver.build.config = None
@ -937,7 +920,7 @@ class BuildTest(unittest.TestCase):
subprocess_check_output, subprocess_check_output,
paramiko_SSHClient, paramiko_SSHClient,
fdroidserver_vmtools_get_clean_builder, fdroidserver_vmtools_get_clean_builder,
fdroidserver_vmtools_get_build_vm, fdroidserver_vmtools_get_build_vm, # pylint: disable=unused-argument
): ):
"""srclibs Prepare: should only be executed in the buildserver""" """srclibs Prepare: should only be executed in the buildserver"""
@ -954,6 +937,7 @@ class BuildTest(unittest.TestCase):
refresh=True, refresh=True,
build=None, build=None,
): ):
# pylint: disable=unused-argument
name, ref = spec.split('@') name, ref = spec.split('@')
libdir = os.path.join(srclib_dir, name) libdir = os.path.join(srclib_dir, name)
os.mkdir(libdir) os.mkdir(libdir)
@ -1098,23 +1082,3 @@ class BuildTest(unittest.TestCase):
fdroidserver.build.options.keep_when_not_allowed = False fdroidserver.build.options.keep_when_not_allowed = False
fdroidserver.build.config = {'keep_when_not_allowed': False} fdroidserver.build.config = {'keep_when_not_allowed': False}
self.assertFalse(fdroidserver.build.keep_when_not_allowed()) self.assertFalse(fdroidserver.build.keep_when_not_allowed())
if __name__ == "__main__":
os.chdir(os.path.dirname(__file__))
import argparse
parser = argparse.ArgumentParser()
parser.add_argument(
"-v",
"--verbose",
action="store_true",
default=False,
help="Spew out even more information than normal",
)
parse_args_for_test(parser, sys.argv)
newSuite = unittest.TestSuite()
newSuite.addTest(unittest.makeSuite(BuildTest))
unittest.main(failfast=False)

View File

@ -1,36 +1,26 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# http://www.drdobbs.com/testing/unit-testing-with-python/240165163
import git import git
import logging
import os import os
import shutil import shutil
import sys
import tempfile import tempfile
import time import time
import unittest import unittest
from unittest import mock from unittest import mock
from pathlib import Path from pathlib import Path
import fdroidserver
localmodule = Path(__file__).resolve().parent.parent
print('localmodule: ' + str(localmodule))
if localmodule not in sys.path:
sys.path.insert(0, str(localmodule))
import fdroidserver.checkupdates import fdroidserver.checkupdates
import fdroidserver.metadata
from fdroidserver.exception import FDroidException
basedir = Path(__file__).parent
class CheckupdatesTest(unittest.TestCase): class CheckupdatesTest(unittest.TestCase):
'''fdroidserver/checkupdates.py''' '''fdroidserver/checkupdates.py'''
def setUp(self): def setUp(self):
logging.basicConfig(level=logging.DEBUG) os.chdir(basedir)
self.basedir = localmodule / 'tests'
os.chdir(self.basedir)
self.testdir = tempfile.TemporaryDirectory( self.testdir = tempfile.TemporaryDirectory(
str(time.time()), self._testMethodName + '_' str(time.time()), self._testMethodName + '_'
) )
@ -70,7 +60,7 @@ class CheckupdatesTest(unittest.TestCase):
): ):
with mock.patch('fdroidserver.metadata.write_metadata', mock.Mock()): with mock.patch('fdroidserver.metadata.write_metadata', mock.Mock()):
with mock.patch('subprocess.call', lambda cmd: 0): with mock.patch('subprocess.call', lambda cmd: 0):
with self.assertRaises(FDroidException): with self.assertRaises(fdroidserver.exception.FDroidException):
fdroidserver.checkupdates.checkupdates_app(app, auto=True) fdroidserver.checkupdates.checkupdates_app(app, auto=True)
build = app['Builds'][-1] build = app['Builds'][-1]
@ -165,7 +155,7 @@ class CheckupdatesTest(unittest.TestCase):
with mock.patch( with mock.patch(
'fdroidserver.checkupdates.check_http', lambda app: (None, 'bla') 'fdroidserver.checkupdates.check_http', lambda app: (None, 'bla')
): ):
with self.assertRaises(FDroidException): with self.assertRaises(fdroidserver.exception.FDroidException):
fdroidserver.checkupdates.checkupdates_app(app, auto=True) fdroidserver.checkupdates.checkupdates_app(app, auto=True)
with mock.patch( with mock.patch(
@ -198,7 +188,7 @@ class CheckupdatesTest(unittest.TestCase):
'fdroidserver.checkupdates.check_tags', 'fdroidserver.checkupdates.check_tags',
lambda app, pattern: (None, 'bla', None), lambda app, pattern: (None, 'bla', None),
): ):
with self.assertRaises(FDroidException): with self.assertRaises(fdroidserver.exception.FDroidException):
fdroidserver.checkupdates.checkupdates_app(app, auto=True) fdroidserver.checkupdates.checkupdates_app(app, auto=True)
with mock.patch( with mock.patch(
@ -236,7 +226,7 @@ class CheckupdatesTest(unittest.TestCase):
faked = scheme + '://fake.url/for/testing/scheme' faked = scheme + '://fake.url/for/testing/scheme'
app.UpdateCheckData = faked + '|ignored|' + faked + '|ignored' app.UpdateCheckData = faked + '|ignored|' + faked + '|ignored'
app.metadatapath = 'metadata/' + app.id + '.yml' app.metadatapath = 'metadata/' + app.id + '.yml'
with self.assertRaises(FDroidException): with self.assertRaises(fdroidserver.exception.FDroidException):
fdroidserver.checkupdates.check_http(app) fdroidserver.checkupdates.check_http(app)
def test_check_http_ignore(self): def test_check_http_ignore(self):
@ -331,7 +321,7 @@ class CheckupdatesTest(unittest.TestCase):
testdir = self.testdir.name testdir = self.testdir.name
os.chdir(testdir) os.chdir(testdir)
os.mkdir('metadata') os.mkdir('metadata')
for f in (self.basedir / 'metadata').glob('*.yml'): for f in (basedir / 'metadata').glob('*.yml'):
shutil.copy(f, 'metadata') shutil.copy(f, 'metadata')
git_repo = git.Repo.init(testdir) git_repo = git.Repo.init(testdir)
git_repo.git.add(all=True) git_repo.git.add(all=True)
@ -434,7 +424,7 @@ class CheckupdatesTest(unittest.TestCase):
@mock.patch('fdroidserver.metadata.read_metadata') @mock.patch('fdroidserver.metadata.read_metadata')
def test_merge_requests_flag(self, read_metadata, sys_exit): def test_merge_requests_flag(self, read_metadata, sys_exit):
def _sys_exit(return_code=0): def _sys_exit(return_code=0):
assert return_code != 0 self.assertNotEqual(return_code, 0)
raise fdroidserver.exception.FDroidException('sys.exit() ran') raise fdroidserver.exception.FDroidException('sys.exit() ran')
def _read_metadata(a=None, b=None): def _read_metadata(a=None, b=None):
@ -479,7 +469,7 @@ class CheckupdatesTest(unittest.TestCase):
@mock.patch('fdroidserver.checkupdates.checkupdates_app') @mock.patch('fdroidserver.checkupdates.checkupdates_app')
def test_merge_requests_branch(self, checkupdates_app, read_app_args, sys_exit): def test_merge_requests_branch(self, checkupdates_app, read_app_args, sys_exit):
def _sys_exit(return_code=0): def _sys_exit(return_code=0):
assert return_code == 0 self.assertEqual(return_code, 0)
def _checkupdates_app(app, auto, commit): # pylint: disable=unused-argument def _checkupdates_app(app, auto, commit): # pylint: disable=unused-argument
os.mkdir('metadata') os.mkdir('metadata')
@ -506,27 +496,8 @@ class CheckupdatesTest(unittest.TestCase):
git_repo.create_remote('origin', os.getcwd()).fetch() git_repo.create_remote('origin', os.getcwd()).fetch()
git_repo.create_remote('upstream', os.getcwd()).fetch() git_repo.create_remote('upstream', os.getcwd()).fetch()
assert appid not in git_repo.heads self.assertNotIn(appid, git_repo.heads)
with mock.patch('sys.argv', ['fdroid checkupdates', '--merge-request', appid]): with mock.patch('sys.argv', ['fdroid checkupdates', '--merge-request', appid]):
fdroidserver.checkupdates.main() fdroidserver.checkupdates.main()
sys_exit.assert_called_once() sys_exit.assert_called_once()
assert appid in git_repo.heads self.assertIn(appid, git_repo.heads)
if __name__ == "__main__":
import argparse
from testcommon import parse_args_for_test
parser = argparse.ArgumentParser()
parser.add_argument(
"-v",
"--verbose",
action="store_true",
default=False,
help="Spew out even more information than normal",
)
parse_args_for_test(parser, sys.argv)
newSuite = unittest.TestSuite()
newSuite.addTest(unittest.makeSuite(CheckupdatesTest))
unittest.main(failfast=False)

View File

@ -1,7 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# http://www.drdobbs.com/testing/unit-testing-with-python/240165163
import difflib import difflib
import git import git
import glob import glob
@ -28,25 +26,20 @@ from unittest import mock
from pathlib import Path from pathlib import Path
localmodule = os.path.realpath( import fdroidserver
os.path.join(os.path.dirname(inspect.getfile(inspect.currentframe())), '..')
)
print('localmodule: ' + localmodule)
if localmodule not in sys.path:
sys.path.insert(0, localmodule)
import fdroidserver.index
import fdroidserver.install
import fdroidserver.signindex import fdroidserver.signindex
import fdroidserver.common import fdroidserver.common
import fdroidserver.metadata import fdroidserver.metadata
from testcommon import TmpCwd, mkdtemp, parse_args_for_test from .testcommon import TmpCwd, mkdtemp
from fdroidserver.common import ANTIFEATURES_CONFIG_NAME, CATEGORIES_CONFIG_NAME from fdroidserver.common import ANTIFEATURES_CONFIG_NAME, CATEGORIES_CONFIG_NAME
from fdroidserver.exception import FDroidException, VCSException,\ from fdroidserver.exception import FDroidException, VCSException,\
MetaDataException, VerificationException MetaDataException, VerificationException
from fdroidserver.looseversion import LooseVersion from fdroidserver.looseversion import LooseVersion
basedir = Path(__file__).parent
def _mock_common_module_options_instance(): def _mock_common_module_options_instance():
"""Helper method to deal with difficult visibility of the module-level options.""" """Helper method to deal with difficult visibility of the module-level options."""
fdroidserver.common.options = mock.Mock() fdroidserver.common.options = mock.Mock()
@ -60,11 +53,10 @@ class CommonTest(unittest.TestCase):
logging.basicConfig(level=logging.DEBUG) logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger('androguard.axml') logger = logging.getLogger('androguard.axml')
logger.setLevel(logging.INFO) # tame the axml debug messages logger.setLevel(logging.INFO) # tame the axml debug messages
self.basedir = os.path.join(localmodule, 'tests') self.tmpdir = os.path.abspath(os.path.join(basedir, '..', '.testfiles'))
self.tmpdir = os.path.abspath(os.path.join(self.basedir, '..', '.testfiles'))
if not os.path.exists(self.tmpdir): if not os.path.exists(self.tmpdir):
os.makedirs(self.tmpdir) os.makedirs(self.tmpdir)
os.chdir(self.basedir) os.chdir(basedir)
# these are declared as None at the top of the module file # these are declared as None at the top of the module file
fdroidserver.common.config = None fdroidserver.common.config = None
@ -77,7 +69,7 @@ class CommonTest(unittest.TestCase):
def tearDown(self): def tearDown(self):
fdroidserver.common.config = None fdroidserver.common.config = None
fdroidserver.common.options = None fdroidserver.common.options = None
os.chdir(self.basedir) os.chdir(basedir)
self._td.cleanup() self._td.cleanup()
if os.path.exists(self.tmpdir): if os.path.exists(self.tmpdir):
shutil.rmtree(self.tmpdir) shutil.rmtree(self.tmpdir)
@ -187,11 +179,11 @@ class CommonTest(unittest.TestCase):
# create test file used in common._add_java_paths_to_config() # create test file used in common._add_java_paths_to_config()
for p in pathlist: for p in pathlist:
if p.startswith('/System') or p.startswith('/Library'): if p.startswith('/System') or p.startswith('/Library'):
basedir = os.path.join(p, 'Contents', 'Home', 'bin') _dir = os.path.join(p, 'Contents', 'Home', 'bin')
else: else:
basedir = os.path.join(p, 'bin') _dir = os.path.join(p, 'bin')
os.makedirs(basedir) os.makedirs(_dir)
open(os.path.join(basedir, 'javac'), 'w').close() open(os.path.join(_dir, 'javac'), 'w').close()
config = dict() config = dict()
config['java_paths'] = dict() config['java_paths'] = dict()
@ -204,21 +196,14 @@ class CommonTest(unittest.TestCase):
fdroidserver.common.config = config fdroidserver.common.config = config
# these are set debuggable # these are set debuggable
testfiles = [] for apkfile in ('urzip.apk', 'urzip-badsig.apk', 'urzip-badcert.apk'):
testfiles.append(os.path.join(self.basedir, 'urzip.apk'))
testfiles.append(os.path.join(self.basedir, 'urzip-badsig.apk'))
testfiles.append(os.path.join(self.basedir, 'urzip-badcert.apk'))
for apkfile in testfiles:
self.assertTrue( self.assertTrue(
fdroidserver.common.is_debuggable_or_testOnly(apkfile), fdroidserver.common.is_debuggable_or_testOnly(str(basedir / apkfile)),
"debuggable APK state was not properly parsed!", "debuggable APK state was not properly parsed!",
) )
# these are set NOT debuggable # these are set NOT debuggable
testfiles = [] testfiles = 'urzip-release.apk', 'urzip-release-unsigned.apk', 'v2.only.sig_2.apk'
testfiles.append(os.path.join(self.basedir, 'urzip-release.apk'))
testfiles.append(os.path.join(self.basedir, 'urzip-release-unsigned.apk'))
testfiles.append(os.path.join(self.basedir, 'v2.only.sig_2.apk'))
for apkfile in testfiles: for apkfile in testfiles:
self.assertFalse( self.assertFalse(
fdroidserver.common.is_debuggable_or_testOnly(apkfile), fdroidserver.common.is_debuggable_or_testOnly(apkfile),
@ -297,7 +282,7 @@ class CommonTest(unittest.TestCase):
teststr = 'FAKE_STR_FOR_TESTING' teststr = 'FAKE_STR_FOR_TESTING'
shutil.copytree( shutil.copytree(
os.path.join(self.basedir, 'source-files'), os.path.join(basedir, 'source-files'),
os.path.join(self.tmpdir, 'source-files'), os.path.join(self.tmpdir, 'source-files'),
) )
@ -356,7 +341,7 @@ class CommonTest(unittest.TestCase):
def test_prepare_sources_with_prebuild_subdir(self): def test_prepare_sources_with_prebuild_subdir(self):
app_build_dir = os.path.join(self.testdir, 'build', 'com.example') app_build_dir = os.path.join(self.testdir, 'build', 'com.example')
shutil.copytree( shutil.copytree(
os.path.join(self.basedir, 'source-files', 'fdroid', 'fdroidclient'), basedir / 'source-files' / 'fdroid' / 'fdroidclient',
app_build_dir, app_build_dir,
) )
@ -418,7 +403,7 @@ class CommonTest(unittest.TestCase):
os.mkdir('metadata') os.mkdir('metadata')
# use a local copy if available to avoid hitting the network # use a local copy if available to avoid hitting the network
tmprepo = os.path.join(self.basedir, 'tmp', 'importer') tmprepo = os.path.join(basedir, 'tmp', 'importer')
if os.path.exists(tmprepo): if os.path.exists(tmprepo):
git_url = tmprepo git_url = tmprepo
else: else:
@ -499,7 +484,7 @@ class CommonTest(unittest.TestCase):
fdroidserver.common.config = config fdroidserver.common.config = config
fdroidserver.signindex.config = config fdroidserver.signindex.config = config
sourcedir = os.path.join(self.basedir, 'signindex') sourcedir = os.path.join(basedir, 'signindex')
with tempfile.TemporaryDirectory( with tempfile.TemporaryDirectory(
prefix=inspect.currentframe().f_code.co_name, dir=self.tmpdir prefix=inspect.currentframe().f_code.co_name, dir=self.tmpdir
) as testsdir: ) as testsdir:
@ -561,7 +546,7 @@ class CommonTest(unittest.TestCase):
"""Sign entry.jar and make sure it validates""" """Sign entry.jar and make sure it validates"""
config = fdroidserver.common.read_config() config = fdroidserver.common.read_config()
config['jarsigner'] = fdroidserver.common.find_sdk_tools_cmd('jarsigner') config['jarsigner'] = fdroidserver.common.find_sdk_tools_cmd('jarsigner')
config['keystore'] = os.path.join(self.basedir, 'keystore.jks') config['keystore'] = os.path.join(basedir, 'keystore.jks')
config['repo_keyalias'] = 'sova' config['repo_keyalias'] = 'sova'
config['keystorepass'] = 'r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI=' config['keystorepass'] = 'r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI='
config['keypass'] = 'r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI=' config['keypass'] = 'r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI='
@ -580,7 +565,7 @@ class CommonTest(unittest.TestCase):
config = fdroidserver.common.read_config() config = fdroidserver.common.read_config()
config['jarsigner'] = fdroidserver.common.find_sdk_tools_cmd('jarsigner') config['jarsigner'] = fdroidserver.common.find_sdk_tools_cmd('jarsigner')
fdroidserver.common.config = config fdroidserver.common.config = config
source_dir = os.path.join(self.basedir, 'signindex') source_dir = os.path.join(basedir, 'signindex')
for f in ('unsigned.jar', 'testy.jar', 'guardianproject.jar', 'guardianproject-v1.jar'): for f in ('unsigned.jar', 'testy.jar', 'guardianproject.jar', 'guardianproject-v1.jar'):
testfile = os.path.join(source_dir, f) testfile = os.path.join(source_dir, f)
with self.assertRaises(fdroidserver.index.VerificationException): with self.assertRaises(fdroidserver.index.VerificationException):
@ -590,7 +575,7 @@ class CommonTest(unittest.TestCase):
config = fdroidserver.common.read_config() config = fdroidserver.common.read_config()
config['jarsigner'] = fdroidserver.common.find_sdk_tools_cmd('jarsigner') config['jarsigner'] = fdroidserver.common.find_sdk_tools_cmd('jarsigner')
fdroidserver.common.config = config fdroidserver.common.config = config
source_dir = os.path.join(self.basedir, 'signindex') source_dir = os.path.join(basedir, 'signindex')
for f in ('testy.jar', 'guardianproject.jar'): for f in ('testy.jar', 'guardianproject.jar'):
testfile = os.path.join(source_dir, f) testfile = os.path.join(source_dir, f)
fdroidserver.common.verify_deprecated_jar_signature(testfile) fdroidserver.common.verify_deprecated_jar_signature(testfile)
@ -604,7 +589,7 @@ class CommonTest(unittest.TestCase):
fdroidserver.common.config = config fdroidserver.common.config = config
_mock_common_module_options_instance() _mock_common_module_options_instance()
sourceapk = os.path.join(self.basedir, 'urzip.apk') sourceapk = os.path.join(basedir, 'urzip.apk')
copyapk = os.path.join(self.testdir, 'urzip-copy.apk') copyapk = os.path.join(self.testdir, 'urzip-copy.apk')
shutil.copy(sourceapk, copyapk) shutil.copy(sourceapk, copyapk)
@ -624,7 +609,7 @@ class CommonTest(unittest.TestCase):
) )
twosigapk = os.path.join(self.testdir, 'urzip-twosig.apk') twosigapk = os.path.join(self.testdir, 'urzip-twosig.apk')
otherapk = ZipFile(os.path.join(self.basedir, 'urzip-release.apk'), 'r') otherapk = ZipFile(os.path.join(basedir, 'urzip-release.apk'), 'r')
with ZipFile(sourceapk, 'r') as apk: with ZipFile(sourceapk, 'r') as apk:
with ZipFile(twosigapk, 'w') as testapk: with ZipFile(twosigapk, 'w') as testapk:
for info in apk.infolist(): for info in apk.infolist():
@ -825,7 +810,7 @@ class CommonTest(unittest.TestCase):
os.makedirs(os.path.dirname(do_not_use)) os.makedirs(os.path.dirname(do_not_use))
with open(do_not_use, 'w') as fp: with open(do_not_use, 'w') as fp:
fp.write('#!/bin/sh\ndate\n') fp.write('#!/bin/sh\ndate\n')
os.chmod(do_not_use, 0o0755) os.chmod(do_not_use, 0o0755) # nosec B103
apksigner = os.path.join(self.tmpdir, 'apksigner') apksigner = os.path.join(self.tmpdir, 'apksigner')
config = {'apksigner': apksigner} config = {'apksigner': apksigner}
with mock.patch.dict(os.environ, clear=True): with mock.patch.dict(os.environ, clear=True):
@ -840,14 +825,14 @@ class CommonTest(unittest.TestCase):
apksigner = os.path.join(self.tmpdir, 'apksigner') apksigner = os.path.join(self.tmpdir, 'apksigner')
with open(apksigner, 'w') as fp: with open(apksigner, 'w') as fp:
fp.write('#!/bin/sh\ndate\n') fp.write('#!/bin/sh\ndate\n')
os.chmod(apksigner, 0o0755) os.chmod(apksigner, 0o0755) # nosec B103
android_home = os.path.join(self.tmpdir, 'ANDROID_HOME') android_home = os.path.join(self.tmpdir, 'ANDROID_HOME')
do_not_use = os.path.join(android_home, 'build-tools', '30.0.3', 'apksigner') do_not_use = os.path.join(android_home, 'build-tools', '30.0.3', 'apksigner')
os.makedirs(os.path.dirname(do_not_use)) os.makedirs(os.path.dirname(do_not_use))
with open(do_not_use, 'w') as fp: with open(do_not_use, 'w') as fp:
fp.write('#!/bin/sh\ndate\n') fp.write('#!/bin/sh\ndate\n')
os.chmod(do_not_use, 0o0755) os.chmod(do_not_use, 0o0755) # nosec B103
config = {'sdk_path': android_home} config = {'sdk_path': android_home}
with mock.patch.dict(os.environ, clear=True): with mock.patch.dict(os.environ, clear=True):
@ -865,13 +850,13 @@ class CommonTest(unittest.TestCase):
os.makedirs(os.path.dirname(apksigner)) os.makedirs(os.path.dirname(apksigner))
with open(apksigner, 'w') as fp: with open(apksigner, 'w') as fp:
fp.write('#!/bin/sh\necho 30.0.3\n') fp.write('#!/bin/sh\necho 30.0.3\n')
os.chmod(apksigner, 0o0755) os.chmod(apksigner, 0o0755) # nosec B103
do_not_use = os.path.join(android_home, 'build-tools', '29.0.3', 'apksigner') do_not_use = os.path.join(android_home, 'build-tools', '29.0.3', 'apksigner')
os.makedirs(os.path.dirname(do_not_use)) os.makedirs(os.path.dirname(do_not_use))
with open(do_not_use, 'w') as fp: with open(do_not_use, 'w') as fp:
fp.write('#!/bin/sh\necho 29.0.3\n') fp.write('#!/bin/sh\necho 29.0.3\n')
os.chmod(do_not_use, 0o0755) os.chmod(do_not_use, 0o0755) # nosec B103
config = {'sdk_path': android_home} config = {'sdk_path': android_home}
with mock.patch.dict(os.environ, clear=True): with mock.patch.dict(os.environ, clear=True):
@ -917,13 +902,13 @@ class CommonTest(unittest.TestCase):
config['keyalias'] = 'sova' config['keyalias'] = 'sova'
config['keystorepass'] = 'r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI=' config['keystorepass'] = 'r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI='
config['keypass'] = 'r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI=' config['keypass'] = 'r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI='
config['keystore'] = os.path.join(self.basedir, 'keystore.jks') config['keystore'] = os.path.join(basedir, 'keystore.jks')
fdroidserver.common.config = config fdroidserver.common.config = config
fdroidserver.signindex.config = config fdroidserver.signindex.config = config
unsigned = os.path.join(self.testdir, 'urzip-release-unsigned.apk') unsigned = os.path.join(self.testdir, 'urzip-release-unsigned.apk')
signed = os.path.join(self.testdir, 'urzip-release.apk') signed = os.path.join(self.testdir, 'urzip-release.apk')
shutil.copy(os.path.join(self.basedir, 'urzip-release-unsigned.apk'), self.testdir) shutil.copy(os.path.join(basedir, 'urzip-release-unsigned.apk'), self.testdir)
self.assertFalse(fdroidserver.common.verify_apk_signature(unsigned)) self.assertFalse(fdroidserver.common.verify_apk_signature(unsigned))
@ -936,7 +921,7 @@ class CommonTest(unittest.TestCase):
unsigned = os.path.join(self.testdir, 'duplicate.permisssions_9999999-unsigned.apk') unsigned = os.path.join(self.testdir, 'duplicate.permisssions_9999999-unsigned.apk')
signed = os.path.join(self.testdir, 'duplicate.permisssions_9999999.apk') signed = os.path.join(self.testdir, 'duplicate.permisssions_9999999.apk')
shutil.copy( shutil.copy(
os.path.join(self.basedir, 'repo', 'duplicate.permisssions_9999999.apk'), os.path.join(basedir, 'repo', 'duplicate.permisssions_9999999.apk'),
os.path.join(unsigned), os.path.join(unsigned),
) )
fdroidserver.common.apk_strip_v1_signatures(unsigned, strip_manifest=True) fdroidserver.common.apk_strip_v1_signatures(unsigned, strip_manifest=True)
@ -946,7 +931,7 @@ class CommonTest(unittest.TestCase):
self.assertTrue(fdroidserver.common.verify_apk_signature(signed)) self.assertTrue(fdroidserver.common.verify_apk_signature(signed))
self.assertEqual('18', fdroidserver.common.get_androguard_APK(signed).get_min_sdk_version()) self.assertEqual('18', fdroidserver.common.get_androguard_APK(signed).get_min_sdk_version())
shutil.copy(os.path.join(self.basedir, 'minimal_targetsdk_30_unsigned.apk'), self.testdir) shutil.copy(os.path.join(basedir, 'minimal_targetsdk_30_unsigned.apk'), self.testdir)
unsigned = os.path.join(self.testdir, 'minimal_targetsdk_30_unsigned.apk') unsigned = os.path.join(self.testdir, 'minimal_targetsdk_30_unsigned.apk')
signed = os.path.join(self.testdir, 'minimal_targetsdk_30.apk') signed = os.path.join(self.testdir, 'minimal_targetsdk_30.apk')
@ -959,7 +944,7 @@ class CommonTest(unittest.TestCase):
# verify it has a v2 signature # verify it has a v2 signature
self.assertTrue(fdroidserver.common.get_androguard_APK(signed).is_signed_v2()) self.assertTrue(fdroidserver.common.get_androguard_APK(signed).is_signed_v2())
shutil.copy(os.path.join(self.basedir, 'no_targetsdk_minsdk30_unsigned.apk'), self.testdir) shutil.copy(os.path.join(basedir, 'no_targetsdk_minsdk30_unsigned.apk'), self.testdir)
unsigned = os.path.join(self.testdir, 'no_targetsdk_minsdk30_unsigned.apk') unsigned = os.path.join(self.testdir, 'no_targetsdk_minsdk30_unsigned.apk')
signed = os.path.join(self.testdir, 'no_targetsdk_minsdk30_signed.apk') signed = os.path.join(self.testdir, 'no_targetsdk_minsdk30_signed.apk')
@ -967,7 +952,7 @@ class CommonTest(unittest.TestCase):
self.assertTrue(fdroidserver.common.verify_apk_signature(signed)) self.assertTrue(fdroidserver.common.verify_apk_signature(signed))
self.assertTrue(fdroidserver.common.get_androguard_APK(signed).is_signed_v2()) self.assertTrue(fdroidserver.common.get_androguard_APK(signed).is_signed_v2())
shutil.copy(os.path.join(self.basedir, 'no_targetsdk_minsdk1_unsigned.apk'), self.testdir) shutil.copy(os.path.join(basedir, 'no_targetsdk_minsdk1_unsigned.apk'), self.testdir)
unsigned = os.path.join(self.testdir, 'no_targetsdk_minsdk1_unsigned.apk') unsigned = os.path.join(self.testdir, 'no_targetsdk_minsdk1_unsigned.apk')
signed = os.path.join(self.testdir, 'no_targetsdk_minsdk1_signed.apk') signed = os.path.join(self.testdir, 'no_targetsdk_minsdk1_signed.apk')
@ -988,18 +973,18 @@ class CommonTest(unittest.TestCase):
config['keyalias'] = 'sova' config['keyalias'] = 'sova'
config['keystorepass'] = 'r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI=' config['keystorepass'] = 'r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI='
config['keypass'] = 'r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI=' config['keypass'] = 'r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI='
config['keystore'] = os.path.join(self.basedir, 'keystore.jks') config['keystore'] = os.path.join(basedir, 'keystore.jks')
fdroidserver.common.config = config fdroidserver.common.config = config
fdroidserver.signindex.config = config fdroidserver.signindex.config = config
unsigned = os.path.join(self.testdir, 'urzip-release-unsigned.apk') unsigned = os.path.join(self.testdir, 'urzip-release-unsigned.apk')
signed = os.path.join(self.testdir, 'urzip-release.apk') signed = os.path.join(self.testdir, 'urzip-release.apk')
shutil.copy(os.path.join(self.basedir, 'urzip-release-unsigned.apk'), self.testdir) shutil.copy(os.path.join(basedir, 'urzip-release-unsigned.apk'), self.testdir)
os.chmod(unsigned, 0o000) os.chmod(unsigned, 0o000)
with self.assertRaises(fdroidserver.exception.BuildException): with self.assertRaises(fdroidserver.exception.BuildException):
fdroidserver.common.sign_apk(unsigned, signed, config['keyalias']) fdroidserver.common.sign_apk(unsigned, signed, config['keyalias'])
os.chmod(unsigned, 0o777) os.chmod(unsigned, 0o777) # nosec B103
self.assertTrue(os.path.isfile(unsigned)) self.assertTrue(os.path.isfile(unsigned))
self.assertFalse(os.path.isfile(signed)) self.assertFalse(os.path.isfile(signed))
@ -1012,7 +997,7 @@ class CommonTest(unittest.TestCase):
config['keyalias'] = 'sova' config['keyalias'] = 'sova'
config['keystorepass'] = 'r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI=' config['keystorepass'] = 'r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI='
config['keypass'] = 'r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI=' config['keypass'] = 'r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI='
config['keystore'] = os.path.join(self.basedir, 'keystore.jks') config['keystore'] = os.path.join(basedir, 'keystore.jks')
fdroidserver.common.config = config fdroidserver.common.config = config
fdroidserver.signindex.config = config fdroidserver.signindex.config = config
@ -1039,7 +1024,7 @@ class CommonTest(unittest.TestCase):
config['keyalias'] = 'sova' config['keyalias'] = 'sova'
config['keystorepass'] = 'r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI=' config['keystorepass'] = 'r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI='
config['keypass'] = 'r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI=' config['keypass'] = 'r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI='
config['keystore'] = os.path.join(self.basedir, 'keystore.jks') config['keystore'] = os.path.join(basedir, 'keystore.jks')
fdroidserver.common.config = config fdroidserver.common.config = config
fdroidserver.signindex.config = config fdroidserver.signindex.config = config
@ -1052,7 +1037,7 @@ class CommonTest(unittest.TestCase):
'v2.only.sig_2.apk', 'v2.only.sig_2.apk',
'SystemWebView-repack.apk', 'SystemWebView-repack.apk',
): ):
original = os.path.join(self.basedir, apk) original = os.path.join(basedir, apk)
unsigned = os.path.join('unsigned', apk) unsigned = os.path.join('unsigned', apk)
resign = os.path.join('repo', apk) resign = os.path.join('repo', apk)
shutil.copy(original, unsigned) shutil.copy(original, unsigned)
@ -1149,7 +1134,7 @@ class CommonTest(unittest.TestCase):
fdroidserver.common.get_apk_id(badzip) fdroidserver.common.get_apk_id(badzip)
def test_get_apk_id_aapt_regex(self): def test_get_apk_id_aapt_regex(self):
files = glob.glob(os.path.join(self.basedir, 'build-tools', '[1-9]*.*', '*.txt')) files = glob.glob(os.path.join(basedir, 'build-tools', '[1-9]*.*', '*.txt'))
self.assertNotEqual(0, len(files)) self.assertNotEqual(0, len(files))
for f in files: for f in files:
appid, versionCode = os.path.splitext(os.path.basename(f))[0][12:].split('_') appid, versionCode = os.path.splitext(os.path.basename(f))[0][12:].split('_')
@ -1556,7 +1541,7 @@ class CommonTest(unittest.TestCase):
def test_remove_signing_keys(self): def test_remove_signing_keys(self):
shutil.copytree( shutil.copytree(
os.path.join(self.basedir, 'source-files'), os.path.join(basedir, 'source-files'),
os.path.join(self.tmpdir, 'source-files'), os.path.join(self.tmpdir, 'source-files'),
) )
os.chdir(self.tmpdir) os.chdir(self.tmpdir)
@ -1575,7 +1560,7 @@ class CommonTest(unittest.TestCase):
if not os.path.isdir(build_dir): if not os.path.isdir(build_dir):
continue continue
fdroidserver.common.remove_signing_keys(build_dir) fdroidserver.common.remove_signing_keys(build_dir)
fromfile = os.path.join(self.basedir, f) fromfile = os.path.join(basedir, f)
with open(f) as fp: with open(f) as fp:
content = fp.read() content = fp.read()
if 'signingConfig' in content: if 'signingConfig' in content:
@ -1605,7 +1590,7 @@ class CommonTest(unittest.TestCase):
if not os.path.isdir(build_dir): if not os.path.isdir(build_dir):
continue continue
fdroidserver.common.remove_signing_keys(build_dir) fdroidserver.common.remove_signing_keys(build_dir)
fromfile = os.path.join(self.basedir, f) fromfile = os.path.join(basedir, f)
with open(fromfile) as fp: with open(fromfile) as fp:
a = fp.readlines() a = fp.readlines()
with open(f) as fp: with open(f) as fp:
@ -1947,7 +1932,7 @@ class CommonTest(unittest.TestCase):
"""Make sure it is possible to use config.yml alone.""" """Make sure it is possible to use config.yml alone."""
os.chdir(self.tmpdir) os.chdir(self.tmpdir)
with mock.patch.dict(os.environ): with mock.patch.dict(os.environ):
os.environ['SECRET'] = 'mysecretpassword' os.environ['SECRET'] = 'mysecretpassword' # nosec B105
with open('config.yml', 'w') as fp: with open('config.yml', 'w') as fp:
fp.write("""keypass: {'env': 'SECRET'}""") fp.write("""keypass: {'env': 'SECRET'}""")
self.assertTrue(os.path.exists('config.yml')) self.assertTrue(os.path.exists('config.yml'))
@ -1983,7 +1968,7 @@ class CommonTest(unittest.TestCase):
with open('config.yml', 'w') as fp: with open('config.yml', 'w') as fp:
fp.write('keystore: foo.jks') fp.write('keystore: foo.jks')
self.assertTrue(os.path.exists(fp.name)) self.assertTrue(os.path.exists(fp.name))
os.chmod(fp.name, 0o666) os.chmod(fp.name, 0o666) # nosec B103
fdroidserver.common.read_config() fdroidserver.common.read_config()
os.remove(fp.name) os.remove(fp.name)
fdroidserver.common.config = None fdroidserver.common.config = None
@ -1991,7 +1976,7 @@ class CommonTest(unittest.TestCase):
with open('config.py', 'w') as fp: with open('config.py', 'w') as fp:
fp.write('keystore = "foo.jks"') fp.write('keystore = "foo.jks"')
self.assertTrue(os.path.exists(fp.name)) self.assertTrue(os.path.exists(fp.name))
os.chmod(fp.name, 0o666) os.chmod(fp.name, 0o666) # nosec B103
fdroidserver.common.read_config() fdroidserver.common.read_config()
def test_with_both_config_yml_py(self): def test_with_both_config_yml_py(self):
@ -2119,7 +2104,7 @@ class CommonTest(unittest.TestCase):
os.makedirs(os.path.dirname(apksigner)) os.makedirs(os.path.dirname(apksigner))
with open(apksigner, 'w') as fp: with open(apksigner, 'w') as fp:
fp.write('#!/bin/sh\ndate\n') fp.write('#!/bin/sh\ndate\n')
os.chmod(apksigner, 0o0755) os.chmod(apksigner, 0o0755) # nosec B103
config = {'apksigner': apksigner} config = {'apksigner': apksigner}
self.assertTrue(fdroidserver.common.test_sdk_exists(config)) self.assertTrue(fdroidserver.common.test_sdk_exists(config))
@ -2129,7 +2114,7 @@ class CommonTest(unittest.TestCase):
os.makedirs(os.path.dirname(apksigner)) os.makedirs(os.path.dirname(apksigner))
with open(apksigner, 'w') as fp: with open(apksigner, 'w') as fp:
fp.write('#!/bin/sh\ndate\n') fp.write('#!/bin/sh\ndate\n')
os.chmod(apksigner, 0o0755) os.chmod(apksigner, 0o0755) # nosec B103
config = {'apksigner': apksigner} config = {'apksigner': apksigner}
self.assertFalse(fdroidserver.common.test_sdk_exists(config)) self.assertFalse(fdroidserver.common.test_sdk_exists(config))
@ -2159,7 +2144,7 @@ class CommonTest(unittest.TestCase):
def test_loading_config_buildserver_yml(self): def test_loading_config_buildserver_yml(self):
"""Smoke check to make sure this file is properly parsed""" """Smoke check to make sure this file is properly parsed"""
os.chdir(self.tmpdir) os.chdir(self.tmpdir)
shutil.copy(os.path.join(self.basedir, '..', 'buildserver', 'config.buildserver.yml'), shutil.copy(os.path.join(basedir, '..', 'buildserver', 'config.buildserver.yml'),
'config.yml') 'config.yml')
self.assertFalse(os.path.exists('config.py')) self.assertFalse(os.path.exists('config.py'))
fdroidserver.common.read_config() fdroidserver.common.read_config()
@ -2238,7 +2223,7 @@ class CommonTest(unittest.TestCase):
@mock.patch.dict(os.environ, {'PATH': os.getenv('PATH')}, clear=True) @mock.patch.dict(os.environ, {'PATH': os.getenv('PATH')}, clear=True)
def test_get_android_tools_versions(self): def test_get_android_tools_versions(self):
sdk_path = os.path.join(self.basedir, 'get_android_tools_versions/android-sdk') sdk_path = os.path.join(basedir, 'get_android_tools_versions/android-sdk')
config = { config = {
'ndk_paths': {'r10e': os.path.join(sdk_path, '..', 'android-ndk-r10e')}, 'ndk_paths': {'r10e': os.path.join(sdk_path, '..', 'android-ndk-r10e')},
'sdk_path': sdk_path, 'sdk_path': sdk_path,
@ -2264,7 +2249,7 @@ class CommonTest(unittest.TestCase):
with tempfile.TemporaryDirectory() as tmpdir: with tempfile.TemporaryDirectory() as tmpdir:
sdk_path = Path(tmpdir) / 'get_android_tools_versions' sdk_path = Path(tmpdir) / 'get_android_tools_versions'
shutil.copytree( shutil.copytree(
os.path.join(self.basedir, 'get_android_tools_versions'), sdk_path os.path.join(basedir, 'get_android_tools_versions'), sdk_path
) )
shutil.rmtree(sdk_path / 'android-ndk-r10e') shutil.rmtree(sdk_path / 'android-ndk-r10e')
shutil.rmtree(sdk_path / 'android-sdk/ndk') shutil.rmtree(sdk_path / 'android-sdk/ndk')
@ -2329,7 +2314,7 @@ class CommonTest(unittest.TestCase):
fdroidserver.common.read_pkg_args(['org.fdroid.fdroid:foo'], allow_vercodes), fdroidserver.common.read_pkg_args(['org.fdroid.fdroid:foo'], allow_vercodes),
def test_apk_strip_v1_signatures(self): def test_apk_strip_v1_signatures(self):
before = os.path.join(self.basedir, 'no_targetsdk_minsdk1_unsigned.apk') before = os.path.join(basedir, 'no_targetsdk_minsdk1_unsigned.apk')
after = os.path.join(self.testdir, 'after.apk') after = os.path.join(self.testdir, 'after.apk')
shutil.copy(before, after) shutil.copy(before, after)
fdroidserver.common.apk_strip_v1_signatures(after, strip_manifest=False) fdroidserver.common.apk_strip_v1_signatures(after, strip_manifest=False)
@ -3156,7 +3141,7 @@ class SignerExtractionTest(unittest.TestCase):
""" """
def setUp(self): def setUp(self):
os.chdir(os.path.join(localmodule, 'tests')) os.chdir(basedir)
self._td = mkdtemp() self._td = mkdtemp()
self.testdir = self._td.name self.testdir = self._td.name
@ -3184,7 +3169,8 @@ class SignerExtractionTest(unittest.TestCase):
@unittest.skip("slow and only needed when adding to APKS_WITH_JAR_SIGNATURES") @unittest.skip("slow and only needed when adding to APKS_WITH_JAR_SIGNATURES")
def test_vs_keytool(self): def test_vs_keytool(self):
unittest.skipUnless(self.keytool, 'requires keytool to run') if not self.keytool:
self.skipTest('requires keytool to run')
pat = re.compile(r'[0-9A-F:]{95}') pat = re.compile(r'[0-9A-F:]{95}')
cmd = [self.keytool, '-printcert', '-jarfile'] cmd = [self.keytool, '-printcert', '-jarfile']
for apk, fingerprint in APKS_WITH_JAR_SIGNATURES: for apk, fingerprint in APKS_WITH_JAR_SIGNATURES:
@ -3199,7 +3185,8 @@ class SignerExtractionTest(unittest.TestCase):
@unittest.skip("slow and only needed when adding to APKS_WITH_JAR_SIGNATURES") @unittest.skip("slow and only needed when adding to APKS_WITH_JAR_SIGNATURES")
def test_vs_apksigner(self): def test_vs_apksigner(self):
unittest.skipUnless(self.apksigner, 'requires apksigner to run') if not self.apksigner:
self.skipTest('requires apksigner to run')
pat = re.compile(r'\s[0-9a-f]{64}\s') pat = re.compile(r'\s[0-9a-f]{64}\s')
cmd = [self.apksigner, 'verify', '--print-certs'] cmd = [self.apksigner, 'verify', '--print-certs']
for apk, fingerprint in APKS_WITH_JAR_SIGNATURES + APKS_WITHOUT_JAR_SIGNATURES: for apk, fingerprint in APKS_WITH_JAR_SIGNATURES + APKS_WITHOUT_JAR_SIGNATURES:
@ -3353,21 +3340,3 @@ class ConfigOptionsScopeTest(unittest.TestCase):
'config' not in vars() and 'config' not in globals(), 'config' not in vars() and 'config' not in globals(),
"The config should not be set in the global context, only module-level.", "The config should not be set in the global context, only module-level.",
) )
if __name__ == "__main__":
os.chdir(os.path.dirname(__file__))
parser = ArgumentParser()
parser.add_argument(
"-v",
"--verbose",
action="store_true",
default=False,
help="Spew out even more information than normal",
)
parse_args_for_test(parser, sys.argv)
newSuite = unittest.TestSuite()
newSuite.addTest(unittest.makeSuite(CommonTest))
unittest.main(failfast=False)

View File

@ -1,11 +1,8 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import configparser import configparser
import inspect
import logging
import os import os
import shutil import shutil
import sys
import tempfile import tempfile
import unittest import unittest
from pathlib import Path from pathlib import Path
@ -13,16 +10,10 @@ from unittest import mock
import git import git
localmodule = os.path.realpath( import fdroidserver
os.path.join(os.path.dirname(inspect.getfile(inspect.currentframe())), '..') from .testcommon import TmpCwd, mkdtemp
)
if localmodule not in sys.path:
sys.path.insert(0, localmodule)
import fdroidserver.common basedir = Path(__file__).parent
import fdroidserver.deploy
from fdroidserver.exception import FDroidException
from testcommon import TmpCwd, mkdtemp, parse_args_for_test
class Options: class Options:
@ -34,9 +25,7 @@ class DeployTest(unittest.TestCase):
'''fdroidserver/deploy.py''' '''fdroidserver/deploy.py'''
def setUp(self): def setUp(self):
logging.basicConfig(level=logging.DEBUG) os.chdir(basedir)
self.basedir = os.path.join(localmodule, 'tests')
os.chdir(self.basedir)
self._td = mkdtemp() self._td = mkdtemp()
self.testdir = self._td.name self.testdir = self._td.name
@ -281,7 +270,7 @@ class DeployTest(unittest.TestCase):
def test_update_serverwebroot_no_rsync_error(self): def test_update_serverwebroot_no_rsync_error(self):
os.environ['PATH'] = self.testdir os.environ['PATH'] = self.testdir
os.chdir(self.testdir) os.chdir(self.testdir)
with self.assertRaises(FDroidException): with self.assertRaises(fdroidserver.exception.FDroidException):
fdroidserver.deploy.update_serverwebroot('serverwebroot', 'repo') fdroidserver.deploy.update_serverwebroot('serverwebroot', 'repo')
def test_update_serverwebroot_make_cur_version_link(self): def test_update_serverwebroot_make_cur_version_link(self):
@ -981,7 +970,7 @@ class DeployTest(unittest.TestCase):
for file in files_to_upload for file in files_to_upload
] ]
mock_driver.upload_object_via_stream.assert_has_calls(calls, any_order=True) mock_driver.upload_object_via_stream.assert_has_calls(calls, any_order=True)
assert mock_driver.upload_object_via_stream.call_count == 2 self.assertEqual(mock_driver.upload_object_via_stream.call_count, 2)
def test_update_awsbucket_libcloud_in_index_only_mode(self): def test_update_awsbucket_libcloud_in_index_only_mode(self):
from libcloud.storage.base import Container from libcloud.storage.base import Container
@ -1047,7 +1036,7 @@ class DeployTest(unittest.TestCase):
calls, calls,
any_order=False, any_order=False,
) )
assert mock_driver.upload_object_via_stream.call_count == 1 self.assertEqual(mock_driver.upload_object_via_stream.call_count, 1)
def test_update_servergitmirrors(self): def test_update_servergitmirrors(self):
# setup parameters for this test run # setup parameters for this test run
@ -1461,7 +1450,7 @@ class Test_UploadToGithubReleasesRepo(unittest.TestCase):
) )
def test_local_token(self): def test_local_token(self):
self.repo_conf["token"] = "local_token" self.repo_conf["token"] = "local_token" # nosec B105
with unittest.mock.patch("fdroidserver.github.GithubApi", self.api_constructor): with unittest.mock.patch("fdroidserver.github.GithubApi", self.api_constructor):
fdroidserver.deploy.upload_to_github_releases_repo( fdroidserver.deploy.upload_to_github_releases_repo(
self.repo_conf, self.repo_conf,
@ -1488,25 +1477,3 @@ class Test_UploadToGithubReleasesRepo(unittest.TestCase):
), ),
], ],
) )
if __name__ == "__main__":
os.chdir(os.path.dirname(__file__))
import argparse
parser = argparse.ArgumentParser()
parser.add_argument(
"-v",
"--verbose",
action="store_true",
default=False,
help="Spew out even more information than normal",
)
parse_args_for_test(parser, sys.argv)
newSuite = unittest.TestSuite()
newSuite.addTest(unittest.makeSuite(DeployTest))
newSuite.addTest(unittest.makeSuite(GitHubReleasesTest))
newSuite.addTest(unittest.makeSuite(Test_UploadToGithubReleasesRepo))
unittest.main(failfast=False)

View File

@ -1,21 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# http://www.drdobbs.com/testing/unit-testing-with-python/240165163
import inspect
import os
import sys
import unittest import unittest
import fdroidserver
localmodule = os.path.realpath(
os.path.join(os.path.dirname(inspect.getfile(inspect.currentframe())), '..')
)
print('localmodule: ' + localmodule)
if localmodule not in sys.path:
sys.path.insert(0, localmodule)
import fdroidserver.common
import fdroidserver.exception
class ExceptionTest(unittest.TestCase): class ExceptionTest(unittest.TestCase):
@ -51,24 +37,3 @@ class ExceptionTest(unittest.TestCase):
raise fdroidserver.exception.FDroidException(('one', 'two', 'three')) raise fdroidserver.exception.FDroidException(('one', 'two', 'three'))
except fdroidserver.exception.FDroidException as e: except fdroidserver.exception.FDroidException as e:
str(e) str(e)
if __name__ == "__main__":
os.chdir(os.path.dirname(__file__))
import argparse
from testcommon import parse_args_for_test
parser = argparse.ArgumentParser()
parser.add_argument(
"-v",
"--verbose",
action="store_true",
default=False,
help="Spew out even more information than normal",
)
parse_args_for_test(parser, sys.argv)
newSuite = unittest.TestSuite()
newSuite.addTest(unittest.makeSuite(ExceptionTest))
unittest.main(failfast=False)

View File

@ -1,21 +1,10 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import inspect import unittest
import optparse
import os
import sys
import unittest.mock import unittest.mock
import testcommon
localmodule = os.path.realpath( from .testcommon import mock_urlopen
os.path.join(os.path.dirname(inspect.getfile(inspect.currentframe())), '..') import fdroidserver
)
print('localmodule: ' + localmodule)
if localmodule not in sys.path:
sys.path.insert(0, localmodule)
import fdroidserver.github
import fdroidserver.common
class GithubApiTest(unittest.TestCase): class GithubApiTest(unittest.TestCase):
@ -40,7 +29,7 @@ class GithubApiTest(unittest.TestCase):
def test_list_released_tags(self): def test_list_released_tags(self):
api = fdroidserver.github.GithubApi('faketoken', 'fakerepopath') api = fdroidserver.github.GithubApi('faketoken', 'fakerepopath')
uomock = testcommon.mock_urlopen( uomock = mock_urlopen(
body='[{"tag_name": "fake"}, {"tag_name": "double_fake"}]' body='[{"tag_name": "fake"}, {"tag_name": "double_fake"}]'
) )
with unittest.mock.patch("urllib.request.urlopen", uomock): with unittest.mock.patch("urllib.request.urlopen", uomock):
@ -59,7 +48,7 @@ class GithubApiTest(unittest.TestCase):
def test_tag_exists(self): def test_tag_exists(self):
api = fdroidserver.github.GithubApi('faketoken', 'fakerepopath') api = fdroidserver.github.GithubApi('faketoken', 'fakerepopath')
uomock = testcommon.mock_urlopen(body='[{"ref": "refs/tags/fake_tag"}]') uomock = mock_urlopen(body='[{"ref": "refs/tags/fake_tag"}]')
with unittest.mock.patch("urllib.request.urlopen", uomock): with unittest.mock.patch("urllib.request.urlopen", uomock):
result = api.tag_exists('fake_tag') result = api.tag_exists('fake_tag')
self.assertTrue(result) self.assertTrue(result)
@ -67,7 +56,7 @@ class GithubApiTest(unittest.TestCase):
def test_tag_exists_failure(self): def test_tag_exists_failure(self):
api = fdroidserver.github.GithubApi('faketoken', 'fakerepopath') api = fdroidserver.github.GithubApi('faketoken', 'fakerepopath')
uomock = testcommon.mock_urlopen(body='[{"error": "failure"}]') uomock = mock_urlopen(body='[{"error": "failure"}]')
with unittest.mock.patch("urllib.request.urlopen", uomock): with unittest.mock.patch("urllib.request.urlopen", uomock):
success = api.tag_exists('fake_tag') success = api.tag_exists('fake_tag')
@ -77,7 +66,7 @@ class GithubApiTest(unittest.TestCase):
def test_list_all_tags(self): def test_list_all_tags(self):
api = fdroidserver.github.GithubApi('faketoken', 'fakerepopath') api = fdroidserver.github.GithubApi('faketoken', 'fakerepopath')
uomock = testcommon.mock_urlopen( uomock = mock_urlopen(
body='[{"ref": "refs/tags/fake"}, {"ref": "refs/tags/double_fake"}]' body='[{"ref": "refs/tags/fake"}, {"ref": "refs/tags/double_fake"}]'
) )
@ -89,7 +78,7 @@ class GithubApiTest(unittest.TestCase):
def test_create_release(self): def test_create_release(self):
api = fdroidserver.github.GithubApi('faketoken', 'fakerepopath') api = fdroidserver.github.GithubApi('faketoken', 'fakerepopath')
uomock = testcommon.mock_urlopen(body='{"id": "fakeid"}') uomock = mock_urlopen(body='{"id": "fakeid"}')
api.tag_exists = lambda x: True api.tag_exists = lambda x: True
api._create_release_asset = unittest.mock.Mock() api._create_release_asset = unittest.mock.Mock()
@ -116,7 +105,7 @@ class GithubApiTest(unittest.TestCase):
def test__create_release_asset(self): def test__create_release_asset(self):
api = fdroidserver.github.GithubApi('faketoken', 'fakerepopath') api = fdroidserver.github.GithubApi('faketoken', 'fakerepopath')
uomock = testcommon.mock_urlopen() uomock = mock_urlopen()
with unittest.mock.patch( with unittest.mock.patch(
'fdroidserver.github.open', 'fdroidserver.github.open',
@ -144,21 +133,3 @@ class GithubApiTest(unittest.TestCase):
}, },
) )
self.assertEqual(req.data, b'fake_content') self.assertEqual(req.data, b'fake_content')
if __name__ == "__main__":
os.chdir(os.path.dirname(__file__))
parser = optparse.OptionParser()
parser.add_option(
"-v",
"--verbose",
action="store_true",
default=False,
help="Spew out even more information than normal",
)
(fdroidserver.common.options, args) = parser.parse_args(["--verbose"])
newSuite = unittest.TestSuite()
newSuite.addTest(unittest.makeSuite(GithubApiTest))
unittest.main(failfast=False)

View File

@ -1,31 +1,20 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import inspect
import json import json
import logging
import os import os
import shutil import shutil
import sys
import tempfile import tempfile
import unittest import unittest
localmodule = os.path.realpath(
os.path.join(os.path.dirname(inspect.getfile(inspect.currentframe())), '..')
)
print('localmodule: ' + localmodule)
if localmodule not in sys.path:
sys.path.insert(0, localmodule)
from fdroidserver import common, gpgsign from fdroidserver import common, gpgsign
from pathlib import Path from pathlib import Path
from unittest.mock import MagicMock, patch from unittest.mock import MagicMock, patch
basedir = Path(__file__).parent
class GpgsignTest(unittest.TestCase): class GpgsignTest(unittest.TestCase):
basedir = Path(__file__).resolve().parent
def setUp(self): def setUp(self):
logging.basicConfig(level=logging.DEBUG)
self.tempdir = tempfile.TemporaryDirectory() self.tempdir = tempfile.TemporaryDirectory()
os.chdir(self.tempdir.name) os.chdir(self.tempdir.name)
self.repodir = Path('repo') self.repodir = Path('repo')
@ -34,7 +23,7 @@ class GpgsignTest(unittest.TestCase):
gpgsign.config = None gpgsign.config = None
config = common.read_config() config = common.read_config()
config['verbose'] = True config['verbose'] = True
config['gpghome'] = str((self.basedir / 'gnupghome').resolve()) config['gpghome'] = str((basedir / 'gnupghome').resolve())
config['gpgkey'] = '1DBA2E89' config['gpgkey'] = '1DBA2E89'
gpgsign.config = config gpgsign.config = config
@ -46,8 +35,8 @@ class GpgsignTest(unittest.TestCase):
def test_sign_index(self, FDroidPopen): def test_sign_index(self, FDroidPopen):
"""This skips running gpg because its hard to setup in a test env""" """This skips running gpg because its hard to setup in a test env"""
index_v1_json = 'repo/index-v1.json' index_v1_json = 'repo/index-v1.json'
shutil.copy(str(self.basedir / index_v1_json), 'repo') shutil.copy(basedir / index_v1_json, 'repo')
shutil.copy(str(self.basedir / 'SpeedoMeterApp.main_1.apk'), 'repo') shutil.copy(basedir / 'SpeedoMeterApp.main_1.apk', 'repo')
def _side_effect(gpg): def _side_effect(gpg):
f = gpg[-1] f = gpg[-1]
@ -68,24 +57,4 @@ class GpgsignTest(unittest.TestCase):
# smoke check status JSON # smoke check status JSON
with (self.repodir / 'status/gpgsign.json').open() as fp: with (self.repodir / 'status/gpgsign.json').open() as fp:
data = json.load(fp) data = json.load(fp)
self.assertTrue('index-v1.json' in data['signed']) self.assertIn('index-v1.json', data['signed'])
if __name__ == "__main__":
os.chdir(os.path.dirname(__file__))
import argparse
parser = argparse.ArgumentParser()
parser.add_argument(
"-v",
"--verbose",
action="store_true",
default=False,
help="Spew out even more information than normal",
)
common.parse_args(parser)
newSuite = unittest.TestSuite()
newSuite.addTest(unittest.makeSuite(GpgsignTest))
unittest.main(failfast=False)

View File

@ -1,7 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# http://www.drdobbs.com/testing/unit-testing-with-python/240165163
import logging import logging
import os import os
import shutil import shutil
@ -15,31 +13,25 @@ import git
import requests import requests
import yaml import yaml
localmodule = Path(__file__).resolve().parent.parent from .testcommon import TmpCwd, mkdtemp
print('localmodule: ' + str(localmodule))
if localmodule not in sys.path:
sys.path.insert(0, str(localmodule))
from testcommon import TmpCwd, mkdtemp, parse_args_for_test import fdroidserver
import fdroidserver.common
import fdroidserver.import_subcommand import fdroidserver.import_subcommand
import fdroidserver.metadata
from fdroidserver.exception import FDroidException basedir = Path(__file__).parent
logging.basicConfig(level=logging.DEBUG)
class ImportTest(unittest.TestCase): class ImportTest(unittest.TestCase):
'''fdroid import''' '''fdroid import'''
def setUp(self): def setUp(self):
logging.basicConfig(level=logging.DEBUG) os.chdir(basedir)
self.basedir = localmodule / 'tests'
os.chdir(self.basedir)
self._td = mkdtemp() self._td = mkdtemp()
self.testdir = self._td.name self.testdir = self._td.name
def tearDown(self): def tearDown(self):
os.chdir(self.basedir) os.chdir(basedir)
self._td.cleanup() self._td.cleanup()
def test_get_all_gradle_and_manifests(self): def test_get_all_gradle_and_manifests(self):
@ -63,7 +55,7 @@ class ImportTest(unittest.TestCase):
paths = [Path('source-files/cn.wildfirechat.chat') / path for path in paths] paths = [Path('source-files/cn.wildfirechat.chat') / path for path in paths]
self.assertEqual(sorted(paths), sorted(a)) self.assertEqual(sorted(paths), sorted(a))
abspath = Path(self.basedir) / 'source-files/realm' abspath = basedir / 'source-files/realm'
p = fdroidserver.import_subcommand.get_all_gradle_and_manifests(abspath) p = fdroidserver.import_subcommand.get_all_gradle_and_manifests(abspath)
self.assertEqual(1, len(p)) self.assertEqual(1, len(p))
self.assertTrue(p[0].is_relative_to(abspath)) self.assertTrue(p[0].is_relative_to(abspath))
@ -99,6 +91,7 @@ class ImportTest(unittest.TestCase):
print('Skipping ImportTest!') print('Skipping ImportTest!')
return return
fdroidserver.common.options = type('Options', (), {'verbose': False})
app = fdroidserver.import_subcommand.get_app_from_url(url) app = fdroidserver.import_subcommand.get_app_from_url(url)
fdroidserver.import_subcommand.clone_to_tmp_dir(app) fdroidserver.import_subcommand.clone_to_tmp_dir(app)
self.assertEqual(app.RepoType, 'git') self.assertEqual(app.RepoType, 'git')
@ -134,7 +127,7 @@ class ImportTest(unittest.TestCase):
tmp_importer, tmp_importer,
onerror=fdroidserver.import_subcommand.handle_retree_error_on_windows, onerror=fdroidserver.import_subcommand.handle_retree_error_on_windows,
) )
shutil.copytree(self.basedir / 'source-files' / appid, tmp_importer) shutil.copytree(basedir / 'source-files' / appid, tmp_importer)
app = fdroidserver.import_subcommand.get_app_from_url(url) app = fdroidserver.import_subcommand.get_app_from_url(url)
with mock.patch( with mock.patch(
@ -185,7 +178,7 @@ class ImportTest(unittest.TestCase):
the network, if it gets past the code that throws the error. the network, if it gets past the code that throws the error.
""" """
with self.assertRaises(FDroidException): with self.assertRaises(fdroidserver.exception.FDroidException):
fdroidserver.import_subcommand.main() fdroidserver.import_subcommand.main()
@mock.patch('sys.argv', ['fdroid import', '-u', 'https://fake/git/url.git']) @mock.patch('sys.argv', ['fdroid import', '-u', 'https://fake/git/url.git'])
@ -195,29 +188,12 @@ class ImportTest(unittest.TestCase):
def test_main_local_git(self): def test_main_local_git(self):
os.chdir(self.testdir) os.chdir(self.testdir)
git.Repo.init('td') git.Repo.init('td')
with Path('td/build.gradle').open('w') as fp: Path('td/build.gradle').write_text(
fp.write('android { defaultConfig { applicationId "com.example" } }') 'android { defaultConfig { applicationId "com.example" } }'
)
fdroidserver.import_subcommand.main() fdroidserver.import_subcommand.main()
with open('metadata/com.example.yml') as fp: with open('metadata/com.example.yml') as fp:
data = yaml.safe_load(fp) data = yaml.safe_load(fp)
self.assertEqual(data['Repo'], sys.argv[2]) self.assertEqual(data['Repo'], sys.argv[2])
self.assertEqual(data['RepoType'], 'git') self.assertEqual(data['RepoType'], 'git')
self.assertEqual(1, len(data['Builds'])) self.assertEqual(1, len(data['Builds']))
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser()
parser.add_argument(
"-v",
"--verbose",
action="store_true",
default=False,
help="Spew out even more information than normal",
)
parse_args_for_test(parser, sys.argv)
newSuite = unittest.TestSuite()
newSuite.addTest(unittest.makeSuite(ImportTest))
unittest.main(failfast=False)

View File

@ -3,11 +3,9 @@
import copy import copy
import datetime import datetime
import glob import glob
import inspect
import logging
import os import os
import sys
import unittest import unittest
from pathlib import Path
import yaml import yaml
import zipfile import zipfile
from unittest.mock import patch from unittest.mock import patch
@ -16,17 +14,12 @@ import tempfile
import json import json
import shutil import shutil
localmodule = os.path.realpath(
os.path.join(os.path.dirname(inspect.getfile(inspect.currentframe())), '..')
)
print('localmodule: ' + localmodule)
if localmodule not in sys.path:
sys.path.insert(0, localmodule)
import fdroidserver import fdroidserver
from fdroidserver import common, index, publish, signindex, update from fdroidserver import common, index, publish, signindex, update
from testcommon import GP_FINGERPRINT, TmpCwd, mkdtemp, parse_args_for_test from .testcommon import GP_FINGERPRINT, TmpCwd, mkdtemp
from pathlib import Path
basedir = Path(__file__).parent
class Options: class Options:
@ -38,17 +31,15 @@ class Options:
class IndexTest(unittest.TestCase): class IndexTest(unittest.TestCase):
@classmethod @classmethod
def setUpClass(cls): def setUpClass(cls):
cls.basedir = os.path.join(localmodule, 'tests')
# TODO something should remove cls.index_v1_jar, but it was # TODO something should remove cls.index_v1_jar, but it was
# causing the tests to be flaky. There seems to be something # causing the tests to be flaky. There seems to be something
# that is running the background somehow, maybe sign_index() # that is running the background somehow, maybe sign_index()
# exits before jarsigner actually finishes? # exits before jarsigner actually finishes?
cls.index_v1_jar = os.path.join(cls.basedir, 'repo', 'index-v1.jar') cls.index_v1_jar = basedir / 'repo' / 'index-v1.jar'
def setUp(self): def setUp(self):
logging.basicConfig(level=logging.ERROR) (basedir / 'config.py').chmod(0o600)
os.chmod(os.path.join(self.basedir, 'config.py'), 0o600) os.chdir(basedir) # so read_config() can find config.py
os.chdir(self.basedir) # so read_config() can find config.py
common.config = None common.config = None
common.options = Options common.options = Options
@ -65,11 +56,11 @@ class IndexTest(unittest.TestCase):
self._td.cleanup() self._td.cleanup()
def _sign_test_index_v1_jar(self): def _sign_test_index_v1_jar(self):
if not os.path.exists(self.index_v1_jar): if not self.index_v1_jar.exists():
signindex.sign_index(os.path.dirname(self.index_v1_jar), 'index-v1.json') signindex.sign_index(self.index_v1_jar.parent, 'index-v1.json')
def test_get_public_key_from_jar_succeeds(self): def test_get_public_key_from_jar_succeeds(self):
source_dir = os.path.join(self.basedir, 'signindex') source_dir = basedir / 'signindex'
for f in ('testy.jar', 'guardianproject.jar'): for f in ('testy.jar', 'guardianproject.jar'):
testfile = os.path.join(source_dir, f) testfile = os.path.join(source_dir, f)
jar = zipfile.ZipFile(testfile) jar = zipfile.ZipFile(testfile)
@ -85,7 +76,7 @@ class IndexTest(unittest.TestCase):
self.assertTrue(fingerprint == GP_FINGERPRINT) self.assertTrue(fingerprint == GP_FINGERPRINT)
def test_get_public_key_from_jar_fails(self): def test_get_public_key_from_jar_fails(self):
source_dir = os.path.join(self.basedir, 'signindex') source_dir = basedir / 'signindex'
testfile = os.path.join(source_dir, 'unsigned.jar') testfile = os.path.join(source_dir, 'unsigned.jar')
jar = zipfile.ZipFile(testfile) jar = zipfile.ZipFile(testfile)
with self.assertRaises(index.VerificationException): with self.assertRaises(index.VerificationException):
@ -186,10 +177,10 @@ class IndexTest(unittest.TestCase):
self.testdir, 'repo', os.path.basename(mirrors[0]['url']) self.testdir, 'repo', os.path.basename(mirrors[0]['url'])
) )
os.chdir(self.testdir) os.chdir(self.testdir)
signindex.config['keystore'] = os.path.join(self.basedir, 'keystore.jks') signindex.config['keystore'] = os.path.join(basedir, 'keystore.jks')
os.mkdir('repo') os.mkdir('repo')
shutil.copy(os.path.join(self.basedir, 'repo', 'entry.json'), 'repo') shutil.copy(basedir / 'repo' / 'entry.json', 'repo')
shutil.copy(os.path.join(self.basedir, 'repo', 'index-v2.json'), 'repo') shutil.copy(basedir / 'repo' / 'index-v2.json', 'repo')
signindex.sign_index('repo', 'entry.json') signindex.sign_index('repo', 'entry.json')
repo_url = 'https://fake.url/fdroid/repo' repo_url = 'https://fake.url/fdroid/repo'
entry_url = 'https://fake.url/fdroid/repo/entry.jar' entry_url = 'https://fake.url/fdroid/repo/entry.jar'
@ -209,10 +200,10 @@ class IndexTest(unittest.TestCase):
self.testdir, 'repo', os.path.basename(mirrors[0]['url']) self.testdir, 'repo', os.path.basename(mirrors[0]['url'])
) )
os.chdir(self.testdir) os.chdir(self.testdir)
signindex.config['keystore'] = os.path.join(self.basedir, 'keystore.jks') signindex.config['keystore'] = os.path.join(basedir, 'keystore.jks')
os.mkdir('repo') os.mkdir('repo')
shutil.copy(os.path.join(self.basedir, 'repo', 'entry.json'), 'repo') shutil.copy(basedir / 'repo' / 'entry.json', 'repo')
shutil.copy(os.path.join(self.basedir, 'repo', 'index-v2.json'), 'repo') shutil.copy(basedir / 'repo' / 'index-v2.json', 'repo')
signindex.sign_index('repo', 'entry.json') signindex.sign_index('repo', 'entry.json')
bad_fp = '0123456789001234567890012345678900123456789001234567890012345678' bad_fp = '0123456789001234567890012345678900123456789001234567890012345678'
bad_fp_url = 'https://fake.url/fdroid/repo?fingerprint=' + bad_fp bad_fp_url = 'https://fake.url/fdroid/repo?fingerprint=' + bad_fp
@ -240,10 +231,10 @@ class IndexTest(unittest.TestCase):
mock_download_using_mirrors.side_effect = download_using_mirrors_def mock_download_using_mirrors.side_effect = download_using_mirrors_def
os.chdir(self.testdir) os.chdir(self.testdir)
signindex.config['keystore'] = os.path.join(self.basedir, 'keystore.jks') signindex.config['keystore'] = os.path.join(basedir, 'keystore.jks')
os.mkdir('repo') os.mkdir('repo')
shutil.copy(os.path.join(self.basedir, 'repo', 'entry.json'), 'repo') shutil.copy(basedir / 'repo' / 'entry.json', 'repo')
shutil.copy(os.path.join(self.basedir, 'repo', 'index-v2.json'), 'repo') shutil.copy(basedir / 'repo' / 'index-v2.json', 'repo')
signindex.sign_index('repo', 'entry.json') signindex.sign_index('repo', 'entry.json')
url = 'https://fake.url/fdroid/repo?fingerprint=' + GP_FINGERPRINT url = 'https://fake.url/fdroid/repo?fingerprint=' + GP_FINGERPRINT
with self.assertRaises(fdroidserver.exception.VerificationException): with self.assertRaises(fdroidserver.exception.VerificationException):
@ -438,7 +429,7 @@ class IndexTest(unittest.TestCase):
os.mkdir('metadata') os.mkdir('metadata')
os.mkdir('repo') os.mkdir('repo')
metadatafile = 'metadata/info.zwanenburg.caffeinetile.yml' metadatafile = 'metadata/info.zwanenburg.caffeinetile.yml'
shutil.copy(os.path.join(self.basedir, metadatafile), metadatafile) shutil.copy(os.path.join(basedir, metadatafile), metadatafile)
repo_icons_dir = os.path.join('repo', 'icons') repo_icons_dir = os.path.join('repo', 'icons')
self.assertFalse(os.path.isdir(repo_icons_dir)) self.assertFalse(os.path.isdir(repo_icons_dir))
repodict = { repodict = {
@ -648,13 +639,13 @@ class IndexTest(unittest.TestCase):
html = f.read() html = f.read()
pretty_html = HTMLBeautifier.beautify(html) pretty_html = HTMLBeautifier.beautify(html)
self.maxDiff = None self.maxDiff = None
self.assertEquals(html, pretty_html) self.assertEqual(html, pretty_html)
with open(os.path.join("repo", "index.css")) as f: with open(os.path.join("repo", "index.css")) as f:
css = f.read() css = f.read()
pretty_css = CSSBeautifier.beautify(css) pretty_css = CSSBeautifier.beautify(css)
self.maxDiff = None self.maxDiff = None
self.assertEquals(css, pretty_css) self.assertEqual(css, pretty_css)
def test_v1_sort_packages_with_invalid(self): def test_v1_sort_packages_with_invalid(self):
i = [ i = [
@ -729,7 +720,6 @@ class IndexTest(unittest.TestCase):
c = {'repo_url': repo_url, 'mirrors': ['http://one/fdroid']} c = {'repo_url': repo_url, 'mirrors': ['http://one/fdroid']}
with open('config.yml', 'w') as fp: with open('config.yml', 'w') as fp:
yaml.dump(c, fp) yaml.dump(c, fp)
os.system('cat config.yml')
common.config = None common.config = None
common.read_config() common.read_config()
repodict = {'address': common.config['repo_url']} repodict = {'address': common.config['repo_url']}
@ -866,8 +856,7 @@ class AltstoreIndexTest(unittest.TestCase):
with tempfile.TemporaryDirectory() as tmpdir, TmpCwd(tmpdir): with tempfile.TemporaryDirectory() as tmpdir, TmpCwd(tmpdir):
repodir = Path(tmpdir) / 'repo' repodir = Path(tmpdir) / 'repo'
repodir.mkdir() repodir.mkdir()
with open(repodir / "fake.ipa", "w") as f: (repodir / "fake.ipa").touch()
f.write("")
fdroidserver.index.make_altstore( fdroidserver.index.make_altstore(
apps, apps,
@ -916,24 +905,3 @@ class AltstoreIndexTest(unittest.TestCase):
}, },
json.load(f), json.load(f),
) )
if __name__ == "__main__":
os.chdir(os.path.dirname(__file__))
import argparse
parser = argparse.ArgumentParser()
parser.add_argument(
"-v",
"--verbose",
action="store_true",
default=False,
help="Spew out even more information than normal",
)
parse_args_for_test(parser, sys.argv)
newSuite = unittest.TestSuite()
newSuite.addTest(unittest.makeSuite(IndexTest))
newSuite.addTest(unittest.makeSuite(AltstoreIndexTest))
unittest.main(failfast=False)

58
tests/test_init.py Executable file
View File

@ -0,0 +1,58 @@
#!/usr/bin/env python3
import os
import pathlib
import shutil
import sys
import unittest
import fdroidserver.common
import fdroidserver.init
from . import testcommon
basedir = pathlib.Path(__file__).parent
class InitTest(unittest.TestCase):
'''fdroidserver/init.py'''
def setUp(self):
fdroidserver.common.config = None
fdroidserver.init.config = None
self._td = testcommon.mkdtemp()
self.testdir = self._td.name
os.chdir(self.testdir)
def tearDown(self):
os.chdir(basedir)
self._td.cleanup()
def test_disable_in_config(self):
configfile = pathlib.Path('config.yml')
configfile.write_text('keystore: NONE\nkeypass: mysupersecrets\n')
configfile.chmod(0o600)
config = fdroidserver.common.read_config()
self.assertEqual('NONE', config['keystore'])
self.assertEqual('mysupersecrets', config['keypass'])
fdroidserver.init.disable_in_config('keypass', 'comment')
self.assertIn('#keypass:', configfile.read_text())
fdroidserver.common.config = None
config = fdroidserver.common.read_config()
self.assertIsNone(config.get('keypass'))
@unittest.skipIf(os.name == 'nt', "calling main() like this hangs on Windows")
def test_main_in_empty_dir(self):
"""Test that `fdroid init` will find apksigner and add it to the config"""
shutil.copy(basedir / 'keystore.jks', self.testdir)
bindir = os.path.join(os.getcwd(), 'bin')
os.mkdir(bindir)
apksigner = os.path.join(bindir, 'apksigner')
open(apksigner, 'w').close()
os.chmod(apksigner, 0o755) # nosec B103
sys.argv = ['fdroid init', '--keystore', 'keystore.jks', '--repo-keyalias=sova']
with unittest.mock.patch.dict(os.environ, {'PATH': bindir}):
fdroidserver.init.main()
self.assertEqual(apksigner, fdroidserver.init.config.get('apksigner'))

View File

@ -1,23 +1,12 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# http://www.drdobbs.com/testing/unit-testing-with-python/240165163
import inspect
import os import os
import sys
import textwrap import textwrap
import unittest import unittest
from pathlib import Path from pathlib import Path
from unittest.mock import Mock, patch from unittest.mock import Mock, patch
localmodule = os.path.realpath(
os.path.join(os.path.dirname(inspect.getfile(inspect.currentframe())), '..')
)
print('localmodule: ' + localmodule)
if localmodule not in sys.path:
sys.path.insert(0, localmodule)
import fdroidserver import fdroidserver
from fdroidserver import common, install from fdroidserver import common, install
from fdroidserver.exception import BuildException, FDroidException from fdroidserver.exception import BuildException, FDroidException
@ -265,24 +254,3 @@ class InstallTest(unittest.TestCase):
def test_download_fdroid_apk_from_github(self): def test_download_fdroid_apk_from_github(self):
f = install.download_fdroid_apk_from_github() f = install.download_fdroid_apk_from_github()
self.assertTrue(Path(f).exists()) self.assertTrue(Path(f).exists())
if __name__ == "__main__":
os.chdir(os.path.dirname(__file__))
import argparse
from testcommon import parse_args_for_test
parser = argparse.ArgumentParser()
parser.add_argument(
"-v",
"--verbose",
action="store_true",
default=False,
help="Spew out even more information than normal",
)
fdroidserver.install.options = parse_args_for_test(parser, sys.argv)
newSuite = unittest.TestSuite()
newSuite.addTest(unittest.makeSuite(InstallTest))
unittest.main(failfast=False)

View File

@ -1,39 +1,28 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# http://www.drdobbs.com/testing/unit-testing-with-python/240165163
import logging import logging
import os import os
import shutil import shutil
import sys
import tempfile import tempfile
import unittest import unittest
from pathlib import Path from pathlib import Path
import ruamel.yaml import ruamel.yaml
localmodule = Path(__file__).resolve().parent.parent from .testcommon import mkdtemp
print('localmodule: ' + str(localmodule))
if localmodule not in sys.path:
sys.path.insert(0, str(localmodule))
from testcommon import mkdtemp, parse_args_for_test
import fdroidserver.common import fdroidserver.common
import fdroidserver.lint import fdroidserver.lint
import fdroidserver.metadata import fdroidserver.metadata
from fdroidserver.common import CATEGORIES_CONFIG_NAME
basedir = Path(__file__).parent
class LintTest(unittest.TestCase): class LintTest(unittest.TestCase):
'''fdroidserver/lint.py''' '''fdroidserver/lint.py'''
def setUp(self): def setUp(self):
logging.basicConfig(level=logging.DEBUG) os.chdir(basedir)
self.basedir = localmodule / 'tests'
self.tmpdir = localmodule / '.testfiles'
self.tmpdir.mkdir(exist_ok=True)
os.chdir(self.basedir)
fdroidserver.common.config = None fdroidserver.common.config = None
fdroidserver.lint.config = None fdroidserver.lint.config = None
fdroidserver.lint.CATEGORIES_KEYS = None fdroidserver.lint.CATEGORIES_KEYS = None
@ -46,13 +35,13 @@ class LintTest(unittest.TestCase):
def test_check_for_unsupported_metadata_files(self): def test_check_for_unsupported_metadata_files(self):
self.assertTrue(fdroidserver.lint.check_for_unsupported_metadata_files()) self.assertTrue(fdroidserver.lint.check_for_unsupported_metadata_files())
with tempfile.TemporaryDirectory(dir=str(self.tmpdir)) as testdir: with tempfile.TemporaryDirectory() as testdir:
testdir = Path(testdir) testdir = Path(testdir)
self.assertFalse( self.assertFalse(
fdroidserver.lint.check_for_unsupported_metadata_files(testdir) fdroidserver.lint.check_for_unsupported_metadata_files(testdir)
) )
shutil.copytree( shutil.copytree(
self.basedir / 'metadata', basedir / 'metadata',
testdir / 'metadata', testdir / 'metadata',
ignore=shutil.ignore_patterns('apk', 'dump', '*.json'), ignore=shutil.ignore_patterns('apk', 'dump', '*.json'),
) )
@ -326,7 +315,9 @@ class LintTest(unittest.TestCase):
self.assertFalse(anywarns) self.assertFalse(anywarns)
def test_check_categories_in_config(self): def test_check_categories_in_config(self):
fdroidserver.lint.config = {CATEGORIES_CONFIG_NAME: ['InConfig']} fdroidserver.lint.config = {
fdroidserver.common.CATEGORIES_CONFIG_NAME: ['InConfig']
}
fdroidserver.lint.load_categories_config() fdroidserver.lint.load_categories_config()
app = fdroidserver.metadata.App({'Categories': ['InConfig']}) app = fdroidserver.metadata.App({'Categories': ['InConfig']})
self.assertEqual(0, len(list(fdroidserver.lint.check_categories(app)))) self.assertEqual(0, len(list(fdroidserver.lint.check_categories(app))))
@ -338,13 +329,15 @@ class LintTest(unittest.TestCase):
self.assertEqual(1, len(list(fdroidserver.lint.check_categories(app)))) self.assertEqual(1, len(list(fdroidserver.lint.check_categories(app))))
def test_check_categories_empty_is_error(self): def test_check_categories_empty_is_error(self):
fdroidserver.lint.config = {CATEGORIES_CONFIG_NAME: []} fdroidserver.lint.config = {fdroidserver.common.CATEGORIES_CONFIG_NAME: []}
fdroidserver.lint.load_categories_config() fdroidserver.lint.load_categories_config()
app = fdroidserver.metadata.App({'Categories': ['something']}) app = fdroidserver.metadata.App({'Categories': ['something']})
self.assertEqual(1, len(list(fdroidserver.lint.check_categories(app)))) self.assertEqual(1, len(list(fdroidserver.lint.check_categories(app))))
def test_check_categories_old_hardcoded_not_defined(self): def test_check_categories_old_hardcoded_not_defined(self):
fdroidserver.lint.config = {CATEGORIES_CONFIG_NAME: ['foo', 'bar']} fdroidserver.lint.config = {
fdroidserver.common.CATEGORIES_CONFIG_NAME: ['foo', 'bar']
}
fdroidserver.lint.load_categories_config() fdroidserver.lint.load_categories_config()
app = fdroidserver.metadata.App({'Categories': ['Writing']}) app = fdroidserver.metadata.App({'Categories': ['Writing']})
self.assertEqual(1, len(list(fdroidserver.lint.check_categories(app)))) self.assertEqual(1, len(list(fdroidserver.lint.check_categories(app))))
@ -493,8 +486,7 @@ class LintTest(unittest.TestCase):
class LintAntiFeaturesTest(unittest.TestCase): class LintAntiFeaturesTest(unittest.TestCase):
def setUp(self): def setUp(self):
self.basedir = localmodule / 'tests' os.chdir(basedir)
os.chdir(self.basedir)
fdroidserver.common.config = dict() fdroidserver.common.config = dict()
fdroidserver.lint.ANTIFEATURES_KEYS = None fdroidserver.lint.ANTIFEATURES_KEYS = None
fdroidserver.lint.load_antiFeatures_config() fdroidserver.lint.load_antiFeatures_config()
@ -537,21 +529,3 @@ class LintAntiFeaturesTest(unittest.TestCase):
app = fdroidserver.metadata.App() app = fdroidserver.metadata.App()
app['Builds'] = [{'antifeatures': ['Ads', 'Tracker']}] app['Builds'] = [{'antifeatures': ['Ads', 'Tracker']}]
self.assertEqual(1, len(list(fdroidserver.lint.check_antiFeatures(app)))) self.assertEqual(1, len(list(fdroidserver.lint.check_antiFeatures(app))))
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser()
parser.add_argument(
"-v",
"--verbose",
action="store_true",
default=False,
help="Spew out even more information than normal",
)
fdroidserver.lint.options = parse_args_for_test(parser, sys.argv)
newSuite = unittest.TestSuite()
newSuite.addTest(unittest.makeSuite(LintTest))
unittest.main(failfast=False)

View File

@ -1,24 +1,14 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import inspect
import os import os
import sys
import pkgutil import pkgutil
import textwrap import textwrap
import unittest import unittest
import tempfile import tempfile
from unittest import mock from unittest import mock
localmodule = os.path.realpath(
os.path.join(os.path.dirname(inspect.getfile(inspect.currentframe())), '..')
)
print('localmodule: ' + localmodule)
if localmodule not in sys.path:
sys.path.insert(0, localmodule)
from fdroidserver import common
import fdroidserver.__main__ import fdroidserver.__main__
from testcommon import TmpCwd, TmpPyPath from .testcommon import TmpCwd, TmpPyPath
class MainTest(unittest.TestCase): class MainTest(unittest.TestCase):
@ -27,7 +17,7 @@ class MainTest(unittest.TestCase):
def test_COMMANDS_check(self): def test_COMMANDS_check(self):
"""make sure the built in sub-command defs didn't change unintentionally""" """make sure the built in sub-command defs didn't change unintentionally"""
self.assertListEqual( self.assertListEqual(
[x for x in fdroidserver.__main__.COMMANDS.keys()], [x for x in fdroidserver.__main__.COMMANDS],
[ [
'build', 'build',
'init', 'init',
@ -206,12 +196,7 @@ class MainTest(unittest.TestCase):
def test_preparse_plugin_lookup_summary_missing(self): def test_preparse_plugin_lookup_summary_missing(self):
with tempfile.TemporaryDirectory() as tmpdir, TmpCwd(tmpdir): with tempfile.TemporaryDirectory() as tmpdir, TmpCwd(tmpdir):
with open('fdroid_testy6.py', 'w') as f: with open('fdroid_testy6.py', 'w') as f:
f.write( f.write("main = lambda: print('all good')")
textwrap.dedent(
"""\
main = lambda: print('all good')"""
)
)
with TmpPyPath(tmpdir): with TmpPyPath(tmpdir):
p = [x for x in pkgutil.iter_modules() if x[1].startswith('fdroid_')] p = [x for x in pkgutil.iter_modules() if x[1].startswith('fdroid_')]
module_dir = p[0][0].path module_dir = p[0][0].path
@ -259,23 +244,3 @@ class MainTest(unittest.TestCase):
module_name = p[0][1] module_name = p[0][1]
d = fdroidserver.__main__.preparse_plugin(module_name, module_path) d = fdroidserver.__main__.preparse_plugin(module_name, module_path)
self.assertDictEqual(d, {'name': 'fdroid_testy8', 'summary': 'ttt'}) self.assertDictEqual(d, {'name': 'fdroid_testy8', 'summary': 'ttt'})
if __name__ == "__main__":
os.chdir(os.path.dirname(__file__))
import argparse
parser = argparse.ArgumentParser()
parser.add_argument(
"-v",
"--verbose",
action="store_true",
default=False,
help="Spew out even more information than normal",
)
common.options = common.parse_args(parser)
newSuite = unittest.TestSuite()
newSuite.addTest(unittest.makeSuite(MainTest))
unittest.main(failfast=False)

View File

@ -2,12 +2,10 @@
import copy import copy
import io import io
import logging
import os import os
import random import random
import ruamel.yaml import ruamel.yaml
import shutil import shutil
import sys
import unittest import unittest
import tempfile import tempfile
import textwrap import textwrap
@ -15,16 +13,14 @@ from collections import OrderedDict
from pathlib import Path from pathlib import Path
from unittest import mock from unittest import mock
localmodule = Path(__file__).resolve().parent.parent
print('localmodule: ' + str(localmodule))
if localmodule not in sys.path:
sys.path.insert(0, str(localmodule))
import fdroidserver import fdroidserver
from fdroidserver import metadata from fdroidserver import metadata
from fdroidserver.exception import MetaDataException from fdroidserver.exception import MetaDataException
from fdroidserver.common import DEFAULT_LOCALE from fdroidserver.common import DEFAULT_LOCALE
from testcommon import TmpCwd, mkdtemp, parse_args_for_test from .testcommon import TmpCwd, mkdtemp
basedir = Path(__file__).parent
def _get_mock_mf(s): def _get_mock_mf(s):
@ -37,9 +33,7 @@ class MetadataTest(unittest.TestCase):
'''fdroidserver/metadata.py''' '''fdroidserver/metadata.py'''
def setUp(self): def setUp(self):
logging.basicConfig(level=logging.DEBUG) os.chdir(basedir)
self.basedir = localmodule / 'tests'
os.chdir(self.basedir)
self._td = mkdtemp() self._td = mkdtemp()
self.testdir = self._td.name self.testdir = self._td.name
fdroidserver.metadata.warnings_action = 'error' fdroidserver.metadata.warnings_action = 'error'
@ -57,12 +51,12 @@ class MetadataTest(unittest.TestCase):
pass pass
def test_fieldtypes_key_exist(self): def test_fieldtypes_key_exist(self):
for k in fdroidserver.metadata.fieldtypes.keys(): for k in fdroidserver.metadata.fieldtypes:
self.assertTrue(k in fdroidserver.metadata.yaml_app_fields) self.assertIn(k, fdroidserver.metadata.yaml_app_fields)
def test_build_flagtypes_key_exist(self): def test_build_flagtypes_key_exist(self):
for k in fdroidserver.metadata.flagtypes.keys(): for k in fdroidserver.metadata.flagtypes:
self.assertTrue(k in fdroidserver.metadata.build_flags) self.assertIn(k, fdroidserver.metadata.build_flags)
def test_FieldValidator_BitcoinAddress(self): def test_FieldValidator_BitcoinAddress(self):
validator = None validator = None
@ -183,7 +177,7 @@ class MetadataTest(unittest.TestCase):
def test_valid_funding_yml_regex(self): def test_valid_funding_yml_regex(self):
"""Check the regex can find all the cases""" """Check the regex can find all the cases"""
with (self.basedir / 'funding-usernames.yaml').open() as fp: with (basedir / 'funding-usernames.yaml').open() as fp:
yaml = ruamel.yaml.YAML(typ='safe') yaml = ruamel.yaml.YAML(typ='safe')
data = yaml.load(fp) data = yaml.load(fp)
@ -201,9 +195,9 @@ class MetadataTest(unittest.TestCase):
m, 'this is a valid %s username: {%s}' % (k, entry) m, 'this is a valid %s username: {%s}' % (k, entry)
) )
@mock.patch('git.Repo') @mock.patch('git.Repo', mock.Mock())
@mock.patch('logging.error') @mock.patch('logging.error')
def test_read_metadata(self, logging_error, git_repo): def test_read_metadata(self, logging_error):
"""Read specified metadata files included in tests/, compare to stored output""" """Read specified metadata files included in tests/, compare to stored output"""
self.maxDiff = None self.maxDiff = None
@ -239,8 +233,8 @@ class MetadataTest(unittest.TestCase):
logging_error.assert_called() logging_error.assert_called()
self.assertEqual(3, len(logging_error.call_args_list)) self.assertEqual(3, len(logging_error.call_args_list))
@mock.patch('git.Repo') @mock.patch('git.Repo', mock.Mock())
def test_metadata_overrides_dot_fdroid_yml(self, git_Repo): def test_metadata_overrides_dot_fdroid_yml(self):
"""Fields in metadata files should override anything in .fdroid.yml.""" """Fields in metadata files should override anything in .fdroid.yml."""
app = metadata.parse_metadata('metadata/info.guardianproject.urzip.yml') app = metadata.parse_metadata('metadata/info.guardianproject.urzip.yml')
self.assertEqual(app['Summary'], '一个实用工具,获取已安装在您的设备上的应用的有关信息') self.assertEqual(app['Summary'], '一个实用工具,获取已安装在您的设备上的应用的有关信息')
@ -258,9 +252,9 @@ class MetadataTest(unittest.TestCase):
fp.write('OpenCollective: test') fp.write('OpenCollective: test')
metadata.parse_metadata(yml) # should not throw an exception metadata.parse_metadata(yml) # should not throw an exception
@mock.patch('git.Repo') @mock.patch('git.Repo', mock.Mock())
@mock.patch('logging.error') @mock.patch('logging.error')
def test_rewrite_yaml_fakeotaupdate(self, logging_error, git_Repo): def test_rewrite_yaml_fakeotaupdate(self, logging_error):
with tempfile.TemporaryDirectory() as testdir: with tempfile.TemporaryDirectory() as testdir:
testdir = Path(testdir) testdir = Path(testdir)
fdroidserver.common.config = {'accepted_formats': ['yml']} fdroidserver.common.config = {'accepted_formats': ['yml']}
@ -286,8 +280,8 @@ class MetadataTest(unittest.TestCase):
logging_error.assert_called() logging_error.assert_called()
self.assertEqual(3, len(logging_error.call_args_list)) self.assertEqual(3, len(logging_error.call_args_list))
@mock.patch('git.Repo') @mock.patch('git.Repo', mock.Mock())
def test_rewrite_yaml_fdroidclient(self, git_Repo): def test_rewrite_yaml_fdroidclient(self):
with tempfile.TemporaryDirectory() as testdir: with tempfile.TemporaryDirectory() as testdir:
testdir = Path(testdir) testdir = Path(testdir)
fdroidserver.common.config = {'accepted_formats': ['yml']} fdroidserver.common.config = {'accepted_formats': ['yml']}
@ -308,14 +302,14 @@ class MetadataTest(unittest.TestCase):
(Path('metadata-rewrite-yml') / file_name).read_text(encoding='utf-8'), (Path('metadata-rewrite-yml') / file_name).read_text(encoding='utf-8'),
) )
@mock.patch('git.Repo') @mock.patch('git.Repo', mock.Mock())
def test_rewrite_yaml_special_build_params(self, git_Repo): def test_rewrite_yaml_special_build_params(self):
"""Test rewriting a plain YAML metadata file without localized files.""" """Test rewriting a plain YAML metadata file without localized files."""
os.chdir(self.testdir) os.chdir(self.testdir)
os.mkdir('metadata') os.mkdir('metadata')
appid = 'app.with.special.build.params' appid = 'app.with.special.build.params'
file_name = Path('metadata/%s.yml' % appid) file_name = Path('metadata/%s.yml' % appid)
shutil.copy(self.basedir / file_name, file_name) shutil.copy(basedir / file_name, file_name)
# rewrite metadata # rewrite metadata
allapps = fdroidserver.metadata.read_metadata({appid: -1}) allapps = fdroidserver.metadata.read_metadata({appid: -1})
@ -326,7 +320,7 @@ class MetadataTest(unittest.TestCase):
self.maxDiff = None self.maxDiff = None
self.assertEqual( self.assertEqual(
file_name.read_text(), file_name.read_text(),
(self.basedir / 'metadata-rewrite-yml' / file_name.name).read_text(), (basedir / 'metadata-rewrite-yml' / file_name.name).read_text(),
) )
def test_normalize_type_string(self): def test_normalize_type_string(self):
@ -508,7 +502,7 @@ class MetadataTest(unittest.TestCase):
metadatadir.mkdir() metadatadir.mkdir()
randomlist = [] randomlist = []
randomapps = list((self.basedir / 'metadata').glob('*.yml')) randomapps = list((basedir / 'metadata').glob('*.yml'))
random.shuffle(randomapps) random.shuffle(randomapps)
i = 1 i = 1
for f in randomapps: for f in randomapps:
@ -911,7 +905,7 @@ class MetadataTest(unittest.TestCase):
{ {
'versionCode': 1, 'versionCode': 1,
'versionName': 'v0.1.0', 'versionName': 'v0.1.0',
'prebuild': ["a && b && " "sed -i 's,a,b,'"], 'prebuild': ["a && b && sed -i 's,a,b,'"],
} }
], ],
}, },
@ -1553,7 +1547,7 @@ class MetadataTest(unittest.TestCase):
) )
with self.assertRaisesRegex( with self.assertRaisesRegex(
MetaDataException, MetaDataException,
"Invalid srclib metadata: " "unknown key 'Evil' in " "'test.yml'", "Invalid srclib metadata: unknown key 'Evil' in 'test.yml'",
): ):
fdroidserver.metadata.parse_yaml_srclib(Path('test.yml')) fdroidserver.metadata.parse_yaml_srclib(Path('test.yml'))
@ -1788,7 +1782,6 @@ class MetadataTest(unittest.TestCase):
) )
def test_build_ndk_path(self): def test_build_ndk_path(self):
""""""
with tempfile.TemporaryDirectory(prefix='android-sdk-') as sdk_path: with tempfile.TemporaryDirectory(prefix='android-sdk-') as sdk_path:
config = {'ndk_paths': {}, 'sdk_path': sdk_path} config = {'ndk_paths': {}, 'sdk_path': sdk_path}
fdroidserver.common.config = config fdroidserver.common.config = config
@ -2442,21 +2435,3 @@ class PostMetadataParseTest(unittest.TestCase):
self.assertEqual(*self._post_metadata_parse_build_list(True, ['true'])) self.assertEqual(*self._post_metadata_parse_build_list(True, ['true']))
self.assertEqual(*self._post_metadata_parse_build_script(True, ['true'])) self.assertEqual(*self._post_metadata_parse_build_script(True, ['true']))
self.assertEqual(*self._post_metadata_parse_build_string(True, 'true')) self.assertEqual(*self._post_metadata_parse_build_string(True, 'true'))
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser()
parser.add_argument(
"-v",
"--verbose",
action="store_true",
default=False,
help="Spew out even more information than normal",
)
parse_args_for_test(parser, sys.argv)
newSuite = unittest.TestSuite()
newSuite.addTest(unittest.makeSuite(MetadataTest))
unittest.main(failfast=False)

View File

@ -1,26 +1,16 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import inspect
import logging
import os import os
import random import random
import requests import requests
import socket import socket
import sys
import tempfile import tempfile
import threading import threading
import time import time
import unittest import unittest
from unittest.mock import MagicMock, patch from unittest.mock import MagicMock, patch
localmodule = os.path.realpath( from fdroidserver import net
os.path.join(os.path.dirname(inspect.getfile(inspect.currentframe())), '..')
)
print('localmodule: ' + localmodule)
if localmodule not in sys.path:
sys.path.insert(0, localmodule)
from fdroidserver import common, net
from pathlib import Path from pathlib import Path
@ -38,7 +28,7 @@ class RetryServer:
def __init__(self, port=None, failures=3): def __init__(self, port=None, failures=3):
self.port = port self.port = port
if self.port is None: if self.port is None:
self.port = random.randint(1024, 65535) self.port = random.randint(1024, 65535) # nosec B311
self.failures = failures self.failures = failures
self.stop_event = threading.Event() self.stop_event = threading.Event()
threading.Thread(target=self.run_fake_server).start() threading.Thread(target=self.run_fake_server).start()
@ -84,10 +74,7 @@ class RetryServer:
class NetTest(unittest.TestCase): class NetTest(unittest.TestCase):
basedir = Path(__file__).resolve().parent
def setUp(self): def setUp(self):
logging.basicConfig(level=logging.DEBUG)
self.tempdir = tempfile.TemporaryDirectory() self.tempdir = tempfile.TemporaryDirectory()
os.chdir(self.tempdir.name) os.chdir(self.tempdir.name)
Path('tmp').mkdir() Path('tmp').mkdir()
@ -155,23 +142,3 @@ class NetTest(unittest.TestCase):
with self.assertRaises(requests.exceptions.ConnectionError): with self.assertRaises(requests.exceptions.ConnectionError):
net.download_using_mirrors(['http://localhost:%d/' % server.port]) net.download_using_mirrors(['http://localhost:%d/' % server.port])
server.stop() server.stop()
if __name__ == "__main__":
os.chdir(os.path.dirname(__file__))
import argparse
parser = argparse.ArgumentParser()
parser.add_argument(
"-v",
"--verbose",
action="store_true",
default=False,
help="Spew out even more information than normal",
)
common.options = common.parse_args(parser)
newSuite = unittest.TestSuite()
newSuite.addTest(unittest.makeSuite(NetTest))
unittest.main(failfast=False)

View File

@ -1,12 +1,10 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import inspect
import logging
import os import os
import platform
import requests import requests
import shutil import shutil
import subprocess import subprocess
import sys
import tempfile import tempfile
import time import time
import unittest import unittest
@ -15,13 +13,6 @@ import yaml
from pathlib import Path from pathlib import Path
from unittest.mock import patch from unittest.mock import patch
localmodule = os.path.realpath(
os.path.join(os.path.dirname(inspect.getfile(inspect.currentframe())), '..')
)
print('localmodule: ' + localmodule)
if localmodule not in sys.path:
sys.path.insert(0, localmodule)
from fdroidserver import common, exception, index, nightly from fdroidserver import common, exception, index, nightly
@ -35,6 +26,9 @@ AOSP_TESTKEY_DEBUG_KEYSTORE_KEY_FILE_NAME = (
'debug_keystore_k47SVrA85+oMZAexHc62PkgvIgO8TJBYN00U82xSlxc_id_rsa' 'debug_keystore_k47SVrA85+oMZAexHc62PkgvIgO8TJBYN00U82xSlxc_id_rsa'
) )
basedir = Path(__file__).parent
testroot = basedir.with_name('.testfiles')
class Options: class Options:
allow_disabled_algorithms = False allow_disabled_algorithms = False
@ -46,20 +40,20 @@ class Options:
verbose = False verbose = False
@unittest.skipUnless(
platform.system() == 'Linux',
'skipping test_nightly, it currently only works GNU/Linux',
)
class NightlyTest(unittest.TestCase): class NightlyTest(unittest.TestCase):
basedir = Path(__file__).resolve().parent
path = os.environ['PATH'] path = os.environ['PATH']
def setUp(self): def setUp(self):
common.config = None common.config = None
nightly.config = None nightly.config = None
logging.basicConfig(level=logging.WARNING) testroot.mkdir(exist_ok=True)
self.basedir = Path(localmodule) / 'tests' os.chdir(basedir)
self.testroot = Path(localmodule) / '.testfiles'
self.testroot.mkdir(exist_ok=True)
os.chdir(self.basedir)
self.tempdir = tempfile.TemporaryDirectory( self.tempdir = tempfile.TemporaryDirectory(
str(time.time()), self._testMethodName + '_', self.testroot str(time.time()), self._testMethodName + '_', testroot
) )
self.testdir = Path(self.tempdir.name) self.testdir = Path(self.tempdir.name)
self.home = self.testdir / 'home' self.home = self.testdir / 'home'
@ -70,21 +64,21 @@ class NightlyTest(unittest.TestCase):
def tearDown(self): def tearDown(self):
self.tempdir.cleanup() self.tempdir.cleanup()
try: try:
os.rmdir(self.testroot) os.rmdir(testroot)
except OSError: # other test modules might have left stuff around except OSError: # other test modules might have left stuff around
pass pass
def _copy_test_debug_keystore(self): def _copy_test_debug_keystore(self):
self.dot_android.mkdir() self.dot_android.mkdir()
shutil.copy( shutil.copy(
self.basedir / 'aosp_testkey_debug.keystore', basedir / 'aosp_testkey_debug.keystore',
self.dot_android / 'debug.keystore', self.dot_android / 'debug.keystore',
) )
def _copy_debug_apk(self): def _copy_debug_apk(self):
outputdir = Path('app/build/output/apk/debug') outputdir = Path('app/build/output/apk/debug')
outputdir.mkdir(parents=True) outputdir.mkdir(parents=True)
shutil.copy(self.basedir / 'urzip.apk', outputdir / 'urzip-debug.apk') shutil.copy(basedir / 'urzip.apk', outputdir / 'urzip-debug.apk')
def test_get_repo_base_url(self): def test_get_repo_base_url(self):
for clone_url, repo_git_base, result in [ for clone_url, repo_git_base, result in [
@ -108,9 +102,7 @@ class NightlyTest(unittest.TestCase):
def test_get_keystore_secret_var(self): def test_get_keystore_secret_var(self):
self.assertEqual( self.assertEqual(
AOSP_TESTKEY_DEBUG_KEYSTORE, AOSP_TESTKEY_DEBUG_KEYSTORE,
nightly._get_keystore_secret_var( nightly._get_keystore_secret_var(basedir / 'aosp_testkey_debug.keystore'),
self.basedir / 'aosp_testkey_debug.keystore'
),
) )
@patch.dict(os.environ, clear=True) @patch.dict(os.environ, clear=True)
@ -118,12 +110,12 @@ class NightlyTest(unittest.TestCase):
os.environ['HOME'] = str(self.home) os.environ['HOME'] = str(self.home)
os.environ['PATH'] = self.path os.environ['PATH'] = self.path
ssh_private_key_file = nightly._ssh_key_from_debug_keystore( ssh_private_key_file = nightly._ssh_key_from_debug_keystore(
self.basedir / 'aosp_testkey_debug.keystore' basedir / 'aosp_testkey_debug.keystore'
) )
with open(ssh_private_key_file) as fp: with open(ssh_private_key_file) as fp:
assert '-----BEGIN RSA PRIVATE KEY-----' in fp.read() self.assertIn('-----BEGIN RSA PRIVATE KEY-----', fp.read())
with open(ssh_private_key_file + '.pub') as fp: with open(ssh_private_key_file + '.pub') as fp:
assert fp.read(8) == 'ssh-rsa ' self.assertEqual(fp.read(8), 'ssh-rsa ')
shutil.rmtree(os.path.dirname(ssh_private_key_file)) shutil.rmtree(os.path.dirname(ssh_private_key_file))
@patch.dict(os.environ, clear=True) @patch.dict(os.environ, clear=True)
@ -149,9 +141,9 @@ class NightlyTest(unittest.TestCase):
self._copy_test_debug_keystore() self._copy_test_debug_keystore()
os.environ['HOME'] = str(self.home) os.environ['HOME'] = str(self.home)
os.environ['PATH'] = self.path os.environ['PATH'] = self.path
assert not dot_ssh.exists() self.assertFalse(dot_ssh.exists())
nightly.main() nightly.main()
assert not dot_ssh.exists() self.assertFalse(dot_ssh.exists())
@patch.dict(os.environ, clear=True) @patch.dict(os.environ, clear=True)
@patch('sys.argv', ['fdroid nightly', '--verbose']) @patch('sys.argv', ['fdroid nightly', '--verbose'])
@ -168,8 +160,10 @@ class NightlyTest(unittest.TestCase):
os.environ['HOME'] = str(self.home) os.environ['HOME'] = str(self.home)
os.environ['PATH'] = self.path os.environ['PATH'] = self.path
nightly.main() nightly.main()
assert (dot_ssh / AOSP_TESTKEY_DEBUG_KEYSTORE_KEY_FILE_NAME).exists() self.assertTrue((dot_ssh / AOSP_TESTKEY_DEBUG_KEYSTORE_KEY_FILE_NAME).exists())
assert (dot_ssh / (AOSP_TESTKEY_DEBUG_KEYSTORE_KEY_FILE_NAME + '.pub')).exists() self.assertTrue(
(dot_ssh / (AOSP_TESTKEY_DEBUG_KEYSTORE_KEY_FILE_NAME + '.pub')).exists()
)
@patch('fdroidserver.common.vcs_git.git', lambda args, e: common.PopenResult(1)) @patch('fdroidserver.common.vcs_git.git', lambda args, e: common.PopenResult(1))
@patch('sys.argv', ['fdroid nightly', '--verbose']) @patch('sys.argv', ['fdroid nightly', '--verbose'])
@ -200,7 +194,7 @@ class NightlyTest(unittest.TestCase):
def _put_fdroid_in_args(self, args): def _put_fdroid_in_args(self, args):
"""Find fdroid command that belongs to this source code tree""" """Find fdroid command that belongs to this source code tree"""
fdroid = os.path.join(localmodule, 'fdroid') fdroid = os.path.join(basedir.parent, 'fdroid')
if not os.path.exists(fdroid): if not os.path.exists(fdroid):
fdroid = os.getenv('fdroid') fdroid = os.getenv('fdroid')
return [fdroid] + args[1:] return [fdroid] + args[1:]
@ -245,7 +239,7 @@ class NightlyTest(unittest.TestCase):
}, },
clear=True, clear=True,
): ):
self.assertTrue(self.testroot == Path.home().parent) self.assertTrue(testroot == Path.home().parent)
with patch('subprocess.check_call', _subprocess_check_call): with patch('subprocess.check_call', _subprocess_check_call):
try: try:
nightly.main() nightly.main()
@ -319,7 +313,7 @@ class NightlyTest(unittest.TestCase):
}, },
clear=True, clear=True,
): ):
self.assertTrue(self.testroot == Path.home().parent) self.assertTrue(testroot == Path.home().parent)
with patch('subprocess.check_call', _subprocess_check_call): with patch('subprocess.check_call', _subprocess_check_call):
try: try:
nightly.main() nightly.main()
@ -356,23 +350,3 @@ class NightlyTest(unittest.TestCase):
) )
del config['identity_file'] del config['identity_file']
self.assertEqual(expected, config) self.assertEqual(expected, config)
if __name__ == "__main__":
os.chdir(os.path.dirname(__file__))
import argparse
parser = argparse.ArgumentParser()
parser.add_argument(
"-v",
"--verbose",
action="store_true",
default=False,
help="Spew out even more information than normal",
)
common.options = common.parse_args(parser)
newSuite = unittest.TestSuite()
newSuite.addTest(unittest.makeSuite(NightlyTest))
unittest.main(failfast=False)

View File

@ -10,45 +10,36 @@
# -keypass 123456 -dname 'CN=test, OU=F-Droid'; done # -keypass 123456 -dname 'CN=test, OU=F-Droid'; done
# #
import inspect
import json import json
import logging
import os import os
import pathlib
import shutil import shutil
import sys import sys
import unittest import unittest
import tempfile import tempfile
import textwrap
from unittest import mock from unittest import mock
localmodule = os.path.realpath(
os.path.join(os.path.dirname(inspect.getfile(inspect.currentframe())), '..')
)
print('localmodule: ' + localmodule)
if localmodule not in sys.path:
sys.path.insert(0, localmodule)
from fdroidserver import publish from fdroidserver import publish
from fdroidserver import common from fdroidserver import common
from fdroidserver import metadata from fdroidserver import metadata
from fdroidserver import signatures from fdroidserver import signatures
from fdroidserver.exception import FDroidException from fdroidserver.exception import FDroidException
from testcommon import mkdtemp, parse_args_for_test from .testcommon import mkdtemp
basedir = pathlib.Path(__file__).parent
class PublishTest(unittest.TestCase): class PublishTest(unittest.TestCase):
'''fdroidserver/publish.py''' '''fdroidserver/publish.py'''
def setUp(self): def setUp(self):
logging.basicConfig(level=logging.DEBUG) os.chdir(basedir)
self.basedir = os.path.join(localmodule, 'tests')
os.chdir(self.basedir)
self._td = mkdtemp() self._td = mkdtemp()
self.testdir = self._td.name self.testdir = self._td.name
def tearDown(self): def tearDown(self):
self._td.cleanup() self._td.cleanup()
os.chdir(self.basedir) os.chdir(basedir)
def test_key_alias(self): def test_key_alias(self):
publish.config = {} publish.config = {}
@ -91,7 +82,7 @@ class PublishTest(unittest.TestCase):
publish.config = common.config publish.config = common.config
publish.config['keystorepass'] = '123456' publish.config['keystorepass'] = '123456'
publish.config['keypass'] = '123456' publish.config['keypass'] = '123456'
publish.config['keystore'] = os.path.join(self.basedir, 'dummy-keystore.jks') publish.config['keystore'] = os.path.join(basedir, 'dummy-keystore.jks')
publish.config['repo_keyalias'] = 'repokey' publish.config['repo_keyalias'] = 'repokey'
appids = [ appids = [
@ -127,12 +118,7 @@ class PublishTest(unittest.TestCase):
with open('config.py', 'r') as f: with open('config.py', 'r') as f:
self.assertEqual( self.assertEqual(
textwrap.dedent( '\nrepo_key_sha256 = "c58460800c7b250a619c30c13b07b7359a43e5af71a4352d86c58ae18c9f6d41"\n',
'''\
repo_key_sha256 = "c58460800c7b250a619c30c13b07b7359a43e5af71a4352d86c58ae18c9f6d41"
'''
),
f.read(), f.read(),
) )
@ -142,7 +128,7 @@ class PublishTest(unittest.TestCase):
publish.config = common.config publish.config = common.config
publish.config['keystorepass'] = '123456' publish.config['keystorepass'] = '123456'
publish.config['keypass'] = '123456' publish.config['keypass'] = '123456'
publish.config['keystore'] = os.path.join(self.basedir, 'dummy-keystore.jks') publish.config['keystore'] = os.path.join(basedir, 'dummy-keystore.jks')
publish.config['repo_keyalias'] = 'repokey' publish.config['repo_keyalias'] = 'repokey'
publish.config['repo_key_sha256'] = 'bad bad bad bad bad bad bad bad bad bad bad bad' publish.config['repo_key_sha256'] = 'bad bad bad bad bad bad bad bad bad bad bad bad'
@ -273,7 +259,7 @@ class PublishTest(unittest.TestCase):
config['repo_keyalias'] = 'sova' config['repo_keyalias'] = 'sova'
config['keystorepass'] = 'r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI=' config['keystorepass'] = 'r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI='
config['keypass'] = 'r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI=' config['keypass'] = 'r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI='
shutil.copy(os.path.join(self.basedir, 'keystore.jks'), self.testdir) shutil.copy(basedir / 'keystore.jks', self.testdir)
config['keystore'] = 'keystore.jks' config['keystore'] = 'keystore.jks'
config['keydname'] = 'CN=Birdman, OU=Cell, O=Alcatraz, L=Alcatraz, S=California, C=US' config['keydname'] = 'CN=Birdman, OU=Cell, O=Alcatraz, L=Alcatraz, S=California, C=US'
publish.config = config publish.config = config
@ -293,7 +279,7 @@ class PublishTest(unittest.TestCase):
metadata.write_metadata(os.path.join('metadata', '%s.yml' % app.id), app) metadata.write_metadata(os.path.join('metadata', '%s.yml' % app.id), app)
os.mkdir('unsigned') os.mkdir('unsigned')
testapk = os.path.join(self.basedir, 'no_targetsdk_minsdk1_unsigned.apk') testapk = basedir / 'no_targetsdk_minsdk1_unsigned.apk'
unsigned = os.path.join('unsigned', common.get_release_filename(app, build)) unsigned = os.path.join('unsigned', common.get_release_filename(app, build))
signed = os.path.join('repo', common.get_release_filename(app, build)) signed = os.path.join('repo', common.get_release_filename(app, build))
shutil.copy(testapk, unsigned) shutil.copy(testapk, unsigned)
@ -348,7 +334,7 @@ class PublishTest(unittest.TestCase):
config['repo_keyalias'] = 'sova' config['repo_keyalias'] = 'sova'
config['keystorepass'] = 'r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI=' config['keystorepass'] = 'r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI='
config['keypass'] = 'r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI=' config['keypass'] = 'r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI='
shutil.copy(os.path.join(self.basedir, 'keystore.jks'), self.testdir) shutil.copy(basedir / 'keystore.jks', self.testdir)
config['keystore'] = 'keystore.jks' config['keystore'] = 'keystore.jks'
config[ config[
'keydname' 'keydname'
@ -370,7 +356,7 @@ class PublishTest(unittest.TestCase):
metadata.write_metadata(os.path.join('metadata', '%s.yml' % app.id), app) metadata.write_metadata(os.path.join('metadata', '%s.yml' % app.id), app)
os.mkdir('unsigned') os.mkdir('unsigned')
testapk = os.path.join(self.basedir, 'no_targetsdk_minsdk1_unsigned.apk') testapk = basedir / 'no_targetsdk_minsdk1_unsigned.apk'
unsigned = os.path.join('unsigned', common.get_release_filename(app, build)) unsigned = os.path.join('unsigned', common.get_release_filename(app, build))
signed = os.path.join('repo', common.get_release_filename(app, build)) signed = os.path.join('repo', common.get_release_filename(app, build))
shutil.copy(testapk, unsigned) shutil.copy(testapk, unsigned)
@ -409,23 +395,3 @@ class PublishTest(unittest.TestCase):
with self.assertRaises(SystemExit) as e: with self.assertRaises(SystemExit) as e:
publish.main() publish.main()
self.assertEqual(e.exception.code, 1) self.assertEqual(e.exception.code, 1)
if __name__ == "__main__":
os.chdir(os.path.dirname(__file__))
import argparse
parser = argparse.ArgumentParser()
parser.add_argument(
"-v",
"--verbose",
action="store_true",
default=False,
help="Spew out even more information than normal",
)
parse_args_for_test(parser, sys.argv)
newSuite = unittest.TestSuite()
newSuite.addTest(unittest.makeSuite(PublishTest))
unittest.main(failfast=False)

View File

@ -1,29 +1,23 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import logging
import os import os
import sys
import unittest import unittest
import tempfile import tempfile
import textwrap import textwrap
from pathlib import Path from pathlib import Path
from unittest import mock
localmodule = Path(__file__).resolve().parent.parent from fdroidserver import metadata, rewritemeta
print('localmodule: ' + str(localmodule)) from .testcommon import TmpCwd, mkdtemp
if localmodule not in sys.path:
sys.path.insert(0, str(localmodule))
from fdroidserver import common, metadata, rewritemeta basedir = Path(__file__).parent
from testcommon import TmpCwd, mkdtemp
class RewriteMetaTest(unittest.TestCase): class RewriteMetaTest(unittest.TestCase):
'''fdroidserver/publish.py''' '''fdroidserver/publish.py'''
def setUp(self): def setUp(self):
logging.basicConfig(level=logging.DEBUG) os.chdir(basedir)
self.basedir = localmodule / 'tests'
os.chdir(self.basedir)
metadata.warnings_action = 'error' metadata.warnings_action = 'error'
self._td = mkdtemp() self._td = mkdtemp()
self.testdir = self._td.name self.testdir = self._td.name
@ -132,6 +126,7 @@ class RewriteMetaTest(unittest.TestCase):
[{'versionCode': 0}, {'versionCode': 1}, {'versionCode': 2}], [{'versionCode': 0}, {'versionCode': 1}, {'versionCode': 2}],
) )
@mock.patch('sys.argv', ['fdroid rewritemeta', 'a'])
def test_rewrite_no_builds(self): def test_rewrite_no_builds(self):
os.chdir(self.testdir) os.chdir(self.testdir)
Path('metadata').mkdir() Path('metadata').mkdir()
@ -152,6 +147,7 @@ class RewriteMetaTest(unittest.TestCase):
), ),
) )
@mock.patch('sys.argv', ['fdroid rewritemeta', 'a'])
def test_rewrite_empty_build_field(self): def test_rewrite_empty_build_field(self):
os.chdir(self.testdir) os.chdir(self.testdir)
Path('metadata').mkdir() Path('metadata').mkdir()
@ -221,9 +217,8 @@ class RewriteMetaTest(unittest.TestCase):
}, },
) )
@mock.patch('sys.argv', ['fdroid rewritemeta', 'a', 'b'])
def test_rewrite_scenario_trivial(self): def test_rewrite_scenario_trivial(self):
sys.argv = ['rewritemeta', 'a', 'b']
with tempfile.TemporaryDirectory() as tmpdir, TmpCwd(tmpdir): with tempfile.TemporaryDirectory() as tmpdir, TmpCwd(tmpdir):
Path('metadata').mkdir() Path('metadata').mkdir()
with Path('metadata/a.yml').open('w') as f: with Path('metadata/a.yml').open('w') as f:
@ -260,21 +255,3 @@ class RewriteMetaTest(unittest.TestCase):
''' '''
), ),
) )
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser()
parser.add_argument(
"-v",
"--verbose",
action="store_true",
default=False,
help="Spew out even more information than normal",
)
common.options = common.parse_args(parser)
newSuite = unittest.TestSuite()
newSuite.addTest(unittest.makeSuite(RewriteMetaTest))
unittest.main(failfast=False)

View File

@ -1,8 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import glob
import inspect
import logging
import os import os
import pathlib import pathlib
import re import re
@ -23,19 +20,13 @@ else:
import tomli as tomllib import tomli as tomllib
import yaml import yaml
localmodule = os.path.realpath(
os.path.join(os.path.dirname(inspect.getfile(inspect.currentframe())), '..')
)
print('localmodule: ' + localmodule)
if localmodule not in sys.path:
sys.path.insert(0, localmodule)
from testcommon import TmpCwd, mkdtemp, mock_open_to_str, parse_args_for_test
import fdroidserver.build import fdroidserver.build
import fdroidserver.common import fdroidserver.common
import fdroidserver.metadata import fdroidserver.metadata
import fdroidserver.scanner import fdroidserver.scanner
from .testcommon import TmpCwd, mkdtemp, mock_open_to_str
basedir = pathlib.Path(__file__).parent
# Always use built-in default rules so changes in downloaded rules don't break tests. # Always use built-in default rules so changes in downloaded rules don't break tests.
@ -45,21 +36,18 @@ import fdroidserver.scanner
) )
class ScannerTest(unittest.TestCase): class ScannerTest(unittest.TestCase):
def setUp(self): def setUp(self):
logging.basicConfig(level=logging.INFO) os.chdir(basedir)
self.basedir = os.path.join(localmodule, 'tests')
os.chdir(self.basedir)
self._td = mkdtemp() self._td = mkdtemp()
self.testdir = self._td.name self.testdir = self._td.name
fdroidserver.scanner.ScannerTool.refresh_allowed = False fdroidserver.scanner.ScannerTool.refresh_allowed = False
def tearDown(self): def tearDown(self):
os.chdir(self.basedir) os.chdir(basedir)
self._td.cleanup() self._td.cleanup()
def test_scan_source_files(self): def test_scan_source_files(self):
fdroidserver.common.options = mock.Mock() fdroidserver.common.options = mock.Mock()
fdroidserver.common.options.json = False fdroidserver.common.options.json = False
source_files = os.path.join(self.basedir, 'source-files')
projects = { projects = {
'OtakuWorld': 2, 'OtakuWorld': 2,
'Zillode': 1, 'Zillode': 1,
@ -76,12 +64,12 @@ class ScannerTest(unittest.TestCase):
'com.lolo.io.onelist': 6, 'com.lolo.io.onelist': 6,
'catalog.test': 22, 'catalog.test': 22,
} }
for d in glob.glob(os.path.join(source_files, '*')): for d in (basedir / 'source-files').iterdir():
build = fdroidserver.metadata.Build() build = fdroidserver.metadata.Build()
fatal_problems = fdroidserver.scanner.scan_source(d, build) fatal_problems = fdroidserver.scanner.scan_source(d, build)
should = projects.get(os.path.basename(d), 0) should = projects.get(d.name, 0)
self.assertEqual( self.assertEqual(
should, fatal_problems, "%s should have %d errors!" % (d, should) should, fatal_problems, f'{d} should have {should} errors!'
) )
def test_get_gradle_compile_commands_without_catalog(self): def test_get_gradle_compile_commands_without_catalog(self):
@ -225,8 +213,7 @@ class ScannerTest(unittest.TestCase):
fp.write(b'\x00\x00') fp.write(b'\x00\x00')
fp.write(uuid.uuid4().bytes) fp.write(uuid.uuid4().bytes)
shutil.copyfile('binary.out', 'fake.png') shutil.copyfile('binary.out', 'fake.png')
os.chmod('fake.png', 0o755) os.chmod('fake.png', 0o755) # nosec B103
os.system('ls -l binary.out')
with open('snippet.png', 'wb') as fp: with open('snippet.png', 'wb') as fp:
fp.write( fp.write(
b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x000\x00\x00' b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x000\x00\x00'
@ -234,8 +221,7 @@ class ScannerTest(unittest.TestCase):
b'IT\x08\x08\x08\x08|\x08d\x88\x00\x00\x00\tpHYs\x00\x00\n' b'IT\x08\x08\x08\x08|\x08d\x88\x00\x00\x00\tpHYs\x00\x00\n'
b'a\x00\x00\na\x01\xfc\xccJ%\x00\x00\x00\x19tEXtSoftware' b'a\x00\x00\na\x01\xfc\xccJ%\x00\x00\x00\x19tEXtSoftware'
) )
os.chmod('snippet.png', 0o755) os.chmod('snippet.png', 0o755) # nosec B103
os.system('ls -l fake.png')
# run scanner as if from `fdroid build` # run scanner as if from `fdroid build`
os.chdir(self.testdir) os.chdir(self.testdir)
@ -365,7 +351,7 @@ class ScannerTest(unittest.TestCase):
def test_gradle_maven_url_regex(self): def test_gradle_maven_url_regex(self):
"""Check the regex can find all the cases""" """Check the regex can find all the cases"""
with open(os.path.join(self.basedir, 'gradle-maven-blocks.yaml')) as fp: with open(basedir / 'gradle-maven-blocks.yaml') as fp:
data = yaml.safe_load(fp) data = yaml.safe_load(fp)
urls = [] urls = []
@ -472,7 +458,7 @@ class ScannerTest(unittest.TestCase):
apk = 'urzip.apk' apk = 'urzip.apk'
mapzip = 'Norway_bouvet_europe_2.obf.zip' mapzip = 'Norway_bouvet_europe_2.obf.zip'
secretfile = os.path.join( secretfile = os.path.join(
self.basedir, 'org.bitbucket.tickytacky.mirrormirror_1.apk' basedir, 'org.bitbucket.tickytacky.mirrormirror_1.apk'
) )
with tempfile.TemporaryDirectory() as tmpdir: with tempfile.TemporaryDirectory() as tmpdir:
shutil.copy(apk, tmpdir) shutil.copy(apk, tmpdir)
@ -503,7 +489,6 @@ class ScannerTest(unittest.TestCase):
class Test_scan_binary(unittest.TestCase): class Test_scan_binary(unittest.TestCase):
def setUp(self): def setUp(self):
self.basedir = os.path.join(localmodule, 'tests')
config = dict() config = dict()
fdroidserver.common.fill_config_defaults(config) fdroidserver.common.fill_config_defaults(config)
fdroidserver.common.config = config fdroidserver.common.config = config
@ -519,7 +504,7 @@ class Test_scan_binary(unittest.TestCase):
fdroidserver.scanner._SCANNER_TOOL.regexs['warn_code_signatures'] = {} fdroidserver.scanner._SCANNER_TOOL.regexs['warn_code_signatures'] = {}
def test_code_signature_match(self): def test_code_signature_match(self):
apkfile = os.path.join(self.basedir, 'no_targetsdk_minsdk1_unsigned.apk') apkfile = os.path.join(basedir, 'no_targetsdk_minsdk1_unsigned.apk')
self.assertEqual( self.assertEqual(
1, 1,
fdroidserver.scanner.scan_binary(apkfile), fdroidserver.scanner.scan_binary(apkfile),
@ -538,7 +523,7 @@ class Test_scan_binary(unittest.TestCase):
"https://gitlab.com/fdroid/fdroidserver/-/merge_requests/1110#note_932026766", "https://gitlab.com/fdroid/fdroidserver/-/merge_requests/1110#note_932026766",
) )
def test_bottom_level_embedded_apk_code_signature(self): def test_bottom_level_embedded_apk_code_signature(self):
apkfile = os.path.join(self.basedir, 'apk.embedded_1.apk') apkfile = os.path.join(basedir, 'apk.embedded_1.apk')
fdroidserver.scanner._SCANNER_TOOL.regexs['err_code_signatures'] = { fdroidserver.scanner._SCANNER_TOOL.regexs['err_code_signatures'] = {
"org/bitbucket/tickytacky/mirrormirror/MainActivity": re.compile( "org/bitbucket/tickytacky/mirrormirror/MainActivity": re.compile(
r'.*org/bitbucket/tickytacky/mirrormirror/MainActivity', r'.*org/bitbucket/tickytacky/mirrormirror/MainActivity',
@ -558,7 +543,7 @@ class Test_scan_binary(unittest.TestCase):
) )
def test_top_level_signature_embedded_apk_present(self): def test_top_level_signature_embedded_apk_present(self):
apkfile = os.path.join(self.basedir, 'apk.embedded_1.apk') apkfile = os.path.join(basedir, 'apk.embedded_1.apk')
fdroidserver.scanner._SCANNER_TOOL.regexs['err_code_signatures'] = { fdroidserver.scanner._SCANNER_TOOL.regexs['err_code_signatures'] = {
"org/fdroid/ci/BuildConfig": re.compile( "org/fdroid/ci/BuildConfig": re.compile(
r'.*org/fdroid/ci/BuildConfig', re.IGNORECASE | re.UNICODE r'.*org/fdroid/ci/BuildConfig', re.IGNORECASE | re.UNICODE
@ -577,7 +562,6 @@ class Test_scan_binary(unittest.TestCase):
class Test_SignatureDataController(unittest.TestCase): class Test_SignatureDataController(unittest.TestCase):
# __init__
def test_init(self): def test_init(self):
sdc = fdroidserver.scanner.SignatureDataController( sdc = fdroidserver.scanner.SignatureDataController(
'nnn', 'fff.yml', 'https://example.com/test.json' 'nnn', 'fff.yml', 'https://example.com/test.json'
@ -776,8 +760,7 @@ class Test_ScannerTool(unittest.TestCase):
def setUp(self): def setUp(self):
fdroidserver.common.options = None fdroidserver.common.options = None
fdroidserver.common.config = None fdroidserver.common.config = None
self.basedir = os.path.join(localmodule, 'tests') os.chdir(basedir)
os.chdir(self.basedir)
self._td = mkdtemp() self._td = mkdtemp()
self.testdir = self._td.name self.testdir = self._td.name
fdroidserver.scanner.ScannerTool.refresh_allowed = True fdroidserver.scanner.ScannerTool.refresh_allowed = True
@ -785,7 +768,7 @@ class Test_ScannerTool(unittest.TestCase):
def tearDown(self): def tearDown(self):
fdroidserver.common.options = None fdroidserver.common.options = None
fdroidserver.common.config = None fdroidserver.common.config = None
os.chdir(self.basedir) os.chdir(basedir)
self._td.cleanup() self._td.cleanup()
def test_load(self): def test_load(self):
@ -879,30 +862,3 @@ class Test_main(unittest.TestCase):
self.exit_func.assert_not_called() self.exit_func.assert_not_called()
self.read_app_args_func.assert_not_called() self.read_app_args_func.assert_not_called()
self.scan_binary_func.assert_called_once_with('local.application.apk') self.scan_binary_func.assert_called_once_with('local.application.apk')
if __name__ == "__main__":
os.chdir(os.path.dirname(__file__))
import argparse
parser = argparse.ArgumentParser()
parser.add_argument(
"-v",
"--verbose",
action="store_true",
default=False,
help="Spew out even more information than normal",
)
parse_args_for_test(parser, sys.argv)
newSuite = unittest.TestSuite()
newSuite.addTests(
[
unittest.makeSuite(ScannerTest),
unittest.makeSuite(Test_scan_binary),
unittest.makeSuite(Test_SignatureDataController),
unittest.makeSuite(Test_main),
]
)
unittest.main(failfast=False)

View File

@ -1,27 +1,18 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import inspect
import os
import sys
import unittest
import hashlib import hashlib
import logging import os
import unittest
from tempfile import TemporaryDirectory from tempfile import TemporaryDirectory
localmodule = os.path.realpath( from .testcommon import TmpCwd
os.path.join(os.path.dirname(inspect.getfile(inspect.currentframe())), '..')
)
print('localmodule: ' + localmodule)
if localmodule not in sys.path:
sys.path.insert(0, localmodule)
from testcommon import TmpCwd
from fdroidserver import common, signatures from fdroidserver import common, signatures
basedir = os.path.dirname(__file__)
class SignaturesTest(unittest.TestCase): class SignaturesTest(unittest.TestCase):
def setUp(self): def setUp(self):
logging.basicConfig(level=logging.DEBUG)
common.config = None common.config = None
config = common.read_config() config = common.read_config()
config['jarsigner'] = common.find_sdk_tools_cmd('jarsigner') config['jarsigner'] = common.find_sdk_tools_cmd('jarsigner')
@ -30,12 +21,11 @@ class SignaturesTest(unittest.TestCase):
def test_main(self): def test_main(self):
# option fixture class:
class OptionsFixture: class OptionsFixture:
APK = [os.path.abspath(os.path.join('repo', 'com.politedroid_3.apk'))] APK = [os.path.join(basedir, 'repo', 'com.politedroid_3.apk')]
with TemporaryDirectory() as tmpdir, TmpCwd(tmpdir): with TemporaryDirectory() as tmpdir, TmpCwd(tmpdir):
signatures.extract(OptionsFixture()) signatures.extract(OptionsFixture)
# check if extracted signatures are where they are supposed to be # check if extracted signatures are where they are supposed to be
# also verify weather if extracted file contian what they should # also verify weather if extracted file contian what they should
@ -49,27 +39,6 @@ class SignaturesTest(unittest.TestCase):
) )
for path, checksum in filesAndHashes: for path, checksum in filesAndHashes:
self.assertTrue(os.path.isfile(path), self.assertTrue(os.path.isfile(path),
msg="check whether '{path}' was extracted " f'check whether {path!r} was extracted correctly.')
"correctly.".format(path=path))
with open(path, 'rb') as f: with open(path, 'rb') as f:
self.assertEqual(hashlib.sha256(f.read()).hexdigest(), checksum) self.assertEqual(hashlib.sha256(f.read()).hexdigest(), checksum)
if __name__ == "__main__":
os.chdir(os.path.dirname(__file__))
import argparse
parser = argparse.ArgumentParser()
parser.add_argument(
"-v",
"--verbose",
action="store_true",
default=False,
help="Spew out even more information than normal",
)
common.options = common.parse_args(parser)
newSuite = unittest.TestSuite()
newSuite.addTest(unittest.makeSuite(SignaturesTest))
unittest.main(failfast=False)

View File

@ -1,22 +1,12 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import inspect
import json import json
import logging
import os import os
import shutil import shutil
import subprocess import subprocess
import sys
import tempfile import tempfile
import unittest import unittest
localmodule = os.path.realpath(
os.path.join(os.path.dirname(inspect.getfile(inspect.currentframe())), '..')
)
print('localmodule: ' + localmodule)
if localmodule not in sys.path:
sys.path.insert(0, localmodule)
from fdroidserver import apksigcopier, common, exception, signindex, update from fdroidserver import apksigcopier, common, exception, signindex, update
from pathlib import Path from pathlib import Path
from unittest.mock import patch from unittest.mock import patch
@ -46,7 +36,6 @@ class SignindexTest(unittest.TestCase):
config['keypass'] = 'r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI=' config['keypass'] = 'r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI='
signindex.config = config signindex.config = config
logging.basicConfig(level=logging.DEBUG)
self.tempdir = tempfile.TemporaryDirectory() self.tempdir = tempfile.TemporaryDirectory()
os.chdir(self.tempdir.name) os.chdir(self.tempdir.name)
self.repodir = Path('repo') self.repodir = Path('repo')
@ -187,23 +176,3 @@ class SignindexTest(unittest.TestCase):
['jarsigner', '-verify', '-verbose', f], stdout=subprocess.PIPE ['jarsigner', '-verify', '-verbose', f], stdout=subprocess.PIPE
) )
self.assertFalse(b'SHA1withRSA' in cp.stdout) self.assertFalse(b'SHA1withRSA' in cp.stdout)
if __name__ == "__main__":
os.chdir(os.path.dirname(__file__))
import argparse
parser = argparse.ArgumentParser()
parser.add_argument(
"-v",
"--verbose",
action="store_true",
default=False,
help="Spew out even more information than normal",
)
common.options = common.parse_args(parser)
newSuite = unittest.TestSuite()
newSuite.addTest(unittest.makeSuite(SignindexTest))
unittest.main(failfast=False)

View File

@ -1,12 +1,9 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# http://www.drdobbs.com/testing/unit-testing-with-python/240165163
import copy import copy
import git import git
import glob import glob
import hashlib import hashlib
import inspect
import json import json
import logging import logging
import os import os
@ -14,8 +11,6 @@ import random
import shutil import shutil
import string import string
import subprocess import subprocess
import sys
import tempfile
import unittest import unittest
import yaml import yaml
import zipfile import zipfile
@ -47,24 +42,21 @@ except ImportError:
except ImportError: except ImportError:
from yaml import Loader as FullLoader from yaml import Loader as FullLoader
localmodule = os.path.realpath(
os.path.join(os.path.dirname(inspect.getfile(inspect.currentframe())), '..')
)
print('localmodule: ' + localmodule)
if localmodule not in sys.path:
sys.path.insert(0, localmodule)
import fdroidserver.common import fdroidserver.common
import fdroidserver.exception import fdroidserver.exception
import fdroidserver.metadata import fdroidserver.metadata
import fdroidserver.update import fdroidserver.update
from fdroidserver.common import CATEGORIES_CONFIG_NAME from fdroidserver.common import CATEGORIES_CONFIG_NAME
from fdroidserver.looseversion import LooseVersion from fdroidserver.looseversion import LooseVersion
from testcommon import TmpCwd, mkdtemp, parse_args_for_test from .testcommon import TmpCwd, mkdtemp
from PIL import PngImagePlugin
DONATION_FIELDS = ('Donate', 'Liberapay', 'OpenCollective') DONATION_FIELDS = ('Donate', 'Liberapay', 'OpenCollective')
logging.getLogger(PngImagePlugin.__name__).setLevel(logging.INFO)
basedir = Path(__file__).parent
class Options: class Options:
allow_disabled_algorithms = False allow_disabled_algorithms = False
@ -80,12 +72,7 @@ class UpdateTest(unittest.TestCase):
'''fdroid update''' '''fdroid update'''
def setUp(self): def setUp(self):
logging.basicConfig(level=logging.INFO) os.chdir(basedir)
from PIL import PngImagePlugin
logging.getLogger(PngImagePlugin.__name__).setLevel(logging.INFO)
self.basedir = os.path.join(localmodule, 'tests')
os.chdir(self.basedir)
self._td = mkdtemp() self._td = mkdtemp()
self.testdir = self._td.name self.testdir = self._td.name
@ -93,7 +80,7 @@ class UpdateTest(unittest.TestCase):
fdroidserver.common.options = None fdroidserver.common.options = None
def tearDown(self): def tearDown(self):
os.chdir(self.basedir) os.chdir(basedir)
self._td.cleanup() self._td.cleanup()
def test_insert_store_metadata(self): def test_insert_store_metadata(self):
@ -103,24 +90,22 @@ class UpdateTest(unittest.TestCase):
fdroidserver.common.fill_config_defaults(config) fdroidserver.common.fill_config_defaults(config)
fdroidserver.update.config = config fdroidserver.update.config = config
repo_dir = os.path.join(self.basedir, 'repo') repo_dir = basedir / 'repo'
os.mkdir('metadata') os.mkdir('metadata')
for packageName in ( for packageName in (
'obb.mainpatch.current', 'obb.mainpatch.current',
'org.videolan.vlc', 'org.videolan.vlc',
): ):
shutil.copytree( shutil.copytree(
os.path.join(repo_dir, packageName), os.path.join('repo', packageName) repo_dir / packageName, os.path.join('repo', packageName)
) )
for packageName in ( for packageName in (
'info.guardianproject.checkey', 'info.guardianproject.checkey',
'info.guardianproject.urzip', 'info.guardianproject.urzip',
'org.smssecure.smssecure', 'org.smssecure.smssecure',
): ):
if not os.path.exists('metadata'):
os.mkdir('metadata')
shutil.copytree( shutil.copytree(
os.path.join(self.basedir, 'metadata', packageName), basedir / 'metadata' / packageName,
os.path.join('metadata', packageName), os.path.join('metadata', packageName),
) )
for packageName in ( for packageName in (
@ -129,12 +114,12 @@ class UpdateTest(unittest.TestCase):
'eu.siacs.conversations', 'eu.siacs.conversations',
): ):
shutil.copytree( shutil.copytree(
os.path.join(self.basedir, 'source-files', packageName), basedir / 'source-files' / packageName,
os.path.join(self.testdir, 'build', packageName), os.path.join(self.testdir, 'build', packageName),
) )
testfilename = 'icon_yAfSvPRJukZzMMfUzvbYqwaD1XmHXNtiPBtuPVHW-6s=.png' testfilename = 'icon_yAfSvPRJukZzMMfUzvbYqwaD1XmHXNtiPBtuPVHW-6s=.png'
testfile = os.path.join(repo_dir, 'org.videolan.vlc', 'en-US', 'icon.png') testfile = repo_dir / 'org.videolan.vlc/en-US/icon.png'
cpdir = os.path.join('metadata', 'org.videolan.vlc', 'en-US') cpdir = os.path.join('metadata', 'org.videolan.vlc', 'en-US')
cpfile = os.path.join(cpdir, testfilename) cpfile = os.path.join(cpdir, testfilename)
os.makedirs(cpdir, exist_ok=True) os.makedirs(cpdir, exist_ok=True)
@ -171,7 +156,7 @@ class UpdateTest(unittest.TestCase):
fdroidserver.update.insert_localized_app_metadata(apps) fdroidserver.update.insert_localized_app_metadata(apps)
fdroidserver.update.ingest_screenshots_from_repo_dir(apps) fdroidserver.update.ingest_screenshots_from_repo_dir(apps)
appdir = os.path.join('repo', 'info.guardianproject.urzip', 'en-US') appdir = Path('repo/info.guardianproject.urzip/en-US')
self.assertTrue( self.assertTrue(
os.path.isfile( os.path.isfile(
os.path.join( os.path.join(
@ -190,8 +175,8 @@ class UpdateTest(unittest.TestCase):
self.assertEqual(6, len(apps)) self.assertEqual(6, len(apps))
for packageName, app in apps.items(): for packageName, app in apps.items():
self.assertTrue('localized' in app, packageName) self.assertIn('localized', app, packageName)
self.assertTrue('en-US' in app['localized']) self.assertIn('en-US', app['localized'])
self.assertEqual(1, len(app['localized'])) self.assertEqual(1, len(app['localized']))
if packageName == 'info.guardianproject.urzip': if packageName == 'info.guardianproject.urzip':
self.assertEqual(7, len(app['localized']['en-US'])) self.assertEqual(7, len(app['localized']['en-US']))
@ -267,7 +252,7 @@ class UpdateTest(unittest.TestCase):
def test_name_title_scraping(self): def test_name_title_scraping(self):
"""metadata file --> fdroiddata localized files --> fastlane/triple-t in app source --> APK""" """metadata file --> fdroiddata localized files --> fastlane/triple-t in app source --> APK"""
shutil.copytree(self.basedir, self.testdir, dirs_exist_ok=True) shutil.copytree(basedir, self.testdir, dirs_exist_ok=True)
config = dict() config = dict()
fdroidserver.common.fill_config_defaults(config) fdroidserver.common.fill_config_defaults(config)
fdroidserver.common.config = config fdroidserver.common.config = config
@ -356,7 +341,7 @@ class UpdateTest(unittest.TestCase):
def test_insert_missing_app_names_from_apks_from_repo(self): def test_insert_missing_app_names_from_apks_from_repo(self):
os.chdir(self.testdir) os.chdir(self.testdir)
shutil.copytree(self.basedir, self.testdir, dirs_exist_ok=True) shutil.copytree(basedir, self.testdir, dirs_exist_ok=True)
config = dict() config = dict()
fdroidserver.common.fill_config_defaults(config) fdroidserver.common.fill_config_defaults(config)
fdroidserver.common.config = config fdroidserver.common.config = config
@ -405,10 +390,10 @@ class UpdateTest(unittest.TestCase):
repoapps['info.guardianproject.urzip']['localized']['en-US']['name']) repoapps['info.guardianproject.urzip']['localized']['en-US']['name'])
def test_insert_triple_t_metadata(self): def test_insert_triple_t_metadata(self):
importer = os.path.join(self.basedir, 'tmp', 'importer') importer = basedir / 'tmp/importer'
packageName = 'org.fdroid.ci.test.app' packageName = 'org.fdroid.ci.test.app'
if not os.path.isdir(importer): if not os.path.isdir(importer):
logging.warning('skipping test_insert_triple_t_metadata, import.TestCase must run first!') logging.warning('skipping test_insert_triple_t_metadata, test_import.py must run first!')
return return
packageDir = os.path.join(self.testdir, 'build', packageName) packageDir = os.path.join(self.testdir, 'build', packageName)
shutil.copytree(importer, packageDir) shutil.copytree(importer, packageDir)
@ -435,7 +420,7 @@ class UpdateTest(unittest.TestCase):
apps = fdroidserver.metadata.read_metadata() apps = fdroidserver.metadata.read_metadata()
fdroidserver.update.copy_triple_t_store_metadata(apps) fdroidserver.update.copy_triple_t_store_metadata(apps)
# TODO ideally, this would compare the whole dict like in metadata.TestCase's test_read_metadata() # TODO ideally, this would compare the whole dict like in test_metadata.test_read_metadata()
correctlocales = [ correctlocales = [
'ar', 'ast_ES', 'az', 'ca', 'ca_ES', 'cs-CZ', 'cs_CZ', 'da', 'ar', 'ast_ES', 'az', 'ca', 'ca_ES', 'cs-CZ', 'cs_CZ', 'da',
'da-DK', 'de', 'de-DE', 'el', 'en-US', 'es', 'es-ES', 'es_ES', 'et', 'da-DK', 'de', 'de-DE', 'el', 'en-US', 'es', 'es-ES', 'es_ES', 'et',
@ -446,12 +431,12 @@ class UpdateTest(unittest.TestCase):
'ru_RU', 'sv-SE', 'sv_SE', 'te', 'tr', 'tr-TR', 'uk', 'uk_UA', 'vi', 'ru_RU', 'sv-SE', 'sv_SE', 'te', 'tr', 'tr-TR', 'uk', 'uk_UA', 'vi',
'vi_VN', 'zh-CN', 'zh_CN', 'zh_TW', 'vi_VN', 'zh-CN', 'zh_CN', 'zh_TW',
] ]
locales = sorted(list(apps['org.fdroid.ci.test.app']['localized'].keys())) locales = sorted(apps['org.fdroid.ci.test.app']['localized'])
self.assertEqual(correctlocales, locales) self.assertEqual(correctlocales, locales)
def test_insert_triple_t_2_metadata(self): def test_insert_triple_t_2_metadata(self):
packageName = 'org.piwigo.android' packageName = 'org.piwigo.android'
shutil.copytree(os.path.join(self.basedir, 'triple-t-2'), self.testdir, dirs_exist_ok=True) shutil.copytree(basedir / 'triple-t-2', self.testdir, dirs_exist_ok=True)
os.chdir(self.testdir) os.chdir(self.testdir)
config = dict() config = dict()
@ -489,7 +474,7 @@ class UpdateTest(unittest.TestCase):
packages = ('com.anysoftkeyboard.languagepack.dutch', 'com.menny.android.anysoftkeyboard') packages = ('com.anysoftkeyboard.languagepack.dutch', 'com.menny.android.anysoftkeyboard')
names = ('Dutch for AnySoftKeyboard', 'AnySoftKeyboard') names = ('Dutch for AnySoftKeyboard', 'AnySoftKeyboard')
shutil.copytree(os.path.join(self.basedir, 'triple-t-anysoftkeyboard'), self.testdir, dirs_exist_ok=True) shutil.copytree(basedir / 'triple-t-anysoftkeyboard', self.testdir, dirs_exist_ok=True)
os.chdir(self.testdir) os.chdir(self.testdir)
for packageName, name in zip(packages, names): for packageName, name in zip(packages, names):
@ -510,7 +495,7 @@ class UpdateTest(unittest.TestCase):
packages = ('verifier', 'wallet') packages = ('verifier', 'wallet')
names = dict(verifier='COVID Certificate Check', wallet='COVID Certificate') names = dict(verifier='COVID Certificate Check', wallet='COVID Certificate')
shutil.copytree(os.path.join(self.basedir, 'triple-t-multiple'), self.testdir, dirs_exist_ok=True) shutil.copytree(basedir / 'triple-t-multiple', self.testdir, dirs_exist_ok=True)
os.chdir(self.testdir) os.chdir(self.testdir)
for p in packages: for p in packages:
@ -530,7 +515,7 @@ class UpdateTest(unittest.TestCase):
def test_insert_triple_t_flutter(self): def test_insert_triple_t_flutter(self):
packageName = 'fr.emersion.goguma' packageName = 'fr.emersion.goguma'
shutil.copytree(os.path.join(self.basedir, 'triple-t-flutter'), self.testdir, dirs_exist_ok=True) shutil.copytree(basedir / 'triple-t-flutter', self.testdir, dirs_exist_ok=True)
os.chdir(self.testdir) os.chdir(self.testdir)
config = dict() config = dict()
@ -602,8 +587,8 @@ class UpdateTest(unittest.TestCase):
def testScanApksAndObbs(self): def testScanApksAndObbs(self):
os.chdir(self.testdir) os.chdir(self.testdir)
shutil.copytree(os.path.join(self.basedir, 'repo'), 'repo') shutil.copytree(basedir / 'repo', 'repo')
shutil.copytree(os.path.join(self.basedir, 'metadata'), 'metadata') shutil.copytree(basedir / 'metadata', 'metadata')
config = dict() config = dict()
fdroidserver.common.fill_config_defaults(config) fdroidserver.common.fill_config_defaults(config)
config['ndk_paths'] = dict() config['ndk_paths'] = dict()
@ -657,7 +642,7 @@ class UpdateTest(unittest.TestCase):
def test_apkcache_json(self): def test_apkcache_json(self):
"""test the migration from pickle to json""" """test the migration from pickle to json"""
os.chdir(self.testdir) os.chdir(self.testdir)
shutil.copytree(os.path.join(self.basedir, 'repo'), 'repo') shutil.copytree(basedir / 'repo', 'repo')
config = dict() config = dict()
fdroidserver.common.fill_config_defaults(config) fdroidserver.common.fill_config_defaults(config)
config['ndk_paths'] = dict() config['ndk_paths'] = dict()
@ -698,7 +683,7 @@ class UpdateTest(unittest.TestCase):
os.chdir(self.testdir) os.chdir(self.testdir)
os.mkdir('repo') os.mkdir('repo')
filename = 'Norway_bouvet_europe_2.obf.zip' filename = 'Norway_bouvet_europe_2.obf.zip'
shutil.copy(os.path.join(self.basedir, filename), 'repo') shutil.copy(basedir / filename, 'repo')
knownapks = fdroidserver.common.KnownApks() knownapks = fdroidserver.common.KnownApks()
files, fcachechanged = fdroidserver.update.scan_repo_files(dict(), 'repo', knownapks, False) files, fcachechanged = fdroidserver.update.scan_repo_files(dict(), 'repo', knownapks, False)
self.assertTrue(fcachechanged) self.assertTrue(fcachechanged)
@ -714,7 +699,7 @@ class UpdateTest(unittest.TestCase):
def test_read_added_date_from_all_apks(self): def test_read_added_date_from_all_apks(self):
os.chdir(self.testdir) os.chdir(self.testdir)
shutil.copytree(os.path.join(self.basedir, 'repo'), 'repo') shutil.copytree(basedir / 'repo', 'repo')
config = dict() config = dict()
fdroidserver.common.fill_config_defaults(config) fdroidserver.common.fill_config_defaults(config)
fdroidserver.common.config = config fdroidserver.common.config = config
@ -727,7 +712,7 @@ class UpdateTest(unittest.TestCase):
def test_apply_info_from_latest_apk(self): def test_apply_info_from_latest_apk(self):
os.chdir(self.testdir) os.chdir(self.testdir)
shutil.copytree(os.path.join(self.basedir, 'repo'), 'repo') shutil.copytree(basedir / 'repo', 'repo')
config = dict() config = dict()
fdroidserver.common.fill_config_defaults(config) fdroidserver.common.fill_config_defaults(config)
fdroidserver.common.config = config fdroidserver.common.config = config
@ -744,7 +729,7 @@ class UpdateTest(unittest.TestCase):
fdroidserver.common.fill_config_defaults(config) fdroidserver.common.fill_config_defaults(config)
fdroidserver.common.config = config fdroidserver.common.config = config
fdroidserver.update.config = config fdroidserver.update.config = config
os.chdir(self.basedir) os.chdir(basedir)
if 'apksigner' in config: if 'apksigner' in config:
apk_info = fdroidserver.update.scan_apk('v2.only.sig_2.apk') apk_info = fdroidserver.update.scan_apk('v2.only.sig_2.apk')
@ -852,7 +837,7 @@ class UpdateTest(unittest.TestCase):
fdroidserver.common.fill_config_defaults(config) fdroidserver.common.fill_config_defaults(config)
fdroidserver.common.config = config fdroidserver.common.config = config
fdroidserver.update.config = config fdroidserver.update.config = config
os.chdir(self.basedir) os.chdir(basedir)
if os.path.basename(os.getcwd()) != 'tests': if os.path.basename(os.getcwd()) != 'tests':
raise Exception('This test must be run in the "tests/" subdir') raise Exception('This test must be run in the "tests/" subdir')
@ -900,10 +885,10 @@ class UpdateTest(unittest.TestCase):
fdroidserver.common.fill_config_defaults(config) fdroidserver.common.fill_config_defaults(config)
fdroidserver.common.config = config fdroidserver.common.config = config
fdroidserver.update.config = config fdroidserver.update.config = config
with tempfile.TemporaryDirectory() as tmpdir, TmpCwd(tmpdir): with mkdtemp() as tmpdir, TmpCwd(tmpdir):
os.mkdir('repo') os.mkdir('repo')
apkfile = 'repo/SystemWebView-repack.apk' apkfile = 'repo/SystemWebView-repack.apk'
shutil.copy(os.path.join(self.basedir, os.path.basename(apkfile)), apkfile) shutil.copy(basedir / os.path.basename(apkfile), apkfile)
fdroidserver.update.scan_apk(apkfile) fdroidserver.update.scan_apk(apkfile)
def test_scan_apk_bad_namespace_in_manifest(self): def test_scan_apk_bad_namespace_in_manifest(self):
@ -923,10 +908,10 @@ class UpdateTest(unittest.TestCase):
fdroidserver.common.fill_config_defaults(config) fdroidserver.common.fill_config_defaults(config)
fdroidserver.common.config = config fdroidserver.common.config = config
fdroidserver.update.config = config fdroidserver.update.config = config
with tempfile.TemporaryDirectory() as tmpdir, TmpCwd(tmpdir): with mkdtemp() as tmpdir, TmpCwd(tmpdir):
os.mkdir('repo') os.mkdir('repo')
apkfile = 'repo/org.sajeg.fallingblocks_3.apk' apkfile = 'repo/org.sajeg.fallingblocks_3.apk'
shutil.copy(os.path.join(self.basedir, os.path.basename(apkfile)), apkfile) shutil.copy(basedir / os.path.basename(apkfile), apkfile)
fdroidserver.update.scan_apk(apkfile) fdroidserver.update.scan_apk(apkfile)
def test_process_apk(self): def test_process_apk(self):
@ -935,7 +920,7 @@ class UpdateTest(unittest.TestCase):
return dumper.represent_dict(data) return dumper.represent_dict(data)
os.chdir(self.testdir) os.chdir(self.testdir)
shutil.copytree(self.basedir, 'tests') shutil.copytree(basedir, 'tests')
config = dict() config = dict()
fdroidserver.common.fill_config_defaults(config) fdroidserver.common.fill_config_defaults(config)
fdroidserver.common.config = config fdroidserver.common.config = config
@ -989,12 +974,12 @@ class UpdateTest(unittest.TestCase):
TestLoader = FullLoader TestLoader = FullLoader
try: try:
testyaml = '- !!python/object/new:fdroidserver.update.UsesPermission\n - test\n - null' testyaml = '- !!python/object/new:fdroidserver.update.UsesPermission\n - test\n - null'
from_yaml = yaml.load(testyaml, Loader=TestLoader) from_yaml = yaml.load(testyaml, Loader=TestLoader) # nosec B506
except yaml.constructor.ConstructorError: except yaml.constructor.ConstructorError:
from yaml import UnsafeLoader as TestLoader from yaml import UnsafeLoader as TestLoader
with open(savepath, 'r') as f: with open(savepath, 'r') as f:
from_yaml = yaml.load(f, Loader=TestLoader) from_yaml = yaml.load(f, Loader=TestLoader) # nosec B506
self.maxDiff = None self.maxDiff = None
if not config.get('ipfs_cid'): if not config.get('ipfs_cid'):
del from_yaml['ipfsCIDv1'] # handle when ipfs_cid is not installed del from_yaml['ipfsCIDv1'] # handle when ipfs_cid is not installed
@ -1017,7 +1002,7 @@ class UpdateTest(unittest.TestCase):
knownapks = fdroidserver.common.KnownApks() knownapks = fdroidserver.common.KnownApks()
with tempfile.TemporaryDirectory() as tmptestsdir, TmpCwd(tmptestsdir): with mkdtemp() as tmptestsdir, TmpCwd(tmptestsdir):
os.mkdir('repo') os.mkdir('repo')
os.mkdir('archive') os.mkdir('archive')
# setup the repo, create icons dirs, etc. # setup the repo, create icons dirs, etc.
@ -1026,7 +1011,7 @@ class UpdateTest(unittest.TestCase):
disabledsigs = ['org.bitbucket.tickytacky.mirrormirror_2.apk'] disabledsigs = ['org.bitbucket.tickytacky.mirrormirror_2.apk']
for apkName in disabledsigs: for apkName in disabledsigs:
shutil.copy(os.path.join(self.basedir, apkName), shutil.copy(basedir / apkName,
os.path.join(tmptestsdir, 'repo')) os.path.join(tmptestsdir, 'repo'))
skip, apk, cachechanged = fdroidserver.update.process_apk({}, apkName, 'repo', skip, apk, cachechanged = fdroidserver.update.process_apk({}, apkName, 'repo',
@ -1081,7 +1066,7 @@ class UpdateTest(unittest.TestCase):
badsigs = ['urzip-badcert.apk', 'urzip-badsig.apk', 'urzip-release-unsigned.apk', ] badsigs = ['urzip-badcert.apk', 'urzip-badsig.apk', 'urzip-release-unsigned.apk', ]
for apkName in badsigs: for apkName in badsigs:
shutil.copy(os.path.join(self.basedir, apkName), shutil.copy(basedir / apkName,
os.path.join(self.testdir, 'repo')) os.path.join(self.testdir, 'repo'))
skip, apk, cachechanged = fdroidserver.update.process_apk({}, apkName, 'repo', skip, apk, cachechanged = fdroidserver.update.process_apk({}, apkName, 'repo',
@ -1093,7 +1078,7 @@ class UpdateTest(unittest.TestCase):
self.assertFalse(cachechanged) self.assertFalse(cachechanged)
def test_process_invalid_apk(self): def test_process_invalid_apk(self):
os.chdir(self.basedir) os.chdir(basedir)
if os.path.basename(os.getcwd()) != 'tests': if os.path.basename(os.getcwd()) != 'tests':
raise Exception('This test must be run in the "tests/" subdir') raise Exception('This test must be run in the "tests/" subdir')
@ -1117,7 +1102,7 @@ class UpdateTest(unittest.TestCase):
def test_get_apks_without_allowed_signatures(self): def test_get_apks_without_allowed_signatures(self):
"""Test when no AllowedAPKSigningKeys is specified""" """Test when no AllowedAPKSigningKeys is specified"""
os.chdir(self.testdir) os.chdir(self.testdir)
shutil.copytree(os.path.join(self.basedir, 'repo'), 'repo') shutil.copytree(basedir / 'repo', 'repo')
config = dict() config = dict()
fdroidserver.common.fill_config_defaults(config) fdroidserver.common.fill_config_defaults(config)
fdroidserver.common.config = config fdroidserver.common.config = config
@ -1128,6 +1113,11 @@ class UpdateTest(unittest.TestCase):
knownapks = fdroidserver.common.KnownApks() knownapks = fdroidserver.common.KnownApks()
apks, cachechanged = fdroidserver.update.process_apks({}, 'repo', knownapks) apks, cachechanged = fdroidserver.update.process_apks({}, 'repo', knownapks)
apkfile = 'v1.v2.sig_1020.apk' apkfile = 'v1.v2.sig_1020.apk'
self.assertIn(
apkfile,
os.listdir('repo'),
f'{apkfile} was archived or otherwise removed from "repo"',
)
(skip, apk, cachechanged) = fdroidserver.update.process_apk( (skip, apk, cachechanged) = fdroidserver.update.process_apk(
{}, apkfile, 'repo', knownapks, False {}, apkfile, 'repo', knownapks, False
) )
@ -1138,7 +1128,7 @@ class UpdateTest(unittest.TestCase):
def test_get_apks_without_allowed_signatures_allowed(self): def test_get_apks_without_allowed_signatures_allowed(self):
"""Test when the APK matches the specified AllowedAPKSigningKeys""" """Test when the APK matches the specified AllowedAPKSigningKeys"""
os.chdir(self.testdir) os.chdir(self.testdir)
shutil.copytree(os.path.join(self.basedir, 'repo'), 'repo') shutil.copytree(basedir / 'repo', 'repo')
config = dict() config = dict()
fdroidserver.common.fill_config_defaults(config) fdroidserver.common.fill_config_defaults(config)
fdroidserver.common.config = config fdroidserver.common.config = config
@ -1163,7 +1153,7 @@ class UpdateTest(unittest.TestCase):
def test_get_apks_without_allowed_signatures_blocked(self): def test_get_apks_without_allowed_signatures_blocked(self):
"""Test when the APK does not match any specified AllowedAPKSigningKeys""" """Test when the APK does not match any specified AllowedAPKSigningKeys"""
os.chdir(self.testdir) os.chdir(self.testdir)
shutil.copytree(os.path.join(self.basedir, 'repo'), 'repo') shutil.copytree(basedir / 'repo', 'repo')
config = dict() config = dict()
fdroidserver.common.fill_config_defaults(config) fdroidserver.common.fill_config_defaults(config)
fdroidserver.common.config = config fdroidserver.common.config = config
@ -1190,12 +1180,12 @@ class UpdateTest(unittest.TestCase):
os.chdir(self.testdir) os.chdir(self.testdir)
os.mkdir('repo') os.mkdir('repo')
testapk = os.path.join('repo', 'com.politedroid_6.apk') testapk = os.path.join('repo', 'com.politedroid_6.apk')
shutil.copy(os.path.join(self.basedir, testapk), testapk) shutil.copy(basedir / testapk, testapk)
os.mkdir('metadata') os.mkdir('metadata')
metadatafile = os.path.join('metadata', 'com.politedroid.yml') metadatafile = os.path.join('metadata', 'com.politedroid.yml')
# Copy and manipulate metadata file # Copy and manipulate metadata file
shutil.copy(os.path.join(self.basedir, metadatafile), metadatafile) shutil.copy(basedir / metadatafile, metadatafile)
with open(metadatafile, 'a') as fp: with open(metadatafile, 'a') as fp:
fp.write( fp.write(
'\n\nAllowedAPKSigningKeys: 32a23624c201b949f085996ba5ed53d40f703aca4989476949cae891022e0ed6\n' '\n\nAllowedAPKSigningKeys: 32a23624c201b949f085996ba5ed53d40f703aca4989476949cae891022e0ed6\n'
@ -1209,7 +1199,7 @@ class UpdateTest(unittest.TestCase):
config['repo_keyalias'] = 'sova' config['repo_keyalias'] = 'sova'
config['keystorepass'] = 'r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI=' config['keystorepass'] = 'r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI='
config['keypass'] = 'r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI=' config['keypass'] = 'r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI='
config['keystore'] = os.path.join(self.basedir, 'keystore.jks') config['keystore'] = os.path.join(basedir, 'keystore.jks')
self.assertTrue(os.path.exists(testapk)) self.assertTrue(os.path.exists(testapk))
@ -1219,7 +1209,7 @@ class UpdateTest(unittest.TestCase):
self.assertTrue(os.path.exists(testapk)) self.assertTrue(os.path.exists(testapk))
# Copy and manipulate metadata file again # Copy and manipulate metadata file again
shutil.copy(os.path.join(self.basedir, metadatafile), metadatafile) shutil.copy(basedir / metadatafile, metadatafile)
with open(metadatafile, 'a') as fp: with open(metadatafile, 'a') as fp:
fp.write( fp.write(
'\n\nAllowedAPKSigningKeys: fa4edeadfa4edeadfa4edeadfa4edeadfa4edeadfa4edeadfa4edeadfa4edead\n' '\n\nAllowedAPKSigningKeys: fa4edeadfa4edeadfa4edeadfa4edeadfa4edeadfa4edeadfa4edeadfa4edead\n'
@ -1232,8 +1222,8 @@ class UpdateTest(unittest.TestCase):
def test_translate_per_build_anti_features(self): def test_translate_per_build_anti_features(self):
os.chdir(self.testdir) os.chdir(self.testdir)
shutil.copytree(os.path.join(self.basedir, 'repo'), 'repo') shutil.copytree(basedir / 'repo', 'repo')
shutil.copytree(os.path.join(self.basedir, 'metadata'), 'metadata') shutil.copytree(basedir / 'metadata', 'metadata')
config = dict() config = dict()
fdroidserver.common.fill_config_defaults(config) fdroidserver.common.fill_config_defaults(config)
config['ndk_paths'] = dict() config['ndk_paths'] = dict()
@ -1263,7 +1253,7 @@ class UpdateTest(unittest.TestCase):
os.chdir(self.testdir) os.chdir(self.testdir)
os.mkdir('repo') os.mkdir('repo')
os.mkdir('metadata') os.mkdir('metadata')
shutil.copy(os.path.join(localmodule, 'tests', 'urzip.apk'), 'repo') shutil.copy(basedir / 'urzip.apk', 'repo')
config = dict() config = dict()
fdroidserver.common.fill_config_defaults(config) fdroidserver.common.fill_config_defaults(config)
@ -1302,7 +1292,7 @@ class UpdateTest(unittest.TestCase):
# test using external template.yml # test using external template.yml
os.remove(testfile) os.remove(testfile)
self.assertFalse(os.path.exists(testfile)) self.assertFalse(os.path.exists(testfile))
shutil.copy(os.path.join(localmodule, 'examples', 'template.yml'), self.testdir) shutil.copy(basedir.with_name('examples') / 'template.yml', self.testdir)
fdroidserver.update.create_metadata_from_template(apk) fdroidserver.update.create_metadata_from_template(apk)
self.assertTrue(os.path.exists(testfile)) self.assertTrue(os.path.exists(testfile))
apps = fdroidserver.metadata.read_metadata() apps = fdroidserver.metadata.read_metadata()
@ -1354,22 +1344,23 @@ class UpdateTest(unittest.TestCase):
# pylint: disable=protected-access # pylint: disable=protected-access
icons_src = fdroidserver.update._get_apk_icons_src('urzip-release.apk', None) icons_src = fdroidserver.update._get_apk_icons_src('urzip-release.apk', None)
assert not icons_src self.assertFalse(icons_src)
def test_strip_and_copy_image(self): def test_strip_and_copy_image(self):
in_file = os.path.join(self.basedir, 'metadata', 'info.guardianproject.urzip', 'en-US', 'images', 'icon.png') in_file = basedir / 'metadata/info.guardianproject.urzip/en-US/images/icon.png'
out_file = os.path.join(self.testdir, 'icon.png') out_file = os.path.join(self.testdir, 'icon.png')
fdroidserver.update._strip_and_copy_image(in_file, out_file) fdroidserver.update._strip_and_copy_image(in_file, out_file)
self.assertTrue(os.path.exists(out_file)) self.assertTrue(os.path.exists(out_file))
in_file = os.path.join(self.basedir, 'corrupt-featureGraphic.png') def test_strip_and_copy_image_bad_filename(self):
in_file = basedir / 'corrupt-featureGraphic.png'
out_file = os.path.join(self.testdir, 'corrupt-featureGraphic.png') out_file = os.path.join(self.testdir, 'corrupt-featureGraphic.png')
fdroidserver.update._strip_and_copy_image(in_file, out_file) fdroidserver.update._strip_and_copy_image(in_file, out_file)
self.assertFalse(os.path.exists(out_file)) self.assertFalse(os.path.exists(out_file))
def test_create_metadata_from_template_empty_keys(self): def test_create_metadata_from_template_empty_keys(self):
apk = {'packageName': 'rocks.janicerand'} apk = {'packageName': 'rocks.janicerand'}
with tempfile.TemporaryDirectory() as tmpdir, TmpCwd(tmpdir): with mkdtemp() as tmpdir, TmpCwd(tmpdir):
os.mkdir('metadata') os.mkdir('metadata')
with open('template.yml', 'w') as f: with open('template.yml', 'w') as f:
f.write( f.write(
@ -1554,7 +1545,7 @@ class UpdateTest(unittest.TestCase):
self.assertIsNone(app.get(field)) self.assertIsNone(app.get(field))
def test_sanitize_funding_yml(self): def test_sanitize_funding_yml(self):
with open(os.path.join(self.basedir, 'funding-usernames.yaml')) as fp: with open(basedir / 'funding-usernames.yaml') as fp:
data = yaml.load(fp, Loader=SafeLoader) data = yaml.load(fp, Loader=SafeLoader)
for k, entries in data.items(): for k, entries in data.items():
for entry in entries: for entry in entries:
@ -1568,7 +1559,7 @@ class UpdateTest(unittest.TestCase):
self.assertIsNotNone(m) self.assertIsNotNone(m)
self.assertIsNone(fdroidserver.update.sanitize_funding_yml_entry('foo\nbar')) self.assertIsNone(fdroidserver.update.sanitize_funding_yml_entry('foo\nbar'))
self.assertIsNone(fdroidserver.update.sanitize_funding_yml_entry( self.assertIsNone(fdroidserver.update.sanitize_funding_yml_entry(
''.join(chr(random.randint(65, 90)) for _ in range(2049)))) ''.join(chr(random.randint(65, 90)) for _ in range(2049)))) # nosec B311
# not recommended but valid entries # not recommended but valid entries
self.assertIsNotNone(fdroidserver.update.sanitize_funding_yml_entry(12345)) self.assertIsNotNone(fdroidserver.update.sanitize_funding_yml_entry(12345))
@ -1593,7 +1584,7 @@ class UpdateTest(unittest.TestCase):
for f, key in files.items(): for f, key in files.items():
limit = config['char_limits'][key] limit = config['char_limits'][key]
with open(f, 'w') as fp: with open(f, 'w') as fp:
fp.write(''.join(random.choice(string.ascii_letters) for i in range(limit + 100))) fp.write(''.join(random.choice(string.ascii_letters) for i in range(limit + 100))) # nosec B311
locale = 'ru_US' locale = 'ru_US'
app = dict() app = dict()
fdroidserver.update._set_localized_text_entry(app, locale, key, f) fdroidserver.update._set_localized_text_entry(app, locale, key, f)
@ -1628,7 +1619,7 @@ class UpdateTest(unittest.TestCase):
limit = config['char_limits']['author'] limit = config['char_limits']['author']
for key in ('authorEmail', 'authorPhone', 'authorWebSite'): for key in ('authorEmail', 'authorPhone', 'authorWebSite'):
with open(f, 'w') as fp: with open(f, 'w') as fp:
fp.write(''.join(random.choice(string.ascii_letters) for i in range(limit + 100))) fp.write(''.join(random.choice(string.ascii_letters) for i in range(limit + 100))) # nosec B311
app = dict() app = dict()
fdroidserver.update._set_author_entry(app, key, f) fdroidserver.update._set_author_entry(app, key, f)
self.assertEqual(limit, len(app[key])) self.assertEqual(limit, len(app[key]))
@ -1643,7 +1634,7 @@ class UpdateTest(unittest.TestCase):
fdroidserver.common.config = {} fdroidserver.common.config = {}
fdroidserver.update.config = {} fdroidserver.update.config = {}
fdroidserver.update.options = Options fdroidserver.update.options = Options
with tempfile.TemporaryDirectory() as tmpdir: with mkdtemp() as tmpdir:
os.chdir(tmpdir) os.chdir(tmpdir)
with mock.patch('sys.argv', ['fdroid update', '']): with mock.patch('sys.argv', ['fdroid update', '']):
fdroidserver.update.status_update_json([], []) fdroidserver.update.status_update_json([], [])
@ -1737,7 +1728,7 @@ class UpdateTest(unittest.TestCase):
os.mkdir('repo') os.mkdir('repo')
testapk = os.path.join('repo', 'com.politedroid_6.apk') testapk = os.path.join('repo', 'com.politedroid_6.apk')
testapk_new = os.path.join('repo', 'Politedroid-1.5.apk') testapk_new = os.path.join('repo', 'Politedroid-1.5.apk')
shutil.copy(os.path.join(self.basedir, testapk), testapk_new) shutil.copy(basedir / testapk, testapk_new)
config = dict() config = dict()
fdroidserver.common.fill_config_defaults(config) fdroidserver.common.fill_config_defaults(config)
@ -1817,14 +1808,14 @@ class UpdateTest(unittest.TestCase):
) )
testapk = os.path.join('repo', 'com.politedroid_6.apk') testapk = os.path.join('repo', 'com.politedroid_6.apk')
shutil.copy(os.path.join(self.basedir, testapk), testapk) shutil.copy(basedir / testapk, testapk)
Path('metadata/com.politedroid.yml').write_text('Name: Polite') Path('metadata/com.politedroid.yml').write_text('Name: Polite')
with mock.patch('sys.argv', ['fdroid update', '--delete-unknown', '--nosign']): with mock.patch('sys.argv', ['fdroid update', '--delete-unknown', '--nosign']):
fdroidserver.update.main() fdroidserver.update.main()
with open('repo/index-v2.json') as fp: with open('repo/index-v2.json') as fp:
index = json.load(fp) index = json.load(fp)
self.assertFalse(CATEGORIES_CONFIG_NAME in index['repo']) self.assertNotIn(CATEGORIES_CONFIG_NAME, index['repo'])
def test_auto_defined_categories(self): def test_auto_defined_categories(self):
"""Repos that don't define categories in config/ should use auto-generated.""" """Repos that don't define categories in config/ should use auto-generated."""
@ -1836,7 +1827,7 @@ class UpdateTest(unittest.TestCase):
) )
testapk = os.path.join('repo', 'com.politedroid_6.apk') testapk = os.path.join('repo', 'com.politedroid_6.apk')
shutil.copy(os.path.join(self.basedir, testapk), testapk) shutil.copy(basedir / testapk, testapk)
Path('metadata/com.politedroid.yml').write_text('Categories: [Time]') Path('metadata/com.politedroid.yml').write_text('Categories: [Time]')
with mock.patch('sys.argv', ['fdroid update', '--delete-unknown', '--nosign']): with mock.patch('sys.argv', ['fdroid update', '--delete-unknown', '--nosign']):
@ -1858,10 +1849,10 @@ class UpdateTest(unittest.TestCase):
) )
testapk = os.path.join('repo', 'com.politedroid_6.apk') testapk = os.path.join('repo', 'com.politedroid_6.apk')
shutil.copy(os.path.join(self.basedir, testapk), testapk) shutil.copy(basedir / testapk, testapk)
Path('metadata/com.politedroid.yml').write_text('Categories: [bar]') Path('metadata/com.politedroid.yml').write_text('Categories: [bar]')
testapk = os.path.join('repo', 'souch.smsbypass_9.apk') testapk = os.path.join('repo', 'souch.smsbypass_9.apk')
shutil.copy(os.path.join(self.basedir, testapk), testapk) shutil.copy(basedir / testapk, testapk)
Path('metadata/souch.smsbypass.yml').write_text('Categories: [foo, bar]') Path('metadata/souch.smsbypass.yml').write_text('Categories: [foo, bar]')
with mock.patch('sys.argv', ['fdroid update', '--delete-unknown', '--nosign']): with mock.patch('sys.argv', ['fdroid update', '--delete-unknown', '--nosign']):
@ -1885,10 +1876,10 @@ class UpdateTest(unittest.TestCase):
) )
testapk = os.path.join('repo', 'com.politedroid_6.apk') testapk = os.path.join('repo', 'com.politedroid_6.apk')
shutil.copy(os.path.join(self.basedir, testapk), testapk) shutil.copy(basedir / testapk, testapk)
Path('metadata/com.politedroid.yml').write_text('Categories: [Time]') Path('metadata/com.politedroid.yml').write_text('Categories: [Time]')
testapk = os.path.join('repo', 'souch.smsbypass_9.apk') testapk = os.path.join('repo', 'souch.smsbypass_9.apk')
shutil.copy(os.path.join(self.basedir, testapk), testapk) shutil.copy(basedir / testapk, testapk)
Path('metadata/souch.smsbypass.yml').write_text('Categories: [System, Time]') Path('metadata/souch.smsbypass.yml').write_text('Categories: [System, Time]')
with mock.patch('sys.argv', ['fdroid update', '--delete-unknown', '--nosign']): with mock.patch('sys.argv', ['fdroid update', '--delete-unknown', '--nosign']):
@ -1915,7 +1906,7 @@ class UpdateTest(unittest.TestCase):
) )
testapk = os.path.join('repo', 'com.politedroid_6.apk') testapk = os.path.join('repo', 'com.politedroid_6.apk')
shutil.copy(os.path.join(self.basedir, testapk), testapk) shutil.copy(basedir / testapk, testapk)
Path('metadata/com.politedroid.yml').write_text('Categories: [Time]') Path('metadata/com.politedroid.yml').write_text('Categories: [Time]')
with mock.patch('sys.argv', ['fdroid update', '--delete-unknown', '--nosign']): with mock.patch('sys.argv', ['fdroid update', '--delete-unknown', '--nosign']):
@ -1937,12 +1928,8 @@ class TestParseIpa(unittest.TestCase):
biplist # silence the linters biplist # silence the linters
except ImportError as e: except ImportError as e:
self.skipTest(str(e)) self.skipTest(str(e))
ipa_path = os.path.join( ipa_path = os.path.join(basedir, 'com.fake.IpaApp_1000000000001.ipa')
os.path.dirname(os.path.abspath(__file__)),
'com.fake.IpaApp_1000000000001.ipa',
)
result = fdroidserver.update.parse_ipa(ipa_path, 'fake_size', 'fake_sha') result = fdroidserver.update.parse_ipa(ipa_path, 'fake_size', 'fake_sha')
self.maxDiff = None
self.assertDictEqual( self.assertDictEqual(
result, result,
{ {
@ -2007,12 +1994,10 @@ class TestUpdateVersionStringToInt(unittest.TestCase):
class TestScanRepoForIpas(unittest.TestCase): class TestScanRepoForIpas(unittest.TestCase):
def setUp(self):
self.maxDiff = None
def test_scan_repo_for_ipas_no_cache(self): def test_scan_repo_for_ipas_no_cache(self):
self.maxDiff = None self.maxDiff = None
with tempfile.TemporaryDirectory() as tmpdir, TmpCwd(tmpdir): with mkdtemp() as tmpdir:
os.chdir(tmpdir)
os.mkdir("repo") os.mkdir("repo")
with open('repo/abc.Def_123.ipa', 'w') as f: with open('repo/abc.Def_123.ipa', 'w') as f:
f.write('abc') f.write('abc')
@ -2020,7 +2005,6 @@ class TestScanRepoForIpas(unittest.TestCase):
f.write('xyz') f.write('xyz')
apkcache = mock.MagicMock() apkcache = mock.MagicMock()
# apkcache['a'] = 1
repodir = "repo" repodir = "repo"
knownapks = mock.MagicMock() knownapks = mock.MagicMock()
@ -2129,7 +2113,7 @@ class TestDiscoverIosScreenshots(unittest.TestCase):
def test_discover_ios_screenshots(self): def test_discover_ios_screenshots(self):
self.maxDiff = None self.maxDiff = None
with tempfile.TemporaryDirectory() as fastlane_dir: with mkdtemp() as fastlane_dir:
fastlane_dir = Path(fastlane_dir) fastlane_dir = Path(fastlane_dir)
(fastlane_dir / "screenshots/en-US").mkdir(parents=True) (fastlane_dir / "screenshots/en-US").mkdir(parents=True)
with open(fastlane_dir / "screenshots/en-US/iPhone 8+ @ iOS 16-1.png", 'w') as f: with open(fastlane_dir / "screenshots/en-US/iPhone 8+ @ iOS 16-1.png", 'w') as f:
@ -2166,6 +2150,14 @@ class TestDiscoverIosScreenshots(unittest.TestCase):
class TestCopyIosScreenshotsToRepo(unittest.TestCase): class TestCopyIosScreenshotsToRepo(unittest.TestCase):
def setUp(self):
self._td = mkdtemp()
os.chdir(self._td.name)
def tearDown(self):
os.chdir(basedir)
self._td.cleanup()
def test_copy_ios_screenshots_to_repo(self): def test_copy_ios_screenshots_to_repo(self):
self.maxDiff = None self.maxDiff = None
@ -2218,7 +2210,7 @@ class TestGetIpaIcon(unittest.TestCase):
def test_get_ipa_icon(self): def test_get_ipa_icon(self):
self.maxDiff = None self.maxDiff = None
with tempfile.TemporaryDirectory() as tmpdir: with mkdtemp() as tmpdir:
tmpdir = Path(tmpdir) tmpdir = Path(tmpdir)
(tmpdir / 'OnionBrowser.xcodeproj').mkdir() (tmpdir / 'OnionBrowser.xcodeproj').mkdir()
with open(tmpdir / 'OnionBrowser.xcodeproj/project.pbxproj', "w") as f: with open(tmpdir / 'OnionBrowser.xcodeproj/project.pbxproj', "w") as f:
@ -2245,7 +2237,7 @@ class TestParseFromPbxproj(unittest.TestCase):
def test_parse_from_pbxproj(self): def test_parse_from_pbxproj(self):
self.maxDiff = None self.maxDiff = None
with tempfile.TemporaryDirectory() as tmpdir: with mkdtemp() as tmpdir:
with open(Path(tmpdir) / "asdf.pbxproj", 'w', encoding="utf-8") as f: with open(Path(tmpdir) / "asdf.pbxproj", 'w', encoding="utf-8") as f:
f.write(""" f.write("""
230jfaod=flc' 230jfaod=flc'
@ -2257,29 +2249,3 @@ class TestParseFromPbxproj(unittest.TestCase):
"ASSETCATALOG_COMPILER_APPICON_NAME" "ASSETCATALOG_COMPILER_APPICON_NAME"
) )
self.assertEqual(v, "MyIcon") self.assertEqual(v, "MyIcon")
if __name__ == "__main__":
os.chdir(os.path.dirname(__file__))
import argparse
parser = argparse.ArgumentParser()
parser.add_argument(
"-v",
"--verbose",
action="store_true",
default=False,
help="Spew out even more information than normal",
)
parse_args_for_test(parser, sys.argv)
newSuite = unittest.TestSuite()
newSuite.addTest(unittest.makeSuite(UpdateTest))
newSuite.addTest(unittest.makeSuite(TestUpdateVersionStringToInt))
newSuite.addTest(unittest.makeSuite(TestScanRepoForIpas))
newSuite.addTest(unittest.makeSuite(TestParseIosScreenShotName))
newSuite.addTest(unittest.makeSuite(TestInsertLocalizedIosAppMetadata))
newSuite.addTest(unittest.makeSuite(TestDiscoverIosScreenshots))
newSuite.addTest(unittest.makeSuite(TestGetIpaIcon))
unittest.main(failfast=False)

View File

@ -1,45 +1,26 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# http://www.drdobbs.com/testing/unit-testing-with-python/240165163
import inspect
import logging
import os import os
import sys
import unittest import unittest
from git import Repo from git import Repo
localmodule = os.path.realpath(
os.path.join(os.path.dirname(inspect.getfile(inspect.currentframe())), '..')
)
print('localmodule: ' + localmodule)
if localmodule not in sys.path:
sys.path.insert(0, localmodule)
import fdroidserver.build
import fdroidserver.common import fdroidserver.common
import fdroidserver.metadata import fdroidserver.metadata
import fdroidserver.scanner from .testcommon import mkdtemp
from testcommon import mkdtemp, parse_args_for_test
class VCSTest(unittest.TestCase): class VCSTest(unittest.TestCase):
"""For some reason the VCS classes are in fdroidserver/common.py""" """For some reason the VCS classes are in fdroidserver/common.py"""
def setUp(self): def setUp(self):
logging.basicConfig(level=logging.DEBUG)
self.basedir = os.path.join(localmodule, 'tests')
os.chdir(self.basedir)
self._td = mkdtemp() self._td = mkdtemp()
self.testdir = self._td.name os.chdir(self._td.name)
def tearDown(self): def tearDown(self):
self._td.cleanup() self._td.cleanup()
os.chdir(self.basedir)
def test_remote_set_head_can_fail(self): def test_remote_set_head_can_fail(self):
os.chdir(self.testdir)
# First create an upstream repo with one commit # First create an upstream repo with one commit
upstream_repo = Repo.init("upstream_repo") upstream_repo = Repo.init("upstream_repo")
with open(upstream_repo.working_dir + "/file", 'w') as f: with open(upstream_repo.working_dir + "/file", 'w') as f:
@ -72,6 +53,8 @@ class VCSTest(unittest.TestCase):
build.androidupdate = ['no'] build.androidupdate = ['no']
vcs, build_dir = fdroidserver.common.setup_vcs(app) vcs, build_dir = fdroidserver.common.setup_vcs(app)
# force an init of the repo, the remote head error only occurs on the second gotorevision call # force an init of the repo, the remote head error only occurs on the second gotorevision call
fdroidserver.common.options = type('Options', (), {'verbose': False})
vcs.gotorevision(build.commit) vcs.gotorevision(build.commit)
fdroidserver.common.prepare_source( fdroidserver.common.prepare_source(
vcs, vcs,
@ -82,23 +65,3 @@ class VCSTest(unittest.TestCase):
extlib_dir="ignore", extlib_dir="ignore",
) )
self.assertTrue(os.path.isfile("build/com.gpl.rpg.AndorsTrail/file")) self.assertTrue(os.path.isfile("build/com.gpl.rpg.AndorsTrail/file"))
if __name__ == "__main__":
os.chdir(os.path.dirname(__file__))
import argparse
parser = argparse.ArgumentParser()
parser.add_argument(
"-v",
"--verbose",
action="store_true",
default=False,
help="Spew out even more information than normal",
)
parse_args_for_test(parser, sys.argv)
newSuite = unittest.TestSuite()
newSuite.addTest(unittest.makeSuite(VCSTest))
unittest.main(failfast=False)

View File

@ -1,25 +1,15 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import inspect
import json import json
import logging
import os import os
import shutil import shutil
import sys
import tempfile import tempfile
import unittest import unittest
from pathlib import Path from pathlib import Path
from unittest.mock import patch from unittest.mock import patch
localmodule = os.path.realpath( from fdroidserver import verify
os.path.join(os.path.dirname(inspect.getfile(inspect.currentframe())), '..')
)
print('localmodule: ' + localmodule)
if localmodule not in sys.path:
sys.path.insert(0, localmodule)
from fdroidserver import common, verify
TEST_APP_ENTRY = { TEST_APP_ENTRY = {
@ -45,12 +35,11 @@ TEST_APP_ENTRY = {
} }
} }
basedir = Path(__file__).parent
class VerifyTest(unittest.TestCase): class VerifyTest(unittest.TestCase):
basedir = Path(__file__).resolve().parent
def setUp(self): def setUp(self):
logging.basicConfig(level=logging.DEBUG)
self.tempdir = tempfile.TemporaryDirectory() self.tempdir = tempfile.TemporaryDirectory()
os.chdir(self.tempdir.name) os.chdir(self.tempdir.name)
self.repodir = Path('repo') self.repodir = Path('repo')
@ -72,8 +61,8 @@ class VerifyTest(unittest.TestCase):
remote_apk = 'tmp/' + apk_name remote_apk = 'tmp/' + apk_name
unsigned_apk = 'unsigned/' + apk_name unsigned_apk = 'unsigned/' + apk_name
# TODO common.use apk_strip_v1_signatures() on unsigned_apk # TODO common.use apk_strip_v1_signatures() on unsigned_apk
shutil.copy(str(self.basedir / 'repo' / apk_name), remote_apk) shutil.copy(basedir / 'repo' / apk_name, remote_apk)
shutil.copy(str(self.basedir / 'repo' / apk_name), unsigned_apk) shutil.copy(basedir / 'repo' / apk_name, unsigned_apk)
url = TEST_APP_ENTRY['1539780240.3885746']['url'] url = TEST_APP_ENTRY['1539780240.3885746']['url']
self.assertFalse(verified_json.exists()) self.assertFalse(verified_json.exists())
@ -88,23 +77,3 @@ class VerifyTest(unittest.TestCase):
secondpass = json.load(fp) secondpass = json.load(fp)
self.assertEqual(firstpass, secondpass) self.assertEqual(firstpass, secondpass)
if __name__ == "__main__":
os.chdir(os.path.dirname(__file__))
import argparse
parser = argparse.ArgumentParser()
parser.add_argument(
"-v",
"--verbose",
action="store_true",
default=False,
help="Spew out even more information than normal",
)
common.options = common.parse_args(parser)
newSuite = unittest.TestSuite()
newSuite.addTest(unittest.makeSuite(VerifyTest))
unittest.main(failfast=False)

View File

@ -78,19 +78,6 @@ def mkdir_testfiles(localmodule, test):
return tempfile.mkdtemp(dir=testdir) return tempfile.mkdtemp(dir=testdir)
def parse_args_for_test(parser, args):
"""Only send --flags to the ArgumentParser, not test classes, etc."""
from fdroidserver.common import parse_args
flags = []
for arg in args:
if arg[0] == '-':
flags.append(flags)
with unittest.mock.patch('sys.argv', flags):
parse_args(parser)
def mock_urlopen(status=200, body=None): def mock_urlopen(status=200, body=None):
resp = unittest.mock.MagicMock() resp = unittest.mock.MagicMock()
resp.getcode.return_value = status resp.getcode.return_value = status