fraggle 0.4.0 → 1.0.0pre
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/Rakefile +17 -0
- data/example/again.rb +21 -0
- data/example/getdir.rb +24 -0
- data/example/ping.rb +19 -0
- data/example/session.rb +16 -0
- data/example/set.rb +21 -0
- data/example/stat.rb +23 -0
- data/example/walk.rb +23 -0
- data/example/watch.rb +22 -0
- data/fraggle.gemspec +25 -0
- data/lib/fraggle.rb +28 -35
- data/lib/fraggle/client.rb +70 -287
- data/lib/fraggle/connection.rb +139 -0
- data/lib/fraggle/msg.pb.rb +62 -0
- data/lib/fraggle/request.rb +37 -10
- data/lib/fraggle/response.rb +17 -38
- data/lib/fraggle/version.rb +3 -0
- data/test/fraggle_client_test.rb +185 -165
- data/test/fraggle_protocol_test.rb +27 -39
- data/test/fraggle_test.rb +5 -10
- data/test/fraggle_transaction_test.rb +220 -0
- data/test/helper.rb +84 -0
- metadata +59 -36
- data/lib/fraggle/emitter.rb +0 -39
- data/lib/fraggle/errors.rb +0 -3
- data/lib/fraggle/logger.rb +0 -32
- data/lib/fraggle/meta.rb +0 -9
- data/lib/fraggle/msg.rb +0 -77
- data/lib/fraggle/protocol.rb +0 -43
- data/lib/fraggle/test.rb +0 -72
@@ -1,20 +1,12 @@
|
|
1
|
-
require
|
2
|
-
require 'fraggle/
|
3
|
-
require 'fraggle/response'
|
4
|
-
require 'fraggle/test'
|
1
|
+
require File.dirname(__FILE__)+"/helper"
|
2
|
+
require 'fraggle/connection'
|
5
3
|
|
6
4
|
class FraggleProtocolTest < Test::Unit::TestCase
|
7
|
-
include Fraggle::Test
|
8
|
-
|
9
|
-
class TestConn < Array
|
10
|
-
include Fraggle::Protocol
|
11
|
-
alias :receive_response :<<
|
12
|
-
end
|
13
5
|
|
14
6
|
attr_reader :cn
|
15
7
|
|
16
8
|
def setup
|
17
|
-
@cn = TestConn.new
|
9
|
+
@cn = TestConn.new("127.0.0.1:0")
|
18
10
|
end
|
19
11
|
|
20
12
|
def encode(req)
|
@@ -23,31 +15,31 @@ class FraggleProtocolTest < Test::Unit::TestCase
|
|
23
15
|
end
|
24
16
|
|
25
17
|
def test_simple
|
26
|
-
req = Fraggle::Response.new :tag => 0, :verb => V::
|
18
|
+
req = Fraggle::Response.new :tag => 0, :verb => V::NOP, :flags => F::VALID
|
27
19
|
cn.receive_data(encode(req))
|
28
20
|
|
29
|
-
assert_equal [req], cn
|
21
|
+
assert_equal [req], cn.received
|
30
22
|
end
|
31
23
|
|
32
24
|
def test_multiple_single
|
33
|
-
a = Fraggle::Response.new :tag => 0, :verb => V::
|
34
|
-
b = Fraggle::Response.new :tag => 1, :verb => V::
|
25
|
+
a = Fraggle::Response.new :tag => 0, :verb => V::NOP, :flags => F::VALID
|
26
|
+
b = Fraggle::Response.new :tag => 1, :verb => V::NOP, :flags => F::VALID
|
35
27
|
cn.receive_data(encode(a) + encode(b))
|
36
28
|
|
37
|
-
assert_equal [a, b], cn
|
29
|
+
assert_equal [a, b], cn.received
|
38
30
|
end
|
39
31
|
|
40
32
|
def test_multiple_double
|
41
|
-
a = Fraggle::Response.new :tag => 0, :verb => V::
|
42
|
-
b = Fraggle::Response.new :tag => 1, :verb => V::
|
33
|
+
a = Fraggle::Response.new :tag => 0, :verb => V::NOP, :flags => F::VALID
|
34
|
+
b = Fraggle::Response.new :tag => 1, :verb => V::NOP, :flags => F::VALID
|
43
35
|
cn.receive_data(encode(a))
|
44
36
|
cn.receive_data(encode(b))
|
45
37
|
|
46
|
-
assert_equal [a, b], cn
|
38
|
+
assert_equal [a, b], cn.received
|
47
39
|
end
|
48
40
|
|
49
41
|
def test_small_chunks
|
50
|
-
req = Fraggle::Response.new :tag => 0, :verb => V::
|
42
|
+
req = Fraggle::Response.new :tag => 0, :verb => V::NOP, :flags => F::VALID
|
51
43
|
|
52
44
|
bytes = encode(req) * 3
|
53
45
|
len = bytes.length
|
@@ -57,11 +49,11 @@ class FraggleProtocolTest < Test::Unit::TestCase
|
|
57
49
|
cn.receive_data(data)
|
58
50
|
end
|
59
51
|
|
60
|
-
assert_equal [req, req, req], cn
|
52
|
+
assert_equal [req, req, req], cn.received
|
61
53
|
end
|
62
54
|
|
63
55
|
def test_big_chunks
|
64
|
-
req = Fraggle::Response.new :tag => 0, :verb => V::
|
56
|
+
req = Fraggle::Response.new :tag => 0, :verb => V::NOP, :flags => F::VALID
|
65
57
|
|
66
58
|
bytes = encode(req) * 3
|
67
59
|
len = bytes.length
|
@@ -71,30 +63,26 @@ class FraggleProtocolTest < Test::Unit::TestCase
|
|
71
63
|
cn.receive_data(data)
|
72
64
|
end
|
73
65
|
|
74
|
-
assert_equal [req, req, req], cn
|
66
|
+
assert_equal [req, req, req], cn.received
|
75
67
|
end
|
76
68
|
|
77
69
|
def test_send_request
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
def initialize
|
84
|
-
@data = ""
|
85
|
-
super(["127.0.0.1:8046"])
|
86
|
-
end
|
70
|
+
req = Fraggle::Request.new :tag => 0, :verb => V::NOP
|
71
|
+
bytes = req.encode
|
72
|
+
head = [bytes.length].pack("N")
|
73
|
+
exp = head+bytes
|
87
74
|
|
88
|
-
|
89
|
-
|
75
|
+
got = ""
|
76
|
+
(class << cn ; self ; end).instance_eval do
|
77
|
+
define_method(:send_data) do |data|
|
78
|
+
got << data
|
90
79
|
end
|
91
|
-
end
|
80
|
+
end
|
92
81
|
|
93
|
-
|
94
|
-
|
95
|
-
head = [bytes.length].pack("N")
|
82
|
+
nop = Fraggle::Request.new :verb => V::NOP
|
83
|
+
cn.send_request(nop)
|
96
84
|
|
97
|
-
assert_equal head+bytes,
|
85
|
+
assert_equal head+bytes, got
|
98
86
|
end
|
99
87
|
|
100
88
|
end
|
data/test/fraggle_test.rb
CHANGED
@@ -1,16 +1,11 @@
|
|
1
1
|
require 'fraggle'
|
2
2
|
|
3
3
|
class FraggleTest < Test::Unit::TestCase
|
4
|
-
def test_addrs_for
|
5
|
-
uri = "doozer:?ca=ec2-123:9999&ca=127.0.0.1:8888"
|
6
|
-
addrs = Fraggle.addrs_for(uri)
|
7
|
-
assert_equal ["ec2-123:9999", "127.0.0.1:8888"], addrs
|
8
|
-
end
|
9
4
|
|
10
|
-
def
|
11
|
-
uri
|
12
|
-
|
13
|
-
|
14
|
-
end
|
5
|
+
def test_uri
|
6
|
+
uri = "doozerd:?ca=1:1&ca=2:2&ca=3:3&ignore=this"
|
7
|
+
addrs = Fraggle.uri(uri)
|
8
|
+
assert_equal ["1:1", "2:2", "3:3"], addrs
|
15
9
|
end
|
10
|
+
|
16
11
|
end
|
@@ -0,0 +1,220 @@
|
|
1
|
+
require File.dirname(__FILE__)+"/helper"
|
2
|
+
require 'fraggle/connection'
|
3
|
+
|
4
|
+
class FraggleTransactionTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
attr_reader :cn, :tmp, :valid, :done, :error
|
7
|
+
|
8
|
+
def nop(attrs={})
|
9
|
+
request(V::NOP, attrs)
|
10
|
+
end
|
11
|
+
|
12
|
+
def setup
|
13
|
+
@cn = TestConn.new("127.0.0.1:0")
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_tagging
|
17
|
+
req, _ = nop
|
18
|
+
assert_equal 0, cn.send_request(req).tag
|
19
|
+
req, _ = nop
|
20
|
+
assert_equal 1, cn.send_request(req).tag
|
21
|
+
req, _ = nop
|
22
|
+
assert_equal 2, cn.send_request(req).tag
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_valid
|
26
|
+
req, log = nop
|
27
|
+
req = cn.send_request(req)
|
28
|
+
|
29
|
+
res = Fraggle::Response.new :tag => req.tag, :flags => F::VALID
|
30
|
+
cn.receive_response(res)
|
31
|
+
|
32
|
+
assert_equal [res], log.valid
|
33
|
+
assert_equal [], log.done
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_done
|
37
|
+
req, log = nop
|
38
|
+
req = cn.send_request(req)
|
39
|
+
|
40
|
+
res = Fraggle::Response.new :tag => req.tag, :flags => F::DONE
|
41
|
+
cn.receive_response(res)
|
42
|
+
|
43
|
+
assert_equal [], log.valid
|
44
|
+
assert_equal [req], log.done
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_valid_and_done
|
48
|
+
req, log = nop
|
49
|
+
req = cn.send_request(req)
|
50
|
+
|
51
|
+
res = Fraggle::Response.new :tag => req.tag, :flags => F::VALID|F::DONE
|
52
|
+
cn.receive_response(res)
|
53
|
+
|
54
|
+
assert_equal [res], log.valid
|
55
|
+
assert_equal [req], log.done
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_error
|
59
|
+
req, log = nop
|
60
|
+
req = cn.send_request(req)
|
61
|
+
|
62
|
+
res = Fraggle::Response.new(
|
63
|
+
:tag => req.tag,
|
64
|
+
:flags => F::VALID|F::DONE,
|
65
|
+
:err_code => E::OTHER
|
66
|
+
)
|
67
|
+
|
68
|
+
cn.receive_response(res)
|
69
|
+
|
70
|
+
assert_equal [], log.valid
|
71
|
+
assert_equal [], log.done
|
72
|
+
assert_equal [res], log.error
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_invalid_tag
|
76
|
+
res = Fraggle::Response.new(
|
77
|
+
:tag => 0,
|
78
|
+
:flags => F::VALID|F::DONE,
|
79
|
+
:err_code => E::OTHER
|
80
|
+
)
|
81
|
+
|
82
|
+
assert_nothing_raised do
|
83
|
+
cn.receive_response(res)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_done_deletes_callback
|
88
|
+
req, log = nop
|
89
|
+
req = cn.send_request(req)
|
90
|
+
|
91
|
+
res = Fraggle::Response.new(:tag => req.tag, :flags => F::VALID|F::DONE)
|
92
|
+
cn.receive_response(res)
|
93
|
+
|
94
|
+
# This should be ignored
|
95
|
+
cn.receive_response(res)
|
96
|
+
|
97
|
+
assert_equal [res], log.valid
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_error_with_done_deletes_callback
|
101
|
+
req, log = nop
|
102
|
+
req = cn.send_request(req)
|
103
|
+
|
104
|
+
res = Fraggle::Response.new(
|
105
|
+
:tag => req.tag,
|
106
|
+
:flags => F::VALID|F::DONE,
|
107
|
+
:err_code => E::OTHER
|
108
|
+
)
|
109
|
+
|
110
|
+
cn.receive_response(res)
|
111
|
+
|
112
|
+
# This should be ignored
|
113
|
+
cn.receive_response(res)
|
114
|
+
|
115
|
+
assert_equal [res], log.error
|
116
|
+
end
|
117
|
+
|
118
|
+
def test_cannot_reuse_sent_request
|
119
|
+
req, _ = nop
|
120
|
+
req = cn.send_request(req)
|
121
|
+
|
122
|
+
assert_raises Fraggle::Connection::SendError do
|
123
|
+
cn.send_request(req)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def test_cancel
|
128
|
+
req, _ = nop
|
129
|
+
req = cn.send_request(req)
|
130
|
+
can = req.cancel
|
131
|
+
|
132
|
+
canx = Fraggle::Response.new(:tag => can.tag, :flags => F::VALID|F::DONE)
|
133
|
+
cn.receive_response(canx)
|
134
|
+
end
|
135
|
+
|
136
|
+
def test_cannot_cancel_more_than_once
|
137
|
+
req, _ = nop
|
138
|
+
req = cn.send_request(req)
|
139
|
+
req.cancel
|
140
|
+
|
141
|
+
assert_raises Fraggle::Connection::SendError do
|
142
|
+
req.cancel
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def test_cancel_emits_done
|
147
|
+
req, log = nop
|
148
|
+
req = cn.send_request(req)
|
149
|
+
can = req.cancel
|
150
|
+
|
151
|
+
canx = Fraggle::Response.new(:tag => can.tag, :flags => F::VALID|F::DONE)
|
152
|
+
cn.receive_response(canx)
|
153
|
+
|
154
|
+
assert_equal [req], log.done
|
155
|
+
end
|
156
|
+
|
157
|
+
def test_disconnected
|
158
|
+
a, al = nop
|
159
|
+
a = cn.send_request(a)
|
160
|
+
b, bl = nop
|
161
|
+
b = cn.send_request(b)
|
162
|
+
c, cl = nop
|
163
|
+
c = cn.send_request(c)
|
164
|
+
|
165
|
+
cn.unbind
|
166
|
+
|
167
|
+
assert_equal 1, al.error.length
|
168
|
+
assert_equal nil, al.error.first
|
169
|
+
|
170
|
+
assert_equal 1, bl.error.length
|
171
|
+
assert_equal nil, bl.error.first
|
172
|
+
|
173
|
+
assert_equal 1, cl.error.length
|
174
|
+
assert_equal nil, cl.error.first
|
175
|
+
end
|
176
|
+
|
177
|
+
def test_send_request_in_error_state
|
178
|
+
cn.err = true
|
179
|
+
|
180
|
+
req, log = nop
|
181
|
+
req = cn.send_request(req)
|
182
|
+
assert_equal nil, req.tag
|
183
|
+
|
184
|
+
assert_equal nil, log.error.first
|
185
|
+
end
|
186
|
+
|
187
|
+
def test_liveness
|
188
|
+
live = cn.post_init
|
189
|
+
|
190
|
+
def cn.timer(_, &blk)
|
191
|
+
blk.call
|
192
|
+
end
|
193
|
+
|
194
|
+
res = Fraggle::Response.new(:tag => live.tag, :rev => 1, :flags => F::VALID|F::DONE)
|
195
|
+
cn.receive_response(res)
|
196
|
+
assert ! cn.err?
|
197
|
+
|
198
|
+
# Connections reuse tags and we're only responding to one request in this
|
199
|
+
# test, so we know the next rev will use the previous tag
|
200
|
+
res = Fraggle::Response.new(:tag => live.tag, :rev => 2, :flags => F::VALID|F::DONE)
|
201
|
+
cn.receive_response(res)
|
202
|
+
assert ! cn.err?
|
203
|
+
end
|
204
|
+
|
205
|
+
def test_not_alive
|
206
|
+
live = cn.post_init
|
207
|
+
|
208
|
+
def cn.timer(_, &blk)
|
209
|
+
blk.call
|
210
|
+
end
|
211
|
+
|
212
|
+
res = Fraggle::Response.new(:tag => live.tag, :rev => 1, :flags => F::VALID|F::DONE)
|
213
|
+
cn.receive_response(res)
|
214
|
+
assert ! cn.err?
|
215
|
+
|
216
|
+
cn.receive_response(res)
|
217
|
+
assert cn.err?
|
218
|
+
end
|
219
|
+
|
220
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'fraggle/connection'
|
3
|
+
|
4
|
+
class TestConn
|
5
|
+
include Fraggle::Connection
|
6
|
+
|
7
|
+
attr_reader :sent, :received
|
8
|
+
attr_writer :err
|
9
|
+
|
10
|
+
def initialize(addr)
|
11
|
+
super(addr)
|
12
|
+
@sent = []
|
13
|
+
@received = []
|
14
|
+
@ticks = []
|
15
|
+
end
|
16
|
+
|
17
|
+
def send_request(req)
|
18
|
+
@sent << super(req)
|
19
|
+
req
|
20
|
+
end
|
21
|
+
|
22
|
+
def receive_response(res)
|
23
|
+
@received << res
|
24
|
+
super(res)
|
25
|
+
end
|
26
|
+
|
27
|
+
def send_data(_)
|
28
|
+
end
|
29
|
+
|
30
|
+
def close_connection
|
31
|
+
unbind
|
32
|
+
end
|
33
|
+
|
34
|
+
# Mimic EMs next_tick
|
35
|
+
def next_tick(&blk)
|
36
|
+
@ticks << blk
|
37
|
+
end
|
38
|
+
|
39
|
+
# Mimic a turn in the reactor
|
40
|
+
def tick!
|
41
|
+
@ticks.each {|blk| blk.call }
|
42
|
+
@ticks.clear
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
class Test::Unit::TestCase
|
48
|
+
|
49
|
+
V = Fraggle::Request::Verb
|
50
|
+
F = Fraggle::Response
|
51
|
+
E = Fraggle::Response::Err
|
52
|
+
|
53
|
+
Log = Struct.new(:valid, :error, :done)
|
54
|
+
|
55
|
+
def request(verb, attrs={})
|
56
|
+
logable(Fraggle::Request.new(attrs.merge(:verb => verb)))
|
57
|
+
end
|
58
|
+
|
59
|
+
def logable(req)
|
60
|
+
log = Log.new([], [], [])
|
61
|
+
req.valid do |e|
|
62
|
+
log.valid << e
|
63
|
+
end
|
64
|
+
req.done do
|
65
|
+
log.done << req
|
66
|
+
end
|
67
|
+
req.error do |e|
|
68
|
+
log.error << e
|
69
|
+
end
|
70
|
+
[req, log]
|
71
|
+
end
|
72
|
+
|
73
|
+
def reply(tag, attrs={})
|
74
|
+
attrs[:flags] ||= 0
|
75
|
+
attrs[:flags] |= F::VALID
|
76
|
+
Fraggle::Response.new(attrs.merge(:tag => tag))
|
77
|
+
end
|
78
|
+
|
79
|
+
def reply!(tag, attrs={})
|
80
|
+
attrs[:flags] = F::DONE
|
81
|
+
reply(tag, attrs)
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|