strc 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +52 -16
- data/VERSION +1 -1
- data/lib/strc.rb +213 -20
- data/strc.gemspec +6 -2
- data/test/test_basic_functions.rb +74 -55
- data/test/test_keys.rb +83 -0
- data/test/test_lists.rb +151 -0
- data/test/test_sets.rb +21 -0
- metadata +15 -11
data/README.rdoc
CHANGED
@@ -1,8 +1,13 @@
|
|
1
1
|
= STRC - Super Terrible Redis Clone
|
2
2
|
|
3
|
-
STRC is a poor attempt to make a
|
3
|
+
STRC is a poor attempt to make a useless Ruby simulation of Redis. Why would you want that? Well, who knows. Maybe you:
|
4
|
+
* don't feel like installing Redis for some reason.
|
5
|
+
* need to be able to run tests on a machine without having to install Redis.
|
6
|
+
* like badly implemented clones.
|
4
7
|
|
5
|
-
|
8
|
+
I'll come out and say it, there's little reason for this to exist, and it's not really written in a fashion that is what you'd call good. It's just for shits and giggles. If that's your thing, read on.
|
9
|
+
|
10
|
+
One thing STRC does kind of have going for it is that it's much more lazy in regards to what you give it. Since you're passing it Ruby objects, that means you could just plop any old object in as a key or a value, instead of just a string. If that's something you're into.
|
6
11
|
|
7
12
|
== Usage
|
8
13
|
|
@@ -41,29 +46,60 @@ Now you could start passing it commands, if they've been implemented.
|
|
41
46
|
>> strc.smembers "stuff"
|
42
47
|
=> ["abc", "123"]
|
43
48
|
|
49
|
+
=== Lists!
|
50
|
+
>> strc.rpush "poo", "abc", "xyz"
|
51
|
+
=> 2
|
52
|
+
>> strc.lpush "poo", "123"
|
53
|
+
=> 3
|
54
|
+
>> strc.rpop "poo"
|
55
|
+
=> "xyz"
|
56
|
+
>> strc.llen "poo"
|
57
|
+
=> 2
|
58
|
+
|
44
59
|
== Command List
|
45
60
|
Currently, the following commands are implemented:
|
46
61
|
* get
|
47
62
|
* set
|
63
|
+
* setnx
|
48
64
|
* del
|
49
65
|
* exists
|
66
|
+
* append
|
67
|
+
* decr
|
68
|
+
* decrby
|
69
|
+
* incr
|
70
|
+
* incrby
|
50
71
|
* rename
|
51
72
|
* renamenx
|
52
|
-
*
|
53
|
-
*
|
54
|
-
*
|
55
|
-
*
|
56
|
-
*
|
57
|
-
*
|
58
|
-
*
|
59
|
-
*
|
60
|
-
*
|
61
|
-
*
|
62
|
-
*
|
63
|
-
*
|
64
|
-
*
|
65
|
-
*
|
73
|
+
* Sets
|
74
|
+
* sadd
|
75
|
+
* srem
|
76
|
+
* sismember
|
77
|
+
* smembers
|
78
|
+
* scard
|
79
|
+
* sinter
|
80
|
+
* sinterstore
|
81
|
+
* sdiff
|
82
|
+
* sdiffstore
|
83
|
+
* sunion
|
84
|
+
* sunionstore
|
85
|
+
* smove
|
86
|
+
* srandmember
|
87
|
+
* spop
|
88
|
+
* Lists
|
89
|
+
* lrange
|
90
|
+
* llen
|
91
|
+
* lpush
|
92
|
+
* lpushx
|
93
|
+
* lpop
|
94
|
+
* rpush
|
95
|
+
* rpushx
|
96
|
+
* rpop
|
97
|
+
* lindex
|
98
|
+
* lset
|
99
|
+
* ltrim
|
100
|
+
* rpoplpush
|
66
101
|
|
67
102
|
== History
|
103
|
+
* 0.0.3 - Some list commands done.
|
68
104
|
* 0.0.2 - Set commands done. Most general commands done.
|
69
105
|
* 0.0.1 - Initial release. Does some basic things.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.3
|
data/lib/strc.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
1
3
|
class STRC
|
2
4
|
Exception = Class.new(StandardError)
|
3
5
|
|
@@ -11,11 +13,75 @@ class STRC
|
|
11
13
|
return "OK"
|
12
14
|
end
|
13
15
|
|
16
|
+
# Set the value of a key only if it doesn't already exist.
|
17
|
+
def setnx(key, value)
|
18
|
+
unless exists(key)
|
19
|
+
set(key, value)
|
20
|
+
return true
|
21
|
+
end
|
22
|
+
return false
|
23
|
+
end
|
24
|
+
|
14
25
|
# Get the value for the given key
|
15
26
|
def get(key)
|
16
27
|
@dict[key]
|
17
28
|
end
|
18
29
|
|
30
|
+
# Append a value to a key
|
31
|
+
def append(key, value)
|
32
|
+
if exists(key)
|
33
|
+
item = get(key)
|
34
|
+
if item.class == String and value.class == String
|
35
|
+
set(key, item + value)
|
36
|
+
else
|
37
|
+
raise STRC::Exception.new "ERR Operation against a key holding the wrong kind of value"
|
38
|
+
end
|
39
|
+
else
|
40
|
+
set(key, value)
|
41
|
+
end
|
42
|
+
return get(key).length
|
43
|
+
end
|
44
|
+
|
45
|
+
# Decrement an integer
|
46
|
+
def decr(key)
|
47
|
+
decrby(key, 1)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Decrement an integer by a certain amount
|
51
|
+
def decrby(key, decrement)
|
52
|
+
unless exists(key)
|
53
|
+
set(key, 0)
|
54
|
+
end
|
55
|
+
value = get(key)
|
56
|
+
if value.class == Fixnum
|
57
|
+
set(key, value - decrement)
|
58
|
+
else
|
59
|
+
raise STRC::Exception.new "ERR Operation against a key holding the wrong kind of value"
|
60
|
+
end
|
61
|
+
get(key)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Increment an integer
|
65
|
+
def incr(key)
|
66
|
+
incrby(key, 1)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Increment an integer by a certain amount
|
70
|
+
def incrby(key, increment)
|
71
|
+
unless exists(key)
|
72
|
+
set(key, 0)
|
73
|
+
end
|
74
|
+
value = get(key)
|
75
|
+
if value.class == Fixnum
|
76
|
+
set(key, value + increment)
|
77
|
+
else
|
78
|
+
raise STRC::Exception.new "ERR Operation against a key holding the wrong kind of value"
|
79
|
+
end
|
80
|
+
get(key)
|
81
|
+
end
|
82
|
+
|
83
|
+
# Key commands!
|
84
|
+
|
19
85
|
# Delete a key
|
20
86
|
def del(*keys)
|
21
87
|
keys.each do |key|
|
@@ -54,22 +120,31 @@ class STRC
|
|
54
120
|
end
|
55
121
|
end
|
56
122
|
|
57
|
-
#
|
123
|
+
# End of key commands~
|
124
|
+
|
125
|
+
# Set commands!
|
58
126
|
|
59
127
|
# Add a member to a set
|
60
128
|
def sadd(key, *args)
|
61
129
|
if args.length < 1
|
62
130
|
raise STRC::Exception.new "Wrong number of arguments (1 for 2)"
|
63
131
|
end
|
64
|
-
set =
|
65
|
-
|
66
|
-
|
132
|
+
set = sget(key)
|
133
|
+
added = 0
|
134
|
+
args.each do |arg|
|
135
|
+
unless set.include?(arg)
|
136
|
+
set << arg
|
137
|
+
added += 1
|
138
|
+
end
|
139
|
+
end
|
140
|
+
@dict[key] = set
|
141
|
+
return added
|
67
142
|
end
|
68
143
|
|
69
144
|
# Remove a member from a set
|
70
145
|
def srem(key, member)
|
71
146
|
if sismember(key, member)
|
72
|
-
@dict[key].
|
147
|
+
@dict[key].delete(member)
|
73
148
|
return true
|
74
149
|
else
|
75
150
|
return false
|
@@ -80,13 +155,13 @@ class STRC
|
|
80
155
|
def sinter(*keys)
|
81
156
|
sets = []
|
82
157
|
keys.each do |key|
|
83
|
-
sets <<
|
158
|
+
sets << sget(key)
|
84
159
|
end
|
85
160
|
inter = sets.shift
|
86
161
|
sets.each do |set|
|
87
162
|
inter &= set
|
88
163
|
end
|
89
|
-
return inter
|
164
|
+
return inter.to_a
|
90
165
|
end
|
91
166
|
|
92
167
|
# Similar to SINTER, but stores in destination instead of returning
|
@@ -100,13 +175,13 @@ class STRC
|
|
100
175
|
def sdiff(*keys)
|
101
176
|
sets = []
|
102
177
|
keys.each do |key|
|
103
|
-
sets <<
|
178
|
+
sets << sget(key)
|
104
179
|
end
|
105
180
|
diff = sets.shift
|
106
181
|
sets.each do |set|
|
107
182
|
diff -= set
|
108
183
|
end
|
109
|
-
return diff
|
184
|
+
return diff.to_a
|
110
185
|
end
|
111
186
|
|
112
187
|
# Similar to SDIFF, but stores in destination instead of returning
|
@@ -117,7 +192,7 @@ class STRC
|
|
117
192
|
|
118
193
|
# Move an item from one set to another
|
119
194
|
def smove(source, destination, member)
|
120
|
-
|
195
|
+
unless sismember(source, member)
|
121
196
|
return false
|
122
197
|
end
|
123
198
|
srem(source, member)
|
@@ -129,6 +204,15 @@ class STRC
|
|
129
204
|
|
130
205
|
# Returs a list of all unique items in the given sets
|
131
206
|
def sunion(*keys)
|
207
|
+
sets = []
|
208
|
+
keys.each do |key|
|
209
|
+
sets << sget(key)
|
210
|
+
end
|
211
|
+
union = sets.shift
|
212
|
+
sets.each do |set|
|
213
|
+
union += set
|
214
|
+
end
|
215
|
+
return union.to_a
|
132
216
|
end
|
133
217
|
|
134
218
|
# Similar to SUNION, but stores in destination instead of returning
|
@@ -139,7 +223,7 @@ class STRC
|
|
139
223
|
|
140
224
|
# Returns a random element from the set
|
141
225
|
def srandmember(key)
|
142
|
-
|
226
|
+
sget(key).to_a.sample
|
143
227
|
end
|
144
228
|
|
145
229
|
# Randomly remove and return an item from the set
|
@@ -151,27 +235,136 @@ class STRC
|
|
151
235
|
|
152
236
|
# Determine if the given value is a member of the set at key
|
153
237
|
def sismember(key, member)
|
154
|
-
set =
|
155
|
-
return
|
238
|
+
set = sget(key)
|
239
|
+
return set.include?(member)
|
156
240
|
end
|
157
241
|
|
158
242
|
# Returns an array of members of the set
|
159
243
|
def smembers(key)
|
244
|
+
sget(key).to_a
|
245
|
+
end
|
246
|
+
|
247
|
+
# Gets the length of a set
|
248
|
+
def scard(key)
|
249
|
+
set = sget(key)
|
250
|
+
return set.length
|
251
|
+
end
|
252
|
+
|
253
|
+
# Gets a set. Private
|
254
|
+
def sget(key)
|
160
255
|
if exists(key)
|
161
256
|
value = get(key)
|
162
|
-
if value.class ==
|
257
|
+
if value.class == Set
|
163
258
|
return value
|
164
259
|
else
|
165
|
-
raise STRC::Exception
|
260
|
+
raise STRC::Exception.new "ERR Operation against a key holding the wrong kind of value"
|
166
261
|
end
|
167
262
|
else
|
168
|
-
return
|
263
|
+
return Set.new
|
169
264
|
end
|
170
265
|
end
|
171
266
|
|
172
|
-
#
|
173
|
-
|
174
|
-
|
175
|
-
|
267
|
+
# End of set commands~
|
268
|
+
|
269
|
+
# List commands!
|
270
|
+
|
271
|
+
# Gets a list. Private
|
272
|
+
def lget(key)
|
273
|
+
list = []
|
274
|
+
if exists(key)
|
275
|
+
list = get(key)
|
276
|
+
unless list.class == Array
|
277
|
+
raise STRC::Exception.new "ERR Operation against a key holding the wrong kind of value"
|
278
|
+
end
|
279
|
+
end
|
280
|
+
return list
|
281
|
+
end
|
282
|
+
|
283
|
+
# Returns elements from key in the given range
|
284
|
+
def lrange(key, start, stop)
|
285
|
+
list = lget(key)[start..stop]
|
286
|
+
return list.nil? ? [] : list
|
287
|
+
end
|
288
|
+
|
289
|
+
# Returns length of list
|
290
|
+
def llen(key)
|
291
|
+
lget(key).length
|
292
|
+
end
|
293
|
+
|
294
|
+
# Append values to a list
|
295
|
+
def rpush(key, *values)
|
296
|
+
list = lget(key)
|
297
|
+
list += values
|
298
|
+
set(key, list)
|
299
|
+
return list.length
|
300
|
+
end
|
301
|
+
|
302
|
+
# RPUSH if the list exists
|
303
|
+
def rpushx(key, *values)
|
304
|
+
if exists(key)
|
305
|
+
rpush(key, *values)
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
# Remove and get the last element in a list
|
310
|
+
def rpop(key)
|
311
|
+
list = lget(key)
|
312
|
+
element = list.pop
|
313
|
+
set(key, list)
|
314
|
+
return element
|
176
315
|
end
|
316
|
+
|
317
|
+
# Prepend values to a list
|
318
|
+
def lpush(key, *values)
|
319
|
+
list = lget(key)
|
320
|
+
list = values + list
|
321
|
+
set(key, list)
|
322
|
+
return list.length
|
323
|
+
end
|
324
|
+
|
325
|
+
# LPUSH if the list exists
|
326
|
+
def lpushx(key, *values)
|
327
|
+
if exists(key)
|
328
|
+
lpush(key, *values)
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
332
|
+
# Remove and get the first element in a list
|
333
|
+
def lpop(key)
|
334
|
+
list = lget(key)
|
335
|
+
element = list.shift
|
336
|
+
set(key, list)
|
337
|
+
return element
|
338
|
+
end
|
339
|
+
|
340
|
+
# Get an element from a list by its index
|
341
|
+
def lindex(key, index)
|
342
|
+
lget(key)[index]
|
343
|
+
end
|
344
|
+
|
345
|
+
# Set value for an element at index in a list
|
346
|
+
def lset(key, index, value)
|
347
|
+
list = lget(key)
|
348
|
+
list[index] = value
|
349
|
+
set(key, list)
|
350
|
+
end
|
351
|
+
|
352
|
+
# Trim a list to the specified range
|
353
|
+
def ltrim(key, start, stop)
|
354
|
+
set(key, lrange(key, start, stop))
|
355
|
+
end
|
356
|
+
|
357
|
+
# Removes an element from the end of one list and puts it at
|
358
|
+
# the beginning of another
|
359
|
+
def rpoplpush(source, destination)
|
360
|
+
lpush(destination, rpop(source))
|
361
|
+
end
|
362
|
+
|
363
|
+
# End of list commands~
|
364
|
+
|
365
|
+
# Hash commands!
|
366
|
+
|
367
|
+
# End of hash commands~
|
368
|
+
|
369
|
+
private :sget, :lget
|
177
370
|
end
|
data/strc.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{strc}
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.3"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Chris O'Neal"]
|
12
|
-
s.date = %q{2011-07-
|
12
|
+
s.date = %q{2011-07-15}
|
13
13
|
s.description = %q{STRC is a terrible Ruby clone of Redis}
|
14
14
|
s.email = %q{ctoneal@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -28,6 +28,8 @@ Gem::Specification.new do |s|
|
|
28
28
|
"strc.gemspec",
|
29
29
|
"test/helper.rb",
|
30
30
|
"test/test_basic_functions.rb",
|
31
|
+
"test/test_keys.rb",
|
32
|
+
"test/test_lists.rb",
|
31
33
|
"test/test_sets.rb",
|
32
34
|
"test/test_strc.rb"
|
33
35
|
]
|
@@ -39,6 +41,8 @@ Gem::Specification.new do |s|
|
|
39
41
|
s.test_files = [
|
40
42
|
"test/helper.rb",
|
41
43
|
"test/test_basic_functions.rb",
|
44
|
+
"test/test_keys.rb",
|
45
|
+
"test/test_lists.rb",
|
42
46
|
"test/test_sets.rb",
|
43
47
|
"test/test_strc.rb"
|
44
48
|
]
|
@@ -28,6 +28,21 @@ class TestBasicFunctions < Test::Unit::TestCase
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
+
context "setnx" do
|
32
|
+
should "be able to set the value of a new key" do
|
33
|
+
result = @test.setnx("test", 10)
|
34
|
+
assert(result)
|
35
|
+
end
|
36
|
+
|
37
|
+
should "not set value if the key already exists" do
|
38
|
+
@test.setnx("test", 10)
|
39
|
+
result = @test.setnx("test", 50)
|
40
|
+
assert(!result)
|
41
|
+
value = @test.get("test")
|
42
|
+
assert_equal(10, value)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
31
46
|
context "get" do
|
32
47
|
should "be able to get the value of a key" do
|
33
48
|
@test.set("test_key", 15)
|
@@ -41,79 +56,83 @@ class TestBasicFunctions < Test::Unit::TestCase
|
|
41
56
|
end
|
42
57
|
end
|
43
58
|
|
44
|
-
context "
|
45
|
-
should "
|
46
|
-
@test.set("test",
|
47
|
-
|
59
|
+
context "append" do
|
60
|
+
should "append to a string" do
|
61
|
+
@test.set("test", "Hello")
|
62
|
+
@test.append("test", " World")
|
63
|
+
value = @test.get("test")
|
64
|
+
assert_equal("Hello World", value)
|
48
65
|
end
|
49
66
|
|
50
|
-
should "return
|
51
|
-
|
67
|
+
should "return the new length of the string" do
|
68
|
+
@test.set("test", "Hello")
|
69
|
+
result = @test.append("test", " World")
|
70
|
+
assert_equal("Hello World".length, result)
|
52
71
|
end
|
53
|
-
end
|
54
72
|
|
55
|
-
|
56
|
-
|
57
|
-
@test.
|
58
|
-
|
59
|
-
assert_equal(1, deleted)
|
60
|
-
assert(!@test.exists("test"))
|
73
|
+
should "set if key doesn't exist" do
|
74
|
+
@test.append("test", "poop")
|
75
|
+
result = @test.get("test")
|
76
|
+
assert_equal("poop", result)
|
61
77
|
end
|
62
78
|
|
63
|
-
should "
|
64
|
-
@test.set("test",
|
65
|
-
@test.
|
66
|
-
@test.set("blah", 4)
|
67
|
-
deleted = @test.del("test", "poop")
|
68
|
-
assert_equal(2, deleted)
|
69
|
-
assert(!@test.exists("test"))
|
70
|
-
assert(!@test.exists("poop"))
|
71
|
-
assert(@test.exists("blah"))
|
79
|
+
should "not work for non string values" do
|
80
|
+
@test.set("test", 15)
|
81
|
+
assert_raise(STRC::Exception) { @test.append("test", "poop")}
|
72
82
|
end
|
73
83
|
end
|
74
84
|
|
75
|
-
context "
|
76
|
-
should "
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
end
|
81
|
-
random = @test.randomkey
|
82
|
-
assert_not_nil(keys.index(random))
|
85
|
+
context "incr" do
|
86
|
+
should "increment integers" do
|
87
|
+
@test.set("poop", 10)
|
88
|
+
@test.incr("poop")
|
89
|
+
assert_equal(11, @test.get("poop"))
|
83
90
|
end
|
84
|
-
end
|
85
91
|
|
86
|
-
|
87
|
-
|
88
|
-
@test.
|
89
|
-
@test.rename("poop", "abc")
|
90
|
-
value = @test.get("abc")
|
91
|
-
assert_equal(1, value)
|
92
|
+
should "not increment other types" do
|
93
|
+
@test.set("poop", "aaa")
|
94
|
+
assert_raise(STRC::Exception) { @test.incr("poop")}
|
92
95
|
end
|
93
96
|
|
94
|
-
should "
|
95
|
-
@test.set("poop",
|
96
|
-
@test.
|
97
|
-
|
98
|
-
value = @test.get("abc")
|
99
|
-
assert_equal(1, value)
|
97
|
+
should "return new value" do
|
98
|
+
@test.set("poop", 10)
|
99
|
+
result = @test.incr("poop")
|
100
|
+
assert_equal(11, result)
|
100
101
|
end
|
101
102
|
end
|
102
103
|
|
103
|
-
context "
|
104
|
-
should "
|
105
|
-
@test.set("poop",
|
106
|
-
@test.
|
107
|
-
|
108
|
-
assert_equal(1, value)
|
104
|
+
context "incrby" do
|
105
|
+
should "be able to increment by value" do
|
106
|
+
@test.set("poop", 10)
|
107
|
+
@test.incrby("poop", 10)
|
108
|
+
assert_equal(20, @test.get("poop"))
|
109
109
|
end
|
110
|
+
end
|
111
|
+
|
112
|
+
context "decr" do
|
113
|
+
should "decrement integers" do
|
114
|
+
@test.set("poop", 10)
|
115
|
+
@test.decr("poop")
|
116
|
+
assert_equal(9, @test.get("poop"))
|
117
|
+
end
|
118
|
+
|
119
|
+
should "not decrement other types" do
|
120
|
+
@test.set("poop", "aaa")
|
121
|
+
assert_raise(STRC::Exception) { @test.decr("poop")}
|
122
|
+
end
|
123
|
+
|
124
|
+
should "return new value" do
|
125
|
+
@test.set("poop", 10)
|
126
|
+
result = @test.decr("poop")
|
127
|
+
assert_equal(9, result)
|
128
|
+
end
|
129
|
+
end
|
110
130
|
|
111
|
-
|
112
|
-
|
113
|
-
@test.set("
|
114
|
-
@test.
|
115
|
-
|
116
|
-
assert_equal(2, value)
|
131
|
+
context "decrby" do
|
132
|
+
should "be able to decrement by value" do
|
133
|
+
@test.set("poop", 10)
|
134
|
+
@test.decrby("poop", 10)
|
135
|
+
assert_equal(0, @test.get("poop"))
|
117
136
|
end
|
118
137
|
end
|
119
138
|
end
|
data/test/test_keys.rb
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestKeys < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@test = STRC.new
|
6
|
+
end
|
7
|
+
|
8
|
+
context "exists" do
|
9
|
+
should "return true if the key exists" do
|
10
|
+
@test.set("test", 1)
|
11
|
+
assert(@test.exists("test"))
|
12
|
+
end
|
13
|
+
|
14
|
+
should "return false if the key doesn't exist" do
|
15
|
+
assert(!@test.exists("test"))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context "del" do
|
20
|
+
should "delete a key" do
|
21
|
+
@test.set("test", 1)
|
22
|
+
deleted = @test.del("test")
|
23
|
+
assert_equal(1, deleted)
|
24
|
+
assert(!@test.exists("test"))
|
25
|
+
end
|
26
|
+
|
27
|
+
should "delete multiple keys" do
|
28
|
+
@test.set("test", 1)
|
29
|
+
@test.set("poop", 2)
|
30
|
+
@test.set("blah", 4)
|
31
|
+
deleted = @test.del("test", "poop")
|
32
|
+
assert_equal(2, deleted)
|
33
|
+
assert(!@test.exists("test"))
|
34
|
+
assert(!@test.exists("poop"))
|
35
|
+
assert(@test.exists("blah"))
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context "randomkey" do
|
40
|
+
should "return a random key from the database" do
|
41
|
+
keys = ["test", "poop", "blah"]
|
42
|
+
keys.each do |key|
|
43
|
+
@test.set(key, 1)
|
44
|
+
end
|
45
|
+
random = @test.randomkey
|
46
|
+
assert_not_nil(keys.index(random))
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context "rename" do
|
51
|
+
should "rename a key" do
|
52
|
+
@test.set("poop", 1)
|
53
|
+
@test.rename("poop", "abc")
|
54
|
+
value = @test.get("abc")
|
55
|
+
assert_equal(1, value)
|
56
|
+
end
|
57
|
+
|
58
|
+
should "overwrite existing keys" do
|
59
|
+
@test.set("poop", 1)
|
60
|
+
@test.set("abc", 2)
|
61
|
+
@test.rename("poop", "abc")
|
62
|
+
value = @test.get("abc")
|
63
|
+
assert_equal(1, value)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context "renamenx" do
|
68
|
+
should "rename a key" do
|
69
|
+
@test.set("poop", 1)
|
70
|
+
@test.renamenx("poop", "abc")
|
71
|
+
value = @test.get("abc")
|
72
|
+
assert_equal(1, value)
|
73
|
+
end
|
74
|
+
|
75
|
+
should "not overwrite existing keys" do
|
76
|
+
@test.set("poop", 1)
|
77
|
+
@test.set("abc", 2)
|
78
|
+
@test.renamenx("poop", "abc")
|
79
|
+
value = @test.get("abc")
|
80
|
+
assert_equal(2, value)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
data/test/test_lists.rb
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestLists < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@test = STRC.new
|
6
|
+
@test.rpush("poop", "a", "b", "c")
|
7
|
+
end
|
8
|
+
|
9
|
+
context "lrange" do
|
10
|
+
should "return a range of elements" do
|
11
|
+
result = @test.lrange("poop", 1, 2)
|
12
|
+
assert_equal(["b", "c"], result)
|
13
|
+
end
|
14
|
+
|
15
|
+
should "be zero based" do
|
16
|
+
result = @test.lrange("poop", 0, 0)
|
17
|
+
assert_equal(["a"], result)
|
18
|
+
end
|
19
|
+
|
20
|
+
should "work with negative numbers" do
|
21
|
+
result = @test.lrange("poop", -3, 2)
|
22
|
+
assert_equal(["a", "b", "c"], result)
|
23
|
+
end
|
24
|
+
|
25
|
+
should "indexing out should give an empty list" do
|
26
|
+
result = @test.lrange("poop", 5, 10)
|
27
|
+
assert_equal([], result)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "llen" do
|
32
|
+
should "return length of the list" do
|
33
|
+
result = @test.llen("poop")
|
34
|
+
assert_equal(3, result)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context "rpush" do
|
39
|
+
should "create a new list" do
|
40
|
+
@test.rpush("asdf", "abc")
|
41
|
+
assert(@test.exists("asdf"))
|
42
|
+
assert_equal(["abc"], @test.lrange("asdf", 0, -1))
|
43
|
+
end
|
44
|
+
|
45
|
+
should "push onto the end of existing lists" do
|
46
|
+
@test.rpush("poop", "d", "e")
|
47
|
+
assert_equal(["a", "b", "c", "d", "e"], @test.lrange("poop", 0, -1))
|
48
|
+
end
|
49
|
+
|
50
|
+
should "return new length of list" do
|
51
|
+
len = @test.rpush("poop", "d", "e")
|
52
|
+
assert_equal(@test.lrange("poop", 0, -1).length, len)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context "rpushx" do
|
57
|
+
should "not be able to create a new list" do
|
58
|
+
@test.rpushx("asdf", "abc")
|
59
|
+
assert(!@test.exists("asdf"))
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context "rpop" do
|
64
|
+
should "return the last element in the list" do
|
65
|
+
element = @test.rpop("poop")
|
66
|
+
assert_equal("c", element)
|
67
|
+
end
|
68
|
+
|
69
|
+
should "remove the last element in the list" do
|
70
|
+
@test.rpop("poop")
|
71
|
+
assert_equal(["a", "b"], @test.lrange("poop", 0, -1))
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context "lpush" do
|
76
|
+
should "create a new list" do
|
77
|
+
@test.lpush("asdf", "abc")
|
78
|
+
assert(@test.exists("asdf"))
|
79
|
+
assert_equal(["abc"], @test.lrange("asdf", 0, -1))
|
80
|
+
end
|
81
|
+
|
82
|
+
should "push onto the beginning of existing lists" do
|
83
|
+
@test.lpush("poop", "d", "e")
|
84
|
+
assert_equal(["d", "e", "a", "b", "c"], @test.lrange("poop", 0, -1))
|
85
|
+
end
|
86
|
+
|
87
|
+
should "return new length of list" do
|
88
|
+
len = @test.lpush("poop", "d", "e")
|
89
|
+
assert_equal(@test.lrange("poop", 0, -1).length, len)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context "lpushx" do
|
94
|
+
should "not be able to create a new list" do
|
95
|
+
@test.lpushx("asdf", "abc")
|
96
|
+
assert(!@test.exists("asdf"))
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
context "lpop" do
|
101
|
+
should "return the first element in the list" do
|
102
|
+
element = @test.lpop("poop")
|
103
|
+
assert_equal("a", element)
|
104
|
+
end
|
105
|
+
|
106
|
+
should "remove the first element in the list" do
|
107
|
+
@test.lpop("poop")
|
108
|
+
assert_equal(["b", "c"], @test.lrange("poop", 0, -1))
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
context "lindex" do
|
113
|
+
should "return value at index" do
|
114
|
+
result = @test.lindex("poop", 1)
|
115
|
+
assert_equal("b", result)
|
116
|
+
end
|
117
|
+
|
118
|
+
should "work with negative numbers" do
|
119
|
+
result = @test.lindex("poop", -2)
|
120
|
+
assert_equal("b", result)
|
121
|
+
end
|
122
|
+
|
123
|
+
should "return nil for out of range" do
|
124
|
+
result = @test.lindex("poop", 10)
|
125
|
+
assert_nil(result)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
context "lset" do
|
130
|
+
should "set value at index" do
|
131
|
+
@test.lset("poop", 2, "test")
|
132
|
+
assert_equal("test", @test.lindex("poop", 2))
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
context "ltrim" do
|
137
|
+
should "trim the list to the range" do
|
138
|
+
@test.ltrim("poop", 1, -1)
|
139
|
+
assert_equal(["b", "c"], @test.lrange("poop", 0, -1))
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
context "rpoplpush" do
|
144
|
+
should "take an element from the end of one list and put it on the front of another" do
|
145
|
+
@test.lpush("asdf", "123")
|
146
|
+
@test.rpoplpush("poop", "asdf")
|
147
|
+
assert_equal(["a", "b"], @test.lrange("poop", 0, -1))
|
148
|
+
assert_equal(["c", "123"], @test.lrange("asdf", 0, -1))
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
data/test/test_sets.rb
CHANGED
@@ -129,6 +129,27 @@ class TestSets < Test::Unit::TestCase
|
|
129
129
|
end
|
130
130
|
end
|
131
131
|
|
132
|
+
context "sunion" do
|
133
|
+
should "give all unique members of given sets" do
|
134
|
+
@test.sadd("set1", "a", "b", "c", "d")
|
135
|
+
@test.sadd("set2", "c")
|
136
|
+
@test.sadd("set3", "a", "c", "e")
|
137
|
+
result = @test.sunion("set1", "set2", "set3")
|
138
|
+
assert_equal(["a", "b", "c", "d", "e"], result)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
context "sunionstore" do
|
143
|
+
should "work like sunion, but store in destination" do
|
144
|
+
@test.sadd("set1", "a", "b", "c", "d")
|
145
|
+
@test.sadd("set2", "c")
|
146
|
+
@test.sadd("set3", "a", "c", "e")
|
147
|
+
@test.sunionstore("new", "set1", "set2", "set3")
|
148
|
+
result = @test.smembers("new")
|
149
|
+
assert_equal(["a", "b", "c", "d", "e"], result)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
132
153
|
context "smove" do
|
133
154
|
should "move an item from one set to another" do
|
134
155
|
@test.sadd("set1", "one" ,"two")
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: strc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,12 +9,12 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-07-
|
12
|
+
date: 2011-07-15 00:00:00.000000000 -05:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: shoulda
|
17
|
-
requirement: &
|
17
|
+
requirement: &9732852 !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
20
|
- - ! '>='
|
@@ -22,10 +22,10 @@ dependencies:
|
|
22
22
|
version: '0'
|
23
23
|
type: :development
|
24
24
|
prerelease: false
|
25
|
-
version_requirements: *
|
25
|
+
version_requirements: *9732852
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: bundler
|
28
|
-
requirement: &
|
28
|
+
requirement: &9732216 !ruby/object:Gem::Requirement
|
29
29
|
none: false
|
30
30
|
requirements:
|
31
31
|
- - ~>
|
@@ -33,10 +33,10 @@ dependencies:
|
|
33
33
|
version: 1.0.0
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
|
-
version_requirements: *
|
36
|
+
version_requirements: *9732216
|
37
37
|
- !ruby/object:Gem::Dependency
|
38
38
|
name: jeweler
|
39
|
-
requirement: &
|
39
|
+
requirement: &9726516 !ruby/object:Gem::Requirement
|
40
40
|
none: false
|
41
41
|
requirements:
|
42
42
|
- - ~>
|
@@ -44,10 +44,10 @@ dependencies:
|
|
44
44
|
version: 1.5.2
|
45
45
|
type: :development
|
46
46
|
prerelease: false
|
47
|
-
version_requirements: *
|
47
|
+
version_requirements: *9726516
|
48
48
|
- !ruby/object:Gem::Dependency
|
49
49
|
name: rcov
|
50
|
-
requirement: &
|
50
|
+
requirement: &9726036 !ruby/object:Gem::Requirement
|
51
51
|
none: false
|
52
52
|
requirements:
|
53
53
|
- - ! '>='
|
@@ -55,7 +55,7 @@ dependencies:
|
|
55
55
|
version: '0'
|
56
56
|
type: :development
|
57
57
|
prerelease: false
|
58
|
-
version_requirements: *
|
58
|
+
version_requirements: *9726036
|
59
59
|
description: STRC is a terrible Ruby clone of Redis
|
60
60
|
email: ctoneal@gmail.com
|
61
61
|
executables: []
|
@@ -75,6 +75,8 @@ files:
|
|
75
75
|
- strc.gemspec
|
76
76
|
- test/helper.rb
|
77
77
|
- test/test_basic_functions.rb
|
78
|
+
- test/test_keys.rb
|
79
|
+
- test/test_lists.rb
|
78
80
|
- test/test_sets.rb
|
79
81
|
- test/test_strc.rb
|
80
82
|
has_rdoc: true
|
@@ -93,7 +95,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
93
95
|
version: '0'
|
94
96
|
segments:
|
95
97
|
- 0
|
96
|
-
hash:
|
98
|
+
hash: 230414097
|
97
99
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
98
100
|
none: false
|
99
101
|
requirements:
|
@@ -109,5 +111,7 @@ summary: Super Terrible Redis Clone
|
|
109
111
|
test_files:
|
110
112
|
- test/helper.rb
|
111
113
|
- test/test_basic_functions.rb
|
114
|
+
- test/test_keys.rb
|
115
|
+
- test/test_lists.rb
|
112
116
|
- test/test_sets.rb
|
113
117
|
- test/test_strc.rb
|