1
0
mirror of https://gitlab.com/fdroid/fdroidserver.git synced 2024-11-15 03:20:10 +01:00
fdroidserver/tests/checkupdates.TestCase
2024-10-30 14:43:45 +00:00

398 lines
15 KiB
Python
Executable File

#!/usr/bin/env python3
# http://www.drdobbs.com/testing/unit-testing-with-python/240165163
import git
import logging
import os
import shutil
import sys
import tempfile
import time
import unittest
from unittest import mock
from pathlib import Path
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.metadata
from fdroidserver.exception import FDroidException
class CheckupdatesTest(unittest.TestCase):
'''fdroidserver/checkupdates.py'''
def setUp(self):
logging.basicConfig(level=logging.DEBUG)
self.basedir = localmodule / 'tests'
os.chdir(self.basedir)
self.testdir = tempfile.TemporaryDirectory(
str(time.time()), self._testMethodName + '_'
)
def tearDown(self):
self.testdir.cleanup()
def test_autoupdatemode_no_suffix(self):
fdroidserver.checkupdates.config = {}
app = fdroidserver.metadata.App()
app.id = 'loop.starts.shooting'
app.metadatapath = 'metadata/' + app.id + '.yml'
app.CurrentVersion = '1.1.8-fdroid'
app.CurrentVersionCode = 10108
app.UpdateCheckMode = 'HTTP'
app.AutoUpdateMode = 'Version %v'
build = fdroidserver.metadata.Build()
build.versionCode = app.CurrentVersionCode
build.versionName = app.CurrentVersion
app['Builds'].append(build)
with mock.patch(
'fdroidserver.checkupdates.check_http', lambda app: ('1.1.9', 10109)
):
with mock.patch('fdroidserver.metadata.write_metadata', mock.Mock()):
with mock.patch('subprocess.call', lambda cmd: 0):
fdroidserver.checkupdates.checkupdates_app(app, auto=True)
build = app['Builds'][-1]
self.assertEqual(build.versionName, '1.1.9')
self.assertEqual(build.commit, '1.1.9')
with mock.patch(
'fdroidserver.checkupdates.check_http', lambda app: ('1.7.9', 10107)
):
with mock.patch('fdroidserver.metadata.write_metadata', mock.Mock()):
with mock.patch('subprocess.call', lambda cmd: 0):
with self.assertRaises(FDroidException):
fdroidserver.checkupdates.checkupdates_app(app, auto=True)
build = app['Builds'][-1]
self.assertEqual(build.versionName, '1.1.9')
self.assertEqual(build.commit, '1.1.9')
def test_autoupdatemode_suffix(self):
fdroidserver.checkupdates.config = {}
app = fdroidserver.metadata.App()
app.id = 'loop.starts.shooting'
app.metadatapath = 'metadata/' + app.id + '.yml'
app.CurrentVersion = '1.1.8-fdroid'
app.CurrentVersionCode = 10108
app.UpdateCheckMode = 'HTTP'
app.AutoUpdateMode = r'Version +.%c-fdroid v%v_%c'
build = fdroidserver.metadata.Build()
build.versionCode = app.CurrentVersionCode
build.versionName = app.CurrentVersion
app['Builds'].append(build)
with mock.patch(
'fdroidserver.checkupdates.check_http', lambda app: ('1.1.9', 10109)
):
with mock.patch('fdroidserver.metadata.write_metadata', mock.Mock()):
with mock.patch('subprocess.call', lambda cmd: 0):
fdroidserver.checkupdates.checkupdates_app(app, auto=True)
build = app['Builds'][-1]
self.assertEqual(build.versionName, '1.1.9.10109-fdroid')
self.assertEqual(build.commit, 'v1.1.9_10109')
def test_autoupdate_multi_variants(self):
fdroidserver.checkupdates.config = {}
app = fdroidserver.metadata.App()
app.id = 'loop.starts.shooting'
app.metadatapath = 'metadata/' + app.id + '.yml'
app.CurrentVersion = '1.1.8'
app.CurrentVersionCode = 101083
app.UpdateCheckMode = 'Tags'
app.AutoUpdateMode = r'Version'
app.VercodeOperation = [
"10*%c+1",
"10*%c+3",
]
build = fdroidserver.metadata.Build()
build.versionCode = app.CurrentVersionCode - 2
build.versionName = app.CurrentVersion
build.gradle = ["arm"]
app['Builds'].append(build)
build = fdroidserver.metadata.Build()
build.versionCode = app.CurrentVersionCode
build.versionName = app.CurrentVersion
build.gradle = ["x86"]
app['Builds'].append(build)
with mock.patch(
'fdroidserver.checkupdates.check_tags',
lambda app, pattern: ('1.1.9', 10109, 'v1.1.9'),
):
with mock.patch('fdroidserver.metadata.write_metadata', mock.Mock()):
with mock.patch('subprocess.call', lambda cmd: 0):
fdroidserver.checkupdates.checkupdates_app(app, auto=True)
build = app['Builds'][-2]
self.assertEqual(build.versionName, '1.1.9')
self.assertEqual(build.versionCode, 101091)
self.assertEqual(build.gradle, ["arm"])
build = app['Builds'][-1]
self.assertEqual(build.versionName, '1.1.9')
self.assertEqual(build.versionCode, 101093)
self.assertEqual(build.gradle, ["x86"])
self.assertEqual(app.CurrentVersion, '1.1.9')
self.assertEqual(app.CurrentVersionCode, 101093)
def test_checkupdates_app_http(self):
fdroidserver.checkupdates.config = {}
app = fdroidserver.metadata.App()
app.id = 'loop.starts.shooting'
app.metadatapath = 'metadata/' + app.id + '.yml'
app.CurrentVersionCode = 10108
app.UpdateCheckMode = 'HTTP'
app.UpdateCheckData = 'mock'
with mock.patch(
'fdroidserver.checkupdates.check_http', lambda app: (None, 'bla')
):
with self.assertRaises(FDroidException):
fdroidserver.checkupdates.checkupdates_app(app, auto=True)
with mock.patch(
'fdroidserver.checkupdates.check_http', lambda app: ('1.1.9', 10109)
):
with mock.patch(
'fdroidserver.metadata.write_metadata', mock.Mock()
) as wrmock:
with mock.patch('subprocess.call', lambda cmd: 0):
fdroidserver.checkupdates.checkupdates_app(app, auto=True)
wrmock.assert_called_with(app.metadatapath, app)
def test_checkupdates_app_tags(self):
fdroidserver.checkupdates.config = {}
app = fdroidserver.metadata.App()
app.id = 'loop.starts.shooting'
app.metadatapath = 'metadata/' + app.id + '.yml'
app.CurrentVersion = '1.1.8'
app.CurrentVersionCode = 10108
app.UpdateCheckMode = 'Tags'
app.AutoUpdateMode = 'Version'
build = fdroidserver.metadata.Build()
build.versionCode = app.CurrentVersionCode
build.versionName = app.CurrentVersion
app['Builds'].append(build)
with mock.patch(
'fdroidserver.checkupdates.check_tags',
lambda app, pattern: (None, 'bla', None),
):
with self.assertRaises(FDroidException):
fdroidserver.checkupdates.checkupdates_app(app, auto=True)
with mock.patch(
'fdroidserver.checkupdates.check_tags',
lambda app, pattern: ('1.1.9', 10109, 'v1.1.9'),
):
with mock.patch('fdroidserver.metadata.write_metadata', mock.Mock()):
with mock.patch('subprocess.call', lambda cmd: 0):
fdroidserver.checkupdates.checkupdates_app(app, auto=True)
build = app['Builds'][-1]
self.assertEqual(build.versionName, '1.1.9')
self.assertEqual(build.commit, 'v1.1.9')
def test_check_http(self):
app = fdroidserver.metadata.App()
app.id = 'loop.starts.shooting'
app.metadatapath = 'metadata/' + app.id + '.yml'
app.CurrentVersionCode = 10108
app.UpdateCheckMode = 'HTTP'
app.UpdateCheckData = r'https://a.net/b.txt|c(.*)|https://d.net/e.txt|v(.*)'
app.UpdateCheckIgnore = 'beta'
respmock = mock.Mock()
respmock.read = lambda: 'v1.1.9\nc10109'.encode('utf-8')
with mock.patch('urllib.request.urlopen', lambda a, b, c: respmock):
vername, vercode = fdroidserver.checkupdates.check_http(app)
self.assertEqual(vername, '1.1.9')
self.assertEqual(vercode, 10109)
def test_check_http_blocks_unknown_schemes(self):
app = fdroidserver.metadata.App()
for scheme in ('file', 'ssh', 'http', ';pwn'):
app.id = scheme
faked = scheme + '://fake.url/for/testing/scheme'
app.UpdateCheckData = faked + '|ignored|' + faked + '|ignored'
app.metadatapath = 'metadata/' + app.id + '.yml'
with self.assertRaises(FDroidException):
fdroidserver.checkupdates.check_http(app)
def test_check_http_ignore(self):
app = fdroidserver.metadata.App()
app.id = 'loop.starts.shooting'
app.metadatapath = 'metadata/' + app.id + '.yml'
app.CurrentVersionCode = 10108
app.UpdateCheckMode = 'HTTP'
app.UpdateCheckData = r'https://a.net/b.txt|c(.*)|https://d.net/e.txt|v(.*)'
app.UpdateCheckIgnore = 'beta'
respmock = mock.Mock()
respmock.read = lambda: 'v1.1.9-beta\nc10109'.encode('utf-8')
with mock.patch('urllib.request.urlopen', lambda a, b, c: respmock):
vername, vercode = fdroidserver.checkupdates.check_http(app)
self.assertEqual(vername, None)
def test_check_tags_data(self):
app = fdroidserver.metadata.App()
app.id = 'loop.starts.shooting'
app.metadatapath = 'metadata/' + app.id + '.yml'
app.RepoType = 'git'
app.CurrentVersionCode = 10108
app.UpdateCheckMode = 'Tags'
app.UpdateCheckData = r'b.txt|c(.*)|e.txt|v(.*)'
vcs = mock.Mock()
vcs.latesttags.return_value = ['1.1.9', '1.1.8']
with mock.patch(
'pathlib.Path.read_text', lambda a: 'v1.1.9\nc10109'
) as _ignored, mock.patch.object(Path, 'is_file') as mock_path, mock.patch(
'fdroidserver.common.getvcs', return_value=vcs
):
_ignored # silence the linters
mock_path.is_file.return_falue = True
vername, vercode, _tag = fdroidserver.checkupdates.check_tags(app, None)
self.assertEqual(vername, '1.1.9')
self.assertEqual(vercode, 10109)
app.UpdateCheckData = r'b.txt|c(.*)|.|v(.*)'
with mock.patch(
'pathlib.Path.read_text', lambda a: 'v1.1.0\nc10109'
) as _ignored, mock.patch.object(Path, 'is_file') as mock_path, mock.patch(
'fdroidserver.common.getvcs', return_value=vcs
):
_ignored # silence the linters
mock_path.is_file.return_falue = True
vername, vercode, _tag = fdroidserver.checkupdates.check_tags(app, None)
self.assertEqual(vername, '1.1.0')
self.assertEqual(vercode, 10109)
app.UpdateCheckData = r'b.txt|c(.*)||'
with mock.patch(
'pathlib.Path.read_text', lambda a: 'v1.1.9\nc10109'
) as _ignored, mock.patch.object(Path, 'is_file') as mock_path, mock.patch(
'fdroidserver.common.getvcs', return_value=vcs
):
_ignored # silence the linters
mock_path.is_file.return_falue = True
vername, vercode, _tag = fdroidserver.checkupdates.check_tags(app, None)
self.assertEqual(vername, '1.1.9')
self.assertEqual(vercode, 10109)
vcs.latesttags.return_value = ['Android-1.1.0', '1.1.8']
app.UpdateCheckData = r'b.txt|c(.*)||Android-([\d.]+)'
with mock.patch(
'pathlib.Path.read_text', lambda a: 'v1.1.9\nc10109'
) as _ignored, mock.patch.object(Path, 'is_file') as mock_path, mock.patch(
'fdroidserver.common.getvcs', return_value=vcs
):
_ignored # silence the linters
mock_path.is_file.return_falue = True
vername, vercode, _tag = fdroidserver.checkupdates.check_tags(app, None)
self.assertEqual(vername, '1.1.0')
self.assertEqual(vercode, 10109)
app.UpdateCheckData = r'|\+(\d+)||Android-([\d.]+)'
vcs.latesttags.return_value = ['Android-1.1.0+1']
with mock.patch('fdroidserver.common.getvcs', return_value=vcs):
vername, vercode, _tag = fdroidserver.checkupdates.check_tags(app, None)
self.assertEqual(vername, '1.1.0')
self.assertEqual(vercode, 1)
app.UpdateCheckData = '|||'
vcs.latesttags.return_value = ['2']
with mock.patch('fdroidserver.common.getvcs', return_value=vcs):
vername, vercode, _tag = fdroidserver.checkupdates.check_tags(app, None)
self.assertEqual(vername, '2')
self.assertEqual(vercode, 2)
def test_push_commits(self):
testdir = self.testdir.name
os.chdir(testdir)
os.mkdir('metadata')
for f in (self.basedir / 'metadata').glob('*.yml'):
shutil.copy(f, 'metadata')
git_repo = git.Repo.init(testdir)
git_repo.git.add(all=True)
git_repo.index.commit("all metadata files")
git_remote_upstream = os.path.join(testdir, 'git_remote_upstream')
upstream = git.Repo.init(git_remote_upstream, bare=True)
git_repo.create_remote('upstream', 'file://' + git_remote_upstream)
git_remote_origin = os.path.join(testdir, 'git_remote_origin')
origin = git.Repo.init(git_remote_origin, bare=True)
git_repo.create_remote('origin', 'file://' + git_remote_origin)
for remote in git_repo.remotes:
remote.push(git_repo.active_branch)
self.assertEqual(git_repo.head, upstream.head)
self.assertEqual(origin.head, upstream.head)
# pretend that checkupdates ran but didn't create any new commits
fdroidserver.checkupdates.push_commits()
appid = 'org.adaway'
self.assertNotIn(appid, git_repo.branches)
self.assertNotIn('checkupdates', git_repo.branches)
self.assertNotIn(appid, git_repo.remotes.origin.repo.branches) # TODO fix
# now make commit
app = fdroidserver.metadata.read_metadata({appid: -1})[appid]
build = fdroidserver.metadata.Build()
build.versionName = 'fake'
build.versionCode = 999999999
app.Builds.append(build)
metadata_file = 'metadata/%s.yml' % appid
fdroidserver.metadata.write_metadata(metadata_file, app)
git_repo.index.add(metadata_file)
git_repo.index.commit('changed ' + appid)
# and push the new commit to the dynamic branch
fdroidserver.checkupdates.push_commits()
self.assertIn(appid, git_repo.branches)
self.assertIn(appid, git_repo.remotes.origin.refs)
self.assertNotIn('checkupdates', git_repo.branches)
self.assertNotIn(appid, git_repo.remotes.upstream.refs)
def test_make_merge_request(self):
testdir = self.testdir.name
os.chdir(testdir)
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)