]> git.saurik.com Git - redis.git/blame - tests/unit/sort.tcl
Copyright date fixed in COPYING file.
[redis.git] / tests / unit / sort.tcl
CommitLineData
5d4f3a8c
PN
1start_server {
2 tags {"sort"}
3 overrides {
4 "list-max-ziplist-value" 16
5 "list-max-ziplist-entries" 32
2b9a5947 6 "set-max-intset-entries" 32
5d4f3a8c
PN
7 }
8} {
9 proc create_random_dataset {num cmd} {
10 set tosort {}
11 set result {}
12 array set seenrand {}
13 r del tosort
14 for {set i 0} {$i < $num} {incr i} {
15 # Make sure all the weights are different because
16 # Redis does not use a stable sort but Tcl does.
17 while 1 {
18 randpath {
19 set rint [expr int(rand()*1000000)]
20 } {
21 set rint [expr rand()]
22 }
23 if {![info exists seenrand($rint)]} break
24 }
25 set seenrand($rint) x
26 r $cmd tosort $i
27 r set weight_$i $rint
28 r hset wobj_$i weight $rint
29 lappend tosort [list $i $rint]
30 }
31 set sorted [lsort -index 1 -real $tosort]
32 for {set i 0} {$i < $num} {incr i} {
33 lappend result [lindex $sorted $i 0]
34 }
35 set _ $result
36 }
37
ced6709c
PN
38 foreach {num cmd enc title} {
39 16 lpush ziplist "Ziplist"
452ccf7a 40 1000 lpush linkedlist "Linked list"
41 10000 lpush linkedlist "Big Linked list"
029e5577 42 16 sadd intset "Intset"
452ccf7a 43 1000 sadd hashtable "Hash table"
44 10000 sadd hashtable "Big Hash table"
ced6709c
PN
45 } {
46 set result [create_random_dataset $num $cmd]
47 assert_encoding $enc tosort
48
49 test "$title: SORT BY key" {
dc11daf3 50 assert_equal $result [r sort tosort BY weight_*]
ced6709c 51 }
5d4f3a8c 52
f54c2990
B
53 test "$title: SORT BY key with limit" {
54 assert_equal [lrange $result 5 9] [r sort tosort BY weight_* LIMIT 5 5]
55 }
56
ced6709c 57 test "$title: SORT BY hash field" {
dc11daf3 58 assert_equal $result [r sort tosort BY wobj_*->weight]
ced6709c 59 }
5d4f3a8c
PN
60 }
61
ced6709c 62 set result [create_random_dataset 16 lpush]
5d4f3a8c
PN
63 test "SORT GET #" {
64 assert_equal [lsort -integer $result] [r sort tosort GET #]
65 }
66
67 test "SORT GET <const>" {
68 r del foo
69 set res [r sort tosort GET foo]
70 assert_equal 16 [llength $res]
71 foreach item $res { assert_equal {} $item }
72 }
73
74 test "SORT GET (key and hash) with sanity check" {
75 set l1 [r sort tosort GET # GET weight_*]
76 set l2 [r sort tosort GET # GET wobj_*->weight]
77 foreach {id1 w1} $l1 {id2 w2} $l2 {
78 assert_equal $id1 $id2
79 assert_equal $w1 [r get weight_$id1]
80 assert_equal $w2 [r get weight_$id1]
81 }
82 }
83
84 test "SORT BY key STORE" {
dc11daf3 85 r sort tosort BY weight_* store sort-res
5d4f3a8c
PN
86 assert_equal $result [r lrange sort-res 0 -1]
87 assert_equal 16 [r llen sort-res]
88 assert_encoding ziplist sort-res
89 }
90
91 test "SORT BY hash field STORE" {
dc11daf3 92 r sort tosort BY wobj_*->weight store sort-res
5d4f3a8c
PN
93 assert_equal $result [r lrange sort-res 0 -1]
94 assert_equal 16 [r llen sort-res]
95 assert_encoding ziplist sort-res
96 }
97
98 test "SORT DESC" {
dc11daf3 99 assert_equal [lsort -decreasing -integer $result] [r sort tosort DESC]
5d4f3a8c
PN
100 }
101
102 test "SORT ALPHA against integer encoded strings" {
98578b57
PN
103 r del mylist
104 r lpush mylist 2
105 r lpush mylist 1
106 r lpush mylist 3
107 r lpush mylist 10
108 r sort mylist alpha
109 } {1 10 2 3}
110
5d4f3a8c
PN
111 test "SORT sorted set" {
112 r del zset
113 r zadd zset 1 a
114 r zadd zset 5 b
115 r zadd zset 2 c
116 r zadd zset 10 d
117 r zadd zset 3 e
118 r sort zset alpha desc
119 } {e d c b a}
98578b57 120
9a914a63 121 test "SORT sorted set BY nosort should retain ordering" {
122 r del zset
123 r zadd zset 1 a
124 r zadd zset 5 b
125 r zadd zset 2 c
126 r zadd zset 10 d
127 r zadd zset 3 e
128 r multi
129 r sort zset by nosort asc
130 r sort zset by nosort desc
131 r exec
132 } {{a c e b d} {d b e c a}}
133
134 test "SORT sorted set BY nosort + LIMIT" {
135 r del zset
136 r zadd zset 1 a
137 r zadd zset 5 b
138 r zadd zset 2 c
139 r zadd zset 10 d
140 r zadd zset 3 e
141 assert_equal [r sort zset by nosort asc limit 0 1] {a}
142 assert_equal [r sort zset by nosort desc limit 0 1] {d}
143 assert_equal [r sort zset by nosort asc limit 0 2] {a c}
144 assert_equal [r sort zset by nosort desc limit 0 2] {d b}
145 assert_equal [r sort zset by nosort limit 5 10] {}
146 assert_equal [r sort zset by nosort limit -10 100] {a c e b d}
147 }
148
149 test "SORT sorted set BY nosort works as expected from scripts" {
150 r del zset
151 r zadd zset 1 a
152 r zadd zset 5 b
153 r zadd zset 2 c
154 r zadd zset 10 d
155 r zadd zset 3 e
156 r eval {
157 return {redis.call('sort','zset','by','nosort','asc'),
158 redis.call('sort','zset','by','nosort','desc')}
159 } 0
160 } {{a c e b d} {d b e c a}}
161
5d4f3a8c
PN
162 test "SORT sorted set: +inf and -inf handling" {
163 r del zset
164 r zadd zset -100 a
165 r zadd zset 200 b
166 r zadd zset -300 c
167 r zadd zset 1000000 d
168 r zadd zset +inf max
169 r zadd zset -inf min
170 r zrange zset 0 -1
171 } {min c a b d max}
98578b57 172
5d4f3a8c
PN
173 test "SORT regression for issue #19, sorting floats" {
174 r flushdb
175 set floats {1.1 5.10 3.10 7.44 2.1 5.75 6.12 0.25 1.15}
176 foreach x $floats {
177 r lpush mylist $x
178 }
179 assert_equal [lsort -real $floats] [r sort mylist]
180 }
98578b57 181
237194b7 182 test "SORT with STORE returns zero if result is empty (github isse 224)" {
183 r flushdb
184 r sort foo store bar
185 } {0}
186
187 test "SORT with STORE does not create empty lists (github issue 224)" {
188 r flushdb
189 r lpush foo bar
2c861050 190 r sort foo alpha limit 10 10 store zap
237194b7 191 r exists zap
192 } {0}
193
a0bf8d0a
MK
194 test "SORT with STORE removes key if result is empty (github issue 227)" {
195 r flushdb
196 r lpush foo bar
197 r sort emptylist store foo
198 r exists foo
199 } {0}
200
de79a2ee 201 test "SORT with BY <constant> and STORE should still order output" {
202 r del myset mylist
44d77bb2 203 r sadd myset a b c d e f g h i l m n o p q r s t u v z aa aaa azz
de79a2ee 204 r sort myset alpha by _ store mylist
205 r lrange mylist 0 -1
44d77bb2 206 } {a aa aaa azz b c d e f g h i l m n o p q r s t u v z}
de79a2ee 207
01f75bf3 208 test "SORT will complain with numerical sorting and bad doubles (1)" {
209 r del myset
210 r sadd myset 1 2 3 4 not-a-double
211 set e {}
212 catch {r sort myset} e
213 set e
214 } {*ERR*double*}
215
216 test "SORT will complain with numerical sorting and bad doubles (2)" {
217 r del myset
218 r sadd myset 1 2 3 4
219 r mset score:1 10 score:2 20 score:3 30 score:4 not-a-double
220 set e {}
221 catch {r sort myset by score:*} e
222 set e
223 } {*ERR*double*}
224
225 test "SORT BY sub-sorts lexicographically if score is the same" {
226 r del myset
44d77bb2 227 r sadd myset a b c d e f g h i l m n o p q r s t u v z aa aaa azz
228 foreach ele {a aa aaa azz b c d e f g h i l m n o p q r s t u v z} {
01f75bf3 229 set score:$ele 100
230 }
231 r sort myset by score:*
44d77bb2 232 } {a aa aaa azz b c d e f g h i l m n o p q r s t u v z}
01f75bf3 233
6a3f0ac6 234 test "SORT GET with pattern ending with just -> does not get hash field" {
235 r del mylist
236 r lpush mylist a
237 r set x:a-> 100
238 r sort mylist by num get x:*->
239 } {100}
240
5d4f3a8c
PN
241 tags {"slow"} {
242 set num 100
243 set res [create_random_dataset $num lpush]
98578b57 244
5d4f3a8c 245 test "SORT speed, $num element list BY key, 100 times" {
7f7499ee
PN
246 set start [clock clicks -milliseconds]
247 for {set i 0} {$i < 100} {incr i} {
dc11daf3 248 set sorted [r sort tosort BY weight_* LIMIT 0 10]
7f7499ee
PN
249 }
250 set elapsed [expr [clock clicks -milliseconds]-$start]
6f8a32d5
PN
251 if {$::verbose} {
252 puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds "
253 flush stdout
254 }
5d4f3a8c 255 }
98578b57 256
5d4f3a8c 257 test "SORT speed, $num element list BY hash field, 100 times" {
7f7499ee
PN
258 set start [clock clicks -milliseconds]
259 for {set i 0} {$i < 100} {incr i} {
dc11daf3 260 set sorted [r sort tosort BY wobj_*->weight LIMIT 0 10]
7f7499ee
PN
261 }
262 set elapsed [expr [clock clicks -milliseconds]-$start]
6f8a32d5
PN
263 if {$::verbose} {
264 puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds "
265 flush stdout
266 }
5d4f3a8c 267 }
98578b57 268
5d4f3a8c 269 test "SORT speed, $num element list directly, 100 times" {
7f7499ee
PN
270 set start [clock clicks -milliseconds]
271 for {set i 0} {$i < 100} {incr i} {
dc11daf3 272 set sorted [r sort tosort LIMIT 0 10]
7f7499ee
PN
273 }
274 set elapsed [expr [clock clicks -milliseconds]-$start]
6f8a32d5
PN
275 if {$::verbose} {
276 puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds "
277 flush stdout
278 }
5d4f3a8c 279 }
98578b57 280
5d4f3a8c 281 test "SORT speed, $num element list BY <const>, 100 times" {
7f7499ee
PN
282 set start [clock clicks -milliseconds]
283 for {set i 0} {$i < 100} {incr i} {
dc11daf3 284 set sorted [r sort tosort BY nokey LIMIT 0 10]
7f7499ee
PN
285 }
286 set elapsed [expr [clock clicks -milliseconds]-$start]
6f8a32d5
PN
287 if {$::verbose} {
288 puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds "
289 flush stdout
290 }
98578b57 291 }
5d4f3a8c 292 }
98578b57 293}