Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(749)

Unified Diff: components/proximity_auth/e2e_test/setup_test.py

Issue 1004283002: Add end-to-end testing tool for Smart Lock. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: components/proximity_auth/e2e_test/setup_test.py
diff --git a/components/proximity_auth/e2e_test/setup_test.py b/components/proximity_auth/e2e_test/setup_test.py
new file mode 100644
index 0000000000000000000000000000000000000000..fbd8242120dc86e3b56908dc8294827cae8837da
--- /dev/null
+++ b/components/proximity_auth/e2e_test/setup_test.py
@@ -0,0 +1,156 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+""" Script that exercises the Smart Lock setup flow, testing that a nearby phone
+can be found and used to unlock a Chromebook.
+
+Note: This script does not currently automate Android phones, so make sure that
+a phone is properly configured and online before starting the test.
+
+Usage:
+ python setup_test.py --remote_address REMOTE_ADDRESS
+ --username USERNAME
+ --password PASSWORD
+ [--app_path APP_PATH]
+
+ If |--app_path| is provided, then a copy of the Smart Lock app on the local
+ machine will be used instead of the app on the ChromeOS device.
+"""
+
+import argparse
+import cros
+import cryptauth
+import logging
+import os
+import subprocess
+import sys
+import tempfile
+
+logger = logging.getLogger('proximity_auth.%s' % __name__)
+
+class SmartLockSetupError(Exception):
+ pass
+
+def pingable_address(address):
+ try:
+ subprocess.check_output(['ping', '-c', '1', '-W', '1', address])
+ except subprocess.CalledProcessError:
+ raise argparse.ArgumentError('%s cannot be reached.' % address)
+ return address
+
+def email(arg):
+ tokens = arg.lower().split('@')
+ if len(tokens) != 2 or '.' not in tokens[1]:
+ raise argparse.ArgumentError('%s is not a valid email address' % arg)
+ name, domain = tokens
+ if domain == 'gmail.com':
+ name = name.replace('.', '')
+ return '@'.join([name, domain])
+
+def directory(path):
+ if not os.path.isdir(path):
+ raise argparse.ArgumentError('%s is not a directory' % path)
+ return path
+
+def ParseArgs():
+ parser = argparse.ArgumentParser(prog='python setup_test.py')
+ parser.add_argument('--remote_address', required=True, type=pingable_address)
+ parser.add_argument('--username', required=True, type=email)
+ parser.add_argument('--password', required=True)
+ parser.add_argument('--app_path', type=directory)
+ args = parser.parse_args()
+ return args
+
+def CheckCryptAuthState(access_token):
+ cryptauth_client = cryptauth.CryptAuthClient(access_token)
+
+ # Check if we can make CryptAuth requests.
+ if cryptauth_client.GetMyDevices() is None:
+ logger.error('Cannot reach CryptAuth on test machine.')
+ return False
+
+ if cryptauth_client.GetUnlockKey() is not None:
+ logger.info('Smart Lock currently enabled, turning off on Cryptauth...')
+ if not cryptauth_client.ToggleEasyUnlock(False):
+ logger.error('ToggleEasyUnlock request failed.')
+ return False
+
+ result = cryptauth_client.FindEligibleUnlockDevices()
+ if result is None:
+ logger.error('FindEligibleUnlockDevices request failed')
+ return False
+ eligibleDevices, _ = result
+ if len(eligibleDevices) == 0:
+ logger.warn('No eligible phones found, trying to ping phones...')
+ result = cryptauth_client.PingPhones()
+ if result is None or not len(result[0]):
+ logger.error('Pinging phones failed :(')
+ return False
+ else:
+ logger.inro('Pinging phones succeeded!')
Ilya Sherman 2015/03/24 01:25:14 nit: logger.info. This is why I prefer compiled l
Tim Song 2015/03/25 23:08:44 Done. I agree!
+ else:
+ logger.info('Found eligible device: %s' % \
+ eligibleDevices[0]['friendlyDeviceName'])
+ return True
+
+def _NavigateSetupDialog(chromeos, app):
+ logger.info('Scanning for nearby phones...')
+ btmon = chromeos.RunBtmon()
+ find_phone_success = app.FindPhone()
+ btmon.terminate()
+
+ if not find_phone_success:
+ fd, filepath = tempfile.mkstemp(prefix='btmon-')
+ os.write(fd, btmon.stdout.read())
+ os.close(fd)
+ logger.info('Logs for btmon can be found at %s' % filepath)
+ raise SmartLockSetupError("Failed to find nearby phone.")
+
+ logger.info('Phone found! Starting pairing...')
+ if not app.PairPhone():
+ raise SmartLockSetupError("Failed to pair with phone.")
+ logger.info('Pairing success! Starting trial run...')
+ app.StartTrialRun()
+
+ logger.info('Unlocking for trial run...')
+ lock_screen = chromeos.GetAccountPickerScreen()
+ lock_screen.WaitForSmartLockState(
+ lock_screen.SmartLockState.AUTHENTICATED)
+ lock_screen.UnlockWithClick()
+
+ logger.info('Trial run success! Dismissing app...')
+ app.DismissApp()
+
+def RunSetupTest(args):
+ logger.info('Starting test for %s at %s' % \
+ (args.username, args.remote_address))
+ if args.app_path is not None:
+ logger.info('Replacing Smart Lock app with %s' % args.app_path)
+
+ chromeos = cros.ChromeOS(args.remote_address, args.username, args.password)
+ with chromeos.Start(local_app_path=args.app_path):
+ logger.info('Chrome initialized')
+
+ # TODO(tengs): The access token is currently fetched from the Smart Lock
+ # app's background page. To be more robust, we should instead mint the
+ # access token ourselves.
+ if not CheckCryptAuthState(chromeos.cryptauth_access_token):
+ raise SmartLockSetupError('Failed to check CryptAuth state')
+
+ logger.info('Opening Smart Lock settings...')
+ settings = chromeos.GetSmartLockSettings()
+ assert(not settings.smart_lock_enabled)
+ logger.info('Starting Smart Lock setup flow...')
+ app = settings.StartSetupAndReturnApp()
+
+ _NavigateSetupDialog(chromeos, app)
+
+def main():
+ logging.basicConfig()
+ logging.getLogger('proximity_auth').setLevel(logging.INFO)
+ args = ParseArgs()
+ RunSetupTest(args)
+
+if __name__ == '__main__':
+ main()

Powered by Google App Engine
This is Rietveld 408576698