Skip to content

Add unittest for module pythonforandroid.distribution #1847

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 9, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
216 changes: 216 additions & 0 deletions tests/test_distribution.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
import os
import json
import unittest

try:
from unittest import mock
except ImportError:
# `Python 2` or lower than `Python 3.3` does not
# have the `unittest.mock` module built-in
import mock
from pythonforandroid.bootstrap import Bootstrap
from pythonforandroid.distribution import Distribution
from pythonforandroid.recipe import Recipe
from pythonforandroid.util import BuildInterruptingException
from pythonforandroid.build import Context

dist_info_data = {
"dist_name": None,
"bootstrap": "sdl2",
"archs": ["armeabi", "armeabi-v7a", "x86", "x86_64", "arm64-v8a"],
"ndk_api": 21,
"use_setup_py": False,
"recipes": ["hostpython3", "python3", "sdl2", "kivy", "requests"],
"hostpython": "/some/fake/hostpython3",
"python_version": "3.7",
}


class TestDistribution(unittest.TestCase):
def setUp(self):
self.ctx = Context()
self.ctx.ndk_api = 21
self.ctx.android_api = 27
self.ctx._sdk_dir = "/opt/android/android-sdk"
self.ctx._ndk_dir = "/opt/android/android-ndk"
self.ctx.setup_dirs(os.getcwd())
self.ctx.recipe_build_order = [
"hostpython3",
"python3",
"sdl2",
"kivy",
]

def setUp_distribution_with_bootstrap(self, bs, **kwargs):
# extend the setUp by configuring a distribution, because some test
# needs a distribution to be set to be properly tested
self.ctx.bootstrap = bs
self.ctx.bootstrap.distribution = Distribution.get_distribution(
self.ctx,
name=kwargs.pop("name", "test_prj"),
recipes=kwargs.pop("recipes", ["python3", "kivy"]),
**kwargs
)

def tearDown(self):
self.ctx.bootstrap = None

def test_properties(self):
self.setUp_distribution_with_bootstrap(
Bootstrap().get_bootstrap("sdl2", self.ctx)
)
distribution = self.ctx.bootstrap.distribution
self.assertEqual(self.ctx, distribution.ctx)
expected_repr = (
"<Distribution: name test_prj with recipes (python3, kivy)>"
)
self.assertEqual(distribution.__str__(), expected_repr)
self.assertEqual(distribution.__repr__(), expected_repr)

@mock.patch("pythonforandroid.distribution.exists")
def test_folder_exist(self, mock_exists):

self.setUp_distribution_with_bootstrap(
Bootstrap().get_bootstrap("sdl2", self.ctx)
)
self.ctx.bootstrap.distribution.folder_exists()
mock_exists.assert_called_with(
self.ctx.bootstrap.distribution.dist_dir
)

@mock.patch("pythonforandroid.distribution.rmtree")
def test_delete(self, mock_rmtree):

self.setUp_distribution_with_bootstrap(
Bootstrap().get_bootstrap("sdl2", self.ctx)
)
self.ctx.bootstrap.distribution.delete()
mock_rmtree.assert_called_with(
self.ctx.bootstrap.distribution.dist_dir
)

@mock.patch("pythonforandroid.distribution.exists")
def test_get_distribution_no_name(self, mock_exists):

mock_exists.return_value = False
self.ctx.bootstrap = Bootstrap().get_bootstrap("sdl2", self.ctx)
dist = Distribution.get_distribution(self.ctx)
self.assertEqual(dist.name, "unnamed_dist_1")

@mock.patch("pythonforandroid.util.chdir")
@mock.patch("pythonforandroid.distribution.open", create=True)
def test_save_info(self, mock_open_dist_info, mock_chdir):
self.setUp_distribution_with_bootstrap(
Bootstrap().get_bootstrap("sdl2", self.ctx)
)
self.ctx.hostpython = "/some/fake/hostpython3"
self.ctx.python_recipe = Recipe.get_recipe("python3", self.ctx)
self.ctx.python_modules = ["requests"]
mock_open_dist_info.side_effect = [
mock.mock_open(read_data=json.dumps(dist_info_data)).return_value
]
self.ctx.bootstrap.distribution.save_info("/fake_dir")
mock_open_dist_info.assert_called_once_with("dist_info.json", "w")
mock_open_dist_info.reset_mock()

