rod 0.7.1 → 0.7.2

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.
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
+