odba 1.0.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.
@@ -0,0 +1,371 @@
1
+ #!/usr/bin/env ruby
2
+ # TestIndex -- oddb -- 13.05.2004 -- hwyss@ywesee.com mwalder@ywesee.com
3
+
4
+ $: << File.dirname(__FILE__)
5
+ $: << File.expand_path("../lib", File.dirname(__FILE__))
6
+
7
+ require 'test/unit'
8
+ require 'odba/index'
9
+ require 'odba/index_definition'
10
+ require 'odba/odba'
11
+ require 'flexmock'
12
+
13
+ module ODBA
14
+ class Origin
15
+ attr_accessor :term, :odba_id
16
+ end
17
+ class OriginSubclass < Origin
18
+ end
19
+ class Target
20
+ attr_accessor :origin, :odba_id
21
+ end
22
+ class TargetSubclass < Target
23
+ end
24
+ class TestIndexCommon < Test::Unit::TestCase
25
+ include FlexMock::TestCase
26
+ def setup
27
+ @storage = flexmock('Storage')
28
+ ODBA.storage = @storage
29
+ df = IndexDefinition.new
30
+ df.index_name = 'index'
31
+ df.origin_klass = :Origin
32
+ df.target_klass = :Target
33
+ df.resolve_origin = :origin
34
+ df.resolve_search_term = :term
35
+ @index = IndexCommon.new(df, ODBA)
36
+ end
37
+ def test_delete
38
+ handle = flexmock('DB-Handle')
39
+ @storage.should_receive(:delete_index_element)\
40
+ .with('index', 15, 'origin_id')\
41
+ .times(1).and_return {assert(true) }
42
+ origin = Origin.new
43
+ origin.odba_id = 15
44
+ @index.delete(origin)
45
+ @storage.should_receive(:delete_index_element)\
46
+ .with('index', 16, 'target_id')\
47
+ .times(1).and_return {assert(true) }
48
+ target = Target.new
49
+ target.odba_id = 16
50
+ @index.delete(target)
51
+ end
52
+ def test_do_update_index
53
+ @storage.should_receive(:update_index)\
54
+ .with('index', 12, 'foo', nil).and_return {
55
+ assert(true)
56
+ }
57
+ @index.do_update_index(12, 'foo')
58
+ end
59
+ def test_fill
60
+ df = IndexDefinition.new
61
+ df.index_name = 'index'
62
+ df.resolve_origin = 'get_origin'
63
+ df.resolve_search_term = 'the_search_term'
64
+ index = IndexCommon.new(df, self)
65
+
66
+ origin = flexmock('origin')
67
+ origin.should_receive(:the_search_term).and_return('tst')
68
+ origin.should_receive(:odba_id).and_return(4)
69
+ target = flexmock('target')
70
+ target.should_receive(:get_origin).and_return(origin)
71
+ target.should_receive(:odba_id).and_return(3)
72
+
73
+ targets = [target, [target]]
74
+
75
+ @storage.should_receive(:update_index)\
76
+ .with('index', 4, 'tst', 3).times(2).and_return { assert(true) }
77
+
78
+ index.fill(targets)
79
+ end
80
+ def test_keys
81
+ @storage.should_receive(:index_fetch_keys).with('index', nil)\
82
+ .and_return { ['key1', 'key2', ''] }
83
+ assert_equal(%w{key1 key2}, @index.keys)
84
+ @storage.should_receive(:index_fetch_keys).with('index', 2)\
85
+ .and_return { ['k1', 'k2', ''] }
86
+ assert_equal(%w{k1 k2}, @index.keys(2))
87
+ @storage.should_receive(:index_fetch_keys).with('index', 1)\
88
+ .and_return { ['1', '2', ''] }
89
+ assert_equal(%w{1 2}, @index.keys(1))
90
+ end
91
+ def test_origin_class
92
+ df = IndexDefinition.new
93
+ df.index_name = 'index'
94
+ df.origin_klass = :Origin
95
+ index = IndexCommon.new(df, self)
96
+ assert_equal(true, index.origin_class?(Origin))
97
+ assert_equal(false, index.origin_class?(Target))
98
+ end
99
+ def test_proc_instance_origin
100
+ df = IndexDefinition.new
101
+ df.index_name = 'index'
102
+ index = IndexCommon.new(df, self)
103
+ pr = index.proc_instance_origin
104
+ stub = Object.new
105
+ assert_equal([stub], pr.call(stub))
106
+ end
107
+ def test_proc_resolve_search_term
108
+ df = IndexDefinition.new
109
+ df.index_name = 'index'
110
+ index = IndexCommon.new(df, self)
111
+ pr = index.proc_resolve_search_term
112
+ stub = Object.new
113
+ assert_equal(stub.to_s.downcase, pr.call(stub))
114
+ end
115
+ def test_search_term
116
+ idf = IndexDefinition.new
117
+ idf.index_name = 'index'
118
+ idf.resolve_search_term = 'resolve_it'
119
+ origin = flexmock('origin')
120
+ origin.should_receive(:resolve_it).times(1).and_return('myterm')
121
+ index = IndexCommon.new(idf, ODBA)
122
+ assert_equal('myterm', index.search_term(origin))
123
+ end
124
+ def test_set_relevance
125
+ meta = flexmock('Meta')
126
+ meta.should_receive(:respond_to?).with(:set_relevance).and_return(true)
127
+ meta.should_receive(:set_relevance).with('foo', 'bar').and_return {
128
+ assert(true) }
129
+ meta.should_receive(:set_relevance).with('baz', 'fro').and_return {
130
+ assert(true) }
131
+ @index.set_relevance(meta, [%w{foo bar}, %w{baz fro}])
132
+ end
133
+ def test_update__origin
134
+ origin = Origin.new
135
+ origin.odba_id = 1
136
+ origin.term = "search-term"
137
+ @storage.should_receive(:index_target_ids).with('index', 1)\
138
+ .and_return([[3, 'old-term'], [4, 'old-term']])
139
+ @storage.should_receive(:index_delete_origin).with('index', 1, "old-term")
140
+ @storage.should_receive(:update_index)\
141
+ .with('index', 1, 'search-term', 3).and_return {
142
+ assert(true) }
143
+ @storage.should_receive(:update_index)\
144
+ .with('index', 1, 'search-term', 4).and_return {
145
+ assert(true) }
146
+ @index.update(origin)
147
+ end
148
+ def test_update__target
149
+ origin = Origin.new
150
+ origin.odba_id = 1
151
+ origin.term = "search-term"
152
+ target = Target.new
153
+ target.odba_id = 2
154
+ target.origin = origin
155
+ @storage.should_receive(:index_origin_ids).with('index', 2)\
156
+ .and_return([[1, 'old-term'], [4, 'obsolete-term']])
157
+ @storage.should_receive(:index_delete_target)\
158
+ .with('index', 1, 'old-term', 2).and_return { assert(true) }
159
+ @storage.should_receive(:index_delete_target)\
160
+ .with('index', 4, 'obsolete-term', 2).and_return { assert(true) }
161
+ @storage.should_receive(:update_index)\
162
+ .with('index', 1, 'search-term', 2).and_return {
163
+ assert(true) }
164
+ @index.update(target)
165
+ end
166
+ def test_update__subclass
167
+ origin = OriginSubclass.new
168
+ target = TargetSubclass.new
169
+ assert_nothing_raised {
170
+ @index.update(origin)
171
+ }
172
+ assert_nothing_raised {
173
+ @index.update(target)
174
+ }
175
+ end
176
+ end
177
+ class TestIndex < Test::Unit::TestCase
178
+ include FlexMock::TestCase
179
+ def setup
180
+ @storage = flexmock('Storage')
181
+ @storage.should_receive(:create_index).with('index')
182
+ ODBA.storage = @storage
183
+ df = IndexDefinition.new
184
+ df.index_name = 'index'
185
+ df.origin_klass = :Origin
186
+ df.target_klass = :Target
187
+ df.resolve_origin = :origin
188
+ df.resolve_search_term = :term
189
+ @index = Index.new(df, self)
190
+ end
191
+ def test_fetch_ids
192
+ rows = [[1,3], [2,2], [3,1]]
193
+ @storage.should_receive(:retrieve_from_index)\
194
+ .with('index', 'search-term', false, false).and_return rows
195
+ assert_equal([1,2,3], @index.fetch_ids('search-term'))
196
+ end
197
+ def test_search_terms
198
+ origin = Origin.new
199
+ origin.term = 'resolved'
200
+ assert_equal(['resolved'], @index.search_terms(origin))
201
+ origin.term = ['resolved']
202
+ assert_equal(['resolved'], @index.search_terms(origin))
203
+ end
204
+ end
205
+ class TestConditionIndex < Test::Unit::TestCase
206
+ include FlexMock::TestCase
207
+ def setup
208
+ @storage = flexmock('Storage')
209
+ @storage.should_receive(:create_condition_index)\
210
+ .with('index', {'crit1' => 'text', 'crit2' => 'Integer'})
211
+ ODBA.storage = @storage
212
+ df = IndexDefinition.new
213
+ df.index_name = 'index'
214
+ df.origin_klass = :Origin
215
+ df.target_klass = :Target
216
+ df.resolve_origin = :origin
217
+ df.resolve_search_term = [
218
+ ['crit1', 'term'],
219
+ ['crit2', {'type' => 'Integer', 'resolve' => 'odba_id'}],
220
+ ]
221
+ @index = ConditionIndex.new(df, self)
222
+ end
223
+ def test_do_update_index
224
+ data = {'crit1' => 'foo', 'condition' => 'like'}
225
+ @storage.should_receive(:update_condition_index)\
226
+ .with('index', 2, data, 3)
227
+ @index.do_update_index(2, data, 3)
228
+ end
229
+ def test_fetch_ids
230
+ rows = [[1,3], [2,2], [3,1]]
231
+ data = {'crit1' => 'foo', 'condition' => 'like'}
232
+ @storage.should_receive(:retrieve_from_condition_index)\
233
+ .with('index', data, false).and_return rows
234
+ assert_equal([1,2,3], @index.fetch_ids(data))
235
+ end
236
+ def test_proc_resolve_search_term
237
+ pr = @index.proc_resolve_search_term
238
+ origin = Origin.new
239
+ origin.term = 'search_term'
240
+ origin.odba_id = 15
241
+ expected = {
242
+ 'crit1' => 'search_term',
243
+ 'crit2' => 15,
244
+ }
245
+ assert_equal(expected, pr.call(origin))
246
+ end
247
+ def test_update_target
248
+ @storage.should_receive(:condition_index_ids)\
249
+ .with('index', 4, 'target_id').and_return {
250
+ [
251
+ {'origin_id' => 1, 'crit1' => '1st',
252
+ 'crit2' => 1, 'target_id' => 5},
253
+ {'origin_id' => 1, 'crit1' => '1st',
254
+ 'crit2' => 2, 'target_id' => 5},
255
+ ]
256
+ }
257
+ target = Target.new
258
+ target.odba_id = 4
259
+ origin1 = Origin.new
260
+ origin1.odba_id = 1
261
+ origin1.term = '1st'
262
+ origin2 = Origin.new
263
+ origin2.term = '2nd'
264
+ origin2.odba_id = 2
265
+ target.origin = [origin1, origin2]
266
+ @storage.should_receive(:condition_index_delete)\
267
+ .with('index', 1, [['crit1', '1st'], ['crit2', 2]], 4)\
268
+ .and_return { assert(true) }
269
+ @storage.should_receive(:update_condition_index)\
270
+ .with('index', 2, [['crit1', '2nd'], ['crit2', 2]], 4)\
271
+ .and_return { assert(true) }
272
+ @index.update_target(target)
273
+ end
274
+ def test_update_origin
275
+ @storage.should_receive(:condition_index_ids)\
276
+ .with('index', 1, 'origin_id').and_return {
277
+ [
278
+ {'origin_id' => 1, 'crit1' => '1st',
279
+ 'crit2' => 1, 'target_id' => 5},
280
+ {'origin_id' => 1, 'crit1' => '1st',
281
+ 'crit2' => 2, 'target_id' => 5},
282
+ ]
283
+ }
284
+ target = Target.new
285
+ target.odba_id = 4
286
+ origin1 = Origin.new
287
+ origin1.odba_id = 1
288
+ origin1.term = '1st'
289
+ origin2 = Origin.new
290
+ origin2.term = '2nd'
291
+ origin2.odba_id = 2
292
+ target.origin = [origin1, origin2]
293
+ @storage.should_receive(:condition_index_delete)\
294
+ .with('index', 1, [['crit1', '1st'], ['crit2', 2]])\
295
+ .and_return { assert(true) }
296
+ @storage.should_receive(:update_condition_index)\
297
+ .with('index', 2, [['crit1', '2nd'], ['crit2', 2]])\
298
+ .and_return { assert(true) }
299
+ @index.update_origin(origin1)
300
+ end
301
+ end
302
+ class TestFulltextIndex < Test::Unit::TestCase
303
+ include FlexMock::TestCase
304
+ def setup
305
+ @storage = flexmock('Storage')
306
+ @storage.should_receive(:create_fulltext_index).with('index')
307
+ ODBA.storage = @storage
308
+ df = IndexDefinition.new
309
+ df.index_name = 'index'
310
+ df.dictionary = 'german'
311
+ df.origin_klass = :Origin
312
+ df.target_klass = :Target
313
+ df.resolve_origin = :origin
314
+ df.resolve_search_term = 'term'
315
+ @index = FulltextIndex.new(df, self)
316
+ end
317
+ def test_fetch_ids
318
+ rows = [[1,3], [2,2], [3,1]]
319
+ @storage.should_receive(:retrieve_from_fulltext_index)\
320
+ .with('index', 'search-term', 'german', false).and_return rows
321
+ assert_equal([1,2,3], @index.fetch_ids('search-term'))
322
+ end
323
+ def test_do_update_index
324
+ @storage.should_receive(:update_fulltext_index)\
325
+ .with('index', 3, 'some full text', 4, 'german')
326
+ @index.do_update_index(3, 'some full text', 4)
327
+ end
328
+ def test_update_target
329
+ ## only deletes entries for the current target, and inserts from
330
+ # all origins
331
+ @storage.should_receive(:fulltext_index_delete)\
332
+ .with('index', 4, 'target_id')
333
+ @storage.should_receive(:update_fulltext_index)\
334
+ .with('index', 1, 'fulltext term', 4, 'german')
335
+ @storage.should_receive(:update_fulltext_index)\
336
+ .with('index', 2, 'fulltext term', 4, 'german')
337
+ target = Target.new
338
+ target.odba_id = 4
339
+ origin1 = Origin.new
340
+ origin1.odba_id = 1
341
+ origin1.term = ['fulltext term']
342
+ origin2 = Origin.new
343
+ origin2.term = ['fulltext term']
344
+ origin2.odba_id = 2
345
+ target.origin = [origin1, origin2]
346
+ @index.update(target)
347
+ end
348
+ def test_update_origin
349
+ ## deletes all entries for the current origin and must restore
350
+ # entries for all targets!
351
+ @storage.should_receive(:fulltext_index_target_ids)\
352
+ .times(1).with('index', 1).and_return([[4],[5]])
353
+ @storage.should_receive(:fulltext_index_delete)\
354
+ .times(1).with('index', 1, 'origin_id')
355
+ @storage.should_receive(:update_fulltext_index)\
356
+ .times(1).with('index', 1, 'fulltext term', 4, 'german')
357
+ @storage.should_receive(:update_fulltext_index)\
358
+ .times(1).with('index', 1, 'fulltext term', 5, 'german')
359
+ target = Target.new
360
+ target.odba_id = 4
361
+ origin1 = Origin.new
362
+ origin1.odba_id = 1
363
+ origin1.term = ['fulltext term']
364
+ origin2 = Origin.new
365
+ origin2.term = ['fulltext term']
366
+ origin2.odba_id = 2
367
+ target.origin = [origin1, origin2]
368
+ @index.update(origin1)
369
+ end
370
+ end
371
+ end
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $: << File.expand_path('../lib', File.dirname(__FILE__))
4
+
5
+ require 'test/unit'
6
+ require 'odba/marshal'
7
+
8
+ module ODBA
9
+ class TestMarshal < Test::Unit::TestCase
10
+ def setup
11
+ @foo = Array.new
12
+ end
13
+ def test_dump
14
+ assert_equal("04085b00",ODBA::Marshal.dump(@foo))
15
+ end
16
+ def test_load
17
+ assert_equal(@foo, ODBA::Marshal.load("04085b00"))
18
+ end
19
+ def test_load_18_in_19
20
+ if RUBY_VERSION >= '1.9'
21
+ require 'odba/18_19_loading_compatibility'
22
+ binary = "\004\bu:\tDate=\004\b[\bo:\rRational\a:\017@numeratori\003\205\353J:\021@denominatori\ai\000i\003\031\025#".unpack('H*').first
23
+ date = Marshal.load(binary)
24
+ assert_equal Date.new(2009,5,27), date
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,625 @@
1
+ #!/usr/bin/env ruby
2
+ # TestPersistable -- odba -- ??.??.???? -- hwyss@ywesee.com
3
+
4
+ $: << File.dirname(__FILE__)
5
+ $: << File.expand_path('../lib/', File.dirname(__FILE__))
6
+
7
+ require 'odba/persistable'
8
+ require 'odba/stub'
9
+ require 'odba/cache'
10
+ require 'odba/odba'
11
+ require 'odba/storage'
12
+ require 'odba/marshal'
13
+ require 'test/unit'
14
+ require 'flexmock'
15
+ require 'yaml'
16
+
17
+ module ODBA
18
+ module Persistable
19
+ attr_accessor :odba_references
20
+ attr_writer :odba_id
21
+ public :odba_replace_excluded!
22
+ end
23
+ class TestPersistable < Test::Unit::TestCase
24
+ include FlexMock::TestCase
25
+ class ODBAExcluding
26
+ include ODBA::Persistable
27
+ ODBA_EXCLUDE_VARS = ["@excluded"]
28
+ attr_accessor :included, :excluded
29
+ end
30
+ class ODBAContainer
31
+ include ODBA::Persistable
32
+ ODBA_SERIALIZABLE = ['@serializable']
33
+ attr_accessor :non_replaceable, :replaceable, :replaceable2,
34
+ :array, :odba_persistent, :serializable
35
+ attr_accessor :odba_snapshot_level
36
+ end
37
+ class Hash
38
+ include ODBA::Persistable
39
+ attr_accessor :odba_persistent
40
+ end
41
+ class IndexedStub
42
+ include Persistable
43
+ #attr_accessor :origin
44
+ odba_index :name
45
+ odba_index :foo, :bar
46
+ odba_index :origin, :origin, :non_replaceable, ODBAContainer
47
+ odba_index :redirect, 'redirect.name'
48
+ end
49
+ def setup
50
+ ODBA.storage = flexmock("storage")
51
+ ODBA.marshaller = flexmock("marshaller")
52
+ ODBA.cache = flexmock("cache")
53
+ @odba = ODBAContainer.new
54
+ end
55
+ def teardown
56
+ ODBA.storage.mock_verify
57
+ ODBA.marshaller.mock_verify
58
+ ODBA.cache.mock_verify
59
+ ODBA.storage = nil
60
+ ODBA.marshaller = nil
61
+ ODBA.cache = nil
62
+ end
63
+ def test_odba_id
64
+ ODBA.cache.mock_handle(:next_id) { ||
65
+ 2
66
+ }
67
+ ODBA.marshaller.mock_handle(:dump) { |obj|
68
+ "foo"
69
+ }
70
+ ODBA.storage.mock_handle(:store) { |id,obj|}
71
+ @odba.odba_take_snapshot(1)
72
+ assert_equal(2, @odba.odba_id)
73
+ ODBA.storage.mock_verify
74
+ ODBA.marshaller.mock_verify
75
+ end
76
+ def test_odba_delete
77
+ odba_container = ODBAContainer.new
78
+ odba_container.odba_id = 2
79
+ #ODBA.storage.mock_handle(:transaction) { |block| block.call}
80
+ ODBA.cache.mock_handle(:delete) { |object|
81
+ assert_equal(odba_container, object)
82
+ }
83
+ odba_container.odba_delete
84
+ end
85
+ def test_odba_replace_excluded
86
+ odba = ODBAExcluding.new
87
+ odba.included = "here to stay"
88
+ odba.excluded = "easy come easy go"
89
+ odba.odba_replace_excluded!
90
+ assert_equal("here to stay", odba.included)
91
+ assert_nil(odba.excluded)
92
+ end
93
+ def test_odba_replace_stubs
94
+ stub = flexmock
95
+ stub.should_receive(:odba_id).and_return(6)
96
+ stub.should_receive(:is_a?).with(Stub).and_return(true)
97
+ @odba.replaceable = stub
98
+ substitution = flexmock
99
+ substitution.should_receive(:odba_id).and_return(6)
100
+ @odba.odba_replace_stubs(6, substitution)
101
+ assert_equal(@odba.replaceable, substitution)
102
+ end
103
+ def test_odba_take_snapshot
104
+ level1 = ODBAContainer.new
105
+ level2 = ODBAContainer.new
106
+ @odba.replaceable = level1
107
+ level1.replaceable = level2
108
+
109
+ ODBA.cache.mock_handle(:store) { |obj| 2}
110
+ ODBA.cache.mock_handle(:store) { |obj| 2}
111
+
112
+ ODBA.cache.mock_handle(:store) { |obj| 2}
113
+
114
+ @odba.odba_take_snapshot
115
+ assert_equal(1, @odba.odba_snapshot_level)
116
+ assert_equal(1, level1.odba_snapshot_level)
117
+ assert_equal(1, level2.odba_snapshot_level)
118
+ ODBA.cache.mock_verify
119
+ end
120
+ def test_odba_unsaved_neighbors
121
+ replaceable = flexmock
122
+ @odba.replaceable = replaceable
123
+ =begin
124
+ replaceable.mock_handle(:is_a?) { |arg| false }
125
+ replaceable.mock_handle(:is_a?) { |arg| false }
126
+ =end
127
+ replaceable.mock_handle(:is_a?) { |arg|
128
+ assert_equal(Persistable, arg)
129
+ true
130
+ }
131
+ replaceable.mock_handle(:odba_unsaved?){ |level| true}
132
+ result = @odba.odba_unsaved_neighbors(2)
133
+ assert_equal([replaceable], result)
134
+ replaceable.mock_verify
135
+ end
136
+ def test_odba_unsaved_neighbors_2
137
+ odba = ODBAExcluding.new
138
+ included = flexmock
139
+ excluded = flexmock
140
+ odba.excluded = excluded
141
+ odba.included = included
142
+ =begin
143
+ included.mock_handle(:is_a?) { |klass|
144
+ assert_equal(Hash, klass)
145
+ false
146
+ }
147
+ included.mock_handle(:is_a?) { |klass|
148
+ assert_equal(Array, klass)
149
+ false
150
+ }
151
+ =end
152
+ included.mock_handle(:is_a?) { |klass|
153
+ assert_equal(ODBA::Persistable, klass)
154
+ true
155
+ }
156
+ included.mock_handle(:odba_unsaved?) { true }
157
+ result = odba.odba_unsaved_neighbors(2)
158
+ assert_equal([included], result)
159
+ excluded.mock_verify
160
+ included.mock_verify
161
+ end
162
+ def test_extend_enumerable
163
+ hash = Hash.new
164
+ array = Array.new
165
+ #@odba.odba_extend_enumerable(hash)
166
+ #@odba.odba_extend_enumerable(array)
167
+ assert_equal(true, hash.is_a?(Persistable))
168
+ assert_equal(true, array.is_a?(Persistable))
169
+ end
170
+ def test_odba_stubize
171
+ replaceable = ODBAContainer.new
172
+ non_rep = ODBAContainer.new
173
+ non_rep.odba_id = 32
174
+ replaceable.odba_id = 24
175
+ @odba.replaceable = replaceable
176
+ @odba.non_replaceable = non_rep
177
+ @odba.odba_stubize(replaceable)
178
+ assert_equal(24, @odba.replaceable.odba_id)
179
+ assert_equal(true, @odba.replaceable.is_a?(Stub))
180
+ assert_equal(true, @odba.non_replaceable.is_a?(ODBAContainer))
181
+ end
182
+ def test_odba_replace_persistables
183
+ replaceable = ODBAContainer.new
184
+ replaceable.odba_id = 12
185
+ non_replaceable = flexmock
186
+ @odba.non_replaceable = non_replaceable
187
+ @odba.replaceable = replaceable
188
+ non_replaceable.should_receive(:is_a?).with(Stub)\
189
+ .times(1).and_return(false)
190
+ non_replaceable.should_receive(:is_a?).with(Persistable)\
191
+ .times(1).and_return(false)
192
+ #ODBA.cache.mock_handle(:next_id){ 13 }
193
+ @odba.odba_replace_persistables
194
+ assert_instance_of(FlexMock, @odba.non_replaceable)
195
+ assert_equal(12, @odba.replaceable.odba_id)
196
+ assert_equal(true, @odba.replaceable.is_a?(Stub))
197
+ non_replaceable.mock_verify
198
+ ODBA.cache.mock_verify
199
+ end
200
+ def test_odba_replace_persistables__stubised_serialisable
201
+ non_replaceable = flexmock
202
+ @odba.serializable = non_replaceable
203
+ non_replaceable.mock_handle(:is_a?) { |arg|
204
+ assert_equal(Stub, arg)
205
+ true
206
+ }
207
+ non_replaceable.mock_handle(:odba_instance) {
208
+ 'serialize this'
209
+ }
210
+ @odba.odba_replace_persistables
211
+ assert_equal('serialize this', @odba.serializable)
212
+ non_replaceable.mock_verify
213
+ end
214
+ def test_odba_store_unsaved
215
+ level1 = ODBAContainer.new
216
+ level2 = ODBAContainer.new
217
+ saved = ODBAContainer.new
218
+ @odba.replaceable = level1
219
+ @odba.non_replaceable = saved
220
+ level1.replaceable = level2
221
+
222
+ saved.odba_persistent = true
223
+ ODBA.cache.should_receive(:store).times(3).and_return {
224
+ assert(true)
225
+ 2
226
+ }
227
+
228
+ @odba.odba_store_unsaved
229
+ end
230
+ def test_odba_store_unsaved_hash
231
+ level1 = ODBAContainer.new
232
+ hash_element = ODBAContainer.new
233
+ hash = Hash.new
234
+ non_rep_hash = Hash.new
235
+ level1.replaceable = hash
236
+ level1.non_replaceable = non_rep_hash
237
+ non_rep_hash.odba_persistent = true
238
+
239
+ ODBA.cache.should_receive(:store).times(2).and_return {
240
+ assert(true)
241
+ 2
242
+ }
243
+
244
+ level1.odba_store_unsaved
245
+ end
246
+ def test_dup
247
+ twin = @odba.dup
248
+ assert_nil(twin.instance_variable_get('@odba_id'))
249
+ end
250
+ def test_odba_dup
251
+ stub = flexmock("stub")
252
+ stub2 = flexmock("stub2")
253
+ @odba.replaceable = stub
254
+ @odba.replaceable2 = stub2
255
+ @odba.non_replaceable = 4
256
+ stub.mock_handle(:is_a?) { true }
257
+ stub.mock_handle(:odba_dup) { stub }
258
+ stub_container = nil
259
+ stub.mock_handle(:odba_container=) { |obj|
260
+ stub_container = obj
261
+ }
262
+ stub2.mock_handle(:is_a?) { true }
263
+ stub2.mock_handle(:odba_dup) { stub2 }
264
+ stub_container2 = nil
265
+ stub2.mock_handle(:odba_container=) { |obj|
266
+ stub_container2 = obj
267
+ }
268
+ odba_twin = @odba.odba_dup
269
+ odba_twin.replaceable.mock_verify
270
+ odba_twin.replaceable2.mock_verify
271
+ assert_equal(odba_twin, stub_container)
272
+ assert_equal(odba_twin, stub_container2)
273
+ end
274
+ def test_odba_unsaved_true
275
+ @odba.instance_variable_set("@odba_persistent", false)
276
+ assert_equal(true, @odba.odba_unsaved?)
277
+ end
278
+ def test_odba_target_ids
279
+ replaceable = flexmock("rep")
280
+ replaceable2 = flexmock("rep2")
281
+ @odba.replaceable = replaceable
282
+ @odba.replaceable2 = replaceable2
283
+ replaceable.mock_handle(:is_a?) { |arg|
284
+ true # is_a?(Persistable)
285
+ }
286
+ replaceable.mock_handle(:odba_id) { 12 }
287
+ replaceable2.mock_handle(:is_a?) { |arg| false }
288
+ expected = [12]
289
+ assert_equal(expected, @odba.odba_target_ids.sort)
290
+ replaceable.mock_verify
291
+ replaceable2.mock_verify
292
+ end
293
+ def test_odba_isolated_dump
294
+ replaceable = flexmock("Replaceable")
295
+ replaceable2 = flexmock("Replaceable2")
296
+ @odba.replaceable = replaceable
297
+ @odba.replaceable2 = replaceable2
298
+ ODBA.cache.mock_handle(:next_id){ 11 }
299
+
300
+ ### from odba_dup and odba_replace_persistables
301
+ replaceable2.should_receive(:is_a?).with(Stub)\
302
+ .times(2).and_return(false)
303
+ replaceable2.should_receive(:is_a?).with(Persistable)\
304
+ .times(1).and_return(true)
305
+ replaceable2.should_receive(:odba_id).times(1).and_return(12)
306
+
307
+ ### from odba_dup
308
+ responses = [false, true]
309
+ replaceable.should_receive(:is_a?).with(Stub)\
310
+ .times(2).and_return { responses.shift }
311
+ replaceable.should_receive(:odba_clear_receiver).times(1)
312
+ replaceable.should_receive(:odba_container=).with(@odba.class).times(1)
313
+ ODBA.marshaller.mock_handle(:dump) { |twin|
314
+ assert(twin.replaceable2.is_a?(ODBA::Stub))
315
+ "TheDump"
316
+ }
317
+ result = @odba.odba_isolated_dump
318
+ assert_equal(replaceable, @odba.replaceable)
319
+ assert_equal(replaceable2, @odba.replaceable2)
320
+ assert_equal("TheDump", result)
321
+ replaceable.mock_verify
322
+ replaceable2.mock_verify
323
+ end
324
+ def test_odba_isolated_dump_2
325
+ tmp = ODBA.marshaller
326
+ ODBA.marshaller = ODBA::Marshal
327
+ odba = ODBAExcluding.new
328
+ odba.excluded = "foo"
329
+ odba.included = "baz"
330
+ ODBA.cache.mock_handle(:next_id) { 1 }
331
+ dump, hash = odba.odba_isolated_dump
332
+ obj = ODBA.marshaller.load(dump)
333
+ assert_equal(nil, obj.excluded)
334
+ assert_equal("baz", obj.included)
335
+ ODBA.marshaller = tmp
336
+ end
337
+ def test_odba_id
338
+ @odba.odba_id = nil
339
+ ODBA.cache.mock_handle(:next_id) { 1 }
340
+ assert_equal(1, @odba.odba_id)
341
+ ODBA.storage.mock_verify
342
+ end
343
+ def test_odba_dump_has_id
344
+ @odba.odba_id = nil
345
+ ODBA.cache.mock_handle(:store) { |obj|
346
+ ODBA.cache.mock_handle(:next_id) { 1 }
347
+ assert_equal(1, obj.odba_id)
348
+ }
349
+ @odba.odba_store
350
+ end
351
+ def test_odba_store_error_raised
352
+ @odba.odba_name = "foo"
353
+ #ODBA.storage.mock_handle(:transaction) { |block| block.call}
354
+ ODBA.cache.mock_handle(:store) { |dump|
355
+ raise DBI::ProgrammingError
356
+ }
357
+ assert_raises(DBI::ProgrammingError) {
358
+ @odba.odba_store('baz')
359
+ }
360
+ assert_equal("foo", @odba.odba_name)
361
+ end
362
+ def test_odba_store_no_error_raised
363
+ @odba.odba_name = "foo"
364
+ #ODBA.storage.mock_handle(:transaction) { |block| block.call}
365
+ ODBA.cache.mock_handle(:store) { |obj|
366
+ assert_equal(@odba, obj)
367
+ }
368
+ @odba.odba_store('bar')
369
+ assert_equal("bar", @odba.odba_name)
370
+ end
371
+ def test_inspect_with_stub_in_array
372
+ ODBA.cache.mock_handle(:next_id) { 12 }
373
+ ODBA.cache.mock_handle(:next_id) { 13 }
374
+ content = ODBAContainer.new
375
+ @odba.instance_variable_set('@contents', [content])
376
+ twin = @odba.odba_isolated_twin
377
+ assert_not_nil(/@contents=#<ODBA::Stub:/.match(twin.inspect))
378
+ ODBA.storage.mock_verify
379
+ end
380
+ def test_to_yaml
381
+ yaml = ''
382
+ assert_nothing_raised {
383
+ yaml = @odba.to_yaml
384
+ }
385
+ loaded = YAML.load(yaml)
386
+ assert_instance_of(ODBAContainer, loaded)
387
+ end
388
+ def test_extend
389
+ ODBA.cache.mock_handle(:store) { |obj| assert_equal('foo', obj) }
390
+ str = 'foo'
391
+ str.extend(Persistable)
392
+ assert_nothing_raised {
393
+ str.odba_store
394
+ }
395
+ ODBA.cache.mock_verify
396
+ end
397
+ def test_odba_index__simple
398
+ stub = IndexedStub.new
399
+ assert_respond_to(stub, :name)
400
+ assert_respond_to(stub, :name=)
401
+ assert_respond_to(IndexedStub, :find_by_name)
402
+ result = flexmock('Result')
403
+
404
+ ## search by one key
405
+ name = 'odba_testpersistable_indexedstub_name'
406
+ args = 'xan'
407
+ ODBA.cache.should_receive(:retrieve_from_index).with(name, args)\
408
+ .times(1).and_return([result])
409
+ assert_equal([result], IndexedStub.search_by_name('xan'))
410
+
411
+ ## exact search by one key
412
+ ODBA.cache.should_receive(:retrieve_from_index)\
413
+ .with(name, args, ODBA::Persistable::Exact)\
414
+ .times(1).and_return([result])
415
+ assert_equal([result], IndexedStub.search_by_exact_name('xan'))
416
+
417
+ ## find by one key
418
+ ODBA.cache.should_receive(:retrieve_from_index)\
419
+ .with(name, args, ODBA::Persistable::Find)\
420
+ .times(1).and_return([result])
421
+ assert_equal(result, IndexedStub.find_by_name('xan'))
422
+
423
+ ## list available keys
424
+ ODBA.cache.should_receive(:index_keys).with(name, nil)\
425
+ .times(1).and_return(['key1', 'key2'])
426
+ assert_equal(['key1', 'key2'], IndexedStub.name_keys)
427
+ ODBA.cache.should_receive(:index_keys).with(name, 2)\
428
+ .times(1).and_return(['k1', 'k2'])
429
+ assert_equal(['k1', 'k2'], IndexedStub.name_keys(2))
430
+ end
431
+ def test_odba_index__multikey
432
+ stub = IndexedStub.new
433
+ assert_respond_to(stub, :foo)
434
+ assert_respond_to(stub, :bar)
435
+ assert_respond_to(IndexedStub, :find_by_foo_and_bar)
436
+ result = flexmock('Result')
437
+
438
+ ## search by multiple keys
439
+ name = 'odba_testpersistable_indexedstub_foo_and_bar'
440
+ args = {
441
+ :foo => { 'condition' => 'like', 'value' => 'oof'},
442
+ :bar => { 'condition' => 'like', 'value' => 'rab'},
443
+ }
444
+ ODBA.cache.should_receive(:retrieve_from_index).with(name, args)\
445
+ .times(1).and_return([result])
446
+ assert_equal([result],
447
+ IndexedStub.search_by_foo_and_bar('oof', 'rab'))
448
+
449
+ ## exact search by multiple keys
450
+ args = {:foo => 'oof', :bar => 'rab'}
451
+ ODBA.cache.should_receive(:retrieve_from_index)\
452
+ .with(name, args, Persistable::Exact)\
453
+ .times(1).and_return([result])
454
+ assert_equal([result],
455
+ IndexedStub.search_by_exact_foo_and_bar('oof', 'rab'))
456
+
457
+ ## find by multiple keys
458
+ args = {:foo => {'value' => 7,'condition' => '='},
459
+ :bar => {'value' => 'rab','condition' => 'like'}}
460
+ ODBA.cache.should_receive(:retrieve_from_index)\
461
+ .with(name, args, Persistable::Find)\
462
+ .times(1).and_return([result])
463
+ assert_equal(result, IndexedStub.find_by_foo_and_bar(7, 'rab'))
464
+ end
465
+ def test_odba_index__directional
466
+ stub = IndexedStub.new
467
+ assert_respond_to(stub, :origin)
468
+ assert_respond_to(stub, :origin=)
469
+ assert_respond_to(IndexedStub, :find_by_origin)
470
+ result = flexmock('Result')
471
+
472
+ ## search by one key
473
+ name = 'odba_testpersistable_indexedstub_origin'
474
+ args = 'xan'
475
+ ODBA.cache.should_receive(:retrieve_from_index).with(name, args)\
476
+ .times(1).and_return([result])
477
+ assert_equal([result], IndexedStub.search_by_origin('xan'))
478
+
479
+ ## exact search by one key
480
+ ODBA.cache.should_receive(:retrieve_from_index)\
481
+ .with(name, args, ODBA::Persistable::Exact)\
482
+ .times(1).and_return([result])
483
+ assert_equal([result], IndexedStub.search_by_exact_origin('xan'))
484
+
485
+ ## find by one key
486
+ ODBA.cache.should_receive(:retrieve_from_index)\
487
+ .with(name, args, ODBA::Persistable::Find)\
488
+ .times(1).and_return([result])
489
+ assert_equal(result, IndexedStub.find_by_origin('xan'))
490
+
491
+ ## list available keys
492
+ ODBA.cache.should_receive(:index_keys).with(name, nil)\
493
+ .times(1).and_return(['key1', 'key2'])
494
+ assert_equal(['key1', 'key2'], IndexedStub.origin_keys)
495
+ ODBA.cache.should_receive(:index_keys).with(name, 2)\
496
+ .times(1).and_return(['k1', 'k2'])
497
+ assert_equal(['k1', 'k2'], IndexedStub.origin_keys(2))
498
+ end
499
+ def test_odba_index__redirected
500
+ stub = IndexedStub.new
501
+ assert_respond_to(stub, :redirect)
502
+ assert_respond_to(stub, :redirect=)
503
+ assert_respond_to(IndexedStub, :find_by_redirect)
504
+ result = flexmock('Result')
505
+
506
+ ## search by one key
507
+ name = 'odba_testpersistable_indexedstub_redirect'
508
+ args = 'xan'
509
+ ODBA.cache.should_receive(:retrieve_from_index).with(name, args)\
510
+ .times(1).and_return([result])
511
+ assert_equal([result], IndexedStub.search_by_redirect('xan'))
512
+
513
+ ## exact search by one key
514
+ ODBA.cache.should_receive(:retrieve_from_index)\
515
+ .with(name, args, ODBA::Persistable::Exact)\
516
+ .times(1).and_return([result])
517
+ assert_equal([result], IndexedStub.search_by_exact_redirect('xan'))
518
+
519
+ ## find by one key
520
+ ODBA.cache.should_receive(:retrieve_from_index)\
521
+ .with(name, args, ODBA::Persistable::Find)\
522
+ .times(1).and_return([result])
523
+ assert_equal(result, IndexedStub.find_by_redirect('xan'))
524
+
525
+ ## list available keys
526
+ ODBA.cache.should_receive(:index_keys).with(name, nil)\
527
+ .times(1).and_return(['key1', 'key2'])
528
+ assert_equal(['key1', 'key2'], IndexedStub.redirect_keys)
529
+ ODBA.cache.should_receive(:index_keys).with(name, 2)\
530
+ .times(1).and_return(['k1', 'k2'])
531
+ assert_equal(['k1', 'k2'], IndexedStub.redirect_keys(2))
532
+ end
533
+ def test_odba_extent
534
+ stub = IndexedStub.new
535
+ assert_respond_to(IndexedStub, :odba_extent)
536
+ ODBA.cache.mock_handle(:extent) { |klass|
537
+ assert_equal(IndexedStub, klass)
538
+ []
539
+ }
540
+ assert_equal([], IndexedStub.odba_extent)
541
+ end
542
+ def test_odba_extent__with_block
543
+ stub = IndexedStub.new
544
+ assert_respond_to(IndexedStub, :odba_extent)
545
+ ODBA.cache.mock_handle(:extent) { |klass|
546
+ assert_equal(IndexedStub, klass)
547
+ ['foo']
548
+ }
549
+ IndexedStub.odba_extent { |obj|
550
+ assert_equal('foo', obj)
551
+ }
552
+ end
553
+ def test_odba_replace__in_object
554
+ ## in rollback, replace instance_variables of modified instances with
555
+ # newly loaded unmodified ones
556
+ modified = Object.new
557
+ modified.extend(ODBA::Persistable)
558
+ modified.instance_variable_set('@data', 'foo')
559
+
560
+ reloaded = modified.dup
561
+
562
+ modified.instance_variable_set('@data', 'bar')
563
+ assert_equal('bar', modified.instance_variable_get('@data'))
564
+
565
+ modified.odba_replace!(reloaded)
566
+ assert_equal('foo', modified.instance_variable_get('@data'))
567
+ end
568
+ def test_odba_add_observer
569
+ assert_nil(@odba.instance_variable_get('@odba_observers'))
570
+ obs = flexmock('Observer')
571
+ @odba.odba_add_observer(obs)
572
+ assert_equal([obs], @odba.instance_variable_get('@odba_observers'))
573
+ end
574
+ def test_odba_delete_observer
575
+ obs = flexmock('Observer')
576
+ @odba.instance_variable_set('@odba_observers', [obs])
577
+ @odba.odba_delete_observer(obs)
578
+ assert_equal([], @odba.instance_variable_get('@odba_observers'))
579
+ end
580
+ def test_odba_delete_observers
581
+ obs = flexmock('Observer')
582
+ @odba.instance_variable_set('@odba_observers', [obs])
583
+ @odba.odba_delete_observers
584
+ assert_nil(@odba.instance_variable_get('@odba_observers'))
585
+ end
586
+ def test_odba_notify_observers
587
+ obs = flexmock('Observer')
588
+ @odba.odba_id = 14
589
+ @odba.instance_variable_set('@odba_observers', [obs])
590
+ obs.should_receive(:odba_update).with(:key, 'foo', 'bar')\
591
+ .and_return { assert(true) }
592
+ @odba.odba_notify_observers(:key, 'foo', 'bar')
593
+ end
594
+ def test_odba_dup
595
+ o = Object.new
596
+ stub = ODBA::Stub.new(15, o, nil)
597
+ o.extend(ODBA::Persistable)
598
+ o.instance_variable_set('@stub', stub)
599
+ p = o.odba_dup
600
+ assert(p.is_a?(ODBA::Persistable))
601
+ stub2 = p.instance_variable_get('@stub')
602
+ assert(stub2.is_a?(ODBA::Stub))
603
+ assert_not_equal(stub.object_id, stub2.object_id)
604
+ assert_equal(15, stub2.odba_id)
605
+ end
606
+ def test_odba_isolated_stub
607
+ @odba.odba_id = 14
608
+ stub = @odba.odba_isolated_stub
609
+ assert(stub.is_a?(ODBA::Stub))
610
+ assert(stub.is_a?(ODBAContainer))
611
+ assert_equal(14, stub.odba_id)
612
+ assert_equal(ODBAContainer, stub.class)
613
+ ODBA.cache.mock_handle(:fetch) { |id, clr|
614
+ assert_equal(14, id)
615
+ assert_equal(nil, clr)
616
+ @odba
617
+ }
618
+ assert_equal(@odba, stub.odba_instance)
619
+ end
620
+ def test_odba_collection
621
+ o = ODBAContainer.new
622
+ assert_equal([], o.odba_collection)
623
+ end
624
+ end
625
+ end