1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
|
# Copyright 2022 the V8 project authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import os
import signal
import subprocess
import sys
from contextlib import contextmanager
from ..local.android import Driver
from .command import (
AndroidCommand,
IOSCommand,
PosixCommand,
WindowsCommand,
terminate_process_windows)
from .pool import DefaultExecutionPool
from .process_utils import EMPTY_PROCESS_LOGGER, PROCESS_LOGGER
from ..testproc.util import list_processes_linux
class DefaultOSContext:
def __init__(self, command, pool=None):
self.command = command
self.pool = pool or DefaultExecutionPool(self)
@contextmanager
def handle_context(self, options):
yield
def list_processes(self):
return []
def terminate_process(self, process):
pass
def platform_shell(self, shell, args, outdir):
return outdir.resolve() / shell
@property
def device_type(self):
return None
class DesktopContext(DefaultOSContext):
@contextmanager
def handle_context(self, options):
log_path = options.log_system_memory
logger = PROCESS_LOGGER if log_path else EMPTY_PROCESS_LOGGER
with logger.log_system_memory(log_path):
yield
class PosixContext(DesktopContext):
def __init__(self):
super().__init__(PosixCommand)
def list_processes(self):
return list_processes_linux()
def terminate_process(self, process):
os.kill(process.pid, signal.SIGTERM)
class WindowsContext(DesktopContext):
def __init__(self):
super().__init__(WindowsCommand)
def terminate_process(self, process):
terminate_process_windows(process)
def platform_shell(self, shell, args, outdir):
return outdir.resolve() / f'{shell}.exe'
class AndroidOSContext(DefaultOSContext):
def __init__(self):
super().__init__(AndroidCommand)
@contextmanager
def handle_context(self, options):
try:
AndroidCommand.driver = Driver.instance(options.device)
yield
finally:
AndroidCommand.driver.tear_down()
@property
def device_type(self):
return AndroidCommand.driver.device_type
class IOSContext(DefaultOSContext):
def __init__(self):
super().__init__(IOSCommand)
def terminate_process(self, process):
os.kill(process.pid, signal.SIGTERM)
def platform_shell(self, shell, appargs, outdir):
# Rather than having to use a physical device (iPhone, iPad, etc), we use
# the iOS Simulator for the test runners in order to ease the job of
# builders and testers.
# At the moment Chromium's iossim tool is being used, which is a wrapper
# around 'simctl' macOS command utility.
iossim = outdir.resolve() / "iossim -d 'iPhone X' "
if isinstance(appargs, list):
appargs = ' '.join(map(str, appargs))
if appargs != "":
iossim = f'{iossim}-c '
appargs = '\"' + appargs + '\"'
app = outdir.resolve() / f'{shell}.app'
return f'{iossim}{appargs} {app}'
# TODO(liviurau): Add documentation with diagrams to describe how context and
# its components gets initialized and eventually teared down and how does it
# interact with both tests and underlying platform specific concerns.
def find_os_context_factory(target_os):
registry = dict(
android=AndroidOSContext, ios=IOSContext, windows=WindowsContext)
return registry.get(target_os, PosixContext)
@contextmanager
def os_context(target_os, options):
factory = find_os_context_factory(target_os)
context_instance = factory()
with context_instance.handle_context(options):
yield context_instance
|