archipelago 0.2.5 → 0.2.6

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.
@@ -0,0 +1,71 @@
1
+
2
+ require File.join(File.dirname(__FILE__), 'test_helper')
3
+
4
+ class DumpTest < Test::Unit::TestCase
5
+
6
+ def setup
7
+ @c = Archipelago::Sanitation::Officer.new(:initial_lookup_timeout => 0)
8
+ @d = Archipelago::Dump::Site.new(:officer => @c,
9
+ :persistence_directory => Pathname.new(__FILE__).parent.join("site.db"))
10
+ end
11
+
12
+ def teardown
13
+ @d.instance_eval do @persistence_provider.unlink! end
14
+ @c.stop!
15
+ end
16
+
17
+ def test_insert_fetch
18
+ @d.insert!("key", ["value", "value1"])
19
+
20
+ assert_equal(["value", "value1"].sort,
21
+ @d.fetch("key").collect do |e| e.last end.sort)
22
+
23
+ @d.insert!("key2", ["value2"])
24
+ @d.insert!("key2", ["value3"])
25
+ assert_equal(["value2"],
26
+ @d.fetch("key2").collect do |e| e.last end.sort)
27
+
28
+ @d.insert!("key2", ["value3"], "hehu")
29
+ assert_equal(["value3"],
30
+ @d.fetch("key2").collect do |e| e.last end.sort)
31
+
32
+ @d.insert!("key", ["value2", "value3"], "apap")
33
+ assert_equal(["value2", "value3"].sort,
34
+ @d.fetch("key").collect do |e| e.last end.sort)
35
+
36
+ @d.delete!("key")
37
+ @d.delete!("key2")
38
+ assert_equal([],
39
+ @d.fetch("key").collect do |e| e.last end)
40
+ assert_equal([],
41
+ @d.fetch("key2").collect do |e| e.last end)
42
+ end
43
+
44
+ def test_too_few
45
+ @d.insert!("a", ["b","c"])
46
+ assert_equal(["b","c"].sort,
47
+ @d.fetch("a").collect do |e| e.last end.sort)
48
+ @d.insert!("a", ["d","c","b"])
49
+ assert_equal(["b","c","d"].sort,
50
+ @d.fetch("a").collect do |e| e.last end.sort)
51
+ end
52
+
53
+ def test_too_many
54
+ @d.insert!("a", ["b","c"])
55
+ assert_equal(["b","c"].sort,
56
+ @d.fetch("a").collect do |e| e.last end.sort)
57
+ @d.insert!("a", ["d"])
58
+ assert_equal(["d"],
59
+ @d.fetch("a").collect do |e| e.last end)
60
+ end
61
+
62
+ def test_wrong_timestamp
63
+ @d.insert!("a", ["b","c"], "epap")
64
+ assert_equal(["b","c"].sort,
65
+ @d.fetch("a").collect do |e| e.last end.sort)
66
+ @d.insert!("a", ["x", "y"], "epao")
67
+ assert_equal(["x","y"].sort,
68
+ @d.fetch("a").collect do |e| e.last end.sort)
69
+ end
70
+
71
+ end
data/tests/pirate_test.rb CHANGED
@@ -4,33 +4,72 @@ require File.join(File.dirname(__FILE__), 'test_helper')
4
4
  class PirateTest < Test::Unit::TestCase
5
5
 
6
6
  def setup
