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,200 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+
4
+ describe "Skiplist serialization", :shared => true do
5
+ it "should correctly load what it dumped" do
6
+ dump1 = @list.marshal_dump
7
+ newlist = @list.class.allocate
8
+ dump2 = newlist.marshal_load(dump1).marshal_dump
9
+ dump1.should == dump2
10
+ end
11
+
12
+ it "should correctly load to_a results" do
13
+ arr1 = @list.to_a
14
+ newlist = @list.class.from_a(arr1)
15
+ arr2 = newlist.to_a
16
+ arr1.should == arr2
17
+ end
18
+ end
19
+
20
+ SimpleSkiplist.with_optimizations(OPTIMIZATIONS) do |lang|
21
+
22
+ describe "Empty SimpleSkiplist [#{lang}]" do
23
+
24
+ before(:each) do
25
+ @maxlevel = 8
26
+ @probability = 0.5
27
+ @list = SimpleSkiplist.new(nil, :maxlevel => @maxlevel, :probability => @probability)
28
+ end
29
+
30
+ it "should be empty" do
31
+ @list.should be_empty
32
+ end
33
+
34
+ it "should be serialized with marshal_dump" do
35
+ @list.marshal_dump.should == {
36
+ :options => {
37
+ :probability => @probability,
38
+ :maxlevel => @maxlevel
39
+ },
40
+ :raw_list => [
41
+ [[nil]*@maxlevel, nil, nil]
42
+ ]
43
+ }
44
+ end
45
+
46
+ it "should find nil in a empty skiplist" do
47
+ @list.find("xx").should == nil
48
+ @list.find("").should == nil
49
+ end
50
+
51
+ it_should_behave_like "Skiplist serialization"
52
+ end
53
+
54
+
55
+ describe "Inserting in a skiplist [#{lang}]" do
56
+
57
+ before(:each) do
58
+ @maxlevel = 8
59
+ @probability = 0.5
60
+ @list = SimpleSkiplist.new(nil, :maxlevel => @maxlevel, :probability => @probability)
61
+ end
62
+
63
+ it "should insert empty key in place of default head" do
64
+ @list.insert("", 42, 1).should == @list
65
+ @list.find("").should == 42
66
+ @list.find("-").should == nil
67
+ @list.to_a.should == [["", 42]]
68
+ end
69
+
70
+ it "should insert non-empty key" do
71
+ @list.insert("x", 42, 1).should == @list
72
+ @list.find("").should == nil
73
+ @list.find("x").should == 42
74
+ @list.find("-").should == nil
75
+ end
76
+
77
+ it "should correctly insert keys in an ascending level order" do
78
+ 1.upto(@maxlevel) do |i|
79
+ k = "x#{i}"
80
+ @list.insert(k, k, i).should == @list
81
+ @list.find("").should == nil
82
+ @list.find(k).should == k
83
+ @list.find("-").should == nil
84
+ end
85
+ # repeat
86
+ 1.upto(@maxlevel) do |i|
87
+ k = "x#{i}"
88
+ @list.find(k).should == k
89
+ end
90
+ end
91
+
92
+ it "should correctly insert keys in a descending level order" do
93
+ @maxlevel.downto(1) do |i|
94
+ k = "x#{@maxlevel-i}"
95
+ @list.insert(k, k, i).should == @list
96
+ @list.find("").should == nil
97
+ @list.find(k).should == k
98
+ @list.find("-").should == nil
99
+ end
100
+ # repeat
101
+ @maxlevel.downto(1) do |i|
102
+ k = "x#{@maxlevel-i}"
103
+ @list.find(k).should == k
104
+ end
105
+ end
106
+ end
107
+
108
+
109
+ describe "Big skiplist [#{lang}]" do
110
+ before(:each) do
111
+ @maxlevel = 8
112
+ @probability = 0.5
113
+ @list = SimpleSkiplist.new(nil, :maxlevel => @maxlevel, :probability => @probability)
114
+ 1000.times do
115
+ k = rand(2**64).to_s
116
+ v = k
117
+ @list.insert(k, v)
118
+ end
119
+ end
120
+
121
+ it_should_behave_like "Skiplist serialization"
122
+
123
+ it "should support to_a with sorted key-value pairs" do
124
+ ary = @list.to_a
125
+ ary.should == ary.sort{|a,b| a[0] <=> b[0] }
126
+ ary.size.should == 1000
127
+ end
128
+
129
+ it "should have iterate pairs with #each" do
130
+ c = []
131
+ @list.each do |key, value|
132
+ c << [key, value]
133
+ end
134
+ c.should have_at_least(10).items
135
+ c[0..10].each do |a|
136
+ a[0].should == a[1] # key == value
137
+ end
138
+ c.should == c.sort{|a, b| a[0] <=> b[0] } # sorted order
139
+ end
140
+
141
+ end
142
+
143
+
144
+ describe "SimpleSkiplist#first_key [#{lang}]" do
145
+ before(:each) do
146
+ @maxlevel = 8
147
+ @probability = 0.5
148
+ @list = SimpleSkiplist.new(nil, :maxlevel => @maxlevel, :probability => @probability)
149
+ end
150
+ it "should return nil for empty skiplist" do
151
+ @list.first_key.should == nil
152
+ end
153
+ it "should return key for non-empty skiplist" do
154
+ @list.insert("b", "data1")
155
+ @list.first_key.should == "b"
156
+ @list.insert("c", "data2")
157
+ @list.first_key.should == "b"
158
+ end
159
+ end
160
+
161
+
162
+ describe "SimpleSkiplist#find_nearest [#{lang}]" do
163
+ before(:each) do
164
+ @maxlevel = 8
165
+ @probability = 0.5
166
+ @list = SimpleSkiplist.new(nil, :maxlevel => @maxlevel, :probability => @probability)
167
+ end
168
+ it "should find nil in empty skiplist" do
169
+ @list.find_nearest("a").should == nil
170
+ @list.find_nearest("").should == nil
171
+ @list.find_nearest(nil).should == nil
172
+ end
173
+ it "should find exact value if it is present" do
174
+ @list.insert("b", "B")
175
+ @list.insert("f", "F")
176
+ @list.find_nearest("b").should == "B"
177
+ @list.find_nearest("f").should == "F"
178
+ end
179
+ it "should find nearest value or nil" do
180
+ @list.insert("b", "B")
181
+ @list.insert("f", "F")
182
+ @list.find_nearest("a").should == nil
183
+ @list.find_nearest("c").should == "B"
184
+ @list.find_nearest("g").should == "F"
185
+ end
186
+ it "should always find empty-string key if nothing found" do
187
+ @list.insert("", "Empty")
188
+ @list.insert("b", "B")
189
+ @list.insert("f", "F")
190
+ @list.find_nearest("a").should == "Empty"
191
+ @list.find_nearest("c").should == "B"
192
+ @list.find_nearest("g").should == "F"
193
+ end
194
+ end
195
+ end
196
+
197
+ def raw_list(list)
198
+ list.marshal_dump[:raw_list]
199
+ end
200
+
@@ -0,0 +1,253 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe "Non-empty skiplist" do
4
+
5
+ before(:each) do
6
+ @list = Skiplist.new("a" => "1",
7
+ "aa" => "2",
8
+ "aaa" => "3",
9
+ "p" => "4",
10
+ "123.1" => "v1",
11
+ "123.2" => "v2",
12
+ "123" => "v0")
13
+ end
14
+
15
+ it "should not be empty" do
16
+ @list.should_not be_empty
17
+ end
18
+
19
+ it "should have size" do
20
+ @list.should have(7).items
21
+ end
22
+
23
+ it "should find" do
24
+ @list.find("a").should == "1"
25
+ @list.find("aaa").should == "3"
26
+ end
27
+
28
+ it "should find entries with prefix" do
29
+ @list.find_all_with_prefix("123").to_set.should == ["v1","v2","v0"].to_set
30
+ end
31
+
32
+ it "should find default value if search with prefix returns nothing" do
33
+ @list.find_all_with_prefix("nothinglike123").should == []
34
+ end
35
+
36
+ it "should return default value if nothing found" do
37
+ @list.find("404").should be_nil
38
+ end
39
+
40
+ it "should give local default value if nothing found" do
41
+ @list.find("404", :default_value).should == :default_value
42
+ end
43
+
44
+ it "should insert data" do
45
+ @list.insert("b", "3.5")
46
+ @list.find("b").should == "3.5"
47
+ end
48
+
49
+ it "should replace data" do
50
+ @list.insert("aaa", "3.5")
51
+ @list.find("aaa").should == "3.5"
52
+ end
53
+
54
+ it "should delete node by key" do
55
+ @list.delete("aaa").should == "3"
56
+ @list.find("aaa").should be_nil
57
+ end
58
+
59
+ it "should not delete non-existent key" do
60
+ @list.find("404").should be_nil
61
+ @list.delete("404").should be_nil
62
+ @list.find("404").should be_nil
63
+ end
64
+
65
+ it "should find the nearest key" do
66
+ @list.find_nearest("0").should == "v0"
67
+ @list.find_nearest("a").should == "1"
68
+ @list.find_nearest("aa").should == "2"
69
+ @list.find_nearest("aa0").should == "2"
70
+ @list.find_nearest("aaa").should == "3"
71
+ @list.find_nearest("ab").should == "3"
72
+ @list.find_nearest("d").should == "3"
73
+ @list.find_nearest("xxx").should == "4"
74
+ end
75
+
76
+ end
77
+
78
+
79
+ describe "Skiplist with duplicate keys" do
80
+
81
+ before(:all) do
82
+ @list = Skiplist.new({}, nil, nil, false)
83
+ @list.insert("a", "v1")
84
+ @list.insert("a", "v2")
85
+ @list.insert("a", "v3")
86
+ end
87
+
88
+ it "should find first value" do
89
+ @list.find("a").should == 'v1'
90
+ end
91
+
92
+ it "should find node iterator" do
93
+ @list.find_node("a").value.should == 'v1'
94
+ @list.find_node("a").next.value.should == 'v2'
95
+ @list.find_node("a").next.next.value.should == 'v3'
96
+ end
97
+
98
+ end
99
+
100
+ describe "Skiplist (cut)" do
101
+
102
+ before(:each) do
103
+ @chunk = Skiplist.new({}, nil, 4)
104
+ @chunk.insert('500', 'V', 2)
105
+ end
106
+
107
+ it "should find single value" do
108
+ @chunk.find('500').should == 'V'
109
+ @chunk.size.should == 1
110
+ end
111
+ [['low level',1],['cut level',1],['high level',6]].each do |t, l|
112
+ it "should insert #{t} item into the start" do
113
+ a, b = @chunk.insert('200', 'W', l)
114
+ a.find('200').should == 'W'
115
+ a.find('500').should == 'V'
116
+ a.should == @chunk
117
+ b.should be_nil
118
+ @chunk.size.should == 2
119
+ end
120
+ end
121
+
122
+ it "should cut when high level item inserted in the middle" do
123
+ a, b = @chunk.insert('600', 'W', 6)
124
+ a.find('500').should == 'V'
125
+ a.find('600').should be_nil
126
+ a.should == @chunk
127
+ a.size.should == 1
128
+ b.should be_kind_of(Skiplist)
129
+ b.find('500').should be_nil
130
+ b.find('600').should == 'W'
131
+ b.size.should == 1
132
+ end
133
+
134
+ it "should cut when high level item inserted in the middle, but several hi-level items in the start" do
135
+ a, b = @chunk.insert('300', 'X', 6)
136
+ a, b = @chunk.insert('200', 'Y', 5)
137
+ a, b = @chunk.insert('600', 'W', 6)
138
+ a.find('500').should == 'V'
139
+ a.find('300').should == 'X'
140
+ a.find('200').should == 'Y'
141
+ a.find('600').should be_nil
142
+ a.should == @chunk
143
+ a.size.should == 3
144
+ b.should be_kind_of(Skiplist)
145
+ b.find('500').should be_nil
146
+ b.find('300').should be_nil
147
+ b.find('200').should be_nil
148
+ b.find('600').should == 'W'
149
+ b.size.should == 1
150
+ end
151
+
152
+
153
+ end
154
+
155
+ describe "Empty big skiplist" do
156
+
157
+ before(:each) do
158
+ @list = Skiplist.new
159
+ end
160
+
161
+ it "should be empty" do
162
+ @list.should be_empty
163
+ @list.should have(0).items
164
+ end
165
+
166
+ it "should be empty with #each iteratpr" do
167
+ a = b = "each{ } did not yield"
168
+ @list.each{|n| a = "each{ } did yield!" }
169
+ a.should == b
170
+ end
171
+
172
+ it "should not find anything" do
173
+ @list.find("a").should be_nil
174
+ @list.find("").should be_nil
175
+ @list.find("aaa").should be_nil
176
+ @list.find(123).should be_nil
177
+ @list.find(-1).should be_nil
178
+ end
179
+
180
+ it "should not delete anything" do
181
+ @list.delete("a").should be_nil
182
+ @list.delete("a").should be_nil
183
+ @list.delete("").should be_nil
184
+ @list.delete("aaa").should be_nil
185
+ @list.delete(123).should be_nil
186
+ @list.delete(-1).should be_nil
187
+ end
188
+ end
189
+
190
+
191
+
192
+ describe "Non-empty big skiplist" do
193
+
194
+ before(:each) do
195
+ a = []
196
+ 100.times { |i|
197
+ a << "#{i}"
198
+ a << "#{rand(100)}"
199
+ }
200
+ @list = Skiplist.new(Hash[*a])
201
+ end
202
+
203
+ it "should contain all the items" do
204
+ #puts @list.to_s_levels
205
+ end
206
+ end
207
+
208
+
209
+
210
+ describe "Skiplist search" do
211
+ before(:each) do
212
+ @times = 100
213
+ @start = 128
214
+ @ratio = 2
215
+ @lists = [@start, @start*@ratio, @start*@ratio*@ratio].map do |len|
216
+ list = Skiplist.new
217
+ len.times do |i|
218
+ list.insert(i, rand)
219
+ end
220
+ list
221
+ end
222
+ end
223
+
224
+ it "should be O(log(n))" do
225
+ t1 = time(@times, @lists[0])
226
+ t2 = time(@times, @lists[1])
227
+ t3 = time(@times, @lists[2])
228
+
229
+ r1 = Math.log(t2/t1)
230
+ r2 = Math.log(t3/t2)
231
+
232
+ #p [t1, t2, t3]
233
+ #p [r1, r2]
234
+
235
+ # r1.should == r2
236
+ end
237
+
238
+ def time(n, list)
239
+ GC.start
240
+ t = Time.now
241
+ s = list.size
242
+ n.times { list.find(rand(s)) }
243
+ Time.now - t
244
+ ensure
245
+ GC.start
246
+ end
247
+ end
248
+
249
+
250
+
251
+
252
+
253
+