ruby_ami 1.3.4 → 2.0.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.
- checksums.yaml +4 -4
- data/.travis.yml +1 -0
- data/CHANGELOG.md +5 -2
- data/README.md +14 -15
- data/features/support/lexer_helper.rb +18 -0
- data/lib/ruby_ami/action.rb +19 -65
- data/lib/ruby_ami/agi_result_parser.rb +2 -2
- data/lib/ruby_ami/client.rb +28 -159
- data/lib/ruby_ami/error.rb +2 -2
- data/lib/ruby_ami/event.rb +2 -2
- data/lib/ruby_ami/response.rb +6 -8
- data/lib/ruby_ami/stream.rb +76 -11
- data/lib/ruby_ami/version.rb +1 -1
- data/lib/ruby_ami.rb +0 -9
- data/ruby_ami.gemspec +0 -4
- data/spec/ruby_ami/action_spec.rb +27 -78
- data/spec/ruby_ami/agi_result_parser_spec.rb +0 -9
- data/spec/ruby_ami/client_spec.rb +17 -287
- data/spec/ruby_ami/event_spec.rb +24 -30
- data/spec/ruby_ami/response_spec.rb +12 -20
- data/spec/ruby_ami/stream_spec.rb +142 -49
- data/spec/spec_helper.rb +2 -3
- data/spec/support/mock_server.rb +0 -4
- metadata +2 -59
- data/lib/ruby_ami/metaprogramming.rb +0 -18
@@ -5,6 +5,10 @@ module RubyAMI
|
|
5
5
|
describe Stream do
|
6
6
|
let(:server_port) { 50000 - rand(1000) }
|
7
7
|
|
8
|
+
def client
|
9
|
+
@client ||= mock('Client')
|
10
|
+
end
|
11
|
+
|
8
12
|
before do
|
9
13
|
def client.message_received(message)
|
10
14
|
@messages ||= Queue.new
|
@@ -22,23 +26,28 @@ module RubyAMI
|
|
22
26
|
messages
|
23
27
|
end
|
24
28
|
|
29
|
+
let(:username) { nil }
|
30
|
+
let(:password) { nil }
|
31
|
+
|
25
32
|
def mocked_server(times = nil, fake_client = nil, &block)
|
26
33
|
mock_target = MockServer.new
|
27
|
-
mock_target.
|
34
|
+
mock_target.should_receive(:receive_data).send(*(times ? [:exactly, times] : [:at_least, 1])).with &block
|
28
35
|
s = ServerMock.new '127.0.0.1', server_port, mock_target
|
29
|
-
@stream = Stream.new '127.0.0.1', server_port, lambda { |m| client.message_received m }
|
36
|
+
@stream = Stream.new '127.0.0.1', server_port, username, password, lambda { |m| client.message_received m }
|
30
37
|
@stream.async.run
|
31
38
|
fake_client.call if fake_client.respond_to? :call
|
32
39
|
Celluloid::Actor.join s
|
33
|
-
|
40
|
+
Timeout.timeout 5 do
|
41
|
+
Celluloid::Actor.join @stream
|
42
|
+
end
|
34
43
|
end
|
35
44
|
|
36
45
|
def expect_connected_event
|
37
|
-
client.
|
46
|
+
client.should_receive(:message_received).with Stream::Connected.new
|
38
47
|
end
|
39
48
|
|
40
49
|
def expect_disconnected_event
|
41
|
-
client.
|
50
|
+
client.should_receive(:message_received).with Stream::Disconnected.new
|
42
51
|
end
|
43
52
|
|
44
53
|
before { @sequence = 1 }
|
@@ -47,17 +56,72 @@ module RubyAMI
|
|
47
56
|
it "should be started" do
|
48
57
|
expect_connected_event
|
49
58
|
expect_disconnected_event
|
50
|
-
mocked_server
|
51
|
-
|
59
|
+
mocked_server 0, -> { @stream.started?.should be_true }
|
60
|
+
end
|
61
|
+
|
62
|
+
it "can send an action" do
|
63
|
+
expect_connected_event
|
64
|
+
expect_disconnected_event
|
65
|
+
mocked_server(1, lambda { @stream.send_action('Command') }) do |val, server|
|
66
|
+
val.should == <<-ACTION
|
67
|
+
Action: command\r
|
68
|
+
ActionID: #{RubyAMI.new_uuid}\r
|
69
|
+
\r
|
70
|
+
ACTION
|
71
|
+
|
72
|
+
server.send_data <<-EVENT
|
73
|
+
Response: Success
|
74
|
+
ActionID: #{RubyAMI.new_uuid}
|
75
|
+
Message: Recording started
|
76
|
+
|
77
|
+
EVENT
|
52
78
|
end
|
53
79
|
end
|
54
80
|
|
55
|
-
it "can send
|
81
|
+
it "can send an action with headers" do
|
56
82
|
expect_connected_event
|
57
83
|
expect_disconnected_event
|
58
|
-
|
59
|
-
|
60
|
-
|
84
|
+
mocked_server(1, lambda { @stream.send_action('Command', 'Command' => 'RECORD FILE evil') }) do |val, server|
|
85
|
+
val.should == <<-ACTION
|
86
|
+
Action: command\r
|
87
|
+
ActionID: #{RubyAMI.new_uuid}\r
|
88
|
+
Command: RECORD FILE evil\r
|
89
|
+
\r
|
90
|
+
ACTION
|
91
|
+
|
92
|
+
server.send_data <<-EVENT
|
93
|
+
Response: Success
|
94
|
+
ActionID: #{RubyAMI.new_uuid}
|
95
|
+
Message: Recording started
|
96
|
+
|
97
|
+
EVENT
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
context "with a username and password set" do
|
102
|
+
let(:username) { 'fred' }
|
103
|
+
let(:password) { 'jones' }
|
104
|
+
|
105
|
+
it "should log itself in" do
|
106
|
+
expect_connected_event
|
107
|
+
expect_disconnected_event
|
108
|
+
mocked_server(1, lambda { }) do |val, server|
|
109
|
+
val.should == <<-ACTION
|
110
|
+
Action: login\r
|
111
|
+
ActionID: #{RubyAMI.new_uuid}\r
|
112
|
+
Username: fred\r
|
113
|
+
Secret: jones\r
|
114
|
+
Events: On\r
|
115
|
+
\r
|
116
|
+
ACTION
|
117
|
+
|
118
|
+
server.send_data <<-EVENT
|
119
|
+
Response: Success
|
120
|
+
ActionID: #{RubyAMI.new_uuid}
|
121
|
+
Message: Authentication accepted
|
122
|
+
|
123
|
+
EVENT
|
124
|
+
end
|
61
125
|
end
|
62
126
|
end
|
63
127
|
end
|
@@ -75,57 +139,86 @@ Cause: 0
|
|
75
139
|
|
76
140
|
client_messages.should be == [
|
77
141
|
Stream::Connected.new,
|
78
|
-
Event.new('Hangup'
|
79
|
-
e['Channel'] = 'SIP/101-3f3f'
|
80
|
-
e['Uniqueid'] = '1094154427.10'
|
81
|
-
e['Cause'] = '0'
|
82
|
-
end,
|
142
|
+
Event.new('Hangup', 'Channel' => 'SIP/101-3f3f', 'Uniqueid' => '1094154427.10', 'Cause' => '0'),
|
83
143
|
Stream::Disconnected.new
|
84
144
|
]
|
85
145
|
end
|
86
146
|
|
87
|
-
|
88
|
-
|
89
|
-
|
147
|
+
describe 'when a response is received' do
|
148
|
+
before do
|
149
|
+
expect_connected_event
|
150
|
+
expect_disconnected_event
|
151
|
+
end
|
152
|
+
|
153
|
+
it 'should be returned from #send_action' do
|
154
|
+
response = nil
|
155
|
+
mocked_server(1, lambda { response = @stream.send_action 'Command', 'Command' => 'RECORD FILE evil' }) do |val, server|
|
156
|
+
server.send_data <<-EVENT
|
90
157
|
Response: Success
|
91
|
-
ActionID:
|
92
|
-
Message:
|
158
|
+
ActionID: #{RubyAMI.new_uuid}
|
159
|
+
Message: Recording started
|
93
160
|
|
94
|
-
|
161
|
+
EVENT
|
162
|
+
end
|
163
|
+
|
164
|
+
response.should == Response.new('ActionID' => RubyAMI.new_uuid, 'Message' => 'Recording started')
|
95
165
|
end
|
96
166
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
Stream::Disconnected.new
|
104
|
-
]
|
105
|
-
end
|
167
|
+
describe 'when it is an error' do
|
168
|
+
it 'should be raised by #send_action, but not kill the stream' do
|
169
|
+
send_action = lambda do
|
170
|
+
expect { @stream.send_action 'status' }.to raise_error(RubyAMI::Error, 'Action failed')
|
171
|
+
@stream.should be_alive
|
172
|
+
end
|
106
173
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
r['Message'].should == 'You stupid git'
|
116
|
-
when 3
|
117
|
-
r.should be_a Stream::Disconnected
|
174
|
+
mocked_server(1, send_action) do |val, server|
|
175
|
+
server.send_data <<-EVENT
|
176
|
+
Response: Error
|
177
|
+
ActionID: #{RubyAMI.new_uuid}
|
178
|
+
Message: Action failed
|
179
|
+
|
180
|
+
EVENT
|
181
|
+
end
|
118
182
|
end
|
119
|
-
@sequence += 1
|
120
183
|
end
|
121
184
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
ActionID
|
126
|
-
|
185
|
+
describe 'for a causal action' do
|
186
|
+
let :expected_events do
|
187
|
+
[
|
188
|
+
Event.new('PeerEntry', 'ActionID' => RubyAMI.new_uuid, 'Channeltype' => 'SIP', 'ObjectName' => 'usera'),
|
189
|
+
Event.new('PeerlistComplete', 'ActionID' => RubyAMI.new_uuid, 'EventList' => 'Complete', 'ListItems' => '2')
|
190
|
+
]
|
191
|
+
end
|
127
192
|
|
128
|
-
|
193
|
+
let :expected_response do
|
194
|
+
Response.new('ActionID' => RubyAMI.new_uuid, 'Message' => 'Events to follow').tap do |response|
|
195
|
+
response.events = expected_events
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
it "should return the response with events" do
|
200
|
+
response = nil
|
201
|
+
mocked_server(1, lambda { response = @stream.send_action 'sippeers' }) do |val, server|
|
202
|
+
server.send_data <<-EVENT
|
203
|
+
Response: Success
|
204
|
+
ActionID: #{RubyAMI.new_uuid}
|
205
|
+
Message: Events to follow
|
206
|
+
|
207
|
+
Event: PeerEntry
|
208
|
+
ActionID: #{RubyAMI.new_uuid}
|
209
|
+
Channeltype: SIP
|
210
|
+
ObjectName: usera
|
211
|
+
|
212
|
+
Event: PeerlistComplete
|
213
|
+
EventList: Complete
|
214
|
+
ListItems: 2
|
215
|
+
ActionID: #{RubyAMI.new_uuid}
|
216
|
+
|
217
|
+
EVENT
|
218
|
+
end
|
219
|
+
|
220
|
+
response.should == expected_response
|
221
|
+
end
|
129
222
|
end
|
130
223
|
end
|
131
224
|
|
data/spec/spec_helper.rb
CHANGED
@@ -1,19 +1,18 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
require 'ruby_ami'
|
4
|
-
require 'countdownlatch'
|
5
4
|
|
6
5
|
Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each {|f| require f}
|
7
6
|
|
8
7
|
include RubyAMI
|
9
8
|
|
10
9
|
RSpec.configure do |config|
|
11
|
-
config.mock_with :
|
10
|
+
config.mock_with :rspec
|
12
11
|
config.filter_run :focus => true
|
13
12
|
config.run_all_when_everything_filtered = true
|
14
13
|
|
15
14
|
config.before :each do
|
16
15
|
uuid = RubyAMI.new_uuid
|
17
|
-
RubyAMI.
|
16
|
+
RubyAMI.stub :new_uuid => uuid
|
18
17
|
end
|
19
18
|
end
|
data/spec/support/mock_server.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby_ami
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben Langfeld
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-04-
|
11
|
+
date: 2013-04-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: celluloid-io
|
@@ -24,48 +24,6 @@ dependencies:
|
|
24
24
|
- - ~>
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0.13'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: future-resource
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - '>='
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '0'
|
34
|
-
type: :runtime
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - '>='
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '0'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: girl_friday
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - '>='
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '0'
|
48
|
-
type: :runtime
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - '>='
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '0'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: countdownlatch
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - ~>
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '1.0'
|
62
|
-
type: :runtime
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - ~>
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '1.0'
|
69
27
|
- !ruby/object:Gem::Dependency
|
70
28
|
name: bundler
|
71
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -136,20 +94,6 @@ dependencies:
|
|
136
94
|
- - '>='
|
137
95
|
- !ruby/object:Gem::Version
|
138
96
|
version: '0'
|
139
|
-
- !ruby/object:Gem::Dependency
|
140
|
-
name: mocha
|
141
|
-
requirement: !ruby/object:Gem::Requirement
|
142
|
-
requirements:
|
143
|
-
- - '>='
|
144
|
-
- !ruby/object:Gem::Version
|
145
|
-
version: '0'
|
146
|
-
type: :development
|
147
|
-
prerelease: false
|
148
|
-
version_requirements: !ruby/object:Gem::Requirement
|
149
|
-
requirements:
|
150
|
-
- - '>='
|
151
|
-
- !ruby/object:Gem::Version
|
152
|
-
version: '0'
|
153
97
|
- !ruby/object:Gem::Dependency
|
154
98
|
name: guard-rspec
|
155
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -226,7 +170,6 @@ files:
|
|
226
170
|
- lib/ruby_ami/event.rb
|
227
171
|
- lib/ruby_ami/lexer.rl.rb
|
228
172
|
- lib/ruby_ami/lexer_machine.rl
|
229
|
-
- lib/ruby_ami/metaprogramming.rb
|
230
173
|
- lib/ruby_ami/response.rb
|
231
174
|
- lib/ruby_ami/stream.rb
|
232
175
|
- lib/ruby_ami/version.rb
|
@@ -1,18 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
class Object
|
3
|
-
def metaclass
|
4
|
-
class << self
|
5
|
-
self
|
6
|
-
end
|
7
|
-
end
|
8
|
-
|
9
|
-
def meta_eval(&block)
|
10
|
-
metaclass.instance_eval &block
|
11
|
-
end
|
12
|
-
|
13
|
-
def meta_def(name, &block)
|
14
|
-
meta_eval do
|
15
|
-
define_method name, &block
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|