xamplr 1.9.13 → 1.9.14

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.
@@ -2,7 +2,7 @@ module Xampl
2
2
 
3
3
  class SimplePersister < Persister
4
4
 
5
- def initialize(name=nil, format=nil)
5
+ def initialize(name=nil, format=nil, ignore=nil)
6
6
  super(name, format)
7
7
 
8
8
  @module_map = {}
@@ -56,6 +56,7 @@ module Xampl
56
56
  end
57
57
 
58
58
  def initialize(name=nil, format=nil, root=File.join(".", "repo"))
59
+ root = File.join(".", "repo") if root.nil?
59
60
  super(root, name, format)
60
61
 
61
62
  @files_dir = "#{ @root_dir }/files"
@@ -487,7 +488,7 @@ module Xampl
487
488
 
488
489
  def write(xampl)
489
490
 
490
- # puts "#{ File.basename __FILE__ }:#{ __LINE__ } [#{__method__}] write #{ xampl }"
491
+ # STDOUT.puts "#{ File.basename __FILE__ }:#{ __LINE__ } [#{__method__}] write #{ xampl }"
491
492
  raise XamplException.new(:no_index_so_no_persist) unless xampl.get_the_index
492
493
 
493
494
  expunging = self.expunged.include?(xampl)
@@ -610,7 +611,8 @@ module Xampl
610
611
  end
611
612
  end
612
613
  end
613
- if index_info[:primary] && 0 < index_info[:secondary].size then
614
+ #NOTE I've changed to to an || from && (so it'll write if only either primary or secondary is defined)
615
+ if index_info[:primary] || 0 < index_info[:secondary].size then
614
616
  file_place += ".idx"
615
617
  File.open(file_place, "w") do |out|
616
618
  out.write index_info.to_yaml
