rod 0.7.1 → 0.7.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. data/.travis.yml +1 -1
  2. data/README.rdoc +38 -10
  3. data/Rakefile +20 -9
  4. data/changelog.txt +25 -0
  5. data/contributors.txt +1 -0
  6. data/data/backward/0.7.0/_join_element.dat +0 -0
  7. data/data/backward/0.7.0/_polymorphic_join_element.dat +0 -0
  8. data/data/backward/0.7.0/char.dat +0 -0
  9. data/data/backward/0.7.0/database.yml +58 -0
  10. data/data/backward/0.7.0/rod_test__automobile.dat +0 -0
  11. data/data/backward/0.7.0/rod_test__caveman.dat +0 -0
  12. data/data/backward/0.7.0/rod_test__dog.dat +0 -0
  13. data/data/backward/0.7.0/rod_test__test_model.dat +0 -0
  14. data/data/portability/_join_element.dat +0 -0
  15. data/data/portability/_polymorphic_join_element.dat +0 -0
  16. data/data/portability/char.dat +0 -0
  17. data/data/portability/database.yml +49 -0
  18. data/data/portability/rod_test__automobile.dat +0 -0
  19. data/data/portability/rod_test__caveman.dat +0 -0
  20. data/data/portability/rod_test__dog.dat +0 -0
  21. data/data/portability/rod_test__test_model.dat +0 -0
  22. data/features/backward.feature +33 -0
  23. data/features/basic.feature +3 -0
  24. data/features/collection_proxy.feature +95 -0
  25. data/features/flat_indexing.feature +44 -2
  26. data/features/hash_indexing.feature +63 -9
  27. data/features/portability.feature +72 -0
  28. data/features/segmented_indexing.feature +45 -2
  29. data/features/steps/collection_proxy.rb +1 -1
  30. data/features/steps/model.rb +48 -5
  31. data/features/steps/rod.rb +15 -16
  32. data/lib/rod.rb +11 -1
  33. data/lib/rod/abstract_database.rb +52 -42
  34. data/lib/rod/berkeley/collection_proxy.rb +96 -0
  35. data/lib/rod/berkeley/database.rb +337 -0
  36. data/lib/rod/berkeley/environment.rb +209 -0
  37. data/lib/rod/berkeley/sequence.rb +222 -0
  38. data/lib/rod/berkeley/transaction.rb +233 -0
  39. data/lib/rod/collection_proxy.rb +76 -1
  40. data/lib/rod/constants.rb +3 -2
  41. data/lib/rod/database.rb +127 -14
  42. data/lib/rod/index/base.rb +12 -3
  43. data/lib/rod/index/hash_index.rb +295 -70
  44. data/lib/rod/index/segmented_index.rb +3 -0
  45. data/lib/rod/model.rb +154 -531
  46. data/lib/rod/property/base.rb +190 -0
  47. data/lib/rod/property/field.rb +258 -0
  48. data/lib/rod/property/plural_association.rb +145 -0
  49. data/lib/rod/property/singular_association.rb +139 -0
  50. data/rod.gemspec +6 -4
  51. data/spec/berkeley/database.rb +83 -0
  52. data/spec/berkeley/environment.rb +58 -0
  53. data/spec/berkeley/sequence.rb +101 -0
  54. data/spec/berkeley/transaction.rb +92 -0
  55. data/spec/collection_proxy.rb +38 -0
  56. data/spec/database.rb +36 -0
  57. data/spec/model.rb +26 -0
  58. data/spec/property/base.rb +73 -0
  59. data/spec/property/field.rb +244 -0
  60. data/spec/property/plural_association.rb +67 -0
  61. data/spec/property/singular_association.rb +65 -0
  62. data/tests/class_compatibility_create.rb +2 -2
  63. data/tests/eff1_test.rb +1 -1
  64. data/tests/eff2_test.rb +1 -1
  65. data/tests/full_runs.rb +1 -1
  66. data/tests/generate_classes_create.rb +14 -14
  67. data/tests/migration_create.rb +47 -47
  68. data/tests/migration_verify.rb +1 -1
  69. data/tests/missing_class_create.rb +6 -6
  70. data/tests/properties_order_create.rb +4 -4
  71. data/tests/read_on_create.rb +33 -34
  72. data/tests/save_struct.rb +40 -39
  73. data/tests/unit/database.rb +1 -1
  74. data/tests/unit/model_tests.rb +73 -65
  75. metadata +71 -15
  76. data/tests/unit/model.rb +0 -36
