#!/usr/bin/env python3 import os import textwrap import unittest from pathlib import Path from unittest.mock import Mock, patch import fdroidserver from fdroidserver import common, install from fdroidserver.exception import BuildException, FDroidException @unittest.skipIf(os.uname().machine == 's390x', 'adb is not ported to s390x') class InstallTest(unittest.TestCase): '''fdroidserver/install.py''' def tearDown(self): common.config = None def test_devices(self): config = dict() fdroidserver.common.fill_config_defaults(config) fdroidserver.common.config = config try: config['adb'] = fdroidserver.common.find_sdk_tools_cmd('adb') except FDroidException as e: self.skipTest(f'Skipping test because: {e}') self.assertTrue(os.path.exists(config['adb'])) self.assertTrue(os.path.isfile(config['adb'])) devices = fdroidserver.install.devices() self.assertIsInstance(devices, list, 'install.devices() did not return a list!') for device in devices: self.assertIsInstance(device, str) def test_devices_fail(self): common.config = dict() common.fill_config_defaults(common.config) common.config['adb'] = '/bin/false' with self.assertRaises(FDroidException): fdroidserver.install.devices() def test_devices_fail_nonexistent(self): """This is mostly just to document this strange difference in behavior""" common.config = dict() common.fill_config_defaults(common.config) common.config['adb'] = '/nonexistent' with self.assertRaises(BuildException): fdroidserver.install.devices() @patch('fdroidserver.common.SdkToolsPopen') def test_devices_with_mock_none(self, mock_SdkToolsPopen): p = Mock() mock_SdkToolsPopen.return_value = p p.output = 'List of devices attached\n\n' p.returncode = 0 common.config = dict() common.fill_config_defaults(common.config) self.assertEqual([], fdroidserver.install.devices()) @patch('fdroidserver.common.SdkToolsPopen') def test_devices_with_mock_one(self, mock_SdkToolsPopen): p = Mock() mock_SdkToolsPopen.return_value = p p.output = 'List of devices attached\n05995813\tdevice\n\n' p.returncode = 0 common.config = dict() common.fill_config_defaults(common.config) self.assertEqual(['05995813'], fdroidserver.install.devices()) @patch('fdroidserver.common.SdkToolsPopen') def test_devices_with_mock_many(self, mock_SdkToolsPopen): p = Mock() mock_SdkToolsPopen.return_value = p p.output = textwrap.dedent( """* daemon not running; starting now at tcp:5037 * daemon started successfully List of devices attached RZCT809FTQM device 05995813 device emulator-5556 device emulator-5554 unauthorized 0a388e93 no permissions (missing udev rules? user is in the plugdev group); see [http://developer.android.com/tools/device.html] 986AY133QL device 09301JEC215064 device 015d165c3010200e device 4DCESKVGUC85VOTO device """ ) p.returncode = 0 common.config = dict() common.fill_config_defaults(common.config) self.assertEqual( [ 'RZCT809FTQM', '05995813', 'emulator-5556', '986AY133QL', '09301JEC215064', '015d165c3010200e', '4DCESKVGUC85VOTO', ], fdroidserver.install.devices(), ) @patch('fdroidserver.common.SdkToolsPopen') def test_devices_with_mock_error(self, mock_SdkToolsPopen): p = Mock() mock_SdkToolsPopen.return_value = p p.output = textwrap.dedent( """* daemon not running. starting it now on port 5037 * * daemon started successfully * ** daemon still not running error: cannot connect to daemon """ ) p.returncode = 0 common.config = dict() common.fill_config_defaults(common.config) self.assertEqual([], fdroidserver.install.devices()) @patch('fdroidserver.common.SdkToolsPopen') def test_devices_with_mock_no_permissions(self, mock_SdkToolsPopen): p = Mock() mock_SdkToolsPopen.return_value = p p.output = textwrap.dedent( """List of devices attached ???????????????? no permissions """ ) p.returncode = 0 common.config = dict() common.fill_config_defaults(common.config) self.assertEqual([], fdroidserver.install.devices()) @patch('fdroidserver.common.SdkToolsPopen') def test_devices_with_mock_unauthorized(self, mock_SdkToolsPopen): p = Mock() mock_SdkToolsPopen.return_value = p p.output = textwrap.dedent( """List of devices attached aeef5e4e unauthorized """ ) p.returncode = 0 common.config = dict() common.fill_config_defaults(common.config) self.assertEqual([], fdroidserver.install.devices()) @patch('fdroidserver.common.SdkToolsPopen') def test_devices_with_mock_no_permissions_with_serial(self, mock_SdkToolsPopen): p = Mock() mock_SdkToolsPopen.return_value = p p.output = textwrap.dedent( """List of devices attached 4DCESKVGUC85VOTO no permissions (missing udev rules? user is in the plugdev group); see [http://developer.android.com/tools/device.html] """ ) p.returncode = 0 common.config = dict() common.fill_config_defaults(common.config) self.assertEqual([], fdroidserver.install.devices()) @staticmethod def _download_raise(privacy_mode): raise Exception('fake failed download') @patch('fdroidserver.install.download_apk') @patch('fdroidserver.install.download_fdroid_apk') @patch('fdroidserver.install.download_fdroid_apk_from_github') @patch('fdroidserver.install.download_fdroid_apk_from_ipns') @patch('fdroidserver.install.download_fdroid_apk_from_maven') def test_install_fdroid_apk_privacy_mode_true( self, maven, ipns, github, download_fdroid_apk, download_apk ): download_apk.side_effect = self._download_raise download_fdroid_apk.side_effect = self._download_raise github.side_effect = self._download_raise ipns.side_effect = self._download_raise maven.side_effect = self._download_raise fdroidserver.common.config = {'jarsigner': 'fakepath'} install.install_fdroid_apk(privacy_mode=True) download_apk.assert_not_called() download_fdroid_apk.assert_not_called() github.assert_called_once() ipns.assert_called_once() maven.assert_called_once() @patch('fdroidserver.install.download_apk') @patch('fdroidserver.install.download_fdroid_apk') @patch('fdroidserver.install.download_fdroid_apk_from_github') @patch('fdroidserver.install.download_fdroid_apk_from_ipns') @patch('fdroidserver.install.download_fdroid_apk_from_maven') def test_install_fdroid_apk_privacy_mode_false( self, maven, ipns, github, download_fdroid_apk, download_apk ): download_apk.side_effect = self._download_raise download_fdroid_apk.side_effect = self._download_raise github.side_effect = self._download_raise ipns.side_effect = self._download_raise maven.side_effect = self._download_raise fdroidserver.common.config = {'jarsigner': 'fakepath'} install.install_fdroid_apk(privacy_mode=False) download_apk.assert_called_once() download_fdroid_apk.assert_called_once() github.assert_called_once() ipns.assert_called_once() maven.assert_called_once() @patch('fdroidserver.install.download_apk') @patch('fdroidserver.install.download_fdroid_apk') @patch('fdroidserver.install.download_fdroid_apk_from_github') @patch('fdroidserver.install.download_fdroid_apk_from_ipns') @patch('fdroidserver.install.download_fdroid_apk_from_maven') @patch('locale.getlocale', lambda: ('zh_CN', 'UTF-8')) def test_install_fdroid_apk_privacy_mode_locale_auto( self, maven, ipns, github, download_fdroid_apk, download_apk ): download_apk.side_effect = self._download_raise download_fdroid_apk.side_effect = self._download_raise github.side_effect = self._download_raise ipns.side_effect = self._download_raise maven.side_effect = self._download_raise fdroidserver.common.config = {'jarsigner': 'fakepath'} install.install_fdroid_apk(privacy_mode=None) download_apk.assert_not_called() download_fdroid_apk.assert_not_called() github.assert_called_once() ipns.assert_called_once() maven.assert_called_once() @patch('fdroidserver.net.download_using_mirrors', lambda m: 'testvalue') def test_download_fdroid_apk_smokecheck(self): self.assertEqual('testvalue', install.download_fdroid_apk()) @unittest.skipUnless(os.getenv('test_download_fdroid_apk'), 'requires net access') def test_download_fdroid_apk(self): f = install.download_fdroid_apk() self.assertTrue(Path(f).exists()) @unittest.skipUnless(os.getenv('test_download_fdroid_apk'), 'requires net access') def test_download_fdroid_apk_from_maven(self): f = install.download_fdroid_apk_from_maven() self.assertTrue(Path(f).exists()) @unittest.skipUnless(os.getenv('test_download_fdroid_apk'), 'requires net access') def test_download_fdroid_apk_from_ipns(self): f = install.download_fdroid_apk_from_ipns() self.assertTrue(Path(f).exists()) @unittest.skipUnless(os.getenv('test_download_fdroid_apk'), 'requires net access') def test_download_fdroid_apk_from_github(self): f = install.download_fdroid_apk_from_github() self.assertTrue(Path(f).exists())