@@ -0,0 +1 @@
1
+ xampl-generated-code
@@ -0,0 +1,3 @@
1
+
2
+ s:
3
+ @spec *spec.rb
@@ -0,0 +1,19 @@
1
+
2
+ module RedisTest
3
+ attr :invalidated
4
+ class Author
5
+ def init_hook
6
+ # called when initialized by xampl
7
+ @invalidated = false
8
+ end
9
+
10
+ def note_invalidate
11
+ # called by xampl to note that this object is invalid
12
+ @invalidated = true
13
+ end
14
+
15
+ def invalidated?
16
+ @invalidated
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,31 @@
1
+ class ProjectGenerator
2
+
3
+ def print_options
4
+ # return an array containing any (or none) of:
5
+ # :schema -- a schema-like xml representation of the generated code
6
+ # :graphml -- a graphml file describing the class model (compatible with yEd)
7
+ # :yuml -- a yuml file that represents a simplified class model (compatible with yUML)
8
+
9
+ #[ :yuml ]
10
+ []
11
+ end
12
+
13
+ def directory
14
+ # return the path name to the generator's output directory
15
+ File.join(%w{ . xampl-generated-code })
16
+ end
17
+
18
+ def resolve_namespaces
19
+ # any array of arrays
20
+ # each sub-array:
21
+ # 0: a string or an array of strings, containing xml namespaces found
22
+ # in the example xml files an empty string is the default namespace
23
+ # 1: a ruby Module name (get the character cases right)
24
+ # 2: a namespace prefix used when writing xml, optional. A generated
25
+ # prefix will be used otherwise.
26
+
27
+ [
28
+ ['http://xampl.com/redis-test', 'RedisTest', 'rt'],
29
+ ]
30
+ end
31
+ end
@@ -0,0 +1,727 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ module Xampl
4
+
5
+ describe 'redis creation and connections' do
6
+ before :each do
7
+ Xampl.drop_all_persisters
8
+ Xampl.set_default_persister_properties(:testing => true,
9
+ :allow_connections => false,
10
+ :connect_to_known => false,
11
+ :connect_to_unknown => false)
12
+ end
13
+ after :each do
14
+ end
15
+
16
+ it 'will create a named instance of the redis persister' do
17
+ repo_name = XamplTestRedis.scratch_name('redis')
18
+ redis = Xampl.create_named_persister(repo_name, :redis)
19
+
20
+ redis.should be_an_instance_of(RedisPersister)
21
+ redis.repo_name.should == repo_name
22
+
23
+ redis.should == Xampl.find_named_persister(repo_name)
24
+ end
25
+
26
+ it 'will insist that it is named when created' do
27
+ lambda do
28
+ Xampl.create_named_persister(nil, :redis)
29
+ end.should raise_exception(NoAnonymousPersisters)
30
+ end
31
+
32
+ it 'will not cache anything but persisted xampl objects' do
33
+ redis = Xampl.create_named_persister(XamplTestRedis.scratch_name('redis'), :redis)
34
+
35
+ lambda do
36
+ redis.perm_cache("hello")
37
+ end.should raise_exception(NotXamplPersistedObject)
38
+ end
39
+
40
+ it 'will generate useful keys' do
41
+ redis = Xampl.create_named_persister(XamplTestRedis.scratch_name('redis'), :redis)
42
+
43
+ thing1 = XamplTestRedis::DroolingIdiotPersistedObject.new(XamplTestRedis.scratch_name('xo'))
44
+ thing2 = XamplTestRedis::DroolingIdiotPersistedObject.new(XamplTestRedis.scratch_name('xo'))
45
+
46
+ redis.key_for_class(thing1.class, thing1.get_the_index).should == redis.key_for_class(thing1.class, thing1.get_the_index)
47
+ redis.key_for_xampl(thing1).should == redis.key_for_xampl(thing1)
48
+ redis.key_for_class(thing1.class, thing1.get_the_index).should == redis.key_for_xampl(thing1)
49
+
50
+ redis.key_for_xampl(thing1).should_not == redis.key_for_xampl(thing2)
51
+ end
52
+
53
+ it 'will generate different keys for different repositories' do
54
+ redis1 = Xampl.create_named_persister(XamplTestRedis.scratch_name('redis'), :redis)
55
+ redis2 = Xampl.create_named_persister(XamplTestRedis.scratch_name('redis'), :redis)
56
+
57
+ thing = XamplTestRedis::DroolingIdiotPersistedObject.new('test')
58
+
59
+ redis1.key_for_class(thing.class, thing.get_the_index).should_not == redis2.key_for_class(thing.class, thing.get_the_index).should
60
+ redis1.key_for_xampl(thing).should_not == redis2.key_for_xampl(thing).should_not
61
+ end
62
+
63
+ it 'will cache a xampl object' do
64
+ redis = Xampl.create_named_persister(XamplTestRedis.scratch_name('redis'), :redis)
65
+
66
+ thing = XamplTestRedis::DroolingIdiotPersistedObject.new('test')
67
+
68
+ redis.perm_cache(thing)
69
+ found, target = redis.read_from_cache(thing.class, thing.get_the_index)
70
+
71
+ found.should == thing
72
+ found.should be_an_instance_of(XamplTestRedis::DroolingIdiotPersistedObject)
73
+ target.should be_nil
74
+ end
75
+
76
+ it 'will moan if two different objects are cached under the same key' do
77
+ redis = Xampl.create_named_persister(XamplTestRedis.scratch_name('redis'), :redis)
78
+
79
+ thing1 = XamplTestRedis::DroolingIdiotPersistedObject.new('test')
80
+ thing2 = XamplTestRedis::DroolingIdiotPersistedObject.new('test')
81
+
82
+ redis.perm_cache(thing1)
83
+ lambda do
84
+ redis.perm_cache(thing2)
85
+ end.should raise_exception(DuplicateXamplInPersister)
86
+
87
+ found, target = redis.read_from_cache(thing1.class, thing1.get_the_index)
88
+ found.should == thing1
89
+ target.should be_nil
90
+ end
91
+
92
+ it 'will store if two different objects are cached under the same key if the first is removed from the cache first' do
93
+ redis = Xampl.create_named_persister(XamplTestRedis.scratch_name('redis'), :redis)
94
+
95
+ thing1 = XamplTestRedis::DroolingIdiotPersistedObject.new('test')
96
+ thing2 = XamplTestRedis::DroolingIdiotPersistedObject.new('test')
97
+
98
+ redis.perm_cache(thing1)
99
+ uncached = redis.perm_uncache(thing1)
100
+ uncached.should == thing1
101
+
102
+ redis.perm_cache(thing2)
103
+
104
+ found, target = redis.read_from_cache(thing2.class, thing2.get_the_index)
105
+ found.should == thing2
106
+ target.should be_nil
107
+ end
108
+
109
+ it "will clear its caches" do
110
+ redis = Xampl.create_named_persister(XamplTestRedis.scratch_name('redis'), :redis)
111
+
112
+ thing = XamplTestRedis::DroolingIdiotPersistedObject.new('test')
113
+
114
+ redis.perm_cache(thing)
115
+ redis.clear_cache
116
+ found, target = redis.read_from_cache(thing.class, thing.get_the_index)
117
+
118
+ found.should be_nil
119
+ target.should be_nil
120
+ end
121
+
122
+ it 'will have weak cache references' do
123
+ redis = Xampl.create_named_persister(XamplTestRedis.scratch_name('redis'), :redis)
124
+
125
+ thing_referenced = XamplTestRedis::DroolingIdiotPersistedObject.new('referenced')
126
+
127
+ redis.perm_cache(thing_referenced)
128
+ redis.perm_cache(XamplTestRedis::DroolingIdiotPersistedObject.new('unreferenced'))
129
+
130
+ GC.start
131
+
132
+ redis.read_from_cache(XamplTestRedis::DroolingIdiotPersistedObject, 'referenced').first.should == thing_referenced
133
+ redis.read_from_cache(XamplTestRedis::DroolingIdiotPersistedObject, 'unreferenced').first.should be_nil
134
+ end
135
+
136
+ it 'two different objects are cached under the same key if the first is GCed' do
137
+ redis = Xampl.create_named_persister(XamplTestRedis.scratch_name('redis'), :redis)
138
+
139
+ redis.perm_cache(XamplTestRedis::DroolingIdiotPersistedObject.new('test'))
140
+ GC.start
141
+ redis.perm_cache(XamplTestRedis::DroolingIdiotPersistedObject.new('test'))
142
+ end
143
+
144
+ it 'will establish a redis connection to an unknown redis database' do
145
+ redis = Xampl.create_named_persister(XamplTestRedis.scratch_name('redis'), :redis,
146
+ :allow_connections => true,
147
+ :connect_to_known => false,
148
+ :connect_to_unknown => true)
149
+
150
+ client = redis.client
151
+ client.should be_an_instance_of(::Redis)
152
+
153
+ repo_properties = redis.repo_properties
154
+ repo_properties['name'].should == redis.name
155
+ repo_properties['mentions'].should be_true
156
+ repo_properties['created_at'].should_not be_nil
157
+ end
158
+
159
+ it 'will establish a redis connection to an known redis database' do
160
+ repo_name = XamplTestRedis.scratch_name('redis')
161
+ redis1 = Xampl.create_named_persister(repo_name, :redis,
162
+ :allow_connections => true,
163
+ :connect_to_known => false,
164
+ :connect_to_unknown => true)
165
+
166
+ client = redis1.client
167
+ client.should be_an_instance_of(::Redis)
168
+
169
+ repo_properties = redis1.repo_properties
170
+ repo_properties['name'].should == redis1.name
171
+ repo_properties['mentions'].should be_true
172
+ repo_properties['created_at'].should_not be_nil
173
+
174
+ Xampl.drop_persister(repo_name)
175
+
176
+ redis2 = Xampl.create_named_persister(repo_name, :redis,
177
+ :allow_connections => true,
178
+ :connect_to_known => true,
179
+ :connect_to_unknown => false)
180
+
181
+ client = redis2.client
182
+ client.should be_an_instance_of(::Redis)
183
+ end
184
+
185
+ it 'will prevent connections to new repositories' do
186
+ repo_name = XamplTestRedis.scratch_name('redis')
187
+ lambda do
188
+ Xampl.create_named_persister(repo_name, :redis,
189
+ :allow_connections => true,
190
+ :connect_to_known => true,
191
+ :connect_to_unknown => false)
192
+ end.should raise_exception(IncompatiblePersisterConfiguration)
193
+ end
194
+
195
+ it 'will prevent connections to existing repositories' do
196
+ repo_name = XamplTestRedis.scratch_name('redis')
197
+ redis1 = Xampl.create_named_persister(repo_name, :redis,
198
+ :allow_connections => true,
199
+ :connect_to_known => false,
200
+ :connect_to_unknown => true)
201
+
202
+ client = redis1.client
203
+ client.should be_an_instance_of(::Redis)
204
+
205
+ Xampl.drop_persister(repo_name)
206
+
207
+ lambda do
208
+ Xampl.create_named_persister(repo_name, :redis,
209
+ :allow_connections => true,
210
+ :connect_to_known => false,
211
+ :connect_to_unknown => true)
212
+ end.should raise_exception(IncompatiblePersisterConfiguration)
213
+ end
214
+
215
+ it "will connect to two different repositories in the same redis db" do
216
+ redis1 = Xampl.create_named_persister(XamplTestRedis.scratch_name('redis'), :redis,
217
+ :allow_connections => true,
218
+ :connect_to_known => false,
219
+ :connect_to_unknown => true)
220
+ redis1.should_not be_nil
221
+ redis2 = Xampl.create_named_persister(XamplTestRedis.scratch_name('redis'), :redis,
222
+ :allow_connections => true,
223
+ :connect_to_known => false,
224
+ :connect_to_unknown => true)
225
+ redis2.should_not be_nil
226
+ redis2.should_not == redis1
227
+
228
+ known_repos = redis1.known_repos
229
+ known_repos.should include(redis1.repo_name, redis2.repo_name)
230
+ end
231
+
232
+ it "will only create one persister wiith a given name" do
233
+ repo_name = XamplTestRedis.scratch_name('redis')
234
+ redis1 = Xampl.create_named_persister(repo_name, :redis,
235
+ :allow_connections => true,
236
+ :connect_to_known => true,
237
+ :connect_to_unknown => true)
238
+ redis2 = Xampl.create_named_persister(repo_name, :redis,
239
+ :allow_connections => true,
240
+ :connect_to_known => true,
241
+ :connect_to_unknown => true)
242
+
243
+ redis1.should == redis2
244
+ end
245
+
246
+ it 'will allow clobbering an entire redis database when clobbering is explicitly enabled' do
247
+ repo_name1 = XamplTestRedis.scratch_name('redis')
248
+ redis1 = Xampl.create_named_persister(repo_name1, :redis,
249
+ :clobbering_allowed => true,
250
+ :allow_connections => true,
251
+ :connect_to_known => true,
252
+ :connect_to_unknown => true)
253
+ repo_name2 = XamplTestRedis.scratch_name('redis')
254
+ redis2 = Xampl.create_named_persister(repo_name2, :redis,
255
+ :allow_connections => true,
256
+ :connect_to_known => true,
257
+ :connect_to_unknown => true)
258
+
259
+ known_repos = redis2.known_repos
260
+ known_repos.should include(repo_name1, repo_name2)
261
+
262
+ redis1_repo_properties_key = redis1.repo_properties_key
263
+ redis1_repo_properties_key.should_not be_nil
264
+ redis2.client.exists(redis1_repo_properties_key).should be_true
265
+
266
+ # add some non-standard keys for this
267
+ prefix = redis1.common_key_prefix
268
+ extra1 = "#{ prefix }one"
269
+ redis1.client.set(extra1, "one")
270
+ extra2 = "#{ prefix }two"
271
+ redis1.client.set(extra2, "two")
272
+ extra3 = "#{ prefix }three"
273
+ redis1.client.set(extra3, "three")
274
+
275
+ redis2.client.get(extra1).should == "one"
276
+ redis2.client.get(extra2).should == "two"
277
+ redis2.client.get(extra3).should == "three"
278
+
279
+ redis1.clobber
280
+
281
+ known_repos = redis2.known_repos
282
+ known_repos.should_not include(repo_name1)
283
+ known_repos.should include(repo_name2)
284
+
285
+ redis2.client.exists(redis1_repo_properties_key).should be_false
286
+
287
+ redis2.client.get(extra1).should be_nil
288
+ redis2.client.get(extra2).should be_nil
289
+ redis2.client.get(extra3).should be_nil
290
+ end
291
+
292
+ it 'will *not* allow clobbering an entire redis database when clobbering is *not* explicitly enabled' do
293
+ repo_name1 = XamplTestRedis.scratch_name('redis')
294
+ redis1 = Xampl.create_named_persister(repo_name1, :redis,
295
+ :allow_connections => true,
296
+ :connect_to_known => true,
297
+ :connect_to_unknown => true)
298
+
299
+ lambda do
300
+ redis1.clobber
301
+ end.should raise_exception(IncompatiblePersisterConfiguration)
302
+ end
303
+
304
+
305
+ it 'will re-establish a redis connection' do
306
+ redis = Xampl.create_named_persister(XamplTestRedis.scratch_name('redis'), :redis,
307
+ :allow_connections => true,
308
+ :connect_to_known => true,
309
+ :connect_to_unknown => true)
310
+
311
+ redis_client = redis.client
312
+ redis_client.client.should be_connected
313
+
314
+ redis.close
315
+
316
+ redis_client.client.should_not be_connected
317
+
318
+ redis_client.ping.should == "PONG" # this will reconnect
319
+ redis_client.client.should be_connected
320
+ end
321
+
322
+ #TODO -- LOCKS!!!! on the db, BUT WAIT FOR THE NEW EXPIRE FUNCTIONALITY
323
+
324
+ end
325
+
326
+ describe 'redis reading and writing xampl objects' do
327
+ before :each do
328
+ Xampl.drop_all_persisters
329
+ Xampl.set_default_persister_properties(:testing => true,
330
+ :allow_connections => true,
331
+ :connect_to_known => true,
332
+ :connect_to_unknown => true)
333
+ end
334
+ after :each do
335
+ end
336
+
337
+
338
+ it "will write an xampl object" do
339
+ repo_name = XamplTestRedis.scratch_name('redis')
340
+ redis = Xampl.create_named_persister(repo_name, :redis)
341
+
342
+ redis_client = redis.client
343
+ redis_client.client.should be_connected
344
+
345
+ author_pid = 'anonymous'
346
+ key = redis.key_for_class(RedisTest::Author, author_pid)
347
+
348
+ redis.in_any_cache?(RedisTest::Author, author_pid).should be_false
349
+
350
+ current_value = redis_client.get(key)
351
+ current_value.should be_nil
352
+
353
+ redis.in_any_cache?(RedisTest::Author, author_pid).should be_false
354
+
355
+ author = nil
356
+ Xampl.transaction(repo_name) do
357
+ author = RedisTest::Author.new(author_pid)
358
+
359
+ redis.in_any_cache?(RedisTest::Author, author_pid).should be_true
360
+ redis.in_new_cache?(RedisTest::Author, author_pid).should be_true
361
+ redis.in_cache?(RedisTest::Author, author_pid).should be_false
362
+ end
363
+
364
+ mentions = []
365
+ xml = redis.represent(author, mentions)
366
+
367
+ current_value = redis_client.get(key)
368
+ current_value.should == xml
369
+
370
+ redis.in_any_cache?(RedisTest::Author, author_pid).should be_true
371
+ redis.in_new_cache?(RedisTest::Author, author_pid).should be_false
372
+ redis.in_cache?(RedisTest::Author, author_pid).should be_true
373
+
374
+ GC.start
375
+
376
+ redis.in_cache?(RedisTest::Author, author_pid).should be_true
377
+
378
+ author = nil
379
+
380
+ GC.start
381
+
382
+ redis.in_cache?(RedisTest::Author, author_pid).should be_false
383
+
384
+ # NOTE -- I don't know if this test passing is a good or bad thing. Seems to be contrary to how docs seem to explain weak_refs,
385
+ # on the other hand, it's what we need here. ??
386
+ end
387
+
388
+ it "will write a changed xampl object" do
389
+ repo_name = XamplTestRedis.scratch_name('redis')
390
+ redis = Xampl.create_named_persister(repo_name, :redis)
391
+ redis_client = redis.client
392
+
393
+ author_pid = 'anonymous'
394
+ key = redis.key_for_class(RedisTest::Author, author_pid)
395
+
396
+ author = nil
397
+ Xampl.transaction(repo_name) do
398
+ author = RedisTest::Author.new(author_pid)
399
+ end
400
+
401
+ mentions = []
402
+ xml1 = redis.represent(author, mentions)
403
+
404
+ current_value = redis_client.get(key)
405
+ current_value.should == xml1
406
+
407
+ Xampl.transaction(repo_name) do
408
+ author.info = 'changed'
409
+ author.should be_dirty
410
+ end
411
+ author.should_not be_dirty
412
+
413
+ mentions = []
414
+ xml2 = redis.represent(author, mentions)
415
+
416
+ xml2.should_not == xml1
417
+
418
+ current_value = redis_client.get(key)
419
+ current_value.should == xml2
420
+ end
421
+
422
+ it "will read a xampl object with different redis instances" do
423
+ repo_name = XamplTestRedis.scratch_name('redis')
424
+ Xampl.create_named_persister(repo_name, :redis)
425
+
426
+ author_pid = 'anonymous'
427
+
428
+ author_info = XamplTestRedis.scratch_name('author-info')
429
+ author_object_id_original = nil
430
+ Xampl.transaction(repo_name) do
431
+ author = RedisTest::Author.new(author_pid)
432
+ author.info = author_info
433
+ author_object_id_original = author.object_id
434
+ end
435
+
436
+ Xampl.drop_all_persisters
437
+ GC.start # shouldn't make any difference, but do it anyway
438
+ GC.start # shouldn't make any difference, but do it anyway
439
+ GC.start # shouldn't make any difference, but do it anyway
440
+
441
+ Xampl.create_named_persister(repo_name, :redis)
442
+
443
+ author = nil
444
+ Xampl.transaction(repo_name) do
445
+ author = RedisTest::Author[author_pid]
446
+ end
447
+
448
+ author.should_not be_nil
449
+ author.info.should == author_info
450
+ author.object_id.should_not == author_object_id_original
451
+ end
452
+
453
+ it "will read a xampl object from cache of same redis instance" do
454
+ repo_name = XamplTestRedis.scratch_name('redis')
455
+ Xampl.create_named_persister(repo_name, :redis)
456
+
457
+ author_pid = 'anonymous'
458
+
459
+ author_info = XamplTestRedis.scratch_name('author-info')
460
+ author_object_id_original = nil
461
+ Xampl.transaction(repo_name) do
462
+ author = RedisTest::Author.new(author_pid)
463
+ author.info = author_info
464
+ author_object_id_original = author.object_id
465
+ end
466
+
467
+ Xampl.create_named_persister(repo_name, :redis)
468
+
469
+ author = nil
470
+ Xampl.transaction(repo_name) do
471
+ author = RedisTest::Author[author_pid]
472
+ end
473
+
474
+ author.should_not be_nil
475
+ author.info.should == author_info
476
+ author.object_id.should == author_object_id_original
477
+ end
478
+
479
+ it "will read a xampl object flushed from the cache cache of same redis instance" do
480
+ repo_name = XamplTestRedis.scratch_name('redis')
481
+ Xampl.create_named_persister(repo_name, :redis)
482
+
483
+ author_pid = 'anonymous'
484
+
485
+ author_info = XamplTestRedis.scratch_name('author-info')
486
+ author_object_id_original = nil
487
+ Xampl.transaction(repo_name) do
488
+ author = RedisTest::Author.new(author_pid)
489
+ author.info = author_info
490
+ author_object_id_original = author.object_id
491
+ end
492
+
493
+ #try this 10 times because the GC can't be counted on to have actually run
494
+ 10.times do
495
+ author = nil
496
+
497
+ # this should empty the weak-ref cache, but maybe not
498
+ GC.start
499
+ sleep(0.2)
500
+
501
+ Xampl.create_named_persister(repo_name, :redis)
502
+
503
+ Xampl.transaction(repo_name) do
504
+ author = RedisTest::Author[author_pid]
505
+ end
506
+
507
+ next if author.object_id == author_object_id_original
508
+
509
+ author.should_not be_nil
510
+ author.info.should == author_info
511
+ author.object_id.should_not == author_object_id_original
512
+ break
513
+ end
514
+ end
515
+
516
+ it "will rollback a newly created xampl object" do
517
+ repo_name = XamplTestRedis.scratch_name('redis')
518
+ redis = Xampl.create_named_persister(repo_name, :redis)
519
+ redis_client = redis.client
520
+
521
+ author_pid = 'anonymous'
522
+ key = redis.key_for_class(RedisTest::Author, author_pid)
523
+
524
+ author = nil
525
+ lambda do
526
+ Xampl.transaction(repo_name) do
527
+ author = RedisTest::Author.new(author_pid)
528
+ raise 'BOOM!'
529
+ end
530
+ end.should raise_exception
531
+
532
+ author.should_not be_nil
533
+ author.should be_invalid # set by the invalidated hook (see author.rb in this directory)
534
+ author.should be_invalidated # a built-in xampl method based on kind_of?(InvalidXampl)
535
+
536
+ author.pid.should == author_pid
537
+
538
+ lambda do
539
+ author.accessed
540
+ end.should raise_exception(Xampl::XamplIsInvalid)
541
+ end
542
+
543
+ it "will NOT rollback a newly created xampl object when throwing" do
544
+ repo_name = XamplTestRedis.scratch_name('redis')
545
+ redis = Xampl.create_named_persister(repo_name, :redis)
546
+ redis_client = redis.client
547
+
548
+ author_pid = 'anonymous'
549
+ key = redis.key_for_class(RedisTest::Author, author_pid)
550
+
551
+ author = nil
552
+
553
+ lambda do
554
+ Xampl.transaction(repo_name) do
555
+ author = RedisTest::Author.new(author_pid)
556
+ throw :idiot_move
557
+ end
558
+ end.should throw_symbol(:idiot_move)
559
+
560
+ author.should_not be_nil
561
+ author.should_not be_invalid # set by the invalidated hook (see author.rb in this directory)
562
+ author.should_not be_invalidated # a built-in xampl method based on kind_of?(InvalidXampl)
563
+
564
+ author.pid.should == author_pid
565
+
566
+ lambda do
567
+ author.accessed
568
+ end.should_not raise_exception(Xampl::XamplIsInvalid)
569
+ end
570
+
571
+ it "will rollback a changed xampl object" do
572
+ repo_name = XamplTestRedis.scratch_name('redis')
573
+ redis = Xampl.create_named_persister(repo_name, :redis)
574
+ redis_client = redis.client
575
+
576
+ author_pid = 'anonymous'
577
+ key = redis.key_for_class(RedisTest::Author, author_pid)
578
+
579
+ author = nil
580
+ Xampl.transaction(repo_name) do
581
+ author = RedisTest::Author.new(author_pid)
582
+ end
583
+ author.info.should be_nil
584
+
585
+ mentions = []
586
+ xml1 = redis.represent(author, mentions)
587
+
588
+ current_value = redis_client.get(key)
589
+ current_value.should == xml1
590
+
591
+ lambda do
592
+ Xampl.transaction(repo_name) do
593
+ author.info = 'changed'
594
+ author.should be_dirty
595
+ raise 'BOOM!'
596
+ end
597
+ end.should raise_exception
598
+
599
+ author.should_not be_dirty
600
+
601
+ author.info.should be_nil
602
+
603
+ author.should_not be_invalid # set by the invalidated hook (see author.rb in this directory)
604
+ author.should_not be_invalidated # a built-in xampl method based on kind_of?(InvalidXampl)
605
+
606
+ mentions = []
607
+ xml2 = redis.represent(author, mentions)
608
+
609
+ xml2.should == xml1
610
+
611
+ current_value = redis_client.get(key)
612
+ current_value.should == xml2
613
+ end
614
+
615
+ it "will NOT rollback a changed xampl object after throwing" do
616
+ repo_name = XamplTestRedis.scratch_name('redis')
617
+ redis = Xampl.create_named_persister(repo_name, :redis)
618
+ redis_client = redis.client
619
+
620
+ author_pid = 'anonymous'
621
+ key = redis.key_for_class(RedisTest::Author, author_pid)
622
+
623
+ author = nil
624
+ Xampl.transaction(repo_name) do
625
+ author = RedisTest::Author.new(author_pid)
626
+ end
627
+ author.info.should be_nil
628
+
629
+ mentions = []
630
+ xml1 = redis.represent(author, mentions)
631
+
632
+ current_value = redis_client.get(key)
633
+ current_value.should == xml1
634
+
635
+ lambda do
636
+ Xampl.transaction(repo_name) do
637
+ author.info = 'changed'
638
+ author.should be_dirty
639
+ throw :idiot_move
640
+ end
641
+ end.should throw_symbol(:idiot_move)
642
+
643
+ author.should_not be_dirty
644
+
645
+ author.info.should == 'changed'
646
+
647
+ author.should_not be_invalid # set by the invalidated hook (see author.rb in this directory)
648
+ author.should_not be_invalidated # a built-in xampl method based on kind_of?(InvalidXampl)
649
+
650
+ mentions = []
651
+ xml2 = redis.represent(author, mentions)
652
+
653
+ xml2.should_not == xml1
654
+
655
+ current_value = redis_client.get(key)
656
+ current_value.should == xml2
657
+ end
658
+
659
+ it "will create an object in a nested transaction" do
660
+ author_pid = 'anonymous'
661
+
662
+ outer_repo_name = XamplTestRedis.scratch_name('redis')
663
+ outer_redis = Xampl.create_named_persister(outer_repo_name, :redis)
664
+
665
+ inner_repo_name = XamplTestRedis.scratch_name('redis')
666
+ inner_redis = Xampl.create_named_persister(inner_repo_name, :redis)
667
+
668
+ outer_redis_client = outer_redis.client
669
+ inner_redis_client = inner_redis.client
670
+
671
+ outer_redis_client.client.should be_connected
672
+ inner_redis_client.client.should be_connected
673
+
674
+ outer_key = outer_redis.key_for_class(RedisTest::Author, author_pid)
675
+ inner_key = inner_redis.key_for_class(RedisTest::Author, author_pid)
676
+
677
+ outer_value = outer_redis_client.get(outer_key)
678
+ outer_value.should be_nil
679
+
680
+ inner_value = inner_redis_client.get(inner_key)
681
+ inner_value.should be_nil
682
+
683
+ author = nil
684
+
685
+ Xampl.transaction(outer_repo_name) do
686
+ Xampl.transaction(inner_repo_name) do
687
+ author = RedisTest::Author.new(author_pid)
688
+ end
689
+ end
690
+
691
+ #TODO -- raise exception in inner
692
+ #TODO -- raise exception in outer
693
+ #TODO -- throw in inner
694
+ #TODO -- throw in outer
695
+
696
+ outer_value = outer_redis_client.get(outer_key)
697
+ outer_value.should be_nil
698
+
699
+ inner_value = inner_redis_client.get(inner_key)
700
+ inner_value.should == author.to_xml
701
+
702
+ author.should_not be_nil
703
+ author.should_not be_invalid # set by the invalidated hook (see author.rb in this directory)
704
+ author.should_not be_invalidated # a built-in xampl method based on kind_of?(InvalidXampl)
705
+ author.pid.should == author_pid
706
+ lambda do
707
+ author.accessed
708
+ end.should_not raise_exception(Xampl::XamplIsInvalid)
709
+ end
710
+
711
+ # explicit return cannot be tested because rspec is doing something
712
+
713
+ # it "will zzz" do
714
+ # pending
715
+ # end
716
+
717
+ # it "will zzz" do
718
+ # pending
719
+ # end
720
+
721
+ # it "will zzz" do
722
+ # pending
723
+ # end
724
+
725
+ end
726
+
727
+ end