249 lines
9.2 KiB
Python
249 lines
9.2 KiB
Python
import unittest
|
|
from os.path import join
|
|
from sys import version as py_version
|
|
|
|
from unittest import mock
|
|
from pythonforandroid.recommendations import (
|
|
check_ndk_api,
|
|
check_ndk_version,
|
|
check_target_api,
|
|
read_ndk_version,
|
|
check_python_version,
|
|
print_recommendations,
|
|
MAX_NDK_VERSION,
|
|
RECOMMENDED_NDK_VERSION,
|
|
RECOMMENDED_TARGET_API,
|
|
MIN_NDK_API,
|
|
MIN_NDK_VERSION,
|
|
NDK_DOWNLOAD_URL,
|
|
ARMEABI_MAX_TARGET_API,
|
|
MIN_TARGET_API,
|
|
UNKNOWN_NDK_MESSAGE,
|
|
PARSE_ERROR_NDK_MESSAGE,
|
|
READ_ERROR_NDK_MESSAGE,
|
|
ENSURE_RIGHT_NDK_MESSAGE,
|
|
NDK_LOWER_THAN_SUPPORTED_MESSAGE,
|
|
UNSUPPORTED_NDK_API_FOR_ARMEABI_MESSAGE,
|
|
CURRENT_NDK_VERSION_MESSAGE,
|
|
RECOMMENDED_NDK_VERSION_MESSAGE,
|
|
TARGET_NDK_API_GREATER_THAN_TARGET_API_MESSAGE,
|
|
OLD_NDK_API_MESSAGE,
|
|
NEW_NDK_MESSAGE,
|
|
OLD_API_MESSAGE,
|
|
MIN_PYTHON_MAJOR_VERSION,
|
|
MIN_PYTHON_MINOR_VERSION,
|
|
PY2_ERROR_TEXT,
|
|
PY_VERSION_ERROR_TEXT,
|
|
)
|
|
|
|
from pythonforandroid.util import BuildInterruptingException
|
|
|
|
running_in_py2 = int(py_version[0]) < 3
|
|
|
|
|
|
class TestRecommendations(unittest.TestCase):
|
|
"""
|
|
An inherited class of `unittest.TestCase`to test the module
|
|
:mod:`~pythonforandroid.recommendations`.
|
|
"""
|
|
|
|
def setUp(self):
|
|
self.ndk_dir = "/opt/android/android-ndk"
|
|
|
|
@unittest.skipIf(running_in_py2, "`assertLogs` requires Python 3.4+")
|
|
@mock.patch("pythonforandroid.recommendations.read_ndk_version")
|
|
def test_check_ndk_version_greater_than_recommended(self, mock_read_ndk):
|
|
mock_read_ndk.return_value.version = [MAX_NDK_VERSION + 1, 0, 5232133]
|
|
with self.assertLogs(level="INFO") as cm:
|
|
check_ndk_version(self.ndk_dir)
|
|
mock_read_ndk.assert_called_once_with(self.ndk_dir)
|
|
self.assertEqual(
|
|
cm.output,
|
|
[
|
|
"INFO:p4a:[INFO]: {}".format(
|
|
CURRENT_NDK_VERSION_MESSAGE.format(
|
|
ndk_version=MAX_NDK_VERSION + 1
|
|
)
|
|
),
|
|
"WARNING:p4a:[WARNING]: {}".format(
|
|
RECOMMENDED_NDK_VERSION_MESSAGE.format(
|
|
recommended_ndk_version=RECOMMENDED_NDK_VERSION
|
|
)
|
|
),
|
|
"WARNING:p4a:[WARNING]: {}".format(NEW_NDK_MESSAGE),
|
|
],
|
|
)
|
|
|
|
@mock.patch("pythonforandroid.recommendations.read_ndk_version")
|
|
def test_check_ndk_version_lower_than_recommended(self, mock_read_ndk):
|
|
mock_read_ndk.return_value.version = [MIN_NDK_VERSION - 1, 0, 5232133]
|
|
with self.assertRaises(BuildInterruptingException) as e:
|
|
check_ndk_version(self.ndk_dir)
|
|
self.assertEqual(
|
|
e.exception.args[0],
|
|
NDK_LOWER_THAN_SUPPORTED_MESSAGE.format(
|
|
min_supported=MIN_NDK_VERSION, ndk_url=NDK_DOWNLOAD_URL
|
|
),
|
|
)
|
|
mock_read_ndk.assert_called_once_with(self.ndk_dir)
|
|
|
|
@unittest.skipIf(running_in_py2, "`assertLogs` requires Python 3.4+")
|
|
def test_check_ndk_version_error(self):
|
|
"""
|
|
Test that a fake ndk dir give us two messages:
|
|
- first should be an `INFO` log
|
|
- second should be an `WARNING` log
|
|
"""
|
|
with self.assertLogs(level="INFO") as cm:
|
|
check_ndk_version(self.ndk_dir)
|
|
self.assertEqual(
|
|
cm.output,
|
|
[
|
|
"INFO:p4a:[INFO]: {}".format(UNKNOWN_NDK_MESSAGE),
|
|
"WARNING:p4a:[WARNING]: {}".format(
|
|
READ_ERROR_NDK_MESSAGE.format(ndk_dir=self.ndk_dir)
|
|
),
|
|
"WARNING:p4a:[WARNING]: {}".format(
|
|
ENSURE_RIGHT_NDK_MESSAGE.format(
|
|
min_supported=MIN_NDK_VERSION,
|
|
rec_version=RECOMMENDED_NDK_VERSION,
|
|
ndk_url=NDK_DOWNLOAD_URL,
|
|
)
|
|
),
|
|
],
|
|
)
|
|
|
|
@mock.patch("pythonforandroid.recommendations.open")
|
|
def test_read_ndk_version(self, mock_open_src_prop):
|
|
mock_open_src_prop.side_effect = [
|
|
mock.mock_open(
|
|
read_data="Pkg.Revision = 17.2.4988734"
|
|
).return_value
|
|
]
|
|
version = read_ndk_version(self.ndk_dir)
|
|
mock_open_src_prop.assert_called_once_with(
|
|
join(self.ndk_dir, "source.properties")
|
|
)
|
|
assert version == "17.2.4988734"
|
|
|
|
@unittest.skipIf(running_in_py2, "`assertLogs` requires Python 3.4+")
|
|
@mock.patch("pythonforandroid.recommendations.open")
|
|
def test_read_ndk_version_error(self, mock_open_src_prop):
|
|
mock_open_src_prop.side_effect = [
|
|
mock.mock_open(read_data="").return_value
|
|
]
|
|
with self.assertLogs(level="INFO") as cm:
|
|
version = read_ndk_version(self.ndk_dir)
|
|
self.assertEqual(
|
|
cm.output,
|
|
["INFO:p4a:[INFO]: {}".format(PARSE_ERROR_NDK_MESSAGE)],
|
|
)
|
|
mock_open_src_prop.assert_called_once_with(
|
|
join(self.ndk_dir, "source.properties")
|
|
)
|
|
assert version is None
|
|
|
|
def test_check_target_api_error_arch_armeabi(self):
|
|
|
|
with self.assertRaises(BuildInterruptingException) as e:
|
|
check_target_api(RECOMMENDED_TARGET_API, "armeabi")
|
|
self.assertEqual(
|
|
e.exception.args[0],
|
|
UNSUPPORTED_NDK_API_FOR_ARMEABI_MESSAGE.format(
|
|
req_ndk_api=RECOMMENDED_TARGET_API,
|
|
max_ndk_api=ARMEABI_MAX_TARGET_API,
|
|
),
|
|
)
|
|
|
|
@unittest.skipIf(running_in_py2, "`assertLogs` requires Python 3.4+")
|
|
def test_check_target_api_warning_target_api(self):
|
|
|
|
with self.assertLogs(level="INFO") as cm:
|
|
check_target_api(MIN_TARGET_API - 1, MIN_TARGET_API)
|
|
self.assertEqual(
|
|
cm.output,
|
|
[
|
|
"WARNING:p4a:[WARNING]: Target API 29 < 30",
|
|
"WARNING:p4a:[WARNING]: {old_api_msg}".format(
|
|
old_api_msg=OLD_API_MESSAGE
|
|
),
|
|
],
|
|
)
|
|
|
|
def test_check_ndk_api_error_android_api(self):
|
|
"""
|
|
Given an `android api` greater than an `ndk_api`, we should get an
|
|
`BuildInterruptingException`.
|
|
"""
|
|
ndk_api = MIN_NDK_API + 1
|
|
android_api = MIN_NDK_API
|
|
with self.assertRaises(BuildInterruptingException) as e:
|
|
check_ndk_api(ndk_api, android_api)
|
|
self.assertEqual(
|
|
e.exception.args[0],
|
|
TARGET_NDK_API_GREATER_THAN_TARGET_API_MESSAGE.format(
|
|
ndk_api=ndk_api, android_api=android_api
|
|
),
|
|
)
|
|
|
|
@unittest.skipIf(running_in_py2, "`assertLogs` requires Python 3.4+")
|
|
def test_check_ndk_api_warning_old_ndk(self):
|
|
"""
|
|
Given an `android api` lower than the supported by p4a, we should
|
|
get an `BuildInterruptingException`.
|
|
"""
|
|
ndk_api = MIN_NDK_API - 1
|
|
android_api = RECOMMENDED_TARGET_API
|
|
with self.assertLogs(level="INFO") as cm:
|
|
check_ndk_api(ndk_api, android_api)
|
|
self.assertEqual(
|
|
cm.output,
|
|
[
|
|
"WARNING:p4a:[WARNING]: {}".format(
|
|
OLD_NDK_API_MESSAGE.format(MIN_NDK_API)
|
|
)
|
|
],
|
|
)
|
|
|
|
def test_check_python_version(self):
|
|
"""With any version info lower than the minimum, we should get a
|
|
BuildInterruptingException with an appropriate message.
|
|
"""
|
|
with mock.patch('sys.version_info') as fake_version_info:
|
|
|
|
# Major version is Python 2 => exception
|
|
fake_version_info.major = MIN_PYTHON_MAJOR_VERSION - 1
|
|
fake_version_info.minor = MIN_PYTHON_MINOR_VERSION
|
|
with self.assertRaises(BuildInterruptingException) as context:
|
|
check_python_version()
|
|
assert context.exception.message == PY2_ERROR_TEXT
|
|
|
|
# Major version too low => exception
|
|
# Using a float valued major version just to test the logic and avoid
|
|
# clashing with the Python 2 check
|
|
fake_version_info.major = MIN_PYTHON_MAJOR_VERSION - 0.1
|
|
fake_version_info.minor = MIN_PYTHON_MINOR_VERSION
|
|
with self.assertRaises(BuildInterruptingException) as context:
|
|
check_python_version()
|
|
assert context.exception.message == PY_VERSION_ERROR_TEXT
|
|
|
|
# Minor version too low => exception
|
|
fake_version_info.major = MIN_PYTHON_MAJOR_VERSION
|
|
fake_version_info.minor = MIN_PYTHON_MINOR_VERSION - 1
|
|
with self.assertRaises(BuildInterruptingException) as context:
|
|
check_python_version()
|
|
assert context.exception.message == PY_VERSION_ERROR_TEXT
|
|
|
|
# Version high enough => nothing interesting happens
|
|
fake_version_info.major = MIN_PYTHON_MAJOR_VERSION
|
|
fake_version_info.minor = MIN_PYTHON_MINOR_VERSION
|
|
check_python_version()
|
|
|
|
def test_print_recommendations(self):
|
|
"""
|
|
Simple test that the function actually runs.
|
|
"""
|
|
# The main failure mode is if the function tries to print a variable
|
|
# that doesn't actually exist, so simply running to check all the
|
|
# prints work is the most important test.
|
|
print_recommendations()
|