7
- DRb.start_service("druby://localhost:#{rand(1000) + 5000}")
7
+ @j = Archipelago::Disco::Jockey.new
8
8
  @p = Archipelago::Pirate::Captain.new(:chest_description => {:class => "TestChest"},
9
- :tranny_description => {:class => "TestManager"})
10
- @c = TestChest.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(__FILE__).parent.join("chest.db")))
11
- @c.publish!
12
- @c2 = TestChest.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(__FILE__).parent.join("chest2.db")))
13
- @c2.publish!
14
- @tm = TestManager.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(__FILE__).parent.join("tranny.db")))
9
+ :tranny_description => {:class => "TestManager"},
10
+ :jockey => @j,
11
+ :initial_lookup_timeout => 0)
12
+ @c = TestChest.new(:captain => @p,
13
+ :persistence_directory => Pathname.new(__FILE__).parent.join("chest.db"))
14
+ @c.publish!(:jockey => @j)
15
+ assert(@j.instance_eval do
16
+ @service_change_subscribers_by_event_type
17
+ end[:lost].include?([@p.instance_eval do
18
+ @service_descriptions
19
+ end[:chests], @c.service_id]))
20
+ assert(@j.instance_eval do
21
+ @service_change_subscribers_by_event_type
22
+ end[:found].include?([@p.instance_eval do
23
+ @service_descriptions
24
+ end[:chests], @c.service_id]))
25
+ assert_within(10) do
26
+ @p.update_services!
27
+ @p.chests.keys.include?(@c.service_id)
28
+ end
29
+ assert_equal(@c.service_id, @c.instance_eval do @predecessor_id end)
30
+
31
+ @c2 = TestChest.new(:captain => @p,
32
+ :persistence_directory => Pathname.new(__FILE__).parent.join("chest2.db"))
33
+ @c2.publish!(:jockey => @j)
34
+ assert_within(10) do
35
+ @p.update_services!
36
+ @p.chests.keys.include?(@c2.service_id)
37
+ end
38
+ assert_within(10) do
39
+ @c2.service_id == @c.instance_eval do @predecessor_id end
40
+ end
41
+ assert_within(10) do
42
+ @c.service_id == @c2.instance_eval do @predecessor_id end
43
+ end
44
+
45
+ @tm = TestManager.new(:captain => @p,
46
+ :persistence_directory => Pathname.new(__FILE__).parent.join("tranny.db"))
15
47
  @tm.publish!
16
- @p.update_services!
17
48
  assert_within(10) do
49
+ @p.update_services!
50
+ @p.trannies.keys.include?(@tm.service_id)
51
+ end
52
+
53
+
54
+ assert_within(10) do
55
+ @p.update_services!
18
56
  @p.chests.keys.sort == [@c.service_id, @c2.service_id].sort
19
57
  end
20
58
  assert_within(10) do
59
+ @p.update_services!
21
60
  @p.trannies.keys == [@tm.service_id]
22
61
  end
23
62
  end
24
63
 
25
64
  def teardown
26
- @p.stop!
27
- @c.stop!
65
+ @c.close!
28
66
  @c.persistence_provider.unlink!
29
- @c2.stop!
67
+ @c2.close!
30
68
  @c2.persistence_provider.unlink!
31
- @tm.stop!
69
+ @tm.close!
32
70
  @tm.persistence_provider.unlink!
33
- DRb.stop_service
71
+ @p.stop!
72
+ @j.stop!
34
73
  end
35
74
 
36
75
  def test_include
@@ -122,18 +161,18 @@ class PirateTest < Test::Unit::TestCase
122
161
  end
123
162
  trans = nil
124
163
  assert_raise(Archipelago::Pirate::CommitFailedException) do
125
- @p.transaction do |trans|
126
- assert_equal(trans.transaction_id, @p.active_transaction.transaction_id)
127
- @p["hehu"] = "haha"
164
+ @p.transaction do |copy|
165
+ trans = copy.active_transaction
166
+ copy["hehu"] = "haha"
128
167
  assert(!p2.include?("hehu"))
129
168
  assert(!p2.include?("hehu", nil))
130
169
  assert_equal(nil, p2.active_transaction)
131
170
  trans2 = nil
132
- p2.transaction do |trans2|
133
- assert_equal(trans2.transaction_id, p2.active_transaction.transaction_id)
134
- p2["hehu"] = "hoj"
135
- assert_equal("haha", @p["hehu"])
136
- assert_equal("hoj", @p["hehu", trans2])
171
+ p2.transaction do |copy2|
172
+ trans2 = copy2.active_transaction
173
+ copy2["hehu"] = "hoj"
174
+ assert_equal("haha", copy["hehu"])
175
+ assert_equal("hoj", copy["hehu", trans2])
137
176
  end
138
177
  assert_equal(:commited, trans2.state)
139
178
  assert_equal(:active, trans.state)
@@ -145,6 +184,20 @@ class PirateTest < Test::Unit::TestCase
145
184
  assert_equal("hoj", @p["hehu"])
