ruby-tokyotyrant 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/COPYING +504 -0
- data/README.rdoc +204 -0
- data/Rakefile +68 -0
- data/benchmarks/bulk_db.rb +74 -0
- data/benchmarks/bulk_table.rb +87 -0
- data/benchmarks/db.rb +114 -0
- data/benchmarks/table.rb +161 -0
- data/ext/extconf.rb +39 -0
- data/ext/tokyo_tyrant.c +147 -0
- data/ext/tokyo_tyrant.h +48 -0
- data/ext/tokyo_tyrant_db.c +227 -0
- data/ext/tokyo_tyrant_db.h +8 -0
- data/ext/tokyo_tyrant_module.c +453 -0
- data/ext/tokyo_tyrant_module.h +10 -0
- data/ext/tokyo_tyrant_query.c +226 -0
- data/ext/tokyo_tyrant_query.h +9 -0
- data/ext/tokyo_tyrant_table.c +319 -0
- data/ext/tokyo_tyrant_table.h +8 -0
- data/spec/ext.lua +4 -0
- data/spec/plu_db.rb +538 -0
- data/spec/spec.rb +1 -0
- data/spec/spec_base.rb +16 -0
- data/spec/start_tyrants.sh +36 -0
- data/spec/stop_tyrants.sh +9 -0
- data/spec/tokyo_tyrant_query_spec.rb +159 -0
- data/spec/tokyo_tyrant_spec.rb +254 -0
- data/spec/tokyo_tyrant_table_spec.rb +301 -0
- metadata +80 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# starting the tt servers (standard + table)
|
|
5
|
+
#
|
|
6
|
+
|
|
7
|
+
TMP=`pwd`/tmp
|
|
8
|
+
SPEC=`pwd`/spec
|
|
9
|
+
# so that tt doesn't complain about relative paths...
|
|
10
|
+
|
|
11
|
+
[ -d $TMP ] || mkdir $TMP
|
|
12
|
+
|
|
13
|
+
ttserver \
|
|
14
|
+
-dmn \
|
|
15
|
+
-port 45000 \
|
|
16
|
+
-pid $TMP/t_spec.pid -rts $TMP/t_spec.rts \
|
|
17
|
+
-log $TMP/t.log \
|
|
18
|
+
-ext $SPEC/ext.lua \
|
|
19
|
+
$TMP/tyrant.tch
|
|
20
|
+
|
|
21
|
+
ttserver \
|
|
22
|
+
-dmn \
|
|
23
|
+
-port 45001 \
|
|
24
|
+
-pid $TMP/tt1_spec.pid -rts $TMP/tt1_spec.rts \
|
|
25
|
+
-log $TMP/tt1.log \
|
|
26
|
+
-ext $SPEC/ext.lua \
|
|
27
|
+
$TMP/tyrant_table1.tct
|
|
28
|
+
|
|
29
|
+
ttserver \
|
|
30
|
+
-dmn \
|
|
31
|
+
-port 45002 \
|
|
32
|
+
-pid $TMP/tt2_spec.pid -rts $TMP/tt2_spec.rts \
|
|
33
|
+
-log $TMP/tt2.log \
|
|
34
|
+
-ext $SPEC/ext.lua \
|
|
35
|
+
$TMP/tyrant_table2.tct
|
|
36
|
+
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
require 'pathname'
|
|
2
|
+
require Pathname(__FILE__).dirname.join('spec_base') unless $root
|
|
3
|
+
|
|
4
|
+
describe TokyoTyrant::Query, "with an open database" do
|
|
5
|
+
before do
|
|
6
|
+
@db = TokyoTyrant::Table.new('127.0.0.1', 45001)
|
|
7
|
+
@db.clear
|
|
8
|
+
load('spec/plu_db.rb') unless $codes
|
|
9
|
+
@db.mput($codes)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "should get a query object" do
|
|
13
|
+
@db.query.class.should == TokyoTyrant::Query
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "should get keys for search conditions" do
|
|
17
|
+
q = @db.query
|
|
18
|
+
q.addcond('type', :streq, 'Spinach')
|
|
19
|
+
q.search.sort.should == %w[3332 34173]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "should get keys for negated search conditions" do
|
|
23
|
+
q = @db.query
|
|
24
|
+
q.addcond('type', '!streq', 'Spinach')
|
|
25
|
+
res = q.search
|
|
26
|
+
%w[3332 34173].each do |k|
|
|
27
|
+
res.should.not.include?(k)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "should get ordered keys for search conditions with default order" do
|
|
32
|
+
q = @db.query
|
|
33
|
+
q.addcond('type', :streq, 'Spinach')
|
|
34
|
+
q.setorder('variety')
|
|
35
|
+
q.search.should == ["3332", "34173"]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "should get ordered keys for search conditions with ascending order" do
|
|
39
|
+
q = @db.query
|
|
40
|
+
q.addcond('type', :streq, 'Spinach')
|
|
41
|
+
q.setorder('variety', :strasc)
|
|
42
|
+
q.search.should == ["3332", "34173"]
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "should get ordered keys for search conditions with decending order" do
|
|
46
|
+
q = @db.query
|
|
47
|
+
q.addcond('type', :streq, 'Spinach')
|
|
48
|
+
q.order_by('variety', :StrDesc)
|
|
49
|
+
q.search.should == ["34173", "3332"]
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it "should get limited keys for search conditions with limit" do
|
|
53
|
+
q = @db.query{ |q|
|
|
54
|
+
q.addcond('type', :streq, 'Apple')
|
|
55
|
+
q.order_by('variety', :strdesc)
|
|
56
|
+
q.setlimit(10)
|
|
57
|
+
}.should == ["4860", "3011", "3271", "3382", "4182", "3353", "4176", "3272", "3297", "3009"]
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it "should get limited keys for search conditions with limit and offset" do
|
|
61
|
+
q = @db.query{ |q|
|
|
62
|
+
q.addcond('type', :streq, 'Apple')
|
|
63
|
+
q.order_by('variety', :strdesc)
|
|
64
|
+
q.setlimit(10, 10)
|
|
65
|
+
}.should == ["3008", "3352", "3077", "3349", "3076", "3073", "3348", "3007", "3078", "3347"]
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "should get records for search conditions" do
|
|
69
|
+
q = @db.query
|
|
70
|
+
q.addcond('type', :streq, 'Garlic')
|
|
71
|
+
res = q.get.sort{ |x,y| x['variety'] <=> y['variety'] }
|
|
72
|
+
res.should == [{ '__id' => "4609", 'variety' => "Elephant", 'code' => "4609", 'type' => "Garlic" },
|
|
73
|
+
{ '__id' => "3401", 'variety' => "One-clove types", 'code' => "3401", 'type' => "Garlic" },
|
|
74
|
+
{ '__id' => "3052", 'variety' => "String", 'code' => "3052", 'type' => "Garlic" }]
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it "should remove records for conditions" do
|
|
78
|
+
q = @db.query
|
|
79
|
+
q.addcond('type', :streq, 'Orange')
|
|
80
|
+
q.search.size.should == 11
|
|
81
|
+
q.searchout.should.be.true
|
|
82
|
+
q.search.size.should == 0
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it "should chain search options" do
|
|
86
|
+
res = @db.query.condition('type', :streq, 'Cucumber').order_by('variety', :strdesc).limit(3).search
|
|
87
|
+
res.should == ["4596", "4595", "4594"]
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it "should query with a block" do
|
|
91
|
+
res = @db.query do |q|
|
|
92
|
+
q.condition('type', :streq, 'Cucumber')
|
|
93
|
+
q.order_by('variety', :strdesc)
|
|
94
|
+
q.limit(3)
|
|
95
|
+
end
|
|
96
|
+
res.should == ["4596", "4595", "4594"]
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it "should find with a block" do
|
|
100
|
+
res = @db.find do |q|
|
|
101
|
+
q.condition('type', :streq, 'Cucumber')
|
|
102
|
+
q.order_by('variety', :strdesc)
|
|
103
|
+
q.limit(3)
|
|
104
|
+
end
|
|
105
|
+
res.should == [{'type'=>"Cucumber", 'variety'=>"Pickling / Gherkin", '__id'=>"4596", 'code'=>"4596"},
|
|
106
|
+
{'type'=>"Cucumber", 'variety'=>"Lemon", '__id'=>"4595", 'code'=>"4595"},
|
|
107
|
+
{'type'=>"Cucumber", 'variety'=>"Japanese / White", '__id'=>"4594", 'code'=>"4594"}]
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
it "should show query count" do
|
|
111
|
+
res = @db.prepare_query{ |q| q.condition('type', :streq, 'Cucumber') }.count
|
|
112
|
+
res.should == 5
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
it "should allow a custom pkey for a result set" do
|
|
116
|
+
q = @db.query
|
|
117
|
+
q.condition('type', :streq, 'Cucumber')
|
|
118
|
+
q.set_pkey(:pk)
|
|
119
|
+
q.get.should == [{'type'=>"Cucumber", 'code'=>"4592", :pk=>"4592", 'variety'=>"Armenian"},
|
|
120
|
+
{'type'=>"Cucumber", 'code'=>"4593", :pk=>"4593", 'variety'=>"English / Hot House / Long Seedless / Telegraph / Continental"},
|
|
121
|
+
{'type'=>"Cucumber", 'code'=>"4594", :pk=>"4594", 'variety'=>"Japanese / White"},
|
|
122
|
+
{'type'=>"Cucumber", 'code'=>"4595", :pk=>"4595", 'variety'=>"Lemon"},
|
|
123
|
+
{'type'=>"Cucumber", 'code'=>"4596", :pk=>"4596", 'variety'=>"Pickling / Gherkin"}]
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
it "should return a query hint" do
|
|
127
|
+
@db.set_index(:type, :lexical)
|
|
128
|
+
q = @db.query
|
|
129
|
+
q.condition(:type, :streq, 'Cucumber')
|
|
130
|
+
q.order_by(:code)
|
|
131
|
+
q.limit(3)
|
|
132
|
+
q.run
|
|
133
|
+
q.hint.should == "\nusing an index: \"type\" asc (STREQ)\nresult set size: 5\nsorting the result set: \"code\"\n"
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
it "should query multiple servers" do
|
|
137
|
+
servers = { 1 => TokyoTyrant::Table.new('127.0.0.1', 45001),
|
|
138
|
+
2 => TokyoTyrant::Table.new('127.0.0.1', 45002) }
|
|
139
|
+
|
|
140
|
+
# dummy data
|
|
141
|
+
servers.each do |account_id, server|
|
|
142
|
+
server.clear
|
|
143
|
+
server["#{account_id}/1"] = {
|
|
144
|
+
:name => "Test 1 (#{account_id})",
|
|
145
|
+
:id => 1,
|
|
146
|
+
}
|
|
147
|
+
server["#{account_id}/2"] = {
|
|
148
|
+
:name => "Test 2 (#{account_id})",
|
|
149
|
+
:id => 2,
|
|
150
|
+
}
|
|
151
|
+
end
|
|
152
|
+
ones = proc{ |q| q.add_condition :id, :numeq, 1 }
|
|
153
|
+
queries = servers.collect{ |account_id,server| server.prepare_query(&ones) }
|
|
154
|
+
results = TokyoTyrant::Query.parallel_search(*queries)
|
|
155
|
+
expected = [{ "" => "1/1", "name" => "Test 1 (1)", "id" => "1" },
|
|
156
|
+
{ "" => "2/1", "name" => "Test 1 (2)", "id" => "1" }]
|
|
157
|
+
results.should == expected
|
|
158
|
+
end
|
|
159
|
+
end
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
require 'pathname'
|
|
2
|
+
require Pathname(__FILE__).dirname.join('spec_base') unless $root
|
|
3
|
+
|
|
4
|
+
describe TokyoTyrant::DB, "with an open database" do
|
|
5
|
+
|
|
6
|
+
before do
|
|
7
|
+
@db = TokyoTyrant::DB.new('127.0.0.1', 45000)
|
|
8
|
+
@db.clear
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it "should not be nil" do
|
|
12
|
+
@db.should.not.be.nil
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "should close" do
|
|
16
|
+
@db.close.should.be.true
|
|
17
|
+
begin
|
|
18
|
+
@db.close
|
|
19
|
+
rescue => e
|
|
20
|
+
e.message.should == 'close error: invalid operation'
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "should return a server expression" do
|
|
25
|
+
@db.server.should == '127.0.0.1:45000'
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "should optimize" do
|
|
29
|
+
@db.optimize.should.be.true
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "should save a value" do
|
|
33
|
+
@db[:salad] = 'bacon bits'
|
|
34
|
+
@db[:salad].should == 'bacon bits'
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "should return a value" do
|
|
38
|
+
@db[:salad] = 'bacon bits'
|
|
39
|
+
@db[:salad].should == 'bacon bits'
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it "should accept binary data" do
|
|
43
|
+
s = "mango#{0.chr}salsa"
|
|
44
|
+
@db.put(s, s).should.be.true
|
|
45
|
+
@db[s].should.equal(s)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it "should save multiple values" do
|
|
49
|
+
h = { 'pizza' => 'old forge style',
|
|
50
|
+
'sandwich' => 'peanut butter jelly',
|
|
51
|
+
'yogurt' => 'greek',
|
|
52
|
+
'coffee' => 'black' }
|
|
53
|
+
@db.mput(h).should.be.empty
|
|
54
|
+
h.each_pair do |k,v|
|
|
55
|
+
@db[k].should == v
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it "should delete multiple values" do
|
|
60
|
+
h = { 'pizza' => 'old forge style',
|
|
61
|
+
'sandwich' => 'peanut butter jelly',
|
|
62
|
+
'yogurt' => 'greek',
|
|
63
|
+
'coffee' => 'black' }
|
|
64
|
+
@db.mput(h)
|
|
65
|
+
@db.outlist('coffee', 'yogurt').should.be.empty
|
|
66
|
+
@db.keys.sort.should == ['pizza','sandwich']
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it "should get multiple values" do
|
|
70
|
+
h = { 'pizza' => 'old forge style',
|
|
71
|
+
'sandwich' => 'peanut butter jelly',
|
|
72
|
+
'yogurt' => 'greek',
|
|
73
|
+
'coffee' => 'black' }
|
|
74
|
+
@db.mput(h)
|
|
75
|
+
@db.mget(h.keys).should == h
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
it "should out a value" do
|
|
79
|
+
k = :tomato
|
|
80
|
+
@db[k] = 'green'
|
|
81
|
+
@db.out(k).should.be.true
|
|
82
|
+
@db[k].should.be.nil
|
|
83
|
+
@db.out(k).should.be.false
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
it "should get a value size" do
|
|
87
|
+
k = :cereal
|
|
88
|
+
v = 'granola'
|
|
89
|
+
@db[k] = v
|
|
90
|
+
@db.vsiz(k).should == v.size
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it "should check a key" do
|
|
94
|
+
k = :fruit
|
|
95
|
+
@db[k] = 'banana'
|
|
96
|
+
@db.check(k).should.be.true
|
|
97
|
+
@db.out(k)
|
|
98
|
+
@db.check(k).should.be.false
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
it "should iterate" do
|
|
102
|
+
@db[:cheese] = 'gouda'
|
|
103
|
+
@db[:grapes] = 'green'
|
|
104
|
+
@db[:oranges] = 'florida'
|
|
105
|
+
@db[:crackers] = 'triscuit'
|
|
106
|
+
|
|
107
|
+
@db.iterinit.should.be.true
|
|
108
|
+
@db.iternext.should == 'cheese'
|
|
109
|
+
@db.iternext.should == 'grapes'
|
|
110
|
+
@db.iternext.should == 'oranges'
|
|
111
|
+
@db.iternext.should == 'crackers'
|
|
112
|
+
@db.iternext.should == nil
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
it "should get forward matching keys" do
|
|
116
|
+
@db['apples/royalgala'] = '4173'
|
|
117
|
+
@db['apples/grannysmith'] = '4139'
|
|
118
|
+
@db['bananas/yellow'] = '4011'
|
|
119
|
+
@db['oranges/shamouti'] = '3027'
|
|
120
|
+
@db['grapefruit/deepred'] = '4288'
|
|
121
|
+
@db.fwmkeys('apples').sort.should == ["apples/grannysmith", "apples/royalgala"]
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
it "should delete forward matching keys" do
|
|
125
|
+
@db['apples/royalgala'] = '4173'
|
|
126
|
+
@db['apples/grannysmith'] = '4139'
|
|
127
|
+
@db['bananas/yellow'] = '4011'
|
|
128
|
+
@db['oranges/shamouti'] = '3027'
|
|
129
|
+
@db['grapefruit/deepred'] = '4288'
|
|
130
|
+
@db.delete_keys_with_prefix('apples').should == nil
|
|
131
|
+
@db.fwmkeys('apples').should.be.empty
|
|
132
|
+
@db.keys.sort.should == ['bananas/yellow', 'grapefruit/deepred', 'oranges/shamouti']
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
it "should get all keys" do
|
|
136
|
+
keys = %w[appetizers entree dessert]
|
|
137
|
+
values = %w[chips chicken\ caeser\ salad ice\ cream]
|
|
138
|
+
keys.each_with_index do |k,i|
|
|
139
|
+
@db[k] = values[i]
|
|
140
|
+
end
|
|
141
|
+
@db.keys.should == keys
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
it "should get all values" do
|
|
145
|
+
keys = %w[appetizers entree dessert]
|
|
146
|
+
values = %w[chips chicken\ caeser\ salad ice\ cream]
|
|
147
|
+
keys.each_with_index do |k,i|
|
|
148
|
+
@db[k] = values[i]
|
|
149
|
+
end
|
|
150
|
+
@db.values.should == values
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
it "should vanish all records" do
|
|
154
|
+
@db['chocolate'] = 'dark'
|
|
155
|
+
@db['tea'] = 'earl grey'
|
|
156
|
+
@db.empty?.should.be.false
|
|
157
|
+
@db.vanish.should.be.true
|
|
158
|
+
@db.empty?.should.be.true
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
it "should count records" do
|
|
162
|
+
@db['hummus'] = 'chickpeas'
|
|
163
|
+
@db['falafel'] = 'chickpeas'
|
|
164
|
+
@db.rnum.should == 2
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
it "should report db size" do
|
|
168
|
+
@db['rootbeer'] = 'virgils'
|
|
169
|
+
@db.db_size.should.not == 0
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
it "should fetch a record" do
|
|
173
|
+
@db.out('beer')
|
|
174
|
+
@db.fetch('beer'){ 'heineken' }.should == 'heineken'
|
|
175
|
+
@db['beer'].should == 'heineken'
|
|
176
|
+
@db.fetch('beer'){ 'becks' }.should == 'heineken'
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
it "should iterate through records" do
|
|
180
|
+
keys = %w[grapejuice tacoshells rice]
|
|
181
|
+
values = %w[Kedem Ortega Uncle\ Ben]
|
|
182
|
+
keys.each_with_index{ |k,i| @db[k] = values[i] }
|
|
183
|
+
|
|
184
|
+
i = 0
|
|
185
|
+
@db.each do |k,v|
|
|
186
|
+
k.should == keys[i]
|
|
187
|
+
v.should == values[i]
|
|
188
|
+
i = i += 1
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
it "should iterate through keys" do
|
|
193
|
+
keys = %w[burritos fajitas tacos tostas enchiladas]
|
|
194
|
+
values = Array.new(keys.size, 'yum')
|
|
195
|
+
keys.each_with_index{ |k,i| @db[k] = values[i] }
|
|
196
|
+
|
|
197
|
+
i = 0
|
|
198
|
+
@db.each_key do |k|
|
|
199
|
+
k.should == keys[i]
|
|
200
|
+
i = i += 1
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
it "should iterate through values" do
|
|
205
|
+
keys = %w[falafel humus couscous tabbouleh tzatziki]
|
|
206
|
+
values = %w[chickpeas chickpeas semolina bulgar yogurt]
|
|
207
|
+
keys.each_with_index{ |k,i| @db[k] = values[i] }
|
|
208
|
+
|
|
209
|
+
i = 0
|
|
210
|
+
@db.each_value do |v|
|
|
211
|
+
v.should == values[i]
|
|
212
|
+
i = i += 1
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
it "should add serialized integer values" do
|
|
217
|
+
key = 'counter'
|
|
218
|
+
@db.out(key)
|
|
219
|
+
@db.add_int(key, 1).should == 1
|
|
220
|
+
@db.add_int(key, 1).should == 2
|
|
221
|
+
@db.get_int(key).should == 2
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
it "should increment integer values" do
|
|
225
|
+
key = 'counter'
|
|
226
|
+
@db.out(key)
|
|
227
|
+
@db.increment(key).should == 1
|
|
228
|
+
@db.increment(key, 2).should == 3
|
|
229
|
+
@db.get_int(key).should == 3
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
it "should add serialized double values" do
|
|
233
|
+
key = 'counter'
|
|
234
|
+
@db.out(key)
|
|
235
|
+
@db.add_double(key, 1.0).should.be.close?(1.0, 0.005)
|
|
236
|
+
@db.add_double(key, 1.0).should.be.close?(2.0, 0.005)
|
|
237
|
+
@db.get_double(key).should.be.close?(2.0, 0.005)
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
it "should run lua extensions" do
|
|
241
|
+
@db.ext('echo', 'hello', 'world').should == "hello\tworld"
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
it "should serialize objects that respond to to_tokyo_tyrant" do
|
|
245
|
+
class Thing
|
|
246
|
+
def to_tokyo_tyrant
|
|
247
|
+
"success"
|
|
248
|
+
end
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
@db["to_tokyo_tyrant"] = Thing.new
|
|
252
|
+
@db["to_tokyo_tyrant"].should == "success"
|
|
253
|
+
end
|
|
254
|
+
end
|