fakeredis 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/.rspec +1 -0
- data/.travis.yml +6 -0
- data/Gemfile +4 -0
- data/LICENSE +21 -0
- data/README.md +40 -0
- data/Rakefile +26 -0
- data/fakeredis.gemspec +23 -0
- data/lib/fakeredis.rb +26 -0
- data/lib/fakeredis/connection.rb +25 -0
- data/lib/fakeredis/hashes.rb +98 -0
- data/lib/fakeredis/keys.rb +82 -0
- data/lib/fakeredis/lists.rb +108 -0
- data/lib/fakeredis/server.rb +65 -0
- data/lib/fakeredis/sets.rb +122 -0
- data/lib/fakeredis/sorted_sets.rb +108 -0
- data/lib/fakeredis/strings.rb +112 -0
- data/lib/fakeredis/transactions.rb +13 -0
- data/lib/fakeredis/version.rb +3 -0
- data/spec/connection_spec.rb +22 -0
- data/spec/hashes_spec.rb +98 -0
- data/spec/keys_spec.rb +95 -0
- data/spec/lists_spec.rb +134 -0
- data/spec/server_spec.rb +28 -0
- data/spec/sets_spec.rb +153 -0
- data/spec/sorted_sets_spec.rb +81 -0
- data/spec/spec_helper.rb +5 -0
- data/spec/strings_spec.rb +140 -0
- data/spec/transactions_spec.rb +19 -0
- metadata +102 -0
data/spec/hashes_spec.rb
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module FakeRedis
|
4
|
+
describe "HashesMethods" do
|
5
|
+
before(:each) do
|
6
|
+
@client = FakeRedis::Redis.new
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should delete a hash field" do
|
10
|
+
@client.hset("key1", "k1", "val1")
|
11
|
+
@client.hset("key1", "k2", "val2")
|
12
|
+
@client.hdel("key1", "k1")
|
13
|
+
|
14
|
+
@client.hget("key1", "k1").should be_nil
|
15
|
+
@client.hget("key1", "k2").should == "val2"
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should determine if a hash field exists" do
|
19
|
+
@client.hset("key1", "index", "value")
|
20
|
+
|
21
|
+
@client.hexists("key1", "index").should be_true
|
22
|
+
@client.hexists("key2", "i2").should be_false
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should get the value of a hash field" do
|
26
|
+
@client.hset("key1", "index", "value")
|
27
|
+
|
28
|
+
@client.hget("key1", "index").should == "value"
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should get all the fields and values in a hash" do
|
32
|
+
@client.hset("key1", "i1", "val1")
|
33
|
+
@client.hset("key1", "i2", "val2")
|
34
|
+
|
35
|
+
@client.hgetall("key1").should == {"i1" => "val1", "i2" => "val2"}
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should increment the integer value of a hash field by the given number" do
|
39
|
+
@client.hset("key1", "cont1", "5")
|
40
|
+
@client.hincrby("key1", "cont1", "5")
|
41
|
+
|
42
|
+
@client.hget("key1", "cont1").should == "10"
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should get all the fields in a hash" do
|
46
|
+
@client.hset("key1", "i1", "val1")
|
47
|
+
@client.hset("key1", "i2", "val2")
|
48
|
+
|
49
|
+
@client.hkeys("key1").should =~ ["i1", "i2"]
|
50
|
+
@client.hkeys("key2").should == []
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should get the number of fields in a hash" do
|
54
|
+
@client.hset("key1", "i1", "val1")
|
55
|
+
@client.hset("key1", "i2", "val2")
|
56
|
+
|
57
|
+
@client.hlen("key1").should == 2
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should get the values of all the given hash fields" do
|
61
|
+
@client.hset("key1", "i1", "val1")
|
62
|
+
@client.hset("key1", "i2", "val2")
|
63
|
+
|
64
|
+
@client.hmget("key1", "i1", "i2", "i3").should =~ ["val1", "val2", nil]
|
65
|
+
@client.hmget("key2", "i1", "i2").should == [nil, nil]
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should set multiple hash fields to multiple values" do
|
69
|
+
@client.hmset("key", "k1", "value1", "k2", "value2")
|
70
|
+
|
71
|
+
@client.hget("key", "k1").should == "value1"
|
72
|
+
@client.hget("key", "k2").should == "value2"
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should set the string value of a hash field" do
|
76
|
+
@client.hset("key1", "k1", "val1")
|
77
|
+
|
78
|
+
@client.hget("key1", "k1").should == "val1"
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should set the value of a hash field, only if the field does not exist" do
|
82
|
+
@client.hset("key1", "k1", "val1")
|
83
|
+
@client.hsetnx("key1", "k1", "value")
|
84
|
+
@client.hsetnx("key1", "k2", "val2")
|
85
|
+
|
86
|
+
@client.hget("key1", "k1").should == "val1"
|
87
|
+
@client.hget("key1", "k2").should == "val2"
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should get all the values in a hash" do
|
91
|
+
@client.hset("key1", "k1", "val1")
|
92
|
+
@client.hset("key1", "k2", "val2")
|
93
|
+
|
94
|
+
@client.hvals("key1").should =~ ["val1", "val2"]
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
end
|
data/spec/keys_spec.rb
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module FakeRedis
|
4
|
+
describe "KeysMethods" do
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
@client = FakeRedis::Redis.new
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should delete a key" do
|
11
|
+
@client.set("key1", "1")
|
12
|
+
@client.set("key2", "2")
|
13
|
+
@client.del("key1", "key2")
|
14
|
+
|
15
|
+
@client.get("key1").should == nil
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should determine if a key exists" do
|
19
|
+
@client.set("key1", "1")
|
20
|
+
|
21
|
+
@client.exists("key1").should == true
|
22
|
+
@client.exists("key2").should == false
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should set a key's time to live in seconds" do
|
26
|
+
@client.set("key1", "1")
|
27
|
+
@client.expire("key1", 1)
|
28
|
+
|
29
|
+
@client.ttl("key1").should == 1
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should set the expiration for a key as a UNIX timestamp" do
|
33
|
+
@client.set("key1", "1")
|
34
|
+
@client.expireat("key1", Time.now.to_i + 2)
|
35
|
+
|
36
|
+
@client.ttl("key1").should == 1
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should find all keys matching the given pattern" do
|
40
|
+
@client.set("key:a", "1")
|
41
|
+
@client.set("key:b", "2")
|
42
|
+
@client.set("key:c", "3")
|
43
|
+
@client.set("akeyd", "4")
|
44
|
+
@client.set("key1", "5")
|
45
|
+
|
46
|
+
@client.keys("key:").should =~ ["key:a", "key:b", "key:c"]
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should remove the expiration from a key" do
|
50
|
+
@client.set("key1", "1")
|
51
|
+
@client.persist("key1")
|
52
|
+
|
53
|
+
@client.ttl("key1").should == -1
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should return a random key from the keyspace" do
|
57
|
+
@client.set("key1", "1")
|
58
|
+
@client.set("key2", "2")
|
59
|
+
|
60
|
+
["key1", "key2"].include?(@client.randomkey).should == true
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should rename a key" do
|
64
|
+
@client.set("key1", "2")
|
65
|
+
@client.rename("key1", "key2")
|
66
|
+
|
67
|
+
@client.get("key1").should == nil
|
68
|
+
@client.get("key2").should == "2"
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should rename a key, only if new key does not exist" do
|
72
|
+
@client.set("key1", "1")
|
73
|
+
@client.set("key2", "2")
|
74
|
+
@client.set("key3", "3")
|
75
|
+
@client.renamenx("key1", "key2")
|
76
|
+
@client.renamenx("key3", "key4")
|
77
|
+
|
78
|
+
@client.get("key1").should == "1"
|
79
|
+
@client.get("key2").should == "2"
|
80
|
+
@client.get("key3").should == nil
|
81
|
+
@client.get("key4").should == "3"
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should sort the elements in a list, set or sorted set" do
|
85
|
+
pending "SORT Command not implemented yet"
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should determine the type stored at key" do
|
89
|
+
@client.set("key1", "1")
|
90
|
+
|
91
|
+
@client.type("key1").should == "string"
|
92
|
+
@client.type("key0").should == "none"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
data/spec/lists_spec.rb
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module FakeRedis
|
4
|
+
describe "ListsMethods" do
|
5
|
+
before(:each) do
|
6
|
+
@client = FakeRedis::Redis.new
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should get an element from a list by its index" do
|
10
|
+
@client.lpush("key1", "val1")
|
11
|
+
@client.lpush("key1", "val2")
|
12
|
+
|
13
|
+
@client.lindex("key1", 0).should == "val2"
|
14
|
+
@client.lindex("key1", -1).should == "val1"
|
15
|
+
@client.lindex("key1", 3).should == nil
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should insert an element before or after another element in a list" do
|
19
|
+
@client.rpush("key1", "v1")
|
20
|
+
@client.rpush("key1", "v3")
|
21
|
+
@client.linsert("key1", :before, "v3", "v2")
|
22
|
+
|
23
|
+
@client.lrange("key1", 0, -1).should == ["v1", "v2", "v3"]
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should get the length of a list" do
|
27
|
+
@client.rpush("key1", "v1")
|
28
|
+
@client.rpush("key1", "v2")
|
29
|
+
|
30
|
+
@client.llen("key1").should == 2
|
31
|
+
@client.llen("key2").should == 0
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should remove and get the first element in a list" do
|
35
|
+
@client.rpush("key1", "v1")
|
36
|
+
@client.rpush("key1", "v2")
|
37
|
+
@client.rpush("key1", "v3")
|
38
|
+
|
39
|
+
@client.lpop("key1").should == "v1"
|
40
|
+
@client.lrange("key1", 0, -1).should == ["v2", "v3"]
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should prepend a value to a list" do
|
44
|
+
@client.rpush("key1", "v1")
|
45
|
+
@client.rpush("key1", "v2")
|
46
|
+
|
47
|
+
@client.lrange("key1", 0, -1).should == ["v1", "v2"]
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should prepend a value to a list, only if the list exists" do
|
51
|
+
@client.lpush("key1", "v1")
|
52
|
+
|
53
|
+
@client.lpushx("key1", "v2")
|
54
|
+
@client.lpushx("key2", "v3")
|
55
|
+
|
56
|
+
@client.lrange("key1", 0, -1).should == ["v2", "v1"]
|
57
|
+
@client.llen("key2").should == 0
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should get a range of elements from a list" do
|
61
|
+
@client.rpush("key1", "v1")
|
62
|
+
@client.rpush("key1", "v2")
|
63
|
+
@client.rpush("key1", "v3")
|
64
|
+
|
65
|
+
@client.lrange("key1", 1, -1).should == ["v2", "v3"]
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should remove elements from a list" do
|
69
|
+
@client.rpush("key1", "v1")
|
70
|
+
@client.rpush("key1", "v2")
|
71
|
+
@client.rpush("key1", "v2")
|
72
|
+
@client.rpush("key1", "v2")
|
73
|
+
@client.rpush("key1", "v1")
|
74
|
+
|
75
|
+
@client.lrem("key1", 1, "v1").should == 1
|
76
|
+
@client.lrem("key1", -2, "v2").should == 2
|
77
|
+
@client.llen("key1").should == 2
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should set the value of an element in a list by its index" do
|
81
|
+
@client.rpush("key1", "one")
|
82
|
+
@client.rpush("key1", "two")
|
83
|
+
@client.rpush("key1", "three")
|
84
|
+
|
85
|
+
@client.lset("key1", 0, "four")
|
86
|
+
@client.lset("key1", -2, "five")
|
87
|
+
@client.lrange("key1", 0, -1).should == ["four", "five", "three"]
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should trim a list to the specified range" do
|
91
|
+
@client.rpush("key1", "one")
|
92
|
+
@client.rpush("key1", "two")
|
93
|
+
@client.rpush("key1", "three")
|
94
|
+
|
95
|
+
@client.ltrim("key1", 1, -1)
|
96
|
+
@client.lrange("key1", 0, -1).should == ["two", "three"]
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should remove and get the last element in a list" do
|
100
|
+
@client.rpush("key1", "one")
|
101
|
+
@client.rpush("key1", "two")
|
102
|
+
@client.rpush("key1", "three")
|
103
|
+
|
104
|
+
@client.rpop("key1").should == "three"
|
105
|
+
@client.lrange("key1", 0, -1).should == ["one", "two"]
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should remove the last element in a list, append it to another list and return it" do
|
109
|
+
@client.rpush("key1", "one")
|
110
|
+
@client.rpush("key1", "two")
|
111
|
+
@client.rpush("key1", "three")
|
112
|
+
@client.rpoplpush("key1", "key2")
|
113
|
+
|
114
|
+
@client.lrange("key1", 0, -1).should == ["one", "two"]
|
115
|
+
@client.lrange("key2", 0, -1).should == ["three"]
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should append a value to a list" do
|
119
|
+
@client.rpush("key1", "one")
|
120
|
+
@client.rpush("key1", "two")
|
121
|
+
|
122
|
+
@client.lrange("key1", 0, -1).should == ["one", "two"]
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should append a value to a list, only if the list exists" do
|
126
|
+
@client.rpush("key1", "one")
|
127
|
+
@client.rpushx("key1", "two")
|
128
|
+
@client.rpushx("key2", "two")
|
129
|
+
|
130
|
+
@client.lrange("key1", 0, -1).should == ["one", "two"]
|
131
|
+
@client.lrange("key2", 0, -1).should == nil
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
data/spec/server_spec.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module FakeRedis
|
4
|
+
describe "ServerMethods" do
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
@client = FakeRedis::Redis.new
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should return the number of keys in the selected database" do
|
11
|
+
@client.set("key1", "1")
|
12
|
+
@client.set("key2", "2")
|
13
|
+
@client.set("key2", "two")
|
14
|
+
|
15
|
+
@client.dbsize.should == 2
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should get debugging information about a key" do
|
19
|
+
@client.set("key1", "1")
|
20
|
+
|
21
|
+
@client.debug_object("key1").should == "1".inspect
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should get information and statistics about the server" do
|
25
|
+
@client.info.key?("redis_version").should == true
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/spec/sets_spec.rb
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module FakeRedis
|
4
|
+
describe "SetsMethods" do
|
5
|
+
before(:each) do
|
6
|
+
@client = FakeRedis::Redis.new
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should add a member to a set" do
|
10
|
+
@client.sadd("key", "value")
|
11
|
+
|
12
|
+
@client.smembers("key").should == ["value"]
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should get the number of members in a set" do
|
16
|
+
@client.sadd("key", "val1")
|
17
|
+
@client.sadd("key", "val2")
|
18
|
+
|
19
|
+
@client.scard("key").should == 2
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should subtract multiple sets" do
|
23
|
+
@client.sadd("key1", "a")
|
24
|
+
@client.sadd("key1", "b")
|
25
|
+
@client.sadd("key1", "c")
|
26
|
+
@client.sadd("key1", "d")
|
27
|
+
@client.sadd("key2", "c")
|
28
|
+
@client.sadd("key3", "a")
|
29
|
+
@client.sadd("key3", "c")
|
30
|
+
@client.sadd("key3", "e")
|
31
|
+
|
32
|
+
@client.sdiff("key1", "key2", "key3").should =~ ["b", "d"]
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should subtract multiple sets and store the resulting set in a key" do
|
36
|
+
@client.sadd("key1", "a")
|
37
|
+
@client.sadd("key1", "b")
|
38
|
+
@client.sadd("key1", "c")
|
39
|
+
@client.sadd("key1", "d")
|
40
|
+
@client.sadd("key2", "c")
|
41
|
+
@client.sadd("key3", "a")
|
42
|
+
@client.sadd("key3", "c")
|
43
|
+
@client.sadd("key3", "e")
|
44
|
+
@client.sdiffstore("key", "key1", "key2", "key3")
|
45
|
+
|
46
|
+
@client.smembers("key").should =~ ["b", "d"]
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should intersect multiple sets" do
|
50
|
+
@client.sadd("key1", "a")
|
51
|
+
@client.sadd("key1", "b")
|
52
|
+
@client.sadd("key1", "c")
|
53
|
+
@client.sadd("key1", "d")
|
54
|
+
@client.sadd("key2", "c")
|
55
|
+
@client.sadd("key3", "a")
|
56
|
+
@client.sadd("key3", "c")
|
57
|
+
@client.sadd("key3", "e")
|
58
|
+
|
59
|
+
@client.sinter("key1", "key2", "key3").should == ["c"]
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should intersect multiple sets and store the resulting set in a key" do
|
63
|
+
@client.sadd("key1", "a")
|
64
|
+
@client.sadd("key1", "b")
|
65
|
+
@client.sadd("key1", "c")
|
66
|
+
@client.sadd("key1", "d")
|
67
|
+
@client.sadd("key2", "c")
|
68
|
+
@client.sadd("key3", "a")
|
69
|
+
@client.sadd("key3", "c")
|
70
|
+
@client.sadd("key3", "e")
|
71
|
+
@client.sinterstore("key", "key1", "key2", "key3")
|
72
|
+
@client.smembers("key").should == ["c"]
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should determine if a given value is a member of a set" do
|
76
|
+
@client.sadd("key1", "a")
|
77
|
+
|
78
|
+
@client.sismember("key1", "a").should == true
|
79
|
+
@client.sismember("key1", "b").should == false
|
80
|
+
@client.sismember("key2", "a").should == false
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should get all the members in a set" do
|
84
|
+
@client.sadd("key", "a")
|
85
|
+
@client.sadd("key", "b")
|
86
|
+
@client.sadd("key", "c")
|
87
|
+
@client.sadd("key", "d")
|
88
|
+
|
89
|
+
@client.smembers("key").should =~ ["a", "b", "c", "d"]
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should move a member from one set to another" do
|
93
|
+
@client.sadd("key1", "a")
|
94
|
+
@client.sadd("key1", "b")
|
95
|
+
@client.sadd("key2", "c")
|
96
|
+
@client.smove("key1", "key2", "a")
|
97
|
+
|
98
|
+
@client.smembers("key1").should == ["b"]
|
99
|
+
@client.smembers("key2").should =~ ["c", "a"]
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should remove and return a random member from a set" do
|
103
|
+
@client.sadd("key1", "a")
|
104
|
+
@client.sadd("key1", "b")
|
105
|
+
|
106
|
+
["a", "b"].include?(@client.spop("key1")).should be_true
|
107
|
+
["a", "b"].include?(@client.spop("key1")).should be_true
|
108
|
+
@client.spop("key1").should be_nil
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should get a random member from a set" do
|
112
|
+
@client.sadd("key1", "a")
|
113
|
+
@client.sadd("key1", "b")
|
114
|
+
|
115
|
+
["a", "b"].include?(@client.spop("key1")).should be_true
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should remove a member from a set" do
|
119
|
+
@client.sadd("key1", "a")
|
120
|
+
@client.sadd("key1", "b")
|
121
|
+
@client.srem("key1", "a")
|
122
|
+
|
123
|
+
@client.smembers("key1").should == ["b"]
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should add multiple sets" do
|
127
|
+
@client.sadd("key1", "a")
|
128
|
+
@client.sadd("key1", "b")
|
129
|
+
@client.sadd("key1", "c")
|
130
|
+
@client.sadd("key1", "d")
|
131
|
+
@client.sadd("key2", "c")
|
132
|
+
@client.sadd("key3", "a")
|
133
|
+
@client.sadd("key3", "c")
|
134
|
+
@client.sadd("key3", "e")
|
135
|
+
|
136
|
+
@client.sunion("key1", "key2", "key3").should =~ ["a", "b", "c", "d", "e"]
|
137
|
+
end
|
138
|
+
|
139
|
+
it "should add multiple sets and store the resulting set in a key" do
|
140
|
+
@client.sadd("key1", "a")
|
141
|
+
@client.sadd("key1", "b")
|
142
|
+
@client.sadd("key1", "c")
|
143
|
+
@client.sadd("key1", "d")
|
144
|
+
@client.sadd("key2", "c")
|
145
|
+
@client.sadd("key3", "a")
|
146
|
+
@client.sadd("key3", "c")
|
147
|
+
@client.sadd("key3", "e")
|
148
|
+
@client.sunionstore("key", "key1", "key2", "key3")
|
149
|
+
|
150
|
+
@client.smembers("key").should =~ ["a", "b", "c", "d", "e"]
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|