146
185
  end
147
186
 
187
+ def test_wrong_chest_exception
188
+ chests = [@c, @c2].sort do |a,b|
189
+ a.service_id <=> b.service_id
190
+ end
191
+ begin
192
+ $DO_ASSERT_MINE = true
193
+ assert_raise(Archipelago::Treasure::WrongChestException) do
194
+ chests.last.call_instance_method(chests.last.service_id.next, :bruhuf, nil)
195
+ end
196
+ ensure
197
+ $DO_ASSERT_MINE = false
198
+ end
199
+ end
200
+
148
201
  def test_write_read_transaction
149
202
  $T = true
150
203
  @p["hej"] = "haha"
@@ -0,0 +1,50 @@
1
+
2
+ require File.join(File.dirname(__FILE__), 'test_helper')
3
+
4
+ class SanitationBenchmark < Test::Unit::TestCase
5
+
6
+ def setup
7
+ @d = Archipelago::Dump::Site.new(:persistence_directory => Pathname.new(__FILE__).parent.join("site.db"))
8
+ @d.publish!
9
+ @c = Archipelago::Sanitation::Officer.new
10
+ assert_within(10) do
11
+ @c.update_services!
12
+ @c.sites.keys == [@d.service_id]
13
+ end
14
+ end
15
+
16
+ def teardown
17
+ @d.close!
18
+ @d.instance_eval do @persistence_provider.unlink! end
19
+ @c.stop!
20
+ end
21
+
22
+ def test_set_get
23
+ do_set_get(8)
24
+ do_set_get(128)
25
+ do_set_get(512)
26
+ do_set_get(1024)
27
+ end
28
+
29
+ private
30
+
31
+ def do_set_get(size)
32
+ k = "apa"
33
+ v = " " * size
34
+ bm("Sanitation#[]= (#{size})", :n => 100) do
35
+ @c[k] = v
36
+ k = k.next
37
+ end
38
+ k = "apa"
39
+ bm("Sanitation#[] (#{size})", :n => 100) do
40
+ t = @c[k]
41
+ k = k.next
42
+ end
43
+ k = "apa"
44
+ bm("Sanitation#delete", :n => 100) do
45
+ t = @c.delete!(k)
46
+ k = k.next
47
+ end
48
+ end
49
+
50
+ end
@@ -0,0 +1,219 @@
1
+
2
+ require File.join(File.dirname(__FILE__), 'test_helper')
3
+
4
+ class SanitationTest < Test::Unit::TestCase
5
+
6
+ def setup
7
+ @c = Archipelago::Sanitation::Officer.new(:initial_lookup_timeout => 0)
8
+ @d = Archipelago::Dump::Site.new(:officer => @c,
9
+ :persistence_directory => Pathname.new(__FILE__).parent.join("site.db"))
10
+ @d.publish!
11
+ begin
12
+ assert_within(10) do
13
+ @c.update_services!
14
+ @c.sites.keys == [@d.service_id]
15
+ end
16
+ rescue Test::Unit::AssertionFailedError => e
17
+ puts "#{@c.sites.keys.inspect} != #{[@d.service_id].inspect}"
18
+ raise e
19
+ end
20
+ end
21
+
22
+ def teardown
23
+ @d.close!
24
+ @d.instance_eval do @persistence_provider.unlink! end
25
+ @c.stop!
26
+ end
27
+
28
+ def test_sanitation_backed_chest
29
+ chest = Archipelago::Treasure::Chest.new(:persistence_directory => Pathname.new(__FILE__).parent.join("site_chest.db"),
30
+ :officer => @c)
31
+ chest.publish!
32
+ begin
33
+ assert_equal(nil, chest["klibb"])
34
+ assert_equal("kladd", chest["klibb"] = "kladd")
35
+ assert_equal("kladd", chest["klibb"])
36
+ assert_equal("KLADD", chest["klibb"].upcase!)
37
+ klibb = chest["klibb"]
38
+ assert_equal("kladd", klibb.downcase)
39
+ assert_equal("kladd", klibb.downcase!)
40
+ assert_equal("KLADD", klibb.upcase)
41
+ assert_equal("kladd", klibb)
42
+ @d.close!
43
+ @c.update_services!(:validate => true)
44
+ assert_raise(Archipelago::Sanitation::NoRemoteDatabaseAvailableException) do
45
+ klibb.upcase!
46
+ end
47
+ ensure
48
+ chest.close!
49
+ chest.instance_eval do @persistence_provider.unlink! end
50
+ end
51
+ end
52
+
53
+ def test_missing_bits
54
+ s1 = Oneliner::SuperString.new("brappa")
55
+ @d.insert!("a", [s1.encode(9)], "abab")
56
+ assert_raise(Archipelago::Sanitation::NotEnoughDataException) do
57
+ @c["a"]
58
+ end
59
+ end
60
+
61
+
62
+ def test_get_set
63
+ @c["hej"] = "hoho"
64
+ assert_equal("hoho", @c["hej"])
65
+ @c.delete!("hej")
66
+ assert_equal(@c["hej"], nil)
67
+ end
68
+
69
+ def test_multi
70
+ #
71
+ # Setup the network
72
+ #
73
+ @d.close!
74
+ dumps = []
75
+ cleaner2 = Archipelago::Sanitation::Officer.new(:minimum_nr_of_chunks => 3,
76
+ :initial_lookup_timeout => 0)
77
+ begin
78
+ 10.times do |n|
79
+ dumps[n] = Archipelago::Dump::Site.new(:officer => cleaner2,
80
+ :service_description => {:service_id => n.to_s},
81
+ :persistence_directory => Pathname.new(__FILE__).parent.join("master_test_#{n}.db"))
82
+ dumps[n].publish!
83
+ end
84
+ #
85
+ # Wait until it is alive
86
+ #
87
+ assert_within(30) do
88
+ cleaner2.update_services!
89
+ dumps.collect do |d| d.service_id end.sort == cleaner2.sites.keys.sort
90
+ end
91
+ #
92
+ # Perform checks on all dumps
93
+ #
94
+ 10.times do |n|
95
+ if n < 9
96
+ assert(dumps[n].instance_eval do right_before?(dumps[n+1].service_id) end,
97
+ "#{dumps[n].service_id} is supposed to be right_before? #{dumps[n+1].service_id}, but isnt. services are #{cleaner2.sites.keys.inspect}")
98
+ assert(dumps[n+1].instance_eval do right_after?(dumps[n].service_id) end,
99
+ "#{dumps[n+1].service_id} is supposed to be right_after? #{dumps[n].service_id}, but isnt. services are #{cleaner2.sites.keys.inspect}")
100
+ else
101
+ assert(dumps[n].instance_eval do right_before?(dumps[0].service_id) end,
102
+ "#{dumps[n].service_id} is supposed to be right_before? #{dumps[0].service_id}, but isnt. services are #{cleaner2.sites.keys.inspect}")
103
+ assert(dumps[0].instance_eval do right_after?(dumps[n].service_id) end,
104
+ "#{dumps[0].service_id} is supposed to be right_after? #{dumps[n].service_id}, but isnt. services are #{cleaner2.sites.keys.inspect}")
105
+ end
106
+ if n > 0
107
+ assert_equal(dumps[n - 1].service_id, cleaner2.predecessor(dumps[n].service_id))
108
+ else
109
+ assert_equal(dumps[9].service_id, cleaner2.predecessor(dumps[0].service_id))
110
+ end
111
+ end
112
+ #
113
+ # Check that only fresh data is returned
114
+ #
115
+ s1 = Oneliner::SuperString.new("brappa")
116
+ s2 = Oneliner::SuperString.new("brappa2")
117
+ assert_equal(0, dumps[0].db.size)
118
+ assert_equal(0, dumps[0].db.size)
119
+ dumps[0].insert!("a", [s1.encode(20)], "aaaa")
120
+ dumps[1].insert!("a", [s2.encode(200)], "aaab")
121
+ assert(cleaner2.responsible_sites("a").include?(dumps[0].service_id))
122
+ assert(cleaner2.responsible_sites("a").include?(dumps[1].service_id))
123
+ assert_equal(s2.to_s, cleaner2["a"])
124
+ #
125
+ # Check the utility methods of sanitation
126
+ #
127
+ assert_equal([dumps[9].service_id, dumps[0].service_id, dumps[1].service_id].sort,
128
+ cleaner2.instance_eval do
129
+ get_greatest_less_than(:sites, dumps[2].service_id, 3)
130
+ end.collect do |d| d[:service_id] end.sort)
131
+ assert_equal([dumps[8].service_id, dumps[9].service_id, dumps[0].service_id].sort,
132
+ cleaner2.instance_eval do
133
+ get_least_greater_than(:sites, dumps[7].service_id, 3)
134
+ end.collect do |d| d[:service_id] end.sort)
135
+ assert_equal(dumps[3].service_id,
136
+ cleaner2.second_master_to(dumps[4].service_id))
137
+ assert_equal(dumps[9].service_id,
138
+ cleaner2.second_master_to(dumps[0].service_id))
139
+ #
140
+ # Check the recovery methods
141
+ #
142
+ assert_equal({
143
+ "6"=>0,
144
+ "7"=>0,
145
+ "8"=>0,
146
+ "9"=>0,
147
+ "0"=>1,
148
+ "1"=>1,
149
+ "2"=>0,
150
+ "3"=>0,
151
+ "4"=>0,
152
+ "5"=>0
153
+ },
154
+ chunks_by_id(cleaner2, "a"))
155
+ cleaner2.redistribute("a")
156
+ healthy_chunks = {
157
+ "6"=>0,
158
+ "7"=>0,
159
+ "8"=>0,
160
+ "9"=>0,
161
+ "0"=>1,
162
+ "1"=>1,
163
+ "2"=>1,
164
+ "3"=>0,
165
+ "4"=>0,
166
+ "5"=>0
167
+ }
168
+ assert_equal(healthy_chunks,
169
+ chunks_by_id(cleaner2, "a"))
170
+ dumps[1].close!
171
+ cleaner2.update_services!(:validate => true)
172
+ dumps[0].instance_eval do lost_peer({:service_id => dumps[1].service_id}) end
173
+ dumps[2].instance_eval do lost_peer({:service_id => dumps[1].service_id}) end
174
+ assert_equal({"6"=>0, "7"=>0, "8"=>0, "9"=>0, "0"=>1, "2"=>1, "3"=>1, "4"=>0, "5"=>0},
175
+ chunks_by_id(cleaner2, "a"))
176
+
177
+ dumps[1] = Archipelago::Dump::Site.new(:officer => cleaner2,
178
+ :service_description => {:service_id => "1"},
179
+ :persistence_directory => Pathname.new(__FILE__).parent.join("master_test_1.db"))
180
+ dumps[1].publish!
181
+ begin
182
+ assert_within(20) do
183
+ cleaner2.update_services!
184
+ ["0","1","2","3","4","5","6","7","8","9"].sort == cleaner2.sites.keys.sort
185
+ end
186
+ rescue Test::Unit::AssertionFailedError => e
187
+ pp chunks_by_id(cleaner2, "a")
188
+ raise e
189
+ end
190
+ assert_equal({"0"=>1, "1"=>1, "2"=>1},
191
+ cleaner2.responsible_sites("a"))
192
+ dumps[3].instance_eval do @edge_check_thread.wakeup end
193
+ cleaner2.update_services!(:validate => true)
194
+ begin
195
+ assert_within(20) do
196
+ chunks_by_id(cleaner2, "a") == healthy_chunks
197
+ end
198
+ rescue Test::Unit::AssertionFailedError => e
199
+ pp chunks_by_id(cleaner2, "a")
200
+ raise e
201
+ end
202
+ ensure
203
+ dumps.extend(Archipelago::Current::ThreadedCollection)
204
+ dumps.t_each do |dump|
205
+ dump.close!
206
+ dump.instance_eval do @persistence_provider.unlink! end
207
+ end
208
+ end
209
+ end
210
+
211
+ private
212
+
213
+ def chunks_by_id(officer, key)
214
+ officer.sites.values.inject({}) do |result, service_desc|
215
+ result.merge({service_desc[:service_id] => service_desc[:service].fetch(key).size})
216
+ end
217
+ end
218
+
219
+ end