adhearsion 2.6.4 → 3.0.0.beta1

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 (242) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +6 -9
  3. data/CHANGELOG.md +22 -7
  4. data/Gemfile +2 -0
  5. data/README.markdown +4 -5
  6. data/Rakefile +1 -2
  7. data/adhearsion.gemspec +19 -8
  8. data/features/cli_create.feature +19 -3
  9. data/features/step_definitions/cli_steps.rb +0 -11
  10. data/features/support/env.rb +3 -4
  11. data/lib/adhearsion.rb +48 -27
  12. data/lib/adhearsion/call.rb +34 -50
  13. data/lib/adhearsion/call_controller.rb +6 -12
  14. data/lib/adhearsion/call_controller/dial.rb +15 -53
  15. data/lib/adhearsion/call_controller/input.rb +39 -162
  16. data/lib/adhearsion/call_controller/input/ask_grammar_builder.rb +44 -0
  17. data/lib/adhearsion/call_controller/input/menu_builder.rb +136 -0
  18. data/lib/adhearsion/call_controller/input/prompt_builder.rb +78 -0
  19. data/lib/adhearsion/call_controller/input/result.rb +46 -0
  20. data/lib/adhearsion/call_controller/output.rb +48 -67
  21. data/lib/adhearsion/call_controller/output/abstract_player.rb +3 -3
  22. data/lib/adhearsion/call_controller/output/async_player.rb +3 -3
  23. data/lib/adhearsion/call_controller/output/player.rb +1 -1
  24. data/lib/adhearsion/call_controller/record.rb +23 -8
  25. data/lib/adhearsion/calls.rb +1 -1
  26. data/lib/adhearsion/cli_commands/ahn_command.rb +2 -65
  27. data/lib/adhearsion/cli_commands/thor_errors.rb +0 -6
  28. data/lib/adhearsion/configuration.rb +91 -39
  29. data/lib/adhearsion/core_ext/blather/stanza.rb +41 -0
  30. data/lib/adhearsion/core_ext/blather/stanza/presence.rb +13 -0
  31. data/lib/adhearsion/error.rb +5 -0
  32. data/lib/adhearsion/event.rb +21 -0
  33. data/lib/adhearsion/event/active_speaker.rb +11 -0
  34. data/lib/adhearsion/event/answered.rb +11 -0
  35. data/lib/adhearsion/event/asterisk.rb +10 -0
  36. data/lib/adhearsion/event/asterisk/ami.rb +34 -0
  37. data/lib/adhearsion/event/complete.rb +75 -0
  38. data/lib/adhearsion/event/dtmf.rb +11 -0
  39. data/lib/adhearsion/event/end.rb +22 -0
  40. data/lib/adhearsion/event/input_timers_started.rb +9 -0
  41. data/lib/adhearsion/event/joined.rb +17 -0
  42. data/lib/adhearsion/event/offer.rb +14 -0
  43. data/lib/adhearsion/event/ringing.rb +11 -0
  44. data/lib/adhearsion/event/started_speaking.rb +13 -0
  45. data/lib/adhearsion/event/stopped_speaking.rb +13 -0
  46. data/lib/adhearsion/event/unjoined.rb +17 -0
  47. data/lib/adhearsion/events.rb +47 -66
  48. data/lib/adhearsion/foundation.rb +0 -1
  49. data/lib/adhearsion/foundation/object.rb +0 -5
  50. data/lib/adhearsion/generators/app/app_generator.rb +4 -1
  51. data/lib/adhearsion/generators/app/templates/Gemfile.erb +2 -10
  52. data/lib/adhearsion/generators/app/templates/adhearsion.erb +9 -9
  53. data/lib/adhearsion/generators/app/templates/config.ru +7 -0
  54. data/lib/adhearsion/generators/app/templates/en.yml +4 -0
  55. data/lib/adhearsion/generators/app/templates/events.erb +2 -2
  56. data/lib/adhearsion/generators/app/templates/hello_world.wav +0 -0
  57. data/lib/adhearsion/generators/app/templates/simon_game.rb +2 -1
  58. data/lib/adhearsion/generators/app/templates/simon_game_spec.rb +2 -2
  59. data/lib/adhearsion/has_headers.rb +34 -0
  60. data/lib/adhearsion/http_server.rb +37 -0
  61. data/lib/adhearsion/initializer.rb +19 -153
  62. data/lib/adhearsion/logging.rb +6 -25
  63. data/lib/adhearsion/outbound_call.rb +5 -5
  64. data/lib/adhearsion/plugin.rb +1 -0
  65. data/lib/adhearsion/protocol_error.rb +26 -0
  66. data/lib/adhearsion/rayo.rb +30 -0
  67. data/lib/adhearsion/rayo/client.rb +62 -0
  68. data/lib/adhearsion/rayo/client/component_registry.rb +33 -0
  69. data/lib/adhearsion/rayo/command.rb +21 -0
  70. data/lib/adhearsion/rayo/command/accept.rb +16 -0
  71. data/lib/adhearsion/rayo/command/answer.rb +16 -0
  72. data/lib/adhearsion/rayo/command/dial.rb +57 -0
  73. data/lib/adhearsion/rayo/command/hangup.rb +16 -0
  74. data/lib/adhearsion/rayo/command/join.rb +43 -0
  75. data/lib/adhearsion/rayo/command/mute.rb +13 -0
  76. data/lib/adhearsion/rayo/command/redirect.rb +23 -0
  77. data/lib/adhearsion/rayo/command/reject.rb +40 -0
  78. data/lib/adhearsion/rayo/command/unjoin.rb +24 -0
  79. data/lib/adhearsion/rayo/command/unmute.rb +13 -0
  80. data/lib/adhearsion/rayo/command_node.rb +47 -0
  81. data/lib/adhearsion/rayo/component.rb +21 -0
  82. data/lib/adhearsion/rayo/component/asterisk.rb +13 -0
  83. data/lib/adhearsion/rayo/component/asterisk/agi.rb +14 -0
  84. data/lib/adhearsion/rayo/component/asterisk/agi/command.rb +46 -0
  85. data/lib/adhearsion/rayo/component/asterisk/ami.rb +14 -0
  86. data/lib/adhearsion/rayo/component/asterisk/ami/action.rb +61 -0
  87. data/lib/adhearsion/rayo/component/component_node.rb +90 -0
  88. data/lib/adhearsion/rayo/component/input.rb +186 -0
  89. data/lib/adhearsion/rayo/component/output.rb +471 -0
  90. data/lib/adhearsion/rayo/component/prompt.rb +53 -0
  91. data/lib/adhearsion/rayo/component/receive_fax.rb +26 -0
  92. data/lib/adhearsion/rayo/component/record.rb +165 -0
  93. data/lib/adhearsion/rayo/component/send_fax.rb +64 -0
  94. data/lib/adhearsion/rayo/component/stop.rb +11 -0
  95. data/lib/adhearsion/rayo/connection.rb +12 -0
  96. data/lib/adhearsion/rayo/connection/asterisk.rb +74 -0
  97. data/lib/adhearsion/rayo/connection/connected.rb +22 -0
  98. data/lib/adhearsion/rayo/connection/generic_connection.rb +22 -0
  99. data/lib/adhearsion/rayo/connection/xmpp.rb +198 -0
  100. data/lib/adhearsion/rayo/disconnected_error.rb +22 -0
  101. data/lib/adhearsion/{punchblock_plugin → rayo}/initializer.rb +19 -19
  102. data/lib/adhearsion/rayo/rayo_node.rb +127 -0
  103. data/lib/adhearsion/rayo/ref.rb +57 -0
  104. data/lib/adhearsion/statistics.rb +1 -1
  105. data/lib/adhearsion/tasks.rb +1 -2
  106. data/lib/adhearsion/tasks/configuration.rb +1 -1
  107. data/lib/adhearsion/tasks/environment.rb +0 -2
  108. data/lib/adhearsion/tasks/i18n.rb +49 -0
  109. data/lib/adhearsion/translator.rb +11 -0
  110. data/lib/adhearsion/translator/asterisk.rb +234 -0
  111. data/lib/adhearsion/translator/asterisk/agi_app.rb +17 -0
  112. data/lib/adhearsion/translator/asterisk/agi_command.rb +45 -0
  113. data/lib/adhearsion/translator/asterisk/ami_error_converter.rb +20 -0
  114. data/lib/adhearsion/translator/asterisk/call.rb +416 -0
  115. data/lib/adhearsion/translator/asterisk/channel.rb +43 -0
  116. data/lib/adhearsion/translator/asterisk/component.rb +88 -0
  117. data/lib/adhearsion/translator/asterisk/component/asterisk.rb +15 -0
  118. data/lib/adhearsion/translator/asterisk/component/asterisk/agi_command.rb +42 -0
  119. data/lib/adhearsion/translator/asterisk/component/asterisk/ami_action.rb +68 -0
  120. data/lib/adhearsion/translator/asterisk/component/composed_prompt.rb +76 -0
  121. data/lib/adhearsion/translator/asterisk/component/dtmf_recognizer.rb +137 -0
  122. data/lib/adhearsion/translator/asterisk/component/input.rb +34 -0
  123. data/lib/adhearsion/translator/asterisk/component/input_component.rb +90 -0
  124. data/lib/adhearsion/translator/asterisk/component/mrcp_native_prompt.rb +71 -0
  125. data/lib/adhearsion/translator/asterisk/component/mrcp_prompt.rb +55 -0
  126. data/lib/adhearsion/translator/asterisk/component/mrcp_recog_prompt.rb +165 -0
  127. data/lib/adhearsion/translator/asterisk/component/output.rb +233 -0
  128. data/lib/adhearsion/translator/asterisk/component/record.rb +101 -0
  129. data/lib/adhearsion/translator/asterisk/component/stop_by_redirect.rb +30 -0
  130. data/lib/adhearsion/translator/asterisk/unimrcp_app.rb +28 -0
  131. data/lib/adhearsion/uri_list.rb +21 -0
  132. data/lib/adhearsion/version.rb +1 -1
  133. data/spec/adhearsion/call_controller/dial_spec.rb +79 -1420
  134. data/spec/adhearsion/call_controller/input_spec.rb +1141 -237
  135. data/spec/adhearsion/call_controller/output/async_player_spec.rb +10 -10
  136. data/spec/adhearsion/call_controller/output/player_spec.rb +8 -8
  137. data/spec/adhearsion/call_controller/output_spec.rb +162 -215
  138. data/spec/adhearsion/call_controller/record_spec.rb +15 -16
  139. data/spec/adhearsion/call_controller_spec.rb +23 -40
  140. data/spec/adhearsion/call_spec.rb +123 -129
  141. data/spec/adhearsion/calls_spec.rb +3 -3
  142. data/spec/adhearsion/configuration_spec.rb +94 -108
  143. data/spec/adhearsion/event/answered_spec.rb +50 -0
  144. data/spec/adhearsion/event/asterisk/Find Results +402 -0
  145. data/spec/adhearsion/event/asterisk/ami_spec.rb +81 -0
  146. data/spec/adhearsion/event/complete_spec.rb +176 -0
  147. data/spec/adhearsion/event/dtmf_spec.rb +35 -0
  148. data/spec/adhearsion/event/end_spec.rb +85 -0
  149. data/spec/adhearsion/event/input_timers_started_spec.rb +19 -0
  150. data/spec/adhearsion/event/joined_spec.rb +53 -0
  151. data/spec/adhearsion/event/offer_spec.rb +106 -0
  152. data/spec/adhearsion/event/ringing_spec.rb +50 -0
  153. data/spec/adhearsion/event/started_speaking_spec.rb +37 -0
  154. data/spec/adhearsion/event/stopped_speaking_spec.rb +37 -0
  155. data/spec/adhearsion/event/unjoined_spec.rb +48 -0
  156. data/spec/adhearsion/event/untitled +0 -0
  157. data/spec/adhearsion/events_spec.rb +19 -45
  158. data/spec/adhearsion/initializer_spec.rb +12 -184
  159. data/spec/adhearsion/logging_spec.rb +5 -20
  160. data/spec/adhearsion/outbound_call_spec.rb +13 -13
  161. data/spec/adhearsion/plugin_spec.rb +3 -4
  162. data/spec/adhearsion/protocol_error_spec.rb +91 -0
  163. data/spec/adhearsion/rayo/client/component_registry_spec.rb +26 -0
  164. data/spec/adhearsion/rayo/client_spec.rb +134 -0
  165. data/spec/adhearsion/rayo/command/accept_spec.rb +63 -0
  166. data/spec/adhearsion/rayo/command/answer_spec.rb +73 -0
  167. data/spec/adhearsion/rayo/command/dial_spec.rb +156 -0
  168. data/spec/adhearsion/rayo/command/hangup_spec.rb +63 -0
  169. data/spec/adhearsion/rayo/command/join_spec.rb +158 -0
  170. data/spec/adhearsion/rayo/command/mute_spec.rb +32 -0
  171. data/spec/adhearsion/rayo/command/redirect_spec.rb +89 -0
  172. data/spec/adhearsion/rayo/command/reject_spec.rb +117 -0
  173. data/spec/adhearsion/rayo/command/unjoin_spec.rb +82 -0
  174. data/spec/adhearsion/rayo/command/unmute_spec.rb +32 -0
  175. data/spec/adhearsion/rayo/command_node_spec.rb +101 -0
  176. data/spec/adhearsion/rayo/component/asterisk/agi/command_spec.rb +111 -0
  177. data/spec/adhearsion/rayo/component/asterisk/ami/action_spec.rb +173 -0
  178. data/spec/adhearsion/rayo/component/component_node_spec.rb +110 -0
  179. data/spec/adhearsion/rayo/component/input_spec.rb +715 -0
  180. data/spec/adhearsion/rayo/component/output_spec.rb +1030 -0
  181. data/spec/adhearsion/rayo/component/prompt_spec.rb +171 -0
  182. data/spec/adhearsion/rayo/component/receive_fax_spec.rb +136 -0
  183. data/spec/adhearsion/rayo/component/record_spec.rb +497 -0
  184. data/spec/adhearsion/rayo/component/send_fax_spec.rb +144 -0
  185. data/spec/adhearsion/rayo/connection/asterisk_spec.rb +118 -0
  186. data/spec/adhearsion/rayo/connection/xmpp_spec.rb +449 -0
  187. data/spec/adhearsion/rayo/initializer_spec.rb +353 -0
  188. data/spec/adhearsion/rayo/ref_spec.rb +168 -0
  189. data/spec/adhearsion/rayo_spec.rb +7 -0
  190. data/spec/adhearsion/router/route_spec.rb +1 -1
  191. data/spec/adhearsion/statistics_spec.rb +2 -5
  192. data/spec/adhearsion/translator/asterisk/call_spec.rb +2047 -0
  193. data/spec/adhearsion/translator/asterisk/component/asterisk/agi_command_spec.rb +256 -0
  194. data/spec/adhearsion/translator/asterisk/component/asterisk/ami_action_spec.rb +151 -0
  195. data/spec/adhearsion/translator/asterisk/component/composed_prompt_spec.rb +257 -0
  196. data/spec/adhearsion/translator/asterisk/component/input_spec.rb +571 -0
  197. data/spec/adhearsion/translator/asterisk/component/mrcp_native_prompt_spec.rb +774 -0
  198. data/spec/adhearsion/translator/asterisk/component/mrcp_prompt_spec.rb +1244 -0
  199. data/spec/adhearsion/translator/asterisk/component/output_spec.rb +1850 -0
  200. data/spec/adhearsion/translator/asterisk/component/record_spec.rb +426 -0
  201. data/spec/adhearsion/translator/asterisk/component/stop_by_redirect_spec.rb +62 -0
  202. data/spec/adhearsion/translator/asterisk/component_spec.rb +83 -0
  203. data/spec/adhearsion/translator/asterisk_spec.rb +685 -0
  204. data/spec/adhearsion/uri_list_spec.rb +88 -0
  205. data/spec/adhearsion_spec.rb +89 -14
  206. data/spec/fixtures/locale/en.yml +13 -0
  207. data/spec/fixtures/locale/it.yml +13 -0
  208. data/spec/spec_helper.rb +18 -5
  209. data/spec/support/call_controller_test_helpers.rb +3 -2
  210. data/spec/support/initializer_stubs.rb +3 -1
  211. data/spec/support/punchblock_examples.rb +65 -0
  212. data/spec/support/punchblock_mocks.rb +12 -0
  213. metadata +412 -70
  214. data/features/cli_daemon.feature +0 -20
  215. data/features/cli_restart.feature +0 -52
  216. data/features/cli_stop.feature +0 -50
  217. data/lib/adhearsion/call_controller/menu_dsl.rb +0 -21
  218. data/lib/adhearsion/call_controller/menu_dsl/array_match_calculator.rb +0 -26
  219. data/lib/adhearsion/call_controller/menu_dsl/calculated_match.rb +0 -43
  220. data/lib/adhearsion/call_controller/menu_dsl/calculated_match_collection.rb +0 -45
  221. data/lib/adhearsion/call_controller/menu_dsl/fixnum_match_calculator.rb +0 -11
  222. data/lib/adhearsion/call_controller/menu_dsl/match_calculator.rb +0 -40
  223. data/lib/adhearsion/call_controller/menu_dsl/menu.rb +0 -207
  224. data/lib/adhearsion/call_controller/menu_dsl/menu_builder.rb +0 -92
  225. data/lib/adhearsion/call_controller/menu_dsl/range_match_calculator.rb +0 -60
  226. data/lib/adhearsion/call_controller/menu_dsl/string_match_calculator.rb +0 -25
  227. data/lib/adhearsion/call_controller/utility.rb +0 -77
  228. data/lib/adhearsion/foundation/custom_daemonizer.rb +0 -52
  229. data/lib/adhearsion/punchblock_plugin.rb +0 -63
  230. data/scripts/cloc-1.64.pl +0 -10483
  231. data/spec/adhearsion/call_controller/menu_dsl/array_match_calculator_spec.rb +0 -76
  232. data/spec/adhearsion/call_controller/menu_dsl/calculated_match_collection_spec.rb +0 -60
  233. data/spec/adhearsion/call_controller/menu_dsl/calculated_match_spec.rb +0 -61
  234. data/spec/adhearsion/call_controller/menu_dsl/fixnum_match_calculator_spec.rb +0 -39
  235. data/spec/adhearsion/call_controller/menu_dsl/match_calculator_spec.rb +0 -17
  236. data/spec/adhearsion/call_controller/menu_dsl/menu_builder_spec.rb +0 -165
  237. data/spec/adhearsion/call_controller/menu_dsl/menu_spec.rb +0 -420
  238. data/spec/adhearsion/call_controller/menu_dsl/range_match_calculator_spec.rb +0 -32
  239. data/spec/adhearsion/call_controller/menu_dsl/string_match_calculator_spec.rb +0 -40
  240. data/spec/adhearsion/call_controller/utility_spec.rb +0 -90
  241. data/spec/adhearsion/punchblock_plugin/initializer_spec.rb +0 -356
  242. data/spec/adhearsion/punchblock_plugin_spec.rb +0 -59
