1// +build int
2
3package main
4
5import (
6	"strings"
7	"testing"
8	"time"
9)
10
11func TestKeys(t *testing.T) {
12	testRaw(t, func(c *client) {
13		c.Do("SET", "one", "1")
14		c.Do("SET", "two", "2")
15		c.Do("SET", "three", "3")
16		c.Do("SET", "four", "4")
17		c.DoSorted("KEYS", `*o*`)
18		c.DoSorted("KEYS", `t??`)
19		c.DoSorted("KEYS", `t?*`)
20		c.DoSorted("KEYS", `*`)
21		c.DoSorted("KEYS", `t*`)
22		c.DoSorted("KEYS", `t\*`)
23		c.DoSorted("KEYS", `[tf]*`)
24
25		// zero length key
26		c.Do("SET", "", "nothing")
27		c.Do("GET", "")
28
29		// Simple failure cases
30		c.Do("KEYS")
31		c.Do("KEYS", "foo", "bar")
32	})
33
34	testRaw(t, func(c *client) {
35		c.Do("SET", "[one]", "1")
36		c.Do("SET", "two", "2")
37		c.DoSorted("KEYS", `[\[o]*`)
38		c.DoSorted("KEYS", `\[*`)
39		c.DoSorted("KEYS", `*o*`)
40		c.DoSorted("KEYS", `[]*`) // nothing
41	})
42}
43
44func TestRandom(t *testing.T) {
45	testRaw(t, func(c *client) {
46		c.Do("RANDOMKEY")
47		// A random key from a DB with a single key. We can test that.
48		c.Do("SET", "one", "1")
49		c.Do("RANDOMKEY")
50
51		// Simple failure cases
52		c.Do("RANDOMKEY", "bar")
53	})
54}
55
56func TestUnknownCommand(t *testing.T) {
57	testRaw(t, func(c *client) {
58		c.Do("nosuch")
59		c.Do("noSUCH")
60		c.Do("noSUCH", "1", "2", "3")
61	})
62}
63
64func TestQuit(t *testing.T) {
65	testRaw(t, func(c *client) {
66		c.Do("QUIT")
67	})
68}
69
70func TestExists(t *testing.T) {
71	testRaw(t, func(c *client) {
72		c.Do("SET", "a", "3")
73		c.Do("HSET", "b", "c", "d")
74		c.Do("EXISTS", "a", "b")
75		c.Do("EXISTS", "a", "b", "q")
76		c.Do("EXISTS", "a", "b", "b", "b", "a", "q")
77
78		// Error cases
79		c.Do("EXISTS")
80	})
81}
82
83func TestRename(t *testing.T) {
84	testRaw(t, func(c *client) {
85		// No 'a' key
86		c.Do("RENAME", "a", "b")
87
88		// Move a key with the TTL.
89		c.Do("SET", "a", "3")
90		c.Do("EXPIRE", "a", "123")
91		c.Do("SET", "b", "12")
92		c.Do("RENAME", "a", "b")
93		c.Do("EXISTS", "a")
94		c.Do("GET", "a")
95		c.Do("TYPE", "a")
96		c.Do("TTL", "a")
97		c.Do("EXISTS", "b")
98		c.Do("GET", "b")
99		c.Do("TYPE", "b")
100		c.Do("TTL", "b")
101
102		// move a key without TTL
103		c.Do("SET", "nottl", "3")
104		c.Do("RENAME", "nottl", "stillnottl")
105		c.Do("TTL", "nottl")
106		c.Do("TTL", "stillnottl")
107
108		// Error cases
109		c.Do("RENAME")
110		c.Do("RENAME", "a")
111		c.Do("RENAME", "a", "b", "toomany")
112	})
113}
114
115func TestRenamenx(t *testing.T) {
116	testRaw(t, func(c *client) {
117		// No 'a' key
118		c.Do("RENAMENX", "a", "b")
119
120		c.Do("SET", "a", "value")
121		c.Do("SET", "str", "value")
122		c.Do("RENAMENX", "a", "str")
123		c.Do("EXISTS", "a")
124		c.Do("EXISTS", "str")
125		c.Do("GET", "a")
126		c.Do("GET", "str")
127
128		c.Do("RENAMENX", "a", "nosuch")
129		c.Do("EXISTS", "a")
130		c.Do("EXISTS", "nosuch")
131
132		// Error cases
133		c.Do("RENAMENX")
134		c.Do("RENAMENX", "a")
135		c.Do("RENAMENX", "a", "b", "toomany")
136	})
137}
138
139func TestScan(t *testing.T) {
140	testRaw(t, func(c *client) {
141		// No keys yet
142		c.Do("SCAN", "0")
143
144		c.Do("SET", "key", "value")
145		c.Do("SCAN", "0")
146		c.Do("SCAN", "0", "COUNT", "12")
147		c.Do("SCAN", "0", "cOuNt", "12")
148
149		c.Do("SET", "anotherkey", "value")
150		c.Do("SCAN", "0", "MATCH", "anoth*")
151		c.Do("SCAN", "0", "MATCH", "anoth*", "COUNT", "100")
152		c.Do("SCAN", "0", "COUNT", "100", "MATCH", "anoth*")
153
154		// Can't really test multiple keys.
155		// c.Do("SET", "key2", "value2")
156		// c.Do("SCAN", "0")
157
158		// Error cases
159		c.Do("SCAN")
160		c.Do("SCAN", "noint")
161		c.Do("SCAN", "0", "COUNT", "noint")
162		c.Do("SCAN", "0", "COUNT")
163		c.Do("SCAN", "0", "MATCH")
164		c.Do("SCAN", "0", "garbage")
165		c.Do("SCAN", "0", "COUNT", "12", "MATCH", "foo", "garbage")
166	})
167}
168
169func TestFastForward(t *testing.T) {
170	testRaw(t, func(c *client) {
171		c.Do("SET", "key1", "value")
172		c.Do("SET", "key", "value", "PX", "100")
173		c.DoSorted("KEYS", "*")
174		time.Sleep(200 * time.Millisecond)
175		c.miniredis.FastForward(200 * time.Millisecond)
176		c.DoSorted("KEYS", "*")
177	})
178
179	testRaw(t, func(c *client) {
180		c.Do("SET", "key1", "value", "PX", "-100")
181		c.Do("SET", "key2", "value", "EX", "-100")
182		c.Do("SET", "key3", "value", "EX", "0")
183		c.DoSorted("KEYS", "*")
184
185		c.Do("SET", "key4", "value")
186		c.DoSorted("KEYS", "*")
187		c.Do("EXPIRE", "key4", "-100")
188		c.DoSorted("KEYS", "*")
189
190		c.Do("SET", "key4", "value")
191		c.DoSorted("KEYS", "*")
192		c.Do("EXPIRE", "key4", "0")
193		c.DoSorted("KEYS", "*")
194	})
195}
196
197func TestProto(t *testing.T) {
198	testRaw(t, func(c *client) {
199		c.Do("ECHO", strings.Repeat("X", 1<<24))
200	})
201}
202
203func TestSwapdb(t *testing.T) {
204	testRaw(t, func(c *client) {
205		c.Do("SET", "key1", "val1")
206		c.Do("SWAPDB", "0", "1")
207		c.Do("SELECT", "1")
208		c.Do("GET", "key1")
209
210		c.Do("SWAPDB", "1", "1")
211		c.Do("GET", "key1")
212
213		c.Do("SWAPDB")
214		c.Do("SWAPDB", "1")
215		c.Do("SWAPDB", "1", "2", "3")
216		c.Do("SWAPDB", "foo", "2")
217		c.Do("SWAPDB", "1", "bar")
218		c.Do("SWAPDB", "foo", "bar")
219		c.Do("SWAPDB", "-1", "2")
220		c.Do("SWAPDB", "1", "-2")
221		// c.Do("SWAPDB", "1", "1000") // miniredis has no upperlimit
222	})
223
224	// SWAPDB with transactions
225	testRaw2(t, func(c1, c2 *client) {
226		c1.Do("SET", "foo", "foooooo")
227
228		c1.Do("MULTI")
229		c1.Do("SWAPDB", "0", "2")
230		c1.Do("GET", "foo")
231		c2.Do("GET", "foo")
232
233		c1.Do("EXEC")
234		c1.Do("GET", "foo")
235		c2.Do("GET", "foo")
236	})
237}
238
239func TestDel(t *testing.T) {
240	testRaw(t, func(c *client) {
241		c.Do("SET", "one", "1")
242		c.Do("SET", "two", "2")
243		c.Do("SET", "three", "3")
244		c.Do("SET", "four", "4")
245		c.Do("DEL", "one")
246		c.DoSorted("KEYS", "*")
247
248		c.Do("DEL", "twoooo")
249		c.DoSorted("KEYS", "*")
250
251		c.Do("DEL", "two", "four")
252		c.DoSorted("KEYS", "*")
253
254		c.Do("DEL")
255		c.DoSorted("KEYS", "*")
256	})
257}
258
259func TestUnlink(t *testing.T) {
260	testRaw(t, func(c *client) {
261		c.Do("SET", "one", "1")
262		c.Do("SET", "two", "2")
263		c.Do("SET", "three", "3")
264		c.Do("SET", "four", "4")
265		c.Do("UNLINK", "one")
266		c.DoSorted("KEYS", "*")
267
268		c.Do("UNLINK", "twoooo")
269		c.DoSorted("KEYS", "*")
270
271		c.Do("UNLINK", "two", "four")
272		c.DoSorted("KEYS", "*")
273
274		c.Do("UNLINK")
275		c.DoSorted("KEYS", "*")
276	})
277}
278
279func TestTouch(t *testing.T) {
280	testRaw(t, func(c *client) {
281		c.Do("SET", "a", "some value")
282		c.Do("TOUCH", "a")
283		c.Do("GET", "a")
284		c.Do("TTL", "a")
285
286		c.Do("TOUCH", "a", "foobar", "a")
287
288		c.Do("TOUCH")
289	})
290}
291
292func TestPersist(t *testing.T) {
293	testRaw(t, func(c *client) {
294		c.Do("SET", "foo", "bar")
295		c.Do("EXPIRE", "foo", "12")
296		c.Do("TTL", "foo")
297		c.Do("PERSIST", "foo")
298		c.Do("TTL", "foo")
299	})
300}
301