strokedb 0.0.2.1 → 0.0.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (192) hide show
  1. data/README +18 -20
  2. data/bench.html +4001 -0
  3. data/bin/strokedb +14 -0
  4. data/examples/movies.rb +105 -0
  5. data/examples/movies2.rb +97 -0
  6. data/examples/strokewiki/README +28 -0
  7. data/examples/strokewiki/view/edit.xhtml +27 -0
  8. data/examples/strokewiki/view/new.xhtml +26 -0
  9. data/examples/strokewiki/view/pages.xhtml +27 -0
  10. data/examples/strokewiki/view/show.xhtml +40 -0
  11. data/examples/strokewiki/view/versions.xhtml +25 -0
  12. data/examples/strokewiki/wiki.rb +106 -0
  13. data/examples/todo.rb +92 -0
  14. data/lib/strokedb.rb +85 -0
  15. data/lib/{config → strokedb}/config.rb +14 -9
  16. data/lib/strokedb/console.rb +87 -0
  17. data/lib/strokedb/core_ext.rb +10 -0
  18. data/lib/{util/ext → strokedb/core_ext}/blank.rb +1 -1
  19. data/lib/{util/ext → strokedb/core_ext}/enumerable.rb +0 -0
  20. data/lib/{util/ext → strokedb/core_ext}/fixnum.rb +0 -0
  21. data/lib/strokedb/core_ext/float.rb +4 -0
  22. data/lib/{util/ext → strokedb/core_ext}/hash.rb +0 -0
  23. data/lib/strokedb/core_ext/infinity.rb +33 -0
  24. data/lib/strokedb/core_ext/kernel.rb +41 -0
  25. data/lib/strokedb/core_ext/object.rb +16 -0
  26. data/lib/{util/ext → strokedb/core_ext}/string.rb +28 -1
  27. data/lib/strokedb/core_ext/symbol.rb +13 -0
  28. data/lib/strokedb/data_structures.rb +5 -0
  29. data/lib/strokedb/data_structures/chunked_skiplist.rb +123 -0
  30. data/lib/{data_structures → strokedb/data_structures}/inverted_list.rb +0 -0
  31. data/lib/{data_structures → strokedb/data_structures}/point_query.rb +0 -0
  32. data/lib/strokedb/data_structures/simple_skiplist.rb +350 -0
  33. data/lib/{data_structures → strokedb/data_structures}/skiplist.rb +1 -1
  34. data/lib/{document → strokedb}/document.rb +180 -71
  35. data/lib/{document → strokedb/document}/callback.rb +0 -0
  36. data/lib/{document → strokedb/document}/delete.rb +2 -2
  37. data/lib/strokedb/document/dsl.rb +4 -0
  38. data/lib/{document → strokedb/document/dsl}/associations.rb +0 -0
  39. data/lib/{document → strokedb/document/dsl}/coercions.rb +0 -0
  40. data/lib/strokedb/document/dsl/meta_dsl.rb +7 -0
  41. data/lib/{document → strokedb/document/dsl}/validations.rb +26 -21
  42. data/lib/{document → strokedb/document/dsl}/virtualize.rb +0 -0
  43. data/lib/{document → strokedb/document}/meta.rb +92 -29
  44. data/lib/{document → strokedb/document}/slot.rb +17 -5
  45. data/lib/{document → strokedb/document}/util.rb +0 -0
  46. data/lib/{document → strokedb/document}/versions.rb +2 -2
  47. data/lib/strokedb/index.rb +2 -0
  48. data/lib/strokedb/nsurl.rb +24 -0
  49. data/lib/strokedb/store.rb +149 -0
  50. data/lib/strokedb/stores.rb +6 -0
  51. data/lib/{stores → strokedb/stores}/chainable_storage.rb +20 -14
  52. data/lib/strokedb/stores/file_storage.rb +118 -0
  53. data/lib/{stores/inverted_list_index → strokedb/stores}/inverted_list_file_storage.rb +50 -0
  54. data/lib/strokedb/stores/memory_storage.rb +80 -0
  55. data/lib/{stores → strokedb/stores}/remote_store.rb +10 -4
  56. data/lib/strokedb/sync.rb +4 -0
  57. data/lib/{sync → strokedb/sync}/chain_sync.rb +0 -0
  58. data/lib/{sync → strokedb/sync}/diff.rb +12 -1
  59. data/lib/{sync/stroke_diff → strokedb/sync/diff}/array.rb +1 -1
  60. data/lib/{sync/stroke_diff → strokedb/sync/diff}/default.rb +0 -0
  61. data/lib/{sync/stroke_diff → strokedb/sync/diff}/hash.rb +1 -1
  62. data/lib/{sync/stroke_diff → strokedb/sync/diff}/string.rb +1 -1
  63. data/lib/{sync → strokedb/sync}/lamport_timestamp.rb +0 -0
  64. data/lib/{sync → strokedb/sync}/store_sync.rb +15 -7
  65. data/lib/strokedb/transaction.rb +78 -0
  66. data/lib/{util → strokedb}/util.rb +14 -7
  67. data/lib/strokedb/util/attach_dsl.rb +29 -0
  68. data/lib/{util → strokedb/util}/blankslate.rb +0 -0
  69. data/lib/strokedb/util/class_optimization.rb +93 -0
  70. data/lib/{util → strokedb/util}/inflect.rb +0 -0
  71. data/lib/strokedb/util/java_util.rb +13 -0
  72. data/lib/{util → strokedb/util}/lazy_array.rb +0 -0
  73. data/lib/{util → strokedb/util}/lazy_mapping_array.rb +4 -0
  74. data/lib/{util → strokedb/util}/lazy_mapping_hash.rb +0 -0
  75. data/lib/{util → strokedb/util}/serialization.rb +21 -0
  76. data/lib/strokedb/util/uuid.rb +159 -0
  77. data/lib/{util → strokedb/util}/xml.rb +0 -0
  78. data/lib/{view → strokedb}/view.rb +2 -2
  79. data/lib/strokedb/volumes.rb +5 -0
  80. data/lib/strokedb/volumes/archive_volume.rb +165 -0
  81. data/lib/strokedb/volumes/block_volume.rb +169 -0
  82. data/lib/strokedb/volumes/distributed_pointer.rb +43 -0
  83. data/lib/strokedb/volumes/fixed_length_skiplist_volume.rb +109 -0
  84. data/lib/strokedb/volumes/map_volume.rb +268 -0
  85. data/meta/MANIFEST +175 -0
  86. data/script/console +2 -70
  87. data/spec/integration/remote_store_spec.rb +70 -0
  88. data/spec/integration/search_spec.rb +76 -0
  89. data/spec/integration/spec_helper.rb +1 -0
  90. data/spec/lib/spec_helper.rb +1 -0
  91. data/spec/lib/strokedb/config_spec.rb +250 -0
  92. data/spec/lib/strokedb/core_ext/blank_spec.rb +20 -0
  93. data/spec/lib/strokedb/core_ext/extract_spec.rb +42 -0
  94. data/spec/lib/strokedb/core_ext/float_spec.rb +62 -0
  95. data/spec/lib/strokedb/core_ext/infinity_spec.rb +40 -0
  96. data/spec/lib/strokedb/core_ext/spec_helper.rb +1 -0
  97. data/spec/lib/strokedb/core_ext/string_spec.rb +25 -0
  98. data/spec/lib/strokedb/core_ext/symbol_spec.rb +8 -0
  99. data/spec/lib/strokedb/data_structures/chunked_skiplist_spec.rb +144 -0
  100. data/spec/lib/strokedb/data_structures/inverted_list_spec.rb +172 -0
  101. data/spec/lib/strokedb/data_structures/simple_skiplist_spec.rb +200 -0
  102. data/spec/lib/strokedb/data_structures/skiplist_spec.rb +253 -0
  103. data/spec/lib/strokedb/data_structures/spec_helper.rb +1 -0
  104. data/spec/lib/strokedb/document/associations_spec.rb +319 -0
  105. data/spec/lib/strokedb/document/callbacks_spec.rb +134 -0
  106. data/spec/lib/strokedb/document/coercions_spec.rb +110 -0
  107. data/spec/lib/strokedb/document/document_spec.rb +1063 -0
  108. data/spec/lib/strokedb/document/meta_meta_spec.rb +30 -0
  109. data/spec/lib/strokedb/document/meta_spec.rb +435 -0
  110. data/spec/lib/strokedb/document/metaslot_spec.rb +43 -0
  111. data/spec/lib/strokedb/document/slot_spec.rb +130 -0
  112. data/spec/lib/strokedb/document/spec_helper.rb +1 -0
  113. data/spec/lib/strokedb/document/validations_spec.rb +1081 -0
  114. data/spec/lib/strokedb/document/virtualize_spec.rb +80 -0
  115. data/spec/lib/strokedb/nsurl_spec.rb +73 -0
  116. data/spec/lib/strokedb/spec_helper.rb +1 -0
  117. data/spec/lib/strokedb/stores/chained_storages_spec.rb +116 -0
  118. data/spec/lib/strokedb/stores/spec_helper.rb +1 -0
  119. data/spec/lib/strokedb/stores/store_spec.rb +201 -0
  120. data/spec/lib/strokedb/stores/transaction_spec.rb +107 -0
  121. data/spec/lib/strokedb/sync/chain_sync_spec.rb +43 -0
  122. data/spec/lib/strokedb/sync/diff_spec.rb +111 -0
  123. data/spec/lib/strokedb/sync/lamport_timestamp_spec.rb +174 -0
  124. data/spec/lib/strokedb/sync/slot_diff_spec.rb +164 -0
  125. data/spec/lib/strokedb/sync/spec_helper.rb +1 -0
  126. data/spec/lib/strokedb/sync/store_sync_spec.rb +181 -0
  127. data/spec/lib/strokedb/sync/stroke_diff/array_spec.rb +97 -0
  128. data/spec/lib/strokedb/sync/stroke_diff/complex_spec.rb +58 -0
  129. data/spec/lib/strokedb/sync/stroke_diff/hash_spec.rb +144 -0
  130. data/spec/lib/strokedb/sync/stroke_diff/scalar_spec.rb +23 -0
  131. data/spec/lib/strokedb/sync/stroke_diff/spec_helper.rb +25 -0
  132. data/spec/lib/strokedb/sync/stroke_diff/string_spec.rb +61 -0
  133. data/spec/lib/strokedb/util/attach_dsl_spec.rb +45 -0
  134. data/spec/lib/strokedb/util/inflect_spec.rb +14 -0
  135. data/spec/lib/strokedb/util/lazy_array_spec.rb +157 -0
  136. data/spec/lib/strokedb/util/lazy_mapping_array_spec.rb +174 -0
  137. data/spec/lib/strokedb/util/lazy_mapping_hash_spec.rb +92 -0
  138. data/spec/lib/strokedb/util/spec_helper.rb +1 -0
  139. data/spec/lib/strokedb/util/uuid_spec.rb +46 -0
  140. data/spec/lib/strokedb/view_spec.rb +228 -0
  141. data/spec/lib/strokedb/volumes/archive_volume_spec.rb +105 -0
  142. data/spec/lib/strokedb/volumes/block_volume_spec.rb +100 -0
  143. data/spec/lib/strokedb/volumes/distributed_pointer_spec.rb +14 -0
  144. data/spec/lib/strokedb/volumes/fixed_length_skiplist_volume_spec.rb +177 -0
  145. data/spec/lib/strokedb/volumes/map_volume_spec.rb +172 -0
  146. data/spec/lib/strokedb/volumes/spec_helper.rb +1 -0
  147. data/spec/regression/docref_spec.rb +94 -0
  148. data/spec/regression/meta_spec.rb +23 -0
  149. data/spec/regression/spec_helper.rb +1 -0
  150. data/spec/regression/sync_spec.rb +36 -0
  151. data/spec/spec.opts +7 -0
  152. data/spec/spec_helper.rb +37 -0
  153. data/spec/temp/storages/TIMESTAMP +1 -0
  154. data/spec/temp/storages/UUID +1 -0
  155. data/spec/temp/storages/database-sync/TIMESTAMP +1 -0
  156. data/spec/temp/storages/database-sync/UUID +1 -0
  157. data/spec/temp/storages/database-sync/config +1 -0
  158. data/spec/temp/storages/database-sync/file/LAST +1 -0
  159. data/spec/temp/storages/database-sync/file/bd/f6/bdf675e5-8a7b-494e-97f2-f74a14ccd95d.av +0 -0
  160. data/spec/temp/storages/database-sync/file/uindex.wal +0 -0
  161. data/spec/temp/storages/database-sync/inverted_list_file/INVERTED_INDEX +1 -0
  162. data/spec/temp/storages/inverted_list_storage/INVERTED_INDEX +0 -0
  163. data/strokedb.gemspec +120 -0
  164. data/task/benchmark.task +9 -0
  165. data/task/ditz.task +30 -0
  166. data/task/echoe.rb +17 -0
  167. data/task/rcov.task +50 -0
  168. data/task/rdoc.task +10 -0
  169. data/task/rspec.task +0 -0
  170. data/vendor/java_inline.rb +106 -0
  171. data/vendor/rbmodexcl/mrimodexcl.rb +82 -0
  172. data/vendor/rbmodexcl/rbmodexcl.rb +5 -0
  173. data/vendor/rbmodexcl/rbxmodexcl.rb +48 -0
  174. data/vendor/rbmodexcl/spec/unextend_spec.rb +50 -0
  175. data/vendor/rbmodexcl/spec/uninclude_spec.rb +26 -0
  176. metadata +271 -79
  177. data/CONTRIBUTORS +0 -7
  178. data/CREDITS +0 -13
  179. data/bin/sdbc +0 -2
  180. data/lib/init.rb +0 -57
  181. data/lib/stores/inverted_list_index/inverted_list_index.rb +0 -49
  182. data/lib/stores/skiplist_store/chunk.rb +0 -119
  183. data/lib/stores/skiplist_store/chunk_storage.rb +0 -21
  184. data/lib/stores/skiplist_store/file_chunk_storage.rb +0 -44
  185. data/lib/stores/skiplist_store/memory_chunk_storage.rb +0 -37
  186. data/lib/stores/skiplist_store/skiplist_store.rb +0 -217
  187. data/lib/stores/store.rb +0 -5
  188. data/lib/sync/stroke_diff/stroke_diff.rb +0 -9
  189. data/lib/util/ext/object.rb +0 -8
  190. data/lib/util/java_util.rb +0 -9
  191. data/lib/util/trigger_partition.rb +0 -136
  192. data/strokedb.rb +0 -75