@mock.patch("pythonforandroid.distribution.open", create=True)
@mock.patch("pythonforandroid.distribution.exists")
@mock.patch("pythonforandroid.distribution.glob.glob")
def test_get_distributions(
self, mock_glob, mock_exists, mock_open_dist_info
):
self.setUp_distribution_with_bootstrap(
Bootstrap().get_bootstrap("sdl2", self.ctx)
)
mock_glob.return_value = ["sdl2-python3"]
mock_open_dist_info.side_effect = [
mock.mock_open(read_data=json.dumps(dist_info_data)).return_value
]

dists = self.ctx.bootstrap.distribution.get_distributions(self.ctx)
self.assertIsInstance(dists, list)
self.assertEqual(len(dists), 1)
self.assertIsInstance(dists[0], Distribution)
self.assertEqual(dists[0].name, "sdl2-python3")
self.assertEqual(dists[0].ndk_api, 21)
self.assertEqual(
dists[0].recipes,
["hostpython3", "python3", "sdl2", "kivy", "requests"],
)
mock_open_dist_info.assert_called_with("sdl2-python3/dist_info.json")
mock_open_dist_info.reset_mock()

@mock.patch("pythonforandroid.distribution.open", create=True)
@mock.patch("pythonforandroid.distribution.exists")
@mock.patch("pythonforandroid.distribution.glob.glob")
def test_get_distributions_error_ndk_api(
self, mock_glob, mock_exists, mock_open_dist_info
):
dist_info_data_no_ndk_api = dist_info_data.copy()
dist_info_data_no_ndk_api.pop("ndk_api")
self.setUp_distribution_with_bootstrap(
Bootstrap().get_bootstrap("sdl2", self.ctx)
)
mock_glob.return_value = ["sdl2-python3"]
mock_open_dist_info.side_effect = [
mock.mock_open(
read_data=json.dumps(dist_info_data_no_ndk_api)
).return_value
]

dists = self.ctx.bootstrap.distribution.get_distributions(self.ctx)
self.assertEqual(dists[0].ndk_api, None)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a random idea, we could also have mocked warning and asserted its call

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right we could do that, but I more concerned to mock the stuff that could slow down our tests (mostly file operations: copy, paste, pack, unpack, read files...)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes I just throw that idea, because I may have mocked it, just to show we're throwing a warning in this specific case. But you're covering the case anyway asserting ndk_api is None. By the way if you like self.assert you also have self.assertIsNone().

mock_open_dist_info.assert_called_with("sdl2-python3/dist_info.json")
mock_open_dist_info.reset_mock()

@mock.patch("pythonforandroid.distribution.Distribution.get_distributions")
@mock.patch("pythonforandroid.distribution.exists")
@mock.patch("pythonforandroid.distribution.glob.glob")
def test_get_distributions_error_ndk_api_mismatch(
self, mock_glob, mock_exists, mock_get_dists
):
expected_dist = Distribution.get_distribution(
self.ctx, name="test_prj", recipes=["python3", "kivy"]
)
mock_get_dists.return_value = [expected_dist]
mock_glob.return_value = ["sdl2-python3"]

with self.assertRaises(BuildInterruptingException) as e:
self.setUp_distribution_with_bootstrap(
Bootstrap().get_bootstrap("sdl2", self.ctx),
allow_replace_dist=False,
ndk_api=22,
)
self.assertEqual(
e.exception.args[0],
"Asked for dist with name test_prj with recipes (python3, kivy)"
" and NDK API 22, but a dist with this name already exists and has"
" either incompatible recipes (python3, kivy) or NDK API 21",
)

def test_get_distributions_error_extra_dist_dirs(self):
self.setUp_distribution_with_bootstrap(
Bootstrap().get_bootstrap("sdl2", self.ctx)
)

with self.assertRaises(BuildInterruptingException) as e:
self.ctx.bootstrap.distribution.get_distributions(
self.ctx, extra_dist_dirs=["/fake/extra/dist_dirs"]
)
self.assertEqual(
e.exception.args[0],
"extra_dist_dirs argument to get"
"_distributions is not yet implemented",
)

@mock.patch("pythonforandroid.distribution.Distribution.get_distributions")
def test_get_distributions_possible_dists(self, mock_get_dists):
expected_dist = Distribution.get_distribution(
self.ctx, name="test_prj", recipes=["python3", "kivy"]
)
mock_get_dists.return_value = [expected_dist]
self.setUp_distribution_with_bootstrap(
Bootstrap().get_bootstrap("sdl2", self.ctx), name="test_prj"
)
dists = self.ctx.bootstrap.distribution.get_distributions(self.ctx)
self.assertEqual(dists[0], expected_dist)