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.
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,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,8 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe "Symbol#/" do
4
+ it "should concatenate symbols with / as a string" do
5
+ :lib/:core_ext.should == "lib/core_ext"
6
+ :lib/:core_ext/:foo.should == "lib/core_ext/foo"
7
+ end
8
+ 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
+