Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: third_party/twisted_8_1/twisted/test/test_memcache.py

Issue 12261012: Remove third_party/twisted_8_1 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 # Copyright (c) 2007 Twisted Matrix Laboratories.
2 # See LICENSE for details.
3
4 """
5 Test the memcache client protocol.
6 """
7
8 from twisted.protocols.memcache import MemCacheProtocol, NoSuchCommand
9 from twisted.protocols.memcache import ClientError, ServerError
10
11 from twisted.trial.unittest import TestCase
12 from twisted.test.proto_helpers import StringTransportWithDisconnection
13 from twisted.internet.task import Clock
14 from twisted.internet.defer import Deferred, gatherResults, TimeoutError
15
16
17
18 class MemCacheTestCase(TestCase):
19 """
20 Test client protocol class L{MemCacheProtocol}.
21 """
22
23 def setUp(self):
24 """
25 Create a memcache client, connect it to a string protocol, and make it
26 use a deterministic clock.
27 """
28 self.proto = MemCacheProtocol()
29 self.clock = Clock()
30 self.proto.callLater = self.clock.callLater
31 self.transport = StringTransportWithDisconnection()
32 self.transport.protocol = self.proto
33 self.proto.makeConnection(self.transport)
34
35
36 def _test(self, d, send, recv, result):
37 """
38 Shortcut method for classic tests.
39
40 @param d: the resulting deferred from the memcache command.
41 @type d: C{Deferred}
42
43 @param send: the expected data to be sent.
44 @type send: C{str}
45
46 @param recv: the data to simulate as reception.
47 @type recv: C{str}
48
49 @param result: the expected result.
50 @type result: C{any}
51 """
52 def cb(res):
53 self.assertEquals(res, result)
54 self.assertEquals(self.transport.value(), send)
55 d.addCallback(cb)
56 self.proto.dataReceived(recv)
57 return d
58
59
60 def test_get(self):
61 """
62 L{MemCacheProtocol.get} should return a L{Deferred} which is
63 called back with the value and the flag associated with the given key
64 if the server returns a successful result.
65 """
66 return self._test(self.proto.get("foo"), "get foo\r\n",
67 "VALUE foo 0 3\r\nbar\r\nEND\r\n", (0, "bar"))
68
69
70 def test_emptyGet(self):
71 """
72 Test getting a non-available key: it should succeed but return C{None}
73 as value and C{0} as flag.
74 """
75 return self._test(self.proto.get("foo"), "get foo\r\n",
76 "END\r\n", (0, None))
77
78
79 def test_set(self):
80 """
81 L{MemCacheProtocol.set} should return a L{Deferred} which is
82 called back with C{True} when the operation succeeds.
83 """
84 return self._test(self.proto.set("foo", "bar"),
85 "set foo 0 0 3\r\nbar\r\n", "STORED\r\n", True)
86
87
88 def test_add(self):
89 """
90 L{MemCacheProtocol.add} should return a L{Deferred} which is
91 called back with C{True} when the operation succeeds.
92 """
93 return self._test(self.proto.add("foo", "bar"),
94 "add foo 0 0 3\r\nbar\r\n", "STORED\r\n", True)
95
96
97 def test_replace(self):
98 """
99 L{MemCacheProtocol.replace} should return a L{Deferred} which
100 is called back with C{True} when the operation succeeds.
101 """
102 return self._test(self.proto.replace("foo", "bar"),
103 "replace foo 0 0 3\r\nbar\r\n", "STORED\r\n", True)
104
105
106 def test_errorAdd(self):
107 """
108 Test an erroneous add: if a L{MemCacheProtocol.add} is called but the
109 key already exists on the server, it returns a B{NOT STORED} answer,
110 which should callback the resulting L{Deferred} with C{False}.
111 """
112 return self._test(self.proto.add("foo", "bar"),
113 "add foo 0 0 3\r\nbar\r\n", "NOT STORED\r\n", False)
114
115
116 def test_errorReplace(self):
117 """
118 Test an erroneous replace: if a L{MemCacheProtocol.replace} is called
119 but the key doesn't exist on the server, it returns a B{NOT STORED}
120 answer, which should callback the resulting L{Deferred} with C{False}.
121 """
122 return self._test(self.proto.replace("foo", "bar"),
123 "replace foo 0 0 3\r\nbar\r\n", "NOT STORED\r\n", False)
124
125
126 def test_delete(self):
127 """
128 L{MemCacheProtocol.delete} should return a L{Deferred} which is
129 called back with C{True} when the server notifies a success.
130 """
131 return self._test(self.proto.delete("bar"), "delete bar\r\n",
132 "DELETED\r\n", True)
133
134
135 def test_errorDelete(self):
136 """
137 Test a error during a delete: if key doesn't exist on the server, it
138 returns a B{NOT FOUND} answer which should callback the resulting
139 L{Deferred} with C{False}.
140 """
141 return self._test(self.proto.delete("bar"), "delete bar\r\n",
142 "NOT FOUND\r\n", False)
143
144
145 def test_increment(self):
146 """
147 Test incrementing a variable: L{MemCacheProtocol.increment} should
148 return a L{Deferred} which is called back with the incremented value of
149 the given key.
150 """
151 return self._test(self.proto.increment("foo"), "incr foo 1\r\n",
152 "4\r\n", 4)
153
154
155 def test_decrement(self):
156 """
157 Test decrementing a variable: L{MemCacheProtocol.decrement} should
158 return a L{Deferred} which is called back with the decremented value of
159 the given key.
160 """
161 return self._test(
162 self.proto.decrement("foo"), "decr foo 1\r\n", "5\r\n", 5)
163
164
165 def test_incrementVal(self):
166 """
167 L{MemCacheProtocol.increment} takes an optional argument C{value} which
168 should replace the default value of 1 when specified.
169 """
170 return self._test(self.proto.increment("foo", 8), "incr foo 8\r\n",
171 "4\r\n", 4)
172
173
174 def test_decrementVal(self):
175 """
176 L{MemCacheProtocol.decrement} takes an optional argument C{value} which
177 should replace the default value of 1 when specified.
178 """
179 return self._test(self.proto.decrement("foo", 3), "decr foo 3\r\n",
180 "5\r\n", 5)
181
182
183 def test_stats(self):
184 """
185 Test retrieving server statistics via the L{MemCacheProtocol.stats}
186 command: it should parse the data sent by the server and call back the
187 resulting L{Deferred} with a dictionary of the received statistics.
188 """
189 return self._test(self.proto.stats(), "stats\r\n",
190 "STAT foo bar\r\nSTAT egg spam\r\nEND\r\n",
191 {"foo": "bar", "egg": "spam"})
192
193
194 def test_version(self):
195 """
196 Test version retrieval via the L{MemCacheProtocol.version} command: it
197 should return a L{Deferred} which is called back with the version sent
198 by the server.
199 """
200 return self._test(self.proto.version(), "version\r\n",
201 "VERSION 1.1\r\n", "1.1")
202
203
204 def test_flushAll(self):
205 """
206 L{MemCacheProtocol.flushAll} should return a L{Deferred} which is
207 called back with C{True} if the server acknowledges success.
208 """
209 return self._test(self.proto.flushAll(), "flush_all\r\n",
210 "OK\r\n", True)
211
212
213 def test_invalidGetResponse(self):
214 """
215 If the value returned doesn't match the expected key of the current, we
216 should get an error in L{MemCacheProtocol.dataReceived}.
217 """
218 self.proto.get("foo")
219 s = "spamegg"
220 self.assertRaises(RuntimeError,
221 self.proto.dataReceived,
222 "VALUE bar 0 %s\r\n%s\r\nEND\r\n" % (len(s), s))
223
224
225 def test_timeOut(self):
226 """
227 Test the timeout on outgoing requests: when timeout is detected, all
228 current commands should fail with a L{TimeoutError}, and the
229 connection should be closed.
230 """
231 d1 = self.proto.get("foo")
232 d2 = self.proto.get("bar")
233 d3 = Deferred()
234 self.proto.connectionLost = d3.callback
235
236 self.clock.advance(self.proto.persistentTimeOut)
237 self.assertFailure(d1, TimeoutError)
238 self.assertFailure(d2, TimeoutError)
239 def checkMessage(error):
240 self.assertEquals(str(error), "Connection timeout")
241 d1.addCallback(checkMessage)
242 return gatherResults([d1, d2, d3])
243
244
245 def test_timeoutRemoved(self):
246 """
247 When a request gets a response, no pending timeout call should remain
248 around.
249 """
250 d = self.proto.get("foo")
251
252 self.clock.advance(self.proto.persistentTimeOut - 1)
253 self.proto.dataReceived("VALUE foo 0 3\r\nbar\r\nEND\r\n")
254
255 def check(result):
256 self.assertEquals(result, (0, "bar"))
257 self.assertEquals(len(self.clock.calls), 0)
258 d.addCallback(check)
259 return d
260
261
262 def test_timeOutRaw(self):
263 """
264 Test the timeout when raw mode was started: the timeout should not be
265 reset until all the data has been received, so we can have a
266 L{TimeoutError} when waiting for raw data.
267 """
268 d1 = self.proto.get("foo")
269 d2 = Deferred()
270 self.proto.connectionLost = d2.callback
271
272 self.proto.dataReceived("VALUE foo 0 10\r\n12345")
273 self.clock.advance(self.proto.persistentTimeOut)
274 self.assertFailure(d1, TimeoutError)
275 return gatherResults([d1, d2])
276
277
278 def test_timeOutStat(self):
279 """
280 Test the timeout when stat command has started: the timeout should not
281 be reset until the final B{END} is received.
282 """
283 d1 = self.proto.stats()
284 d2 = Deferred()
285 self.proto.connectionLost = d2.callback
286
287 self.proto.dataReceived("STAT foo bar\r\n")
288 self.clock.advance(self.proto.persistentTimeOut)
289 self.assertFailure(d1, TimeoutError)
290 return gatherResults([d1, d2])
291
292
293 def test_timeoutPipelining(self):
294 """
295 When two requests are sent, a timeout call should remain around for the
296 second request, and its timeout time should be correct.
297 """
298 d1 = self.proto.get("foo")
299 d2 = self.proto.get("bar")
300 d3 = Deferred()
301 self.proto.connectionLost = d3.callback
302
303 self.clock.advance(self.proto.persistentTimeOut - 1)
304 self.proto.dataReceived("VALUE foo 0 3\r\nbar\r\nEND\r\n")
305
306 def check(result):
307 self.assertEquals(result, (0, "bar"))
308 self.assertEquals(len(self.clock.calls), 1)
309 for i in range(self.proto.persistentTimeOut):
310 self.clock.advance(1)
311 return self.assertFailure(d2, TimeoutError).addCallback(checkTime)
312 def checkTime(ignored):
313 # Check that the timeout happened C{self.proto.persistentTimeOut}
314 # after the last response
315 self.assertEquals(self.clock.seconds(),
316 2 * self.proto.persistentTimeOut - 1)
317 d1.addCallback(check)
318 return d1
319
320
321 def test_timeoutNotReset(self):
322 """
323 Check that timeout is not resetted for every command, but keep the
324 timeout from the first command without response.
325 """
326 d1 = self.proto.get("foo")
327 d3 = Deferred()
328 self.proto.connectionLost = d3.callback
329
330 self.clock.advance(self.proto.persistentTimeOut - 1)
331 d2 = self.proto.get("bar")
332 self.clock.advance(1)
333 self.assertFailure(d1, TimeoutError)
334 self.assertFailure(d2, TimeoutError)
335 return gatherResults([d1, d2, d3])
336
337
338 def test_tooLongKey(self):
339 """
340 Test that an error is raised when trying to use a too long key: the
341 called command should return a L{Deferred} which fail with a
342 L{ClientError}.
343 """
344 d1 = self.assertFailure(self.proto.set("a" * 500, "bar"), ClientError)
345 d2 = self.assertFailure(self.proto.increment("a" * 500), ClientError)
346 d3 = self.assertFailure(self.proto.get("a" * 500), ClientError)
347 d4 = self.assertFailure(self.proto.append("a" * 500, "bar"), ClientError )
348 d5 = self.assertFailure(self.proto.prepend("a" * 500, "bar"), ClientErro r)
349 return gatherResults([d1, d2, d3, d4, d5])
350
351
352 def test_invalidCommand(self):
353 """
354 When an unknown command is sent directly (not through public API), the
355 server answers with an B{ERROR} token, and the command should fail with
356 L{NoSuchCommand}.
357 """
358 d = self.proto._set("egg", "foo", "bar", 0, 0, "")
359 self.assertEquals(self.transport.value(), "egg foo 0 0 3\r\nbar\r\n")
360 self.assertFailure(d, NoSuchCommand)
361 self.proto.dataReceived("ERROR\r\n")
362 return d
363
364
365 def test_clientError(self):
366 """
367 Test the L{ClientError} error: when the server send a B{CLIENT_ERROR}
368 token, the originating command should fail with L{ClientError}, and the
369 error should contain the text sent by the server.
370 """
371 a = "eggspamm"
372 d = self.proto.set("foo", a)
373 self.assertEquals(self.transport.value(),
374 "set foo 0 0 8\r\neggspamm\r\n")
375 self.assertFailure(d, ClientError)
376 def check(err):
377 self.assertEquals(str(err), "We don't like egg and spam")
378 d.addCallback(check)
379 self.proto.dataReceived("CLIENT_ERROR We don't like egg and spam\r\n")
380 return d
381
382
383 def test_serverError(self):
384 """
385 Test the L{ServerError} error: when the server send a B{SERVER_ERROR}
386 token, the originating command should fail with L{ServerError}, and the
387 error should contain the text sent by the server.
388 """
389 a = "eggspamm"
390 d = self.proto.set("foo", a)
391 self.assertEquals(self.transport.value(),
392 "set foo 0 0 8\r\neggspamm\r\n")
393 self.assertFailure(d, ServerError)
394 def check(err):
395 self.assertEquals(str(err), "zomg")
396 d.addCallback(check)
397 self.proto.dataReceived("SERVER_ERROR zomg\r\n")
398 return d
399
400
401 def test_unicodeKey(self):
402 """
403 Using a non-string key as argument to commands should raise an error.
404 """
405 d1 = self.assertFailure(self.proto.set(u"foo", "bar"), ClientError)
406 d2 = self.assertFailure(self.proto.increment(u"egg"), ClientError)
407 d3 = self.assertFailure(self.proto.get(1), ClientError)
408 d4 = self.assertFailure(self.proto.delete(u"bar"), ClientError)
409 d5 = self.assertFailure(self.proto.append(u"foo", "bar"), ClientError)
410 d6 = self.assertFailure(self.proto.prepend(u"foo", "bar"), ClientError)
411 return gatherResults([d1, d2, d3, d4, d5, d6])
412
413
414 def test_unicodeValue(self):
415 """
416 Using a non-string value should raise an error.
417 """
418 return self.assertFailure(self.proto.set("foo", u"bar"), ClientError)
419
420
421 def test_pipelining(self):
422 """
423 Test that multiple requests can be sent subsequently to the server, and
424 that the protocol order the responses correctly and dispatch to the
425 corresponding client command.
426 """
427 d1 = self.proto.get("foo")
428 d1.addCallback(self.assertEquals, (0, "bar"))
429 d2 = self.proto.set("bar", "spamspamspam")
430 d2.addCallback(self.assertEquals, True)
431 d3 = self.proto.get("egg")
432 d3.addCallback(self.assertEquals, (0, "spam"))
433 self.assertEquals(self.transport.value(),
434 "get foo\r\nset bar 0 0 12\r\nspamspamspam\r\nget egg\r\n")
435 self.proto.dataReceived("VALUE foo 0 3\r\nbar\r\nEND\r\n"
436 "STORED\r\n"
437 "VALUE egg 0 4\r\nspam\r\nEND\r\n")
438 return gatherResults([d1, d2, d3])
439
440
441 def test_getInChunks(self):
442 """
443 If the value retrieved by a C{get} arrive in chunks, the protocol
444 should be able to reconstruct it and to produce the good value.
445 """
446 d = self.proto.get("foo")
447 d.addCallback(self.assertEquals, (0, "0123456789"))
448 self.assertEquals(self.transport.value(), "get foo\r\n")
449 self.proto.dataReceived("VALUE foo 0 10\r\n0123456")
450 self.proto.dataReceived("789")
451 self.proto.dataReceived("\r\nEND")
452 self.proto.dataReceived("\r\n")
453 return d
454
455
456 def test_append(self):
457 """
458 L{MemCacheProtocol.append} behaves like a L{MemCacheProtocol.set}
459 method: it should return a L{Deferred} which is called back with
460 C{True} when the operation succeeds.
461 """
462 return self._test(self.proto.append("foo", "bar"),
463 "append foo 0 0 3\r\nbar\r\n", "STORED\r\n", True)
464
465
466 def test_prepend(self):
467 """
468 L{MemCacheProtocol.prepend} behaves like a L{MemCacheProtocol.set}
469 method: it should return a L{Deferred} which is called back with
470 C{True} when the operation succeeds.
471 """
472 return self._test(self.proto.prepend("foo", "bar"),
473 "prepend foo 0 0 3\r\nbar\r\n", "STORED\r\n", True)
474
475
476 def test_gets(self):
477 """
478 L{MemCacheProtocol.get} should handle an additional cas result when
479 C{withIdentifier} is C{True} and forward it in the resulting
480 L{Deferred}.
481 """
482 return self._test(self.proto.get("foo", True), "gets foo\r\n",
483 "VALUE foo 0 3 1234\r\nbar\r\nEND\r\n", (0, "1234", "bar"))
484
485
486 def test_emptyGets(self):
487 """
488 Test getting a non-available key with gets: it should succeed but
489 return C{None} as value, C{0} as flag and an empty cas value.
490 """
491 return self._test(self.proto.get("foo", True), "gets foo\r\n",
492 "END\r\n", (0, "", None))
493
494
495 def test_checkAndSet(self):
496 """
497 L{MemCacheProtocol.checkAndSet} passes an additional cas identifier that the
498 server should handle to check if the data has to be updated.
499 """
500 return self._test(self.proto.checkAndSet("foo", "bar", cas="1234"),
501 "cas foo 0 0 3 1234\r\nbar\r\n", "STORED\r\n", True)
502
503
504 def test_casUnknowKey(self):
505 """
506 When L{MemCacheProtocol.checkAndSet} response is C{EXISTS}, the resultin g
507 L{Deferred} should fire with C{False}.
508 """
509 return self._test(self.proto.checkAndSet("foo", "bar", cas="1234"),
510 "cas foo 0 0 3 1234\r\nbar\r\n", "EXISTS\r\n", False)
OLDNEW
« no previous file with comments | « third_party/twisted_8_1/twisted/test/test_manhole.py ('k') | third_party/twisted_8_1/twisted/test/test_modules.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698