adhearsion 1.2.6 → 2.0.0.alpha1

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.
Files changed (236) hide show
  1. data/.gitignore +17 -10
  2. data/CHANGELOG.md +273 -0
  3. data/Gemfile +1 -1
  4. data/Guardfile +17 -0
  5. data/README.markdown +61 -9
  6. data/Rakefile +16 -48
  7. data/adhearsion.gemspec +21 -7
  8. data/bin/ahn +3 -1
  9. data/cucumber.yml +4 -0
  10. data/features/app_generator.feature +42 -0
  11. data/features/cli.feature +108 -0
  12. data/features/step_definitions/app_generator_steps.rb +6 -0
  13. data/features/step_definitions/cli_steps.rb +74 -0
  14. data/features/support/aruba_helper.rb +22 -0
  15. data/features/support/env.rb +37 -0
  16. data/features/support/utils.rb +8 -0
  17. data/lib/adhearsion.rb +85 -41
  18. data/lib/adhearsion/call.rb +176 -0
  19. data/lib/adhearsion/call_controller.rb +134 -0
  20. data/lib/adhearsion/call_controller/dial.rb +70 -0
  21. data/lib/adhearsion/call_controller/input.rb +173 -0
  22. data/lib/adhearsion/call_controller/menu.rb +124 -0
  23. data/lib/adhearsion/call_controller/output.rb +267 -0
  24. data/lib/adhearsion/call_controller/record.rb +42 -0
  25. data/lib/adhearsion/call_controller/utility.rb +60 -0
  26. data/lib/adhearsion/calls.rb +81 -0
  27. data/lib/adhearsion/cli.rb +1 -3
  28. data/lib/adhearsion/cli_commands.rb +142 -0
  29. data/lib/adhearsion/configuration.rb +149 -0
  30. data/lib/adhearsion/console.rb +19 -8
  31. data/lib/adhearsion/dialplan_controller.rb +9 -0
  32. data/lib/adhearsion/events.rb +84 -0
  33. data/lib/adhearsion/foundation/all.rb +0 -7
  34. data/lib/adhearsion/foundation/custom_daemonizer.rb +4 -6
  35. data/lib/adhearsion/foundation/exception_handler.rb +9 -0
  36. data/lib/adhearsion/foundation/object.rb +26 -8
  37. data/lib/adhearsion/foundation/synchronized_hash.rb +3 -6
  38. data/lib/adhearsion/foundation/thread_safety.rb +17 -1
  39. data/lib/adhearsion/generators/app/app_generator.rb +4 -13
  40. data/lib/adhearsion/generators/app/templates/Gemfile +10 -5
  41. data/lib/adhearsion/generators/app/templates/Procfile +1 -0
  42. data/lib/adhearsion/generators/app/templates/README.md +28 -0
  43. data/lib/adhearsion/generators/app/templates/config/adhearsion.rb +41 -0
  44. data/lib/adhearsion/generators/app/templates/{components/simon_game → lib}/simon_game.rb +6 -18
  45. data/lib/adhearsion/generators/app/templates/script/ahn +2 -2
  46. data/lib/adhearsion/initializer.rb +151 -293
  47. data/lib/adhearsion/initializer/logging.rb +33 -0
  48. data/lib/adhearsion/logging.rb +65 -69
  49. data/lib/adhearsion/menu_dsl.rb +15 -0
  50. data/lib/adhearsion/menu_dsl/calculated_match.rb +39 -0
  51. data/lib/adhearsion/menu_dsl/calculated_match_collection.rb +41 -0
  52. data/lib/adhearsion/menu_dsl/fixnum_match_calculator.rb +18 -0
  53. data/lib/adhearsion/menu_dsl/match_calculator.rb +36 -0
  54. data/lib/adhearsion/{voip/menu_state_machine/menu_class.rb → menu_dsl/menu.rb} +38 -40
  55. data/lib/adhearsion/menu_dsl/menu_builder.rb +69 -0
  56. data/lib/adhearsion/menu_dsl/range_match_calculator.rb +55 -0
  57. data/lib/adhearsion/menu_dsl/string_match_calculator.rb +21 -0
  58. data/lib/adhearsion/outbound_call.rb +64 -0
  59. data/lib/adhearsion/plugin.rb +319 -0
  60. data/lib/adhearsion/plugin/collection.rb +19 -0
  61. data/lib/adhearsion/plugin/initializer.rb +37 -0
  62. data/lib/adhearsion/plugin/methods_container.rb +6 -0
  63. data/lib/adhearsion/process.rb +94 -0
  64. data/lib/adhearsion/punchblock_plugin.rb +29 -0
  65. data/lib/adhearsion/punchblock_plugin/initializer.rb +137 -0
  66. data/lib/adhearsion/router.rb +30 -0
  67. data/lib/adhearsion/router/route.rb +42 -0
  68. data/lib/adhearsion/script_ahn_loader.rb +2 -2
  69. data/lib/adhearsion/tasks.rb +14 -9
  70. data/lib/adhearsion/tasks/configuration.rb +26 -0
  71. data/lib/adhearsion/tasks/plugins.rb +17 -0
  72. data/lib/adhearsion/version.rb +8 -14
  73. data/spec/adhearsion/call_controller/dial_spec.rb +138 -0
  74. data/spec/adhearsion/call_controller/input_spec.rb +278 -0
  75. data/spec/adhearsion/call_controller/menu_spec.rb +120 -0
  76. data/spec/adhearsion/call_controller/output_spec.rb +466 -0
  77. data/spec/adhearsion/call_controller/record_spec.rb +125 -0
  78. data/spec/adhearsion/call_controller_spec.rb +395 -0
  79. data/spec/adhearsion/call_spec.rb +438 -0
  80. data/spec/adhearsion/calls_spec.rb +47 -0
  81. data/spec/adhearsion/configuration_spec.rb +308 -0
  82. data/spec/adhearsion/dialplan_controller_spec.rb +26 -0
  83. data/spec/adhearsion/events_spec.rb +112 -0
  84. data/spec/adhearsion/initializer/logging_spec.rb +58 -0
  85. data/spec/adhearsion/initializer_spec.rb +209 -122
  86. data/spec/adhearsion/logging_spec.rb +58 -47
  87. data/spec/adhearsion/menu_dsl/calculated_match_collection_spec.rb +56 -0
  88. data/spec/adhearsion/menu_dsl/calculated_match_spec.rb +57 -0
  89. data/spec/adhearsion/menu_dsl/fixnum_match_calculator_spec.rb +33 -0
  90. data/spec/adhearsion/menu_dsl/match_calculator_spec.rb +13 -0
  91. data/spec/adhearsion/menu_dsl/menu_builder_spec.rb +118 -0
  92. data/spec/adhearsion/menu_dsl/menu_spec.rb +210 -0
  93. data/spec/adhearsion/menu_dsl/range_match_calculator_spec.rb +28 -0
  94. data/spec/adhearsion/menu_dsl/string_match_calculator_spec.rb +36 -0
  95. data/spec/adhearsion/menu_dsl_spec.rb +12 -0
  96. data/spec/adhearsion/outbound_call_spec.rb +174 -0
  97. data/spec/adhearsion/plugin_spec.rb +489 -0
  98. data/spec/adhearsion/process_spec.rb +34 -0
  99. data/spec/adhearsion/punchblock_plugin/initializer_spec.rb +294 -0
  100. data/spec/adhearsion/router/route_spec.rb +99 -0
  101. data/spec/adhearsion/router_spec.rb +106 -0
  102. data/spec/adhearsion_spec.rb +46 -0
  103. data/spec/spec_helper.rb +14 -14
  104. data/spec/support/call_controller_test_helpers.rb +48 -0
  105. data/spec/support/initializer_stubs.rb +8 -13
  106. data/spec/support/punchblock_mocks.rb +6 -0
  107. metadata +255 -253
  108. data/CHANGELOG +0 -174
  109. data/bin/ahnctl +0 -68
  110. data/bin/jahn +0 -43
  111. data/examples/asterisk_manager_interface/standalone.rb +0 -51
  112. data/lib/adhearsion/commands.rb +0 -302
  113. data/lib/adhearsion/component_manager.rb +0 -278
  114. data/lib/adhearsion/component_manager/component_tester.rb +0 -54
  115. data/lib/adhearsion/component_manager/spec_framework.rb +0 -18
  116. data/lib/adhearsion/events_support.rb +0 -65
  117. data/lib/adhearsion/foundation/blank_slate.rb +0 -3
  118. data/lib/adhearsion/foundation/event_socket.rb +0 -205
  119. data/lib/adhearsion/foundation/future_resource.rb +0 -36
  120. data/lib/adhearsion/foundation/metaprogramming.rb +0 -17
  121. data/lib/adhearsion/foundation/numeric.rb +0 -13
  122. data/lib/adhearsion/foundation/pseudo_guid.rb +0 -10
  123. data/lib/adhearsion/foundation/relationship_properties.rb +0 -42
  124. data/lib/adhearsion/foundation/string.rb +0 -26
  125. data/lib/adhearsion/generators/app/templates/.ahnrc +0 -34
  126. data/lib/adhearsion/generators/app/templates/README +0 -8
  127. data/lib/adhearsion/generators/app/templates/components/ami_remote/ami_remote.rb +0 -15
  128. data/lib/adhearsion/generators/app/templates/components/disabled/HOW_TO_ENABLE +0 -7
  129. data/lib/adhearsion/generators/app/templates/components/disabled/stomp_gateway/README.markdown +0 -47
  130. data/lib/adhearsion/generators/app/templates/components/disabled/stomp_gateway/stomp_gateway.rb +0 -34
  131. data/lib/adhearsion/generators/app/templates/components/disabled/stomp_gateway/stomp_gateway.yml +0 -12
  132. data/lib/adhearsion/generators/app/templates/components/disabled/xmpp_gateway/README.markdown +0 -3
  133. data/lib/adhearsion/generators/app/templates/components/disabled/xmpp_gateway/xmpp_gateway.rb +0 -11
  134. data/lib/adhearsion/generators/app/templates/components/disabled/xmpp_gateway/xmpp_gateway.yml +0 -0
  135. data/lib/adhearsion/generators/app/templates/config/startup.rb +0 -81
  136. data/lib/adhearsion/generators/app/templates/dialplan.rb +0 -3
  137. data/lib/adhearsion/generators/app/templates/events.rb +0 -33
  138. data/lib/adhearsion/host_definitions.rb +0 -67
  139. data/lib/adhearsion/initializer/asterisk.rb +0 -86
  140. data/lib/adhearsion/initializer/configuration.rb +0 -324
  141. data/lib/adhearsion/initializer/database.rb +0 -60
  142. data/lib/adhearsion/initializer/drb.rb +0 -31
  143. data/lib/adhearsion/initializer/freeswitch.rb +0 -22
  144. data/lib/adhearsion/initializer/ldap.rb +0 -57
  145. data/lib/adhearsion/initializer/rails.rb +0 -41
  146. data/lib/adhearsion/initializer/xmpp.rb +0 -42
  147. data/lib/adhearsion/tasks/components.rb +0 -32
  148. data/lib/adhearsion/tasks/database.rb +0 -5
  149. data/lib/adhearsion/tasks/deprecations.rb +0 -59
  150. data/lib/adhearsion/tasks/generating.rb +0 -20
  151. data/lib/adhearsion/tasks/lint.rb +0 -4
  152. data/lib/adhearsion/voip/asterisk.rb +0 -4
  153. data/lib/adhearsion/voip/asterisk/agi_server.rb +0 -121
  154. data/lib/adhearsion/voip/asterisk/commands.rb +0 -1966
  155. data/lib/adhearsion/voip/asterisk/config_generators/agents.conf.rb +0 -140
  156. data/lib/adhearsion/voip/asterisk/config_generators/config_generator.rb +0 -102
  157. data/lib/adhearsion/voip/asterisk/config_generators/queues.conf.rb +0 -250
  158. data/lib/adhearsion/voip/asterisk/config_generators/voicemail.conf.rb +0 -240
  159. data/lib/adhearsion/voip/asterisk/config_manager.rb +0 -64
  160. data/lib/adhearsion/voip/asterisk/manager_interface.rb +0 -697
  161. data/lib/adhearsion/voip/asterisk/manager_interface/ami_lexer.rb +0 -1681
  162. data/lib/adhearsion/voip/asterisk/manager_interface/ami_lexer.rl.rb +0 -341
  163. data/lib/adhearsion/voip/asterisk/manager_interface/ami_messages.rb +0 -78
  164. data/lib/adhearsion/voip/asterisk/manager_interface/ami_protocol_lexer_machine.rl +0 -87
  165. data/lib/adhearsion/voip/asterisk/special_dial_plan_managers.rb +0 -80
  166. data/lib/adhearsion/voip/call.rb +0 -521
  167. data/lib/adhearsion/voip/call_routing.rb +0 -64
  168. data/lib/adhearsion/voip/commands.rb +0 -17
  169. data/lib/adhearsion/voip/constants.rb +0 -39
  170. data/lib/adhearsion/voip/conveniences.rb +0 -18
  171. data/lib/adhearsion/voip/dial_plan.rb +0 -252
  172. data/lib/adhearsion/voip/dsl/dialing_dsl.rb +0 -151
  173. data/lib/adhearsion/voip/dsl/dialing_dsl/dialing_dsl_monkey_patches.rb +0 -37
  174. data/lib/adhearsion/voip/dsl/dialplan/control_passing_exception.rb +0 -27
  175. data/lib/adhearsion/voip/dsl/dialplan/dispatcher.rb +0 -124
  176. data/lib/adhearsion/voip/dsl/dialplan/parser.rb +0 -69
  177. data/lib/adhearsion/voip/dsl/dialplan/thread_mixin.rb +0 -16
  178. data/lib/adhearsion/voip/dsl/numerical_string.rb +0 -128
  179. data/lib/adhearsion/voip/freeswitch/basic_connection_manager.rb +0 -48
  180. data/lib/adhearsion/voip/freeswitch/event_handler.rb +0 -58
  181. data/lib/adhearsion/voip/freeswitch/freeswitch_dialplan_command_factory.rb +0 -129
  182. data/lib/adhearsion/voip/freeswitch/inbound_connection_manager.rb +0 -38
  183. data/lib/adhearsion/voip/freeswitch/oes_server.rb +0 -195
  184. data/lib/adhearsion/voip/menu_state_machine/calculated_match.rb +0 -80
  185. data/lib/adhearsion/voip/menu_state_machine/matchers.rb +0 -123
  186. data/lib/adhearsion/voip/menu_state_machine/menu_builder.rb +0 -57
  187. data/lib/adhearsion/xmpp/connection.rb +0 -61
  188. data/lib/theatre.rb +0 -147
  189. data/lib/theatre/README.markdown +0 -64
  190. data/lib/theatre/callback_definition_loader.rb +0 -86
  191. data/lib/theatre/guid.rb +0 -23
  192. data/lib/theatre/invocation.rb +0 -131
  193. data/lib/theatre/namespace_manager.rb +0 -153
  194. data/lib/theatre/version.rb +0 -2
  195. data/spec/adhearsion/cli_spec.rb +0 -306
  196. data/spec/adhearsion/component_manager_spec.rb +0 -292
  197. data/spec/adhearsion/constants_spec.rb +0 -8
  198. data/spec/adhearsion/drb_spec.rb +0 -65
  199. data/spec/adhearsion/fixtures/dialplan.rb +0 -3
  200. data/spec/adhearsion/foundation/event_socket_spec.rb +0 -168
  201. data/spec/adhearsion/host_definitions_spec.rb +0 -79
  202. data/spec/adhearsion/initializer/configuration_spec.rb +0 -291
  203. data/spec/adhearsion/initializer/loading_spec.rb +0 -154
  204. data/spec/adhearsion/initializer/paths_spec.rb +0 -74
  205. data/spec/adhearsion/relationship_properties_spec.rb +0 -54
  206. data/spec/adhearsion/voip/asterisk/agi_server_spec.rb +0 -473
  207. data/spec/adhearsion/voip/asterisk/ami/ami_spec.rb +0 -550
  208. data/spec/adhearsion/voip/asterisk/ami/lexer/ami_fixtures.yml +0 -30
  209. data/spec/adhearsion/voip/asterisk/ami/lexer/lexer_story +0 -291
  210. data/spec/adhearsion/voip/asterisk/ami/lexer/lexer_story.rb +0 -241
  211. data/spec/adhearsion/voip/asterisk/ami/lexer/story_helper.rb +0 -124
  212. data/spec/adhearsion/voip/asterisk/commands_spec.rb +0 -3241
  213. data/spec/adhearsion/voip/asterisk/config_file_generators/agents_spec.rb +0 -251
  214. data/spec/adhearsion/voip/asterisk/config_file_generators/queues_spec.rb +0 -323
  215. data/spec/adhearsion/voip/asterisk/config_file_generators/voicemail_spec.rb +0 -306
  216. data/spec/adhearsion/voip/asterisk/config_manager_spec.rb +0 -127
  217. data/spec/adhearsion/voip/asterisk/menu_command/calculated_match_spec.rb +0 -109
  218. data/spec/adhearsion/voip/asterisk/menu_command/matchers_spec.rb +0 -97
  219. data/spec/adhearsion/voip/call_routing_spec.rb +0 -125
  220. data/spec/adhearsion/voip/dialplan_manager_spec.rb +0 -468
  221. data/spec/adhearsion/voip/dsl/dialing_dsl_spec.rb +0 -270
  222. data/spec/adhearsion/voip/dsl/dispatcher_spec.rb +0 -82
  223. data/spec/adhearsion/voip/dsl/dispatcher_spec_helper.rb +0 -45
  224. data/spec/adhearsion/voip/dsl/parser_spec.rb +0 -69
  225. data/spec/adhearsion/voip/freeswitch/basic_connection_manager_spec.rb +0 -39
  226. data/spec/adhearsion/voip/freeswitch/inbound_connection_manager_spec.rb +0 -39
  227. data/spec/adhearsion/voip/freeswitch/oes_server_spec.rb +0 -9
  228. data/spec/adhearsion/voip/numerical_string_spec.rb +0 -61
  229. data/spec/adhearsion/voip/phone_number_spec.rb +0 -45
  230. data/spec/support/the_following_code.rb +0 -3
  231. data/spec/theatre/dsl_examples/simple_before_call.rb +0 -7
  232. data/spec/theatre/dsl_spec.rb +0 -69
  233. data/spec/theatre/invocation_spec.rb +0 -182
  234. data/spec/theatre/namespace_spec.rb +0 -125
  235. data/spec/theatre/spec_helper_spec.rb +0 -28
  236. data/spec/theatre/theatre_class_spec.rb +0 -148
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe Adhearsion::Process do
4
+ before :each do
5
+ Adhearsion::Process.reset
6
+ end
7
+
8
+ it 'should trigger :stop_requested events on #shutdown' do
9
+ flexmock(Adhearsion::Events).should_receive(:trigger_immediately).once.with(:stop_requested)
10
+ Adhearsion::Process.booted
11
+ Adhearsion::Process.shutdown
12
+ end
13
+
14
+ it '#stop_when_zero_calls should wait until the list of active calls reaches 0' do
15
+ pending
16
+ calls = ThreadSafeArray.new
17
+ 3.times do
18
+ fake_call = Object.new
19
+ flexmock(fake_call).should_receive(:hangup).once
20
+ calls << fake_call
21
+ end
22
+ flexmock(Adhearsion).should_receive(:active_calls).and_return calls
23
+ flexmock(Adhearsion::Process.instance).should_receive(:final_shutdown).once
24
+ calls = []
25
+ 3.times { calls << Thread.new { sleep 1; calls.pop } }
26
+ Adhearsion::Process.stop_when_zero_calls
27
+ calls.each { |thread| thread.join }
28
+ end
29
+
30
+ it 'should terminate the process immediately on #force_stop' do
31
+ flexmock(::Process).should_receive(:exit).with(1).once.and_return true
32
+ Adhearsion::Process.force_stop
33
+ end
34
+ end
@@ -0,0 +1,294 @@
1
+ require 'spec_helper'
2
+
3
+ module Adhearsion
4
+ class PunchblockPlugin
5
+ describe Initializer do
6
+
7
+ def reset_default_config
8
+ Adhearsion.config.punchblock do |config|
9
+ config.platform = :xmpp
10
+ config.username = "usera@127.0.0.1"
11
+ config.password = "1"
12
+ config.host = nil
13
+ config.port = nil
14
+ config.root_domain = nil
15
+ config.calls_domain = nil
16
+ config.mixers_domain = nil
17
+ config.connection_timeout = 60
18
+ config.reconnect_attempts = 1.0/0.0
19
+ config.reconnect_timer = 5
20
+ end
21
+ end
22
+
23
+ def initialize_punchblock(options = {})
24
+ reset_default_config
25
+ flexmock(Initializer).should_receive(:connect)
26
+ Adhearsion.config.punchblock do |config|
27
+ config.platform = options[:platform] if options.has_key?(:platform)
28
+ config.username = options[:username] if options.has_key?(:username)
29
+ config.password = options[:password] if options.has_key?(:password)
30
+ config.host = options[:host] if options.has_key?(:host)
31
+ config.port = options[:port] if options.has_key?(:port)
32
+ config.root_domain = options[:root_domain] if options.has_key?(:root_domain)
33
+ config.calls_domain = options[:calls_domain] if options.has_key?(:calls_domain)
34
+ config.mixers_domain = options[:mixers_domain] if options.has_key?(:mixers_domain)
35
+ config.connection_timeout = options[:connection_timeout] if options.has_key?(:connection_timeout)
36
+ config.reconnect_attempts = options[:reconnect_attempts] if options.has_key?(:reconnect_attempts)
37
+ config.reconnect_timer = options[:reconnect_timer] if options.has_key?(:reconnect_timer)
38
+ end
39
+
40
+ Initializer.start
41
+ Adhearsion.config[:punchblock]
42
+ end
43
+
44
+ before do
45
+ Events.refresh!
46
+ end
47
+
48
+ let(:call_id) { rand }
49
+ let(:offer) { ::Punchblock::Event::Offer.new.tap { |o| o.call_id = call_id } }
50
+ let(:mock_call) { flexmock('Call', :id => call_id).tap { |call| call.should_ignore_missing } }
51
+ let(:mock_manager) { flexmock 'a mock dialplan manager' }
52
+
53
+ describe "starts the client with the default values" do
54
+ subject { initialize_punchblock }
55
+
56
+ it "should set properly the username value" do
57
+ subject.username.should == 'usera@127.0.0.1'
58
+ end
59
+
60
+ it "should set properly the password value" do
61
+ subject.password.should == '1'
62
+ end
63
+
64
+ it "should set properly the host value" do
65
+ subject.host.should be_nil
66
+ end
67
+
68
+ it "should set properly the port value" do
69
+ subject.port.should be_nil
70
+ end
71
+
72
+ it "should set properly the root_domain value" do
73
+ subject.root_domain.should be_nil
74
+ end
75
+
76
+ it "should set properly the calls_domain value" do
77
+ subject.calls_domain.should be_nil
78
+ end
79
+
80
+ it "should set properly the mixers_domain value" do
81
+ subject.mixers_domain.should be_nil
82
+ end
83
+
84
+ it "should properly set the reconnect_attempts value" do
85
+ subject.reconnect_attempts.should == 1.0/0.0
86
+ end
87
+
88
+ it "should properly set the reconnect_timer value" do
89
+ subject.reconnect_timer.should == 5
90
+ end
91
+ end
92
+
93
+ it "starts the client with any overridden settings" do
94
+ overrides = {:username => 'userb@127.0.0.1', :password => '123', :host => 'foo.bar.com', :port => 200, :connection_timeout => 20, :root_domain => 'foo.com', :calls_domain => 'call.foo.com', :mixers_domain => 'mixer.foo.com'}
95
+
96
+ flexmock(::Punchblock::Connection::XMPP).should_receive(:new).once.with(overrides).and_return do
97
+ flexmock 'Client', :event_handler= => true
98
+ end
99
+ initialize_punchblock overrides
100
+ end
101
+
102
+ describe "#connect" do
103
+ it 'should block until the connection is established' do
104
+ reset_default_config
105
+ mock_connection = flexmock :mock_connection
106
+ mock_connection.should_receive(:register_event_handler).once
107
+ flexmock(::Punchblock::Client).should_receive(:new).once.and_return mock_connection
108
+ flexmock(mock_connection).should_receive(:run).once
109
+ t = Thread.new { Initializer.start }
110
+ t.join 5
111
+ t.status.should == "sleep"
112
+ Events.trigger_immediately :punchblock, ::Punchblock::Connection::Connected.new
113
+ t.join
114
+ end
115
+ end
116
+
117
+ describe '#connect_to_server' do
118
+ let(:mock_client) { flexmock :client }
119
+
120
+ before :each do
121
+ Adhearsion::Process.reset
122
+ Initializer.config = reset_default_config
123
+ Initializer.config.reconnect_attempts = 1
124
+ flexmock(Adhearsion::Logging.get_logger(Initializer)).should_receive(:fatal).at_most.once
125
+ flexmock(Initializer).should_receive(:client).and_return mock_client
126
+ end
127
+
128
+ after :each do
129
+ Adhearsion::Process.reset
130
+ end
131
+
132
+ it 'should reset the Adhearsion process state to "booting"' do
133
+ Adhearsion::Process.booted
134
+ Adhearsion::Process.state_name.should == :running
135
+ mock_client.should_receive(:run).and_raise ::Punchblock::DisconnectedError
136
+ expect { Initializer.connect_to_server }.should raise_error ::Punchblock::DisconnectedError
137
+ Adhearsion::Process.state_name.should == :booting
138
+ end
139
+
140
+ it 'should retry the connection the specified number of times' do
141
+ Initializer.config.reconnect_attempts = 3
142
+ mock_client.should_receive(:run).and_raise ::Punchblock::DisconnectedError
143
+ expect { Initializer.connect_to_server }.should raise_error ::Punchblock::DisconnectedError
144
+ Initializer.attempts.should == 3
145
+ end
146
+
147
+ it 'should preserve a Punchblock::ProtocolError exception and give up' do
148
+ mock_client.should_receive(:run).and_raise ::Punchblock::ProtocolError
149
+ expect { Initializer.connect_to_server }.should raise_error ::Punchblock::ProtocolError
150
+ end
151
+
152
+ it 'should not attempt to reconnect if Adhearsion is shutting down' do
153
+ Adhearsion::Process.booted
154
+ Adhearsion::Process.shutdown
155
+ mock_client.should_receive(:run).and_raise ::Punchblock::DisconnectedError
156
+ Initializer.should_not raise_error ::Punchblock::DisconnectedError
157
+ end
158
+ end
159
+
160
+ describe 'using Asterisk' do
161
+ let(:overrides) { {:username => 'test', :password => '123', :host => 'foo.bar.com', :port => 200, :connection_timeout => 20, :root_domain => 'foo.com', :calls_domain => 'call.foo.com', :mixers_domain => 'mixer.foo.com'} }
162
+
163
+ it 'should start an Asterisk PB connection' do
164
+ flexmock(::Punchblock::Connection::Asterisk).should_receive(:new).once.with(overrides).and_return do
165
+ flexmock 'Client', :event_handler= => true
166
+ end
167
+ initialize_punchblock overrides.merge(:platform => :asterisk)
168
+ end
169
+ end
170
+
171
+ it 'should place events from Punchblock into the event handler' do
172
+ flexmock(Events.instance).should_receive(:trigger).once.with(:punchblock, offer)
173
+ initialize_punchblock
174
+ Initializer.client.handle_event offer
175
+ end
176
+
177
+ describe "dispatching an offer" do
178
+ before do
179
+ initialize_punchblock
180
+ flexmock(Adhearsion::Process).should_receive(:state_name).once.and_return process_state
181
+ flexmock(Adhearsion.active_calls).should_receive(:from_offer).once.and_return mock_call
182
+ end
183
+
184
+ context "when the Adhearsion::Process is :booting" do
185
+ let(:process_state) { :booting }
186
+
187
+ it 'should reject a call with cause :declined' do
188
+ mock_call.should_receive(:reject).once.with(:decline)
189
+ end
190
+ end
191
+
192
+ context "when when Adhearsion::Process is in :running" do
193
+ let(:process_state) { :running }
194
+
195
+ it "should execute the dispatcher provided by the router" do
196
+ controller = Class.new
197
+ Adhearsion.router do
198
+ route 'foobar', controller
199
+ end
200
+ first_route = Adhearsion.router.routes.first
201
+ flexmock(first_route.dispatcher).should_receive(:call).once.with mock_call
202
+ end
203
+ end
204
+
205
+ context "when when Adhearsion::Process is in :rejecting" do
206
+ let(:process_state) { :rejecting }
207
+
208
+ it 'should reject a call with cause :declined' do
209
+ mock_call.should_receive(:reject).once.with(:decline)
210
+ end
211
+ end
212
+
213
+ context "when when Adhearsion::Process is not :running, :stopping or :rejecting" do
214
+ let(:process_state) { :foobar }
215
+
216
+ it 'should reject a call with cause :error' do
217
+ mock_call.should_receive(:reject).once.with(:error)
218
+ end
219
+ end
220
+
221
+ after { Events.trigger_immediately :punchblock, offer }
222
+ end
223
+
224
+ describe "dispatching a component event" do
225
+ let(:component) { flexmock 'ComponentNode' }
226
+ let(:mock_event) { flexmock 'Event', :call_id => call_id, :source => component }
227
+
228
+ before do
229
+ initialize_punchblock
230
+ end
231
+
232
+ it "should place the event in the call's inbox" do
233
+ component.should_receive(:trigger_event_handler).once.with mock_event
234
+ Events.trigger_immediately :punchblock, mock_event
235
+ end
236
+ end
237
+
238
+ describe "dispatching a call event" do
239
+ let(:mock_event) { flexmock 'Event', :call_id => call_id }
240
+ let(:latch) { CountDownLatch.new 1 }
241
+
242
+ describe "with an active call" do
243
+ before do
244
+ initialize_punchblock
245
+ Adhearsion.active_calls << mock_call
246
+ end
247
+
248
+ it "should log an error" do
249
+ flexmock(Adhearsion::Logging.get_logger(Initializer)).should_receive(:debug).once.with("Event received for call #{call_id}: #{mock_event.inspect}")
250
+ Events.trigger_immediately :punchblock, mock_event
251
+ end
252
+
253
+ it "should place the event in the call's inbox" do
254
+ mock_call.should_receive(:<<).once.with(mock_event)
255
+ Initializer.dispatch_call_event mock_event, latch
256
+ latch.wait(10).should be_true
257
+ end
258
+ end
259
+
260
+ describe "with an inactive call" do
261
+ let(:mock_event) { flexmock 'Event', :call_id => call_id }
262
+
263
+ it "should log an error" do
264
+ flexmock(Adhearsion::Logging.get_logger(Initializer)).should_receive(:error).once.with("Event received for inactive call #{call_id}: #{mock_event.inspect}")
265
+ Initializer.dispatch_call_event mock_event
266
+ end
267
+ end
268
+ end
269
+
270
+ context "Punchblock configuration" do
271
+ describe "with config specified" do
272
+ before do
273
+ Adhearsion.config.punchblock do |config|
274
+ config.username = 'userb@127.0.0.1'
275
+ config.password = 'abc123'
276
+ end
277
+ end
278
+
279
+ subject do
280
+ Adhearsion.config[:punchblock]
281
+ end
282
+
283
+ it "should set properly the username value" do
284
+ subject.username.should == 'userb@127.0.0.1'
285
+ end
286
+
287
+ it "should set properly the password value" do
288
+ subject.password.should == 'abc123'
289
+ end
290
+ end
291
+ end
292
+ end
293
+ end
294
+ end
@@ -0,0 +1,99 @@
1
+ require 'spec_helper'
2
+
3
+ module Adhearsion
4
+ class Router
5
+ describe Route do
6
+ describe 'a new route' do
7
+ let(:name) { 'catchall' }
8
+ let(:guards) do
9
+ [
10
+ {:to => /foobar/},
11
+ [{:from => 'fred'}, {:from => 'paul'}]
12
+ ]
13
+ end
14
+
15
+ describe "with a class target and guards" do
16
+ let(:target) { CallController }
17
+
18
+ subject { Route.new name, target, *guards }
19
+
20
+ its(:name) { should == name }
21
+ its(:target) { should == target }
22
+ its(:guards) { should == guards }
23
+ end
24
+
25
+ describe "with a block target and guards" do
26
+ subject { Route.new(name, *guards) { :foo } }
27
+
28
+ its(:name) { should == name }
29
+ its(:target) { should be_a Proc }
30
+ its(:guards) { should == guards }
31
+ end
32
+ end
33
+
34
+ describe "a guarded route" do
35
+ subject { Route.new 'foobar', CallController, *guards }
36
+
37
+ def should_match_the_call
38
+ subject.match?(call).should be true
39
+ end
40
+
41
+ def should_not_match_the_call
42
+ subject.match?(call).should be false
43
+ end
44
+
45
+ describe "matching calls from fred to paul" do
46
+ let :guards do
47
+ [
48
+ {:from => 'fred', :to => 'paul'}
49
+ ]
50
+ end
51
+
52
+ context "with a call from fred to paul" do
53
+ let(:call) { flexmock 'Adhearsion::Call', :from => 'fred', :to => 'paul' }
54
+ it { should_match_the_call }
55
+ end
56
+
57
+ context "with a call from fred to frank" do
58
+ let(:call) { flexmock 'Adhearsion::Call', :from => 'fred', :to => 'frank' }
59
+ it { should_not_match_the_call }
60
+ end
61
+
62
+ context "with a call from frank to paul" do
63
+ let(:call) { flexmock 'Adhearsion::Call', :from => 'frank', :to => 'paul' }
64
+ it { should_not_match_the_call }
65
+ end
66
+ end
67
+ end
68
+
69
+ describe "dispatching a call" do
70
+ let(:call) { Call.new }
71
+
72
+ context "via a call controller" do
73
+ let(:controller) { CallController }
74
+ let(:route) { Route.new 'foobar', controller }
75
+
76
+ it "should instruct the call to use an instance of the controller" do
77
+ flexmock(call).should_receive(:execute_controller).once.with controller
78
+ route.dispatcher.call call
79
+ end
80
+ end
81
+
82
+ context "via a block" do
83
+ let :route do
84
+ Route.new 'foobar' do
85
+ :foobar
86
+ end
87
+ end
88
+
89
+ it "should instruct the call to use an instance of DialplanController with the correct block" do
90
+ flexmock(call).should_receive(:execute_controller).once.with(DialplanController).and_return do |controller|
91
+ controller.dialplan.call.should == :foobar
92
+ end
93
+ route.dispatcher.call call
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,106 @@
1
+ require 'spec_helper'
2
+
3
+ FooBarController = Class.new
4
+
5
+ module Adhearsion
6
+ describe Router do
7
+ describe 'a new router' do
8
+ subject { Router.new {} }
9
+
10
+ it "should make the router available to the block" do
11
+ foo = nil
12
+ Router.new do
13
+ foo = self
14
+ end
15
+ foo.should be_a Router
16
+ end
17
+
18
+ describe "defining routes in the block" do
19
+ let(:router) do
20
+ Router.new do
21
+ route 'calls from fred', FooBarController, :from => 'fred'
22
+ route 'calls from paul', :from => 'paul' do
23
+ :bar
24
+ end
25
+ route 'catchall' do
26
+ :foo
27
+ end
28
+ end
29
+ end
30
+
31
+ subject { router.routes }
32
+
33
+ it { should have(3).elements }
34
+
35
+ it "should contain Routes" do
36
+ subject.each do |route|
37
+ route.should be_a Router::Route
38
+ end
39
+ end
40
+
41
+ it "should build up the routes with the correct data" do
42
+ subject[0].name.should == 'calls from fred'
43
+ subject[0].guards.should == [{:from => 'fred'}]
44
+ subject[0].target.should == FooBarController
45
+
46
+ subject[1].name.should == 'calls from paul'
47
+ subject[1].guards.should == [{:from => 'paul'}]
48
+ subject[1].target.should be_a Proc
49
+
50
+ subject[2].name.should == 'catchall'
51
+ subject[2].guards.should == []
52
+ subject[2].target.should be_a Proc
53
+ end
54
+ end
55
+
56
+ describe "matching a call" do
57
+ let(:router) do
58
+ Router.new do
59
+ route 'calls from fred', FooBarController, :from => 'fred'
60
+ route 'calls from fred2', :from => 'fred' do
61
+ :car
62
+ end
63
+ route 'calls from paul', :from => 'paul' do
64
+ :bar
65
+ end
66
+ route 'catchall' do
67
+ :foo
68
+ end
69
+ end
70
+ end
71
+
72
+ subject { router.match call }
73
+
74
+ context 'with a call from fred' do
75
+ let(:call) { flexmock 'Adhearsion::Call', :from => 'fred' }
76
+ its(:name) { should == 'calls from fred' }
77
+ end
78
+
79
+ context 'with a call from paul' do
80
+ let(:call) { flexmock 'Adhearsion::Call', :from => 'paul' }
81
+ its(:name) { should == 'calls from paul' }
82
+ end
83
+
84
+ context 'with a call from frank' do
85
+ let(:call) { flexmock 'Adhearsion::Call', :from => 'frank' }
86
+ its(:name) { should == 'catchall' }
87
+ end
88
+ end
89
+
90
+ describe "handling a call" do
91
+ subject do
92
+ Router.new do
93
+ route 'catchall', FooBarController
94
+ end
95
+ end
96
+
97
+ let(:call) { flexmock 'Adhearsion::Call', :id => 'abc123' }
98
+ let(:route) { subject.routes.first }
99
+
100
+ it "should return the route's dispatcher" do
101
+ subject.handle(call).should be route.dispatcher
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end