fraggle 0.4.0 → 1.0.0pre
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/.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
|