Skip to content

Commit e721a27

Browse files
committed
enhance workflows and tests: set AVD-specific environment variables for Android emulator setup and operations, update test cases to incorporate explicit AVD paths for improved consistency and debugging
1 parent 6d5358e commit e721a27

3 files changed

Lines changed: 110 additions & 45 deletions

File tree

.github/workflows/e2e-android-test.yml

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,18 @@ jobs:
118118
echo " Architecture: ${{ matrix.arch }}"
119119
echo " OS: ${{ matrix.os }}"
120120
121+
# Set Android environment variables for AVD location
122+
export ANDROID_HOME=$HOME/ovmb_cache/android-sdk
123+
export ANDROID_SDK_ROOT=$HOME/ovmb_cache/android-sdk
124+
export ANDROID_SDK_HOME=$HOME/ovmb_cache/android-sdk
125+
export ANDROID_AVD_HOME=$HOME/ovmb_cache/android-sdk/.android/avd
126+
127+
echo "📍 Environment variables set:"
128+
echo " ANDROID_HOME=$ANDROID_HOME"
129+
echo " ANDROID_SDK_ROOT=$ANDROID_SDK_ROOT"
130+
echo " ANDROID_SDK_HOME=$ANDROID_SDK_HOME"
131+
echo " ANDROID_AVD_HOME=$ANDROID_AVD_HOME"
132+
121133
python -m ovmobilebench.cli setup-android \
122134
-c ${{ matrix.config_file }} \
123135
--api ${{ matrix.android-api }} \
@@ -129,9 +141,24 @@ jobs:
129141
echo "📊 Android SDK setup complete:"
130142
echo " Cache size: $(du -sh $HOME/ovmb_cache 2>/dev/null || echo 'calculating...')"
131143
144+
# List created AVDs
145+
echo "📱 Created AVDs:"
146+
ls -la $ANDROID_AVD_HOME 2>/dev/null || echo "AVD directory not found"
147+
132148
# === PREPARE EMULATOR ===
133149
- name: Start Android Emulator
134150
run: |
151+
# Set Android environment variables for AVD location
152+
export ANDROID_HOME=$HOME/ovmb_cache/android-sdk
153+
export ANDROID_SDK_ROOT=$HOME/ovmb_cache/android-sdk
154+
export ANDROID_SDK_HOME=$HOME/ovmb_cache/android-sdk
155+
export ANDROID_AVD_HOME=$HOME/ovmb_cache/android-sdk/.android/avd
156+
157+
echo "📍 Starting emulator with environment:"
158+
echo " ANDROID_AVD_HOME=$ANDROID_AVD_HOME"
159+
echo "📱 Available AVDs:"
160+
ls -la $ANDROID_AVD_HOME 2>/dev/null || echo "No AVDs found"
161+
135162
python tests/e2e/test_emulator_helper.py -c ${{ matrix.config_file }} start-emulator &
136163
# Give emulator a moment to start before checking
137164
sleep 10
@@ -207,7 +234,14 @@ jobs:
207234
# === CLEANUP ===
208235
- name: Stop emulator
209236
if: always()
210-
run: python tests/e2e/test_emulator_helper.py -c ${{ matrix.config_file }} stop-emulator
237+
run: |
238+
# Set Android environment variables
239+
export ANDROID_HOME=$HOME/ovmb_cache/android-sdk
240+
export ANDROID_SDK_ROOT=$HOME/ovmb_cache/android-sdk
241+
export ANDROID_SDK_HOME=$HOME/ovmb_cache/android-sdk
242+
export ANDROID_AVD_HOME=$HOME/ovmb_cache/android-sdk/.android/avd
243+
244+
python tests/e2e/test_emulator_helper.py -c ${{ matrix.config_file }} stop-emulator
211245
212246
- name: Upload artifacts
213247
if: always()

tests/e2e/test_emulator_helper.py

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,15 @@ def get_sdk_path_from_config(config_file=None):
5858
return str(Path.cwd() / "ovmb_cache" / "android-sdk")
5959

6060

61+
def get_avd_home_from_config(config_file=None):
62+
"""Get AVD home directory - use .android/avd in SDK location."""
63+
sdk_path = get_sdk_path_from_config(config_file)
64+
# AVD home is in SDK_PATH/.android/avd
65+
avd_home = str(Path(sdk_path) / ".android" / "avd")
66+
logger.info(f"Using AVD home: {avd_home}")
67+
return avd_home
68+
69+
6170
def get_arch_from_config(config_file=None):
6271
"""Get architecture from OVMobileBench config."""
6372
# Use provided config file or default
@@ -82,6 +91,7 @@ def get_arch_from_config(config_file=None):
8291

