strokedb 0.0.2.1 → 0.0.2.2
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.
- 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,20 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
describe "fasle" do
|
|
5
|
+
it "should be blank" do
|
|
6
|
+
false.should be_blank
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
describe "true" do
|
|
11
|
+
it "should not be blank" do
|
|
12
|
+
true.should_not be_blank
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
describe "Numeric" do
|
|
17
|
+
it "should not be blank" do
|
|
18
|
+
Numeric.should_not be_blank
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
|
2
|
+
|
|
3
|
+
describe "Kernel#extract" do
|
|
4
|
+
|
|
5
|
+
it "should correctly extract various arguments" do
|
|
6
|
+
extract(Regexp, String, Hash, [ ]).should == [nil, nil, nil]
|
|
7
|
+
|
|
8
|
+
extract(Regexp, String, Hash, [/a/ ]).should == [/a/, nil, nil]
|
|
9
|
+
extract(Regexp, String, Hash, [ "a" ]).should == [nil, "a", nil]
|
|
10
|
+
extract(Regexp, String, Hash, [ {1=>2}]).should == [nil, nil, {1=>2}]
|
|
11
|
+
|
|
12
|
+
extract(Regexp, String, Hash, [//, "" ]).should == [//, "", nil]
|
|
13
|
+
extract(Regexp, String, Hash, [//, {}]).should == [//, nil, {} ]
|
|
14
|
+
extract(Regexp, String, Hash, [ "", {}]).should == [nil, "", {}]
|
|
15
|
+
|
|
16
|
+
extract(Regexp, String, Hash, [//, "", {}]).should == [//, "", {} ]
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "should raise ArgumentError when wrong arguments are passed" do
|
|
20
|
+
|
|
21
|
+
bad_case(Regexp, String, Hash, [123])
|
|
22
|
+
bad_case(Regexp, String, Hash, ["", //])
|
|
23
|
+
bad_case(Regexp, String, Hash, [{}, ""])
|
|
24
|
+
bad_case(Regexp, String, Hash, [true])
|
|
25
|
+
bad_case(Regexp, String, Hash, [false])
|
|
26
|
+
bad_case(Regexp, String, Hash, [//,false])
|
|
27
|
+
bad_case(Regexp, String, Hash, [nil])
|
|
28
|
+
bad_case(Regexp, String, Hash, ["", nil])
|
|
29
|
+
bad_case(Regexp, String, Hash, [nil, nil])
|
|
30
|
+
bad_case(Regexp, String, Hash, [{}, {}])
|
|
31
|
+
bad_case(Regexp, String, Hash, [//, //])
|
|
32
|
+
bad_case(Regexp, String, Hash, [ [] ])
|
|
33
|
+
bad_case(Regexp, String, Hash, [Object.new])
|
|
34
|
+
bad_case(Regexp, String, Hash, [Object.new, Object.new])
|
|
35
|
+
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def bad_case(*args)
|
|
39
|
+
lambda { extract(*args) }.should raise_error(ArgumentError)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Infinity do
|
|
4
|
+
|
|
5
|
+
it "should correctly compare with integers and floats" do
|
|
6
|
+
Infinity.should > 1
|
|
7
|
+
Infinity.should > 1.0
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it "should correctly work with ranges" do
|
|
11
|
+
(-Infinity..1).should include(-100)
|
|
12
|
+
(-Infinity..Infinity).should include(Float::MAX)
|
|
13
|
+
(0..Infinity).should include(Float::MAX)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "should return Infinity in arithmetics" do
|
|
17
|
+
(Infinity + Infinity).should == Infinity
|
|
18
|
+
(Infinity * Infinity).should == Infinity
|
|
19
|
+
(Infinity ** Infinity).should == Infinity
|
|
20
|
+
(Infinity / 0).should == Infinity
|
|
21
|
+
(Infinity / 0.0).should == Infinity
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "should return NaN in arithmetics" do
|
|
25
|
+
(Infinity - Infinity).should be_nan
|
|
26
|
+
(Infinity / Infinity).should be_nan
|
|
27
|
+
(Infinity * 0).should be_nan
|
|
28
|
+
(Infinity * 0.0).should be_nan
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
describe NaN do
|
|
34
|
+
|
|
35
|
+
it "should correctly compare with numerics" do
|
|
36
|
+
(NaN < 1).should be_false
|
|
37
|
+
(NaN > 1).should be_false
|
|
38
|
+
(NaN == 1).should be_false
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "should not compare with itself" do
|
|
42
|
+
NaN.should_not == NaN
|
|
43
|
+
NaN.should be_nan
|
|
44
|
+
NaN.object_id.should == NaN.object_id
|
|
45
|
+
(NaN + 1).object_id.should_not == NaN.object_id
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it "should produce NaN in all the operations except NaN**0 == 1" do
|
|
49
|
+
(NaN + 1).should be_nan
|
|
50
|
+
(NaN + Infinity).should be_nan
|
|
51
|
+
(NaN - 1).should be_nan
|
|
52
|
+
(NaN * 0).should be_nan
|
|
53
|
+
(NaN * Infinity).should be_nan
|
|
54
|
+
(NaN ** 0).should == 1 # <-- WTF? (Ruby 1.8.6 rel. 2007-03-13)
|
|
55
|
+
(NaN ** 1).should be_nan
|
|
56
|
+
(NaN ** Infinity).should be_nan
|
|
57
|
+
(NaN / 0).should be_nan
|
|
58
|
+
(NaN / 1).should be_nan
|
|
59
|
+
(NaN / Infinity).should be_nan
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
|
2
|
+
|
|
3
|
+
describe "Object#infinity?" do
|
|
4
|
+
it "should return false for the finite values" do
|
|
5
|
+
Object.should_not be_infinite
|
|
6
|
+
Object.new.should_not be_infinite
|
|
7
|
+
String.new.should_not be_infinite
|
|
8
|
+
Time.now.should_not be_infinite
|
|
9
|
+
:sym.should_not be_infinite
|
|
10
|
+
nil.should_not be_infinite
|
|
11
|
+
false.should_not be_infinite
|
|
12
|
+
true.should_not be_infinite
|
|
13
|
+
Float::MAX.should_not be_infinite
|
|
14
|
+
2.71828.should_not be_infinite
|
|
15
|
+
42.should_not be_infinite
|
|
16
|
+
(1..Infinity).should_not be_infinite # yep, this too.
|
|
17
|
+
end
|
|
18
|
+
it "should return true for infinite 'values'" do
|
|
19
|
+
Infinity.should be_infinite
|
|
20
|
+
(-Infinity).should be_infinite
|
|
21
|
+
(InfiniteString).should be_infinite
|
|
22
|
+
(InfiniteTime).should be_infinite
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
describe InfiniteString do
|
|
27
|
+
it "should be used in Range" do
|
|
28
|
+
(InfiniteString.."a").should be_a_kind_of(Range)
|
|
29
|
+
("a"..InfiniteString).should be_a_kind_of(Range)
|
|
30
|
+
(InfiniteString..InfiniteString).should be_a_kind_of(Range)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
describe InfiniteTime do
|
|
35
|
+
it "should be used in Range" do
|
|
36
|
+
(InfiniteTime..Time.now).should be_a_kind_of(Range)
|
|
37
|
+
(Time.now..InfiniteTime).should be_a_kind_of(Range)
|
|
38
|
+
(InfiniteTime..InfiniteTime).should be_a_kind_of(Range)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
|
2
|
+
|
|
3
|
+
describe "String#/" do
|
|
4
|
+
it "should concatenate strings with /" do
|
|
5
|
+
"lib"/"core_ext".should == "lib/core_ext"
|
|
6
|
+
"lib/core_ext"/"foo".should == "lib/core_ext/foo"
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
describe "String#modulize" do
|
|
11
|
+
|
|
12
|
+
it "if there is no module, leave nothing" do
|
|
13
|
+
"A".modulize.should == ""
|
|
14
|
+
"::A".modulize.should == ""
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "should leave single module" do
|
|
18
|
+
"A::B".modulize.should == "A"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "should leave multiple modules" do
|
|
22
|
+
"A::B::C".modulize.should == "A::B"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
end
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
|
2
|
+
|
|
3
|
+
describe "Empty chunked skiplist" do
|
|
4
|
+
before(:each) do
|
|
5
|
+
@cut_level = 4
|
|
6
|
+
@list = Skiplist.new({}, nil, @cut_level)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it "should make first node level first-level only" do
|
|
10
|
+
@list.head.level.should == 1
|
|
11
|
+
@list.insert("k","v", @cut_level + 1)
|
|
12
|
+
@list.head.level.should == 1
|
|
13
|
+
@list.head.forward[0].level.should == 1
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
describe "Chunked skiplist (variants)" do
|
|
20
|
+
|
|
21
|
+
before(:each) do
|
|
22
|
+
@cut_level = 16
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "should be valid with ascending level order" do
|
|
26
|
+
@list = Skiplist.new({}, nil, @cut_level)
|
|
27
|
+
(1..10).each do |i|
|
|
28
|
+
@list.insert("K#{i*10}", "V", i)
|
|
29
|
+
end
|
|
30
|
+
@list.should have(10).items
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "should be valid with descending level order" do
|
|
34
|
+
@list = Skiplist.new({}, nil, @cut_level)
|
|
35
|
+
(1..10).each do |i|
|
|
36
|
+
@list.insert("K#{i*10}", "V", 11 - i)
|
|
37
|
+
end
|
|
38
|
+
@list.should have(10).items
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "should be valid with fixed level order" do
|
|
42
|
+
@list = Skiplist.new({}, nil, @cut_level)
|
|
43
|
+
(1..10).each do |i|
|
|
44
|
+
@list.insert("K#{i*10}", "V", 15)
|
|
45
|
+
end
|
|
46
|
+
@list.should have(10).items
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
describe "Insertion into skiplist" do
|
|
53
|
+
|
|
54
|
+
before(:each) do
|
|
55
|
+
@cut_level = 4
|
|
56
|
+
@list = Skiplist.new({}, nil, @cut_level)
|
|
57
|
+
@levels_list = []
|
|
58
|
+
(0..9).each do |i|
|
|
59
|
+
@list.insert("K#{i*10}", "V", x = rand(@cut_level-1)+1)
|
|
60
|
+
@levels_list << x
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it "should return [self, nil] if not cut" do
|
|
65
|
+
a, b = @list.insert("K42", "L", @cut_level-1)
|
|
66
|
+
a.should == @list
|
|
67
|
+
b.should be_nil
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it "should cut list by middle-entered value" do
|
|
71
|
+
a, b = @list.insert("K42", "H", @cut_level)
|
|
72
|
+
a.should == @list
|
|
73
|
+
b.should be_a_kind_of(Skiplist)
|
|
74
|
+
(0..4).each do |i|
|
|
75
|
+
chunks_should_have_separate_values(a, b, "K#{i*10}", "V")
|
|
76
|
+
end
|
|
77
|
+
chunks_should_have_separate_values(b, a, "K42", "H")
|
|
78
|
+
(5..9).each do |i|
|
|
79
|
+
chunks_should_have_separate_values(b, a, "K#{i*10}", "V")
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def chunks_should_have_separate_values(a, b, a_key, a_value)
|
|
84
|
+
a.find(a_key).should == a_value
|
|
85
|
+
b.find(a_key).should == nil
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
=begin
|
|
90
|
+
random chunk writings, bad test. Come back to it in ChunkStore
|
|
91
|
+
describe "Chunked skiplist process" do
|
|
92
|
+
|
|
93
|
+
before(:all) do
|
|
94
|
+
@cut_level = 4
|
|
95
|
+
list = Skiplist.new({}, nil, @cut_level)
|
|
96
|
+
@lists = {list => 1}
|
|
97
|
+
n = ((1/Skiplist::PROBABILITY)**(@cut_level+2)).round
|
|
98
|
+
srand 12345
|
|
99
|
+
n.times do |i|
|
|
100
|
+
a, b = @lists.keys[rand(@lists.size)].insert(rand(100_000).to_s, "V")
|
|
101
|
+
@lists[a] = 1
|
|
102
|
+
@lists[b] = 1 if b
|
|
103
|
+
end
|
|
104
|
+
@lists = @lists.keys
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
it "should produce several chunks after many insertions" do
|
|
108
|
+
@lists.size.should > 1
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# TODO: move to separate description with narrow assertions
|
|
112
|
+
it "should keep all the nodes except the first one on a lower level in each chunk" do
|
|
113
|
+
counted_first_node = false
|
|
114
|
+
@lists.each do |list|
|
|
115
|
+
cut_level = list.map{|node| node.level }.max
|
|
116
|
+
counted_cut = false
|
|
117
|
+
puts list.to_s_levels
|
|
118
|
+
puts "------"
|
|
119
|
+
if cut_level < @cut_level
|
|
120
|
+
#puts list
|
|
121
|
+
#puts "------- #{cut_level}"
|
|
122
|
+
end
|
|
123
|
+
if cut_level < @cut_level && !counted_first_node
|
|
124
|
+
counted_first_node = true
|
|
125
|
+
else
|
|
126
|
+
#cut_level.should >= @cut_level
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
list.each do |node|
|
|
130
|
+
unless counted_cut && node.level == cut_level
|
|
131
|
+
counted_cut = true
|
|
132
|
+
else
|
|
133
|
+
if node.level >= @cut_level
|
|
134
|
+
#puts list
|
|
135
|
+
end
|
|
136
|
+
#node.level.should < @cut_level
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
end
|
|
143
|
+
=end
|
|
144
|
+
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
|
2
|
+
|
|
3
|
+
describe InvertedList, " with flat string attributes" do
|
|
4
|
+
|
|
5
|
+
before(:all) do
|
|
6
|
+
@il = InvertedList.new
|
|
7
|
+
@oleg_profile = new_doc('Profile', :name => 'Oleg',
|
|
8
|
+
:email => 'oleganza')
|
|
9
|
+
@yrashk_profile = new_doc('Profile', :name => 'Yurii',
|
|
10
|
+
:email => 'yrashk')
|
|
11
|
+
@article1 = new_doc('Article', :title => 'StrokeDB kicks ass',
|
|
12
|
+
:author => ('@#' + @yrashk_profile[:uuid]))
|
|
13
|
+
@article2 = new_doc('Article', :title => 'StrokeDB strikes back',
|
|
14
|
+
:date => '28 Jan 2008',
|
|
15
|
+
:author => ('@#' + @yrashk_profile[:uuid]))
|
|
16
|
+
@post1 = new_doc('Post', :title => 'Hello',
|
|
17
|
+
:date => '28 Jan 2008',
|
|
18
|
+
:author => ('@#' + @yrashk_profile[:uuid]))
|
|
19
|
+
|
|
20
|
+
insert_doc(@il, @oleg_profile)
|
|
21
|
+
insert_doc(@il, @yrashk_profile)
|
|
22
|
+
insert_doc(@il, @article1)
|
|
23
|
+
insert_doc(@il, @article2)
|
|
24
|
+
insert_doc(@il, @post1)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "should find objects by a single attribute" do
|
|
28
|
+
@il.find(:name => 'Oleg').should == [@oleg_profile[:uuid]].to_set
|
|
29
|
+
@il.find(:email => 'yrashk').should == [@yrashk_profile[:uuid]].to_set
|
|
30
|
+
@il.find(:meta => 'Article').should == [@article1[:uuid], @article2[:uuid]].to_set
|
|
31
|
+
@il.find(:version => @article1[:slots][:version]).should == [@article1[:uuid]].to_set
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "should not find object by a not matched attribute" do
|
|
35
|
+
@il.find(:name => 'Nobody').should == [ ].to_set
|
|
36
|
+
@il.find(:meta => 'NoMeta').should == [ ].to_set
|
|
37
|
+
@il.find(:version => 'no-version').should == [ ].to_set
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "should find objects by a pair of attributes" do
|
|
41
|
+
@il.find(:date => '28 Jan 2008', :title => 'Hello').should == [@post1[:uuid]].to_set
|
|
42
|
+
@il.find(:date => '28 Jan 2008', :meta => 'Article').should == [@article2[:uuid]].to_set
|
|
43
|
+
@il.find(:date => '28 Jan 2008', :author => ('@#' + @yrashk_profile[:uuid])).should == [@post1[:uuid], @article2[:uuid]].to_set
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it "should not find objects by a not matched pair of attributes" do
|
|
47
|
+
@il.find(:date => '28 Jan 2008', :title => 'StrokeDB kicks ass').should == [ ].to_set
|
|
48
|
+
@il.find(:date => '28 Jan 2008', :meta => 'Profile').should == [ ].to_set
|
|
49
|
+
@il.find(:date => '28 Jan 2008', :author => ('@#' + @oleg_profile[:uuid])).should == [ ].to_set
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it "should find objects by three attributes" do
|
|
53
|
+
@il.find(:date => '28 Jan 2008',
|
|
54
|
+
:author => ('@#' + @yrashk_profile[:uuid]),
|
|
55
|
+
:meta => 'Article'
|
|
56
|
+
).should == [ @article2[:uuid] ].to_set
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it "should not find objects by not matched three attributes" do
|
|
60
|
+
@il.find(:date => '28 Jan 2008',
|
|
61
|
+
:author => ('@#' + @oleg_profile[:uuid]),
|
|
62
|
+
:meta => 'Article'
|
|
63
|
+
).should == [ ].to_set
|
|
64
|
+
@il.find(:date => '42 Jan 2008',
|
|
65
|
+
:author => ('@#' + @yrashk_profile[:uuid]),
|
|
66
|
+
:meta => 'Article'
|
|
67
|
+
).should == [ ].to_set
|
|
68
|
+
@il.find(:date => '28 Jan 2008',
|
|
69
|
+
:author => ('@#' + @yrashk_profile[:uuid]),
|
|
70
|
+
:meta => 'Profile'
|
|
71
|
+
).should == [ ].to_set
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it "should delete doc from index" do
|
|
75
|
+
@il.find(:name => 'Oleg').should == [@oleg_profile[:uuid]].to_set
|
|
76
|
+
delete_doc(@il, @oleg_profile)
|
|
77
|
+
@il.find(:name => 'Oleg').should == [ ].to_set
|
|
78
|
+
@il.find(:email => 'yrashk').should == [@yrashk_profile[:uuid]].to_set
|
|
79
|
+
delete_doc(@il, @yrashk_profile)
|
|
80
|
+
@il.find(:email => 'yrashk').should == [ ].to_set
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
describe InvertedList, " with numeric attributes" do
|
|
86
|
+
|
|
87
|
+
before(:all) do
|
|
88
|
+
@il = InvertedList.new
|
|
89
|
+
@ps = []
|
|
90
|
+
@ps << new_doc('Point', :x => 0, :y => 0) # 0
|
|
91
|
+
@ps << new_doc('Point', :x => 10, :y => 50) # 1
|
|
92
|
+
@ps << new_doc('Point', :x => 50, :y => 50) # 2
|
|
93
|
+
@ps << new_doc('Point', :x => 200, :y => 10) # 3
|
|
94
|
+
@ps << new_doc('Point', :x => 500, :y => 10) # 4
|
|
95
|
+
@ps << new_doc('Point', :x => -500, :y => 10) # 5
|
|
96
|
+
@ps << new_doc('Point', :x => -20, :y => 10) # 6
|
|
97
|
+
@ps << new_doc('Point', :x => -2.1, :y => 10) # 7
|
|
98
|
+
@ps << new_doc('Point', :x => 20.6, :y => 10) # 8
|
|
99
|
+
|
|
100
|
+
@ps.each {|p| insert_doc(@il, p) }
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it "should find by positive value" do
|
|
104
|
+
@il.find(:x => 10).should == [@ps[1][:uuid]].to_set
|
|
105
|
+
@il.find(:x => 50).should == [@ps[2][:uuid]].to_set
|
|
106
|
+
@il.find(:x => 200).should == [@ps[3][:uuid]].to_set
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
it "should find by negative value" do
|
|
110
|
+
@il.find(:x => -500).should == [@ps[5][:uuid]].to_set
|
|
111
|
+
@il.find(:x => -20).should == [@ps[6][:uuid]].to_set
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it "should find by zero value" do
|
|
115
|
+
@il.find(:x => 0).should == [@ps[0][:uuid]].to_set
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Dangerous: 2.1 may suddenly appear as 2.0999999999996235 or like that
|
|
119
|
+
it "should find by float value" do
|
|
120
|
+
@il.find(:x => -2.1).should == [@ps[7][:uuid]].to_set
|
|
121
|
+
@il.find(:x => 20.6).should == [@ps[8][:uuid]].to_set
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
end
|
|
125
|
+
=begin
|
|
126
|
+
describe InvertedList, " with multivalue slots" do
|
|
127
|
+
before(:all) do
|
|
128
|
+
@il = InvertedList.new
|
|
129
|
+
@ab = new_doc(%w[A B])
|
|
130
|
+
@a = new_doc(%w[A])
|
|
131
|
+
@b = new_doc(%w[B])
|
|
132
|
+
@c = new_doc(%w[C])
|
|
133
|
+
insert_doc(@il, @ab)
|
|
134
|
+
insert_doc(@il, @a)
|
|
135
|
+
insert_doc(@il, @b)
|
|
136
|
+
insert_doc(@il, @c)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
it "should find multivalue objects by a single value" do
|
|
140
|
+
@il.find(:meta => proc{|v| v.include? 'A' }).should == [@a[:uuid], @ab[:uuid]].to_set
|
|
141
|
+
@il.find(:meta => proc{|v| v.include? 'B' }).should == [@b[:uuid], @ab[:uuid]].to_set
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
it "should not find by scalar value" do
|
|
145
|
+
@il.find(:meta => 'A').should == [ ].to_set
|
|
146
|
+
@il.find(:meta => 'B').should == [ ].to_set
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
it "should find multivalue objects with a complex predicate" do
|
|
150
|
+
@il.find(:meta => proc{|v| v.include?('A') && !v.include?('B') }).should == [@a[:uuid]].to_set
|
|
151
|
+
@il.find(:meta => proc{|v| v.include?('A') || v.include?('B') }).should ==
|
|
152
|
+
[@a[:uuid], @ab[:uuid], @b[:uuid]].to_set
|
|
153
|
+
@il.find(:meta => proc{|v| v.include?('A') && v.include?('B') }).should == [@ab[:uuid]].to_set
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
=end
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def new_doc(meta, slots = {})
|
|
160
|
+
slots[:meta] = meta
|
|
161
|
+
slots[:version] = 'v1' + rand(10000000).to_s
|
|
162
|
+
{:uuid => meta.to_s + '-' + rand(1000000).to_s, :slots => slots}
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def insert_doc(il, doc)
|
|
166
|
+
il.insert(doc[:slots], doc[:uuid])
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def delete_doc(il, doc)
|
|
170
|
+
il.delete(doc[:slots], doc[:uuid])
|
|
171
|
+
end
|
|
172
|
+
|