archipelago 0.1.0
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.
- data/GPL-2 +339 -0
- data/README +39 -0
- data/TODO +3 -0
- data/lib/archipelago.rb +24 -0
- data/lib/current.rb +128 -0
- data/lib/disco.rb +548 -0
- data/lib/hashish.rb +199 -0
- data/lib/pirate.rb +205 -0
- data/lib/tranny.rb +650 -0
- data/lib/treasure.rb +679 -0
- data/profiles/1000xChest#join!-prepare!-commit!.rb +19 -0
- data/profiles/1000xDubloon#[]=(t).rb +19 -0
- data/profiles/1000xDubloon#method_missing(t).rb +21 -0
- data/profiles/README +3 -0
- data/profiles/profile_helper.rb +25 -0
- data/scripts/chest.rb +20 -0
- data/scripts/console +3 -0
- data/scripts/pirate.rb +6 -0
- data/scripts/tranny.rb +20 -0
- data/tests/current_test.rb +28 -0
- data/tests/disco_test.rb +179 -0
- data/tests/pirate_test.rb +75 -0
- data/tests/test_helper.rb +60 -0
- data/tests/tranny_test.rb +70 -0
- data/tests/treasure_test.rb +257 -0
- metadata +69 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
|
|
2
|
+
require File.join(File.dirname(__FILE__), 'profile_helper')
|
|
3
|
+
require 'treasure'
|
|
4
|
+
require 'drb'
|
|
5
|
+
|
|
6
|
+
DRb.start_service
|
|
7
|
+
@c = TestChest.new
|
|
8
|
+
@tm = TestManager.new
|
|
9
|
+
|
|
10
|
+
tr = @tm.begin
|
|
11
|
+
k = "hej"
|
|
12
|
+
v = "oj"
|
|
13
|
+
@c[k,tr] = v
|
|
14
|
+
v = @c[k,tr]
|
|
15
|
+
1000.times do |n|
|
|
16
|
+
t = v.upcase
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
@c.persistence_provider.unlink
|
|
20
|
+
File.unlink(@tm.db.filename)
|
|
21
|
+
DRb.stop_service
|
data/profiles/README
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
|
|
2
|
+
home = File.expand_path(File.dirname(__FILE__))
|
|
3
|
+
$: << File.join(home, "..", "lib")
|
|
4
|
+
|
|
5
|
+
require 'pp'
|
|
6
|
+
require 'tranny'
|
|
7
|
+
require 'treasure'
|
|
8
|
+
|
|
9
|
+
class TestManager < Archipelago::Tranny::Manager
|
|
10
|
+
attr_reader :db
|
|
11
|
+
def log_error(e)
|
|
12
|
+
puts e
|
|
13
|
+
pp e.backtrace
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
class TestChest < Archipelago::Treasure::Chest
|
|
18
|
+
attr_reader :persistence_provider
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
class TestTransaction
|
|
22
|
+
def join(o)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
data/scripts/chest.rb
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
if ARGV.size < 1
|
|
4
|
+
puts "Usage: #{$0} DB-PATH [DRB-URI]"
|
|
5
|
+
exit 1
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
$: << File.join(File.dirname(__FILE__), "..", "lib")
|
|
9
|
+
|
|
10
|
+
require 'treasure'
|
|
11
|
+
|
|
12
|
+
if ARGV.size > 1
|
|
13
|
+
DRb.start_service(ARGV[1])
|
|
14
|
+
else
|
|
15
|
+
DRb.start_service
|
|
16
|
+
end
|
|
17
|
+
c = Archipelago::Treasure::Chest.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(ARGV[0])))
|
|
18
|
+
c.publish!
|
|
19
|
+
|
|
20
|
+
DRb.thread.join
|
data/scripts/console
ADDED
data/scripts/pirate.rb
ADDED
data/scripts/tranny.rb
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
if ARGV.size < 1
|
|
4
|
+
puts "Usage: #{$0} DB-PATH DRB-URI"
|
|
5
|
+
exit 1
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
$: << File.join(File.dirname(__FILE__), "..", "lib")
|
|
9
|
+
|
|
10
|
+
require 'treasure'
|
|
11
|
+
|
|
12
|
+
if ARGV.size > 1
|
|
13
|
+
DRb.start_service(ARGV[1])
|
|
14
|
+
else
|
|
15
|
+
DRb.start_service
|
|
16
|
+
end
|
|
17
|
+
t = Archipelago::Tranny::Manager.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(ARGV[0])))
|
|
18
|
+
t.publish!
|
|
19
|
+
|
|
20
|
+
DRb.thread.join
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
|
|
2
|
+
require File.join(File.dirname(__FILE__), 'test_helper')
|
|
3
|
+
require 'current'
|
|
4
|
+
|
|
5
|
+
class CurrentTest < Test::Unit::TestCase
|
|
6
|
+
|
|
7
|
+
def test_synchronized
|
|
8
|
+
t = true
|
|
9
|
+
|
|
10
|
+
a = "hej"
|
|
11
|
+
a.extend(Archipelago::Current::Synchronized)
|
|
12
|
+
|
|
13
|
+
o = "gnu"
|
|
14
|
+
a.synchronize_on(o) do
|
|
15
|
+
Thread.new do
|
|
16
|
+
a.synchronize_on(o) do
|
|
17
|
+
t = false
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
Thread.pass
|
|
21
|
+
assert(t)
|
|
22
|
+
end
|
|
23
|
+
assert_within(0.5) do
|
|
24
|
+
!t
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
end
|
data/tests/disco_test.rb
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
|
|
2
|
+
require File.join(File.dirname(__FILE__), 'test_helper')
|
|
3
|
+
require 'disco'
|
|
4
|
+
require 'drb'
|
|
5
|
+
require 'socket'
|
|
6
|
+
require 'ipaddr'
|
|
7
|
+
require 'thread'
|
|
8
|
+
|
|
9
|
+
class RemoteValidator
|
|
10
|
+
include DRb::DRbUndumped
|
|
11
|
+
attr_accessor :valid
|
|
12
|
+
def initialize(valid)
|
|
13
|
+
@valid = valid
|
|
14
|
+
end
|
|
15
|
+
def valid?
|
|
16
|
+
@valid
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
class DiscoTest < Test::Unit::TestCase
|
|
21
|
+
|
|
22
|
+
def setup
|
|
23
|
+
DRb.start_service
|
|
24
|
+
@d1 = TestJockey.new(:thrifty_publishing => false,
|
|
25
|
+
:thrifty_replying => false,
|
|
26
|
+
:thrifty_caching => false)
|
|
27
|
+
@d2 = TestJockey.new(:thrifty_publishing => false)
|
|
28
|
+
@v1 = RemoteValidator.new(true)
|
|
29
|
+
@p1 = Archipelago::Disco::Record.new(:service_id => 1,
|
|
30
|
+
:validator => DRbObject.new(@v1),
|
|
31
|
+
:epa => "blar")
|
|
32
|
+
@d1.publish(@p1)
|
|
33
|
+
assert(!@d2.lookup(Archipelago::Disco::Query.new(:epa => "blar")).empty?)
|
|
34
|
+
|
|
35
|
+
@listener = UDPSocket.new
|
|
36
|
+
@listener.setsockopt(Socket::IPPROTO_IP,
|
|
37
|
+
Socket::IP_ADD_MEMBERSHIP,
|
|
38
|
+
IPAddr.new(Archipelago::Disco::ADDRESS).hton + Socket.gethostbyname("0.0.0.0")[3])
|
|
39
|
+
|
|
40
|
+
@listener.setsockopt(Socket::SOL_SOCKET,
|
|
41
|
+
Socket::SO_REUSEADDR,
|
|
42
|
+
true)
|
|
43
|
+
begin
|
|
44
|
+
@listener.setsockopt(Socket::SOL_SOCKET,
|
|
45
|
+
Socket::SO_REUSEPORT,
|
|
46
|
+
true)
|
|
47
|
+
rescue
|
|
48
|
+
# /moo
|
|
49
|
+
end
|
|
50
|
+
@listener.bind('', Archipelago::Disco::PORT)
|
|
51
|
+
@ltq = []
|
|
52
|
+
@lt = Thread.new do
|
|
53
|
+
loop do
|
|
54
|
+
begin
|
|
55
|
+
@ltq << @listener.recv(1024)
|
|
56
|
+
rescue Exception => e
|
|
57
|
+
puts e
|
|
58
|
+
pp e.backtrace
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def teardown
|
|
65
|
+
@d1.stop
|
|
66
|
+
@d2.stop
|
|
67
|
+
DRb.stop_service
|
|
68
|
+
@lt.kill
|
|
69
|
+
@listener.close
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def test_publish_lookup
|
|
73
|
+
empty = true
|
|
74
|
+
Thread.new do
|
|
75
|
+
empty = @d2.lookup(Archipelago::Disco::Query.new(:epa => "blar2")).empty?
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
assert(empty)
|
|
79
|
+
|
|
80
|
+
@d1.publish(Archipelago::Disco::Record.new(:service_id => 1,
|
|
81
|
+
:validator => Archipelago::Disco::MockValidator.new,
|
|
82
|
+
:epa => "blar2"))
|
|
83
|
+
|
|
84
|
+
assert_within(0.5) do
|
|
85
|
+
!empty
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def test_publish_invalidate
|
|
90
|
+
@v1.valid = false
|
|
91
|
+
assert(@d2.lookup(Archipelago::Disco::Query.new(:epa => "blar"), 0).empty?)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def test_thrifty_publishing
|
|
95
|
+
@ltq.clear
|
|
96
|
+
|
|
97
|
+
@d1.publish(Archipelago::Disco::Record.new(:glada => "jaa", :validator => Archipelago::Disco::MockValidator.new, :service_id => 344))
|
|
98
|
+
sleep 0.1
|
|
99
|
+
assert(@ltq.any? do |d|
|
|
100
|
+
o = Marshal.load(d)
|
|
101
|
+
case o
|
|
102
|
+
when Archipelago::Disco::Record
|
|
103
|
+
o[:glada] == "jaa"
|
|
104
|
+
else
|
|
105
|
+
false
|
|
106
|
+
end
|
|
107
|
+
end)
|
|
108
|
+
|
|
109
|
+
@d1.stop
|
|
110
|
+
@d2.stop
|
|
111
|
+
|
|
112
|
+
@ltq.clear
|
|
113
|
+
c3 = Archipelago::Disco::Jockey.new(:thrifty_publishing => true)
|
|
114
|
+
c3.publish(Archipelago::Disco::Record.new(:glad => "ja", :validator => Archipelago::Disco::MockValidator.new, :service_id => 33))
|
|
115
|
+
sleep 0.1
|
|
116
|
+
assert(@ltq.empty?)
|
|
117
|
+
|
|
118
|
+
c1 = Archipelago::Disco::Jockey.new(:thrifty_publishing => true)
|
|
119
|
+
assert(!c1.lookup(Archipelago::Disco::Query.new(:glad => "ja")).empty?)
|
|
120
|
+
|
|
121
|
+
c1.stop
|
|
122
|
+
c3.stop
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def test_thrifty_replying
|
|
126
|
+
@d1.publish(Archipelago::Disco::Record.new(:gladaa => "jaaa", :validator => Archipelago::Disco::MockValidator.new, :service_id => 3444))
|
|
127
|
+
|
|
128
|
+
@ltq.clear
|
|
129
|
+
assert(!@d2.lookup(Archipelago::Disco::Query.new(:gladaa => "jaaa")).empty?)
|
|
130
|
+
assert(@ltq.any? do |d|
|
|
131
|
+
o = Marshal.load(d)
|
|
132
|
+
case o
|
|
133
|
+
when Archipelago::Disco::Record
|
|
134
|
+
o[:gladaa] == "jaaa"
|
|
135
|
+
else
|
|
136
|
+
false
|
|
137
|
+
end
|
|
138
|
+
end)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
@d1.stop
|
|
142
|
+
@d2.stop
|
|
143
|
+
c3 = Archipelago::Disco::Jockey.new(:thrifty_replying => true, :thrifty_publishing => true)
|
|
144
|
+
c3.publish(Archipelago::Disco::Record.new(:glad2 => "ja2", :validator => Archipelago::Disco::MockValidator.new, :service_id => 34))
|
|
145
|
+
|
|
146
|
+
@ltq.clear
|
|
147
|
+
|
|
148
|
+
c1 = Archipelago::Disco::Jockey.new
|
|
149
|
+
assert(!c1.lookup(Archipelago::Disco::Query.new(:glad2 => "ja2"), 2).empty?)
|
|
150
|
+
|
|
151
|
+
assert(!@ltq.any? do |data|
|
|
152
|
+
o = Marshal.load(data)
|
|
153
|
+
if Archipelago::Disco::Record === o
|
|
154
|
+
o[:glad2] == "ja2"
|
|
155
|
+
else
|
|
156
|
+
false
|
|
157
|
+
end
|
|
158
|
+
end)
|
|
159
|
+
|
|
160
|
+
c1.stop
|
|
161
|
+
c3.stop
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def test_thrifty_caching
|
|
165
|
+
@d2.publish(Archipelago::Disco::Record.new(:bojkotta => "jag", :validator => Archipelago::Disco::MockValidator.new, :service_id => 411))
|
|
166
|
+
sleep 0.1
|
|
167
|
+
assert(@d1.remote_services.include?(411))
|
|
168
|
+
|
|
169
|
+
c1 = TestJockey.new(:thrifty_caching => true)
|
|
170
|
+
assert(!c1.local_services.include?(41))
|
|
171
|
+
assert(!c1.remote_services.include?(41))
|
|
172
|
+
@d1.publish(Archipelago::Disco::Record.new(:bojkott => "ja", :validator => Archipelago::Disco::MockValidator.new, :service_id => 41))
|
|
173
|
+
sleep 0.1
|
|
174
|
+
assert(!c1.local_services.include?(41))
|
|
175
|
+
assert(!c1.remote_services.include?(41))
|
|
176
|
+
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
|
|
2
|
+
require File.join(File.dirname(__FILE__), 'test_helper')
|
|
3
|
+
require 'treasure'
|
|
4
|
+
require 'drb'
|
|
5
|
+
require 'tranny'
|
|
6
|
+
require 'hashish'
|
|
7
|
+
require 'pirate'
|
|
8
|
+
|
|
9
|
+
class PirateTest < Test::Unit::TestCase
|
|
10
|
+
|
|
11
|
+
def setup
|
|
12
|
+
DRb.start_service("druby://localhost:#{rand(1000) + 5000}")
|
|
13
|
+
@p = Archipelago::Pirate::Captain.new(:chest_description => {:class => "TestChest"},
|
|
14
|
+
:tranny_description => {:class => "TestManager"})
|
|
15
|
+
@c = TestChest.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(__FILE__).parent.join("chest.db")))
|
|
16
|
+
@c.publish!
|
|
17
|
+
@c2 = TestChest.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(__FILE__).parent.join("chest2.db")))
|
|
18
|
+
@c2.publish!
|
|
19
|
+
@tm = TestManager.new
|
|
20
|
+
@tm.publish!
|
|
21
|
+
assert_within(10) do
|
|
22
|
+
!@p.chests.empty?
|
|
23
|
+
end
|
|
24
|
+
assert_within(10) do
|
|
25
|
+
!@p.trannies.empty?
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def teardown
|
|
30
|
+
@c.persistence_provider.unlink
|
|
31
|
+
@c2.persistence_provider.unlink
|
|
32
|
+
@tm.persistence_provider.unlink
|
|
33
|
+
DRb.stop_service
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def test_write_read
|
|
37
|
+
0.upto(100) do |n|
|
|
38
|
+
@p["#{n}"] = "#{n}"
|
|
39
|
+
end
|
|
40
|
+
chest_ids = Set.new
|
|
41
|
+
0.upto(100) do |n|
|
|
42
|
+
chest_ids << @c.service_id if @c["#{n}"]
|
|
43
|
+
chest_ids << @c2.service_id if @c2["#{n}"]
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
assert(chest_ids.include?(@c.service_id), "This may fail due to bad luck, try again")
|
|
47
|
+
assert(chest_ids.include?(@c2.service_id), "This may fail due to bad luck, try again")
|
|
48
|
+
|
|
49
|
+
@p["brupp"] = "jojo"
|
|
50
|
+
assert_equal("jojo", @p["brupp"])
|
|
51
|
+
s1 = @p["brupp"]
|
|
52
|
+
s2 = @p["brupp"]
|
|
53
|
+
assert_equal(s1, s2)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def test_write_read_transaction
|
|
57
|
+
$T = true
|
|
58
|
+
@p["hej"] = "haha"
|
|
59
|
+
p2 = @p.begin
|
|
60
|
+
assert_equal(p2["hej"], @p["hej"])
|
|
61
|
+
p2["hej"] = "bums"
|
|
62
|
+
assert(p2["hej"] != @p["hej"])
|
|
63
|
+
p2.commit!
|
|
64
|
+
assert_equal("bums", p2["hej"])
|
|
65
|
+
assert_equal(p2["hej"], @p["hej"])
|
|
66
|
+
|
|
67
|
+
p2 = @p.begin
|
|
68
|
+
p2["hej"] = "glass"
|
|
69
|
+
assert(p2["hej"] != @p["hej"])
|
|
70
|
+
p2.abort!
|
|
71
|
+
assert("bums", @p["hej"])
|
|
72
|
+
$T = false
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
|
|
2
|
+
home = File.expand_path(File.dirname(__FILE__))
|
|
3
|
+
$: << File.join(home, "..", "lib")
|
|
4
|
+
|
|
5
|
+
require 'pp'
|
|
6
|
+
require 'test/unit'
|
|
7
|
+
require 'tranny'
|
|
8
|
+
require 'treasure'
|
|
9
|
+
require 'benchmark'
|
|
10
|
+
|
|
11
|
+
class TestTransaction
|
|
12
|
+
def join(o)
|
|
13
|
+
end
|
|
14
|
+
def state
|
|
15
|
+
:active
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
class TestManager < Archipelago::Tranny::Manager
|
|
20
|
+
attr_reader :persistence_provider
|
|
21
|
+
def log_error(e)
|
|
22
|
+
puts e
|
|
23
|
+
pp e.backtrace
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
class TestJockey < Archipelago::Disco::Jockey
|
|
28
|
+
attr_reader :remote_services, :local_services
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
class TestChest < Archipelago::Treasure::Chest
|
|
32
|
+
attr_reader :persistence_provider
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
class Test::Unit::TestCase
|
|
36
|
+
|
|
37
|
+
def bm(label, options = {})
|
|
38
|
+
n = options[:n] || 1000
|
|
39
|
+
width = options[:width] || 50
|
|
40
|
+
Benchmark.benchmark(" " * width + Benchmark::Tms::CAPTION, width, Benchmark::Tms::FMTSTR, "ms/call") do |b|
|
|
41
|
+
times = b.report("#{n}x#{label}") do
|
|
42
|
+
n.times do
|
|
43
|
+
yield
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
[times * 1000 / n.to_f]
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def assert_within(timeout, &block)
|
|
51
|
+
t = Time.new
|
|
52
|
+
rval = yield
|
|
53
|
+
while !rval && t > Time.new - timeout
|
|
54
|
+
rval = yield
|
|
55
|
+
sleep(0.05)
|
|
56
|
+
end
|
|
57
|
+
assert(rval)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
end
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
|
|
2
|
+
require File.join(File.dirname(__FILE__), 'test_helper')
|
|
3
|
+
require 'tranny'
|
|
4
|
+
require 'drb'
|
|
5
|
+
|
|
6
|
+
class TrannyTest < Test::Unit::TestCase
|
|
7
|
+
|
|
8
|
+
def setup
|
|
9
|
+
DRb.start_service
|
|
10
|
+
@tm = TestManager.new(:db_path => Pathname.new(__FILE__).parent.join("tranny.db"))
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def teardown
|
|
14
|
+
@tm.persistence_provider.unlink
|
|
15
|
+
DRb.stop_service
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
class Participant
|
|
19
|
+
include DRb::DRbUndumped
|
|
20
|
+
|
|
21
|
+
attr_accessor :state
|
|
22
|
+
attr_accessor :mode
|
|
23
|
+
|
|
24
|
+
def assert_equal(a,b)
|
|
25
|
+
raise "#{a} != #{b}" unless a == b
|
|
26
|
+
end
|
|
27
|
+
def initialize(mode)
|
|
28
|
+
@mode = mode
|
|
29
|
+
@state = :none
|
|
30
|
+
end
|
|
31
|
+
def abort!(t)
|
|
32
|
+
@state = :aborted
|
|
33
|
+
end
|
|
34
|
+
def prepare!(t)
|
|
35
|
+
assert_equal(:voting, t.state)
|
|
36
|
+
@mode
|
|
37
|
+
end
|
|
38
|
+
def commit!(t)
|
|
39
|
+
assert_equal(:commited, t.state)
|
|
40
|
+
@state = :commited
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def test_successful_commit
|
|
45
|
+
p1 = Participant.new(:commit)
|
|
46
|
+
p2 = Participant.new(:commit)
|
|
47
|
+
trans = @tm.begin
|
|
48
|
+
assert_equal(:active, trans.state)
|
|
49
|
+
trans.join(DRbObject.new(p1))
|
|
50
|
+
trans.join(DRbObject.new(p2))
|
|
51
|
+
assert_equal(:commited, trans.commit!)
|
|
52
|
+
assert_equal(:commited, trans.state)
|
|
53
|
+
assert_equal(:commited, p1.state)
|
|
54
|
+
assert_equal(:commited, p2.state)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def test_aborted_commit
|
|
58
|
+
p1 = Participant.new(:commit)
|
|
59
|
+
p2 = Participant.new(:abort)
|
|
60
|
+
trans = @tm.begin
|
|
61
|
+
assert_equal(:active, trans.state)
|
|
62
|
+
trans.join(DRbObject.new(p1))
|
|
63
|
+
trans.join(DRbObject.new(p2))
|
|
64
|
+
assert_equal(:aborted, trans.commit!)
|
|
65
|
+
assert_equal(:aborted, trans.state)
|
|
66
|
+
assert_equal(:aborted, p1.state)
|
|
67
|
+
assert_equal(:none, p2.state)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
end
|