Skip to content

Commit eb91462

Browse files
authored
Allow to override emulator config from config file defined by path in EVN (#492)
1 parent ac251e7 commit eb91462

4 files changed

Lines changed: 66 additions & 2 deletions

File tree

cli/src/constants/ENV.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
EMULATOR_NAME = "EMULATOR_NAME"
3131
EMULATOR_NO_SKIN = "EMULATOR_NO_SKIN"
3232
EMULATOR_SYS_IMG = "EMULATOR_SYS_IMG"
33+
EMULATOR_CONFIG_PATH = "EMULATOR_CONFIG_PATH"
3334

3435
# Device (Genymotion - General)
3536
GENYMOTION_TEMPLATE_PATH = "GENYMOTION_TEMPLATE_PATH"

cli/src/device/emulator.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,30 @@ def _add_profile(self) -> None:
108108
symlink_force(path_device_profile_source, self.path_device_profile_target)
109109
self.logger.info("Samsung device profile is linked")
110110

111+
def _use_override_config(self) -> None:
112+
override_confg_path = os.getenv(ENV.EMULATOR_CONFIG_PATH)
113+
114+
if override_confg_path is None:
115+
self.logger.info(f"The environment variable 'EMULATOR_CONFIG_PATH' is not set")
116+
return
117+
118+
self.logger.info(f"Environment variable 'EMULATOR_CONFIG_PATH' found: {override_confg_path}")
119+
120+
if not os.path.isfile(override_confg_path):
121+
self.logger.warning(f"Source file '{override_confg_path}' does not exist.")
122+
return
123+
124+
if not os.access(override_confg_path, os.R_OK):
125+
self.logger.warning(f"Source file '{override_confg_path}' is not readable.")
126+
return
127+
128+
try:
129+
with open(override_confg_path, 'r') as src, open(self.path_emulator_config, 'a') as dst:
130+
dst.write(src.read())
131+
self.logger.info(f"Content from '{override_confg_path}' successfully appended to '{self.path_emulator_config}'.")
132+
except Exception as e:
133+
self.logger.error(f"An error occurred while copying file content: {e}")
134+
111135
def _add_skin(self) -> None:
112136
device_skin_path = os.path.join(
113137
self.path_emulator_skins, "{fn}".format(fn=self.file_name))
@@ -132,6 +156,7 @@ def create(self) -> None:
132156
self.logger.info(f"Command to create emulator: '{creation_cmd}'")
133157
subprocess.check_call(creation_cmd, shell=True)
134158
self._add_skin()
159+
self._use_override_config()
135160
self.logger.info(f"{self.device_type} is created!")
136161

137162
def change_permission(self) -> None:

cli/src/tests/device/test_emulator.py

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,20 +56,23 @@ def test_initialisation_device_exists(self):
5656
@mock.patch("src.device.emulator.Emulator._add_profile")
5757
@mock.patch("subprocess.check_call")
5858
@mock.patch("src.device.emulator.Emulator._add_skin")
59+
@mock.patch("src.device.emulator.Emulator._use_override_config")
5960
@mock.patch("src.device.emulator.Emulator.is_initialized", mock.MagicMock(return_value=False))
60-
def test_create_device_not_exist(self, mocked_status, mocked_profile, mocked_subprocess, mocked_skin):
61+
def test_create_device_not_exist(self, mocked_status, mocked_profile, mocked_subprocess, mocked_skin, mocked_override_config):
6162
self.emu.create()
6263
self.assertEqual(mocked_status.called, True)
6364
self.assertEqual(mocked_profile.called, True)
6465
self.assertEqual(mocked_subprocess.called, True)
6566
self.assertEqual(mocked_skin.called, True)
67+
self.assertEqual(mocked_override_config.called, True)
6668

6769
@mock.patch("src.device.Device.set_status")
6870
@mock.patch("src.device.emulator.Emulator._add_profile")
6971
@mock.patch("subprocess.check_call")
7072
@mock.patch("src.device.emulator.Emulator._add_skin")
73+
@mock.patch("src.device.emulator.Emulator._use_override_config")
7174
@mock.patch("src.device.emulator.Emulator.is_initialized", mock.MagicMock(return_value=True))
72-
def test_create_device_exists(self, mocked_status, mocked_profile, mocked_subprocess, mocked_skin):
75+
def test_create_device_exists(self, mocked_status, mocked_profile, mocked_subprocess, mocked_skin, mocked_override_config):
7376
self.emu.create()
7477
self.assertEqual(mocked_status.called, False)
7578
self.assertEqual(mocked_profile.called, False)
@@ -85,3 +88,25 @@ def test_check_adb_command_out_of_attempts(self):
8588
with self.assertRaises(RuntimeError):
8689
self.emu.check_adb_command(
8790
self.emu.ReadinessCheck.BOOTED, "mocked_command", "1", 3, 0)
91+
92+
def test_use_override_config_no_env(self):
93+
with mock.patch("os.getenv", return_value=None):
94+
self.emu._use_override_config()
95+
96+
def test_use_override_config_file_not_exist(self):
97+
with mock.patch("os.getenv", return_value="mock/path/to/config"):
98+
with mock.patch("os.path.isfile", return_value=False):
99+
self.emu._use_override_config()
100+
101+
def test_use_override_config_file_not_readable(self):
102+
with mock.patch("os.getenv", return_value="mock/path/to/config"):
103+
with mock.patch("os.path.isfile", return_value=True):
104+
with mock.patch("os.access", return_value=False):
105+
self.emu._use_override_config()
106+
107+
def test_use_override_config_malformed_content(self):
108+
with mock.patch("os.getenv", return_value="mock/path/to/config"):
109+
with mock.patch("os.path.isfile", return_value=True):
110+
with mock.patch("os.access", return_value=True):
111+
with mock.patch("builtins.open", mock.mock_open(read_data="malformed data")):
112+
self.emu._use_override_config()

documentations/CUSTOM_CONFIGURATIONS.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,5 +57,18 @@ Possible environment variable to configure the Emulator:
5757
5858
The user can also pass needed arguments to android emulator through environment variable ***EMULATOR_ADDITIONAL_ARGS***. Please check [this page](https://developer.android.com/studio/run/emulator-commandline) for possible arguments that can be passed.
5959
60+
EMULATOR - OVERRIDE CONFIG FILE
61+
-------------------------------
62+
63+
To utilize this feature, ensure the following setup:
64+
65+
- Set the config file path into environment variable EMULATOR_CONFIG_PATH, eg. `/tmp/emulator-override-config.ini` (the file name doesn't matter)
66+
- Mount the file as Docker volume (parameter `-v` for Docker run command) to the path as you set into ENV
67+
68+
Example:
69+
70+
```shell
71+
docker run -d -p 6080:6080 -e /tmp/emulator-override-config.ini -v /path/on/your/machine/emulator-override-config.ini:/tmp/emulator-override-config.ini -e EMULATOR_DEVICE="Samsung Galaxy S10" -e WEB_VNC=true --device /dev/kvm --name android-container budtmo/docker-android:emulator_14.0
72+
```
6073

6174
[<- BACK TO README](../README.md)

0 commit comments

Comments
 (0)