@@ -0,0 +1,38 @@
1
+ require 'bundler/setup'
2
+ require 'minitest/autorun'
3
+ require 'rod'
4
+ require 'mocha'
5
+
6
+ # TODO translate collection proxy feature into spec.
7
+ describe Rod::CollectionProxy do
8
+ describe "a persisted collection proxy" do
9
+ before do
10
+ @size = 10
11
+ @offset = 0
12
+ @db = Object.new
13
+ @size.times do |index|
14
+ @db.expects(:join_index).with(@offset,index).returns(index+1).at_least(0)
15
+ end
16
+ @proxy = Rod::CollectionProxy.new(@size,@db,@offset,Rod::Model)
17
+ end
18
+
19
+ describe "with another collection proxy" do
20
+ before do
21
+ size = 10
22
+ size.times do |index|
23
+ # these collections have 5 rod_ids in common (6 = 1 + 5, 0 for nil objects)
24
+ @db.expects(:join_index).with(@size,index).returns(index+6).at_least(0)
25
+ end
26
+ @other_proxy = Rod::CollectionProxy.new(size,@db,@size,Rod::Model)
27
+ end
28
+
29
+ it "should be possible to compute their intersection" do
30
+ (@proxy & @other_proxy).size.must_equal 5
31
+ end
32
+
33
+ it "should be possible to compute their sum" do
34
+ (@proxy | @other_proxy).size.must_equal 15
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,36 @@
1
+ require 'bundler/setup'
2
+ require 'minitest/autorun'
3
+ require 'rod'
4
+
5
+ describe Rod::Database do
6
+ describe "a database" do
7
+ it "should allow to create itself without a block given" do
8
+ database = Rod::Database.instance
9
+ database.opened?.must_equal false
10
+ database.create_database("tmp/without_block")
11
+ database.opened?.must_equal true
12
+ database.close_database
13
+ database.opened?.must_equal false
14
+ end
15
+
16
+ it "should allow to create itself with a block given" do
17
+ database = Rod::Database.instance
18
+ database.opened?.must_equal false
19
+ database.create_database("tmp/without_block") do
20
+ database.opened?.must_equal true
21
+ end
22
+ database.opened?.must_equal false
23
+ end
24
+
25
+ it "should close itself on create even if an exception is raised" do
26
+ database = Rod::Database.instance
27
+ (proc do
28
+ database.create_database("tmp/block_exception") do
29
+ database.opened?.must_equal true
30
+ raise "Runtime exception"
31
+ end
32
+ end).must_raise RuntimeError
33
+ database.opened?.must_equal false
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,26 @@
1
+ require 'bundler/setup'
2
+ require 'minitest/autorun'
3
+ require 'rod'
4
+
5
+ class User < Rod::Model
6
+ database_class Rod::Database
7
+ end
8
+
9
+ describe Rod::Model do
10
+ describe "a model" do
11
+ before do
12
+ @database = Rod::Database.instance
13
+ @database.create_database("tmp/model")
14
+ end
15
+
16
+ after do
17
+ @database.close_database
18
+ end
19
+
20
+ it "should return nil if index in #[] is out of scope" do
21
+ User[0].must_equal nil
22
+ User[1].must_equal nil
23
+ User[-1].must_equal nil
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,73 @@
1
+ require 'bundler/setup'
2
+ require 'minitest/autorun'
3
+ require 'rod'
4
+
5
+ describe Rod::Property::Base do
6
+ describe "a property" do
7
+ before do
8
+ @klass = MiniTest::Mock.new
9
+ @klass.expect :nil?,false
10
+ @field = Rod::Property::Field.new(@klass,:user_name,:string)
11
+ end
12
+
13
+ after do
14
+ @klass.verify
15
+ end
16
+
17
+ it "must have proper name" do
18
+ @field.name.must_equal :user_name
19
+ end
20
+
21
+ it "must have proper type" do
22
+ @field.type.must_equal :string
23
+ end
24
+
25
+ it "must produce its metadata" do
26
+ @field.metadata.wont_be_nil
27
+ end
28
+
29
+ it "must covert to C struct" do
30
+ @field.to_c_struct.wont_be_nil
31
+ end
32
+
33
+ it "must produce its layout" do
34
+ @field.layout.wont_be_nil
35
+ end
36
+
37
+ it "must not have an index" do
38
+ @field.has_index?.wont_equal true
39
+ end
40
+ end
41
+
42
+ describe "an indexed property" do
43
+ before do
44
+ @klass = MiniTest::Mock.new
45
+ @klass.expect :nil?,false
46
+ @field = Rod::Property::Field.new(@klass,:user_name,:string,:index => :flat)
47
+ end
48
+
49
+ it "must have an index" do
50
+ @field.has_index?.must_equal true
51
+ end
52
+
53
+ it "must return an index" do
54
+ database = MiniTest::Mock.new
55
+ database.expect :path,"path"
56
+ @klass.expect :database,database
57
+ @klass.expect :model_path,"model_path"
58
+ @field.index.wont_be_nil
59
+ database.verify
60
+ end
61
+
62
+ it "must define finders" do
63
+ database = MiniTest::Mock.new
64
+ database.expect :nil?,false
65
+ database.expect :path,"path"
66
+ @klass.expect :database,database
67
+ @klass.expect :model_path,"model_path"
68
+ @field.define_finders
69
+ proc {@klass.find_by_user_name("Name")}.must_be_silent
70
+ database.verify
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,244 @@
1
+ require 'bundler/setup'
2
+ require 'minitest/autorun'
3
+ require 'rod'
4
+
5
+ describe Rod::Property::Field do
6
+ before do
7
+ @klass = MiniTest::Mock.new
8
+ @klass.expect :nil?,false
9
+ end
10
+
11
+ after do
12
+ @klass.verify
13
+ end
14
+
15
+ describe "a generic field" do
16
+ before do
17
+ @builder = MiniTest::Mock.new
18
+ @field = Rod::Property::Field.new(@klass,:user_name,:string)
19
+ end
20
+
21
+ after do
22
+ @builder.verify
23
+ end
24
+
25
+ it "must be a field" do
26
+ @field.field?.must_equal true
27
+ end
28
+
29
+ it "must not be an association" do
30
+ @field.association?.wont_equal true
31
+ end
32
+
33
+ it "must define C accessors" do
34
+ @klass.expect :struct_name, "struct_name"
35
+ @builder.expect :c,nil,[String]
36
+ @field.define_c_accessors(@builder)
37
+ end
38
+
39
+ it "must seal C accessors" do
40
+ @klass.expect :send,nil,[:private,String]
41
+ @field.seal_c_accessors
42
+ end
43
+
44
+ it "must define getter" do
45
+ @klass.expect :send,nil,[:define_method,"user_name"]
46
+ @klass.expect :database,nil
47
+ @field.define_getter
48
+ end
49
+
50
+ it "must define setter" do
51
+ @klass.expect :send,nil,[:define_method,"user_name="]
52
+ @field.define_setter
53
+ end
54
+ end
55
+
56
+ describe "a string field" do
57
+ before do
58
+ @field = Rod::Property::Field.new(@klass,:user_name,:string)
59
+ end
60
+
61
+ it "must have string type" do
62
+ @field.type.must_equal :string
63
+ end
64
+
65
+ it "must have empty string as default value" do
66
+ @field.default_value.must_equal ''
67
+ end
68
+
69
+ it "must be a variable size field" do
70
+ @field.variable_size?.must_equal true
71
+ end
72
+
73
+ it "must set utf-8 encoding for dumped value" do
74
+ @field.dump("string").encoding.must_equal Encoding.find("utf-8")
75
+ end
76
+
77
+ it "must set utf-8 encoding for loaded value" do
78
+ @field.load("string").encoding.must_equal Encoding.find("utf-8")
79
+ end
80
+
81
+ it "must not be an identifier" do
82
+ @field.identifier?.wont_equal true
83
+ end
84
+
85
+ it "must produce proper metadata" do
86
+ @field.metadata.must_equal({:type => :string})
87
+ end
88
+ end
89
+
90
+ describe "an object field" do
91
+ before do
92
+ @field = Rod::Property::Field.new(@klass,:tag,:object)
93
+ end
94
+
95
+ it "must have object type" do
96
+ @field.type.must_equal :object
97
+ end
98
+
99
+ it "must have nil as default value" do
100
+ @field.default_value.must_equal nil
101
+ end
102
+
103
+ it "must be a variable size field" do
104
+ @field.variable_size?.must_equal true
105
+ end
106
+
107
+ it "must marshal dumped value" do
108
+ @field.dump(:value).must_equal Marshal::dump(:value)
109
+ end
110
+
111
+ it "must unmarshal loaded value" do
112
+ @field.load(Marshal::dump(:value)).must_equal :value
113
+ end
114
+
115
+ it "must produce proper metadata" do
116
+ @field.metadata.must_equal({:type => :object})
117
+ end
118
+ end
119
+
120
+ describe "a json field" do
121
+ before do
122
+ @field = Rod::Property::Field.new(@klass,:tag,:json)
123
+ end
124
+
125
+ it "must have json type" do
126
+ @field.type.must_equal :json
127
+ end
128
+
129
+ it "must have nil as default value" do
130
+ @field.default_value.must_equal nil
131
+ end
132
+
133
+ it "must be a variable size field" do
134
+ @field.variable_size?.must_equal true
135
+ end
136
+
137
+ it "must convert to json dumped value" do
138
+ @field.dump("value").must_equal JSON::dump(["value"])
139
+ end
140
+
141
+ it "must convert from json loaded value" do
142
+ @field.load(JSON::dump(["value"])).must_equal "value"
143
+ end
144
+
145
+ it "must produce proper metadata" do
146
+ @field.metadata.must_equal({:type => :json})
147
+ end
148
+ end
149
+
150
+ describe "an integer field" do
151
+ before do
152
+ @field = Rod::Property::Field.new(@klass,:tag,:integer)
153
+ end
154
+
155
+ it "must have integer type" do
156
+ @field.type.must_equal :integer
157
+ end
158
+
159
+ it "must have 0 as default value" do
160
+ @field.default_value.must_equal 0
161
+ end
162
+
163
+ it "must not be a variable size field" do
164
+ @field.variable_size?.wont_equal true
165
+ end
166
+
167
+ it "must pass dumped value" do
168
+ @field.dump(-10).must_equal -10
169
+ end
170
+
171
+ it "must pass loaded value" do
172
+ @field.load(-10).must_equal -10
173
+ end
174
+
175
+ it "must produce proper metadata" do
176
+ @field.metadata.must_equal({:type => :integer})
177
+ end
178
+ end
179
+
180
+ describe "a float field" do
181
+ before do
182
+ @field = Rod::Property::Field.new(@klass,:tag,:float)
183
+ end
184
+
185
+ it "must have float type" do
186
+ @field.type.must_equal :float
187
+ end
188
+
189
+ it "must have 0.0 as default value" do
190
+ @field.default_value.must_equal 0.0
191
+ end
192
+
193
+ it "must not be a variable size field" do
194
+ @field.variable_size?.wont_equal true
195
+ end
196
+
197
+ it "must pass dumped value" do
198
+ @field.dump(-10.0).must_equal -10.0
199
+ end
200
+
201
+ it "must pass loaded value" do
202
+ @field.load(-10.0).must_equal -10.0
203
+ end
204
+
205
+ it "must produce proper metadata" do
206
+ @field.metadata.must_equal({:type => :float})
207
+ end
208
+ end
209
+
210
+ describe "an ulong field" do
211
+ before do
212
+ @field = Rod::Property::Field.new(@klass,:tag,:ulong)
213
+ end
214
+
215
+ it "must have ulong type" do
216
+ @field.type.must_equal :ulong
217
+ end
218
+
219
+ it "must have 0 as default value" do
220
+ @field.default_value.must_equal 0
221
+ end
222
+
223
+ it "must not be a variable size field" do
224
+ @field.variable_size?.wont_equal true
225
+ end
226
+
227
+ it "must pass dumped value if it is greater or equals 0" do
228
+ @field.dump(10.0).must_equal 10.0
229
+ @field.dump(0).must_equal 0
230
+ end
231
+
232
+ it "must raise exception when dumping value lower than 0" do
233
+ proc {@field.dump(-10)}.must_raise Rod::InvalidArgument
234
+ end
235
+
236
+ it "must pass loaded value" do
237
+ @field.load(10).must_equal 10
238
+ end
239
+
240
+ it "must produce proper metadata" do
241
+ @field.metadata.must_equal({:type => :ulong})
242
+ end
243
+ end
244
+ end
@@ -0,0 +1,67 @@
1
+ require 'bundler/setup'
2
+ require 'minitest/autorun'
3
+ require 'rod'
4
+
5
+ describe Rod::Property::PluralAssociation do
6
+ before do
7
+ @klass = MiniTest::Mock.new
8
+ @builder = MiniTest::Mock.new
9
+ @klass.expect :nil?,false
10
+ end
11
+
12
+ after do
13
+ @klass.verify
14
+ @builder.verify
15
+ end
16
+
17
+ describe "a plural association" do
18
+ before do
19
+ @association = Rod::Property::PluralAssociation.new(@klass,:users,
20
+ :polymorphic => true)
21
+ end
22
+
23
+ it "must not be a field" do
24
+ @association.field?.wont_equal true
25
+ end
26
+
27
+ it "must be an association" do
28
+ @association.association?.must_equal true
29
+ end
30
+
31
+ it "must not be a singular association" do
32
+ @association.singular?.wont_equal true
33
+ end
34
+
35
+ it "must be a plural association" do
36
+ @association.plural?.must_equal true
37
+ end
38
+
39
+ it "must produce proper metadata" do
40
+ @association.metadata.must_equal({:polymorphic => true})
41
+ end
42
+
43
+ it "must define C accessors" do
44
+ @klass.expect :struct_name, "struct_name"
45
+ @builder.expect :c,nil,[String]
46
+ @association.define_c_accessors(@builder)
47
+ end
48
+
49
+ it "must seal C accessors" do
50
+ @klass.expect :send,nil,[:private,String]
51
+ @association.seal_c_accessors
52
+ end
53
+
54
+ it "must define getter" do
55
+ @klass.expect :send,nil,[:define_method,"users"]
56
+ @klass.expect :scope_name,"Rod"
57
+ @klass.expect :database, nil
58
+ @association.define_getter
59
+ end
60
+
61
+ it "must define setter" do
62
+ @klass.expect :send,nil,[:define_method,"users="]
63
+ @association.define_setter
64
+ end
65
+ end
66
+ end
67
+