xref: /redis-3.2.3/tests/unit/sort.tcl (revision 80586cb8)
1start_server {
2    tags {"sort"}
3    overrides {
4        "list-max-ziplist-value" 16
5        "list-max-ziplist-entries" 32
6        "set-max-intset-entries" 32
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
38    foreach {num cmd enc title} {
39        16 lpush ziplist "Ziplist"
40        1000 lpush linkedlist "Linked list"
41        10000 lpush linkedlist "Big Linked list"
42        16 sadd intset "Intset"
43        1000 sadd hashtable "Hash table"
44        10000 sadd hashtable "Big Hash table"
45    } {
46        set result [create_random_dataset $num $cmd]
47        assert_encoding $enc tosort
48
49        test "$title: SORT BY key" {
50            assert_equal $result [r sort tosort BY weight_*]
51        }
52
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
57        test "$title: SORT BY hash field" {
58            assert_equal $result [r sort tosort BY wobj_*->weight]
59        }
60    }
61
62    set result [create_random_dataset 16 lpush]
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" {
85        r sort tosort BY weight_* store sort-res
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" {
92        r sort tosort BY wobj_*->weight store sort-res
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" {
99        assert_equal [lsort -decreasing -integer $result] [r sort tosort DESC]
100    }
101
102    test "SORT ALPHA against integer encoded strings" {
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
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}
120
121    test "SORT sorted set: +inf and -inf handling" {
122        r del zset
123        r zadd zset -100 a
124        r zadd zset 200 b
125        r zadd zset -300 c
126        r zadd zset 1000000 d
127        r zadd zset +inf max
128        r zadd zset -inf min
129        r zrange zset 0 -1
130    } {min c a b d max}
131
132    test "SORT regression for issue #19, sorting floats" {
133        r flushdb
134        set floats {1.1 5.10 3.10 7.44 2.1 5.75 6.12 0.25 1.15}
135        foreach x $floats {
136            r lpush mylist $x
137        }
138        assert_equal [lsort -real $floats] [r sort mylist]
139    }
140
141    test "SORT with STORE returns zero if result is empty (github isse 224)" {
142        r flushdb
143        r sort foo store bar
144    } {0}
145
146    test "SORT with STORE does not create empty lists (github issue 224)" {
147        r flushdb
148        r lpush foo bar
149        r sort foo limit 10 10 store zap
150        r exists zap
151    } {0}
152
153    tags {"slow"} {
154        set num 100
155        set res [create_random_dataset $num lpush]
156
157        test "SORT speed, $num element list BY key, 100 times" {
158            set start [clock clicks -milliseconds]
159            for {set i 0} {$i < 100} {incr i} {
160                set sorted [r sort tosort BY weight_* LIMIT 0 10]
161            }
162            set elapsed [expr [clock clicks -milliseconds]-$start]
163            if {$::verbose} {
164                puts -nonewline "\n  Average time to sort: [expr double($elapsed)/100] milliseconds "
165                flush stdout
166            }
167        }
168
169        test "SORT speed, $num element list BY hash field, 100 times" {
170            set start [clock clicks -milliseconds]
171            for {set i 0} {$i < 100} {incr i} {
172                set sorted [r sort tosort BY wobj_*->weight LIMIT 0 10]
173            }
174            set elapsed [expr [clock clicks -milliseconds]-$start]
175            if {$::verbose} {
176                puts -nonewline "\n  Average time to sort: [expr double($elapsed)/100] milliseconds "
177                flush stdout
178            }
179        }
180
181        test "SORT speed, $num element list directly, 100 times" {
182            set start [clock clicks -milliseconds]
183            for {set i 0} {$i < 100} {incr i} {
184                set sorted [r sort tosort LIMIT 0 10]
185            }
186            set elapsed [expr [clock clicks -milliseconds]-$start]
187            if {$::verbose} {
188                puts -nonewline "\n  Average time to sort: [expr double($elapsed)/100] milliseconds "
189                flush stdout
190            }
191        }
192
193        test "SORT speed, $num element list BY <const>, 100 times" {
194            set start [clock clicks -milliseconds]
195            for {set i 0} {$i < 100} {incr i} {
196                set sorted [r sort tosort BY nokey LIMIT 0 10]
197            }
198            set elapsed [expr [clock clicks -milliseconds]-$start]
199            if {$::verbose} {
200                puts -nonewline "\n  Average time to sort: [expr double($elapsed)/100] milliseconds "
201                flush stdout
202            }
203        }
204    }
205}
206