xamplr 1.9.13 → 1.9.14

Sign up to get free protection for your applications and to get access to all the features.
@@ -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