@@ -0,0 +1,107 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe 'Transaction', :shared => true do
4
+
5
+ it "should have UUID" do
6
+ @txn.uuid.should match(/#{UUID_RE}/)
7
+ end
8
+
9
+ it "should act as a store for documents initialized within transaction scope" do
10
+ @txn.execute do
11
+ @doc = Document.new
12
+ @doc.store.should == @txn
13
+ end
14
+ end
15
+
16
+ it "should revert newly instantiated documents' store to main one outside of transaction scope" do
17
+ @txn.execute do
18
+ @doc = Document.new
19
+ end
20
+ @doc.store.should == @txn.store
21
+ end
22
+
23
+ it "should acts as a store for already initialized documents" do
24
+ @doc = Document.new
25
+ @txn.execute do
26
+ @doc.store.should == @txn
27
+ end
28
+ end
29
+
30
+ it "should return block result on block execution" do
31
+ @txn.execute do
32
+ :some_result
33
+ end.should == :some_result
34
+ end
35
+
36
+ it "should be able to find already existing document within transaction scope" do
37
+ @doc = Document.create!
38
+ @txn.execute do
39
+ Document.find(@doc.uuid).should == @doc
40
+ end
41
+ end
42
+
43
+ it "should be able to save new documents within block execution without exposing them to original storage" do
44
+ @txn.execute do
45
+ @doc = Document.create!
46
+ Document.find(@doc.uuid).should == @doc
47
+ end
48
+ Document.find(@doc.uuid).should be_nil
49
+ end
50
+
51
+ it "should see its own head version of the document" do
52
+ @doc = Document.create!
53
+ @txn.execute do |txn|
54
+ @doc.update_slots! :new_version => 'yes'
55
+ @doc.store.head_version(@doc.uuid).should == @doc.version
56
+ end
57
+ @doc.store.head_version(@doc.uuid).should == @doc.versions.previous.version
58
+ end
59
+
60
+ it "should be able to commit transaction" do
61
+ @txn.execute do |txn|
62
+ @doc = Document.create!
63
+ txn.commit!
64
+ end
65
+ Document.find(@doc.uuid).should == @doc
66
+ end
67
+
68
+ it "should be able to rollback transaction" do
69
+ @txn.execute do |txn|
70
+ @doc = Document.create!
71
+ txn.rollback!
72
+ Document.find(@doc.uuid).should be_nil
73
+ end
74
+ Document.find(@doc.uuid).should be_nil
75
+ end
76
+
77
+ it "should pop transaction on code that raises some exception" do
78
+ lambda do
79
+ @txn.execute do |txn|
80
+ raise Exception
81
+ end
82
+ end.should raise_error(Exception)
83
+ Thread.current[:strokedb_transactions].should be_empty
84
+ end
85
+
86
+ it "should pop transaction on code that raises no exception" do
87
+ lambda do
88
+ @txn.execute do |txn|
89
+ end
90
+ end.should_not raise_error(Exception)
91
+ Thread.current[:strokedb_transactions].should be_empty
92
+ end
93
+
94
+
95
+ end
96
+
97
+ describe "New", Transaction do
98
+
99
+ before(:each) do
100
+ StrokeDB::Config.build :default => true, :storages => [:memory], :base_path => TEMP_STORAGES + '/txn'
101
+ @txn = Transaction.new(:store => StrokeDB.default_store)
102
+ Thread.current[:strokedb_transactions] = nil
103
+ end
104
+
105
+ it_should_behave_like 'Transaction'
106
+
107
+ end
@@ -0,0 +1,43 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe "Chain sync" do
4
+ include ChainSync
5
+ before(:each) do
6
+ @chain1 = %w[ a b c ]
7
+ @chain2 = %w[ a b c d e ]
8
+ @chain3 = %w[ a b q w r ]
9
+ @chain4 = %w[ t y u i o ]
10
+ end
11
+
12
+ it "should raise NonMatchingChains for non-matching chains" do
13
+ lambda{ sync_chains(@chain1, @chain4) }.should raise_error(ChainSync::NonMatchingChains)
14
+ lambda{ sync_chains(@chain4, @chain1) }.should raise_error(ChainSync::NonMatchingChains)
15
+ end
16
+
17
+ it "should not raise NonMatchingChains for matching chains" do
18
+ lambda{ sync_chains(@chain1, @chain2) }.should_not raise_error
19
+ lambda{ sync_chains(@chain1, @chain3) }.should_not raise_error
20
+ lambda{ sync_chains(@chain2, @chain3) }.should_not raise_error
21
+ lambda{ sync_chains(@chain2, @chain1) }.should_not raise_error
22
+ lambda{ sync_chains(@chain3, @chain1) }.should_not raise_error
23
+ lambda{ sync_chains(@chain3, @chain2) }.should_not raise_error
24
+ end
25
+
26
+ it "should resolve up-to-date situation" do
27
+ sync_chains(@chain1, @chain2).should == :up_to_date
28
+ sync_chains(@chain2, @chain1).should_not == :up_to_date
29
+ end
30
+
31
+ it "should resolve fast-forward situation" do
32
+ status, subchain = sync_chains(@chain2, @chain1)
33
+ status.should == :fast_forward
34
+ subchain.should == %w[ c d e ]
35
+ end
36
+
37
+ it "should resolve merge situation" do
38
+ status, subchain_from, subchain_to = sync_chains(@chain2, @chain3)
39
+ status.should == :merge
40
+ subchain_from.should == %w[ b c d e ]
41
+ subchain_to.should == %w[ b q w r ]
42
+ end
43
+ end
@@ -0,0 +1,111 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe "Diffing documents", :shared => true do
4
+ it "should have from and to specified" do
5
+ [:from,:to].each do |slotname|
6
+ @diff[slotname].should be_a_kind_of(Document)
7
+ end
8
+ end
9
+
10
+ it "should be appliable as patch" do
11
+ from = @from.dup
12
+ @diff.patch!(from)
13
+ (from.slotnames - ['version','previous_version']).should == (@to.slotnames-['version','previous_version'])
14
+ (from.slotnames - ['version','previous_version']).each do |slotname|
15
+ from[slotname].should == @to[slotname]
16
+ end
17
+ end
18
+ end
19
+
20
+ describe "Diffing documents with slot added" do
21
+ before(:each) do
22
+ @store = setup_default_store
23
+ @from = Document.create! :slot1 => 1
24
+ @to = Document.create! :slot1 => 1, :slot2 => 2
25
+ @diff = @to.diff(@from)
26
+ end
27
+
28
+ it "should list added slot" do
29
+ @diff.added_slots.keys.to_set.should == ['slot2'].to_set
30
+ @diff.added_slots['slot2'].should == 2
31
+ end
32
+
33
+
34
+ it "should report as modified" do
35
+ @diff.should be_different
36
+ end
37
+
38
+ it_should_behave_like "Diffing documents"
39
+
40
+ end
41
+
42
+ describe "Diffing documents with slot removed" do
43
+ before(:each) do
44
+ @store = setup_default_store
45
+ @from = Document.create! :slot1 => 1, :slot2 => 2
46
+ @to = Document.create! :slot1 => 1
47
+ @diff = @to.diff(@from)
48
+ end
49
+
50
+ it "should list removed slot" do
51
+ @diff.removed_slots.keys.to_set.should == ['slot2'].to_set
52
+ @diff.removed_slots['slot2'].should == 2
53
+ end
54
+
55
+
56
+ it "should report as modified" do
57
+ @diff.should be_different
58
+ end
59
+
60
+ it_should_behave_like "Diffing documents"
61
+
62
+
63
+ end
64
+
65
+ describe "Diffing documents with slot changed" do
66
+ before(:each) do
67
+ @store = setup_default_store
68
+ @from = Document.create! :slot1 => 1
69
+ @to = Document.create! :slot1 => 2
70
+ @diff = @to.diff(@from)
71
+ end
72
+
73
+ it "should list updated slot" do
74
+ @diff.updated_slots.keys.to_set.should == ['slot1','uuid'].to_set
75
+ @diff.updated_slots['slot1'].should == 2
76
+ end
77
+
78
+
79
+ it "should report as modified" do
80
+ @diff.should be_different
81
+ end
82
+
83
+
84
+ it_should_behave_like "Diffing documents"
85
+
86
+ end
87
+
88
+
89
+ ['slot_1_diff','default_slot_diff'].each do |strategy|
90
+ describe "Diffing documents with slot changed with slot diffing strategy" do
91
+ before(:each) do
92
+ @store = setup_default_store
93
+
94
+ Object.send!(:remove_const,'Slot1Diff') if defined?(Slot1Diff)
95
+ Slot1Diff = Class.new(SlotDiffStrategy)
96
+ Slot1Diff.should_receive(:diff).with("abcdef","abcdef1").any_number_of_times.and_return("1")
97
+ Slot1Diff.should_receive(:patch).with("abcdef","1").any_number_of_times.and_return("abcdef1")
98
+
99
+
100
+ @meta = Document.create! :diff_strategy_slot1 => strategy # TODO: fix this spec, it willn't care if I say strategy_slot1
101
+
102
+ @from = Document.create! :slot1 => "abcdef", :meta => @meta
103
+ @to = Document.create! :slot1 => "abcdef1", :meta => @meta
104
+
105
+ @diff = @to.diff(@from)
106
+ end
107
+
108
+ it_should_behave_like "Diffing documents"
109
+
110
+ end
111
+ end
@@ -0,0 +1,174 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe "LamportTimestamp" do
4
+ it "#zero_string" do
5
+ LamportTimestamp.zero_string.should == '000000000000000000000000-0000-0000-0000-000000000000'
6
+ end
7
+ end
8
+
9
+ describe "Initial LamportTimestamp" do
10
+ before(:each) do
11
+ @t0 = LamportTimestamp.new
12
+ end
13
+
14
+ it "should have counter == 0" do
15
+ @t0.counter.should == 0
16
+ end
17
+
18
+ it "should have UUID-based uuid" do
19
+ @t0.uuid.should match(UUID_RE)
20
+ end
21
+
22
+ it "should pass generated uuid on #next" do
23
+ @t0.next.uuid.should == @t0.uuid
24
+ end
25
+
26
+ it "shoul return marshal_dump as json" do
27
+ @t0.to_json.should == '"0000000000000000'+@t0.uuid+'"'
28
+ end
29
+ end
30
+
31
+
32
+ describe "Initial LamportTimestamp with uuid specified" do
33
+ before(:each) do
34
+ @t0 = LamportTimestamp.new(0,NIL_UUID)
35
+ end
36
+
37
+ it "should have counter == 0" do
38
+ @t0.counter.should == 0
39
+ end
40
+
41
+ it "should have UUID-based uuid as defined" do
42
+ @t0.uuid.should == NIL_UUID
43
+ end
44
+
45
+ it "should pass uuid on #next" do
46
+ @t0.next.uuid.should == @t0.uuid
47
+ end
48
+ end
49
+
50
+
51
+ describe "Preset LamportTimestamp" do
52
+ before(:each) do
53
+ @t0 = LamportTimestamp.new()
54
+ @t123 = LamportTimestamp.new(123)
55
+ @t234 = LamportTimestamp.new(234)
56
+ end
57
+
58
+ it "should be compared properly" do
59
+ (@t0 <=> @t123).should == -1
60
+ (@t123 <=> @t234).should == -1
61
+ end
62
+
63
+ it "should have UUID-based uuid" do
64
+ @t123.uuid.should match(UUID_RE)
65
+ @t234.uuid.should match(UUID_RE)
66
+ end
67
+ end
68
+
69
+
70
+ describe "LamportTimestamp equality" do
71
+ before(:each) do
72
+ @t = LamportTimestamp.new(123)
73
+ @t_dumped = Marshal.dump(@t)
74
+ @t_loaded = Marshal.load(@t_dumped)
75
+ end
76
+
77
+ # Positive
78
+ it { @t.should == @t }
79
+ it { @t.should == @t_loaded }
80
+ it "should correctly compare tons of dumped-loaded timestamps" do
81
+ 1000.times do
82
+ t = LamportTimestamp.new(rand(2**64))
83
+ t.should == Marshal.load(Marshal.dump(t))
84
+ end
85
+ end
86
+
87
+ # Negative
88
+ it { LamportTimestamp.new().should_not == LamportTimestamp.new() }
89
+ it { LamportTimestamp.new(123).should_not == LamportTimestamp.new(123) }
90
+ it { LamportTimestamp.new(234).should_not == LamportTimestamp.new(234) }
91
+ end
92
+
93
+
94
+ describe "Lesser and greater LamportTimestamps" do
95
+ before(:each) do
96
+ @t0 = LamportTimestamp.new()
97
+ @t123 = LamportTimestamp.new(123)
98
+ end
99
+
100
+ it "should be comparable with <" do
101
+ @t0.should < @t123
102
+ @t123.should_not < @t0
103
+ end
104
+
105
+ it "should be comparable with <=" do
106
+ @t0.should <= @t123
107
+ @t123.should <= @t123
108
+ @t123.should_not <= @t0
109
+ end
110
+
111
+ it "should be comparable with >" do
112
+ @t123.should > @t0
113
+ @t123.should_not > @t123
114
+ @t0.should_not > @t123
115
+ end
116
+
117
+ it "should be comparable with >=" do
118
+ @t123.should >= @t0
119
+ @t123.should >= @t123
120
+ @t0.should_not >= @t123
121
+ end
122
+
123
+ it { 1000.times { t = LamportTimestamp.new(rand(2**64)); t.next.next.should > t.next } }
124
+
125
+ it "should generate a list of successive timestamps with next!" do
126
+ t = LamportTimestamp.new(rand(2**32))
127
+ 1000.times do
128
+ t_ = t.dup
129
+ t.next!
130
+ t_.should < t
131
+ t_.uuid.should == t.uuid
132
+ end
133
+ end
134
+ end
135
+
136
+
137
+ describe "LamportTimestamp maximum counter exception" do
138
+ it "should raise error if counter is too big" do
139
+ lambda { LamportTimestamp.new(2**64 + 1) }.should raise_error(LamportTimestamp::CounterOverflow)
140
+ end
141
+ it "should not raise error if counter is 2**64" do
142
+ lambda { LamportTimestamp.new(2**64) }.should_not raise_error
143
+ lambda { LamportTimestamp.new(2**64-1) }.should_not raise_error
144
+ end
145
+ it "should raise error on LamportTimestamp#next" do
146
+ lambda { LamportTimestamp.new(2**64).next }.should raise_error(LamportTimestamp::CounterOverflow)
147
+ end
148
+ it "should not raise error on LamportTimestamp#next if no overflow occured" do
149
+ lambda { LamportTimestamp.new(2**64 - 1).next }.should_not raise_error
150
+ end
151
+ end
152
+
153
+
154
+ describe "LamportTimestamp raw format" do
155
+ before(:each) do
156
+ @t = LamportTimestamp.new(123)
157
+ end
158
+ it "should convert to simple string" do
159
+ @t.to_raw.should == @t.to_s
160
+ end
161
+ it "should correctly convert end-to-end" do
162
+ LamportTimestamp.from_raw(@t.to_raw).should == @t
163
+ end
164
+ it "should compare raw representation exactly like object representation" do
165
+ 1000.times do
166
+ t1 = LTS.new(rand(2**32))
167
+ t2 = LTS.new(rand(2**32))
168
+ object_comparison = (t1 <=> t2)
169
+ raw_comparison = (t1.to_raw <=> t2.to_raw)
170
+ object_comparison.should == raw_comparison
171
+ end
172
+ end
173
+ end
174
+
@@ -0,0 +1,164 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe "Diffing documents with slot changed and slot's diff strategy is specified on meta" do
4
+
5
+ before(:each) do
6
+ @store = setup_default_store
7
+ Object.send!(:remove_const,'Slot1Diff') if defined?(Slot1Diff)
8
+ Slot1Diff = Class.new(SlotDiffStrategy)
9
+ Slot1Diff.should_receive(:diff).with(1,2).and_return(3)
10
+
11
+ @meta = Document.create! :diff_strategy_slot1 => 'slot_1_diff'
12
+
13
+ @from = Document.create! :slot1 => 1, :meta => @meta
14
+ @to = Document.create! :slot1 => 2, :meta => @meta
15
+
16
+ @diff = @to.diff(@from)
17
+ end
18
+
19
+ it "should diff slot value according to its strategy" do
20
+ @diff.updated_slots['slot1'].should == 3
21
+ end
22
+
23
+ end
24
+
25
+
26
+ describe "Diffing documents with slot changed and slot's diff strategy is specified on meta, but there is no such diff strategy" do
27
+
28
+ before(:each) do
29
+ @store = setup_default_store
30
+
31
+ Object.send!(:remove_const,'Slot1Diff') if defined?(Slot1Diff)
32
+ @meta = Document.create! :diff_strategy_slot1 => 'slot_1_diff'
33
+
34
+ @from = Document.create! :slot1 => 1, :meta => @meta
35
+ @to = Document.create! :slot1 => 2, :meta => @meta
36
+
37
+ @diff = @to.diff(@from)
38
+ end
39
+
40
+ it "should not diff slot" do
41
+ @diff.updated_slots['slot1'].should == 2
42
+ end
43
+
44
+ end
45
+
46
+ describe "Diffing documents with slot changed and slot's diff strategy is specified on meta, but diff strategy is invalid" do
47
+
48
+ before(:each) do
49
+ @store = setup_default_store
50
+ Object.send!(:remove_const,'Slot1Diff') if defined?(Slot1Diff)
51
+
52
+ Slot1Diff = Class.new
53
+
54
+ @meta = Document.create! :diff_strategy_slot1 => 'slot_1_diff'
55
+
56
+ @from = Document.create! :slot1 => 1, :meta => @meta
57
+ @to = Document.create! :slot1 => 2, :meta => @meta
58
+
59
+ @diff = @to.diff(@from)
60
+ end
61
+
62
+ it "should not diff slot" do
63
+ @diff.updated_slots['slot1'].should == 2
64
+ end
65
+
66
+ end
67
+
68
+ [DefaultSlotDiff].each do |strategy|
69
+
70
+ describe "#{strategy.name} for String" do
71
+ before(:each) do
72
+ @string1 = "hello world"
73
+ @string2 = "bye world"
74
+ end
75
+
76
+ it "should diff to an LCS structure" do
77
+ strategy.diff(@string1, @string2).should be_a_kind_of(Array)
78
+ end
79
+
80
+ it "should patch String back" do
81
+ strategy.patch(@string1,strategy.diff(@string1, @string2)).should == @string2
82
+ end
83
+
84
+ end
85
+
86
+ describe "#{strategy.name} for Array" do
87
+ before(:each) do
88
+ @array1 = [1,2,3]
89
+ @array2 = [1,5,3]
90
+ end
91
+
92
+ it "should diff to an LCS structure" do
93
+ strategy.diff(@array1, @array2).should be_a_kind_of(Array)
94
+ end
95
+
96
+ it "should patch Array back" do
97
+ strategy.patch(@array1,strategy.diff(@array1, @array2)).should == @array2
98
+ end
99
+ end
100
+
101
+ describe "#{strategy.name} for Hash" do
102
+ before(:each) do
103
+ @hash1 = { :a => 1}
104
+ @hash2 = { :a => 1, :b => 2}
105
+ end
106
+
107
+ it "should diff to an LCS structure" do
108
+ strategy.diff(@hash1, @hash2).should be_a_kind_of(Array)
109
+ end
110
+
111
+ it "should patch Hash back" do
112
+ strategy.patch(@hash1,strategy.diff(@hash1, @hash2)).should == @hash2
113
+ end
114
+ end
115
+
116
+
117
+ describe "#{strategy.name} for document reference" do
118
+ before(:each) do
119
+ @ref1 = "@##{Util.random_uuid}"
120
+ @ref2 = "@##{Util.random_uuid}"
121
+ end
122
+
123
+ it "should diff to an LCS structure" do
124
+ strategy.diff(@ref1, @ref2).should be_a_kind_of(String)
125
+ end
126
+
127
+ it "should patch document reference back" do
128
+ strategy.patch(@ref1,strategy.diff(@ref1, @ref2)).should == @ref2
129
+ end
130
+ end
131
+
132
+
133
+
134
+ describe "#{strategy.name} for number" do
135
+ before(:each) do
136
+ @num1 = 1
137
+ @num2 = 2
138
+ end
139
+
140
+ it "should diff to an LCS structure" do
141
+ strategy.diff(@num1, @num2).should be_a_kind_of(Numeric)
142
+ end
143
+
144
+ it "should patch number back" do
145
+ strategy.patch(@num1,strategy.diff(@num1, @num2)).should == @num2
146
+ end
147
+ end
148
+
149
+ describe "#{strategy.name} for different types" do
150
+ before(:each) do
151
+ @val1 = 1
152
+ @val2 = "a"
153
+ end
154
+
155
+ it "should diff to target value" do
156
+ strategy.diff(@val1, @val2).should == @val2
157
+ end
158
+
159
+ it "should patch number back" do
160
+ strategy.patch(@val1,strategy.diff(@val1, @val2)).should == @val2
161
+ end
162
+
163
+ end
164
+ end