| Index: recipe_engine/unittests/fetch_test.py
|
| diff --git a/recipe_engine/unittests/fetch_test.py b/recipe_engine/unittests/fetch_test.py
|
| index 9b8c38fe73ada09143e32094d438fd6166721b32..b3c7260d9ea92a8bef0b77f73e76d89388f592ef 100755
|
| --- a/recipe_engine/unittests/fetch_test.py
|
| +++ b/recipe_engine/unittests/fetch_test.py
|
| @@ -9,6 +9,7 @@ import json
|
| import os
|
| import sys
|
| import unittest
|
| +import time
|
|
|
| import test_env
|
|
|
| @@ -158,9 +159,9 @@ project_id: "foo"
|
| recipes_path: "path/to/recipes"
|
| """.lstrip()
|
| requests_get.side_effect = [
|
| - mock.Mock(text=u')]}\'\n{ "commit": "abc123" }'),
|
| - mock.Mock(text=base64.b64encode(proto_text)),
|
| - mock.Mock(content=''),
|
| + mock.Mock(text=u')]}\'\n{ "commit": "abc123" }', status_code=200),
|
| + mock.Mock(text=base64.b64encode(proto_text), status_code=200),
|
| + mock.Mock(content='', status_code=200),
|
| ]
|
|
|
| fetch.GitilesBackend().checkout(
|
| @@ -217,9 +218,9 @@ recipes_path: "path/to/recipes"
|
| ],
|
| }
|
| requests_get.side_effect = [
|
| - mock.Mock(text=u')]}\'\n{ "commit": "sha_a" }'),
|
| - mock.Mock(text=u')]}\'\n{ "commit": "sha_b" }'),
|
| - mock.Mock(text=u')]}\'\n%s' % json.dumps(log_json)),
|
| + mock.Mock(text=u')]}\'\n{ "commit": "sha_a" }', status_code=200),
|
| + mock.Mock(text=u')]}\'\n{ "commit": "sha_b" }', status_code=200),
|
| + mock.Mock(text=u')]}\'\n%s' % json.dumps(log_json), status_code=200),
|
| ]
|
|
|
| self.assertEqual(
|
| @@ -241,7 +242,8 @@ recipes_path: "path/to/recipes"
|
| 'message': 'message',
|
| }
|
| requests_get.side_effect = [
|
| - mock.Mock(text=u')]}\'\n%s' % json.dumps(revision_json)),
|
| + mock.Mock(text=u')]}\'\n%s' % json.dumps(revision_json),
|
| + status_code=200),
|
| ]
|
| result = fetch.GitilesBackend().commit_metadata(
|
| 'repo', 'revision', 'dir', allow_fetch=True)
|
| @@ -253,6 +255,56 @@ recipes_path: "path/to/recipes"
|
| mock.call('repo/+/revision?format=JSON'),
|
| ])
|
|
|
| + @mock.patch('requests.get')
|
| + def test_non_transient_error(self, requests_get):
|
| + requests_get.side_effect = [
|
| + mock.Mock(text='Not permitted.', status_code=403),
|
| + ]
|
| + with self.assertRaises(fetch.GitilesFetchError):
|
| + fetch.GitilesBackend().commit_metadata(
|
| + 'repo', 'revision', 'dir', allow_fetch=True)
|
| + requests_get.assert_has_calls([
|
| + mock.call('repo/+/revision?format=JSON'),
|
| + ])
|
| +
|
| + @mock.patch('requests.get')
|
| + @mock.patch('time.sleep')
|
| + @mock.patch('logging.exception')
|
| + def test_transient_retry(self, logging_exception, time_sleep, requests_get):
|
| + counts = {
|
| + 'sleeps': 0,
|
| + 'fails': 0,
|
| + }
|
| +
|
| + def count_sleep(delay):
|
| + counts['sleeps'] += 1
|
| + time_sleep.side_effect = count_sleep
|
| +
|
| + revision_json = {
|
| + 'author': {'email': 'author'},
|
| + 'message': 'message',
|
| + }
|
| +
|
| + # Fail transiently 4 times, but succeed on the 5th.
|
| + def transient_side_effect(*args, **kwargs):
|
| + if counts['fails'] < 4:
|
| + counts['fails'] += 1
|
| + return mock.Mock(text=u'Not permitted (%(fails)d).' % counts,
|
| + status_code=500)
|
| + return mock.Mock(text=u')]}\'\n%s' % json.dumps(revision_json),
|
| + status_code=200)
|
| + requests_get.side_effect = transient_side_effect
|
| +
|
| + result = fetch.GitilesBackend().commit_metadata(
|
| + 'repo', 'revision', 'dir', allow_fetch=True)
|
| + self.assertEqual(result, {
|
| + 'author': 'author',
|
| + 'message': 'message',
|
| + })
|
| + self.assertEqual(counts['sleeps'], 4)
|
| + requests_get.assert_has_calls([
|
| + mock.call('repo/+/revision?format=JSON'),
|
| + ] * 5)
|
|
|
| if __name__ == '__main__':
|
| unittest.main()
|
|
|