adhearsion 2.0.0.beta1 → 2.0.0.rc1
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/.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
|