1# Copyright 2017 Google LLC 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15import datetime 16import itertools 17 18import mock 19 20from google.api_core import timeout 21 22 23def test__exponential_timeout_generator_base_2(): 24 gen = timeout._exponential_timeout_generator(1.0, 60.0, 2.0, deadline=None) 25 26 result = list(itertools.islice(gen, 8)) 27 assert result == [1, 2, 4, 8, 16, 32, 60, 60] 28 29 30@mock.patch("google.api_core.datetime_helpers.utcnow", autospec=True) 31def test__exponential_timeout_generator_base_deadline(utcnow): 32 # Make each successive call to utcnow() advance one second. 33 utcnow.side_effect = [ 34 datetime.datetime.min + datetime.timedelta(seconds=n) for n in range(15) 35 ] 36 37 gen = timeout._exponential_timeout_generator(1.0, 60.0, 2.0, deadline=30.0) 38 39 result = list(itertools.islice(gen, 14)) 40 # Should grow until the cumulative time is > 30s, then start decreasing as 41 # the cumulative time approaches 60s. 42 assert result == [1, 2, 4, 8, 16, 24, 23, 22, 21, 20, 19, 18, 17, 16] 43 44 45class TestConstantTimeout(object): 46 def test_constructor(self): 47 timeout_ = timeout.ConstantTimeout() 48 assert timeout_._timeout is None 49 50 def test_constructor_args(self): 51 timeout_ = timeout.ConstantTimeout(42.0) 52 assert timeout_._timeout == 42.0 53 54 def test___str__(self): 55 timeout_ = timeout.ConstantTimeout(1) 56 assert str(timeout_) == "<ConstantTimeout timeout=1.0>" 57 58 def test_apply(self): 59 target = mock.Mock(spec=["__call__", "__name__"], __name__="target") 60 timeout_ = timeout.ConstantTimeout(42.0) 61 wrapped = timeout_(target) 62 63 wrapped() 64 65 target.assert_called_once_with(timeout=42.0) 66 67 def test_apply_passthrough(self): 68 target = mock.Mock(spec=["__call__", "__name__"], __name__="target") 69 timeout_ = timeout.ConstantTimeout(42.0) 70 wrapped = timeout_(target) 71 72 wrapped(1, 2, meep="moop") 73 74 target.assert_called_once_with(1, 2, meep="moop", timeout=42.0) 75 76 77class TestExponentialTimeout(object): 78 def test_constructor(self): 79 timeout_ = timeout.ExponentialTimeout() 80 assert timeout_._initial == timeout._DEFAULT_INITIAL_TIMEOUT 81 assert timeout_._maximum == timeout._DEFAULT_MAXIMUM_TIMEOUT 82 assert timeout_._multiplier == timeout._DEFAULT_TIMEOUT_MULTIPLIER 83 assert timeout_._deadline == timeout._DEFAULT_DEADLINE 84 85 def test_constructor_args(self): 86 timeout_ = timeout.ExponentialTimeout(1, 2, 3, 4) 87 assert timeout_._initial == 1 88 assert timeout_._maximum == 2 89 assert timeout_._multiplier == 3 90 assert timeout_._deadline == 4 91 92 def test_with_timeout(self): 93 original_timeout = timeout.ExponentialTimeout() 94 timeout_ = original_timeout.with_deadline(42) 95 assert original_timeout is not timeout_ 96 assert timeout_._initial == timeout._DEFAULT_INITIAL_TIMEOUT 97 assert timeout_._maximum == timeout._DEFAULT_MAXIMUM_TIMEOUT 98 assert timeout_._multiplier == timeout._DEFAULT_TIMEOUT_MULTIPLIER 99 assert timeout_._deadline == 42 100 101 def test___str__(self): 102 timeout_ = timeout.ExponentialTimeout(1, 2, 3, 4) 103 assert str(timeout_) == ( 104 "<ExponentialTimeout initial=1.0, maximum=2.0, multiplier=3.0, " 105 "deadline=4.0>" 106 ) 107 108 def test_apply(self): 109 target = mock.Mock(spec=["__call__", "__name__"], __name__="target") 110 timeout_ = timeout.ExponentialTimeout(1, 10, 2) 111 wrapped = timeout_(target) 112 113 wrapped() 114 target.assert_called_with(timeout=1) 115 116 wrapped() 117 target.assert_called_with(timeout=2) 118 119 wrapped() 120 target.assert_called_with(timeout=4) 121 122 def test_apply_passthrough(self): 123 target = mock.Mock(spec=["__call__", "__name__"], __name__="target") 124 timeout_ = timeout.ExponentialTimeout(42.0, 100, 2) 125 wrapped = timeout_(target) 126 127 wrapped(1, 2, meep="moop") 128 129 target.assert_called_once_with(1, 2, meep="moop", timeout=42.0) 130