Commit a3b6fd06 authored by Edward Lemur's avatar Edward Lemur Committed by LUCI CQ

Reland "my_activity.py: Run using vpython3 by default."

Fix issue with gerrit_util.py and add tests.

Change-Id: Ie523ea59ddb93cf5c7fa35f3761310ce96747720
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/2081092Reviewed-by: 's avatarAnthony Polito <apolito@google.com>
Commit-Queue: Edward Lesmes <ehmaldonado@chromium.org>
parent 45768514
......@@ -60,6 +60,12 @@ def time_sleep(seconds):
return time.sleep(seconds)
def time_time():
# Use this so that it can be mocked in tests without interfering with python
# system machinery.
return time.time()
class GerritError(Exception):
"""Exception class for errors commuicating with the gerrit-on-borg service."""
def __init__(self, http_status, message, *args, **kwargs):
......@@ -286,22 +292,24 @@ class GceAuthenticator(Authenticator):
@classmethod
def _test_is_gce(cls):
# Based on https://cloud.google.com/compute/docs/metadata#runninggce
try:
resp, _ = cls._get(cls._INFO_URL)
except (socket.error, httplib2.HttpLib2Error):
# Could not resolve URL.
resp, _ = cls._get(cls._INFO_URL)
if resp is None:
return False
return resp.get('metadata-flavor') == 'Google'
@staticmethod
def _get(url, **kwargs):
next_delay_sec = 1
for i in xrange(TRY_LIMIT):
for i in range(TRY_LIMIT):
p = urllib.parse.urlparse(url)
if p.scheme not in ('http', 'https'):
raise RuntimeError(
"Don't know how to work with protocol '%s'" % protocol)
resp, contents = httplib2.Http().request(url, 'GET', **kwargs)
try:
resp, contents = httplib2.Http().request(url, 'GET', **kwargs)
except (socket.error, httplib2.HttpLib2Error) as e:
LOGGER.debug('GET [%s] raised %s', url, e)
return None, None
LOGGER.debug('GET [%s] #%d/%d (%d)', url, i+1, TRY_LIMIT, resp.status)
if resp.status < 500:
return (resp, contents)
......@@ -313,19 +321,19 @@ class GceAuthenticator(Authenticator):
next_delay_sec, TRY_LIMIT - i - 1)
time_sleep(next_delay_sec)
next_delay_sec *= 2
return None, None
@classmethod
def _get_token_dict(cls):
if cls._token_cache:
# If it expires within 25 seconds, refresh.
if cls._token_expiration < time.time() - 25:
return cls._token_cache
# If cached token is valid for at least 25 seconds, return it.
if cls._token_cache and time_time() + 25 < cls._token_expiration:
return cls._token_cache
resp, contents = cls._get(cls._ACQUIRE_URL, headers=cls._ACQUIRE_HEADERS)
if resp.status != 200:
if resp is None or resp.status != 200:
return None
cls._token_cache = json.loads(contents)
cls._token_expiration = cls._token_cache['expires_in'] + time.time()
cls._token_expiration = cls._token_cache['expires_in'] + time_time()
return cls._token_cache
def get_auth_header(self, _host):
......
#!/usr/bin/env vpython
#!/usr/bin/env vpython3
# Copyright (c) 2012 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.
......@@ -46,6 +46,8 @@ import gerrit_util
if sys.version_info.major == 2:
logging.warning(
'Python 2 is deprecated. Run my_activity.py using vpython3.')
import urllib as urllib_parse
else:
import urllib.parse as urllib_parse
......
......@@ -9,6 +9,7 @@ from __future__ import unicode_literals
import base64
import httplib2
import json
import os
import sys
......@@ -175,6 +176,97 @@ class CookiesAuthenticatorTest(unittest.TestCase):
self.assertIsNone(auth.get_auth_email('some-review.example.com'))
class GceAuthenticatorTest(unittest.TestCase):
def setUp(self):
super(GceAuthenticatorTest, self).setUp()
mock.patch('httplib2.Http').start()
mock.patch('os.getenv', return_value=None).start()
mock.patch('gerrit_util.time_sleep').start()
mock.patch('gerrit_util.time_time').start()
self.addCleanup(mock.patch.stopall)
# GceAuthenticator has class variables that cache the results. Build a new
# class for every test to avoid inter-test dependencies.
class GceAuthenticator(gerrit_util.GceAuthenticator):
pass
self.GceAuthenticator = GceAuthenticator
def testIsGce_EnvVarSkip(self, *_mocks):
os.getenv.return_value = '1'
self.assertFalse(self.GceAuthenticator.is_gce())
os.getenv.assert_called_once_with('SKIP_GCE_AUTH_FOR_GIT')
def testIsGce_Error(self):
httplib2.Http().request.side_effect = httplib2.HttpLib2Error
self.assertFalse(self.GceAuthenticator.is_gce())
def testIsGce_500(self):
httplib2.Http().request.return_value = (mock.Mock(status=500), None)
self.assertFalse(self.GceAuthenticator.is_gce())
self.assertEqual(
[mock.call(1), mock.call(2)], gerrit_util.time_sleep.mock_calls)
def testIsGce_FailsThenSucceeds(self):
response = mock.Mock(status=200)
response.get.return_value = 'Google'
httplib2.Http().request.side_effect = [
(mock.Mock(status=500), None),
(response, 'who cares'),
]
self.assertTrue(self.GceAuthenticator.is_gce())
def testIsGce_MetadataFlavorIsNotGoogle(self):
response = mock.Mock(status=200)
response.get.return_value = None
httplib2.Http().request.return_value = (response, 'who cares')
self.assertFalse(self.GceAuthenticator.is_gce())
response.get.assert_called_once_with('metadata-flavor')
def testIsGce_ResultIsCached(self):
response = mock.Mock(status=200)
response.get.return_value = 'Google'
httplib2.Http().request.side_effect = [(response, 'who cares')]
self.assertTrue(self.GceAuthenticator.is_gce())
self.assertTrue(self.GceAuthenticator.is_gce())
httplib2.Http().request.assert_called_once()
def testGetAuthHeader_Error(self):
httplib2.Http().request.side_effect = httplib2.HttpLib2Error
self.assertIsNone(self.GceAuthenticator().get_auth_header(''))
def testGetAuthHeader_500(self):
httplib2.Http().request.return_value = (mock.Mock(status=500), None)
self.assertIsNone(self.GceAuthenticator().get_auth_header(''))
def testGetAuthHeader_Non200(self):
httplib2.Http().request.return_value = (mock.Mock(status=403), None)
self.assertIsNone(self.GceAuthenticator().get_auth_header(''))
def testGetAuthHeader_OK(self):
httplib2.Http().request.return_value = (
mock.Mock(status=200),
'{"expires_in": 125, "token_type": "TYPE", "access_token": "TOKEN"}')
gerrit_util.time_time.return_value = 0
self.assertEqual('TYPE TOKEN', self.GceAuthenticator().get_auth_header(''))
def testGetAuthHeader_Cache(self):
httplib2.Http().request.return_value = (
mock.Mock(status=200),
'{"expires_in": 125, "token_type": "TYPE", "access_token": "TOKEN"}')
gerrit_util.time_time.return_value = 0
self.assertEqual('TYPE TOKEN', self.GceAuthenticator().get_auth_header(''))
self.assertEqual('TYPE TOKEN', self.GceAuthenticator().get_auth_header(''))
httplib2.Http().request.assert_called_once()
def testGetAuthHeader_CacheOld(self):
httplib2.Http().request.return_value = (
mock.Mock(status=200),
'{"expires_in": 125, "token_type": "TYPE", "access_token": "TOKEN"}')
gerrit_util.time_time.side_effect = [0, 100, 200]
self.assertEqual('TYPE TOKEN', self.GceAuthenticator().get_auth_header(''))
self.assertEqual('TYPE TOKEN', self.GceAuthenticator().get_auth_header(''))
self.assertEqual(2, len(httplib2.Http().request.mock_calls))
class GerritUtilTest(unittest.TestCase):
def setUp(self):
super(GerritUtilTest, self).setUp()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment