adhearsion 2.0.0.beta1 → 2.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +2 -4
- data/CHANGELOG.md +34 -4
- data/README.markdown +2 -1
- data/Rakefile +22 -1
- data/adhearsion.gemspec +1 -0
- data/bin/ahn +0 -2
- data/features/cli_daemon.feature +2 -0
- data/features/cli_restart.feature +19 -0
- data/features/cli_start.feature +4 -6
- data/features/cli_stop.feature +3 -0
- data/features/step_definitions/app_generator_steps.rb +2 -0
- data/features/step_definitions/cli_steps.rb +2 -0
- data/features/support/aruba_helper.rb +2 -0
- data/features/support/env.rb +8 -46
- data/features/support/utils.rb +2 -0
- data/lib/adhearsion.rb +4 -6
- data/lib/adhearsion/call.rb +71 -17
- data/lib/adhearsion/call_controller.rb +25 -14
- data/lib/adhearsion/call_controller/dial.rb +34 -15
- data/lib/adhearsion/call_controller/input.rb +186 -144
- data/lib/adhearsion/call_controller/output.rb +10 -6
- data/lib/adhearsion/call_controller/record.rb +11 -13
- data/lib/adhearsion/call_controller/utility.rb +2 -0
- data/lib/adhearsion/calls.rb +4 -2
- data/lib/adhearsion/cli.rb +4 -0
- data/lib/adhearsion/cli_commands.rb +8 -2
- data/lib/adhearsion/configuration.rb +7 -3
- data/lib/adhearsion/console.rb +17 -17
- data/lib/adhearsion/events.rb +10 -4
- data/lib/adhearsion/foundation.rb +9 -0
- data/lib/adhearsion/foundation/custom_daemonizer.rb +3 -1
- data/lib/adhearsion/foundation/exception_handler.rb +2 -0
- data/lib/adhearsion/foundation/libc.rb +2 -0
- data/lib/adhearsion/foundation/object.rb +3 -0
- data/lib/adhearsion/foundation/thread_safety.rb +5 -11
- data/lib/adhearsion/generators.rb +2 -0
- data/lib/adhearsion/generators/app/app_generator.rb +2 -0
- data/lib/adhearsion/generators/app/templates/README.md +9 -0
- data/lib/adhearsion/generators/app/templates/config/adhearsion.rb +38 -16
- data/lib/adhearsion/generators/app/templates/config/environment.rb +2 -0
- data/lib/adhearsion/generators/app/templates/lib/simon_game.rb +5 -3
- data/lib/adhearsion/generators/controller/controller_generator.rb +2 -0
- data/lib/adhearsion/generators/controller/templates/lib/controller.rb +2 -0
- data/lib/adhearsion/generators/controller/templates/spec/controller_spec.rb +2 -0
- data/lib/adhearsion/generators/generator.rb +3 -1
- data/lib/adhearsion/generators/plugin/plugin_generator.rb +2 -0
- data/lib/adhearsion/initializer.rb +31 -17
- data/lib/adhearsion/linux_proc_name.rb +2 -0
- data/lib/adhearsion/logging.rb +5 -3
- data/lib/adhearsion/menu_dsl.rb +2 -0
- data/lib/adhearsion/menu_dsl/calculated_match.rb +2 -0
- data/lib/adhearsion/menu_dsl/calculated_match_collection.rb +2 -0
- data/lib/adhearsion/menu_dsl/fixnum_match_calculator.rb +2 -0
- data/lib/adhearsion/menu_dsl/match_calculator.rb +2 -0
- data/lib/adhearsion/menu_dsl/menu.rb +58 -4
- data/lib/adhearsion/menu_dsl/menu_builder.rb +14 -1
- data/lib/adhearsion/menu_dsl/range_match_calculator.rb +4 -1
- data/lib/adhearsion/menu_dsl/string_match_calculator.rb +2 -0
- data/lib/adhearsion/outbound_call.rb +2 -0
- data/lib/adhearsion/plugin.rb +9 -7
- data/lib/adhearsion/plugin/collection.rb +3 -1
- data/lib/adhearsion/plugin/initializer.rb +3 -1
- data/lib/adhearsion/process.rb +8 -2
- data/lib/adhearsion/punchblock_plugin.rb +3 -1
- data/lib/adhearsion/punchblock_plugin/initializer.rb +34 -11
- data/lib/adhearsion/router.rb +4 -2
- data/lib/adhearsion/router/route.rb +2 -0
- data/lib/adhearsion/script_ahn_loader.rb +2 -0
- data/lib/adhearsion/tasks.rb +2 -0
- data/lib/adhearsion/tasks/configuration.rb +2 -0
- data/lib/adhearsion/tasks/debugging.rb +8 -0
- data/lib/adhearsion/tasks/environment.rb +2 -0
- data/lib/adhearsion/tasks/plugins.rb +2 -0
- data/lib/adhearsion/tasks/testing.rb +2 -0
- data/lib/adhearsion/version.rb +3 -1
- data/pre-commit +2 -0
- data/spec/adhearsion/call_controller/dial_spec.rb +114 -25
- data/spec/adhearsion/call_controller/input_spec.rb +192 -169
- data/spec/adhearsion/call_controller/output_spec.rb +26 -12
- data/spec/adhearsion/call_controller/record_spec.rb +29 -77
- data/spec/adhearsion/call_controller/utility_spec.rb +69 -0
- data/spec/adhearsion/call_controller_spec.rb +90 -15
- data/spec/adhearsion/call_spec.rb +92 -24
- data/spec/adhearsion/calls_spec.rb +9 -7
- data/spec/adhearsion/configuration_spec.rb +58 -56
- data/spec/adhearsion/console_spec.rb +4 -2
- data/spec/adhearsion/events_spec.rb +9 -7
- data/spec/adhearsion/generators_spec.rb +3 -1
- data/spec/adhearsion/initializer_spec.rb +16 -14
- data/spec/adhearsion/logging_spec.rb +11 -9
- data/spec/adhearsion/menu_dsl/calculated_match_collection_spec.rb +6 -4
- data/spec/adhearsion/menu_dsl/calculated_match_spec.rb +6 -4
- data/spec/adhearsion/menu_dsl/fixnum_match_calculator_spec.rb +3 -1
- data/spec/adhearsion/menu_dsl/match_calculator_spec.rb +2 -0
- data/spec/adhearsion/menu_dsl/menu_builder_spec.rb +42 -11
- data/spec/adhearsion/menu_dsl/menu_spec.rb +197 -36
- data/spec/adhearsion/menu_dsl/range_match_calculator_spec.rb +4 -2
- data/spec/adhearsion/menu_dsl/string_match_calculator_spec.rb +5 -3
- data/spec/adhearsion/outbound_call_spec.rb +7 -5
- data/spec/adhearsion/plugin_spec.rb +19 -15
- data/spec/adhearsion/process_spec.rb +12 -7
- data/spec/adhearsion/punchblock_plugin/initializer_spec.rb +35 -15
- data/spec/adhearsion/punchblock_plugin_spec.rb +4 -1
- data/spec/adhearsion/router/route_spec.rb +8 -6
- data/spec/adhearsion/router_spec.rb +12 -10
- data/spec/adhearsion_spec.rb +13 -2
- data/spec/capture_warnings.rb +33 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/support/call_controller_test_helpers.rb +2 -4
- data/spec/support/initializer_stubs.rb +8 -5
- data/spec/support/logging_helpers.rb +2 -0
- data/spec/support/punchblock_mocks.rb +2 -0
- metadata +84 -71
- data/EVENTS +0 -11
- data/lib/adhearsion/call_controller/menu.rb +0 -124
- data/lib/adhearsion/foundation/all.rb +0 -8
- data/spec/adhearsion/call_controller/menu_spec.rb +0 -120
- data/spec/adhearsion/menu_dsl_spec.rb +0 -12
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
module Adhearsion
|
2
4
|
module MenuDSL
|
3
5
|
|
@@ -8,11 +10,12 @@ module Adhearsion
|
|
8
10
|
def initialize
|
9
11
|
@patterns = []
|
10
12
|
@menu_callbacks = {}
|
13
|
+
@context = nil
|
11
14
|
end
|
12
15
|
|
13
16
|
def build(&block)
|
14
17
|
@context = eval "self", block.binding
|
15
|
-
instance_eval
|
18
|
+
instance_eval(&block)
|
16
19
|
end
|
17
20
|
|
18
21
|
def match(*args, &block)
|
@@ -35,8 +38,13 @@ module Adhearsion
|
|
35
38
|
@patterns
|
36
39
|
end
|
37
40
|
|
41
|
+
def has_matchers?
|
42
|
+
@patterns.size > 0
|
43
|
+
end
|
44
|
+
|
38
45
|
def execute_hook_for(symbol, input)
|
39
46
|
callback = @menu_callbacks[symbol]
|
47
|
+
return unless callback
|
40
48
|
@context.instance_exec input, &callback
|
41
49
|
end
|
42
50
|
|
@@ -55,6 +63,11 @@ module Adhearsion
|
|
55
63
|
@menu_callbacks[:failure] = block
|
56
64
|
end
|
57
65
|
|
66
|
+
def validator(&block)
|
67
|
+
raise LocalJumpError, "Must supply a block!" unless block_given?
|
68
|
+
@menu_callbacks[:validator] = block
|
69
|
+
end
|
70
|
+
|
58
71
|
def calculate_matches_for(result)
|
59
72
|
CalculatedMatchCollection.new.tap do |collection|
|
60
73
|
weighted_match_calculators.each do |pattern|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
module Adhearsion
|
2
4
|
module MenuDSL
|
3
5
|
|
@@ -42,7 +44,8 @@ module Adhearsion
|
|
42
44
|
power = 0
|
43
45
|
while num < last
|
44
46
|
ones_count = 10**power - 1
|
45
|
-
|
47
|
+
range = ([num, first].max..[num + ones_count, last].min).to_a
|
48
|
+
matches.concat range
|
46
49
|
num *= 10
|
47
50
|
power += 1
|
48
51
|
end
|
data/lib/adhearsion/plugin.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
module Adhearsion
|
2
4
|
|
3
5
|
# Plugin is the core of extension of Adhearsion framework and provides the easiest
|
@@ -99,9 +101,9 @@ module Adhearsion
|
|
99
101
|
end
|
100
102
|
|
101
103
|
def load_tasks
|
102
|
-
|
104
|
+
container = Object.new.tap { |o| o.extend Rake::DSL if defined? Rake::DSL }
|
103
105
|
tasks.each do |block|
|
104
|
-
|
106
|
+
container.instance_eval(&block)
|
105
107
|
end
|
106
108
|
end
|
107
109
|
|
@@ -124,7 +126,7 @@ module Adhearsion
|
|
124
126
|
end
|
125
127
|
|
126
128
|
def inherited(base)
|
127
|
-
logger.
|
129
|
+
logger.info "Detected new plugin: #{base.name}"
|
128
130
|
subclasses << base
|
129
131
|
end
|
130
132
|
|
@@ -159,15 +161,15 @@ module Adhearsion
|
|
159
161
|
end
|
160
162
|
|
161
163
|
# Recursively initialization of all the loaded plugins
|
162
|
-
def init_plugins
|
164
|
+
def init_plugins(*args)
|
163
165
|
initializers.tsort.each do |initializer|
|
164
|
-
initializer.run
|
166
|
+
initializer.run(*args)
|
165
167
|
end
|
166
168
|
end
|
167
169
|
|
168
|
-
def run_plugins
|
170
|
+
def run_plugins(*args)
|
169
171
|
runners.tsort.each do |runner|
|
170
|
-
runner.run
|
172
|
+
runner.run(*args)
|
171
173
|
end
|
172
174
|
end
|
173
175
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
require 'tsort'
|
2
4
|
|
3
5
|
module Adhearsion
|
@@ -8,7 +10,7 @@ module Adhearsion
|
|
8
10
|
alias :tsort_each_node :each
|
9
11
|
|
10
12
|
def tsort_each_child(child, &block)
|
11
|
-
select { |i| i.before == child.name || i.name == child.after }.each
|
13
|
+
select { |i| i.before == child.name || i.name == child.after }.each(&block)
|
12
14
|
end
|
13
15
|
|
14
16
|
def +(other)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
module Adhearsion
|
2
4
|
class Plugin
|
3
5
|
class Initializer
|
@@ -21,7 +23,7 @@ module Adhearsion
|
|
21
23
|
end
|
22
24
|
|
23
25
|
def run(*args)
|
24
|
-
@context.instance_exec
|
26
|
+
@context.instance_exec(*args, &block)
|
25
27
|
end
|
26
28
|
|
27
29
|
def bind(context)
|
data/lib/adhearsion/process.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
require 'state_machine'
|
2
4
|
require 'singleton'
|
3
5
|
require 'socket'
|
@@ -41,7 +43,7 @@ module Adhearsion
|
|
41
43
|
end
|
42
44
|
|
43
45
|
event :stop do
|
44
|
-
transition
|
46
|
+
transition all => :stopped
|
45
47
|
end
|
46
48
|
|
47
49
|
event :force_stop do
|
@@ -81,12 +83,16 @@ module Adhearsion
|
|
81
83
|
Events.trigger_immediately :shutdown
|
82
84
|
|
83
85
|
Console.stop
|
86
|
+
|
87
|
+
logger.info "Adhearsion shut down"
|
84
88
|
end
|
85
89
|
|
86
90
|
def stop_when_zero_calls
|
91
|
+
i = 0
|
87
92
|
until Adhearsion.active_calls.count == 0
|
88
|
-
logger.
|
93
|
+
logger.info "Stop requested but we still have #{Adhearsion.active_calls.count} active calls." if (i % 50) == 0
|
89
94
|
sleep 0.2
|
95
|
+
i += 1
|
90
96
|
end
|
91
97
|
final_shutdown
|
92
98
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
module Adhearsion
|
2
4
|
class PunchblockPlugin < Plugin
|
3
5
|
extend ActiveSupport::Autoload
|
@@ -41,7 +43,7 @@ module Adhearsion
|
|
41
43
|
end
|
42
44
|
|
43
45
|
def execute_component(command, timeout = 60)
|
44
|
-
client.execute_command command
|
46
|
+
client.execute_command command, :async => true
|
45
47
|
response = command.response timeout
|
46
48
|
raise response if response.is_a? Exception
|
47
49
|
command
|
@@ -1,3 +1,7 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'blather'
|
4
|
+
|
1
5
|
module Adhearsion
|
2
6
|
class PunchblockPlugin
|
3
7
|
class Initializer
|
@@ -8,12 +12,15 @@ module Adhearsion
|
|
8
12
|
class << self
|
9
13
|
def init
|
10
14
|
self.config = Adhearsion.config[:punchblock]
|
15
|
+
|
16
|
+
username = self.config.username
|
11
17
|
connection_class = case (self.config.platform || :xmpp)
|
12
18
|
when :xmpp
|
13
|
-
username =
|
19
|
+
username = Blather::JID.new username
|
20
|
+
username = Blather::JID.new username.node, username.domain, resource unless username.resource
|
21
|
+
username = username.to_s
|
14
22
|
::Punchblock::Connection::XMPP
|
15
23
|
when :asterisk
|
16
|
-
username = self.config.username
|
17
24
|
::Punchblock::Connection::Asterisk
|
18
25
|
end
|
19
26
|
|
@@ -50,7 +57,7 @@ module Adhearsion
|
|
50
57
|
|
51
58
|
# Handle events from Punchblock via events system
|
52
59
|
self.client.register_event_handler do |event|
|
53
|
-
|
60
|
+
handle_event event
|
54
61
|
end
|
55
62
|
|
56
63
|
Events.punchblock ::Punchblock::Connection::Connected do |event|
|
@@ -81,6 +88,7 @@ module Adhearsion
|
|
81
88
|
blocker = ConditionVariable.new
|
82
89
|
|
83
90
|
Events.punchblock ::Punchblock::Connection::Connected do
|
91
|
+
Adhearsion::Process.booted
|
84
92
|
m.synchronize { blocker.broadcast }
|
85
93
|
end
|
86
94
|
|
@@ -103,15 +111,21 @@ module Adhearsion
|
|
103
111
|
client.run
|
104
112
|
rescue ::Punchblock::DisconnectedError => e
|
105
113
|
# We only care about disconnects if the process is up or booting
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
+
return unless [:booting, :running].include? Adhearsion::Process.state_name
|
115
|
+
|
116
|
+
Adhearsion::Process.reset unless Adhearsion::Process.state_name == :booting
|
117
|
+
|
118
|
+
self.attempts += 1
|
119
|
+
|
120
|
+
if self.attempts >= self.config.reconnect_attempts
|
121
|
+
logger.fatal "Connection lost. Connection retry attempts exceeded."
|
122
|
+
Adhearsion::Process.stop!
|
123
|
+
return
|
114
124
|
end
|
125
|
+
|
126
|
+
logger.error "Connection lost. Attempting reconnect #{self.attempts} of #{self.config.reconnect_attempts}"
|
127
|
+
sleep self.config.reconnect_timer
|
128
|
+
retry
|
115
129
|
rescue ::Punchblock::ProtocolError => e
|
116
130
|
logger.fatal "The connection failed due to a protocol error: #{e.name}."
|
117
131
|
raise e
|
@@ -123,6 +137,7 @@ module Adhearsion
|
|
123
137
|
call = Adhearsion.active_calls.from_offer offer
|
124
138
|
case Adhearsion::Process.state_name
|
125
139
|
when :booting, :rejecting
|
140
|
+
logger.info "Declining call because the process is not yet running."
|
126
141
|
call.reject :decline
|
127
142
|
when :running
|
128
143
|
call.accept
|
@@ -142,6 +157,14 @@ module Adhearsion
|
|
142
157
|
end
|
143
158
|
end
|
144
159
|
|
160
|
+
def handle_event(event)
|
161
|
+
Events.trigger :punchblock, event
|
162
|
+
case event
|
163
|
+
when Punchblock::Event::Asterisk::AMI::Event
|
164
|
+
Events.trigger :ami, event
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
145
168
|
def resource
|
146
169
|
[Adhearsion::Process.fqdn, ::Process.pid].join '-'
|
147
170
|
end
|
data/lib/adhearsion/router.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
module Adhearsion
|
2
4
|
class Router
|
3
5
|
extend ActiveSupport::Autoload
|
@@ -8,7 +10,7 @@ module Adhearsion
|
|
8
10
|
|
9
11
|
def initialize(&block)
|
10
12
|
@routes = []
|
11
|
-
instance_exec
|
13
|
+
instance_exec(&block)
|
12
14
|
end
|
13
15
|
|
14
16
|
def route(*args, &block)
|
@@ -23,7 +25,7 @@ module Adhearsion
|
|
23
25
|
|
24
26
|
def handle(call)
|
25
27
|
return unless route = match(call)
|
26
|
-
logger.
|
28
|
+
logger.info "Call #{call.id} selected route \"#{route.name}\" (#{route.target})"
|
27
29
|
route.dispatcher
|
28
30
|
end
|
29
31
|
end
|
data/lib/adhearsion/tasks.rb
CHANGED
data/lib/adhearsion/version.rb
CHANGED
data/pre-commit
ADDED
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
module Adhearsion
|
@@ -13,11 +15,14 @@ module Adhearsion
|
|
13
15
|
let(:second_other_call_id) { new_uuid }
|
14
16
|
let(:second_other_mock_call) { flexmock OutboundCall.new, :id => second_other_call_id }
|
15
17
|
|
16
|
-
let(:mock_end) { flexmock Punchblock::Event::End.new, :reason => :hangup }
|
17
18
|
let(:mock_answered) { Punchblock::Event::Answered.new }
|
18
19
|
|
19
20
|
let(:latch) { CountDownLatch.new 1 }
|
20
21
|
|
22
|
+
def mock_end(reason = :hangup)
|
23
|
+
flexmock Punchblock::Event::End.new, :reason => reason
|
24
|
+
end
|
25
|
+
|
21
26
|
describe "#dial" do
|
22
27
|
before do
|
23
28
|
other_mock_call
|
@@ -48,14 +53,16 @@ module Adhearsion
|
|
48
53
|
|
49
54
|
describe "without a block" do
|
50
55
|
before do
|
51
|
-
flexmock(other_mock_call).should_receive(:dial).once
|
56
|
+
flexmock(other_mock_call).should_receive(:dial).once.with(to, options)
|
52
57
|
flexmock(other_mock_call).should_receive(:hangup).once
|
53
58
|
flexmock(OutboundCall).should_receive(:new).and_return other_mock_call
|
54
59
|
end
|
55
60
|
|
61
|
+
let(:options) { { :foo => :bar } }
|
62
|
+
|
56
63
|
def dial_in_thread
|
57
64
|
Thread.new do
|
58
|
-
status = subject.dial to
|
65
|
+
status = subject.dial to, options
|
59
66
|
latch.countdown!
|
60
67
|
status
|
61
68
|
end
|
@@ -113,13 +120,29 @@ module Adhearsion
|
|
113
120
|
|
114
121
|
sleep 0.5
|
115
122
|
|
116
|
-
other_mock_call << mock_end
|
123
|
+
other_mock_call << mock_end(:reject)
|
117
124
|
|
118
125
|
latch.wait(2).should be_true
|
119
126
|
|
120
127
|
t.join
|
121
128
|
status = t.value
|
122
|
-
status.result.should == :no_answer
|
129
|
+
status.result.should be == :no_answer
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
context "when the call ends with an error" do
|
134
|
+
it "has an overall dial status of :error" do
|
135
|
+
t = dial_in_thread
|
136
|
+
|
137
|
+
sleep 0.5
|
138
|
+
|
139
|
+
other_mock_call << mock_end(:error)
|
140
|
+
|
141
|
+
latch.wait(2).should be_true
|
142
|
+
|
143
|
+
t.join
|
144
|
+
status = t.value
|
145
|
+
status.result.should be == :error
|
123
146
|
end
|
124
147
|
end
|
125
148
|
|
@@ -138,28 +161,32 @@ module Adhearsion
|
|
138
161
|
|
139
162
|
t.join
|
140
163
|
status = t.value
|
141
|
-
status.result.should == :answer
|
164
|
+
status.result.should be == :answer
|
142
165
|
end
|
143
166
|
end
|
144
167
|
end
|
145
168
|
|
146
169
|
describe "with multiple third parties specified" do
|
170
|
+
let(:options) { {} }
|
171
|
+
let(:other_options) { options }
|
172
|
+
let(:second_other_options) { options }
|
173
|
+
|
147
174
|
before do
|
148
175
|
second_other_mock_call
|
149
176
|
|
150
177
|
flexmock(OutboundCall).should_receive(:new).and_return other_mock_call, second_other_mock_call
|
151
178
|
|
152
|
-
flexmock(other_mock_call).should_receive(:dial).once
|
179
|
+
flexmock(other_mock_call).should_receive(:dial).once.with(to, other_options)
|
153
180
|
flexmock(other_mock_call).should_receive(:hangup).once
|
154
181
|
|
155
|
-
flexmock(second_other_mock_call).should_receive(:dial).once
|
182
|
+
flexmock(second_other_mock_call).should_receive(:dial).once.with(second_to, second_other_options)
|
156
183
|
flexmock(second_other_mock_call).should_receive(:join).never
|
157
184
|
flexmock(second_other_mock_call).should_receive(:hangup).once
|
158
185
|
end
|
159
186
|
|
160
187
|
def dial_in_thread
|
161
188
|
Thread.new do
|
162
|
-
status = subject.dial [to, second_to]
|
189
|
+
status = subject.dial [to, second_to], options
|
163
190
|
latch.countdown!
|
164
191
|
status
|
165
192
|
end
|
@@ -213,24 +240,94 @@ module Adhearsion
|
|
213
240
|
status.calls.each { |c| c.should be_a OutboundCall }
|
214
241
|
end
|
215
242
|
|
243
|
+
describe "with options overrides" do
|
244
|
+
let(:options) do
|
245
|
+
{
|
246
|
+
:from => 'foo',
|
247
|
+
:timeout => 3000,
|
248
|
+
:headers => {
|
249
|
+
:x_foo => 'bar'
|
250
|
+
}
|
251
|
+
}
|
252
|
+
end
|
253
|
+
|
254
|
+
let(:dial_other_options) do
|
255
|
+
{
|
256
|
+
:foo => 'bar',
|
257
|
+
:headers => {
|
258
|
+
:x_foo => 'buzz'
|
259
|
+
}
|
260
|
+
}
|
261
|
+
end
|
262
|
+
|
263
|
+
let(:other_options) do
|
264
|
+
{
|
265
|
+
:from => 'foo',
|
266
|
+
:timeout => 3000,
|
267
|
+
:foo => 'bar',
|
268
|
+
:headers => {
|
269
|
+
:x_foo => 'buzz'
|
270
|
+
}
|
271
|
+
|
272
|
+
}
|
273
|
+
end
|
274
|
+
|
275
|
+
let(:dial_second_other_options) do
|
276
|
+
{
|
277
|
+
:timeout => 5000,
|
278
|
+
:headers => {
|
279
|
+
:x_bar => 'barbuzz'
|
280
|
+
}
|
281
|
+
}
|
282
|
+
end
|
283
|
+
|
284
|
+
let(:second_other_options) do
|
285
|
+
{
|
286
|
+
:from => 'foo',
|
287
|
+
:timeout => 5000,
|
288
|
+
:headers => {
|
289
|
+
:x_foo => 'bar',
|
290
|
+
:x_bar => 'barbuzz'
|
291
|
+
}
|
292
|
+
}
|
293
|
+
end
|
294
|
+
|
295
|
+
it "with multiple destinations as an hash, with overrides for each, and an options hash, it dials each call with specified options" do
|
296
|
+
t = Thread.new do
|
297
|
+
subject.dial({
|
298
|
+
to => dial_other_options,
|
299
|
+
second_to => dial_second_other_options
|
300
|
+
}, options)
|
301
|
+
latch.countdown!
|
302
|
+
end
|
303
|
+
|
304
|
+
latch.wait(1).should be_false
|
305
|
+
other_mock_call << mock_end
|
306
|
+
latch.wait(1).should be_false
|
307
|
+
second_other_mock_call << mock_end
|
308
|
+
latch.wait(2).should be_true
|
309
|
+
t.join
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
216
313
|
context "when all calls are rejected" do
|
217
314
|
it "has an overall dial status of :no_answer" do
|
218
315
|
t = dial_in_thread
|
219
316
|
|
220
317
|
sleep 0.5
|
221
318
|
|
222
|
-
other_mock_call << mock_end
|
223
|
-
second_other_mock_call << mock_end
|
319
|
+
other_mock_call << mock_end(:reject)
|
320
|
+
second_other_mock_call << mock_end(:reject)
|
224
321
|
|
225
322
|
latch.wait(2).should be_true
|
226
323
|
|
227
324
|
t.join
|
228
325
|
status = t.value
|
229
|
-
status.result.should == :no_answer
|
326
|
+
status.result.should be == :no_answer
|
230
327
|
end
|
231
328
|
end
|
232
329
|
|
233
|
-
context "when a call is answered and joined" do
|
330
|
+
context "when a call is answered and joined, and the other ends with an error" do
|
234
331
|
it "has an overall dial status of :answer" do
|
235
332
|
flexmock(other_mock_call).should_receive(:join).once.with(call)
|
236
333
|
flexmock(second_other_mock_call).should_receive(:hangup).once
|
@@ -242,13 +339,13 @@ module Adhearsion
|
|
242
339
|
other_mock_call << mock_answered
|
243
340
|
other_mock_call << mock_end
|
244
341
|
|
245
|
-
second_other_mock_call << mock_end
|
342
|
+
second_other_mock_call << mock_end(:error)
|
246
343
|
|
247
344
|
latch.wait(1).should be_true
|
248
345
|
|
249
346
|
t.join
|
250
347
|
status = t.value
|
251
|
-
status.result.should == :answer
|
348
|
+
status.result.should be == :answer
|
252
349
|
end
|
253
350
|
end
|
254
351
|
end
|
@@ -271,20 +368,12 @@ module Adhearsion
|
|
271
368
|
|
272
369
|
latch.wait
|
273
370
|
time = Time.now - time
|
274
|
-
time.to_i.should == timeout
|
371
|
+
time.to_i.should be == timeout
|
275
372
|
t.join
|
276
373
|
status = t.value
|
277
|
-
status.result.should == :timeout
|
374
|
+
status.result.should be == :timeout
|
278
375
|
end
|
279
376
|
end
|
280
|
-
|
281
|
-
describe "with a block" do
|
282
|
-
it "uses the block as the controller for the new call"
|
283
|
-
|
284
|
-
it "joins the new call to the existing call once the block returns"
|
285
|
-
|
286
|
-
it "does not try to join the calls if the new call is hungup when the block returns"
|
287
|
-
end
|
288
377
|
end#describe #dial
|
289
378
|
end
|
290
379
|
end
|