strokedb 0.0.2.1 → 0.0.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (192) hide show
  1. data/README +18 -20
  2. data/bench.html +4001 -0
  3. data/bin/strokedb +14 -0
  4. data/examples/movies.rb +105 -0
  5. data/examples/movies2.rb +97 -0
  6. data/examples/strokewiki/README +28 -0
  7. data/examples/strokewiki/view/edit.xhtml +27 -0
  8. data/examples/strokewiki/view/new.xhtml +26 -0
  9. data/examples/strokewiki/view/pages.xhtml +27 -0
  10. data/examples/strokewiki/view/show.xhtml +40 -0
  11. data/examples/strokewiki/view/versions.xhtml +25 -0
  12. data/examples/strokewiki/wiki.rb +106 -0
  13. data/examples/todo.rb +92 -0
  14. data/lib/strokedb.rb +85 -0
  15. data/lib/{config → strokedb}/config.rb +14 -9
  16. data/lib/strokedb/console.rb +87 -0
  17. data/lib/strokedb/core_ext.rb +10 -0
  18. data/lib/{util/ext → strokedb/core_ext}/blank.rb +1 -1
  19. data/lib/{util/ext → strokedb/core_ext}/enumerable.rb +0 -0
  20. data/lib/{util/ext → strokedb/core_ext}/fixnum.rb +0 -0
  21. data/lib/strokedb/core_ext/float.rb +4 -0
  22. data/lib/{util/ext → strokedb/core_ext}/hash.rb +0 -0
  23. data/lib/strokedb/core_ext/infinity.rb +33 -0
  24. data/lib/strokedb/core_ext/kernel.rb +41 -0
  25. data/lib/strokedb/core_ext/object.rb +16 -0
  26. data/lib/{util/ext → strokedb/core_ext}/string.rb +28 -1
  27. data/lib/strokedb/core_ext/symbol.rb +13 -0
  28. data/lib/strokedb/data_structures.rb +5 -0
  29. data/lib/strokedb/data_structures/chunked_skiplist.rb +123 -0
  30. data/lib/{data_structures → strokedb/data_structures}/inverted_list.rb +0 -0
  31. data/lib/{data_structures → strokedb/data_structures}/point_query.rb +0 -0
  32. data/lib/strokedb/data_structures/simple_skiplist.rb +350 -0
  33. data/lib/{data_structures → strokedb/data_structures}/skiplist.rb +1 -1
  34. data/lib/{document → strokedb}/document.rb +180 -71
  35. data/lib/{document → strokedb/document}/callback.rb +0 -0
  36. data/lib/{document → strokedb/document}/delete.rb +2 -2
  37. data/lib/strokedb/document/dsl.rb +4 -0
  38. data/lib/{document → strokedb/document/dsl}/associations.rb +0 -0
  39. data/lib/{document → strokedb/document/dsl}/coercions.rb +0 -0
  40. data/lib/strokedb/document/dsl/meta_dsl.rb +7 -0
  41. data/lib/{document → strokedb/document/dsl}/validations.rb +26 -21
  42. data/lib/{document → strokedb/document/dsl}/virtualize.rb +0 -0
  43. data/lib/{document → strokedb/document}/meta.rb +92 -29
  44. data/lib/{document → strokedb/document}/slot.rb +17 -5
  45. data/lib/{document → strokedb/document}/util.rb +0 -0
  46. data/lib/{document → strokedb/document}/versions.rb +2 -2
  47. data/lib/strokedb/index.rb +2 -0
  48. data/lib/strokedb/nsurl.rb +24 -0
  49. data/lib/strokedb/store.rb +149 -0
  50. data/lib/strokedb/stores.rb +6 -0
  51. data/lib/{stores → strokedb/stores}/chainable_storage.rb +20 -14
  52. data/lib/strokedb/stores/file_storage.rb +118 -0
  53. data/lib/{stores/inverted_list_index → strokedb/stores}/inverted_list_file_storage.rb +50 -0
  54. data/lib/strokedb/stores/memory_storage.rb +80 -0
  55. data/lib/{stores → strokedb/stores}/remote_store.rb +10 -4
  56. data/lib/strokedb/sync.rb +4 -0
  57. data/lib/{sync → strokedb/sync}/chain_sync.rb +0 -0
  58. data/lib/{sync → strokedb/sync}/diff.rb +12 -1
  59. data/lib/{sync/stroke_diff → strokedb/sync/diff}/array.rb +1 -1
  60. data/lib/{sync/stroke_diff → strokedb/sync/diff}/default.rb +0 -0
  61. data/lib/{sync/stroke_diff → strokedb/sync/diff}/hash.rb +1 -1
  62. data/lib/{sync/stroke_diff → strokedb/sync/diff}/string.rb +1 -1
  63. data/lib/{sync → strokedb/sync}/lamport_timestamp.rb +0 -0
  64. data/lib/{sync → strokedb/sync}/store_sync.rb +15 -7
  65. data/lib/strokedb/transaction.rb +78 -0
  66. data/lib/{util → strokedb}/util.rb +14 -7
  67. data/lib/strokedb/util/attach_dsl.rb +29 -0
  68. data/lib/{util → strokedb/util}/blankslate.rb +0 -0
  69. data/lib/strokedb/util/class_optimization.rb +93 -0
  70. data/lib/{util → strokedb/util}/inflect.rb +0 -0
  71. data/lib/strokedb/util/java_util.rb +13 -0
  72. data/lib/{util → strokedb/util}/lazy_array.rb +0 -0
  73. data/lib/{util → strokedb/util}/lazy_mapping_array.rb +4 -0
  74. data/lib/{util → strokedb/util}/lazy_mapping_hash.rb +0 -0
  75. data/lib/{util → strokedb/util}/serialization.rb +21 -0
  76. data/lib/strokedb/util/uuid.rb +159 -0
  77. data/lib/{util → strokedb/util}/xml.rb +0 -0
  78. data/lib/{view → strokedb}/view.rb +2 -2
  79. data/lib/strokedb/volumes.rb +5 -0
  80. data/lib/strokedb/volumes/archive_volume.rb +165 -0
  81. data/lib/strokedb/volumes/block_volume.rb +169 -0
  82. data/lib/strokedb/volumes/distributed_pointer.rb +43 -0
  83. data/lib/strokedb/volumes/fixed_length_skiplist_volume.rb +109 -0
  84. data/lib/strokedb/volumes/map_volume.rb +268 -0
  85. data/meta/MANIFEST +175 -0
  86. data/script/console +2 -70
  87. data/spec/integration/remote_store_spec.rb +70 -0
  88. data/spec/integration/search_spec.rb +76 -0
  89. data/spec/integration/spec_helper.rb +1 -0
  90. data/spec/lib/spec_helper.rb +1 -0
  91. data/spec/lib/strokedb/config_spec.rb +250 -0
  92. data/spec/lib/strokedb/core_ext/blank_spec.rb +20 -0
  93. data/spec/lib/strokedb/core_ext/extract_spec.rb +42 -0
  94. data/spec/lib/strokedb/core_ext/float_spec.rb +62 -0
  95. data/spec/lib/strokedb/core_ext/infinity_spec.rb +40 -0
  96. data/spec/lib/strokedb/core_ext/spec_helper.rb +1 -0
  97. data/spec/lib/strokedb/core_ext/string_spec.rb +25 -0
  98. data/spec/lib/strokedb/core_ext/symbol_spec.rb +8 -0
  99. data/spec/lib/strokedb/data_structures/chunked_skiplist_spec.rb +144 -0
  100. data/spec/lib/strokedb/data_structures/inverted_list_spec.rb +172 -0
  101. data/spec/lib/strokedb/data_structures/simple_skiplist_spec.rb +200 -0
  102. data/spec/lib/strokedb/data_structures/skiplist_spec.rb +253 -0
  103. data/spec/lib/strokedb/data_structures/spec_helper.rb +1 -0
  104. data/spec/lib/strokedb/document/associations_spec.rb +319 -0
  105. data/spec/lib/strokedb/document/callbacks_spec.rb +134 -0
  106. data/spec/lib/strokedb/document/coercions_spec.rb +110 -0
  107. data/spec/lib/strokedb/document/document_spec.rb +1063 -0
  108. data/spec/lib/strokedb/document/meta_meta_spec.rb +30 -0
  109. data/spec/lib/strokedb/document/meta_spec.rb +435 -0
  110. data/spec/lib/strokedb/document/metaslot_spec.rb +43 -0
  111. data/spec/lib/strokedb/document/slot_spec.rb +130 -0
  112. data/spec/lib/strokedb/document/spec_helper.rb +1 -0
  113. data/spec/lib/strokedb/document/validations_spec.rb +1081 -0
  114. data/spec/lib/strokedb/document/virtualize_spec.rb +80 -0
  115. data/spec/lib/strokedb/nsurl_spec.rb +73 -0
  116. data/spec/lib/strokedb/spec_helper.rb +1 -0
  117. data/spec/lib/strokedb/stores/chained_storages_spec.rb +116 -0
  118. data/spec/lib/strokedb/stores/spec_helper.rb +1 -0
  119. data/spec/lib/strokedb/stores/store_spec.rb +201 -0
  120. data/spec/lib/strokedb/stores/transaction_spec.rb +107 -0
  121. data/spec/lib/strokedb/sync/chain_sync_spec.rb +43 -0
  122. data/spec/lib/strokedb/sync/diff_spec.rb +111 -0
  123. data/spec/lib/strokedb/sync/lamport_timestamp_spec.rb +174 -0
  124. data/spec/lib/strokedb/sync/slot_diff_spec.rb +164 -0
  125. data/spec/lib/strokedb/sync/spec_helper.rb +1 -0
  126. data/spec/lib/strokedb/sync/store_sync_spec.rb +181 -0
  127. data/spec/lib/strokedb/sync/stroke_diff/array_spec.rb +97 -0
  128. data/spec/lib/strokedb/sync/stroke_diff/complex_spec.rb +58 -0
  129. data/spec/lib/strokedb/sync/stroke_diff/hash_spec.rb +144 -0
  130. data/spec/lib/strokedb/sync/stroke_diff/scalar_spec.rb +23 -0
  131. data/spec/lib/strokedb/sync/stroke_diff/spec_helper.rb +25 -0
  132. data/spec/lib/strokedb/sync/stroke_diff/string_spec.rb +61 -0
  133. data/spec/lib/strokedb/util/attach_dsl_spec.rb +45 -0
  134. data/spec/lib/strokedb/util/inflect_spec.rb +14 -0
  135. data/spec/lib/strokedb/util/lazy_array_spec.rb +157 -0
  136. data/spec/lib/strokedb/util/lazy_mapping_array_spec.rb +174 -0
  137. data/spec/lib/strokedb/util/lazy_mapping_hash_spec.rb +92 -0
  138. data/spec/lib/strokedb/util/spec_helper.rb +1 -0
  139. data/spec/lib/strokedb/util/uuid_spec.rb +46 -0
  140. data/spec/lib/strokedb/view_spec.rb +228 -0
  141. data/spec/lib/strokedb/volumes/archive_volume_spec.rb +105 -0
  142. data/spec/lib/strokedb/volumes/block_volume_spec.rb +100 -0
  143. data/spec/lib/strokedb/volumes/distributed_pointer_spec.rb +14 -0
  144. data/spec/lib/strokedb/volumes/fixed_length_skiplist_volume_spec.rb +177 -0
  145. data/spec/lib/strokedb/volumes/map_volume_spec.rb +172 -0
  146. data/spec/lib/strokedb/volumes/spec_helper.rb +1 -0
  147. data/spec/regression/docref_spec.rb +94 -0
  148. data/spec/regression/meta_spec.rb +23 -0
  149. data/spec/regression/spec_helper.rb +1 -0
  150. data/spec/regression/sync_spec.rb +36 -0
  151. data/spec/spec.opts +7 -0
  152. data/spec/spec_helper.rb +37 -0
  153. data/spec/temp/storages/TIMESTAMP +1 -0
  154. data/spec/temp/storages/UUID +1 -0
  155. data/spec/temp/storages/database-sync/TIMESTAMP +1 -0
  156. data/spec/temp/storages/database-sync/UUID +1 -0
  157. data/spec/temp/storages/database-sync/config +1 -0
  158. data/spec/temp/storages/database-sync/file/LAST +1 -0
  159. data/spec/temp/storages/database-sync/file/bd/f6/bdf675e5-8a7b-494e-97f2-f74a14ccd95d.av +0 -0
  160. data/spec/temp/storages/database-sync/file/uindex.wal +0 -0
  161. data/spec/temp/storages/database-sync/inverted_list_file/INVERTED_INDEX +1 -0
  162. data/spec/temp/storages/inverted_list_storage/INVERTED_INDEX +0 -0
  163. data/strokedb.gemspec +120 -0
  164. data/task/benchmark.task +9 -0
  165. data/task/ditz.task +30 -0
  166. data/task/echoe.rb +17 -0
  167. data/task/rcov.task +50 -0
  168. data/task/rdoc.task +10 -0
  169. data/task/rspec.task +0 -0
  170. data/vendor/java_inline.rb +106 -0
  171. data/vendor/rbmodexcl/mrimodexcl.rb +82 -0
  172. data/vendor/rbmodexcl/rbmodexcl.rb +5 -0
  173. data/vendor/rbmodexcl/rbxmodexcl.rb +48 -0
  174. data/vendor/rbmodexcl/spec/unextend_spec.rb +50 -0
  175. data/vendor/rbmodexcl/spec/uninclude_spec.rb +26 -0
  176. metadata +271 -79
  177. data/CONTRIBUTORS +0 -7
  178. data/CREDITS +0 -13
  179. data/bin/sdbc +0 -2
  180. data/lib/init.rb +0 -57
  181. data/lib/stores/inverted_list_index/inverted_list_index.rb +0 -49
  182. data/lib/stores/skiplist_store/chunk.rb +0 -119
  183. data/lib/stores/skiplist_store/chunk_storage.rb +0 -21
  184. data/lib/stores/skiplist_store/file_chunk_storage.rb +0 -44
  185. data/lib/stores/skiplist_store/memory_chunk_storage.rb +0 -37
  186. data/lib/stores/skiplist_store/skiplist_store.rb +0 -217
  187. data/lib/stores/store.rb +0 -5
  188. data/lib/sync/stroke_diff/stroke_diff.rb +0 -9
  189. data/lib/util/ext/object.rb +0 -8
  190. data/lib/util/java_util.rb +0 -9
  191. data/lib/util/trigger_partition.rb +0 -136
  192. data/strokedb.rb +0 -75
@@ -0,0 +1,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
+