1// +build int
2
3package main
4
5// Sorted Set keys.
6
7import (
8	"math"
9	"testing"
10)
11
12func TestSortedSet(t *testing.T) {
13	testCommands(t,
14		succ("ZADD", "z", 1, "aap", 2, "noot", 3, "mies"),
15		succ("ZADD", "z", 1, "vuur", 4, "noot"),
16		succ("TYPE", "z"),
17		succ("EXISTS", "z"),
18		succ("ZCARD", "z"),
19
20		succ("ZRANK", "z", "aap"),
21		succ("ZRANK", "z", "noot"),
22		succ("ZRANK", "z", "mies"),
23		succ("ZRANK", "z", "vuur"),
24		succ("ZRANK", "z", "nosuch"),
25		succ("ZRANK", "nosuch", "nosuch"),
26		succ("ZREVRANK", "z", "aap"),
27		succ("ZREVRANK", "z", "noot"),
28		succ("ZREVRANK", "z", "mies"),
29		succ("ZREVRANK", "z", "vuur"),
30		succ("ZREVRANK", "z", "nosuch"),
31		succ("ZREVRANK", "nosuch", "nosuch"),
32
33		succ("ZADD", "zi", "inf", "aap", "-inf", "noot", "+inf", "mies"),
34		succ("ZRANK", "zi", "noot"),
35
36		// Double key
37		succ("ZADD", "zz", 1, "aap", 2, "aap"),
38		succ("ZCARD", "zz"),
39
40		succ("ZPOPMAX", "zz", 2),
41		succ("ZPOPMAX", "zz"),
42		succ("ZPOPMAX", "zz", -100),
43		succ("ZPOPMAX", "nosuch", 1),
44		succ("ZPOPMAX", "zz", 100),
45
46		succ("ZPOPMIN", "zz", 2),
47		succ("ZPOPMIN", "zz"),
48		succ("ZPOPMIN", "zz", -100),
49		succ("ZPOPMIN", "nosuch", 1),
50		succ("ZPOPMIN", "zz", 100),
51
52		// failure cases
53		succ("SET", "str", "I am a string"),
54		fail("ZADD"),
55		fail("ZADD", "s"),
56		fail("ZADD", "s", 1),
57		fail("ZADD", "s", 1, "aap", 1),
58		fail("ZADD", "s", "nofloat", "aap"),
59		fail("ZADD", "str", 1, "aap"),
60		fail("ZCARD"),
61		fail("ZCARD", "too", "many"),
62		fail("ZCARD", "str"),
63		fail("ZRANK"),
64		fail("ZRANK", "key"),
65		fail("ZRANK", "key", "too", "many"),
66		fail("ZRANK", "str", "member"),
67		fail("ZREVRANK"),
68		fail("ZREVRANK", "key"),
69		fail("ZPOPMAX"),
70		fail("ZPOPMAX", "set", "noint"),
71		fail("ZPOPMAX", "set", 1, "toomany"),
72		fail("ZPOPMIN"),
73		fail("ZPOPMIN", "set", "noint"),
74		fail("ZPOPMIN", "set", 1, "toomany"),
75
76		succ("RENAME", "z", "z2"),
77		succ("EXISTS", "z"),
78		succ("EXISTS", "z2"),
79		succ("MOVE", "z2", 3),
80		succ("EXISTS", "z2"),
81		succ("SELECT", 3),
82		succ("EXISTS", "z2"),
83		succ("DEL", "z2"),
84		succ("EXISTS", "z2"),
85	)
86
87	testCommands(t,
88		succ("ZADD", "z", 0, "new\nline\n"),
89		succ("ZADD", "z", 0, "line"),
90		succ("ZADD", "z", 0, "another\nnew\nline\n"),
91		succ("ZSCAN", "z", 0, "MATCH", "*"),
92		succ("ZRANGEBYLEX", "z", "[a", "[z"),
93		succ("ZRANGE", "z", 0, -1, "WITHSCORES"),
94	)
95}
96
97func TestSortedSetAdd(t *testing.T) {
98	testCommands(t,
99		succ("ZADD", "z",
100			1, "aap",
101			2, "noot",
102		),
103		succ("ZADD", "z", "NX",
104			1.1, "aap",
105			3, "mies",
106		),
107		succ("ZADD", "z", "XX",
108			1.2, "aap",
109			4, "vuur",
110		),
111		succ("ZADD", "z", "CH",
112			1.2, "aap",
113			4.1, "vuur",
114			5, "roos",
115		),
116		succ("ZADD", "z", "CH", "XX",
117			1.2, "aap",
118			4.2, "vuur",
119			5, "roos",
120			5, "zand",
121		),
122		succ("ZADD", "z", "XX", "XX", "XX", "XX",
123			1.2, "aap",
124		),
125		succ("ZADD", "z", "NX", "NX", "NX", "NX",
126			1.2, "aap",
127		),
128		fail("ZADD", "z", "XX", "NX", 1.1, "foo"),
129		fail("ZADD", "z", "XX"),
130		fail("ZADD", "z", "NX"),
131		fail("ZADD", "z", "CH"),
132		fail("ZADD", "z", "??"),
133		fail("ZADD", "z", 1.2, "aap", "XX"),
134		fail("ZADD", "z", 1.2, "aap", "CH"),
135		fail("ZADD", "z"),
136	)
137	testCommands(t,
138		succ("ZADD", "z", "INCR", 1, "aap"),
139		succ("ZADD", "z", "INCR", 1, "aap"),
140		succ("ZADD", "z", "INCR", 1, "aap"),
141		succ("ZADD", "z", "INCR", -12, "aap"),
142		succ("ZADD", "z", "INCR", "INCR", -12, "aap"),
143		succ("ZADD", "z", "CH", "INCR", -12, "aap"), // 'CH' is ignored
144		succ("ZADD", "z", "INCR", "CH", -12, "aap"), // 'CH' is ignored
145		succ("ZADD", "z", "INCR", "NX", 12, "aap"),
146		succ("ZADD", "z", "INCR", "XX", 12, "aap"),
147		succ("ZADD", "q", "INCR", "NX", 12, "aap"),
148		succ("ZADD", "q", "INCR", "XX", 12, "aap"),
149
150		fail("ZADD", "z", "INCR", 1, "aap", 2, "tiger"),
151		fail("ZADD", "z", "INCR", -12),
152		fail("ZADD", "z", "INCR", -12, "aap", "NX"),
153	)
154}
155
156func TestSortedSetRange(t *testing.T) {
157	testCommands(t,
158		succ("ZADD", "z",
159			1, "aap",
160			2, "noot",
161			3, "mies",
162			2, "nootagain",
163			3, "miesagain",
164			math.Inf(+1), "the stars",
165			math.Inf(+1), "more stars",
166			math.Inf(-1), "big bang",
167		),
168		succ("ZRANGE", "z", 0, -1),
169		succ("ZRANGE", "z", 0, -1, "WITHSCORES"),
170		succ("ZRANGE", "z", 0, -1, "WiThScOrEs"),
171		succ("ZRANGE", "z", 0, -2),
172		succ("ZRANGE", "z", 0, -1000),
173		succ("ZRANGE", "z", 2, -2),
174		succ("ZRANGE", "z", 400, -1),
175		succ("ZRANGE", "z", 300, -110),
176		succ("ZREVRANGE", "z", 0, -1),
177		succ("ZREVRANGE", "z", 0, -1, "WITHSCORES"),
178		succ("ZREVRANGE", "z", 0, -1, "WiThScOrEs"),
179		succ("ZREVRANGE", "z", 0, -2),
180		succ("ZREVRANGE", "z", 0, -1000),
181		succ("ZREVRANGE", "z", 2, -2),
182		succ("ZREVRANGE", "z", 400, -1),
183		succ("ZREVRANGE", "z", 300, -110),
184
185		succ("ZADD", "zz",
186			0, "aap",
187			0, "Aap",
188			0, "AAP",
189			0, "aAP",
190			0, "aAp",
191		),
192		succ("ZRANGE", "zz", 0, -1),
193
194		// failure cases
195		fail("ZRANGE"),
196		fail("ZRANGE", "foo"),
197		fail("ZRANGE", "foo", 1),
198		fail("ZRANGE", "foo", 2, 3, "toomany"),
199		fail("ZRANGE", "foo", 2, 3, "WITHSCORES", "toomany"),
200		fail("ZRANGE", "foo", "noint", 3),
201		fail("ZRANGE", "foo", 2, "noint"),
202		succ("SET", "str", "I am a string"),
203		fail("ZRANGE", "str", 300, -110),
204
205		fail("ZREVRANGE"),
206		fail("ZREVRANGE", "str", 300, -110),
207	)
208}
209
210func TestSortedSetRem(t *testing.T) {
211	testCommands(t,
212		succ("ZADD", "z",
213			1, "aap",
214			2, "noot",
215			3, "mies",
216			2, "nootagain",
217			3, "miesagain",
218			math.Inf(+1), "the stars",
219			math.Inf(+1), "more stars",
220			math.Inf(-1), "big bang",
221		),
222		succ("ZREM", "z", "nosuch"),
223		succ("ZREM", "z", "mies", "nootagain"),
224		succ("ZRANGE", "z", 0, -1),
225
226		// failure cases
227		fail("ZREM"),
228		fail("ZREM", "foo"),
229		succ("SET", "str", "I am a string"),
230		fail("ZREM", "str", "member"),
231	)
232}
233
234func TestSortedSetRemRangeByLex(t *testing.T) {
235	testCommands(t,
236		succ("ZADD", "z",
237			12, "zero kelvin",
238			12, "minusfour",
239			12, "one",
240			12, "oneone",
241			12, "two",
242			12, "zwei",
243			12, "three",
244			12, "drei",
245			12, "inf",
246		),
247		succ("ZRANGEBYLEX", "z", "-", "+"),
248		succ("ZREMRANGEBYLEX", "z", "[o", "(t"),
249		succ("ZRANGEBYLEX", "z", "-", "+"),
250		succ("ZREMRANGEBYLEX", "z", "-", "+"),
251		succ("ZRANGEBYLEX", "z", "-", "+"),
252
253		// failure cases
254		fail("ZREMRANGEBYLEX"),
255		fail("ZREMRANGEBYLEX", "key"),
256		fail("ZREMRANGEBYLEX", "key", "[a"),
257		fail("ZREMRANGEBYLEX", "key", "[a", "[b", "c"),
258		fail("ZREMRANGEBYLEX", "key", "!a", "[b"),
259		succ("SET", "str", "I am a string"),
260		fail("ZREMRANGEBYLEX", "str", "[a", "[b"),
261	)
262}
263
264func TestSortedSetRemRangeByRank(t *testing.T) {
265	testCommands(t,
266		succ("ZADD", "z",
267			12, "zero kelvin",
268			12, "minusfour",
269			12, "one",
270			12, "oneone",
271			12, "two",
272			12, "zwei",
273			12, "three",
274			12, "drei",
275			12, "inf",
276		),
277		succ("ZREMRANGEBYRANK", "z", -2, -1),
278		succ("ZRANGE", "z", 0, -1),
279		succ("ZRANGEBYSCORE", "z", "-inf", "inf"),
280		succ("ZREMRANGEBYRANK", "z", -2, -1),
281		succ("ZRANGE", "z", 0, -1),
282		succ("ZREMRANGEBYRANK", "z", 0, -1),
283		succ("EXISTS", "z"),
284
285		succ("ZREMRANGEBYRANK", "nosuch", -2, -1),
286
287		// failure cases
288		fail("ZREMRANGEBYRANK"),
289		fail("ZREMRANGEBYRANK", "key"),
290		fail("ZREMRANGEBYRANK", "key", 0),
291		fail("ZREMRANGEBYRANK", "key", "noint", -1),
292		fail("ZREMRANGEBYRANK", "key", 0, "noint"),
293		fail("ZREMRANGEBYRANK", "key", "0", "1", "too many"),
294		succ("SET", "str", "I am a string"),
295		fail("ZREMRANGEBYRANK", "str", "0", "-1"),
296	)
297}
298
299func TestSortedSetRemRangeByScore(t *testing.T) {
300	testCommands(t,
301		succ("ZADD", "z",
302			1, "aap",
303			2, "noot",
304			3, "mies",
305			2, "nootagain",
306			3, "miesagain",
307			math.Inf(+1), "the stars",
308			math.Inf(+1), "more stars",
309			math.Inf(-1), "big bang",
310		),
311		succ("ZREMRANGEBYSCORE", "z", "-inf", "(2"),
312		succ("ZRANGE", "z", 0, -1),
313		succ("ZREMRANGEBYSCORE", "z", "(1000", "(2000"),
314		succ("ZRANGE", "z", 0, -1),
315		succ("ZREMRANGEBYSCORE", "z", "-inf", "+inf"),
316		succ("EXISTS", "z"),
317
318		succ("ZREMRANGEBYSCORE", "nosuch", "-inf", "inf"),
319
320		// failure cases
321		fail("ZREMRANGEBYSCORE"),
322		fail("ZREMRANGEBYSCORE", "key"),
323		fail("ZREMRANGEBYSCORE", "key", 0),
324		fail("ZREMRANGEBYSCORE", "key", "noint", -1),
325		fail("ZREMRANGEBYSCORE", "key", 0, "noint"),
326		fail("ZREMRANGEBYSCORE", "key", "0", "1", "too many"),
327		succ("SET", "str", "I am a string"),
328		fail("ZREMRANGEBYSCORE", "str", "0", "-1"),
329	)
330}
331
332func TestSortedSetScore(t *testing.T) {
333	testCommands(t,
334		succ("ZADD", "z",
335			1, "aap",
336			2, "noot",
337			3, "mies",
338			2, "nootagain",
339			3, "miesagain",
340			math.Inf(+1), "the stars",
341		),
342		succ("ZSCORE", "z", "mies"),
343		succ("ZSCORE", "z", "the stars"),
344		succ("ZSCORE", "z", "nosuch"),
345		succ("ZSCORE", "nosuch", "nosuch"),
346
347		// failure cases
348		fail("ZSCORE"),
349		fail("ZSCORE", "foo"),
350		fail("ZSCORE", "foo", "too", "many"),
351		succ("SET", "str", "I am a string"),
352		fail("ZSCORE", "str", "member"),
353	)
354}
355
356func TestSortedSetRangeByScore(t *testing.T) {
357	testCommands(t,
358		succ("ZADD", "z",
359			1, "aap",
360			2, "noot",
361			3, "mies",
362			2, "nootagain",
363			3, "miesagain",
364			math.Inf(+1), "the stars",
365			math.Inf(+1), "more stars",
366			math.Inf(-1), "big bang",
367		),
368		succ("ZRANGEBYSCORE", "z", "-inf", "inf"),
369		succ("ZRANGEBYSCORE", "z", "-inf", "inf", "LIMIT", 1, 2),
370		succ("ZRANGEBYSCORE", "z", "-inf", "inf", "LIMIT", -1, 2),
371		succ("ZRANGEBYSCORE", "z", "-inf", "inf", "LIMIT", 1, -2),
372		succ("ZREVRANGEBYSCORE", "z", "inf", "-inf"),
373		succ("ZREVRANGEBYSCORE", "z", "inf", "-inf", "LIMIT", 1, 2),
374		succ("ZREVRANGEBYSCORE", "z", "inf", "-inf", "LIMIT", -1, 2),
375		succ("ZREVRANGEBYSCORE", "z", "inf", "-inf", "LIMIT", 1, -2),
376		succ("ZRANGEBYSCORE", "z", "-inf", "inf", "WITHSCORES"),
377		succ("ZRANGEBYSCORE", "z", "-inf", "inf", "WiThScOrEs"),
378		succ("ZREVRANGEBYSCORE", "z", "-inf", "inf", "WITHSCORES", "LIMIT", 1, 2),
379		succ("ZRANGEBYSCORE", "z", 0, 3),
380		succ("ZRANGEBYSCORE", "z", 0, "inf"),
381		succ("ZRANGEBYSCORE", "z", "(1", "3"),
382		succ("ZRANGEBYSCORE", "z", "(1", "(3"),
383		succ("ZRANGEBYSCORE", "z", "1", "(3"),
384		succ("ZRANGEBYSCORE", "z", "1", "(3", "LIMIT", 0, 2),
385		succ("ZRANGEBYSCORE", "foo", 2, 3, "LIMIT", 1, 2, "WITHSCORES"),
386		succ("ZCOUNT", "z", "-inf", "inf"),
387		succ("ZCOUNT", "z", 0, 3),
388		succ("ZCOUNT", "z", 0, "inf"),
389		succ("ZCOUNT", "z", "(2", "inf"),
390
391		// Bunch of limit edge cases
392		succ("ZRANGEBYSCORE", "z", "-inf", "inf", "LIMIT", 0, 7),
393		succ("ZRANGEBYSCORE", "z", "-inf", "inf", "LIMIT", 0, 8),
394		succ("ZRANGEBYSCORE", "z", "-inf", "inf", "LIMIT", 0, 9),
395		succ("ZRANGEBYSCORE", "z", "-inf", "inf", "LIMIT", 7, 0),
396		succ("ZRANGEBYSCORE", "z", "-inf", "inf", "LIMIT", 7, 1),
397		succ("ZRANGEBYSCORE", "z", "-inf", "inf", "LIMIT", 7, 2),
398		succ("ZRANGEBYSCORE", "z", "-inf", "inf", "LIMIT", 8, 0),
399		succ("ZRANGEBYSCORE", "z", "-inf", "inf", "LIMIT", 8, 1),
400		succ("ZRANGEBYSCORE", "z", "-inf", "inf", "LIMIT", 8, 2),
401		succ("ZRANGEBYSCORE", "z", "-inf", "inf", "LIMIT", 9, 2),
402		succ("ZRANGEBYSCORE", "z", "-inf", "inf", "LIMIT", -1, 2),
403		succ("ZRANGEBYSCORE", "z", "-inf", "inf", "LIMIT", -1, -1),
404
405		// failure cases
406		fail("ZRANGEBYSCORE"),
407		fail("ZRANGEBYSCORE", "foo"),
408		fail("ZRANGEBYSCORE", "foo", 1),
409		fail("ZRANGEBYSCORE", "foo", 2, 3, "toomany"),
410		fail("ZRANGEBYSCORE", "foo", 2, 3, "WITHSCORES", "toomany"),
411		fail("ZRANGEBYSCORE", "foo", 2, 3, "LIMIT", "noint", 1),
412		fail("ZRANGEBYSCORE", "foo", 2, 3, "LIMIT", 1, "noint"),
413		fail("ZREVRANGEBYSCORE", "z", "-inf", "inf", "WITHSCORES", "LIMIT", 1, -2, "toomany"),
414		fail("ZRANGEBYSCORE", "foo", "noint", 3),
415		fail("ZRANGEBYSCORE", "foo", "[4", 3),
416		fail("ZRANGEBYSCORE", "foo", 2, "noint"),
417		fail("ZRANGEBYSCORE", "foo", "4", "[3"),
418		succ("SET", "str", "I am a string"),
419		fail("ZRANGEBYSCORE", "str", 300, -110),
420
421		fail("ZREVRANGEBYSCORE"),
422		fail("ZREVRANGEBYSCORE", "foo", "[4", 3),
423		fail("ZREVRANGEBYSCORE", "str", 300, -110),
424
425		fail("ZCOUNT"),
426		fail("ZCOUNT", "foo", "[4", 3),
427		fail("ZCOUNT", "str", 300, -110),
428	)
429
430	// Issue #10
431	testCommands(t,
432		succ("ZADD", "key", "3.3", "element"),
433		succ("ZRANGEBYSCORE", "key", "3.3", "3.3"),
434		succ("ZRANGEBYSCORE", "key", "4.3", "4.3"),
435		succ("ZREVRANGEBYSCORE", "key", "3.3", "3.3"),
436		succ("ZREVRANGEBYSCORE", "key", "4.3", "4.3"),
437	)
438}
439
440func TestSortedSetRangeByLex(t *testing.T) {
441	testCommands(t,
442		succ("ZADD", "z",
443			12, "zero kelvin",
444			12, "minusfour",
445			12, "one",
446			12, "oneone",
447			12, "two",
448			12, "zwei",
449			12, "three",
450			12, "drei",
451			12, "inf",
452		),
453		succ("ZRANGEBYLEX", "z", "-", "+"),
454		succ("ZREVRANGEBYLEX", "z", "+", "-"),
455		succ("ZLEXCOUNT", "z", "-", "+"),
456		succ("ZRANGEBYLEX", "z", "[o", "[three"),
457		succ("ZREVRANGEBYLEX", "z", "[three", "[o"),
458		succ("ZLEXCOUNT", "z", "[o", "[three"),
459		succ("ZRANGEBYLEX", "z", "(o", "(z"),
460		succ("ZREVRANGEBYLEX", "z", "(z", "(o"),
461		succ("ZLEXCOUNT", "z", "(o", "(z"),
462		succ("ZRANGEBYLEX", "z", "+", "(z"),
463		succ("ZREVRANGEBYLEX", "z", "(z", "+"),
464		succ("ZRANGEBYLEX", "z", "(a", "-"),
465		succ("ZREVRANGEBYLEX", "z", "-", "(a"),
466		succ("ZRANGEBYLEX", "z", "(z", "(a"),
467		succ("ZREVRANGEBYLEX", "z", "(a", "(z"),
468		succ("ZRANGEBYLEX", "nosuch", "-", "+"),
469		succ("ZREVRANGEBYLEX", "nosuch", "+", "-"),
470		succ("ZLEXCOUNT", "nosuch", "-", "+"),
471		succ("ZRANGEBYLEX", "z", "-", "+", "LIMIT", 1, 2),
472		succ("ZREVRANGEBYLEX", "z", "+", "-", "LIMIT", 1, 2),
473		succ("ZRANGEBYLEX", "z", "-", "+", "LIMIT", -1, 2),
474		succ("ZREVRANGEBYLEX", "z", "+", "-", "LIMIT", -1, 2),
475		succ("ZRANGEBYLEX", "z", "-", "+", "LIMIT", 1, -2),
476		succ("ZREVRANGEBYLEX", "z", "+", "-", "LIMIT", 1, -2),
477
478		succ("ZADD", "z", 12, "z"),
479		succ("ZADD", "z", 12, "zz"),
480		succ("ZADD", "z", 12, "zzz"),
481		succ("ZADD", "z", 12, "zzzz"),
482		succ("ZRANGEBYLEX", "z", "[z", "+"),
483		succ("ZREVRANGEBYLEX", "z", "+", "[z"),
484		succ("ZRANGEBYLEX", "z", "(z", "+"),
485		succ("ZREVRANGEBYLEX", "z", "+", "(z"),
486		succ("ZLEXCOUNT", "z", "(z", "+"),
487
488		// failure cases
489		fail("ZRANGEBYLEX"),
490		fail("ZREVRANGEBYLEX"),
491		fail("ZRANGEBYLEX", "key"),
492		fail("ZRANGEBYLEX", "key", "[a"),
493		fail("ZRANGEBYLEX", "key", "[a", "[b", "c"),
494		fail("ZRANGEBYLEX", "key", "!a", "[b"),
495		fail("ZRANGEBYLEX", "key", "[a", "!b"),
496		fail("ZRANGEBYLEX", "key", "[a", "b]"),
497		failWith("not valid string range item", "ZRANGEBYLEX", "key", "[a", ""),
498		failWith("not valid string range item", "ZRANGEBYLEX", "key", "", "[b"),
499		fail("ZRANGEBYLEX", "key", "[a", "[b", "LIMIT"),
500		fail("ZRANGEBYLEX", "key", "[a", "[b", "LIMIT", 1),
501		fail("ZRANGEBYLEX", "key", "[a", "[b", "LIMIT", "a", 1),
502		fail("ZRANGEBYLEX", "key", "[a", "[b", "LIMIT", 1, "a"),
503		fail("ZRANGEBYLEX", "key", "[a", "[b", "LIMIT", 1, 1, "toomany"),
504		succ("SET", "str", "I am a string"),
505		fail("ZRANGEBYLEX", "str", "[a", "[b"),
506
507		fail("ZLEXCOUNT"),
508		fail("ZLEXCOUNT", "key"),
509		fail("ZLEXCOUNT", "key", "[a"),
510		fail("ZLEXCOUNT", "key", "[a", "[b", "c"),
511		fail("ZLEXCOUNT", "key", "!a", "[b"),
512		fail("ZLEXCOUNT", "str", "[a", "[b"),
513	)
514
515	testCommands(t,
516		succ("ZADD", "idx", 0, "ccc"),
517		succ("ZRANGEBYLEX", "idx", "[d", "[e"),
518		succ("ZRANGEBYLEX", "idx", "[c", "[d"),
519	)
520}
521
522func TestSortedSetIncyby(t *testing.T) {
523	testCommands(t,
524		succ("ZINCRBY", "z", 1.0, "m"),
525		succ("ZINCRBY", "z", 1.0, "m"),
526		succ("ZINCRBY", "z", 1.0, "m"),
527		succ("ZINCRBY", "z", 2.0, "m"),
528		succ("ZINCRBY", "z", 3, "m2"),
529		succ("ZINCRBY", "z", 3, "m2"),
530		succ("ZINCRBY", "z", 3, "m2"),
531
532		// failure cases
533		fail("ZINCRBY"),
534		fail("ZINCRBY", "key"),
535		fail("ZINCRBY", "key", 1.0),
536		fail("ZINCRBY", "key", "nofloat", "m"),
537		fail("ZINCRBY", "key", 1.0, "too", "many"),
538		succ("SET", "str", "I am a string"),
539		fail("ZINCRBY", "str", 1.0, "member"),
540	)
541}
542
543func TestZscan(t *testing.T) {
544	testCommands(t,
545		// No set yet
546		succ("ZSCAN", "h", 0),
547
548		succ("ZADD", "h", 1.0, "key1"),
549		succ("ZSCAN", "h", 0),
550		succ("ZSCAN", "h", 0, "COUNT", 12),
551		succ("ZSCAN", "h", 0, "cOuNt", 12),
552
553		succ("ZADD", "h", 2.0, "anotherkey"),
554		succ("ZSCAN", "h", 0, "MATCH", "anoth*"),
555		succ("ZSCAN", "h", 0, "MATCH", "anoth*", "COUNT", 100),
556		succ("ZSCAN", "h", 0, "COUNT", 100, "MATCH", "anoth*"),
557
558		// Can't really test multiple keys.
559		// succ("SET", "key2", "value2"),
560		// succ("SCAN", 0),
561
562		// Error cases
563		fail("ZSCAN"),
564		fail("ZSCAN", "noint"),
565		fail("ZSCAN", "h", 0, "COUNT", "noint"),
566		fail("ZSCAN", "h", 0, "COUNT"),
567		fail("ZSCAN", "h", 0, "MATCH"),
568		fail("ZSCAN", "h", 0, "garbage"),
569		fail("ZSCAN", "h", 0, "COUNT", 12, "MATCH", "foo", "garbage"),
570		// fail("ZSCAN", "nosuch", 0, "COUNT", "garbage"),
571		succ("SET", "str", "1"),
572		fail("ZSCAN", "str", 0),
573	)
574}
575
576func TestZunionstore(t *testing.T) {
577	testCommands(t,
578		succ("ZADD", "h1", 1.0, "key1"),
579		succ("ZADD", "h1", 2.0, "key2"),
580		succ("ZADD", "h2", 1.0, "key1"),
581		succ("ZADD", "h2", 4.0, "key2"),
582		succ("ZUNIONSTORE", "res", 2, "h1", "h2"),
583		succ("ZRANGE", "res", 0, -1, "WITHSCORES"),
584
585		succ("ZUNIONSTORE", "weighted", 2, "h1", "h2", "WEIGHTS", "2.0", "12"),
586		succ("ZRANGE", "weighted", 0, -1, "WITHSCORES"),
587		succ("ZUNIONSTORE", "weighted2", 2, "h1", "h2", "WEIGHTS", "2", "-12"),
588		succ("ZRANGE", "weighted2", 0, -1, "WITHSCORES"),
589
590		succ("ZUNIONSTORE", "amin", 2, "h1", "h2", "AGGREGATE", "min"),
591		succ("ZRANGE", "amin", 0, -1, "WITHSCORES"),
592		succ("ZUNIONSTORE", "amax", 2, "h1", "h2", "AGGREGATE", "max"),
593		succ("ZRANGE", "amax", 0, -1, "WITHSCORES"),
594		succ("ZUNIONSTORE", "asum", 2, "h1", "h2", "AGGREGATE", "sum"),
595		succ("ZRANGE", "asum", 0, -1, "WITHSCORES"),
596
597		// Error cases
598		fail("ZUNIONSTORE"),
599		fail("ZUNIONSTORE", "h"),
600		fail("ZUNIONSTORE", "h", "noint"),
601		fail("ZUNIONSTORE", "h", 0, "f"),
602		fail("ZUNIONSTORE", "h", 2, "f"),
603		fail("ZUNIONSTORE", "h", -1, "f"),
604		fail("ZUNIONSTORE", "h", 2, "f1", "f2", "f3"),
605		fail("ZUNIONSTORE", "h", 2, "f1", "f2", "WEIGHTS"),
606		fail("ZUNIONSTORE", "h", 2, "f1", "f2", "WEIGHTS", 1),
607		fail("ZUNIONSTORE", "h", 2, "f1", "f2", "WEIGHTS", 1, 2, 3),
608		fail("ZUNIONSTORE", "h", 2, "f1", "f2", "WEIGHTS", "f", 2),
609		fail("ZUNIONSTORE", "h", 2, "f1", "f2", "AGGREGATE", "foo"),
610		succ("SET", "str", "1"),
611		fail("ZUNIONSTORE", "h", 1, "str"),
612	)
613	// overwrite
614	testCommands(t,
615		succ("ZADD", "h1", 1.0, "key1"),
616		succ("ZADD", "h1", 2.0, "key2"),
617		succ("ZADD", "h2", 1.0, "key1"),
618		succ("ZADD", "h2", 4.0, "key2"),
619		succ("SET", "str", "1"),
620		succ("ZUNIONSTORE", "str", 2, "h1", "h2"),
621		succ("TYPE", "str"),
622		succ("ZUNIONSTORE", "h2", 2, "h1", "h2"),
623		succ("ZRANGE", "h2", 0, -1, "WITHSCORES"),
624		succ("TYPE", "h1"),
625		succ("TYPE", "h2"),
626	)
627	// not a sorted set, still fine
628	testCommands(t,
629		succ("SADD", "super", "1", "2", "3"),
630		succ("SADD", "exclude", "3"),
631		succ("ZUNIONSTORE", "tmp", "2", "super", "exclude", "weights", "1", "0", "aggregate", "min"),
632		succ("ZRANGE", "tmp", "0", "-1", "withscores"),
633	)
634}
635
636func TestZinterstore(t *testing.T) {
637	testCommands(t,
638		succ("ZADD", "h1", 1.0, "key1"),
639		succ("ZADD", "h1", 2.0, "key2"),
640		succ("ZADD", "h1", 3.0, "key3"),
641		succ("ZADD", "h2", 1.0, "key1"),
642		succ("ZADD", "h2", 4.0, "key2"),
643		succ("ZADD", "h3", 4.0, "key4"),
644		succ("ZINTERSTORE", "res", 2, "h1", "h2"),
645		succ("ZRANGE", "res", 0, -1, "WITHSCORES"),
646
647		succ("ZINTERSTORE", "weighted", 2, "h1", "h2", "WEIGHTS", "2.0", "12"),
648		succ("ZRANGE", "weighted", 0, -1, "WITHSCORES"),
649		succ("ZINTERSTORE", "weighted2", 2, "h1", "h2", "WEIGHTS", "2", "-12"),
650		succ("ZRANGE", "weighted2", 0, -1, "WITHSCORES"),
651
652		succ("ZINTERSTORE", "amin", 2, "h1", "h2", "AGGREGATE", "min"),
653		succ("ZRANGE", "amin", 0, -1, "WITHSCORES"),
654		succ("ZINTERSTORE", "amax", 2, "h1", "h2", "AGGREGATE", "max"),
655		succ("ZRANGE", "amax", 0, -1, "WITHSCORES"),
656		succ("ZINTERSTORE", "asum", 2, "h1", "h2", "AGGREGATE", "sum"),
657		succ("ZRANGE", "asum", 0, -1, "WITHSCORES"),
658
659		// Error cases
660		fail("ZINTERSTORE"),
661		fail("ZINTERSTORE", "h"),
662		fail("ZINTERSTORE", "h", "noint"),
663		fail("ZINTERSTORE", "h", 0, "f"),
664		fail("ZINTERSTORE", "h", 2, "f"),
665		fail("ZINTERSTORE", "h", -1, "f"),
666		fail("ZINTERSTORE", "h", 2, "f1", "f2", "f3"),
667		fail("ZINTERSTORE", "h", 2, "f1", "f2", "WEIGHTS"),
668		fail("ZINTERSTORE", "h", 2, "f1", "f2", "WEIGHTS", 1),
669		fail("ZINTERSTORE", "h", 2, "f1", "f2", "WEIGHTS", 1, 2, 3),
670		fail("ZINTERSTORE", "h", 2, "f1", "f2", "WEIGHTS", "f", 2),
671		fail("ZINTERSTORE", "h", 2, "f1", "f2", "AGGREGATE", "foo"),
672		succ("SET", "str", "1"),
673		fail("ZINTERSTORE", "h", 1, "str"),
674	)
675}
676
677func TestZpopminmax(t *testing.T) {
678	testCommands(t,
679		succ("ZADD", "set:zpop", 1.0, "key1"),
680		succ("ZADD", "set:zpop", 2.0, "key2"),
681		succ("ZADD", "set:zpop", 3.0, "key3"),
682		succ("ZADD", "set:zpop", 4.0, "key4"),
683		succ("ZADD", "set:zpop", 5.0, "key5"),
684		succ("ZCARD", "set:zpop"),
685
686		succ("ZSCORE", "set:zpop", "key1"),
687		succ("ZSCORE", "set:zpop", "key5"),
688
689		succ("ZPOPMIN", "set:zpop"),
690		succ("ZPOPMIN", "set:zpop", 2),
691		succ("ZPOPMIN", "set:zpop", 100),
692		succ("ZPOPMIN", "set:zpop", -100),
693
694		succ("ZPOPMAX", "set:zpop"),
695		succ("ZPOPMAX", "set:zpop", 2),
696		succ("ZPOPMAX", "set:zpop", 100),
697		succ("ZPOPMAX", "set:zpop", -100),
698		succ("ZPOPMAX", "nosuch", 1),
699
700		// Wrong args
701		fail("ZPOPMIN"),
702		fail("ZPOPMIN", "set:zpop", "h1"),
703		fail("ZPOPMIN", "set:zpop", 1, "h2"),
704	)
705}
706