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,92 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe "LazyMappingHash instance" do
4
+
5
+ before(:each) do
6
+ @lash = LazyMappingHash.new
7
+ end
8
+
9
+ it "should have class Hash" do
10
+ @lash.class.should == Hash
11
+ end
12
+
13
+ it "should be inherited from Hash" do
14
+ @lash.class.ancestors.first.should == Hash
15
+ end
16
+
17
+ it "should match case expressions" do
18
+ @lash.should be_a_kind_of(Hash)
19
+ end
20
+ end
21
+
22
+ describe "LazyMappingHash instance with block specified" do
23
+ before(:each) do
24
+ @original = Hash[1,2,3,4,5,6]
25
+ @decoder = proc {|k| k.is_a?(Hash) && k[:struct] || k }
26
+ @encoder = proc {|k| {:struct => k} }
27
+
28
+ @lash = LazyMappingHash.new(@original).map_with(&@encoder).unmap_with(&@decoder)
29
+ end
30
+
31
+ it "should call mapping proc on #keys" do
32
+ @lash.keys.should == @original.keys.map {|k| @encoder.call(k)}
33
+ end
34
+
35
+ it "should call mapping proc on #values" do
36
+ @lash.values.should == @original.values.map {|k| @encoder.call(k)}
37
+ end
38
+
39
+ it "should call unmapping proc on #[key]=" do
40
+ @lash[1] = { :struct => :x }
41
+ Hash[@lash][1].should == :x
42
+ @lash[{:struct => :x}] = 1
43
+ Hash[@lash][:x].should == 1
44
+ end
45
+
46
+ it "should call mapping proc on #[key]" do
47
+ @lash[1].should == @encoder.call(@original[1])
48
+ @lash[2].should == @encoder.call(@original[2])
49
+ end
50
+
51
+ it "should call mapping proc on #[mapped_key]" do
52
+ @lash[@encoder.call(1)].should == @encoder.call(@original[1])
53
+ @lash[@encoder.call(2)].should == @encoder.call(@original[2])
54
+ end
55
+
56
+ it "should yield mapped key/value in #each block" do
57
+ orig_kv = []
58
+ lash_kv = []
59
+ @original.each do |k, v|
60
+ orig_kv << [@encoder.call(k), @encoder.call(v)]
61
+ end
62
+ @lash.each do |k, v|
63
+ lash_kv << [k,v]
64
+ end
65
+ orig_kv.should == lash_kv
66
+ end
67
+
68
+ it "should yield mapped key/value in #map block" do
69
+ orig_kv = @original.map do |k, v|
70
+ [@encoder.call(k), @encoder.call(v)]
71
+ end
72
+ lash_kv = @lash.map do |k, v|
73
+ [k, v]
74
+ end
75
+ orig_kv.should == lash_kv
76
+ end
77
+
78
+ it "should yield mapped key/value in #zip block (lash.zip(original))" do
79
+ orig_kv = []
80
+ lash_kv = []
81
+ @original.zip(@original) do |kv1, kv2|
82
+ orig_kv << [kv1.map{|e| @encoder.call(e)}, kv2]
83
+ end
84
+ @lash.zip(@original) do |kv1, kv2|
85
+ lash_kv << [kv1, kv2]
86
+ end
87
+ orig_kv.should == lash_kv
88
+ end
89
+
90
+ # TODO: zip support
91
+
92
+ end
@@ -0,0 +1 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
@@ -0,0 +1,46 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe "String UUID" do
4
+ it "should have specific format" do
5
+ 1000.times do
6
+ uuid = Util::random_uuid
7
+ uuid.should =~ /^#{UUID_RE}$/
8
+ end
9
+ end
10
+ it "should be converted to raw string" do
11
+ "00000000-0000-0000-0000-000000000010".to_raw_uuid.should == "\x00"*15 + "\x10"
12
+ "ffffffff-ffff-ffff-ffff-ffffffffffff".to_raw_uuid.should == "\xff"*16
13
+ "00000000-0000-0000-ffff-ffffffffffff".to_raw_uuid.should == "\x00"*8 + "\xff"*8
14
+ end
15
+ end
16
+
17
+ describe "Raw UUID" do
18
+ it "should have specific format" do
19
+ 1000.times do
20
+ uuid = Util::random_uuid_raw
21
+ uuid.should be_an_instance_of(String)
22
+ uuid.size.should == 16
23
+ end
24
+ end
25
+ it "should be converted to formatted string" do
26
+ ("\x00"*15 + "\x10").to_formatted_uuid.should == "00000000-0000-0000-0000-000000000010"
27
+ ("\xff"*16).to_formatted_uuid.should == "ffffffff-ffff-ffff-ffff-ffffffffffff"
28
+ ("\x00"*8 + "\xff"*8).to_formatted_uuid.should == "00000000-0000-0000-ffff-ffffffffffff"
29
+ end
30
+ end
31
+
32
+ describe "UUID String conversion" do
33
+ it "should convert raw to formatted and back" do
34
+ 1000.times do
35
+ raw = Util::random_uuid_raw
36
+ raw.to_formatted_uuid.to_raw_uuid.should == raw
37
+ end
38
+ end
39
+ it "should convert formatted to raw and back" do
40
+ 1000.times do
41
+ fmt = Util::random_uuid
42
+ fmt.to_raw_uuid.to_formatted_uuid.should == fmt
43
+ end
44
+ end
45
+ end
46
+
@@ -0,0 +1,228 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe "View without map_with and reduce_with blocks" do
4
+
5
+ before(:each) do
6
+ setup_default_store
7
+ setup_index
8
+ @view = View.new(:name => "without block")
9
+ ViewCut.document # this is to ensure that ViewCut document is created prior to emitting more data in cuts
10
+ end
11
+
12
+ it "should return all documents plus Meta and View" do
13
+ @documents = []
14
+ 10.times do |i|
15
+ @documents << Document.create!(:i => i)
16
+ end
17
+ @view.emit.to_a.sort_by {|doc| doc.uuid}.should == (@documents + [Meta.document,View.document,ViewCut.document]).sort_by {|doc| doc.uuid}
18
+ end
19
+
20
+ end
21
+
22
+ describe "View with map_with (without extra arguments)" do
23
+
24
+ before(:each) do
25
+ setup_default_store
26
+ setup_index
27
+ @view = View.new(:name => "with map_with (without extra arguments)").map_with {|doc| doc.slotnames.include?('i') ? doc : nil}
28
+ ViewCut.document # this is to ensure that ViewCut document is created prior to emitting more data in cuts
29
+ end
30
+
31
+ it "should return all documents plus three nils" do
32
+ @documents = []
33
+ 10.times do |i|
34
+ @documents << Document.create!(:i => i)
35
+ end
36
+ @view.emit.to_a.sort_by {|doc| doc.nil? ? "0" : doc.uuid}.should == (@documents + [nil,nil,nil]).sort_by {|doc| doc.nil? ? "0" : doc.uuid}
37
+ end
38
+
39
+ end
40
+
41
+ describe "View with map_with (with extra arguments)" do
42
+
43
+ before(:each) do
44
+ setup_default_store
45
+ setup_index
46
+ @view = View.new(:name => "with map_with (with extra arguments)").map_with {|doc,slotname| doc.slotnames.include?(slotname.to_s) ? doc : nil}
47
+ ViewCut.document # this is to ensure that ViewCut document is created prior to emitting more data in cuts
48
+ end
49
+
50
+ it "should return all documents plus three nils" do
51
+ @documents = []
52
+ 10.times do |i|
53
+ @documents << Document.create!(:i => i)
54
+ end
55
+ @view.emit(:i).to_a.sort_by {|doc| doc.nil? ? "0" : doc.uuid}.should == (@documents + [nil,nil,nil]).sort_by {|doc| doc.nil? ? "0" : doc.uuid}
56
+ end
57
+
58
+ end
59
+
60
+ describe "View with map_with and reduce_with" do
61
+
62
+ before(:each) do
63
+ setup_default_store
64
+ setup_index
65
+ @view = View.new(:name => "with map_with and reduce_with").map_with {|doc| doc.slotnames.include?('i') ? doc : nil}.reduce_with{|doc| !doc.nil? }
66
+ ViewCut.document # this is to ensure that ViewCut document is created prior to emitting more data in cuts
67
+ end
68
+
69
+ it "should return all documents" do
70
+ @documents = []
71
+ 10.times do |i|
72
+ @documents << Document.create!(:i => i)
73
+ end
74
+ @view.emit.to_a.sort_by {|doc| doc.uuid}.should == @documents.sort_by {|doc| doc.uuid}
75
+ end
76
+
77
+ end
78
+
79
+ describe "View with reduce_with" do
80
+
81
+ before(:each) do
82
+ setup_default_store
83
+ setup_index
84
+ @view = View.new(:name => "with reduce_with").reduce_with{|doc| doc.slotnames.include?('i') }
85
+ ViewCut.document # this is to ensure that ViewCut document is created prior to emitting more data in cuts
86
+ end
87
+
88
+ it "should return all documents" do
89
+ @documents = []
90
+ 10.times do |i|
91
+ @documents << Document.create!(:i => i)
92
+ end
93
+ @view.emit.to_a.sort_by {|doc| doc.uuid}.should == @documents.sort_by {|doc| doc.uuid}
94
+ end
95
+
96
+ end
97
+
98
+ describe "View with reduce_with (with extra arguments)" do
99
+
100
+ before(:each) do
101
+ setup_default_store
102
+ setup_index
103
+ @view = View.new(:name => "with reduce_with (with extra arguments)").reduce_with {|doc,slotname| doc.slotnames.include?(slotname.to_s) }
104
+ ViewCut.document # this is to ensure that ViewCut document is created prior to emitting more data in cuts
105
+ end
106
+
107
+ it "should return all documents plus two nils" do
108
+ @documents = []
109
+ 10.times do |i|
110
+ @documents << Document.create!(:i => i)
111
+ end
112
+ @view.emit(:i).to_a.sort_by {|doc| doc.uuid}.should == @documents.sort_by {|doc| doc.uuid}
113
+ end
114
+
115
+ end
116
+
117
+ describe "View" do
118
+
119
+ before(:each) do
120
+ setup_default_store
121
+ setup_index
122
+ @view = View.new(:name => "incremental view").reduce_with{|doc| doc.slotnames.include?('i') }
123
+ ViewCut.document # this is to ensure that ViewCut document is created prior to emitting more data in cuts
124
+ end
125
+
126
+ it "should make documents VersionedDocuments" do
127
+ @documents = []
128
+ 10.times do |i|
129
+ @documents << Document.create!(:i => i)
130
+ end
131
+ @view.emit.to_a.each {|d| d.should be_a_kind_of(VersionedDocument)}
132
+ end
133
+
134
+ it "should be able to return new documents incrementally" do
135
+ @documents = []
136
+ 10.times do |i|
137
+ @documents << Document.create!(:i => i)
138
+ end
139
+ cut = @view.emit
140
+ @documents = []
141
+ 10.times do |i|
142
+ @documents << Document.create!(:i => i+100)
143
+ end
144
+ a = cut.emit.to_a
145
+ a.sort_by {|doc| doc.uuid }.should == @documents.sort_by {|doc| doc.uuid }
146
+ a.each {|d| d.should be_a_kind_of(VersionedDocument)} # make sure next emit produces VersionedDocuments as well
147
+ end
148
+
149
+ it "should be able to return new document heads incrementally" do
150
+ @documents = []
151
+ 10.times do |i|
152
+ @documents << Document.create!(:i => i)
153
+ end
154
+ cut = @view.emit
155
+ new_docs = @documents.map {|doc| doc.new_slot = "new"; doc.save!}
156
+ a = cut.emit.to_a
157
+ a.sort_by {|doc| doc.uuid }.should == new_docs.sort_by {|doc| doc.uuid }
158
+ end
159
+
160
+ it "should be able to return new document versions incrementally if told so" do
161
+ @documents = []
162
+ 10.times do |i|
163
+ @documents << Document.create!(:i => i)
164
+ end
165
+ cut = @view.emit
166
+ @view.include_versions = true
167
+ @view.save!
168
+ new_docs = @documents.map {|doc| doc.new_slot = "new"; doc.save!}
169
+ docs = @documents.map {|doc| doc.reload }
170
+ a = cut.emit.to_a
171
+ a.sort_by {|doc| doc.uuid }.should == (new_docs+docs).sort_by {|doc| doc.uuid }
172
+ end
173
+
174
+ end
175
+
176
+ describe "Newly created View" do
177
+
178
+ before(:each) do
179
+ setup_default_store
180
+ setup_index
181
+ @view = View.new
182
+ ViewCut.document # this is to ensure that ViewCut document is created prior to emitting more data in cuts
183
+ end
184
+
185
+ it "should reference first cut as last cut when it is saved" do
186
+ cut = @view.emit
187
+ cut.save!
188
+ @view.last_cut.should == cut
189
+ end
190
+
191
+ it "save view on first cut save" do
192
+ cut = @view.emit
193
+ cut.save!
194
+ @view.should_not be_new
195
+ end
196
+
197
+ end
198
+
199
+ describe "View with cut(s) available" do
200
+
201
+ before(:each) do
202
+ setup_default_store
203
+ setup_index
204
+ @view = View.new
205
+ ViewCut.document # this is to ensure that ViewCut document is created prior to emitting more data in cuts
206
+ @cut = @view.emit
207
+ @cut.save!
208
+ end
209
+
210
+ it "should refer to newly emitted cut as last cut (when it is saved)" do
211
+ new_cut = @cut.emit
212
+ @view.reload.last_cut.should == @cut
213
+ new_cut.save!
214
+ @view.reload.last_cut.should == new_cut
215
+ end
216
+
217
+ it "should not refer to newly emitted cut as last cut (when it is saved) if this cut isn't really last" do
218
+ new_cut = @cut.emit
219
+ new_cut.save!
220
+ @view.reload.last_cut.should == new_cut
221
+ another_cut = @cut.emit
222
+ another_cut.save!
223
+ @view.reload.last_cut.should == new_cut.reload # we are reloading new_cut to let it have DocRefs instead of loaded documents
224
+ # just for the sake of this comparison
225
+ # However TODO: investigate this
226
+ end
227
+
228
+ end
@@ -0,0 +1,105 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe ArchiveVolume, "initialization" do
4
+
5
+ before(:all) do
6
+ FileUtils.rm_rf TEMP_STORAGES + '/archive_volume_spec'
7
+ end
8
+
9
+ before(:each) do
10
+ @path = TEMP_STORAGES + '/archive_volume_spec'
11
+ @size = 64*1024
12
+ @options = {:size => @size, :path => @path}
13
+ end
14
+
15
+ it "should go well with raw uuid" do
16
+ raw_uuid = Util.random_uuid_raw
17
+ ArchiveVolume.new(@options.merge(:uuid => raw_uuid)).uuid.should == raw_uuid.to_formatted_uuid
18
+ end
19
+
20
+ it "should go well with formatted uuid" do
21
+ uuid = Util.random_uuid
22
+ ArchiveVolume.new(@options.merge(:uuid => uuid)).uuid.should == uuid
23
+ end
24
+
25
+ it "should generate new UUID if none given" do
26
+ ArchiveVolume.new(@options).uuid.should match(/#{UUID_RE}/)
27
+ end
28
+
29
+
30
+ end
31
+
32
+ describe ArchiveVolume do
33
+
34
+ before(:all) do
35
+ FileUtils.rm_rf TEMP_STORAGES + '/archive_volume_spec'
36
+ end
37
+
38
+ before(:each) do
39
+ @path = TEMP_STORAGES + '/archive_volume_spec'
40
+ @raw_uuid = Util.random_uuid_raw
41
+ @size = 64*1024
42
+ @options = {:uuid => @raw_uuid, :size => @size, :path => @path}
43
+ end
44
+
45
+ it "should be created with given size" do
46
+ dv = ArchiveVolume.new(@options)
47
+ fname = dv.file_path
48
+ File.should be_exist(fname)
49
+ File.size(fname).should == @size
50
+ File.open(fname){|f| f.read }[4..-1].should == "\x00"*(@size-4)
51
+ dv.delete!
52
+ File.should_not be_exist(fname)
53
+ end
54
+
55
+ it "should write some data and return its position" do
56
+ dv = ArchiveVolume.new(@options)
57
+ tail = dv.tail
58
+ tail.should == 4
59
+ prefix = 4
60
+
61
+ p1 = dv.insert("7 bytes")
62
+ p1.should == 0 + tail
63
+ p2 = dv.insert("13 more bytes")
64
+ p2.should == 7 + prefix + tail
65
+ p3 = dv.insert("1")
66
+ p3.should == 20 + prefix*2 + tail
67
+ dv.close!
68
+ end
69
+
70
+ it "should read & write data" do
71
+ dv = ArchiveVolume.new(@options)
72
+ p1 = dv.insert("7 bytes")
73
+ p2 = dv.insert("13 more bytes")
74
+ p3 = dv.insert("1")
75
+
76
+ dv.read(p2).should == "13 more bytes"
77
+ dv.read(p1).should == "7 bytes"
78
+ dv.read(p3).should == "1"
79
+
80
+ p4 = dv.insert("")
81
+
82
+ dv.read(p2).should == "13 more bytes"
83
+ dv.read(p1).should == "7 bytes"
84
+ dv.read(p3).should == "1"
85
+ dv.read(p4).should == ""
86
+
87
+ dv.close!
88
+ end
89
+
90
+ it "should raise exception if file is closed" do
91
+ dv = ArchiveVolume.new(@options)
92
+ dv.close!
93
+
94
+ lambda { dv.read(4) }.should raise_error(ArchiveVolume::VolumeClosedException)
95
+ lambda { dv.insert("data") }.should raise_error(ArchiveVolume::VolumeClosedException)
96
+ end
97
+
98
+ it "should raise exception if capacity is exceeded" do
99
+ dv = ArchiveVolume.new(@options)
100
+ # Since ArchiveVolume maintains some system information like header and record size
101
+ # record size of file size will exceed volume's capacity
102
+ lambda { dv.insert(" "*@size) }.should raise_error(ArchiveVolume::VolumeCapacityExceeded)
103
+ end
104
+
105
+ end