diff --git a/cli/src/constants/ENV.py b/cli/src/constants/ENV.py index 8a8254c..34ed87a 100644 --- a/cli/src/constants/ENV.py +++ b/cli/src/constants/ENV.py @@ -30,6 +30,7 @@ EMULATOR_IMG_TYPE = "EMULATOR_IMG_TYPE" EMULATOR_NAME = "EMULATOR_NAME" EMULATOR_NO_SKIN = "EMULATOR_NO_SKIN" EMULATOR_SYS_IMG = "EMULATOR_SYS_IMG" +EMULATOR_CONFIG_PATH = "EMULATOR_CONFIG_PATH" # Device (Genymotion - General) GENYMOTION_TEMPLATE_PATH = "GENYMOTION_TEMPLATE_PATH" diff --git a/cli/src/device/emulator.py b/cli/src/device/emulator.py index 83647b8..ae8ed63 100644 --- a/cli/src/device/emulator.py +++ b/cli/src/device/emulator.py @@ -108,6 +108,30 @@ class Emulator(Device): symlink_force(path_device_profile_source, self.path_device_profile_target) self.logger.info("Samsung device profile is linked") + def _use_override_config(self) -> None: + override_confg_path = os.getenv(ENV.EMULATOR_CONFIG_PATH) + + if override_confg_path is None: + self.logger.info(f"The environment variable 'EMULATOR_CONFIG_PATH' is not set") + return + + self.logger.info(f"Environment variable 'EMULATOR_CONFIG_PATH' found: {override_confg_path}") + + if not os.path.isfile(override_confg_path): + self.logger.warning(f"Source file '{override_confg_path}' does not exist.") + return + + if not os.access(override_confg_path, os.R_OK): + self.logger.warning(f"Source file '{override_confg_path}' is not readable.") + return + + try: + with open(override_confg_path, 'r') as src, open(self.path_emulator_config, 'a') as dst: + dst.write(src.read()) + self.logger.info(f"Content from '{override_confg_path}' successfully appended to '{self.path_emulator_config}'.") + except Exception as e: + self.logger.error(f"An error occurred while copying file content: {e}") + def _add_skin(self) -> None: device_skin_path = os.path.join( self.path_emulator_skins, "{fn}".format(fn=self.file_name)) @@ -132,6 +156,7 @@ class Emulator(Device): self.logger.info(f"Command to create emulator: '{creation_cmd}'") subprocess.check_call(creation_cmd, shell=True) self._add_skin() + self._use_override_config() self.logger.info(f"{self.device_type} is created!") def change_permission(self) -> None: diff --git a/cli/src/tests/device/test_emulator.py b/cli/src/tests/device/test_emulator.py index 9661031..c5ba343 100644 --- a/cli/src/tests/device/test_emulator.py +++ b/cli/src/tests/device/test_emulator.py @@ -56,20 +56,23 @@ class TestEmulator(BaseDeviceTest): @mock.patch("src.device.emulator.Emulator._add_profile") @mock.patch("subprocess.check_call") @mock.patch("src.device.emulator.Emulator._add_skin") + @mock.patch("src.device.emulator.Emulator._use_override_config") @mock.patch("src.device.emulator.Emulator.is_initialized", mock.MagicMock(return_value=False)) - def test_create_device_not_exist(self, mocked_status, mocked_profile, mocked_subprocess, mocked_skin): + def test_create_device_not_exist(self, mocked_status, mocked_profile, mocked_subprocess, mocked_skin, mocked_override_config): self.emu.create() self.assertEqual(mocked_status.called, True) self.assertEqual(mocked_profile.called, True) self.assertEqual(mocked_subprocess.called, True) self.assertEqual(mocked_skin.called, True) + self.assertEqual(mocked_override_config.called, True) @mock.patch("src.device.Device.set_status") @mock.patch("src.device.emulator.Emulator._add_profile") @mock.patch("subprocess.check_call") @mock.patch("src.device.emulator.Emulator._add_skin") + @mock.patch("src.device.emulator.Emulator._use_override_config") @mock.patch("src.device.emulator.Emulator.is_initialized", mock.MagicMock(return_value=True)) - def test_create_device_exists(self, mocked_status, mocked_profile, mocked_subprocess, mocked_skin): + def test_create_device_exists(self, mocked_status, mocked_profile, mocked_subprocess, mocked_skin, mocked_override_config): self.emu.create() self.assertEqual(mocked_status.called, False) self.assertEqual(mocked_profile.called, False) @@ -85,3 +88,25 @@ class TestEmulator(BaseDeviceTest): with self.assertRaises(RuntimeError): self.emu.check_adb_command( self.emu.ReadinessCheck.BOOTED, "mocked_command", "1", 3, 0) + + def test_use_override_config_no_env(self): + with mock.patch("os.getenv", return_value=None): + self.emu._use_override_config() + + def test_use_override_config_file_not_exist(self): + with mock.patch("os.getenv", return_value="mock/path/to/config"): + with mock.patch("os.path.isfile", return_value=False): + self.emu._use_override_config() + + def test_use_override_config_file_not_readable(self): + with mock.patch("os.getenv", return_value="mock/path/to/config"): + with mock.patch("os.path.isfile", return_value=True): + with mock.patch("os.access", return_value=False): + self.emu._use_override_config() + + def test_use_override_config_malformed_content(self): + with mock.patch("os.getenv", return_value="mock/path/to/config"): + with mock.patch("os.path.isfile", return_value=True): + with mock.patch("os.access", return_value=True): + with mock.patch("builtins.open", mock.mock_open(read_data="malformed data")): + self.emu._use_override_config() diff --git a/documentations/CUSTOM_CONFIGURATIONS.md b/documentations/CUSTOM_CONFIGURATIONS.md index c6dd90a..393fd45 100644 --- a/documentations/CUSTOM_CONFIGURATIONS.md +++ b/documentations/CUSTOM_CONFIGURATIONS.md @@ -57,5 +57,18 @@ Possible environment variable to configure the Emulator: 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. +EMULATOR - OVERRIDE CONFIG FILE +------------------------------- + +To utilize this feature, ensure the following setup: + +- Set the config file path into environment variable EMULATOR_CONFIG_PATH, eg. `/tmp/emulator-override-config.ini` (the file name doesn't matter) +- Mount the file as Docker volume (parameter `-v` for Docker run command) to the path as you set into ENV + +Example: + +```shell +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 +``` [<- BACK TO README](../README.md)