@@ -0,0 +1,353 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Adhearsion::Rayo::Initializer do
6
+
7
+ def reset_default_config
8
+ Adhearsion.config.core do |config|
9
+ config.type = :xmpp
10
+ config.username = "usera@127.0.0.1"
11
+ config.password = "1"
12
+ config.host = nil
13
+ config.port = nil
14
+ config.certs_directory = nil
15
+ config.root_domain = nil
16
+ config.connection_timeout = 60
17
+ config.reconnect_attempts = 1.0/0.0
18
+ config.reconnect_timer = 5
19
+ end
20
+ end
21
+
22
+ def initialize_rayo(options = {})
23
+ reset_default_config
24
+ allow(described_class).to receive(:connect)
25
+ Adhearsion.config.core do |config|
26
+ config.type = options[:type] if options.has_key?(:type)
27
+ config.username = options[:username] if options.has_key?(:username)
28
+ config.password = options[:password] if options.has_key?(:password)
29
+ config.host = options[:host] if options.has_key?(:host)
30
+ config.port = options[:port] if options.has_key?(:port)
31
+ config.certs_directory = options[:certs_directory] if options.has_key?(:certs_directory)
32
+ config.root_domain = options[:root_domain] if options.has_key?(:root_domain)
33
+ config.connection_timeout = options[:connection_timeout] if options.has_key?(:connection_timeout)
34
+ config.reconnect_attempts = options[:reconnect_attempts] if options.has_key?(:reconnect_attempts)
35
+ config.reconnect_timer = options[:reconnect_timer] if options.has_key?(:reconnect_timer)
36
+ end
37
+
38
+ described_class.init
39
+ Adhearsion.config.core
40
+ end
41
+
42
+ let(:call_id) { rand }
43
+ let(:offer) { Adhearsion::Event::Offer.new :target_call_id => call_id }
44
+ let(:mock_call) { Adhearsion::Call.new }
45
+ let(:mock_client) { double 'Client' }
46
+
47
+ before do
48
+ allow(mock_call).to receive_messages :id => call_id
49
+ mock_client.as_null_object
50
+ allow(mock_client).to receive_messages :event_handler= => true
51
+ Adhearsion::Events.refresh!
52
+ allow(Adhearsion::Process).to receive_messages :fqdn => 'hostname'
53
+ allow(::Process).to receive_messages :pid => 1234
54
+ end
55
+
56
+ describe "starts the client with the default values" do
57
+ subject { initialize_rayo }
58
+
59
+ it "should set properly the username value" do
60
+ expect(subject.username).to eq('usera@127.0.0.1')
61
+ end
62
+
63
+ it "should set properly the password value" do
64
+ expect(subject.password).to eq('1')
65
+ end
66
+
67
+ it "should set properly the host value" do
68
+ expect(subject.host).to be_nil
69
+ end
70
+
71
+ it "should set properly the port value" do
72
+ expect(subject.port).to be_nil
73
+ end
74
+
75
+ it "should set properly the certs_directory value" do
76
+ expect(subject.certs_directory).to be_nil
77
+ end
78
+
79
+ it "should set properly the root_domain value" do
80
+ expect(subject.root_domain).to be_nil
81
+ end
82
+
83
+ it "should properly set the reconnect_attempts value" do
84
+ expect(subject.reconnect_attempts).to eq(1.0/0.0)
85
+ end
86
+
87
+ it "should properly set the reconnect_timer value" do
88
+ expect(subject.reconnect_timer).to eq(5)
89
+ end
90
+ end
91
+
92
+ it "starts the client with the correct resource" do
93
+ username = "usera@127.0.0.1/hostname-1234"
94
+
95
+ expect(Adhearsion::Rayo::Connection::XMPP).to receive(:new).once.with(hash_including :username => username).and_return mock_client
96
+ initialize_rayo
97
+ end
98
+
99
+ context "when the fqdn is not available" do
100
+ it "should use the local hostname instead" do
101
+ allow(Adhearsion::Process).to receive(:fqdn).and_raise SocketError
102
+ allow(Socket).to receive(:gethostname).and_return 'local_hostname'
103
+
104
+ username = "usera@127.0.0.1/local_hostname-1234"
105
+
106
+ expect(Adhearsion::Rayo::Connection::XMPP).to receive(:new).once.with(hash_including :username => username).and_return mock_client
107
+ initialize_rayo
108
+ end
109
+ end
110
+
111
+ it "starts the client with any overridden settings" do
112
+ expect(Adhearsion::Rayo::Connection::XMPP).to receive(:new).once.with(username: 'userb@127.0.0.1/foo', password: '123', host: 'foo.bar.com', port: 200, certs: '/foo/bar', connection_timeout: 20, root_domain: 'foo.com').and_return mock_client
113
+ initialize_rayo username: 'userb@127.0.0.1/foo', password: '123', host: 'foo.bar.com', port: 200, certs_directory: '/foo/bar', connection_timeout: 20, root_domain: 'foo.com'
114
+ end
115
+
116
+ describe "#connect" do
117
+ it 'should block until the connection is established' do
118
+ reset_default_config
119
+ mock_connection = double :mock_connection
120
+ expect(mock_connection).to receive(:register_event_handler).once
121
+ expect(Adhearsion::Rayo::Client).to receive(:new).once.and_return mock_connection
122
+ expect(mock_connection).to receive(:run).once
123
+ t = Thread.new { described_class.init; described_class.run }
124
+ t.join 5
125
+ expect(t.status).to eq("sleep")
126
+ Adhearsion::Events.trigger_immediately :rayo, Adhearsion::Rayo::Connection::Connected.new
127
+ t.join
128
+ end
129
+ end
130
+
131
+ describe '#connect_to_server' do
132
+ before :each do
133
+ Adhearsion::Process.reset
134
+ described_class.config = reset_default_config
135
+ described_class.config.reconnect_attempts = 1
136
+ expect(Adhearsion::Logging.get_logger(described_class)).to receive(:fatal).at_most(:once)
137
+ allow(described_class).to receive(:client).and_return mock_client
138
+ end
139
+
140
+ after :each do
141
+ Adhearsion::Process.reset
142
+ end
143
+
144
+ it 'should reset the Adhearsion process state to "booting"' do
145
+ Adhearsion::Process.booted
146
+ expect(Adhearsion::Process.state_name).to eq(:running)
147
+ allow(mock_client).to receive(:run).and_raise Adhearsion::Rayo::DisconnectedError
148
+ expect(Adhearsion::Process).to receive(:reset).at_least(:once)
149
+ described_class.connect_to_server
150
+ end
151
+
152
+ it 'should retry the connection the specified number of times' do
153
+ described_class.config.reconnect_attempts = 3
154
+ allow(mock_client).to receive(:run).and_raise Adhearsion::Rayo::DisconnectedError
155
+ described_class.connect_to_server
156
+ expect(described_class.attempts).to eq(3)
157
+ end
158
+
159
+ it 'should preserve a Adhearsion::ProtocolError exception and give up' do
160
+ allow(mock_client).to receive(:run).and_raise Adhearsion::ProtocolError
161
+ expect { described_class.connect_to_server }.to raise_error Adhearsion::ProtocolError
162
+ end
163
+
164
+ it 'should not attempt to reconnect if Adhearsion is shutting down' do
165
+ Adhearsion::Process.booted
166
+ Adhearsion::Process.shutdown
167
+ allow(mock_client).to receive(:run).and_raise Adhearsion::Rayo::DisconnectedError
168
+ expect { described_class.connect_to_server }.not_to raise_error
169
+ end
170
+ end
171
+
172
+ describe 'using Asterisk' do
173
+ let(:overrides) { {:username => 'test', :password => '123', :host => 'foo.bar.com', :port => 200, :certs => nil, :connection_timeout => 20, :root_domain => 'foo.com'} }
174
+
175
+ it 'should start an Asterisk PB connection' do
176
+ expect(Adhearsion::Rayo::Connection::Asterisk).to receive(:new).once.with(overrides).and_return mock_client
177
+ initialize_rayo overrides.merge(:type => :asterisk)
178
+ end
179
+ end
180
+
181
+ it 'should place events into the event handler' do
182
+ event = nil
183
+ latch = CountDownLatch.new 1
184
+
185
+ Adhearsion::Events.register_handler :rayo do |offer|
186
+ event = offer
187
+ latch.countdown!
188
+ end
189
+
190
+ initialize_rayo
191
+ described_class.client.handle_event offer
192
+
193
+ expect(latch.wait(2)).to be_truthy
194
+ expect(event).to be(offer)
195
+ end
196
+
197
+ describe "dispatching an offer" do
198
+ before do
199
+ initialize_rayo
200
+ expect(Adhearsion::Process).to receive(:state_name).once.and_return process_state
201
+ expect(Adhearsion::Call).to receive(:new).once.and_return mock_call
202
+ end
203
+
204
+ context "when the Adhearsion::Process is :booting" do
205
+ let(:process_state) { :booting }
206
+
207
+ it 'should reject a call with cause :declined' do
208
+ expect(mock_call).to receive(:reject).once.with(:decline)
209
+ end
210
+ end
211
+
212
+ [ :running, :stopping ].each do |state|
213
+ context "when when Adhearsion::Process is in :#{state}" do
214
+ let(:process_state) { state }
215
+
216
+ it "should dispatch via the router" do
217
+ Adhearsion.router do
218
+ route 'foobar', Class.new
219
+ end
220
+ expect(Adhearsion.router).to receive(:handle).once.with mock_call
221
+ end
222
+ end
223
+ end
224
+
225
+ context "when when Adhearsion::Process is in :rejecting" do
226
+ let(:process_state) { :rejecting }
227
+
228
+ it 'should reject a call with cause :declined' do
229
+ expect(mock_call).to receive(:reject).once.with(:decline)
230
+ end
231
+ end
232
+
233
+ context "when when Adhearsion::Process is not :running, :stopping or :rejecting" do
234
+ let(:process_state) { :foobar }
235
+
236
+ it 'should reject a call with cause :error' do
237
+ expect(mock_call).to receive(:reject).once.with(:error)
238
+ end
239
+ end
240
+
241
+ after { Adhearsion::Events.trigger_immediately :rayo, offer }
242
+ end
243
+
244
+ describe "dispatching a component event" do
245
+ let(:component) { double 'ComponentNode' }
246
+ let(:mock_event) { double 'Event' }
247
+
248
+ before { allow(mock_event).to receive_messages target_call_id: call_id, source: component }
249
+
250
+ before do
251
+ initialize_rayo
252
+ end
253
+
254
+ it "should place the event in the call's inbox" do
255
+ expect(component).to receive(:trigger_event_handler).once.with mock_event
256
+ Adhearsion::Events.trigger_immediately :rayo, mock_event
257
+ end
258
+ end
259
+
260
+ describe "dispatching a call event" do
261
+ let(:mock_event) { double 'Event' }
262
+
263
+ before { allow(mock_event).to receive_messages target_call_id: call_id }
264
+
265
+ describe "with an active call" do
266
+ before do
267
+ initialize_rayo
268
+ Adhearsion.active_calls << mock_call
269
+ end
270
+
271
+ it "should forward the event to the call actor" do
272
+ events = []
273
+ mock_call.register_event_handler do |event|
274
+ events << event
275
+ end
276
+ described_class.dispatch_call_event mock_event
277
+ sleep 0.5
278
+ expect(events).to eql([mock_event])
279
+ end
280
+
281
+ it "should not block on the call handling the event" do
282
+
283
+ mock_call.register_event_handler do |event|
284
+ sleep 5
285
+ end
286
+ start_time = Time.now
287
+ described_class.dispatch_call_event mock_event
288
+ sleep 0.5
289
+ expect(Time.now - start_time).to be < 1
290
+ end
291
+ end
292
+
293
+ describe "with an inactive call" do
294
+ it "should log a warning" do
295
+ expect(Adhearsion::Logging.get_logger(described_class)).to receive(:warn).once.with("Event received for inactive call #{call_id}: #{mock_event.inspect}")
296
+ described_class.dispatch_call_event mock_event
297
+ end
298
+ end
299
+
300
+ describe "when the registry contains a dead call" do
301
+ before do
302
+ mock_call.terminate
303
+ Adhearsion.active_calls[mock_call.id] = mock_call
304
+ end
305
+
306
+ it "should log a warning" do
307
+ expect(Adhearsion::Logging.get_logger(described_class)).to receive(:warn).once.with("Event received for inactive call #{call_id}: #{mock_event.inspect}")
308
+ described_class.dispatch_call_event mock_event
309
+ end
310
+ end
311
+ end
312
+
313
+ context "rayo configuration" do
314
+ describe "with config specified" do
315
+ before do
316
+ Adhearsion.config.core do |config|
317
+ config.username = 'userb@127.0.0.1'
318
+ config.password = 'abc123'
319
+ end
320
+ end
321
+
322
+ subject do
323
+ Adhearsion.config.core
324
+ end
325
+
326
+ it "should set properly the username value" do
327
+ expect(subject.username).to eq('userb@127.0.0.1')
328
+ end
329
+
330
+ it "should set properly the password value" do
331
+ expect(subject.password).to eq('abc123')
332
+ end
333
+ end
334
+ end
335
+
336
+ it "should allow easily registering handlers for AMI events" do
337
+ result = nil
338
+ ami_event = Adhearsion::Event::Asterisk::AMI.new :name => 'foobar'
339
+ latch = CountDownLatch.new 1
340
+
341
+ Adhearsion::Events.draw do
342
+ ami :name => 'foobar' do |event|
343
+ result = event
344
+ latch.countdown!
345
+ end
346
+ end
347
+
348
+ described_class.handle_event ami_event
349
+
350
+ expect(latch.wait(1)).to be true
351
+ expect(result).to be ami_event
352
+ end
353
+ end
@@ -0,0 +1,168 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Adhearsion::Rayo::Ref do
6
+ it 'registers itself' do
7
+ expect(Adhearsion::Rayo::RayoNode.class_from_registration(:ref, 'urn:xmpp:rayo:1')).to eq(described_class)
8
+ end
9
+
10
+ describe "from a stanza" do
11
+ let(:uri) { 'some_uri' }
12
+ let(:stanza) { "<ref uri='#{uri}' xmlns='urn:xmpp:rayo:1' />" }
13
+
14
+ subject { Adhearsion::Rayo::RayoNode.from_xml parse_stanza(stanza).root, '9f00061', '1' }
15
+
16
+ it { is_expected.to be_instance_of described_class }
17
+
18
+ describe '#target_call_id' do
19
+ subject { super().target_call_id }
20
+ it { is_expected.to eq('9f00061') }
21
+ end
22
+
23
+ context "when the URI isn't actually a URI" do
24
+ let(:uri) { 'fgh4590' }
25
+
26
+ describe '#uri' do
27
+ subject { super().uri }
28
+ it { is_expected.to eq(URI('fgh4590')) }
29
+ end
30
+
31
+ describe '#scheme' do
32
+ subject { super().scheme }
33
+ it { is_expected.to eq(nil) }
34
+ end
35
+
36
+ describe '#call_id' do
37
+ subject { super().call_id }
38
+ it { is_expected.to eq('fgh4590') }
39
+ end
40
+
41
+ describe '#domain' do
42
+ subject { super().domain }
43
+ it { is_expected.to eq(nil) }
44
+ end
45
+
46
+ describe '#component_id' do
47
+ subject { super().component_id }
48
+ it { is_expected.to eq('fgh4590') }
49
+ end
50
+ end
51
+
52
+ context "when the URI is an XMPP JID" do
53
+ let(:uri) { 'xmpp:fgh4590@rayo.net/abc123' }
54
+
55
+ describe '#uri' do
56
+ subject { super().uri }
57
+ it { is_expected.to eq(URI('xmpp:fgh4590@rayo.net/abc123')) }
58
+ end
59
+
60
+ describe '#scheme' do
61
+ subject { super().scheme }
62
+ it { is_expected.to eq('xmpp') }
63
+ end
64
+
65
+ describe '#call_id' do
66
+ subject { super().call_id }
67
+ it { is_expected.to eq('fgh4590') }
68
+ end
69
+
70
+ describe '#domain' do
71
+ subject { super().domain }
72
+ it { is_expected.to eq('rayo.net') }
73
+ end
74
+
75
+ describe '#component_id' do
76
+ subject { super().component_id }
77
+ it { is_expected.to eq('abc123') }
78
+ end
79
+ end
80
+
81
+ context "when the URI is an asterisk UUID" do
82
+ let(:uri) { 'asterisk:fgh4590' }
83
+
84
+ describe '#uri' do
85
+ subject { super().uri }
86
+ it { is_expected.to eq(URI('asterisk:fgh4590')) }
87
+ end
88
+
89
+ describe '#scheme' do
90
+ subject { super().scheme }
91
+ it { is_expected.to eq('asterisk') }
92
+ end
93
+
94
+ describe '#call_id' do
95
+ subject { super().call_id }
96
+ it { is_expected.to eq('fgh4590') }
97
+ end
98
+
99
+ describe '#domain' do
100
+ subject { super().domain }
101
+ it { is_expected.to eq(nil) }
102
+ end
103
+
104
+ describe '#component_id' do
105
+ subject { super().component_id }
106
+ it { is_expected.to eq('fgh4590') }
107
+ end
108
+ end
109
+ end
110
+
111
+ describe "when setting options in initializer" do
112
+ subject { described_class.new uri: uri }
113
+ let(:uri) { 'xmpp:fgh4590@rayo.net/abc123' }
114
+
115
+ describe '#uri' do
116
+ subject { super().uri }
117
+ it { is_expected.to eq(URI('xmpp:fgh4590@rayo.net/abc123')) }
118
+ end
119
+
120
+ describe "exporting to Rayo" do
121
+ context "when the URI isn't actually a URI" do
122
+ let(:uri) { 'fgh4590' }
123
+
124
+ it "should export to XML that can be understood by its parser" do
125
+ new_instance = Adhearsion::Rayo::RayoNode.from_xml subject.to_rayo
126
+ expect(new_instance).to be_instance_of described_class
127
+ expect(new_instance.uri).to eq(URI('fgh4590'))
128
+ end
129
+ end
130
+
131
+ context "when the URI is an XMPP JID" do
132
+ let(:uri) { 'xmpp:fgh4590@rayo.net' }
133
+
134
+ it "should export to XML that can be understood by its parser" do
135
+ new_instance = Adhearsion::Rayo::RayoNode.from_xml subject.to_rayo
136
+ expect(new_instance).to be_instance_of described_class
137
+ expect(new_instance.uri).to eq(URI('xmpp:fgh4590@rayo.net'))
138
+ end
139
+ end
140
+
141
+ context "when the URI is an asterisk UUID" do
142
+ let(:uri) { 'asterisk:fgh4590' }
143
+
144
+ it "should export to XML that can be understood by its parser" do
145
+ new_instance = Adhearsion::Rayo::RayoNode.from_xml subject.to_rayo
146
+ expect(new_instance).to be_instance_of described_class
147
+ expect(new_instance.uri).to eq(URI('asterisk:fgh4590'))
148
+ end
149
+ end
150
+
151
+ it "should render to a parent node if supplied" do
152
+ doc = Nokogiri::XML::Document.new
153
+ parent = Nokogiri::XML::Node.new 'foo', doc
154
+ doc.root = parent
155
+ rayo_doc = subject.to_rayo(parent)
156
+ expect(rayo_doc).to eq(parent)
157
+ end
158
+
159
+ context "when attributes are not set" do
160
+ subject { described_class.new }
161
+
162
+ it "should not include them in the XML representation" do
163
+ expect(subject.to_rayo['uri']).to be_nil
164
+ end
165
+ end
166
+ end
167
+ end
168
+ end