8392
# Global variables that will be initialized in main()
8493
ANDROID_HOME = None
94+
AVD_HOME = None
8595
ARCHITECTURE = None
8696

8797

@@ -95,6 +105,16 @@ def create_avd(api_level: int, avd_name: str = None):
95105
)
96106

97107
avdmanager_path = Path(ANDROID_HOME) / "cmdline-tools" / "latest" / "bin" / "avdmanager"
108+
109+
# Set environment variables for AVD creation
110+
env = os.environ.copy()
111+
env["ANDROID_SDK_ROOT"] = ANDROID_HOME
112+
env["ANDROID_HOME"] = ANDROID_HOME
113+
env["ANDROID_AVD_HOME"] = AVD_HOME
114+
115+
# Create AVD directory if it doesn't exist
116+
Path(AVD_HOME).mkdir(parents=True, exist_ok=True)
117+
98118
cmd = [
99119
str(avdmanager_path),
100120
"create",
@@ -108,8 +128,8 @@ def create_avd(api_level: int, avd_name: str = None):
108128
"--force",
109129
]
110130

111-
subprocess.run(cmd, input="no\n", text=True, check=True)
112-
logger.info(f"AVD '{avd_name}' created successfully")
131+
subprocess.run(cmd, input="no\n", text=True, check=True, env=env)
132+
logger.info(f"AVD '{avd_name}' created successfully in {AVD_HOME}")
113133

114134

115135
def start_emulator(avd_name: str = None, api_level: int = 30):
@@ -155,7 +175,7 @@ def start_emulator(avd_name: str = None, api_level: int = 30):
155175
env = os.environ.copy()
156176
env["ANDROID_SDK_ROOT"] = ANDROID_HOME
157177
env["ANDROID_HOME"] = ANDROID_HOME
158-
env["ANDROID_AVD_HOME"] = str(Path(ANDROID_HOME) / "avd")
178+
env["ANDROID_AVD_HOME"] = AVD_HOME
159179

160180
subprocess.Popen(cmd, env=env)
161181
logger.info("Emulator started in background")
@@ -242,7 +262,14 @@ def delete_avd(avd_name: str = None, api_level: int = 30):
242262

243263
logger.info(f"Deleting AVD '{avd_name}'...")
244264
avdmanager_path = Path(ANDROID_HOME) / "cmdline-tools" / "latest" / "bin" / "avdmanager"
245-
subprocess.run([str(avdmanager_path), "delete", "avd", "-n", avd_name], check=False)
265+
266+
# Set environment variables for AVD deletion
267+
env = os.environ.copy()
268+
env["ANDROID_SDK_ROOT"] = ANDROID_HOME
269+
env["ANDROID_HOME"] = ANDROID_HOME
270+
env["ANDROID_AVD_HOME"] = AVD_HOME
271+
272+
subprocess.run([str(avdmanager_path), "delete", "avd", "-n", avd_name], check=False, env=env)
246273

247274

248275
def main():
@@ -280,13 +307,16 @@ def main():
280307

281308
args = parser.parse_args()
282309

283-
# Initialize ANDROID_HOME and ARCHITECTURE from config
284-
global ANDROID_HOME, ARCHITECTURE
310+
# Initialize ANDROID_HOME, AVD_HOME and ARCHITECTURE from config
311+
global ANDROID_HOME, AVD_HOME, ARCHITECTURE
285312
ANDROID_HOME = get_sdk_path_from_config(args.config)
313+
AVD_HOME = get_avd_home_from_config(args.config)
286314
ARCHITECTURE = get_arch_from_config(args.config)
287315
os.environ["ANDROID_HOME"] = ANDROID_HOME
288316
os.environ["ANDROID_SDK_ROOT"] = ANDROID_HOME
317+
os.environ["ANDROID_AVD_HOME"] = AVD_HOME
289318
logger.info(f"Using Android SDK: {ANDROID_HOME}")
319+
logger.info(f"Using AVD home: {AVD_HOME}")
290320
logger.info(f"Using architecture: {ARCHITECTURE}")
291321

292322
if args.command == "create-avd":

tests/helpers/test_emulator_helper.py

Lines changed: 39 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@
1313
# Import and configure test_emulator_helper module
1414
import test_emulator_helper
1515

16-
# Set ANDROID_HOME and ARCHITECTURE for all tests
16+
# Set ANDROID_HOME, AVD_HOME and ARCHITECTURE for all tests
1717
test_emulator_helper.ANDROID_HOME = "/mock/android-sdk"
18+
test_emulator_helper.AVD_HOME = "/mock/android-sdk/.android/avd"
1819
test_emulator_helper.ARCHITECTURE = "arm64-v8a" # Default for tests
1920

2021

