Chromium Code Reviews| Index: experimental/telemetry_mini/android_go_stories.py |
| diff --git a/experimental/telemetry_mini/android_go_stories.py b/experimental/telemetry_mini/android_go_stories.py |
| index 7d9c57b929c93a3c30713396c359973e7a029078..ca907b07eda51e0be23fe2c1e1eb5df2d290de79 100755 |
| --- a/experimental/telemetry_mini/android_go_stories.py |
| +++ b/experimental/telemetry_mini/android_go_stories.py |
| @@ -4,6 +4,7 @@ |
| # found in the LICENSE file. |
| import argparse |
| +import fnmatch |
| import logging |
| import os |
| import sys |
| @@ -31,81 +32,6 @@ BROWSERS = { |
| } |
| -class ProcessWatcher(object): |
|
perezju
2017/08/18 11:30:33
Did not changed any of this code. Just moved it a
|
| - def __init__(self, device): |
| - self.device = device |
| - self._process_pid = {} |
| - |
| - def StartWatching(self, process_name): |
| - """Register a process or android app to keep track of its PID.""" |
| - if isinstance(process_name, telemetry_mini.AndroidApp): |
| - process_name = process_name.PACKAGE_NAME |
| - |
| - @telemetry_mini.RetryOn(returns_falsy=True) |
| - def GetPids(): |
| - # Returns an empty list if the process name is not found. |
| - return self.device.ProcessStatus()[process_name] |
| - |
| - assert process_name not in self._process_pid |
| - pids = GetPids() |
| - assert pids, 'PID for %s not found' % process_name |
| - assert len(pids) == 1, 'Single PID for %s expected, but found: %s' % ( |
| - process_name, pids) |
| - logging.info('Started watching %s (PID=%d)', process_name, pids[0]) |
| - self._process_pid[process_name] = pids[0] |
| - |
| - def AssertAllAlive(self): |
| - """Check that all watched processes remain alive and were not restarted.""" |
| - status = self.device.ProcessStatus() |
| - all_alive = True |
| - for process_name, old_pid in sorted(self._process_pid.iteritems()): |
| - new_pids = status[process_name] |
| - if not new_pids: |
| - all_alive = False |
| - logging.error('Process %s died (PID=%d).', process_name, old_pid) |
| - elif new_pids != [old_pid]: |
| - all_alive = False |
| - logging.error( |
| - 'Process %s restarted (PID=%d -> %s).', process_name, |
| - old_pid, new_pids) |
| - else: |
| - logging.info('Process %s still alive (PID=%d)', process_name, old_pid) |
| - assert all_alive, 'Some watched processes died or got restarted' |
| - |
| - |
| -def EnsureSingleBrowser(device, browser_name, force_install=False): |
| - """Ensure a single Chrome browser is installed and available on the device. |
| - |
| - Having more than one Chrome browser available may produce results which are |
| - confusing or unreliable (e.g. unclear which browser will respond by default |
| - to intents triggered by other apps). |
| - |
| - This function ensures only the selected browser is available, installing it |
| - if necessary, and uninstalling/disabling others. |
| - """ |
| - browser = BROWSERS[browser_name](device) |
| - available_browsers = set(device.ListPackages('chrome', only_enabled=True)) |
| - |
| - # Install or enable if needed. |
| - if force_install or browser.PACKAGE_NAME not in available_browsers: |
| - browser.Install() |
| - |
| - # Uninstall disable other browser apps. |
| - for other_browser in BROWSERS.itervalues(): |
| - if (other_browser.PACKAGE_NAME != browser.PACKAGE_NAME and |
| - other_browser.PACKAGE_NAME in available_browsers): |
| - other_browser(device).Uninstall() |
| - |
| - # Finally check that only the selected browser is actually available. |
| - available_browsers = device.ListPackages('chrome', only_enabled=True) |
| - assert browser.PACKAGE_NAME in available_browsers, ( |
| - 'Unable to make %s available' % browser.PACKAGE_NAME) |
| - available_browsers.remove(browser.PACKAGE_NAME) |
| - assert not available_browsers, ( |
| - 'Other browsers may intefere with the test: %s' % available_browsers) |
| - return browser |
| - |
| - |
| class TwitterApp(telemetry_mini.AndroidApp): |
| PACKAGE_NAME = 'com.twitter.android' |
| @@ -115,6 +41,14 @@ class InstagramApp(telemetry_mini.AndroidApp): |
| class TwitterFlipkartStory(telemetry_mini.UserStory): |
| + """Load Chrome Custom Tab from another application. |
| + |
| + The flow of the story is: |
| + - Start Twitter app to view the @flipkart profile. |
| + - Tap on a link to open Flipkart in a Chrome Custom Tab. |
| + - Return to Twitter app. |
| + """ |
| + NAME = 'twitter_flipkart' |
| FLIPKART_TWITTER_LINK = [ |
| ('package', 'com.twitter.android'), |
| ('class', 'android.widget.TextView'), |
| @@ -149,6 +83,16 @@ class TwitterFlipkartStory(telemetry_mini.UserStory): |
| class FlipkartInstagramStory(telemetry_mini.UserStory): |
| + """Interaction between Chrome, PWAs and a WebView-based app. |
| + |
| + The flow of the story is: |
| + - Launch the Flipkart PWA. |
| + - Go back home and launch the Instagram app. |
| + - Use the app switcher to return to Flipkart. |
| + - Go back home and launch Cricbuzz from a shortcut. |
| + """ |
| + NAME = 'flipkart_instagram' |
| + |
| def __init__(self, *args, **kwargs): |
| super(FlipkartInstagramStory, self).__init__(*args, **kwargs) |
| self.watcher = ProcessWatcher(self.device) |
| @@ -187,6 +131,87 @@ class FlipkartInstagramStory(telemetry_mini.UserStory): |
| self.instagram.ForceStop() |
| +STORIES = ( |
| + TwitterFlipkartStory, |
| + FlipkartInstagramStory |
| +) |
| + |
| + |
| +class ProcessWatcher(object): |
|
perezju
2017/08/18 11:30:33
Code removed from above pasted back here.
|
| + def __init__(self, device): |
| + self.device = device |
| + self._process_pid = {} |
| + |
| + def StartWatching(self, process_name): |
| + """Register a process or android app to keep track of its PID.""" |
| + if isinstance(process_name, telemetry_mini.AndroidApp): |
| + process_name = process_name.PACKAGE_NAME |
| + |
| + @telemetry_mini.RetryOn(returns_falsy=True) |
| + def GetPids(): |
| + # Returns an empty list if the process name is not found. |
| + return self.device.ProcessStatus()[process_name] |
| + |
| + assert process_name not in self._process_pid |
| + pids = GetPids() |
| + assert pids, 'PID for %s not found' % process_name |
| + assert len(pids) == 1, 'Single PID for %s expected, but found: %s' % ( |
| + process_name, pids) |
| + logging.info('Started watching %s (PID=%d)', process_name, pids[0]) |
| + self._process_pid[process_name] = pids[0] |
| + |
| + def AssertAllAlive(self): |
| + """Check that all watched processes remain alive and were not restarted.""" |
| + status = self.device.ProcessStatus() |
| + all_alive = True |
| + for process_name, old_pid in sorted(self._process_pid.iteritems()): |
| + new_pids = status[process_name] |
| + if not new_pids: |
| + all_alive = False |
| + logging.error('Process %s died (PID=%d).', process_name, old_pid) |
| + elif new_pids != [old_pid]: |
| + all_alive = False |
| + logging.error( |
| + 'Process %s restarted (PID=%d -> %s).', process_name, |
| + old_pid, new_pids) |
| + else: |
| + logging.info('Process %s still alive (PID=%d)', process_name, old_pid) |
| + assert all_alive, 'Some watched processes died or got restarted' |
| + |
| + |
| +def EnsureSingleBrowser(device, browser_name, force_install=False): |
| + """Ensure a single Chrome browser is installed and available on the device. |
| + |
| + Having more than one Chrome browser available may produce results which are |
| + confusing or unreliable (e.g. unclear which browser will respond by default |
| + to intents triggered by other apps). |
| + |
| + This function ensures only the selected browser is available, installing it |
| + if necessary, and uninstalling/disabling others. |
| + """ |
| + browser = BROWSERS[browser_name](device) |
| + available_browsers = set(device.ListPackages('chrome', only_enabled=True)) |
| + |
| + # Install or enable if needed. |
| + if force_install or browser.PACKAGE_NAME not in available_browsers: |
| + browser.Install() |
| + |
| + # Uninstall disable other browser apps. |
| + for other_browser in BROWSERS.itervalues(): |
| + if (other_browser.PACKAGE_NAME != browser.PACKAGE_NAME and |
| + other_browser.PACKAGE_NAME in available_browsers): |
| + other_browser(device).Uninstall() |
| + |
| + # Finally check that only the selected browser is actually available. |
| + available_browsers = device.ListPackages('chrome', only_enabled=True) |
| + assert browser.PACKAGE_NAME in available_browsers, ( |
| + 'Unable to make %s available' % browser.PACKAGE_NAME) |
| + available_browsers.remove(browser.PACKAGE_NAME) |
| + assert not available_browsers, ( |
| + 'Other browsers may intefere with the test: %s' % available_browsers) |
| + return browser |
| + |
| + |
| def main(): |
| browser_names = sorted(BROWSERS) |
| default_browser = 'android-chrome' |
| @@ -201,6 +226,15 @@ def main(): |
| help='one of: %s' % ', '.join( |
| '%s (default)' % b if b == default_browser else b |
| for b in browser_names)) |
| + parser.add_argument('--story-filter', metavar='PATTERN', default='*', |
| + help='run the matching stories only (allows Unix' |
| + ' shell-style wildcards)') |
| + parser.add_argument('--storyset-repeat', metavar='NUM', type=int, default=1, |
| + help='repeat the story set a number of times' |
| + ' (default: %(default)d)') |
|
nednguyen
2017/08/18 14:00:32
I would just name this to "--repeat" for less typi
perezju
2017/08/18 14:09:05
Good point. Done!
|
| + parser.add_argument('--output-dir', metavar='PATH', |
| + help='path to directory for placing output trace files' |
| + ' (defaults to current directory)') |
| parser.add_argument('--force-install', action='store_true', |
| help='install APK even if browser is already available') |
| parser.add_argument('--apks-dir', metavar='PATH', |
| @@ -215,6 +249,17 @@ def main(): |
| if args.verbose: |
| logging.getLogger().setLevel(logging.INFO) |
| + stories = [s for s in STORIES if fnmatch.fnmatch(s.NAME, args.story_filter)] |
| + if not stories: |
| + return 'No matching stories' |
| + |
| + if args.output_dir is None: |
| + args.output_dir = os.getcwd() |
| + else: |
| + args.output_dir = os.path.realpath(args.output_dir) |
| + if not os.path.isdir(args.output_dir): |
| + return 'Output directory does not exit' |
| + |
| if args.apks_dir is None: |
| args.apks_dir = os.path.realpath(os.path.join( |
| os.path.dirname(__file__), '..', '..', '..', '..', |
| @@ -233,10 +278,11 @@ def main(): |
| device.RunCommand('wait-for-device') |
| browser = EnsureSingleBrowser(device, args.browser, args.force_install) |
| + browser.SetBrowserFlags(BROWSER_FLAGS) |
| + browser.SetTraceConfig(TRACE_CONFIG) |
| browser.SetDevToolsLocalPort(args.port) |
| - |
| - story = FlipkartInstagramStory(browser) |
| - story.Run(BROWSER_FLAGS, TRACE_CONFIG, 'trace.json') |
| + telemetry_mini.RunStories( |
| + browser, stories, args.storyset_repeat, args.output_dir) |
| if __name__ == '__main__': |