Move project test environments into the workspace

This commit is contained in:
2026-10-01 21:48:49 +08:00
parent f011d8357d
commit c2756ca4d6
23 changed files with 834 additions and 6 deletions
@@ -0,0 +1,107 @@
"""Host-only relocation and preservation checks; no network, devices or installs."""
import importlib.util
from pathlib import Path
import tempfile
import unittest
from unittest.mock import patch
import local_env as env
class LocalEnvironmentTests(unittest.TestCase):
def test_workspace_location_uses_source_not_cwd(self):
self.assertEqual(env.ROOT / '测试相关资料/如何测试/本机测试环境', env.HERE)
module = env.ROOT / '移动端相关内容/安卓app/如何安卓测试/local_test_paths.py'
spec = importlib.util.spec_from_file_location('test_paths', module)
value = importlib.util.module_from_spec(spec)
spec.loader.exec_module(value)
self.assertEqual(value.SSH_KNOWN_HOSTS, env.LOCAL / 'private/qms-mobile-known_hosts')
def test_copied_venv_is_rejected_without_overwriting(self):
with tempfile.TemporaryDirectory(prefix='中文 relocation ') as tmp:
local = Path(tmp)
venv = local / 'ssh/venv'
(venv / 'Scripts').mkdir(parents=True)
(venv / 'Scripts/python.exe').touch()
cfg = venv / 'pyvenv.cfg'
cfg.write_text('command = python -m venv old-location\n', encoding='utf-8')
with patch.object(env, 'LOCAL', local), patch.object(env, 'run', side_effect=AssertionError('unexpected install')):
with self.assertRaisesRegex(RuntimeError, 'preserve/rename'):
env.setup_python('ssh', offline=True)
self.assertEqual(cfg.read_text(encoding='utf-8'), 'command = python -m venv old-location\n')
def test_source_dependency_change_requires_a_new_lock(self):
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
source = root / '移动端相关内容/安卓app/如何安卓测试/requirements-host.txt'
source.parent.mkdir(parents=True)
source.write_text('paramiko==5.0.0\n', encoding='utf-8')
(root / 'requirements-ssh.lock.txt').write_text('paramiko==4.0.0 --hash=sha256:old\n', encoding='utf-8')
with patch.object(env, 'ROOT', root), patch.object(env, 'HERE', root):
with self.assertRaisesRegex(RuntimeError, 'source requirements changed'):
env.validate_lock('ssh')
def test_offline_missing_image_does_not_download(self):
with tempfile.TemporaryDirectory(prefix='中文 offline ') as tmp:
local = Path(tmp)
args = type('Args', (), {'offline': True, 'image_archive': None})()
with patch.object(env, 'LOCAL', local), patch.object(env, 'CONFIG', local / 'tools.local.json'), patch('urllib.request.urlopen', side_effect=AssertionError('network')):
with self.assertRaisesRegex(RuntimeError, 'missing image'):
env.setup_android(args)
def test_stale_avd_can_refresh_paths_without_resetting_userdata(self):
with tempfile.TemporaryDirectory(prefix='中文 avd ') as tmp:
local = Path(tmp)
directory = local / 'android/sdk/system-images/android-35/google_apis/x86_64'
directory.mkdir(parents=True)
avd = local / 'android/avd/qms-local-api35.avd'
avd.mkdir(parents=True)
(avd / '.qms-managed').touch()
(avd / 'config.ini').write_text('hw.ramSize=3072\nimage.sysdir.1=old\n', encoding='utf-8')
userdata = avd / 'userdata-qemu.img'
userdata.write_bytes(b'preserve')
args = type('Args', (), {'offline': True, 'image_archive': None})()
with patch.object(env, 'LOCAL', local), patch.object(env, 'CONFIG', local / 'tools.local.json'), patch.object(env, 'check_android'):
env.setup_android(args)
config = (avd / 'config.ini').read_text(encoding='utf-8')
self.assertIn('hw.ramSize=3072', config)
self.assertIn(str(directory.resolve()), config)
self.assertEqual(userdata.read_bytes(), b'preserve')
def test_unmanaged_avd_is_never_overwritten(self):
with tempfile.TemporaryDirectory() as tmp:
local = Path(tmp)
(local / 'android/sdk/system-images/android-35/google_apis/x86_64').mkdir(parents=True)
avd = local / 'android/avd/qms-local-api35.avd'
avd.mkdir(parents=True)
cfg = avd / 'config.ini'
cfg.write_text('owner=someone-else\n', encoding='utf-8')
args = type('Args', (), {'offline': True, 'image_archive': None})()
with patch.object(env, 'LOCAL', local), patch.object(env, 'CONFIG', local / 'tools.local.json'):
with self.assertRaisesRegex(RuntimeError, 'unmanaged'):
env.setup_android(args)
self.assertEqual(cfg.read_text(encoding='utf-8'), 'owner=someone-else\n')
@unittest.skipUnless(__import__('os').name == 'nt', 'Windows junction lifecycle')
def test_emulator_session_restores_image_path_and_removes_only_alias(self):
with tempfile.TemporaryDirectory(prefix='中文 session ') as tmp:
local = Path(tmp)
avd = local / 'android/avd/qms-local-api35.avd'
avd.mkdir(parents=True)
cfg = avd / 'config.ini'
cfg.write_text('hw.ramSize = 3072\nimage.sysdir.1 = before\n', encoding='utf-8')
(local / 'android/emulator-home').mkdir()
with patch.object(env, 'LOCAL', local):
with env.android_session() as (launch, image, alias):
self.assertTrue(alias.is_junction())
self.assertTrue(str(image).isascii())
self.assertTrue(str(launch['ANDROID_AVD_HOME']).isascii())
cfg.write_text(f'hw.ramSize = 3072\nimage.sysdir.1 = {image}\n', encoding='utf-8')
self.assertFalse(alias.exists())
self.assertEqual(env.ini_values(cfg)['image.sysdir.1'], str(env.image_dir().resolve()))
self.assertEqual(env.ini_values(cfg)['hw.ramSize'], '3072')
self.assertTrue(avd.is_dir())
if __name__ == '__main__':
unittest.main()