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
@@ -0,0 +1,139 @@
|
|
1
|
+
require 'fraggle/request'
|
2
|
+
require 'fraggle/response'
|
3
|
+
|
4
|
+
module Fraggle
|
5
|
+
|
6
|
+
module Connection
|
7
|
+
|
8
|
+
# Base class for all Connection errors
|
9
|
+
class Error < StandardError
|
10
|
+
attr_accessor :req
|
11
|
+
|
12
|
+
def initialize(req, msg=nil)
|
13
|
+
@req = req
|
14
|
+
super(msg)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Raised when a request is invalid
|
19
|
+
class SendError < Error
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
attr_reader :last_received, :addr
|
24
|
+
|
25
|
+
def initialize(addr)
|
26
|
+
@addr, @cb = addr, {}
|
27
|
+
end
|
28
|
+
|
29
|
+
def receive_data(data)
|
30
|
+
@last_received = Time.now
|
31
|
+
|
32
|
+
(@buf ||= "") << data
|
33
|
+
|
34
|
+
while @buf.length > 0
|
35
|
+
if @len && @buf.length >= @len
|
36
|
+
bytes = @buf.slice!(0, @len)
|
37
|
+
@len = nil
|
38
|
+
res = Response.decode(bytes)
|
39
|
+
receive_response(res)
|
40
|
+
elsif @buf.length >= 4
|
41
|
+
bytes = @buf.slice!(0, 4)
|
42
|
+
@len = bytes.unpack("N")[0]
|
43
|
+
else
|
44
|
+
break
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# The default receive_response
|
50
|
+
def receive_response(res)
|
51
|
+
req = @cb[res.tag]
|
52
|
+
|
53
|
+
if ! req
|
54
|
+
return
|
55
|
+
end
|
56
|
+
|
57
|
+
if ! res.ok?
|
58
|
+
@cb.delete(req.tag)
|
59
|
+
req.emit(:error, res)
|
60
|
+
return
|
61
|
+
end
|
62
|
+
|
63
|
+
if res.done?
|
64
|
+
@cb.delete(req.tag)
|
65
|
+
req.emit(:done)
|
66
|
+
end
|
67
|
+
|
68
|
+
if res.valid?
|
69
|
+
req.emit(:valid, res)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def send_request(req)
|
74
|
+
if req.tag
|
75
|
+
raise SendError, "Already sent #{req.inspect}"
|
76
|
+
end
|
77
|
+
|
78
|
+
if err?
|
79
|
+
next_tick { req.emit(:error, nil) }
|
80
|
+
return req
|
81
|
+
end
|
82
|
+
|
83
|
+
req.tag = 0
|
84
|
+
while @cb.has_key?(req.tag)
|
85
|
+
req.tag += 1
|
86
|
+
|
87
|
+
req.tag %= 2**31
|
88
|
+
end
|
89
|
+
|
90
|
+
req.cn = self
|
91
|
+
|
92
|
+
@cb[req.tag] = req
|
93
|
+
|
94
|
+
data = req.encode
|
95
|
+
head = [data.length].pack("N")
|
96
|
+
|
97
|
+
send_data("#{head}#{data}")
|
98
|
+
|
99
|
+
req
|
100
|
+
end
|
101
|
+
|
102
|
+
def post_init
|
103
|
+
last = 0
|
104
|
+
rev = Request.new :verb => Request::Verb::REV
|
105
|
+
|
106
|
+
rev.valid do |e|
|
107
|
+
if e.rev <= last
|
108
|
+
close_connection
|
109
|
+
else
|
110
|
+
timer(5) { send_request(rev.dup) }
|
111
|
+
last = e.rev
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
send_request(rev.dup)
|
116
|
+
end
|
117
|
+
|
118
|
+
def unbind
|
119
|
+
@err = true
|
120
|
+
@cb.values.each do |req|
|
121
|
+
req.emit(:error, nil)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def err?
|
126
|
+
!!@err
|
127
|
+
end
|
128
|
+
|
129
|
+
def timer(n, &blk)
|
130
|
+
EM.add_timer(n, &blk)
|
131
|
+
end
|
132
|
+
|
133
|
+
def next_tick(&blk)
|
134
|
+
EM.next_tick(&blk)
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
## Generated from msg.proto for proto
|
2
|
+
require "beefcake"
|
3
|
+
|
4
|
+
module Fraggle
|
5
|
+
|
6
|
+
class Request
|
7
|
+
include Beefcake::Message
|
8
|
+
|
9
|
+
module Verb
|
10
|
+
CHECKIN = 0
|
11
|
+
GET = 1
|
12
|
+
SET = 2
|
13
|
+
DEL = 3
|
14
|
+
ESET = 4
|
15
|
+
REV = 5
|
16
|
+
NOP = 7
|
17
|
+
WATCH = 8
|
18
|
+
WALK = 9
|
19
|
+
CANCEL = 10
|
20
|
+
GETDIR = 14
|
21
|
+
STAT = 16
|
22
|
+
end
|
23
|
+
|
24
|
+
required :tag, :int32, 1
|
25
|
+
required :verb, Request::Verb, 2
|
26
|
+
optional :path, :string, 4
|
27
|
+
optional :value, :bytes, 5
|
28
|
+
optional :other_tag, :int32, 6
|
29
|
+
optional :offset, :int32, 7
|
30
|
+
optional :limit, :int32, 8
|
31
|
+
optional :rev, :int64, 9
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
class Response
|
36
|
+
include Beefcake::Message
|
37
|
+
|
38
|
+
module Err
|
39
|
+
OTHER = 127
|
40
|
+
TAG_IN_USE = 1
|
41
|
+
UNKNOWN_VERB = 2
|
42
|
+
REDIRECT = 3
|
43
|
+
TOO_LATE = 4
|
44
|
+
REV_MISMATCH = 5
|
45
|
+
BAD_PATH = 6
|
46
|
+
MISSING_ARG = 7
|
47
|
+
NOTDIR = 20
|
48
|
+
ISDIR = 21
|
49
|
+
NOENT = 22
|
50
|
+
end
|
51
|
+
|
52
|
+
required :tag, :int32, 1
|
53
|
+
required :flags, :int32, 2
|
54
|
+
optional :rev, :int64, 3
|
55
|
+
optional :path, :string, 5
|
56
|
+
optional :value, :bytes, 6
|
57
|
+
optional :len, :int32, 8
|
58
|
+
optional :err_code, Response::Err, 100
|
59
|
+
optional :err_detail, :string, 101
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
data/lib/fraggle/request.rb
CHANGED
@@ -1,15 +1,42 @@
|
|
1
|
-
require 'fraggle/msg'
|
2
|
-
require 'fraggle/emitter'
|
3
|
-
|
4
|
-
##
|
5
|
-
# An extension to Request in msg.rb. I want to keep these seperated so when
|
6
|
-
# future versions of Beefcake can generate code, we don't have to manually add
|
7
|
-
# this back in for each generation.
|
1
|
+
require 'fraggle/msg.pb'
|
8
2
|
|
9
3
|
module Fraggle
|
10
|
-
|
11
4
|
class Request
|
12
|
-
include Emitter
|
13
|
-
end
|
14
5
|
|
6
|
+
attr_accessor :cn
|
7
|
+
attr_reader :cb
|
8
|
+
|
9
|
+
def initialize(attrs={})
|
10
|
+
super(attrs)
|
11
|
+
@cb = Hash.new(Proc.new{})
|
12
|
+
end
|
13
|
+
|
14
|
+
def valid(&blk)
|
15
|
+
@cb[:valid] = blk
|
16
|
+
self
|
17
|
+
end
|
18
|
+
|
19
|
+
def done(&blk)
|
20
|
+
@cb[:done] = blk
|
21
|
+
self
|
22
|
+
end
|
23
|
+
|
24
|
+
def error(&blk)
|
25
|
+
@cb[:error] = blk
|
26
|
+
self
|
27
|
+
end
|
28
|
+
|
29
|
+
def emit(name, *args)
|
30
|
+
@cb[name].call(*args)
|
31
|
+
end
|
32
|
+
|
33
|
+
def cancel
|
34
|
+
@can ||= Request.new(:verb => Verb::CANCEL, :other_tag => self.tag)
|
35
|
+
req = cn.send_request(@can)
|
36
|
+
req.done do
|
37
|
+
emit(:done)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
15
42
|
end
|
data/lib/fraggle/response.rb
CHANGED
@@ -1,49 +1,28 @@
|
|
1
|
-
require 'fraggle/msg'
|
2
|
-
|
3
|
-
##
|
4
|
-
# An extension to Response in msg.rb. I want to keep these seperated so when
|
5
|
-
# future versions of Beefcake can generate code, we don't have to manually add
|
6
|
-
# this back in for each generation.
|
1
|
+
require 'fraggle/msg.pb'
|
7
2
|
|
8
3
|
module Fraggle
|
9
|
-
|
10
4
|
class Response
|
11
5
|
|
12
|
-
|
13
|
-
|
14
|
-
DONE = 2
|
15
|
-
SET = 4
|
16
|
-
DEL = 8
|
17
|
-
end
|
18
|
-
|
19
|
-
|
20
|
-
Missing = 0
|
21
|
-
Clobber = -1
|
22
|
-
Dir = -2
|
23
|
-
Nop = -3
|
6
|
+
VALID = 1
|
7
|
+
DONE = 2
|
24
8
|
|
25
|
-
|
9
|
+
def valid?
|
10
|
+
return false if !flags
|
11
|
+
(flags & VALID) > 0
|
12
|
+
end
|
26
13
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
14
|
+
def done?
|
15
|
+
return false if !flags
|
16
|
+
(flags & DONE) > 0
|
17
|
+
end
|
31
18
|
|
32
|
-
def
|
33
|
-
|
19
|
+
def ok?
|
20
|
+
err_code.nil?
|
21
|
+
end
|
34
22
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
def unknown_verb? ; err_code == Err::UNKNOWN_VERB ; end
|
39
|
-
def redirect? ; err_code == Err::REDIRECT ; end
|
40
|
-
def too_late? ; err_code == Err::TOO_LATE ; end
|
41
|
-
def mismatch? ; err_code == Err::CAS_MISMATCH ; end
|
42
|
-
def not_dir? ; err_code == Err::NOT_DIR ; end
|
43
|
-
def is_dir? ; err_code == Err::ISDIR ; end
|
23
|
+
def redirect?
|
24
|
+
err_code == Err::REDIRECT
|
25
|
+
end
|
44
26
|
|
45
|
-
# Custom
|
46
|
-
def disconnected? ; err_code == Errno::ECONNREFUSED::Errno ; end
|
47
27
|
end
|
48
|
-
|
49
28
|
end
|
data/test/fraggle_client_test.rb
CHANGED
@@ -1,239 +1,259 @@
|
|
1
|
+
require File.dirname(__FILE__)+"/helper"
|
1
2
|
require 'fraggle/client'
|
2
|
-
require 'fraggle/response'
|
3
|
-
require 'fraggle/test'
|
4
3
|
|
5
4
|
class FraggleClientTest < Test::Unit::TestCase
|
6
|
-
include Fraggle::Test
|
7
5
|
|
8
|
-
attr_reader :c, :blk
|
6
|
+
attr_reader :c, :addrs, :blk, :called
|
9
7
|
|
10
8
|
def setup
|
11
|
-
|
12
|
-
|
13
|
-
end
|
9
|
+
addr = "127.0.0.1:0"
|
10
|
+
cn = TestConn.new(addr)
|
14
11
|
|
15
|
-
|
16
|
-
|
12
|
+
@addrs = ["1.1.1.1:1", "2.2.2.2:2", "3.3.3.3:3"]
|
13
|
+
@c = Fraggle::Client.new(cn, @addrs)
|
17
14
|
|
18
|
-
|
19
|
-
|
15
|
+
def @c.reconnect(addr)
|
16
|
+
@cn = TestConn.new(addr)
|
17
|
+
end
|
20
18
|
end
|
21
19
|
|
22
|
-
def
|
23
|
-
req =
|
20
|
+
def test_send_valid_done
|
21
|
+
req, log = request(V::NOP)
|
22
|
+
req = c.send(req)
|
24
23
|
|
25
|
-
|
26
|
-
|
27
|
-
reply(req.tag)
|
24
|
+
res = Fraggle::Response.new :tag => req.tag, :value => "ing", :flags => F::VALID|F::DONE
|
25
|
+
c.cn.receive_response(res)
|
28
26
|
|
29
|
-
assert_equal
|
27
|
+
assert_equal [res], log.valid
|
28
|
+
assert_equal [req], log.done
|
29
|
+
assert_equal [], log.error
|
30
30
|
end
|
31
31
|
|
32
|
-
def
|
33
|
-
req =
|
34
|
-
req.
|
35
|
-
|
36
|
-
reply!(req.tag)
|
37
|
-
|
38
|
-
assert_equal 1, blk.length
|
32
|
+
def test_send_error
|
33
|
+
req, log = request(V::NOP)
|
34
|
+
req = c.send(req)
|
39
35
|
|
40
|
-
req.
|
36
|
+
res = Fraggle::Response.new :tag => req.tag, :err_code => E::OTHER, :flags => F::VALID|F::DONE
|
37
|
+
c.cn.receive_response(res)
|
41
38
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
assert_equal 1, blk.length
|
39
|
+
assert_equal [], log.valid
|
40
|
+
assert_equal [], log.done
|
41
|
+
assert_equal [res], log.error
|
47
42
|
end
|
48
43
|
|
49
|
-
def
|
50
|
-
|
51
|
-
req.error(&blk)
|
44
|
+
def test_reconnect_without_pending_requests
|
45
|
+
exp = @addrs.dup
|
52
46
|
|
53
|
-
|
54
|
-
|
47
|
+
# Disconnect from 127.0.0.1:0
|
48
|
+
c.cn.close_connection
|
55
49
|
|
56
|
-
|
57
|
-
|
50
|
+
# Send a request to invoke reconnect
|
51
|
+
req, log = request(V::NOP)
|
52
|
+
req = c.send(req)
|
58
53
|
|
59
|
-
|
60
|
-
|
54
|
+
# Fake reactor turn (only available in tests)
|
55
|
+
c.cn.tick!
|
61
56
|
|
62
|
-
|
63
|
-
assert_equal t+1, c.noop.tag
|
64
|
-
assert_equal t+2, c.noop.tag
|
65
|
-
assert_equal t+3, c.noop.tag
|
66
|
-
assert_equal t+4, c.noop.tag
|
67
|
-
end
|
57
|
+
assert exp.include?(c.cn.addr), "#{c.cn.addr.inspect} not in #{exp.inspect}"
|
68
58
|
|
69
|
-
|
70
|
-
|
71
|
-
c.send(req)
|
72
|
-
assert_sent 99
|
59
|
+
# If the client can handle an error, it should not mention it to the user.
|
60
|
+
assert_equal [], log.error
|
73
61
|
end
|
74
62
|
|
75
|
-
|
76
|
-
|
77
|
-
req = c.checkin("abc123", 123).valid(&blk)
|
63
|
+
def test_reconnect_with_pending_request
|
64
|
+
exp = @addrs.dup
|
78
65
|
|
79
|
-
|
80
|
-
|
81
|
-
|
66
|
+
# Send a request to invoke reconnect
|
67
|
+
req, log = request(V::NOP)
|
68
|
+
req = c.send(req)
|
82
69
|
|
83
|
-
|
84
|
-
|
85
|
-
req = c.get(0, "/ping").valid(&blk)
|
70
|
+
# Disconnect from 127.0.0.1:0
|
71
|
+
c.cn.close_connection
|
86
72
|
|
87
|
-
|
88
|
-
|
89
|
-
end
|
73
|
+
# Fake reactor turn (only available in tests)
|
74
|
+
c.cn.tick!
|
90
75
|
|
91
|
-
|
92
|
-
def test_stat
|
93
|
-
req = c.stat(0, "/ping").valid(&blk)
|
76
|
+
assert exp.include?(c.cn.addr), "#{c.cn.addr.inspect} not in #{exp.inspect}"
|
94
77
|
|
95
|
-
|
96
|
-
|
78
|
+
# If the client can handle an error, it should not mention it to the user.
|
79
|
+
assert_equal [], log.error
|
97
80
|
end
|
98
81
|
|
99
|
-
#
|
100
|
-
def
|
101
|
-
req =
|
102
|
-
|
103
|
-
assert_sent req.tag, :rev => 0, :verb => V::GETDIR, :path => "/test"
|
104
|
-
assert_recv reply(req.tag, :rev => 123, :value => "a")
|
82
|
+
# retry
|
83
|
+
def test_resend_pending_requests
|
84
|
+
req, log = request(V::GET, :path => "/foo")
|
85
|
+
req = c.resend(req)
|
105
86
|
|
106
|
-
|
87
|
+
c.cn.close_connection
|
107
88
|
|
108
|
-
|
109
|
-
assert_recv reply(req.tag, :cas => 123, :value => "b")
|
89
|
+
assert_equal [req], c.cn.sent
|
110
90
|
end
|
111
91
|
|
112
|
-
|
113
|
-
|
114
|
-
req = c.
|
92
|
+
def test_manage_offset
|
93
|
+
req, log = request(V::WALK, :path => "/foo/*", :offset => 3)
|
94
|
+
req = c.resend(req)
|
115
95
|
|
116
|
-
|
117
|
-
|
118
|
-
end
|
96
|
+
res = Fraggle::Response.new :tag => req.tag, :flags => F::VALID
|
97
|
+
c.cn.receive_response(res)
|
119
98
|
|
120
|
-
|
121
|
-
def test_del
|
122
|
-
req = c.del("/foo", 123).valid(&blk)
|
99
|
+
c.cn.close_connection
|
123
100
|
|
124
|
-
|
125
|
-
|
101
|
+
exp, _ = request(V::WALK, :tag => req.tag, :path => "/foo/*", :offset => 4)
|
102
|
+
assert_equal [exp], c.cn.sent
|
126
103
|
end
|
127
104
|
|
128
|
-
|
129
|
-
|
130
|
-
req = c.
|
131
|
-
|
132
|
-
assert_respond_to req, :cancel
|
105
|
+
def test_manage_limit
|
106
|
+
req, log = request(V::WALK, :path => "/foo/*", :limit => 4)
|
107
|
+
req = c.resend(req)
|
133
108
|
|
134
|
-
|
135
|
-
|
136
|
-
assert_recv(reply(req.tag, :rev => 456, :path => "/foo/b", :value => "2"))
|
137
|
-
assert_recv(reply(req.tag, :rev => 789, :path => "/foo/c", :value => "3"))
|
138
|
-
end
|
109
|
+
res = Fraggle::Response.new :tag => req.tag, :flags => F::VALID
|
110
|
+
c.cn.receive_response(res)
|
139
111
|
|
140
|
-
|
141
|
-
def test_watch
|
142
|
-
req = c.watch(123, "/foo/*").valid(&blk)
|
112
|
+
c.cn.close_connection
|
143
113
|
|
144
|
-
|
114
|
+
exp, _ = request(V::WALK, :tag => req.tag, :path => "/foo/*", :limit => 3)
|
115
|
+
assert_equal [exp], c.cn.sent
|
116
|
+
end
|
145
117
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
118
|
+
def test_manage_rev
|
119
|
+
req, log = request(V::WALK, :path => "/foo/*", :rev => 4)
|
120
|
+
req = c.resend(req)
|
121
|
+
|
122
|
+
# nil rev
|
123
|
+
res = Fraggle::Response.new :tag => req.tag, :flags => F::VALID
|
124
|
+
c.cn.receive_response(res)
|
125
|
+
assert_equal 4, req.rev
|
126
|
+
|
127
|
+
# equal to rev
|
128
|
+
res = Fraggle::Response.new :tag => req.tag, :rev => 4, :flags => F::VALID
|
129
|
+
c.cn.receive_response(res)
|
130
|
+
assert_equal 4, req.rev
|
131
|
+
|
132
|
+
# less than rev
|
133
|
+
res = Fraggle::Response.new :tag => req.tag, :rev => 3, :flags => F::VALID
|
134
|
+
c.cn.receive_response(res)
|
135
|
+
assert_equal 4, req.rev
|
136
|
+
|
137
|
+
# greater than rev
|
138
|
+
# NOTE: This will never happen in life on a WALK, this is purely a
|
139
|
+
# test.
|
140
|
+
res = Fraggle::Response.new :tag => req.tag, :rev => 5, :flags => F::VALID
|
141
|
+
c.cn.receive_response(res)
|
142
|
+
assert_equal 5, req.rev
|
143
|
+
|
144
|
+
# force retry
|
145
|
+
c.cn.close_connection
|
146
|
+
|
147
|
+
exp, _ = request(V::WALK, :tag => req.tag, :rev => 5, :path => "/foo/*")
|
148
|
+
assert_equal [exp], c.cn.sent
|
150
149
|
end
|
151
150
|
|
152
|
-
|
153
|
-
|
154
|
-
req = c.
|
151
|
+
def test_redirect
|
152
|
+
req, log = request(V::SET, :rev => 0, :path => "/foo", :value => "bar")
|
153
|
+
req = c.send(req)
|
155
154
|
|
156
|
-
|
157
|
-
|
158
|
-
|
155
|
+
res = Fraggle::Response.new(
|
156
|
+
:tag => req.tag,
|
157
|
+
:err_code => E::REDIRECT,
|
158
|
+
:err_detail => "9.9.9.9:9",
|
159
|
+
:flags => F::VALID|F::DONE
|
160
|
+
)
|
159
161
|
|
160
|
-
|
161
|
-
def test_cancel
|
162
|
-
nop = c.noop.valid(&blk)
|
163
|
-
req = c.__cancel__(nop).valid(&blk)
|
162
|
+
c.cn.receive_response(res)
|
164
163
|
|
165
|
-
|
166
|
-
assert_recv(reply(req.tag))
|
164
|
+
assert_equal "1.1.1.1:1", c.cn.addr
|
167
165
|
end
|
168
166
|
|
169
|
-
def test_cancelable
|
170
|
-
can = c.cancelable(Fraggle::Request.new(:tag => 123))
|
171
167
|
|
172
|
-
|
168
|
+
###
|
169
|
+
# Sugar
|
173
170
|
|
174
|
-
|
171
|
+
def last_sent
|
172
|
+
c.cn.sent.last
|
173
|
+
end
|
175
174
|
|
176
|
-
|
177
|
-
|
178
|
-
|
175
|
+
def assert_verb(exp, name, *args)
|
176
|
+
called = false
|
177
|
+
blk = Proc.new { called = true }
|
178
|
+
req = c.__send__(name, *args, &blk)
|
179
|
+
exp[:tag] = req.tag
|
180
|
+
assert_equal exp, last_sent.to_hash
|
179
181
|
|
180
|
-
|
181
|
-
|
182
|
-
|
182
|
+
c.cn.receive_response(reply(req.tag))
|
183
|
+
assert called
|
184
|
+
end
|
183
185
|
|
184
|
-
|
185
|
-
|
186
|
+
def test_set
|
187
|
+
exp = {
|
188
|
+
:verb => V::SET,
|
189
|
+
:rev => 0,
|
190
|
+
:path => "/foo",
|
191
|
+
:value => "bar"
|
192
|
+
}
|
193
|
+
|
194
|
+
assert_verb exp, :set, 0, "/foo", "bar"
|
186
195
|
end
|
187
196
|
|
188
|
-
def
|
189
|
-
|
190
|
-
|
197
|
+
def test_get
|
198
|
+
exp = {
|
199
|
+
:verb => V::GET,
|
200
|
+
:rev => 0,
|
201
|
+
:path => "/foo"
|
202
|
+
}
|
191
203
|
|
192
|
-
|
193
|
-
assert_not_equal x.tag, y.tag
|
204
|
+
assert_verb exp, :get, 0, "/foo"
|
194
205
|
end
|
195
206
|
|
196
|
-
def
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
207
|
+
def test_del
|
208
|
+
exp = {
|
209
|
+
:verb => V::DEL,
|
210
|
+
:rev => 0,
|
211
|
+
:path => "/foo"
|
212
|
+
}
|
201
213
|
|
202
|
-
|
203
|
-
# remaining data from the server should be discarded.
|
204
|
-
assert_equal 0, blk.length
|
214
|
+
assert_verb exp, :del, 0, "/foo"
|
205
215
|
end
|
206
216
|
|
207
|
-
def
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
217
|
+
def test_getdir
|
218
|
+
exp = {
|
219
|
+
:verb => V::GETDIR,
|
220
|
+
:rev => 0,
|
221
|
+
:path => "/foo",
|
222
|
+
:offset => 0,
|
223
|
+
:limit => 5
|
224
|
+
}
|
225
|
+
|
226
|
+
assert_verb exp, :getdir, 0, "/foo", 0, 5
|
227
|
+
end
|
214
228
|
|
215
|
-
|
229
|
+
def test_rev
|
230
|
+
exp = {
|
231
|
+
:verb => V::REV
|
232
|
+
}
|
216
233
|
|
217
|
-
|
218
|
-
assert_not_equal y.tag, z.tag
|
234
|
+
assert_verb exp, :rev
|
219
235
|
end
|
220
236
|
|
221
|
-
def
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
237
|
+
def test_walk
|
238
|
+
exp = {
|
239
|
+
:verb => V::WALK,
|
240
|
+
:rev => 0,
|
241
|
+
:path => "/foo/*",
|
242
|
+
:offset => 0,
|
243
|
+
:limit => 5
|
244
|
+
}
|
245
|
+
|
246
|
+
assert_verb exp, :walk, 0, "/foo/*", 0, 5
|
247
|
+
end
|
226
248
|
|
227
|
-
|
249
|
+
def test_watch
|
250
|
+
exp = {
|
251
|
+
:verb => V::WATCH,
|
252
|
+
:rev => 0,
|
253
|
+
:path => "/foo/*"
|
254
|
+
}
|
228
255
|
|
229
|
-
|
256
|
+
assert_verb exp, :watch, 0, "/foo/*"
|
230
257
|
end
|
231
258
|
|
232
|
-
# These are planned for future doozer versions
|
233
|
-
#
|
234
|
-
# ESET cas, path => {}
|
235
|
-
# GETDIR path => {cas, value}+
|
236
|
-
# MONITOR path => {cas, path, value}+
|
237
|
-
# SYNCPATH path => cas, value
|
238
|
-
|
239
259
|
end
|