rod 0.6.1 → 0.6.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.
- data/.gitignore +7 -0
- data/{README → README.rdoc} +33 -2
- data/Rakefile +7 -2
- data/changelog.txt +13 -0
- data/contributors.txt +2 -0
- data/features/append.feature +221 -0
- data/features/assoc_indexing.feature +66 -0
- data/features/basic.feature +199 -0
- data/features/collection.feature +171 -0
- data/features/flat_indexing.feature +140 -0
- data/features/fred.feature +49 -0
- data/features/inheritence.feature +211 -0
- data/features/muliple_db.feature +113 -0
- data/features/relationships.feature +195 -0
- data/features/segmented_indexing.feature +172 -0
- data/features/steps/model.rb +386 -0
- data/features/steps/rod.rb +71 -0
- data/features/steps/test_helper.rb +5 -0
- data/lib/rod/abstract_database.rb +17 -5
- data/lib/rod/constants.rb +1 -1
- data/lib/rod/database.rb +95 -74
- data/lib/rod/join_element.rb +6 -2
- data/lib/rod/model.rb +37 -9
- data/rod.gemspec +15 -12
- data/tests/check_strings.rb +10 -0
- data/tests/class_compatibility_create.rb +14 -0
- data/tests/class_compatibility_verify.rb +18 -0
- data/tests/eff1_test.rb +60 -0
- data/tests/eff2_test.rb +61 -0
- data/tests/full_runs.rb +68 -0
- data/tests/generate_classes_create.rb +25 -0
- data/tests/generate_classes_model.rb +23 -0
- data/tests/generate_classes_rewrite.rb +7 -0
- data/tests/generate_classes_verify.rb +46 -0
- data/tests/load_struct.rb +24 -0
- data/tests/migration_create.rb +25 -0
- data/tests/migration_migrate.rb +22 -0
- data/tests/migration_model1.rb +23 -0
- data/tests/migration_model2.rb +27 -0
- data/tests/migration_verify.rb +56 -0
- data/tests/mock_tests.rb +128 -0
- data/tests/read_on_create.rb +45 -0
- data/tests/save_struct.rb +49 -0
- data/tests/structures.rb +52 -0
- data/tests/unit/database.rb +60 -0
- data/tests/unit/model.rb +36 -0
- data/tests/unit/model_tests.rb +116 -0
- data/tests/validate_read_on_create.rb +12 -0
- data/utils/convert_index.rb +31 -0
- metadata +77 -28
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rod'
|
2
|
+
|
3
|
+
class Database < Rod::Database
|
4
|
+
end
|
5
|
+
|
6
|
+
class Model < Rod::Model
|
7
|
+
database_class Database
|
8
|
+
end
|
9
|
+
|
10
|
+
class User < Model
|
11
|
+
field :name, :string, :index => :flat
|
12
|
+
field :surname, :string
|
13
|
+
has_one :account, :index => :flat
|
14
|
+
has_many :files, :index => :flat, :class_name => "UserFile"
|
15
|
+
end
|
16
|
+
|
17
|
+
class Account < Model
|
18
|
+
field :login, :string
|
19
|
+
end
|
20
|
+
|
21
|
+
class UserFile < Model
|
22
|
+
field :data, :string
|
23
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'rod'
|
2
|
+
|
3
|
+
class Database < Rod::Database
|
4
|
+
end
|
5
|
+
|
6
|
+
class Model < Rod::Model
|
7
|
+
database_class Database
|
8
|
+
end
|
9
|
+
|
10
|
+
class User < Model
|
11
|
+
field :name, :string, :index => :flat
|
12
|
+
field :age, :integer
|
13
|
+
has_one :account, :index => :flat
|
14
|
+
has_many :files, :index => :flat, :class_name => "UserFile"
|
15
|
+
has_many :accounts, :index => :flat
|
16
|
+
end
|
17
|
+
|
18
|
+
class Account < Model
|
19
|
+
field :login, :string
|
20
|
+
field :password, :string
|
21
|
+
end
|
22
|
+
|
23
|
+
class UserFile < Model
|
24
|
+
field :data, :string
|
25
|
+
field :name, :string, :index => :flat
|
26
|
+
end
|
27
|
+
|
@@ -0,0 +1,56 @@
|
|
1
|
+
$:.unshift("lib")
|
2
|
+
require 'rod'
|
3
|
+
require 'rspec/expectations'
|
4
|
+
require File.join(".",File.dirname(__FILE__),"migration_model2")
|
5
|
+
|
6
|
+
Rod::Database.development_mode = true
|
7
|
+
|
8
|
+
Database.instance.open_database("tmp/migration")
|
9
|
+
|
10
|
+
user = User[0]
|
11
|
+
user.should_not == nil
|
12
|
+
user = User.find_by_name("John")
|
13
|
+
user.should_not == nil
|
14
|
+
user.name.should == "John"
|
15
|
+
user.age.should == 0
|
16
|
+
user.account.should_not == nil
|
17
|
+
user.account.should == Account[0]
|
18
|
+
user.files.size.should == 3
|
19
|
+
user.accounts.size.should == 1
|
20
|
+
user.accounts[0].should == user.account
|
21
|
+
|
22
|
+
account = Account[0]
|
23
|
+
account.login.should == "john"
|
24
|
+
account.password.should == ""
|
25
|
+
User.find_all_by_account(account).size.should == 1
|
26
|
+
User.find_all_by_account(account)[0].should == user
|
27
|
+
User.find_by_account(account).should_not == nil
|
28
|
+
user.account.should == account
|
29
|
+
|
30
|
+
user = User.find_by_name("Amanda")
|
31
|
+
user.should_not == nil
|
32
|
+
user.name.should == "Amanda"
|
33
|
+
user.age.should == 0
|
34
|
+
user.account.should_not == nil
|
35
|
+
user.files.size.should == 5
|
36
|
+
user.accounts.size.should == 1
|
37
|
+
user.accounts[0].should == user.account
|
38
|
+
|
39
|
+
account = Account[1]
|
40
|
+
account.login.should == "amanda"
|
41
|
+
account.password.should == ""
|
42
|
+
User.find_by_account(account).should_not == nil
|
43
|
+
user.account.should == account
|
44
|
+
|
45
|
+
file = UserFile[0]
|
46
|
+
file.data.should == "0 data"
|
47
|
+
|
48
|
+
UserFile.each do |file|
|
49
|
+
file.data.should_not == nil
|
50
|
+
file.name.should == ""
|
51
|
+
end
|
52
|
+
users = User.find_all_by_files(file)
|
53
|
+
users.size.should == 2
|
54
|
+
users[1].should == user
|
55
|
+
|
56
|
+
Database.instance.close_database
|
data/tests/mock_tests.rb
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
$:.unshift("lib")
|
2
|
+
|
3
|
+
require 'rod'
|
4
|
+
require 'test/unit'
|
5
|
+
require 'mocha'
|
6
|
+
|
7
|
+
module RodTest
|
8
|
+
class InnerExporter < Rod::Exporter
|
9
|
+
end
|
10
|
+
|
11
|
+
class InnerLoader < Rod::Loader
|
12
|
+
end
|
13
|
+
|
14
|
+
class Exporter
|
15
|
+
def self.method_missing(method_sym, *arguments)
|
16
|
+
arguments_str = ""
|
17
|
+
# begin
|
18
|
+
arguments_str = arguments.to_s
|
19
|
+
# rescue TypeError
|
20
|
+
# empty is ok - thrown when trying to access fields too early
|
21
|
+
# end
|
22
|
+
puts "EX: static #{method_sym.to_s} (#{arguments_str})"
|
23
|
+
InnerExporter.send(method_sym, *arguments)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class Loader
|
28
|
+
def self.method_missing(method_sym, *arguments)
|
29
|
+
arguments_str = arguments.to_s
|
30
|
+
puts "LD: static #{method_sym.to_s} (#{arguments_str})"
|
31
|
+
InnerLoader.send(method_sym, *arguments)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class Database < Rod::Database
|
36
|
+
end
|
37
|
+
|
38
|
+
class Model < Rod::Model
|
39
|
+
attr_accessor :used
|
40
|
+
database_class Database
|
41
|
+
end
|
42
|
+
|
43
|
+
class BStruct < Model
|
44
|
+
field :b, :string
|
45
|
+
has_one :a_struct
|
46
|
+
|
47
|
+
def to_s
|
48
|
+
"#{self.b}"
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
class AStruct < Model
|
54
|
+
field :a1, :integer
|
55
|
+
field :a2, :ulong, :index => true
|
56
|
+
has_many :b_structs, :class_name => "RodTest::BStruct"
|
57
|
+
|
58
|
+
# def to_s <- causes strange Error - see Exporter::method_missing
|
59
|
+
# "#{a1}, #{a2}"
|
60
|
+
# end
|
61
|
+
end
|
62
|
+
|
63
|
+
class ModuleTests < Test::Unit::TestCase
|
64
|
+
|
65
|
+
MAGNITUDE = 5
|
66
|
+
TEST_FILENAME = "tmp/db"
|
67
|
+
|
68
|
+
def setup
|
69
|
+
@as = Array.new
|
70
|
+
@bs = Array.new
|
71
|
+
|
72
|
+
(0..MAGNITUDE).each do |j|
|
73
|
+
@as[j] = AStruct.new
|
74
|
+
@as[j].a1 = j
|
75
|
+
@as[j].a2 = j * 10000
|
76
|
+
end
|
77
|
+
|
78
|
+
(0..MAGNITUDE).each do |j|
|
79
|
+
@bs[j] = BStruct.new
|
80
|
+
@bs[j].b = "string_#{j}"
|
81
|
+
@bs[j].a_struct = @as[j]
|
82
|
+
end
|
83
|
+
|
84
|
+
# (0..MAGNITUDE).each do |j|
|
85
|
+
# @as[j].b_structs = @bs[j .. ((j+1) % MAGNITUDE)]
|
86
|
+
# end
|
87
|
+
end
|
88
|
+
|
89
|
+
def teardown
|
90
|
+
begin
|
91
|
+
RodTest::Database.instance.close_database
|
92
|
+
rescue RuntimeError
|
93
|
+
#ok, because of mocking store subroutines not all references are marked as stored
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_store
|
98
|
+
puts
|
99
|
+
|
100
|
+
Database.instance.create_database("#{TEST_FILENAME}2")
|
101
|
+
|
102
|
+
Database.instance.expects(:_store_rod_test__a_struct).times(6)
|
103
|
+
Database.instance.expects(:_store_rod_test__b_struct).times(6)
|
104
|
+
@as.each do |a|
|
105
|
+
a.store
|
106
|
+
end
|
107
|
+
@bs.each do |b|
|
108
|
+
b.store
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_create
|
113
|
+
puts
|
114
|
+
|
115
|
+
Database.instance..expects(:create)
|
116
|
+
Database.instance.create_database("#{TEST_FILENAME}3")
|
117
|
+
end
|
118
|
+
|
119
|
+
def test_close
|
120
|
+
puts
|
121
|
+
|
122
|
+
Database.instance.create_database("#{TEST_FILENAME}4")
|
123
|
+
Exporter.instance.expects(:close)
|
124
|
+
Database.instance.close_database()
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
$:.unshift("tests")
|
2
|
+
require 'structures'
|
3
|
+
require 'validate_read_on_create'
|
4
|
+
|
5
|
+
puts "-- Read data while creating DB --"
|
6
|
+
Rod::Database.development_mode = true
|
7
|
+
|
8
|
+
|
9
|
+
RodTest::Database.instance.create_database("tmp/read_write")
|
10
|
+
my_structures = []
|
11
|
+
MAGNITUDO.times do |index|
|
12
|
+
your_struct = RodTest::YourStruct.new
|
13
|
+
your_struct.counter = index
|
14
|
+
your_struct.title = "Title_#{index}"
|
15
|
+
your_struct.store
|
16
|
+
|
17
|
+
my_struct = RodTest::MyStruct.new
|
18
|
+
my_struct.count = index
|
19
|
+
my_struct.your_struct = your_struct
|
20
|
+
my_struct.title = "Title_#{index}"
|
21
|
+
my_struct.title2 = "Title2_#{index}"
|
22
|
+
|
23
|
+
my_struct.store
|
24
|
+
my_structures << my_struct
|
25
|
+
end
|
26
|
+
|
27
|
+
MAGNITUDO.times do |index|
|
28
|
+
# validate object fetched from cache
|
29
|
+
struct = RodTest::MyStruct[index]
|
30
|
+
validate(index,struct)
|
31
|
+
# validate object referenced previously
|
32
|
+
validate(index,my_structures[index])
|
33
|
+
# validate referential integrity
|
34
|
+
if struct.object_id != my_structures[index].object_id
|
35
|
+
raise "Object stored and recived are different #{struct.object_id} " +
|
36
|
+
"#{my_structures[index].object_id}"
|
37
|
+
end
|
38
|
+
if struct != my_structures[index]
|
39
|
+
raise "Object stored and recived are different #{struct} " +
|
40
|
+
"#{my_structures[index]}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
RodTest::Database.instance.close_database
|
@@ -0,0 +1,49 @@
|
|
1
|
+
$:.unshift("tests")
|
2
|
+
require 'structures'
|
3
|
+
|
4
|
+
puts "-- Save sample structures test --"
|
5
|
+
Rod::Database.development_mode = true
|
6
|
+
RodTest::Database.instance.create_database("tmp/abc")
|
7
|
+
|
8
|
+
#MAGNITUDE = 100000
|
9
|
+
MAGNITUDE = 50
|
10
|
+
|
11
|
+
his = []
|
12
|
+
(MAGNITUDE * 10).times do |i|
|
13
|
+
his[i] = RodTest::HisStruct.new
|
14
|
+
his[i].inde = i
|
15
|
+
end
|
16
|
+
|
17
|
+
ys = []
|
18
|
+
(MAGNITUDE * 1).times do |i|
|
19
|
+
ys[i] = RodTest::YourStruct.new
|
20
|
+
ys[i].counter = 10
|
21
|
+
ys[i].his_structs = his[i*10...(i+1)*10]
|
22
|
+
end
|
23
|
+
|
24
|
+
ms = []
|
25
|
+
(MAGNITUDE * 1).times do |i|
|
26
|
+
ms[i] = RodTest::MyStruct.new
|
27
|
+
ms[i].count = 10 * i
|
28
|
+
ms[i].precision = 0.1 * i
|
29
|
+
ms[i].identifier = i
|
30
|
+
ms[i].your_struct = ys[i]
|
31
|
+
ms[i].title = "title_#{i}"
|
32
|
+
ms[i].title2 = "title2_#{i}"
|
33
|
+
ms[i].body = "body_#{i}"
|
34
|
+
end
|
35
|
+
|
36
|
+
RodTest::Database.instance.print_layout
|
37
|
+
ms.each_with_index{|s,i|
|
38
|
+
begin
|
39
|
+
puts i if i % 1000 == 0
|
40
|
+
s.store
|
41
|
+
rescue Exception => e
|
42
|
+
puts e
|
43
|
+
raise
|
44
|
+
end
|
45
|
+
}
|
46
|
+
ys.each{|y| y.store}
|
47
|
+
his.each{|h| h.store}
|
48
|
+
RodTest::Database.instance.print_layout
|
49
|
+
RodTest::Database.instance.close_database
|
data/tests/structures.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
$:.unshift("lib")
|
2
|
+
require 'rod'
|
3
|
+
|
4
|
+
module RodTest
|
5
|
+
class Database < Rod::Database
|
6
|
+
end
|
7
|
+
|
8
|
+
class Model < Rod::Model
|
9
|
+
database_class Database
|
10
|
+
end
|
11
|
+
|
12
|
+
class MyStruct < Model
|
13
|
+
field :count, :integer
|
14
|
+
field :precision, :float
|
15
|
+
field :identifier, :ulong
|
16
|
+
field :title, :string, :index => :segmented
|
17
|
+
field :title2, :string
|
18
|
+
field :body, :string
|
19
|
+
has_one :your_struct
|
20
|
+
|
21
|
+
def to_s
|
22
|
+
"#{self.title} #{self.body} " +
|
23
|
+
"count #{self.count}, precision #{self.precision}, " +
|
24
|
+
"identifier #{self.identifier} rod_id #{self.rod_id} " +
|
25
|
+
"your_struct #{self.your_struct}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class YourStruct < Model
|
30
|
+
field :counter, :integer
|
31
|
+
field :title, :string
|
32
|
+
has_many :his_structs
|
33
|
+
has_many :her_structs, :class_name => "RodTest::HisStruct"
|
34
|
+
|
35
|
+
def to_s
|
36
|
+
"counter #{self.counter}, title #{self.title} his structs " +
|
37
|
+
"#{self.his_structs.map{|e| e.inde}.join("")}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class HisStruct < Model
|
42
|
+
field :inde, :integer
|
43
|
+
|
44
|
+
def to_s
|
45
|
+
"inde #{self.inde}"
|
46
|
+
end
|
47
|
+
|
48
|
+
def inspect
|
49
|
+
self.to_s
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
$:.unshift("lib")
|
2
|
+
require 'test/unit'
|
3
|
+
require 'rod'
|
4
|
+
|
5
|
+
class DatabaseTest < Test::Unit::TestCase
|
6
|
+
def setup
|
7
|
+
@database = Rod::Database.instance
|
8
|
+
@database.create_database("tmp/unit_database")
|
9
|
+
end
|
10
|
+
|
11
|
+
def teardown
|
12
|
+
@database.close_database
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_version_validity
|
16
|
+
Rod::VERSION.sub!(/.*/,"0.1.0")
|
17
|
+
file = "0.1.0"
|
18
|
+
assert(@database.send(:valid_version?,file))
|
19
|
+
|
20
|
+
Rod::VERSION.sub!(/.*/,"0.1.1")
|
21
|
+
file = "0.1.0"
|
22
|
+
assert(not(@database.send(:valid_version?,file)))
|
23
|
+
|
24
|
+
Rod::VERSION.sub!(/.*/,"0.2.1")
|
25
|
+
file = "0.2.0"
|
26
|
+
assert(@database.send(:valid_version?,file))
|
27
|
+
|
28
|
+
Rod::VERSION.sub!(/.*/,"0.2.0")
|
29
|
+
file = "0.2.1"
|
30
|
+
assert(!@database.send(:valid_version?,file))
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_created_at
|
34
|
+
assert(Time.now - @database.metadata["Rod"][:created_at] < 10)
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_updated_at
|
38
|
+
sleep(1)
|
39
|
+
@database.close_database
|
40
|
+
@database.open_database("tmp/unit_database",false)
|
41
|
+
assert(@database.metadata["Rod"][:updated_at] -
|
42
|
+
@database.metadata["Rod"][:created_at] >= 1)
|
43
|
+
assert(@database.metadata["Rod"][:updated_at] -
|
44
|
+
@database.metadata["Rod"][:created_at] < 4)
|
45
|
+
sleep(2)
|
46
|
+
@database.close_database
|
47
|
+
@database.open_database("tmp/unit_database",false)
|
48
|
+
assert(@database.metadata["Rod"][:updated_at] -
|
49
|
+
@database.metadata["Rod"][:created_at] >= 3)
|
50
|
+
assert(@database.metadata["Rod"][:updated_at] -
|
51
|
+
@database.metadata["Rod"][:created_at] < 6)
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_superclass
|
55
|
+
@database.close_database
|
56
|
+
@database.open_database("tmp/unit_database")
|
57
|
+
assert(@database.metadata["Rod::StringElement"][:superclass] ==
|
58
|
+
Rod::AbstractModel.name)
|
59
|
+
end
|
60
|
+
end
|