OLD | NEW |
(Empty) | |
| 1 # Copyright 2016 Google Inc. All Rights Reserved. |
| 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 |
| 15 from __future__ import absolute_import |
| 16 |
| 17 import collections |
| 18 import datetime |
| 19 import unittest2 |
| 20 |
| 21 from expects import be, be_a, be_none, equal, expect, raise_error |
| 22 |
| 23 from google.api.control import caches, report_request |
| 24 |
| 25 |
| 26 _TEST_NUM_ENTRIES = 3 # arbitrary |
| 27 |
| 28 |
| 29 class TestDequeOutLRUCache(unittest2.TestCase): |
| 30 |
| 31 def test_constructor_should_set_up_a_default_deque(self): |
| 32 c = caches.DequeOutLRUCache(_TEST_NUM_ENTRIES) |
| 33 expect(c.out_deque).to(be_a(collections.deque)) |
| 34 |
| 35 def test_constructor_should_fail_on_bad_deques(self): |
| 36 testf = lambda: caches.DequeOutLRUCache(_TEST_NUM_ENTRIES, |
| 37 out_deque=object()) |
| 38 expect(testf).to(raise_error(ValueError)) |
| 39 |
| 40 def test_constructor_should_accept_deques(self): |
| 41 a_deque = collections.deque() |
| 42 c = caches.DequeOutLRUCache(_TEST_NUM_ENTRIES, out_deque=a_deque) |
| 43 expect(c.out_deque).to(be(a_deque)) |
| 44 |
| 45 def test_lru(self): |
| 46 lru_limit = 2 |
| 47 cache = caches.DequeOutLRUCache(lru_limit) |
| 48 cache[1] = 1 |
| 49 cache[2] = 2 |
| 50 cache[3] = 3 |
| 51 expect(len(cache)).to(equal(2)) |
| 52 expect(cache[2]).to(equal(2)) |
| 53 expect(cache[3]).to(equal(3)) |
| 54 expect(cache.get(1)).to(be_none) |
| 55 expect(len(cache.out_deque)).to(be(1)) |
| 56 cache[4] = 4 |
| 57 expect(cache.get(2)).to(be_none) |
| 58 expect(len(cache.out_deque)).to(be(2)) |
| 59 |
| 60 |
| 61 class _Timer(object): |
| 62 def __init__(self, auto=False): |
| 63 self.auto = auto |
| 64 self.time = 0 |
| 65 |
| 66 def __call__(self): |
| 67 if self.auto: |
| 68 self.tick() |
| 69 return self.time |
| 70 |
| 71 def tick(self): |
| 72 self.time += 1 |
| 73 |
| 74 |
| 75 _TEST_TTL = 3 # arbitrary |
| 76 |
| 77 |
| 78 class TestDequeOutTTLCache(unittest2.TestCase): |
| 79 # pylint: disable=fixme |
| 80 # |
| 81 # TODO: add a ttl test based on the one in cachetools testsuite |
| 82 |
| 83 def test_constructor_should_set_up_a_default_deque(self): |
| 84 c = caches.DequeOutTTLCache(_TEST_NUM_ENTRIES, _TEST_TTL) |
| 85 expect(c.out_deque).to(be_a(collections.deque)) |
| 86 |
| 87 def test_constructor_should_fail_on_bad_deques(self): |
| 88 testf = lambda: caches.DequeOutTTLCache(_TEST_NUM_ENTRIES, _TEST_TTL, |
| 89 out_deque=object()) |
| 90 expect(testf).to(raise_error(ValueError)) |
| 91 |
| 92 def test_constructor_should_accept_deques(self): |
| 93 a_deque = collections.deque() |
| 94 c = caches.DequeOutTTLCache(3, 3, out_deque=a_deque) |
| 95 expect(c.out_deque).to(be(a_deque)) |
| 96 |
| 97 def test_lru(self): |
| 98 lru_limit = 2 |
| 99 expiry = 100 |
| 100 cache = caches.DequeOutTTLCache(lru_limit, expiry) |
| 101 cache[1] = 1 |
| 102 cache[2] = 2 |
| 103 cache[3] = 3 |
| 104 expect(len(cache)).to(equal(2)) |
| 105 expect(cache[2]).to(equal(2)) |
| 106 expect(cache[3]).to(equal(3)) |
| 107 expect(cache.get(1)).to(be_none) |
| 108 expect(len(cache.out_deque)).to(be(1)) |
| 109 cache[4] = 4 |
| 110 expect(cache.get(2)).to(be_none) |
| 111 expect(len(cache.out_deque)).to(be(2)) |
| 112 |
| 113 def test_ttl(self): |
| 114 cache = caches.DequeOutTTLCache(2, ttl=1, timer=_Timer()) |
| 115 expect(cache.timer()).to(equal(0)) |
| 116 expect(cache.ttl).to(equal(1)) |
| 117 |
| 118 cache[1] = 1 |
| 119 expect(set(cache)).to(equal({1})) |
| 120 expect(len(cache)).to(equal(1)) |
| 121 expect(cache[1]).to(equal(1)) |
| 122 |
| 123 cache.timer.tick() |
| 124 expect(set(cache)).to(equal({1})) |
| 125 expect(len(cache)).to(equal(1)) |
| 126 expect(cache[1]).to(equal(1)) |
| 127 |
| 128 cache[2] = 2 |
| 129 expect(set(cache)).to(equal({1, 2})) |
| 130 expect(len(cache)).to(equal(2)) |
| 131 expect(cache[1]).to(equal(1)) |
| 132 expect(cache[2]).to(equal(2)) |
| 133 |
| 134 cache.timer.tick() |
| 135 expect(set(cache)).to(equal({2})) |
| 136 expect(len(cache)).to(equal(1)) |
| 137 expect(cache[2]).to(equal(2)) |
| 138 expect(cache.get(1)).to(be_none) |
| 139 |
| 140 |
| 141 class _DateTimeTimer(object): |
| 142 def __init__(self, auto=False): |
| 143 self.auto = auto |
| 144 self.time = datetime.datetime(1970, 1, 1) |
| 145 |
| 146 def __call__(self): |
| 147 if self.auto: |
| 148 self.tick() |
| 149 return self.time |
| 150 |
| 151 def tick(self): |
| 152 self.time += datetime.timedelta(seconds=1) |
| 153 |
| 154 |
| 155 class TestCreate(unittest2.TestCase): |
| 156 |
| 157 def test_should_fail_if_bad_options_are_used(self): |
| 158 should_fail = [ |
| 159 lambda: caches.create(object()), |
| 160 ] |
| 161 for testf in should_fail: |
| 162 expect(testf).to(raise_error(ValueError)) |
| 163 |
| 164 def test_should_return_none_if_options_is_none(self): |
| 165 expect(caches.create(None)).to(be_none) |
| 166 |
| 167 def test_should_return_none_if_cache_size_not_positive(self): |
| 168 should_be_none = [ |
| 169 lambda: caches.create(caches.CheckOptions(num_entries=0)), |
| 170 lambda: caches.create(caches.CheckOptions(num_entries=-1)), |
| 171 lambda: caches.create(caches.ReportOptions(num_entries=0)), |
| 172 lambda: caches.create(caches.ReportOptions(num_entries=-1)), |
| 173 ] |
| 174 for testf in should_be_none: |
| 175 expect(testf()).to(be_none) |
| 176 |
| 177 def test_should_return_ttl_cache_if_flush_interval_is_positive(self): |
| 178 delta = datetime.timedelta(seconds=1) |
| 179 should_be_ttl = [ |
| 180 lambda timer: caches.create( |
| 181 caches.CheckOptions(num_entries=1, flush_interval=delta), |
| 182 timer=timer |
| 183 ), |
| 184 lambda timer: caches.create( |
| 185 caches.ReportOptions(num_entries=1, flush_interval=delta), |
| 186 timer=timer |
| 187 ), |
| 188 ] |
| 189 for testf in should_be_ttl: |
| 190 timer = _DateTimeTimer() |
| 191 sync_cache = testf(timer) |
| 192 expect(sync_cache).to(be_a(caches.LockedObject)) |
| 193 with sync_cache as cache: |
| 194 expect(cache).to(be_a(caches.DequeOutTTLCache)) |
| 195 expect(cache.timer()).to(equal(0)) |
| 196 cache[1] = 1 |
| 197 expect(set(cache)).to(equal({1})) |
| 198 expect(cache.get(1)).to(equal(1)) |
| 199 timer.tick() |
| 200 expect(cache.get(1)).to(equal(1)) |
| 201 timer.tick() |
| 202 expect(cache.get(1)).to(be_none) |
| 203 |
| 204 # Is still TTL without the custom timer |
| 205 sync_cache = testf(None) |
| 206 expect(sync_cache).to(be_a(caches.LockedObject)) |
| 207 with sync_cache as cache: |
| 208 expect(cache).to(be_a(caches.DequeOutTTLCache)) |
| 209 |
| 210 def test_should_return_a_lru_cache_if_flush_interval_is_negative(self): |
| 211 delta = datetime.timedelta(seconds=-1) |
| 212 should_be_ttl = [ |
| 213 lambda: caches.create( |
| 214 caches.CheckOptions(num_entries=1, flush_interval=delta), |
| 215 ), |
| 216 lambda: caches.create( |
| 217 caches.ReportOptions(num_entries=1, flush_interval=delta)), |
| 218 ] |
| 219 for testf in should_be_ttl: |
| 220 sync_cache = testf() |
| 221 expect(sync_cache).to(be_a(caches.LockedObject)) |
| 222 with sync_cache as cache: |
| 223 expect(cache).to(be_a(caches.DequeOutLRUCache)) |
| 224 |
| 225 |
| 226 class TestReportOptions(unittest2.TestCase): |
| 227 |
| 228 def test_should_create_with_defaults(self): |
| 229 options = caches.ReportOptions() |
| 230 expect(options.num_entries).to(equal( |
| 231 caches.ReportOptions.DEFAULT_NUM_ENTRIES)) |
| 232 expect(options.flush_interval).to(equal( |
| 233 caches.ReportOptions.DEFAULT_FLUSH_INTERVAL)) |
| 234 |
| 235 |
| 236 class TestCheckOptions(unittest2.TestCase): |
| 237 AN_INTERVAL = datetime.timedelta(milliseconds=2) |
| 238 A_LOWER_INTERVAL = datetime.timedelta(milliseconds=1) |
| 239 |
| 240 def test_should_create_with_defaults(self): |
| 241 options = caches.CheckOptions() |
| 242 expect(options.num_entries).to(equal( |
| 243 caches.CheckOptions.DEFAULT_NUM_ENTRIES)) |
| 244 expect(options.flush_interval).to(equal( |
| 245 caches.CheckOptions.DEFAULT_FLUSH_INTERVAL)) |
| 246 expect(options.expiration).to(equal( |
| 247 caches.CheckOptions.DEFAULT_EXPIRATION)) |
| 248 |
| 249 def test_should_ignores_lower_expiration(self): |
| 250 wanted_expiration = ( |
| 251 self.AN_INTERVAL + datetime.timedelta(milliseconds=1)) |
| 252 options = caches.CheckOptions(flush_interval=self.AN_INTERVAL, |
| 253 expiration=self.A_LOWER_INTERVAL) |
| 254 expect(options.flush_interval).to(equal(self.AN_INTERVAL)) |
| 255 expect(options.expiration).to(equal(wanted_expiration)) |
| 256 expect(options.expiration).not_to(equal(self.A_LOWER_INTERVAL)) |
OLD | NEW |