@@ -24,65 +25,65 @@ class TestEmulatorHelper:
2425
@pytest.fixture(autouse=True)
2526
def setup(self):
2627
"""Setup test environment."""
27-
# Ensure ANDROID_HOME and ARCHITECTURE are set for all tests
28+
# Ensure ANDROID_HOME, AVD_HOME and ARCHITECTURE are set for all tests
2829
test_emulator_helper.ANDROID_HOME = "/mock/android-sdk"
30+
test_emulator_helper.AVD_HOME = "/mock/android-sdk/.android/avd"
2931
test_emulator_helper.ARCHITECTURE = "arm64-v8a" # Default for tests
3032

3133
def test_create_avd_with_default_name(self):
3234
"""Test AVD creation with default naming."""
3335
from test_emulator_helper import create_avd
3436

3537
with patch("subprocess.run") as mock_run:
36-
mock_run.return_value = Mock(returncode=0)
38+
with patch("pathlib.Path.mkdir"): # Mock mkdir to avoid filesystem operations
39+
mock_run.return_value = Mock(returncode=0)
40+
41+
create_avd(api_level=30)
3742

38-
create_avd(api_level=30)
39-
40-
expected_cmd = [
41-
"/mock/android-sdk/cmdline-tools/latest/bin/avdmanager",
42-
"create",
43-
"avd",
44-
"-n",
45-
"ovmobilebench_avd_api30",
46-
"-k",
47-
"system-images;android-30;google_apis;arm64-v8a",
48-
"-d",
49-
"pixel_5",
50-
"--force",
51-
]
52-
mock_run.assert_called_once_with(expected_cmd, input="no\n", text=True, check=True)
43+
# Check that subprocess.run was called with correct parameters
44+
actual_call = mock_run.call_args
45+
assert (
46+
actual_call[0][0][0] == "/mock/android-sdk/cmdline-tools/latest/bin/avdmanager"
47+
)
48+
assert "create" in actual_call[0][0]
49+
assert "avd" in actual_call[0][0]
50+
assert "ovmobilebench_avd_api30" in actual_call[0][0]
51+
assert "system-images;android-30;google_apis;arm64-v8a" in actual_call[0][0]
52+
assert actual_call[1]["input"] == "no\n"
53+
assert actual_call[1]["check"] is True
5354

5455
def test_create_avd_with_custom_name(self):
5556
"""Test AVD creation with custom name."""
5657
from test_emulator_helper import create_avd
5758

5859
with patch("subprocess.run") as mock_run:
59-
mock_run.return_value = Mock(returncode=0)
60-
61-
create_avd(api_level=34, avd_name="custom_avd")
62-
63-
expected_cmd = [
64-
"/mock/android-sdk/cmdline-tools/latest/bin/avdmanager",
65-
"create",
66-
"avd",
67-
"-n",
68-
"custom_avd",
69-
"-k",
70-
"system-images;android-34;google_apis;arm64-v8a",
71-
"-d",
72-
"pixel_5",
73-
"--force",
74-
]
75-
mock_run.assert_called_once_with(expected_cmd, input="no\n", text=True, check=True)
60+
with patch("pathlib.Path.mkdir"): # Mock mkdir to avoid filesystem operations
61+
mock_run.return_value = Mock(returncode=0)
62+
63+
create_avd(api_level=34, avd_name="custom_avd")
64+
65+
# Check that subprocess.run was called with correct parameters
66+
actual_call = mock_run.call_args
67+
assert (
68+
actual_call[0][0][0] == "/mock/android-sdk/cmdline-tools/latest/bin/avdmanager"
69+
)
70+
assert "create" in actual_call[0][0]
71+
assert "avd" in actual_call[0][0]
72+
assert "custom_avd" in actual_call[0][0]
73+
assert "system-images;android-34;google_apis;arm64-v8a" in actual_call[0][0]
74+
assert actual_call[1]["input"] == "no\n"
75+
assert actual_call[1]["check"] is True
7676

7777
def test_create_avd_failure(self):
7878
"""Test AVD creation failure handling."""
7979
from test_emulator_helper import create_avd
8080

8181
with patch("subprocess.run") as mock_run:
82-
mock_run.side_effect = subprocess.CalledProcessError(1, "avdmanager")
82+
with patch("pathlib.Path.mkdir"): # Mock mkdir to avoid filesystem operations
83+
mock_run.side_effect = subprocess.CalledProcessError(1, "avdmanager")
8384

84-
with pytest.raises(subprocess.CalledProcessError):
85-
create_avd(api_level=30)
85+
with pytest.raises(subprocess.CalledProcessError):
86+
create_avd(api_level=30)
8687

8788
@patch("platform.system")
8889
def test_start_emulator_linux(self, mock_platform):

0 commit comments

Comments
 (0)