| OLD | NEW |
| 1 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 1 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 import dbus, logging, os, re, shutil, socket, sys | 5 import dbus, logging, os, re, shutil, socket, sys |
| 6 import common | 6 import common |
| 7 import auth_server, constants as chromeos_constants, cryptohome, dns_server | 7 import auth_server, constants, cryptohome, dns_server |
| 8 import cros_logging, cros_ui, login, ownership | 8 import cros_logging, cros_ui, login, ownership |
| 9 from autotest_lib.client.bin import test, utils | 9 from autotest_lib.client.bin import test, utils |
| 10 from autotest_lib.client.common_lib import error | 10 from autotest_lib.client.common_lib import error |
| 11 from dbus.mainloop.glib import DBusGMainLoop | 11 from dbus.mainloop.glib import DBusGMainLoop |
| 12 | 12 |
| 13 from autotest_lib.client.cros import flimflam_test_path | 13 from autotest_lib.client.cros import flimflam_test_path |
| 14 import flimflam | 14 import flimflam |
| 15 | 15 |
| 16 | 16 |
| 17 class UITest(test.test): | 17 class UITest(test.test): |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 79 for device in self._flim.GetObjectList('Device'): | 79 for device in self._flim.GetObjectList('Device'): |
| 80 properties = device.GetProperties() | 80 properties = device.GetProperties() |
| 81 interface = properties['Interface'] | 81 interface = properties['Interface'] |
| 82 logging.debug("Considering " + interface) | 82 logging.debug("Considering " + interface) |
| 83 for path in properties['IPConfigs']: | 83 for path in properties['IPConfigs']: |
| 84 ipconfig = self._flim.GetObjectInterface('IPConfig', path) | 84 ipconfig = self._flim.GetObjectInterface('IPConfig', path) |
| 85 | 85 |
| 86 servers = ipconfig.GetProperties().get('NameServers', None) | 86 servers = ipconfig.GetProperties().get('NameServers', None) |
| 87 if servers != None: | 87 if servers != None: |
| 88 self._dns[path] = ','.join(servers) | 88 self._dns[path] = ','.join(servers) |
| 89 logging.debug("Stored DNS for " + interface) | 89 logging.debug("Stored %s for %s" % (self._dns[path], |
| 90 interface)) |
| 90 ipconfig.SetProperty('NameServers', '127.0.0.1') | 91 ipconfig.SetProperty('NameServers', '127.0.0.1') |
| 91 logging.debug("Using local DNS for " + interface) | 92 logging.debug("Using local DNS for " + interface) |
| 92 | 93 |
| 93 utils.poll_for_condition( | 94 utils.poll_for_condition( |
| 94 lambda: self.__attempt_resolve('www.google.com', '127.0.0.1'), | 95 lambda: self.__attempt_resolve('www.google.com', '127.0.0.1'), |
| 95 login.TimeoutError('Timed out waiting for DNS changes.'), | 96 login.TimeoutError('Timed out waiting for DNS changes.'), |
| 96 10) | 97 10) |
| 97 | 98 |
| 98 | 99 |
| 99 def revert_dns(self): | 100 def revert_dns(self): |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 145 Authentication is not performed against live servers. Instead, we spin | 146 Authentication is not performed against live servers. Instead, we spin |
| 146 up a local DNS server that will lie and say that all sites resolve to | 147 up a local DNS server that will lie and say that all sites resolve to |
| 147 127.0.0.1. We use DBus to tell flimflam to use this DNS server to | 148 127.0.0.1. We use DBus to tell flimflam to use this DNS server to |
| 148 resolve addresses. We then spin up a local httpd that will respond | 149 resolve addresses. We then spin up a local httpd that will respond |
| 149 to queries at the Google Accounts endpoints. We clear the DNS setting | 150 to queries at the Google Accounts endpoints. We clear the DNS setting |
| 150 and tear down these servers in cleanup(). | 151 and tear down these servers in cleanup(). |
| 151 | 152 |
| 152 Args: | 153 Args: |
| 153 creds: String specifying the credentials for this test case. Can | 154 creds: String specifying the credentials for this test case. Can |
| 154 be a named set of credentials as defined by | 155 be a named set of credentials as defined by |
| 155 chromeos_constants.CREDENTIALS, or a 'username:password' pair. | 156 constants.CREDENTIALS, or a 'username:password' pair. |
| 156 Defaults to None -- browse without signing-in. | 157 Defaults to None -- browse without signing-in. |
| 157 is_creating_owner: If the test case is creating a new device owner. | 158 is_creating_owner: If the test case is creating a new device owner. |
| 158 | 159 |
| 159 """ | 160 """ |
| 160 | 161 |
| 161 # Mark /var/log/messages now; we'll run through all subsequent | 162 # Mark /var/log/messages now; we'll run through all subsequent |
| 162 # log messages at the end of the test and log info about processes that | 163 # log messages at the end of the test and log info about processes that |
| 163 # crashed. | 164 # crashed. |
| 164 self._log_reader = cros_logging.LogReader() | 165 self._log_reader = cros_logging.LogReader() |
| 165 self._log_reader.set_start_by_current() | 166 self._log_reader.set_start_by_current() |
| 166 | 167 |
| 167 if creds: | 168 if creds: |
| 168 self.start_authserver() | 169 self.start_authserver() |
| 169 | 170 |
| 170 # Fake ownership unless the test is explicitly testing owner creation. | 171 # Fake ownership unless the test is explicitly testing owner creation. |
| 171 if not is_creating_owner and not os.access( | 172 if not is_creating_owner and not os.access( |
| 172 chromeos_constants.OWNER_KEY_FILE, os.F_OK): | 173 constants.OWNER_KEY_FILE, os.F_OK): |
| 173 logging.info('Owner credentials not found. Faking ownership...') | 174 logging.info('Owner credentials not found. Faking ownership...') |
| 174 self.__fake_ownership() | 175 self.__fake_ownership() |
| 175 self.fake_owner = True | 176 self.fake_owner = True |
| 176 | 177 |
| 177 if login.logged_in(): | 178 if login.logged_in(): |
| 178 login.attempt_logout() | 179 login.attempt_logout() |
| 179 | 180 |
| 180 (self.username, self.password) = self.__resolve_creds(creds) | 181 (self.username, self.password) = self.__resolve_creds(creds) |
| 181 # Ensure there's no stale cryptohome from previous tests. | 182 # Ensure there's no stale cryptohome from previous tests. |
| 182 try: | 183 try: |
| 183 cryptohome.remove_vault(self.username) | 184 cryptohome.remove_vault(self.username) |
| 184 except cryptohome.ChromiumOSError as err: | 185 except cryptohome.ChromiumOSError as err: |
| 185 logging.error(err) | 186 logging.error(err) |
| 186 | 187 |
| 187 if is_creating_owner: | 188 if is_creating_owner: |
| 188 logging.info('Erasing stale owner state.') | 189 logging.info('Erasing stale owner state.') |
| 189 # Ensure there's no stale owner state from previous tests. | 190 ownership.clear_ownership() |
| 190 try: | |
| 191 os.unlink(chromeos_constants.OWNER_KEY_FILE) | |
| 192 os.unlink(chromeos_constants.SIGNED_PREFERENCES_FILE) | |
| 193 except (IOError, OSError) as err: | |
| 194 logging.info(err) | |
| 195 | 191 |
| 196 login.refresh_login_screen() | 192 login.refresh_login_screen() |
| 197 if self.auto_login: | 193 if self.auto_login: |
| 198 self.login(self.username, self.password) | 194 self.login(self.username, self.password) |
| 199 if is_creating_owner: | 195 if is_creating_owner: |
| 200 login.wait_for_ownership() | 196 login.wait_for_ownership() |
| 201 | 197 |
| 202 def __fake_ownership(self): | 198 def __fake_ownership(self): |
| 203 """Fake ownership by generating the necessary magic files.""" | 199 """Fake ownership by generating the necessary magic files.""" |
| 204 # Determine the module directory. | 200 # Determine the module directory. |
| 205 dirname = os.path.dirname(__file__) | 201 dirname = os.path.dirname(__file__) |
| 206 mock_certfile = os.path.join(dirname, 'mock_owner_cert.pem') | 202 mock_certfile = os.path.join(dirname, 'mock_owner_cert.pem') |
| 207 mock_signedprefsfile = os.path.join(dirname, 'mock_owner.preferences') | 203 mock_signedprefsfile = os.path.join(dirname, 'mock_owner.preferences') |
| 208 utils.open_write_close( | 204 utils.open_write_close( |
| 209 chromeos_constants.OWNER_KEY_FILE, | 205 constants.OWNER_KEY_FILE, |
| 210 ownership.cert_extract_pubkey_der(mock_certfile)) | 206 ownership.cert_extract_pubkey_der(mock_certfile)) |
| 211 shutil.copy(mock_signedprefsfile, | 207 shutil.copy(mock_signedprefsfile, |
| 212 chromeos_constants.SIGNED_PREFERENCES_FILE) | 208 constants.SIGNED_PREFERENCES_FILE) |
| 213 | 209 |
| 214 | 210 |
| 215 def __canonicalize(self, credential): | 211 def __canonicalize(self, credential): |
| 216 """Perform basic canonicalization of |email_address| | 212 """Perform basic canonicalization of |email_address| |
| 217 | 213 |
| 218 Perform basic canonicalization of |email_address|, taking | 214 Perform basic canonicalization of |email_address|, taking |
| 219 into account that gmail does not consider '.' or caps inside a | 215 into account that gmail does not consider '.' or caps inside a |
| 220 username to matter. It also ignores everything after a '+'. | 216 username to matter. It also ignores everything after a '+'. |
| 221 For example, c.masone+abc@gmail.com == cMaSone@gmail.com, per | 217 For example, c.masone+abc@gmail.com == cMaSone@gmail.com, per |
| 222 http://mail.google.com/support/bin/answer.py?hl=en&ctx=mail&answer=10313 | 218 http://mail.google.com/support/bin/answer.py?hl=en&ctx=mail&answer=10313 |
| 223 """ | 219 """ |
| 224 if not credential: | 220 if not credential: |
| 225 return None | 221 return None |
| 226 | 222 |
| 227 parts = credential.split('@') | 223 parts = credential.split('@') |
| 228 if len(parts) != 2: | 224 if len(parts) != 2: |
| 229 raise error.TestError("Malformed email: " + credential) | 225 raise error.TestError("Malformed email: " + credential) |
| 230 | 226 |
| 231 (name, domain) = parts | 227 (name, domain) = parts |
| 232 name = name.partition('+')[0] | 228 name = name.partition('+')[0] |
| 233 if (domain == chromeos_constants.SPECIAL_CASE_DOMAIN): | 229 if (domain == constants.SPECIAL_CASE_DOMAIN): |
| 234 name = name.replace('.', '') | 230 name = name.replace('.', '') |
| 235 return '@'.join([name, domain]).lower() | 231 return '@'.join([name, domain]).lower() |
| 236 | 232 |
| 237 | 233 |
| 238 def __resolve_creds(self, creds): | 234 def __resolve_creds(self, creds): |
| 239 """Map credential identifier to username, password and type. | 235 """Map credential identifier to username, password and type. |
| 240 Args: | 236 Args: |
| 241 creds: credential identifier to resolve. | 237 creds: credential identifier to resolve. |
| 242 | 238 |
| 243 Returns: | 239 Returns: |
| 244 A (username, password) tuple. | 240 A (username, password) tuple. |
| 245 """ | 241 """ |
| 246 if not creds: | 242 if not creds: |
| 247 return [None, None] # Browse without signing-in. | 243 return [None, None] # Browse without signing-in. |
| 248 if creds[0] == '$': | 244 if creds[0] == '$': |
| 249 if creds not in chromeos_constants.CREDENTIALS: | 245 if creds not in constants.CREDENTIALS: |
| 250 raise error.TestFail('Unknown credentials: %s' % creds) | 246 raise error.TestFail('Unknown credentials: %s' % creds) |
| 251 | 247 |
| 252 (name, passwd) = chromeos_constants.CREDENTIALS[creds] | 248 (name, passwd) = constants.CREDENTIALS[creds] |
| 253 return [self.__canonicalize(name), passwd] | 249 return [self.__canonicalize(name), passwd] |
| 254 | 250 |
| 255 (name, passwd) = creds.split(':') | 251 (name, passwd) = creds.split(':') |
| 256 return [self.__canonicalize(name), passwd] | 252 return [self.__canonicalize(name), passwd] |
| 257 | 253 |
| 258 | 254 |
| 259 def ensure_login_complete(self): | 255 def ensure_login_complete(self): |
| 260 """Wait for authentication to complete. If you want a different | 256 """Wait for authentication to complete. If you want a different |
| 261 termination condition, override this method. | 257 termination condition, override this method. |
| 262 """ | 258 """ |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 334 in_logout = False | 330 in_logout = False |
| 335 for line in self._log_reader.get_logs().splitlines(): | 331 for line in self._log_reader.get_logs().splitlines(): |
| 336 if logout_start_regex.search(line): | 332 if logout_start_regex.search(line): |
| 337 in_logout = True | 333 in_logout = True |
| 338 elif logout_complete_regex.search(line): | 334 elif logout_complete_regex.search(line): |
| 339 in_logout = False | 335 in_logout = False |
| 340 else: | 336 else: |
| 341 match = crash_regex.search(line) | 337 match = crash_regex.search(line) |
| 342 if (match and not match.group(1) in processes and | 338 if (match and not match.group(1) in processes and |
| 343 not (in_logout and | 339 not (in_logout and |
| 344 (match.group(1) == chromeos_constants.BROWSER or | 340 (match.group(1) == constants.BROWSER or |
| 345 match.group(1) == 'supplied_chrome') and | 341 match.group(1) == 'supplied_chrome') and |
| 346 match.group(2) == 'sig 6')): | 342 match.group(2) == 'sig 6')): |
| 347 self.job.record('INFO', self.tagged_testname, | 343 self.job.record('INFO', self.tagged_testname, |
| 348 line[match.start():]) | 344 line[match.start():]) |
| 349 | 345 |
| 350 | 346 |
| 351 def cleanup(self): | 347 def cleanup(self): |
| 352 """Overridden from test.cleanup() to log out when the test is complete. | 348 """Overridden from test.cleanup() to log out when the test is complete. |
| 353 """ | 349 """ |
| 354 logpath = chromeos_constants.CHROME_LOG_DIR | 350 logpath = constants.CHROME_LOG_DIR |
| 355 | 351 |
| 356 try: | 352 try: |
| 357 for filename in os.listdir(logpath): | 353 for filename in os.listdir(logpath): |
| 358 fullpath = os.path.join(logpath, filename) | 354 fullpath = os.path.join(logpath, filename) |
| 359 if os.path.isfile(fullpath): | 355 if os.path.isfile(fullpath): |
| 360 shutil.copy(fullpath, os.path.join(self.resultsdir, | 356 shutil.copy(fullpath, os.path.join(self.resultsdir, |
| 361 filename)) | 357 filename)) |
| 362 | 358 |
| 363 except (IOError, OSError) as err: | 359 except (IOError, OSError) as err: |
| 364 logging.error(err) | 360 logging.error(err) |
| 365 | 361 |
| 366 if login.logged_in(): | 362 if login.logged_in(): |
| 367 try: | 363 try: |
| 368 shutil.copy( | 364 shutil.copy( |
| 369 os.path.join(chromeos_constants.CRYPTOHOME_MOUNT_PT, | 365 os.path.join(constants.CRYPTOHOME_MOUNT_PT, |
| 370 'log', 'chrome'), | 366 'log', 'chrome'), |
| 371 self.resultsdir+'/chrome_postlogin_log') | 367 self.resultsdir+'/chrome_postlogin_log') |
| 372 except (IOError, OSError) as err: | 368 except (IOError, OSError) as err: |
| 373 logging.error(err) | 369 logging.error(err) |
| 374 self.logout() | 370 self.logout() |
| 375 | 371 |
| 376 if os.path.isfile(chromeos_constants.CRYPTOHOMED_LOG): | 372 if os.path.isfile(constants.CRYPTOHOMED_LOG): |
| 377 try: | 373 try: |
| 378 base = os.path.basename(chromeos_constants.CRYPTOHOMED_LOG) | 374 base = os.path.basename(constants.CRYPTOHOMED_LOG) |
| 379 shutil.copy(chromeos_constants.CRYPTOHOMED_LOG, | 375 shutil.copy(constants.CRYPTOHOMED_LOG, |
| 380 os.path.join(self.resultsdir, base)) | 376 os.path.join(self.resultsdir, base)) |
| 381 except (IOError, OSError) as err: | 377 except (IOError, OSError) as err: |
| 382 logging.error(err) | 378 logging.error(err) |
| 383 | 379 |
| 384 if self.fake_owner: | 380 if self.fake_owner: |
| 385 logging.info('Erasing fake owner state.') | 381 logging.info('Erasing fake owner state.') |
| 386 try: | 382 ownership.clear_ownership() |
| 387 os.unlink(chromeos_constants.OWNER_KEY_FILE) | |
| 388 os.unlink(chromeos_constants.SIGNED_PREFERENCES_FILE) | |
| 389 except (IOError, OSError) as err: | |
| 390 logging.info(err) | |
| 391 | 383 |
| 392 self.stop_authserver() | 384 self.stop_authserver() |
| 393 self.__log_crashed_processes(self.crash_blacklist) | 385 self.__log_crashed_processes(self.crash_blacklist) |
| 394 | 386 |
| 395 | 387 |
| 396 def get_auth_endpoint_misses(self): | 388 def get_auth_endpoint_misses(self): |
| 397 if hasattr(self, '_authServer'): | 389 if hasattr(self, '_authServer'): |
| 398 return self._authServer.get_endpoint_misses() | 390 return self._authServer.get_endpoint_misses() |
| 399 else: | 391 else: |
| 400 return {} | 392 return {} |
| OLD | NEW |