1package miniredis
2
3import (
4	"sort"
5	"testing"
6
7	"github.com/gomodule/redigo/redis"
8)
9
10// Test SADD / SMEMBERS.
11func TestSadd(t *testing.T) {
12	s, err := Run()
13	ok(t, err)
14	defer s.Close()
15	c, err := redis.Dial("tcp", s.Addr())
16	ok(t, err)
17
18	{
19		b, err := redis.Int(c.Do("SADD", "s", "aap", "noot", "mies"))
20		ok(t, err)
21		equals(t, 3, b) // New elements.
22
23		members, err := s.Members("s")
24		ok(t, err)
25		equals(t, []string{"aap", "mies", "noot"}, members)
26
27		m, err := redis.Strings(c.Do("SMEMBERS", "s"))
28		ok(t, err)
29		equals(t, []string{"aap", "mies", "noot"}, m)
30	}
31
32	{
33		b, err := redis.String(c.Do("TYPE", "s"))
34		ok(t, err)
35		equals(t, "set", b)
36	}
37
38	// SMEMBERS on an nonexisting key
39	{
40		m, err := redis.Strings(c.Do("SMEMBERS", "nosuch"))
41		ok(t, err)
42		equals(t, []string{}, m)
43	}
44
45	{
46		b, err := redis.Int(c.Do("SADD", "s", "new", "noot", "mies"))
47		ok(t, err)
48		equals(t, 1, b) // Only one new field.
49
50		members, err := s.Members("s")
51		ok(t, err)
52		equals(t, []string{"aap", "mies", "new", "noot"}, members)
53	}
54
55	t.Run("direct usage", func(t *testing.T) {
56		added, err := s.SetAdd("s1", "aap")
57		ok(t, err)
58		equals(t, 1, added)
59
60		members, err := s.Members("s1")
61		ok(t, err)
62		equals(t, []string{"aap"}, members)
63	})
64
65	t.Run("errors", func(t *testing.T) {
66		_, err := redis.String(c.Do("SET", "str", "value"))
67		ok(t, err)
68		_, err = redis.Int(c.Do("SADD", "str", "hi"))
69		mustFail(t, err, msgWrongType)
70		_, err = redis.Int(c.Do("SMEMBERS", "str"))
71		mustFail(t, err, msgWrongType)
72		// Wrong argument counts
73		_, err = redis.String(c.Do("SADD"))
74		mustFail(t, err, "ERR wrong number of arguments for 'sadd' command")
75		_, err = redis.String(c.Do("SADD", "set"))
76		mustFail(t, err, "ERR wrong number of arguments for 'sadd' command")
77		_, err = redis.String(c.Do("SMEMBERS"))
78		mustFail(t, err, "ERR wrong number of arguments for 'smembers' command")
79		_, err = redis.String(c.Do("SMEMBERS", "set", "spurious"))
80		mustFail(t, err, "ERR wrong number of arguments for 'smembers' command")
81	})
82}
83
84// Test SISMEMBER
85func TestSismember(t *testing.T) {
86	s, err := Run()
87	ok(t, err)
88	defer s.Close()
89	c, err := redis.Dial("tcp", s.Addr())
90	ok(t, err)
91
92	s.SetAdd("s", "aap", "noot", "mies")
93
94	{
95		b, err := redis.Int(c.Do("SISMEMBER", "s", "aap"))
96		ok(t, err)
97		equals(t, 1, b)
98
99		b, err = redis.Int(c.Do("SISMEMBER", "s", "nosuch"))
100		ok(t, err)
101		equals(t, 0, b)
102	}
103
104	// a nonexisting key
105	{
106		b, err := redis.Int(c.Do("SISMEMBER", "nosuch", "nosuch"))
107		ok(t, err)
108		equals(t, 0, b)
109	}
110
111	t.Run("direct usage", func(t *testing.T) {
112		isMember, err := s.IsMember("s", "noot")
113		ok(t, err)
114		equals(t, true, isMember)
115	})
116
117	t.Run("errors", func(t *testing.T) {
118		_, err := redis.String(c.Do("SET", "str", "value"))
119		ok(t, err)
120		_, err = redis.Int(c.Do("SISMEMBER", "str"))
121		mustFail(t, err, "ERR wrong number of arguments for 'sismember' command")
122		// Wrong argument counts
123		_, err = redis.String(c.Do("SISMEMBER"))
124		mustFail(t, err, "ERR wrong number of arguments for 'sismember' command")
125		_, err = redis.String(c.Do("SISMEMBER", "set"))
126		mustFail(t, err, "ERR wrong number of arguments for 'sismember' command")
127		_, err = redis.String(c.Do("SISMEMBER", "set", "spurious", "args"))
128		mustFail(t, err, "ERR wrong number of arguments for 'sismember' command")
129	})
130}
131
132// Test SREM
133func TestSrem(t *testing.T) {
134	s, err := Run()
135	ok(t, err)
136	defer s.Close()
137	c, err := redis.Dial("tcp", s.Addr())
138	ok(t, err)
139
140	s.SetAdd("s", "aap", "noot", "mies", "vuur")
141
142	{
143		b, err := redis.Int(c.Do("SREM", "s", "aap", "noot"))
144		ok(t, err)
145		equals(t, 2, b)
146
147		members, err := s.Members("s")
148		ok(t, err)
149		equals(t, []string{"mies", "vuur"}, members)
150	}
151
152	// a nonexisting field
153	{
154		b, err := redis.Int(c.Do("SREM", "s", "nosuch"))
155		ok(t, err)
156		equals(t, 0, b)
157	}
158
159	// a nonexisting key
160	{
161		b, err := redis.Int(c.Do("SREM", "nosuch", "nosuch"))
162		ok(t, err)
163		equals(t, 0, b)
164	}
165
166	t.Run("direct usage", func(t *testing.T) {
167		b, err := s.SRem("s", "mies")
168		ok(t, err)
169		equals(t, 1, b)
170
171		members, err := s.Members("s")
172		ok(t, err)
173		equals(t, []string{"vuur"}, members)
174	})
175
176	t.Run("errors", func(t *testing.T) {
177		_, err := redis.String(c.Do("SET", "str", "value"))
178		ok(t, err)
179		_, err = redis.Int(c.Do("SREM", "str", "value"))
180		mustFail(t, err, msgWrongType)
181		// Wrong argument counts
182		_, err = redis.String(c.Do("SREM"))
183		mustFail(t, err, "ERR wrong number of arguments for 'srem' command")
184		_, err = redis.String(c.Do("SREM", "set"))
185		mustFail(t, err, "ERR wrong number of arguments for 'srem' command")
186		_, err = redis.String(c.Do("SREM", "set", "spurious", "args"))
187		assert(t, err != nil, "SREM error")
188	})
189}
190
191// Test SMOVE
192func TestSmove(t *testing.T) {
193	s, err := Run()
194	ok(t, err)
195	defer s.Close()
196	c, err := redis.Dial("tcp", s.Addr())
197	ok(t, err)
198
199	s.SetAdd("s", "aap", "noot")
200
201	{
202		b, err := redis.Int(c.Do("SMOVE", "s", "s2", "aap"))
203		ok(t, err)
204		equals(t, 1, b)
205
206		m, err := s.IsMember("s", "aap")
207		ok(t, err)
208		equals(t, false, m)
209		m, err = s.IsMember("s2", "aap")
210		ok(t, err)
211		equals(t, true, m)
212	}
213
214	// Move away the last member
215	{
216		b, err := redis.Int(c.Do("SMOVE", "s", "s2", "noot"))
217		ok(t, err)
218		equals(t, 1, b)
219
220		equals(t, false, s.Exists("s"))
221
222		m, err := s.IsMember("s2", "noot")
223		ok(t, err)
224		equals(t, true, m)
225	}
226
227	// a nonexisting member
228	{
229		b, err := redis.Int(c.Do("SMOVE", "s", "s2", "nosuch"))
230		ok(t, err)
231		equals(t, 0, b)
232	}
233
234	// a nonexisting key
235	{
236		b, err := redis.Int(c.Do("SMOVE", "nosuch", "nosuch2", "nosuch"))
237		ok(t, err)
238		equals(t, 0, b)
239	}
240
241	t.Run("errors", func(t *testing.T) {
242		_, err := redis.String(c.Do("SET", "str", "value"))
243		ok(t, err)
244		_, err = redis.Int(c.Do("SMOVE", "str", "dst", "value"))
245		mustFail(t, err, msgWrongType)
246		_, err = redis.Int(c.Do("SMOVE", "s2", "str", "value"))
247		mustFail(t, err, msgWrongType)
248		// Wrong argument counts
249		_, err = redis.String(c.Do("SMOVE"))
250		mustFail(t, err, "ERR wrong number of arguments for 'smove' command")
251		_, err = redis.String(c.Do("SMOVE", "set"))
252		mustFail(t, err, "ERR wrong number of arguments for 'smove' command")
253		_, err = redis.String(c.Do("SMOVE", "set", "set2"))
254		mustFail(t, err, "ERR wrong number of arguments for 'smove' command")
255		_, err = redis.String(c.Do("SMOVE", "set", "set2", "spurious", "args"))
256		mustFail(t, err, "ERR wrong number of arguments for 'smove' command")
257	})
258}
259
260// Test SPOP
261func TestSpop(t *testing.T) {
262	s, err := Run()
263	ok(t, err)
264	defer s.Close()
265	c, err := redis.Dial("tcp", s.Addr())
266	ok(t, err)
267
268	t.Run("basics", func(t *testing.T) {
269		s.SetAdd("s", "aap", "noot")
270		el, err := redis.String(c.Do("SPOP", "s"))
271		ok(t, err)
272		assert(t, el == "aap" || el == "noot", "spop got something")
273
274		el, err = redis.String(c.Do("SPOP", "s"))
275		ok(t, err)
276		assert(t, el == "aap" || el == "noot", "spop got something")
277
278		assert(t, !s.Exists("s"), "all spopped away")
279	})
280
281	t.Run("nonexisting key", func(t *testing.T) {
282		b, err := c.Do("SPOP", "nosuch")
283		ok(t, err)
284		equals(t, nil, b)
285	})
286
287	t.Run("various errors", func(t *testing.T) {
288		s.SetAdd("chk", "aap", "noot")
289		s.Set("str", "value")
290
291		_, err = redis.String(c.Do("SMOVE"))
292		mustFail(t, err, "ERR wrong number of arguments for 'smove' command")
293		_, err = redis.String(c.Do("SMOVE", "chk", "set2"))
294		mustFail(t, err, "ERR wrong number of arguments for 'smove' command")
295
296		_, err = c.Do("SPOP", "str")
297		mustFail(t, err, msgWrongType)
298	})
299
300	t.Run("count argument", func(t *testing.T) {
301		s.SetAdd("s", "aap", "noot", "mies", "vuur")
302		el, err := redis.Strings(c.Do("SPOP", "s", 2))
303		ok(t, err)
304		assert(t, len(el) == 2, "SPOP s 2")
305		members, err := s.Members("s")
306		ok(t, err)
307		assert(t, len(members) == 2, "SPOP s 2")
308
309		_, err = c.Do("SPOP", "str", -12)
310		mustFail(t, err, msgOutOfRange)
311	})
312}
313
314// Test SRANDMEMBER
315func TestSrandmember(t *testing.T) {
316	s, err := Run()
317	ok(t, err)
318	defer s.Close()
319	c, err := redis.Dial("tcp", s.Addr())
320	ok(t, err)
321
322	s.SetAdd("s", "aap", "noot", "mies")
323
324	s.Seed(42)
325	// No count
326	{
327		el, err := redis.String(c.Do("SRANDMEMBER", "s"))
328		ok(t, err)
329		assert(t, el == "aap" || el == "noot" || el == "mies", "srandmember got something")
330	}
331
332	// Positive count
333	{
334		els, err := redis.Strings(c.Do("SRANDMEMBER", "s", 2))
335		ok(t, err)
336		equals(t, 2, len(els))
337		equals(t, "noot", els[0])
338		equals(t, "mies", els[1])
339	}
340
341	// Negative count
342	{
343		els, err := redis.Strings(c.Do("SRANDMEMBER", "s", -2))
344		ok(t, err)
345		equals(t, 2, len(els))
346		equals(t, "aap", els[0])
347		equals(t, "mies", els[1])
348	}
349
350	// a nonexisting key
351	{
352		b, err := c.Do("SRANDMEMBER", "nosuch")
353		ok(t, err)
354		equals(t, nil, b)
355	}
356
357	t.Run("errors", func(t *testing.T) {
358		s.SetAdd("chk", "aap", "noot")
359		s.Set("str", "value")
360
361		_, err = redis.String(c.Do("SRANDMEMBER"))
362		mustFail(t, err, "ERR wrong number of arguments for 'srandmember' command")
363		_, err = redis.String(c.Do("SRANDMEMBER", "chk", "noint"))
364		mustFail(t, err, "ERR value is not an integer or out of range")
365		_, err = redis.String(c.Do("SRANDMEMBER", "chk", 1, "toomanu"))
366		mustFail(t, err, "ERR syntax error")
367
368		_, err = c.Do("SRANDMEMBER", "str")
369		mustFail(t, err, msgWrongType)
370	})
371}
372
373// Test SDIFF
374func TestSdiff(t *testing.T) {
375	s, err := Run()
376	ok(t, err)
377	defer s.Close()
378	c, err := redis.Dial("tcp", s.Addr())
379	ok(t, err)
380
381	s.SetAdd("s1", "aap", "noot", "mies")
382	s.SetAdd("s2", "noot", "mies", "vuur")
383	s.SetAdd("s3", "aap", "mies", "wim")
384
385	// Simple case
386	{
387		els, err := redis.Strings(c.Do("SDIFF", "s1", "s2"))
388		ok(t, err)
389		equals(t, []string{"aap"}, els)
390	}
391
392	// No other set
393	{
394		els, err := redis.Strings(c.Do("SDIFF", "s1"))
395		ok(t, err)
396		sort.Strings(els)
397		equals(t, []string{"aap", "mies", "noot"}, els)
398	}
399
400	// 3 sets
401	{
402		els, err := redis.Strings(c.Do("SDIFF", "s1", "s2", "s3"))
403		ok(t, err)
404		equals(t, []string{}, els)
405	}
406
407	// A nonexisting key
408	{
409		els, err := redis.Strings(c.Do("SDIFF", "s9"))
410		ok(t, err)
411		equals(t, []string{}, els)
412	}
413
414	t.Run("errors", func(t *testing.T) {
415		s.SetAdd("chk", "aap", "noot")
416		s.Set("str", "value")
417
418		_, err = redis.String(c.Do("SDIFF"))
419		mustFail(t, err, "ERR wrong number of arguments for 'sdiff' command")
420		_, err = redis.String(c.Do("SDIFF", "str"))
421		mustFail(t, err, msgWrongType)
422		_, err = redis.String(c.Do("SDIFF", "chk", "str"))
423		mustFail(t, err, msgWrongType)
424	})
425}
426
427// Test SDIFFSTORE
428func TestSdiffstore(t *testing.T) {
429	s, err := Run()
430	ok(t, err)
431	defer s.Close()
432	c, err := redis.Dial("tcp", s.Addr())
433	ok(t, err)
434
435	s.SetAdd("s1", "aap", "noot", "mies")
436	s.SetAdd("s2", "noot", "mies", "vuur")
437	s.SetAdd("s3", "aap", "mies", "wim")
438
439	// Simple case
440	{
441		i, err := redis.Int(c.Do("SDIFFSTORE", "res", "s1", "s3"))
442		ok(t, err)
443		equals(t, 1, i)
444		s.CheckSet(t, "res", "noot")
445	}
446
447	t.Run("errors", func(t *testing.T) {
448		s.SetAdd("chk", "aap", "noot")
449		s.Set("str", "value")
450
451		_, err = redis.String(c.Do("SDIFFSTORE"))
452		mustFail(t, err, "ERR wrong number of arguments for 'sdiffstore' command")
453		_, err = redis.String(c.Do("SDIFFSTORE", "t"))
454		mustFail(t, err, "ERR wrong number of arguments for 'sdiffstore' command")
455		_, err = redis.String(c.Do("SDIFFSTORE", "t", "str"))
456		mustFail(t, err, msgWrongType)
457	})
458}
459
460// Test SINTER
461func TestSinter(t *testing.T) {
462	s, err := Run()
463	ok(t, err)
464	defer s.Close()
465	c, err := redis.Dial("tcp", s.Addr())
466	ok(t, err)
467
468	s.SetAdd("s1", "aap", "noot", "mies")
469	s.SetAdd("s2", "noot", "mies", "vuur")
470	s.SetAdd("s3", "aap", "mies", "wim")
471
472	// Simple case
473	{
474		els, err := redis.Strings(c.Do("SINTER", "s1", "s2"))
475		ok(t, err)
476		sort.Strings(els)
477		equals(t, []string{"mies", "noot"}, els)
478	}
479
480	// No other set
481	{
482		els, err := redis.Strings(c.Do("SINTER", "s1"))
483		ok(t, err)
484		sort.Strings(els)
485		equals(t, []string{"aap", "mies", "noot"}, els)
486	}
487
488	// 3 sets
489	{
490		els, err := redis.Strings(c.Do("SINTER", "s1", "s2", "s3"))
491		ok(t, err)
492		equals(t, []string{"mies"}, els)
493	}
494
495	// A nonexisting key
496	{
497		els, err := redis.Strings(c.Do("SINTER", "s9"))
498		ok(t, err)
499		equals(t, []string{}, els)
500	}
501
502	// With one of the keys being an empty set, the resulting set is also empty
503	{
504		els, err := redis.Strings(c.Do("SINTER", "s1", "s9"))
505		ok(t, err)
506		equals(t, []string{}, els)
507	}
508
509	t.Run("errors", func(t *testing.T) {
510		s.SetAdd("chk", "aap", "noot")
511		s.Set("str", "value")
512
513		_, err = redis.String(c.Do("SINTER"))
514		mustFail(t, err, "ERR wrong number of arguments for 'sinter' command")
515		_, err = redis.String(c.Do("SINTER", "str"))
516		mustFail(t, err, msgWrongType)
517		_, err = redis.String(c.Do("SINTER", "chk", "str"))
518		mustFail(t, err, msgWrongType)
519	})
520}
521
522// Test SINTERSTORE
523func TestSinterstore(t *testing.T) {
524	s, err := Run()
525	ok(t, err)
526	defer s.Close()
527	c, err := redis.Dial("tcp", s.Addr())
528	ok(t, err)
529
530	s.SetAdd("s1", "aap", "noot", "mies")
531	s.SetAdd("s2", "noot", "mies", "vuur")
532	s.SetAdd("s3", "aap", "mies", "wim")
533
534	// Simple case
535	{
536		i, err := redis.Int(c.Do("SINTERSTORE", "res", "s1", "s3"))
537		ok(t, err)
538		equals(t, 2, i)
539		s.CheckSet(t, "res", "aap", "mies")
540	}
541
542	// With one of the keys being an empty set, the resulting set is also empty
543	{
544		i, err := redis.Int(c.Do("SINTERSTORE", "res", "s1", "s9"))
545		ok(t, err)
546		equals(t, 0, i)
547		s.CheckSet(t, "res", []string{}...)
548	}
549
550	t.Run("errors", func(t *testing.T) {
551		s.SetAdd("chk", "aap", "noot")
552		s.Set("str", "value")
553
554		_, err = redis.String(c.Do("SINTERSTORE"))
555		mustFail(t, err, "ERR wrong number of arguments for 'sinterstore' command")
556		_, err = redis.String(c.Do("SINTERSTORE", "t"))
557		mustFail(t, err, "ERR wrong number of arguments for 'sinterstore' command")
558		_, err = redis.String(c.Do("SINTERSTORE", "t", "str"))
559		mustFail(t, err, msgWrongType)
560	})
561}
562
563// Test SUNION
564func TestSunion(t *testing.T) {
565	s, err := Run()
566	ok(t, err)
567	defer s.Close()
568	c, err := redis.Dial("tcp", s.Addr())
569	ok(t, err)
570
571	s.SetAdd("s1", "aap", "noot", "mies")
572	s.SetAdd("s2", "noot", "mies", "vuur")
573	s.SetAdd("s3", "aap", "mies", "wim")
574
575	// Simple case
576	{
577		els, err := redis.Strings(c.Do("SUNION", "s1", "s2"))
578		ok(t, err)
579		sort.Strings(els)
580		equals(t, []string{"aap", "mies", "noot", "vuur"}, els)
581	}
582
583	// No other set
584	{
585		els, err := redis.Strings(c.Do("SUNION", "s1"))
586		ok(t, err)
587		sort.Strings(els)
588		equals(t, []string{"aap", "mies", "noot"}, els)
589	}
590
591	// 3 sets
592	{
593		els, err := redis.Strings(c.Do("SUNION", "s1", "s2", "s3"))
594		ok(t, err)
595		sort.Strings(els)
596		equals(t, []string{"aap", "mies", "noot", "vuur", "wim"}, els)
597	}
598
599	// A nonexisting key
600	{
601		els, err := redis.Strings(c.Do("SUNION", "s9"))
602		ok(t, err)
603		equals(t, []string{}, els)
604	}
605
606	t.Run("errors", func(t *testing.T) {
607		s.SetAdd("chk", "aap", "noot")
608		s.Set("str", "value")
609
610		_, err = redis.String(c.Do("SUNION"))
611		mustFail(t, err, "ERR wrong number of arguments for 'sunion' command")
612		_, err = redis.String(c.Do("SUNION", "str"))
613		mustFail(t, err, msgWrongType)
614		_, err = redis.String(c.Do("SUNION", "chk", "str"))
615		mustFail(t, err, msgWrongType)
616	})
617}
618
619// Test SUNIONSTORE
620func TestSunionstore(t *testing.T) {
621	s, err := Run()
622	ok(t, err)
623	defer s.Close()
624	c, err := redis.Dial("tcp", s.Addr())
625	ok(t, err)
626
627	s.SetAdd("s1", "aap", "noot", "mies")
628	s.SetAdd("s2", "noot", "mies", "vuur")
629	s.SetAdd("s3", "aap", "mies", "wim")
630
631	// Simple case
632	{
633		i, err := redis.Int(c.Do("SUNIONSTORE", "res", "s1", "s3"))
634		ok(t, err)
635		equals(t, 4, i)
636		s.CheckSet(t, "res", "aap", "mies", "noot", "wim")
637	}
638
639	t.Run("errors", func(t *testing.T) {
640		s.SetAdd("chk", "aap", "noot")
641		s.Set("str", "value")
642
643		_, err = redis.String(c.Do("SUNIONSTORE"))
644		mustFail(t, err, "ERR wrong number of arguments for 'sunionstore' command")
645		_, err = redis.String(c.Do("SUNIONSTORE", "t"))
646		mustFail(t, err, "ERR wrong number of arguments for 'sunionstore' command")
647		_, err = redis.String(c.Do("SUNIONSTORE", "t", "str"))
648		mustFail(t, err, msgWrongType)
649	})
650}
651
652func TestSscan(t *testing.T) {
653	s, err := Run()
654	ok(t, err)
655	defer s.Close()
656	c, err := redis.Dial("tcp", s.Addr())
657	ok(t, err)
658
659	// We cheat with sscan. It always returns everything.
660
661	s.SetAdd("set", "value1", "value2")
662
663	// No problem
664	{
665		res, err := redis.Values(c.Do("SSCAN", "set", 0))
666		ok(t, err)
667		equals(t, 2, len(res))
668
669		var c int
670		var keys []string
671		_, err = redis.Scan(res, &c, &keys)
672		ok(t, err)
673		equals(t, 0, c)
674		equals(t, []string{"value1", "value2"}, keys)
675	}
676
677	// Invalid cursor
678	{
679		res, err := redis.Values(c.Do("SSCAN", "set", 42))
680		ok(t, err)
681		equals(t, 2, len(res))
682
683		var c int
684		var keys []string
685		_, err = redis.Scan(res, &c, &keys)
686		ok(t, err)
687		equals(t, 0, c)
688		equals(t, []string(nil), keys)
689	}
690
691	// COUNT (ignored)
692	{
693		res, err := redis.Values(c.Do("SSCAN", "set", 0, "COUNT", 200))
694		ok(t, err)
695		equals(t, 2, len(res))
696
697		var c int
698		var keys []string
699		_, err = redis.Scan(res, &c, &keys)
700		ok(t, err)
701		equals(t, 0, c)
702		equals(t, []string{"value1", "value2"}, keys)
703	}
704
705	// MATCH
706	{
707		s.SetAdd("set", "aap", "noot", "mies")
708		res, err := redis.Values(c.Do("SSCAN", "set", 0, "MATCH", "mi*"))
709		ok(t, err)
710		equals(t, 2, len(res))
711
712		var c int
713		var keys []string
714		_, err = redis.Scan(res, &c, &keys)
715		ok(t, err)
716		equals(t, 0, c)
717		equals(t, []string{"mies"}, keys)
718	}
719
720	t.Run("errors", func(t *testing.T) {
721		_, err := redis.Int(c.Do("SSCAN"))
722		mustFail(t, err, "ERR wrong number of arguments for 'sscan' command")
723		_, err = redis.Int(c.Do("SSCAN", "set"))
724		mustFail(t, err, "ERR wrong number of arguments for 'sscan' command")
725		_, err = redis.Int(c.Do("SSCAN", "set", "noint"))
726		mustFail(t, err, msgInvalidCursor)
727		_, err = redis.Int(c.Do("SSCAN", "set", 1, "MATCH"))
728		mustFail(t, err, msgSyntaxError)
729		_, err = redis.Int(c.Do("SSCAN", "set", 1, "COUNT"))
730		mustFail(t, err, msgSyntaxError)
731		_, err = redis.Int(c.Do("SSCAN", "set", 1, "COUNT", "noint"))
732		mustFail(t, err, msgInvalidInt)
733		s.Set("str", "value")
734		_, err = redis.Int(c.Do("SSCAN", "str", 1))
735		assert(t, err != nil, "do SSCAN error")
736	})
737}
738