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.
- data/README +18 -20
- data/bench.html +4001 -0
- data/bin/strokedb +14 -0
- data/examples/movies.rb +105 -0
- data/examples/movies2.rb +97 -0
- data/examples/strokewiki/README +28 -0
- data/examples/strokewiki/view/edit.xhtml +27 -0
- data/examples/strokewiki/view/new.xhtml +26 -0
- data/examples/strokewiki/view/pages.xhtml +27 -0
- data/examples/strokewiki/view/show.xhtml +40 -0
- data/examples/strokewiki/view/versions.xhtml +25 -0
- data/examples/strokewiki/wiki.rb +106 -0
- data/examples/todo.rb +92 -0
- data/lib/strokedb.rb +85 -0
- data/lib/{config → strokedb}/config.rb +14 -9
- data/lib/strokedb/console.rb +87 -0
- data/lib/strokedb/core_ext.rb +10 -0
- data/lib/{util/ext → strokedb/core_ext}/blank.rb +1 -1
- data/lib/{util/ext → strokedb/core_ext}/enumerable.rb +0 -0
- data/lib/{util/ext → strokedb/core_ext}/fixnum.rb +0 -0
- data/lib/strokedb/core_ext/float.rb +4 -0
- data/lib/{util/ext → strokedb/core_ext}/hash.rb +0 -0
- data/lib/strokedb/core_ext/infinity.rb +33 -0
- data/lib/strokedb/core_ext/kernel.rb +41 -0
- data/lib/strokedb/core_ext/object.rb +16 -0
- data/lib/{util/ext → strokedb/core_ext}/string.rb +28 -1
- data/lib/strokedb/core_ext/symbol.rb +13 -0
- data/lib/strokedb/data_structures.rb +5 -0
- data/lib/strokedb/data_structures/chunked_skiplist.rb +123 -0
- data/lib/{data_structures → strokedb/data_structures}/inverted_list.rb +0 -0
- data/lib/{data_structures → strokedb/data_structures}/point_query.rb +0 -0
- data/lib/strokedb/data_structures/simple_skiplist.rb +350 -0
- data/lib/{data_structures → strokedb/data_structures}/skiplist.rb +1 -1
- data/lib/{document → strokedb}/document.rb +180 -71
- data/lib/{document → strokedb/document}/callback.rb +0 -0
- data/lib/{document → strokedb/document}/delete.rb +2 -2
- data/lib/strokedb/document/dsl.rb +4 -0
- data/lib/{document → strokedb/document/dsl}/associations.rb +0 -0
- data/lib/{document → strokedb/document/dsl}/coercions.rb +0 -0
- data/lib/strokedb/document/dsl/meta_dsl.rb +7 -0
- data/lib/{document → strokedb/document/dsl}/validations.rb +26 -21
- data/lib/{document → strokedb/document/dsl}/virtualize.rb +0 -0
- data/lib/{document → strokedb/document}/meta.rb +92 -29
- data/lib/{document → strokedb/document}/slot.rb +17 -5
- data/lib/{document → strokedb/document}/util.rb +0 -0
- data/lib/{document → strokedb/document}/versions.rb +2 -2
- data/lib/strokedb/index.rb +2 -0
- data/lib/strokedb/nsurl.rb +24 -0
- data/lib/strokedb/store.rb +149 -0
- data/lib/strokedb/stores.rb +6 -0
- data/lib/{stores → strokedb/stores}/chainable_storage.rb +20 -14
- data/lib/strokedb/stores/file_storage.rb +118 -0
- data/lib/{stores/inverted_list_index → strokedb/stores}/inverted_list_file_storage.rb +50 -0
- data/lib/strokedb/stores/memory_storage.rb +80 -0
- data/lib/{stores → strokedb/stores}/remote_store.rb +10 -4
- data/lib/strokedb/sync.rb +4 -0
- data/lib/{sync → strokedb/sync}/chain_sync.rb +0 -0
- data/lib/{sync → strokedb/sync}/diff.rb +12 -1
- data/lib/{sync/stroke_diff → strokedb/sync/diff}/array.rb +1 -1
- data/lib/{sync/stroke_diff → strokedb/sync/diff}/default.rb +0 -0
- data/lib/{sync/stroke_diff → strokedb/sync/diff}/hash.rb +1 -1
- data/lib/{sync/stroke_diff → strokedb/sync/diff}/string.rb +1 -1
- data/lib/{sync → strokedb/sync}/lamport_timestamp.rb +0 -0
- data/lib/{sync → strokedb/sync}/store_sync.rb +15 -7
- data/lib/strokedb/transaction.rb +78 -0
- data/lib/{util → strokedb}/util.rb +14 -7
- data/lib/strokedb/util/attach_dsl.rb +29 -0
- data/lib/{util → strokedb/util}/blankslate.rb +0 -0
- data/lib/strokedb/util/class_optimization.rb +93 -0
- data/lib/{util → strokedb/util}/inflect.rb +0 -0
- data/lib/strokedb/util/java_util.rb +13 -0
- data/lib/{util → strokedb/util}/lazy_array.rb +0 -0
- data/lib/{util → strokedb/util}/lazy_mapping_array.rb +4 -0
- data/lib/{util → strokedb/util}/lazy_mapping_hash.rb +0 -0
- data/lib/{util → strokedb/util}/serialization.rb +21 -0
- data/lib/strokedb/util/uuid.rb +159 -0
- data/lib/{util → strokedb/util}/xml.rb +0 -0
- data/lib/{view → strokedb}/view.rb +2 -2
- data/lib/strokedb/volumes.rb +5 -0
- data/lib/strokedb/volumes/archive_volume.rb +165 -0
- data/lib/strokedb/volumes/block_volume.rb +169 -0
- data/lib/strokedb/volumes/distributed_pointer.rb +43 -0
- data/lib/strokedb/volumes/fixed_length_skiplist_volume.rb +109 -0
- data/lib/strokedb/volumes/map_volume.rb +268 -0
- data/meta/MANIFEST +175 -0
- data/script/console +2 -70
- data/spec/integration/remote_store_spec.rb +70 -0
- data/spec/integration/search_spec.rb +76 -0
- data/spec/integration/spec_helper.rb +1 -0
- data/spec/lib/spec_helper.rb +1 -0
- data/spec/lib/strokedb/config_spec.rb +250 -0
- data/spec/lib/strokedb/core_ext/blank_spec.rb +20 -0
- data/spec/lib/strokedb/core_ext/extract_spec.rb +42 -0
- data/spec/lib/strokedb/core_ext/float_spec.rb +62 -0
- data/spec/lib/strokedb/core_ext/infinity_spec.rb +40 -0
- data/spec/lib/strokedb/core_ext/spec_helper.rb +1 -0
- data/spec/lib/strokedb/core_ext/string_spec.rb +25 -0
- data/spec/lib/strokedb/core_ext/symbol_spec.rb +8 -0
- data/spec/lib/strokedb/data_structures/chunked_skiplist_spec.rb +144 -0
- data/spec/lib/strokedb/data_structures/inverted_list_spec.rb +172 -0
- data/spec/lib/strokedb/data_structures/simple_skiplist_spec.rb +200 -0
- data/spec/lib/strokedb/data_structures/skiplist_spec.rb +253 -0
- data/spec/lib/strokedb/data_structures/spec_helper.rb +1 -0
- data/spec/lib/strokedb/document/associations_spec.rb +319 -0
- data/spec/lib/strokedb/document/callbacks_spec.rb +134 -0
- data/spec/lib/strokedb/document/coercions_spec.rb +110 -0
- data/spec/lib/strokedb/document/document_spec.rb +1063 -0
- data/spec/lib/strokedb/document/meta_meta_spec.rb +30 -0
- data/spec/lib/strokedb/document/meta_spec.rb +435 -0
- data/spec/lib/strokedb/document/metaslot_spec.rb +43 -0
- data/spec/lib/strokedb/document/slot_spec.rb +130 -0
- data/spec/lib/strokedb/document/spec_helper.rb +1 -0
- data/spec/lib/strokedb/document/validations_spec.rb +1081 -0
- data/spec/lib/strokedb/document/virtualize_spec.rb +80 -0
- data/spec/lib/strokedb/nsurl_spec.rb +73 -0
- data/spec/lib/strokedb/spec_helper.rb +1 -0
- data/spec/lib/strokedb/stores/chained_storages_spec.rb +116 -0
- data/spec/lib/strokedb/stores/spec_helper.rb +1 -0
- data/spec/lib/strokedb/stores/store_spec.rb +201 -0
- data/spec/lib/strokedb/stores/transaction_spec.rb +107 -0
- data/spec/lib/strokedb/sync/chain_sync_spec.rb +43 -0
- data/spec/lib/strokedb/sync/diff_spec.rb +111 -0
- data/spec/lib/strokedb/sync/lamport_timestamp_spec.rb +174 -0
- data/spec/lib/strokedb/sync/slot_diff_spec.rb +164 -0
- data/spec/lib/strokedb/sync/spec_helper.rb +1 -0
- data/spec/lib/strokedb/sync/store_sync_spec.rb +181 -0
- data/spec/lib/strokedb/sync/stroke_diff/array_spec.rb +97 -0
- data/spec/lib/strokedb/sync/stroke_diff/complex_spec.rb +58 -0
- data/spec/lib/strokedb/sync/stroke_diff/hash_spec.rb +144 -0
- data/spec/lib/strokedb/sync/stroke_diff/scalar_spec.rb +23 -0
- data/spec/lib/strokedb/sync/stroke_diff/spec_helper.rb +25 -0
- data/spec/lib/strokedb/sync/stroke_diff/string_spec.rb +61 -0
- data/spec/lib/strokedb/util/attach_dsl_spec.rb +45 -0
- data/spec/lib/strokedb/util/inflect_spec.rb +14 -0
- data/spec/lib/strokedb/util/lazy_array_spec.rb +157 -0
- data/spec/lib/strokedb/util/lazy_mapping_array_spec.rb +174 -0
- data/spec/lib/strokedb/util/lazy_mapping_hash_spec.rb +92 -0
- data/spec/lib/strokedb/util/spec_helper.rb +1 -0
- data/spec/lib/strokedb/util/uuid_spec.rb +46 -0
- data/spec/lib/strokedb/view_spec.rb +228 -0
- data/spec/lib/strokedb/volumes/archive_volume_spec.rb +105 -0
- data/spec/lib/strokedb/volumes/block_volume_spec.rb +100 -0
- data/spec/lib/strokedb/volumes/distributed_pointer_spec.rb +14 -0
- data/spec/lib/strokedb/volumes/fixed_length_skiplist_volume_spec.rb +177 -0
- data/spec/lib/strokedb/volumes/map_volume_spec.rb +172 -0
- data/spec/lib/strokedb/volumes/spec_helper.rb +1 -0
- data/spec/regression/docref_spec.rb +94 -0
- data/spec/regression/meta_spec.rb +23 -0
- data/spec/regression/spec_helper.rb +1 -0
- data/spec/regression/sync_spec.rb +36 -0
- data/spec/spec.opts +7 -0
- data/spec/spec_helper.rb +37 -0
- data/spec/temp/storages/TIMESTAMP +1 -0
- data/spec/temp/storages/UUID +1 -0
- data/spec/temp/storages/database-sync/TIMESTAMP +1 -0
- data/spec/temp/storages/database-sync/UUID +1 -0
- data/spec/temp/storages/database-sync/config +1 -0
- data/spec/temp/storages/database-sync/file/LAST +1 -0
- data/spec/temp/storages/database-sync/file/bd/f6/bdf675e5-8a7b-494e-97f2-f74a14ccd95d.av +0 -0
- data/spec/temp/storages/database-sync/file/uindex.wal +0 -0
- data/spec/temp/storages/database-sync/inverted_list_file/INVERTED_INDEX +1 -0
- data/spec/temp/storages/inverted_list_storage/INVERTED_INDEX +0 -0
- data/strokedb.gemspec +120 -0
- data/task/benchmark.task +9 -0
- data/task/ditz.task +30 -0
- data/task/echoe.rb +17 -0
- data/task/rcov.task +50 -0
- data/task/rdoc.task +10 -0
- data/task/rspec.task +0 -0
- data/vendor/java_inline.rb +106 -0
- data/vendor/rbmodexcl/mrimodexcl.rb +82 -0
- data/vendor/rbmodexcl/rbmodexcl.rb +5 -0
- data/vendor/rbmodexcl/rbxmodexcl.rb +48 -0
- data/vendor/rbmodexcl/spec/unextend_spec.rb +50 -0
- data/vendor/rbmodexcl/spec/uninclude_spec.rb +26 -0
- metadata +271 -79
- data/CONTRIBUTORS +0 -7
- data/CREDITS +0 -13
- data/bin/sdbc +0 -2
- data/lib/init.rb +0 -57
- data/lib/stores/inverted_list_index/inverted_list_index.rb +0 -49
- data/lib/stores/skiplist_store/chunk.rb +0 -119
- data/lib/stores/skiplist_store/chunk_storage.rb +0 -21
- data/lib/stores/skiplist_store/file_chunk_storage.rb +0 -44
- data/lib/stores/skiplist_store/memory_chunk_storage.rb +0 -37
- data/lib/stores/skiplist_store/skiplist_store.rb +0 -217
- data/lib/stores/store.rb +0 -5
- data/lib/sync/stroke_diff/stroke_diff.rb +0 -9
- data/lib/util/ext/object.rb +0 -8
- data/lib/util/java_util.rb +0 -9
- data/lib/util/trigger_partition.rb +0 -136
- 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
|