]> git.saurik.com Git - redis.git/blob - client-libraries/cpp/test_client.cpp
ignore gcc warning about write() return code not checked. It is esplicitily this...
[redis.git] / client-libraries / cpp / test_client.cpp
1 #include "redisclient.h"
2
3 #include <iostream>
4
5 using namespace std;
6
7 #define ASSERT_EQUAL(x,y) assert_equal(x, y, __LINE__)
8 #define ASSERT_NOT_EQUAL(x,y) assert_not_equal(x, y, __LINE__)
9 #define ASSERT_GT(x,y) assert_gt(x, y, __LINE__)
10
11 template <typename T>
12 void assert_equal(const T & actual, const T & expected, int lineno)
13 {
14 #ifndef NDEBUG
15 cerr << "assert_equal('" << expected << "', '" << actual << "')" << endl;
16 #endif
17
18 if (expected != actual)
19 {
20 cerr << "expected '" << expected << "' got '" << actual << "'" << endl
21 << "failing test called from line " << lineno << endl;
22
23 exit(1);
24 }
25
26 #ifndef NDEBUG
27 cerr << "... OK" << endl;
28 #endif
29 }
30
31 template <typename T>
32 void assert_not_equal(const T & a, const T & b, int lineno)
33 {
34 if (a == b)
35 {
36 cerr << "expected inequality" << endl
37 << "failing test called from line " << lineno << endl;
38
39 exit(1);
40 }
41 }
42
43 template <typename T>
44 void assert_gt(const T & a, const T & b, int lineno)
45 {
46 #ifndef NDEBUG
47 cerr << "assert_gt('" << a << "', '" << b << "')" << endl;
48 #endif
49
50 if (a <= b)
51 {
52 cerr << "expected '" << a << "' > '" << b << "'" << endl
53 << "failing test called from line " << lineno << endl;
54
55 exit(1);
56 }
57
58 #ifndef NDEBUG
59 cerr << "... OK" << endl;
60 #endif
61 }
62
63 void test(const string & name)
64 {
65 #ifndef NDEBUG
66 cerr << "------------------------------" << endl
67 << "starting test: " << name << endl;
68 #endif
69 }
70
71 int main(int argc, char ** argv)
72 {
73 try
74 {
75 redis::client c;
76
77 // Test on high number databases
78
79 c.select(14);
80 c.flushdb();
81
82 c.select(15);
83 c.flushdb();
84
85 string foo("foo"), bar("bar"), baz("baz"), buz("buz"), goo("goo");
86
87 test("auth");
88 {
89 // TODO ... needs a conf for redis-server
90 }
91
92 test("info");
93 {
94 // doesn't throw? then, has valid numbers and known info-keys.
95 redis::server_info info;
96 c.info(info);
97 }
98
99 test("set, get");
100 {
101 c.set(foo, bar);
102 ASSERT_EQUAL(c.get(foo), bar);
103 }
104
105 test("getset");
106 {
107 ASSERT_EQUAL(c.getset(foo, baz), bar);
108 ASSERT_EQUAL(c.get(foo), baz);
109 }
110
111 test("mget");
112 {
113 string x_val("hello"), y_val("world");
114 c.set("x", x_val);
115 c.set("y", y_val);
116 redis::client::string_vector keys;
117 keys.push_back("x");
118 keys.push_back("y");
119 redis::client::string_vector vals;
120 c.mget(keys, vals);
121 ASSERT_EQUAL(vals.size(), size_t(2));
122 ASSERT_EQUAL(vals[0], x_val);
123 ASSERT_EQUAL(vals[1], y_val);
124 }
125
126 test("setnx");
127 {
128 ASSERT_EQUAL(c.setnx(foo, bar), false);
129 ASSERT_EQUAL(c.setnx(buz, baz), true);
130 ASSERT_EQUAL(c.get(buz), baz);
131 }
132
133 test("incr");
134 {
135 ASSERT_EQUAL(c.incr("goo"), 1L);test("nonexistent (0) -> 1");
136 ASSERT_EQUAL(c.incr("goo"), 2L);test("1->2");
137 }
138
139 test("decr");
140 {
141 ASSERT_EQUAL(c.decr("goo"), 1L);test("2->1");
142 ASSERT_EQUAL(c.decr("goo"), 0L);test("1->0");
143 }
144
145 test("incrby");
146 {
147 ASSERT_EQUAL(c.incrby("goo", 3), 3L);test("0->3");
148 ASSERT_EQUAL(c.incrby("goo", 2), 5L);test("3->5");
149 }
150
151 test("exists");
152 {
153 ASSERT_EQUAL(c.exists("goo"), true);
154 }
155
156 test("del");
157 {
158 c.del("goo");
159 ASSERT_EQUAL(c.exists("goo"), false);
160 }
161
162 test("type (basic)");
163 {
164 ASSERT_EQUAL(c.type(goo), redis::client::datatype_none);test("we deleted it");
165 c.set(goo, "redis");
166 ASSERT_EQUAL(c.type(goo), redis::client::datatype_string);
167 }
168
169 test("keys");
170 {
171 redis::client::string_vector keys;
172 ASSERT_EQUAL(c.keys("*oo", keys), 2L);
173 ASSERT_EQUAL(keys.size(), 2UL);
174 ASSERT_EQUAL(keys[0], foo);
175 ASSERT_EQUAL(keys[1], goo);
176 }
177
178 test("randomkey");
179 {
180 ASSERT_GT(c.randomkey().size(), 0UL);
181 }
182
183 test("rename");
184 {
185 ASSERT_EQUAL(c.exists("foo"), true);
186 ASSERT_EQUAL(c.exists("doo"), false);
187 c.rename("foo", "doo");
188 ASSERT_EQUAL(c.exists("foo"), false);
189 ASSERT_EQUAL(c.exists("doo"), true);
190 }
191
192 test("renamenx");
193 {
194 ASSERT_EQUAL(c.exists("doo"), true);
195 ASSERT_EQUAL(c.exists("foo"), false);
196 ASSERT_EQUAL(c.renamenx("doo", "foo"), true);
197 ASSERT_EQUAL(c.exists("doo"), false);
198 ASSERT_EQUAL(c.exists("foo"), true);
199 ASSERT_EQUAL(c.renamenx("goo", "foo"), false);
200 ASSERT_EQUAL(c.exists("foo"), true);
201 ASSERT_EQUAL(c.exists("goo"), true);
202 }
203
204 test("dbsize");
205 {
206 ASSERT_GT(c.dbsize(), 0L);
207 }
208
209 test("expire");
210 {
211 c.expire("goo", 1);
212 #ifndef NDEBUG
213 cerr << "please wait a few seconds.." << endl;
214 #endif
215 sleep(2);
216 ASSERT_EQUAL(c.exists("goo"), false);
217 }
218
219 test("rpush");
220 {
221 ASSERT_EQUAL(c.exists("list1"), false);
222 c.rpush("list1", "val1");
223 ASSERT_EQUAL(c.llen("list1"), 1L);
224 ASSERT_EQUAL(c.type("list1"), redis::client::datatype_list);
225 c.rpush("list1", "val2");
226 ASSERT_EQUAL(c.llen("list1"), 2L);
227 ASSERT_EQUAL(c.lindex("list1", 0), string("val1"));
228 ASSERT_EQUAL(c.lindex("list1", 1), string("val2"));
229 }
230
231 test("lpush");
232 {
233 c.del("list1");
234 ASSERT_EQUAL(c.exists("list1"), false);
235 c.lpush("list1", "val1");
236 ASSERT_EQUAL(c.type("list1"), redis::client::datatype_list);
237 ASSERT_EQUAL(c.llen("list1"), 1L);
238 c.lpush("list1", "val2");
239 ASSERT_EQUAL(c.llen("list1"), 2L);
240 ASSERT_EQUAL(c.lindex("list1", 0), string("val2"));
241 ASSERT_EQUAL(c.lindex("list1", 1), string("val1"));
242 }
243
244 test("llen");
245 {
246 c.del("list1");
247 ASSERT_EQUAL(c.exists("list1"), false);
248 ASSERT_EQUAL(c.llen("list1"), 0L);
249 c.lpush("list1", "x");
250 ASSERT_EQUAL(c.llen("list1"), 1L);
251 c.lpush("list1", "y");
252 ASSERT_EQUAL(c.llen("list1"), 2L);
253 }
254
255 test("lrange");
256 {
257 ASSERT_EQUAL(c.exists("list1"), true);
258 ASSERT_EQUAL(c.llen("list1"), 2L);
259 redis::client::string_vector vals;
260 ASSERT_EQUAL(c.lrange("list1", 0, -1, vals), 2L);
261 ASSERT_EQUAL(vals.size(), 2UL);
262 ASSERT_EQUAL(vals[0], string("y"));
263 ASSERT_EQUAL(vals[1], string("x"));
264 }
265
266 test("lrange with subset of full list");
267 {
268 ASSERT_EQUAL(c.exists("list1"), true);
269 ASSERT_EQUAL(c.llen("list1"), 2L);
270 redis::client::string_vector vals;
271 ASSERT_EQUAL(c.lrange("list1", 0, 1, vals), 2L); // inclusive, so entire list
272 ASSERT_EQUAL(vals.size(), 2UL);
273 ASSERT_EQUAL(vals[0], string("y"));
274 ASSERT_EQUAL(vals[1], string("x"));
275
276 redis::client::string_vector vals2;
277 ASSERT_EQUAL(c.lrange("list1", 0, 0, vals2), 1L); // inclusive, so first item
278 ASSERT_EQUAL(vals2.size(), 1UL);
279 ASSERT_EQUAL(vals2[0], string("y"));
280
281 redis::client::string_vector vals3;
282 ASSERT_EQUAL(c.lrange("list1", -1, -1, vals3), 1L); // inclusive, so first item
283 ASSERT_EQUAL(vals3.size(), 1UL);
284 ASSERT_EQUAL(vals3[0], string("x"));
285 }
286
287 test("get_list");
288 {
289 ASSERT_EQUAL(c.exists("list1"), true);
290 ASSERT_EQUAL(c.llen("list1"), 2L);
291 redis::client::string_vector vals;
292 ASSERT_EQUAL(c.get_list("list1", vals), 2L);
293 ASSERT_EQUAL(vals.size(), 2UL);
294 ASSERT_EQUAL(vals[0], string("y"));
295 ASSERT_EQUAL(vals[1], string("x"));
296 }
297
298 test("ltrim");
299 {
300 ASSERT_EQUAL(c.exists("list1"), true);
301 ASSERT_EQUAL(c.llen("list1"), 2L);
302 c.ltrim("list1", 0, 0);
303 ASSERT_EQUAL(c.exists("list1"), true);
304 ASSERT_EQUAL(c.llen("list1"), 1L);
305 redis::client::string_vector vals;
306 ASSERT_EQUAL(c.get_list("list1", vals), 1L);
307 ASSERT_EQUAL(vals[0], string("y"));
308 }
309
310 test("lindex");
311 {
312 ASSERT_EQUAL(c.lindex("list1", 0), string("y"));
313 c.rpush("list1", "x");
314 ASSERT_EQUAL(c.llen("list1"), 2L);
315 ASSERT_EQUAL(c.lindex("list1", -1), string("x"));
316 ASSERT_EQUAL(c.lindex("list1", 1), string("x"));
317 }
318
319 test("lset");
320 {
321 c.lset("list1", 1, "z");
322 ASSERT_EQUAL(c.lindex("list1", 1), string("z"));
323 ASSERT_EQUAL(c.llen("list1"), 2L);
324 }
325
326 test("lrem");
327 {
328 c.lrem("list1", 1, "z");
329 ASSERT_EQUAL(c.llen("list1"), 1L);
330 ASSERT_EQUAL(c.lindex("list1", 0), string("y"));
331
332 // list1 = [ y ]
333 ASSERT_EQUAL(c.lrem("list1", 0, "q"), 0L);
334
335 c.rpush("list1", "z");
336 c.rpush("list1", "z");
337 c.rpush("list1", "z");
338 c.rpush("list1", "a");
339 // list1 = [ y, z, z, z, a ]
340 ASSERT_EQUAL(c.lrem("list1", 2, "z"), 2L);
341 // list1 = [ y, z, a ]
342 ASSERT_EQUAL(c.llen("list1"), 3L);
343 ASSERT_EQUAL(c.lindex("list1", 0), string("y"));
344 ASSERT_EQUAL(c.lindex("list1", 1), string("z"));
345 ASSERT_EQUAL(c.lindex("list1", 2), string("a"));
346
347 c.rpush("list1", "z");
348 // list1 = [ y, z, a, z ]
349 ASSERT_EQUAL(c.lrem("list1", -1, "z"), 1L); // <0 => rm R to L
350 // list1 = [ y, z, a ]
351 ASSERT_EQUAL(c.llen("list1"), 3L);
352 ASSERT_EQUAL(c.lindex("list1", 0), string("y"));
353 ASSERT_EQUAL(c.lindex("list1", 1), string("z"));
354 ASSERT_EQUAL(c.lindex("list1", 2), string("a"));
355
356 // list1 = [ y, z, a ]
357 // try to remove 5 'a's but there's only 1 ... no problem.
358 ASSERT_EQUAL(c.lrem("list1", 5, "a"), 1L);
359 // list1 = [ y, z ]
360 ASSERT_EQUAL(c.llen("list1"), 2L);
361 ASSERT_EQUAL(c.lindex("list1", 0), string("y"));
362 ASSERT_EQUAL(c.lindex("list1", 1), string("z"));
363 }
364
365 test("lrem_exact");
366 {
367 // list1 = [ y, z ]
368
369 // try to remove 5 'z's but there's only 1 ... now it's a problem.
370
371 bool threw = false;
372
373 try
374 {
375 c.lrem_exact("list1", 5, "z");
376 }
377 catch (redis::value_error & e)
378 {
379 threw = true;
380 }
381
382 ASSERT_EQUAL(threw, true);
383
384 // This DOES remove the one 'z' though
385 // list1 = [ y ]
386
387 ASSERT_EQUAL(c.llen("list1"), 1L);
388 ASSERT_EQUAL(c.lindex("list1", 0), string("y"));
389 }
390
391 test("lpop");
392 {
393 ASSERT_EQUAL(c.lpop("list1"), string("y"));
394 // list1 = []
395 ASSERT_EQUAL(c.lpop("list1"), redis::client::missing_value);
396 }
397
398 test("rpop");
399 {
400 c.rpush("list1", "hello");
401 c.rpush("list1", "world");
402 ASSERT_EQUAL(c.rpop("list1"), string("world"));
403 ASSERT_EQUAL(c.rpop("list1"), string("hello"));
404 ASSERT_EQUAL(c.lpop("list1"), redis::client::missing_value);
405 }
406
407 test("sadd");
408 {
409 c.sadd("set1", "sval1");
410 ASSERT_EQUAL(c.exists("set1"), true);
411 ASSERT_EQUAL(c.type("set1"), redis::client::datatype_set);
412 ASSERT_EQUAL(c.sismember("set1", "sval1"), true);
413 }
414
415 test("srem");
416 {
417 c.srem("set1", "sval1");
418 ASSERT_EQUAL(c.exists("set1"), true);
419 ASSERT_EQUAL(c.type("set1"), redis::client::datatype_set);
420 ASSERT_EQUAL(c.sismember("set1", "sval1"), false);
421 }
422
423 test("smove");
424 {
425 c.sadd("set1", "hi");
426 // set1 = { hi }
427 ASSERT_EQUAL(c.exists("set2"), false);
428 c.smove("set1", "set2", "hi");
429 ASSERT_EQUAL(c.sismember("set1", "hi"), false);
430 ASSERT_EQUAL(c.sismember("set2", "hi"), true);
431 }
432
433 test("scard");
434 {
435 ASSERT_EQUAL(c.scard("set1"), 0L);
436 ASSERT_EQUAL(c.scard("set2"), 1L);
437 }
438
439 test("sismember");
440 {
441 // see above
442 }
443
444 test("smembers");
445 {
446 c.sadd("set2", "bye");
447 redis::client::string_set members;
448 ASSERT_EQUAL(c.smembers("set2", members), 2L);
449 ASSERT_EQUAL(members.size(), 2UL);
450 ASSERT_NOT_EQUAL(members.find("hi"), members.end());
451 ASSERT_NOT_EQUAL(members.find("bye"), members.end());
452 }
453
454 test("sinter");
455 {
456 c.sadd("set3", "bye");
457 c.sadd("set3", "bye2");
458 redis::client::string_vector keys;
459 keys.push_back("set2");
460 keys.push_back("set3");
461 redis::client::string_set intersection;
462 ASSERT_EQUAL(c.sinter(keys, intersection), 1L);
463 ASSERT_EQUAL(intersection.size(), 1UL);
464 ASSERT_NOT_EQUAL(intersection.find("bye"), intersection.end());
465 }
466
467 test("sinterstore");
468 {
469 c.sadd("seta", "1");
470 c.sadd("seta", "2");
471 c.sadd("seta", "3");
472
473 c.sadd("setb", "2");
474 c.sadd("setb", "3");
475 c.sadd("setb", "4");
476
477 redis::client::string_vector keys;
478 keys.push_back("seta");
479 keys.push_back("setb");
480
481 c.sinterstore("setc", keys);
482
483 redis::client::string_set members;
484 ASSERT_EQUAL(c.smembers("setc", members), 2L);
485 ASSERT_EQUAL(members.size(), 2UL);
486 ASSERT_NOT_EQUAL(members.find("2"), members.end());
487 ASSERT_NOT_EQUAL(members.find("3"), members.end());
488 }
489
490 test("sunion");
491 {
492 c.sadd("setd", "1");
493 c.sadd("sete", "2");
494 redis::client::string_vector keys;
495 keys.push_back("setd");
496 keys.push_back("sete");
497 redis::client::string_set a_union;
498 ASSERT_EQUAL(c.sunion(keys, a_union), 2L);
499 ASSERT_EQUAL(a_union.size(), 2UL);
500 ASSERT_NOT_EQUAL(a_union.find("1"), a_union.end());
501 ASSERT_NOT_EQUAL(a_union.find("2"), a_union.end());
502 }
503
504 test("sunionstore");
505 {
506 c.sadd("setf", "1");
507 c.sadd("setg", "2");
508
509 redis::client::string_vector keys;
510 keys.push_back("setf");
511 keys.push_back("setg");
512
513 c.sunionstore("seth", keys);
514
515 redis::client::string_set members;
516 ASSERT_EQUAL(c.smembers("seth", members), 2L);
517 ASSERT_EQUAL(members.size(), 2UL);
518 ASSERT_NOT_EQUAL(members.find("1"), members.end());
519 ASSERT_NOT_EQUAL(members.find("2"), members.end());
520 }
521
522 test("move");
523 {
524 c.select(14);
525 ASSERT_EQUAL(c.exists("ttt"), false);
526 c.select(15);
527 c.set("ttt", "uuu");
528 c.move("ttt", 14);
529 c.select(14);
530 ASSERT_EQUAL(c.exists("ttt"), true);
531 c.select(15);
532 ASSERT_EQUAL(c.exists("ttt"), false);
533 }
534
535 test("move should fail since key exists already");
536 {
537 c.select(14);
538 c.set("ttt", "xxx");
539 c.select(15);
540 c.set("ttt", "uuu");
541
542 bool threw = false;
543
544 try
545 {
546 c.move("ttt", 14);
547 }
548 catch (redis::protocol_error & e)
549 {
550 threw = true;
551 }
552
553 ASSERT_EQUAL(threw, true);
554
555 c.select(14);
556 ASSERT_EQUAL(c.exists("ttt"), true);
557 c.select(15);
558 ASSERT_EQUAL(c.exists("ttt"), true);
559 }
560
561 test("sort ascending");
562 {
563 c.sadd("sort1", "3");
564 c.sadd("sort1", "2");
565 c.sadd("sort1", "1");
566
567 redis::client::string_vector sorted;
568 ASSERT_EQUAL(c.sort("sort1", sorted), 3L);
569 ASSERT_EQUAL(sorted.size(), 3UL);
570 ASSERT_EQUAL(sorted[0], string("1"));
571 ASSERT_EQUAL(sorted[1], string("2"));
572 ASSERT_EQUAL(sorted[2], string("3"));
573 }
574
575 test("sort descending");
576 {
577 redis::client::string_vector sorted;
578 ASSERT_EQUAL(c.sort("sort1", sorted, redis::client::sort_order_descending), 3L);
579 ASSERT_EQUAL(sorted.size(), 3UL);
580 ASSERT_EQUAL(sorted[0], string("3"));
581 ASSERT_EQUAL(sorted[1], string("2"));
582 ASSERT_EQUAL(sorted[2], string("1"));
583 }
584
585 test("sort with limit");
586 {
587 // TODO
588 }
589
590 test("sort lexicographically");
591 {
592 // TODO
593 }
594
595 test("sort with pattern and weights");
596 {
597 // TODO
598 }
599
600 test("save");
601 {
602 c.save();
603 }
604
605 test("bgsave");
606 {
607 c.bgsave();
608 }
609
610 test("lastsave");
611 {
612 ASSERT_GT(c.lastsave(), 0L);
613 }
614
615 test("shutdown");
616 {
617 // You can test this if you really want to ...
618 // c.shutdown();
619 }
620 }
621 catch (redis::redis_error & e)
622 {
623 cerr << "got exception: " << string(e) << endl << "FAIL" << endl;
624 return 1;
625 }
626
627 cout << endl << "testing completed successfully" << endl;
628 return 0;
629 }