eric-adhearsion 0.7.999 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (150) hide show
  1. data/CHANGELOG +8 -2
  2. data/EVENTS +11 -0
  3. data/Rakefile +96 -24
  4. data/adhearsion.gemspec +148 -0
  5. data/app_generators/ahn/ahn_generator.rb +24 -9
  6. data/app_generators/ahn/templates/.ahnrc +25 -3
  7. data/app_generators/ahn/templates/Rakefile +22 -2
  8. data/app_generators/ahn/templates/components/ami_remote/ami_remote.rb +15 -0
  9. data/app_generators/ahn/templates/components/disabled/HOW_TO_ENABLE +7 -0
  10. data/app_generators/ahn/templates/components/disabled/stomp_gateway/README.markdown +47 -0
  11. data/app_generators/ahn/templates/components/disabled/stomp_gateway/config.yml +12 -0
  12. data/app_generators/ahn/templates/components/disabled/stomp_gateway/stomp_gateway.rb +34 -0
  13. data/app_generators/ahn/templates/components/simon_game/{lib/simon_game.rb → simon_game.rb} +14 -19
  14. data/app_generators/ahn/templates/config/startup.rb +3 -6
  15. data/app_generators/ahn/templates/dialplan.rb +2 -3
  16. data/app_generators/ahn/templates/events.rb +32 -0
  17. data/bin/jahn +10 -0
  18. data/examples/asterisk_manager_interface/standalone.rb +51 -0
  19. data/lib/adhearsion.rb +17 -11
  20. data/lib/adhearsion/cli.rb +141 -24
  21. data/lib/adhearsion/component_manager.rb +169 -238
  22. data/lib/adhearsion/component_manager/component_tester.rb +55 -0
  23. data/lib/adhearsion/component_manager/spec_framework.rb +24 -0
  24. data/lib/adhearsion/events_support.rb +84 -0
  25. data/lib/adhearsion/{core_extensions → foundation}/all.rb +0 -0
  26. data/lib/adhearsion/{blank_slate.rb → foundation/blank_slate.rb} +0 -0
  27. data/lib/adhearsion/{core_extensions → foundation}/custom_daemonizer.rb +0 -0
  28. data/lib/adhearsion/foundation/event_socket.rb +203 -0
  29. data/lib/adhearsion/foundation/future_resource.rb +36 -0
  30. data/lib/adhearsion/{core_extensions → foundation}/global.rb +0 -0
  31. data/lib/adhearsion/{core_extensions → foundation}/metaprogramming.rb +0 -0
  32. data/lib/adhearsion/foundation/numeric.rb +13 -0
  33. data/lib/adhearsion/foundation/pseudo_guid.rb +10 -0
  34. data/lib/adhearsion/{core_extensions → foundation}/relationship_properties.rb +2 -0
  35. data/lib/adhearsion/foundation/string.rb +26 -0
  36. data/lib/adhearsion/foundation/synchronized_hash.rb +96 -0
  37. data/lib/adhearsion/{core_extensions → foundation}/thread_safety.rb +0 -0
  38. data/lib/adhearsion/host_definitions.rb +5 -1
  39. data/lib/adhearsion/initializer.rb +229 -73
  40. data/lib/adhearsion/initializer/asterisk.rb +33 -11
  41. data/lib/adhearsion/initializer/configuration.rb +58 -6
  42. data/lib/adhearsion/initializer/database.rb +3 -46
  43. data/lib/adhearsion/initializer/drb.rb +9 -3
  44. data/lib/adhearsion/initializer/freeswitch.rb +3 -3
  45. data/lib/adhearsion/initializer/rails.rb +1 -1
  46. data/lib/adhearsion/tasks.rb +2 -1
  47. data/lib/adhearsion/tasks/deprecations.rb +59 -0
  48. data/lib/adhearsion/version.rb +3 -3
  49. data/lib/adhearsion/voip/asterisk.rb +2 -2
  50. data/lib/adhearsion/voip/asterisk/agi_server.rb +9 -6
  51. data/lib/adhearsion/voip/asterisk/commands.rb +106 -4
  52. data/lib/adhearsion/voip/asterisk/manager_interface.rb +562 -0
  53. data/lib/adhearsion/voip/asterisk/manager_interface/ami_lexer.rb +1754 -0
  54. data/lib/adhearsion/voip/asterisk/manager_interface/ami_lexer.rl.rb +286 -0
  55. data/lib/adhearsion/voip/asterisk/manager_interface/ami_messages.rb +78 -0
  56. data/lib/adhearsion/voip/asterisk/manager_interface/ami_protocol_lexer_machine.rl +87 -0
  57. data/lib/adhearsion/voip/asterisk/super_manager.rb +19 -0
  58. data/lib/adhearsion/voip/call.rb +51 -2
  59. data/lib/adhearsion/voip/dial_plan.rb +74 -61
  60. data/lib/adhearsion/voip/dsl/dialing_dsl.rb +1 -1
  61. data/lib/adhearsion/voip/dsl/dialplan/parser.rb +2 -6
  62. data/lib/adhearsion/voip/dsl/numerical_string.rb +2 -2
  63. data/lib/adhearsion/voip/freeswitch/oes_server.rb +2 -2
  64. data/lib/theatre.rb +151 -0
  65. data/lib/theatre/README.markdown +64 -0
  66. data/lib/theatre/callback_definition_loader.rb +84 -0
  67. data/lib/theatre/guid.rb +23 -0
  68. data/lib/theatre/invocation.rb +121 -0
  69. data/lib/theatre/namespace_manager.rb +153 -0
  70. data/lib/theatre/version.rb +2 -0
  71. metadata +63 -138
  72. data/Manifest.txt +0 -149
  73. data/README.txt +0 -6
  74. data/ahn_generators/component/USAGE +0 -5
  75. data/ahn_generators/component/component_generator.rb +0 -57
  76. data/ahn_generators/component/templates/configuration.rb +0 -0
  77. data/ahn_generators/component/templates/lib/lib.rb.erb +0 -3
  78. data/ahn_generators/component/templates/test/test.rb.erb +0 -12
  79. data/ahn_generators/component/templates/test/test_helper.rb +0 -14
  80. data/app_generators/ahn/templates/components/simon_game/configuration.rb +0 -0
  81. data/app_generators/ahn/templates/components/simon_game/test/test_helper.rb +0 -14
  82. data/app_generators/ahn/templates/components/simon_game/test/test_simon_game.rb +0 -31
  83. data/lib/adhearsion/core_extensions/array.rb +0 -0
  84. data/lib/adhearsion/core_extensions/guid.rb +0 -5
  85. data/lib/adhearsion/core_extensions/hash.rb +0 -0
  86. data/lib/adhearsion/core_extensions/numeric.rb +0 -4
  87. data/lib/adhearsion/core_extensions/proc.rb +0 -0
  88. data/lib/adhearsion/core_extensions/pseudo_uuid.rb +0 -11
  89. data/lib/adhearsion/core_extensions/publishable.rb +0 -73
  90. data/lib/adhearsion/core_extensions/string.rb +0 -26
  91. data/lib/adhearsion/core_extensions/thread.rb +0 -13
  92. data/lib/adhearsion/core_extensions/time.rb +0 -0
  93. data/lib/adhearsion/distributed/gateways/dbus_gateway.rb +0 -0
  94. data/lib/adhearsion/distributed/gateways/osa_gateway.rb +0 -0
  95. data/lib/adhearsion/distributed/gateways/rest_gateway.rb +0 -9
  96. data/lib/adhearsion/distributed/gateways/soap_gateway.rb +0 -9
  97. data/lib/adhearsion/distributed/gateways/xmlrpc_gateway.rb +0 -9
  98. data/lib/adhearsion/distributed/peer_finder.rb +0 -0
  99. data/lib/adhearsion/distributed/remote_cli.rb +0 -0
  100. data/lib/adhearsion/hooks.rb +0 -57
  101. data/lib/adhearsion/initializer/paths.rb +0 -55
  102. data/lib/adhearsion/services/scheduler.rb +0 -5
  103. data/lib/adhearsion/voip/asterisk/ami.rb +0 -147
  104. data/lib/adhearsion/voip/asterisk/ami/actions.rb +0 -238
  105. data/lib/adhearsion/voip/asterisk/ami/machine.rb +0 -871
  106. data/lib/adhearsion/voip/asterisk/ami/machine.rl +0 -109
  107. data/lib/adhearsion/voip/asterisk/ami/parser.rb +0 -262
  108. data/script/destroy +0 -14
  109. data/script/generate +0 -14
  110. data/spec/fixtures/dialplan.rb +0 -3
  111. data/spec/initializer/test_configuration.rb +0 -267
  112. data/spec/initializer/test_loading.rb +0 -162
  113. data/spec/initializer/test_paths.rb +0 -43
  114. data/spec/silence.rb +0 -10
  115. data/spec/test_ahn_command.rb +0 -149
  116. data/spec/test_code_quality.rb +0 -87
  117. data/spec/test_component_manager.rb +0 -97
  118. data/spec/test_constants.rb +0 -8
  119. data/spec/test_drb.rb +0 -104
  120. data/spec/test_helper.rb +0 -94
  121. data/spec/test_hooks.rb +0 -37
  122. data/spec/test_host_definitions.rb +0 -79
  123. data/spec/test_initialization.rb +0 -105
  124. data/spec/test_logging.rb +0 -80
  125. data/spec/test_relationship_properties.rb +0 -54
  126. data/spec/voip/asterisk/ami_response_definitions.rb +0 -23
  127. data/spec/voip/asterisk/config_file_generators/test_agents.rb +0 -253
  128. data/spec/voip/asterisk/config_file_generators/test_queues.rb +0 -325
  129. data/spec/voip/asterisk/config_file_generators/test_voicemail.rb +0 -306
  130. data/spec/voip/asterisk/menu_command/test_calculated_match.rb +0 -111
  131. data/spec/voip/asterisk/menu_command/test_matchers.rb +0 -98
  132. data/spec/voip/asterisk/mock_ami_server.rb +0 -176
  133. data/spec/voip/asterisk/test_agi_server.rb +0 -451
  134. data/spec/voip/asterisk/test_ami.rb +0 -227
  135. data/spec/voip/asterisk/test_commands.rb +0 -2006
  136. data/spec/voip/asterisk/test_config_manager.rb +0 -129
  137. data/spec/voip/dsl/dispatcher_spec_helper.rb +0 -45
  138. data/spec/voip/dsl/test_dialing_dsl.rb +0 -268
  139. data/spec/voip/dsl/test_dispatcher.rb +0 -82
  140. data/spec/voip/dsl/test_parser.rb +0 -87
  141. data/spec/voip/freeswitch/test_basic_connection_manager.rb +0 -39
  142. data/spec/voip/freeswitch/test_inbound_connection_manager.rb +0 -39
  143. data/spec/voip/freeswitch/test_oes_server.rb +0 -9
  144. data/spec/voip/test_call_routing.rb +0 -127
  145. data/spec/voip/test_dialplan_manager.rb +0 -372
  146. data/spec/voip/test_numerical_string.rb +0 -48
  147. data/spec/voip/test_phone_number.rb +0 -36
  148. data/test/test_ahn_generator.rb +0 -59
  149. data/test/test_component_generator.rb +0 -52
  150. data/test/test_generator_helper.rb +0 -20
@@ -1,87 +0,0 @@
1
- require File.dirname(__FILE__) + '/../../test_helper'
2
-
3
- require 'adhearsion/voip/dsl/dialplan/parser'
4
-
5
- describe "The Adhearsion VoIP dialplan parser" do
6
-
7
- test "should return a list of dialplans properly from dialplan code" do
8
- file = "foobar.rb"
9
- flexmock(Adhearsion::Paths).should_receive(:manager_for?).and_return true
10
- flexmock(Adhearsion::VoIP::DSL::Dialplan::DialplanParser).
11
- should_receive(:all_dialplans).and_return [file]
12
-
13
- flexmock(File).should_receive(:exists?).with(file).and_return true
14
- flexmock(File).should_receive(:read).once.with(file).and_return <<-DIALPLAN
15
- internal {
16
- play "hello-world"
17
- }
18
- monkeys {
19
- play "tt-monkeys"
20
- }
21
- DIALPLAN
22
- contexts = Adhearsion::VoIP::DSL::Dialplan::DialplanParser.get_contexts
23
- contexts.keys.size.should.equal(2)
24
- contexts.keys.should.include(:internal)
25
- contexts.keys.should.include(:monkeys)
26
- contexts.each_pair do |context, struct|
27
- struct.should.be.kind_of(OpenStruct)
28
- %w"file name block".each do |method|
29
- struct.should.respond_to(method)
30
- end
31
- end
32
- end
33
-
34
- test "should raise an error when no dialplan paths were in the .ahnrc file" do
35
- lambda do
36
- # Not loading it here is the same as it not existing in the "paths" sub-Hash
37
- Adhearsion::Paths.manager_for?("dialplans").once.and_return false
38
- Adhearsion::VoIP::DSL::Dialplan::DialplanParser.get_contexts
39
- end.should.raise NoMethodError
40
- end
41
-
42
- test "should warn() when no dialplan files exist but return an empty Hash" #do
43
- # Adhearsion::Paths.should_receive(:manager_for?).with("dialplans").and_return true
44
- # Adhearsion::Paths.
45
- # Adhearsion::Logging::LoggingMethods.should_receive(:warn)
46
- #
47
- # end
48
-
49
- test "should warn() when no contexts were found but return an empty Hash" do
50
-
51
- end
52
-
53
- end
54
-
55
- describe "The Adhearsion VoIP dialplan interpreter" do
56
-
57
- test "should make dialplan contexts available within the context's block" do
58
- file = "contexts_from_code_helper_pseudo_dialplan.rb"
59
- flexmock(Adhearsion::Paths).should_receive(:manager_for?).once.with("dialplans").and_return true
60
- flexmock(Adhearsion::VoIP::DSL::Dialplan::DialplanParser).
61
- should_receive(:all_dialplans).and_return [file]
62
-
63
- flexmock(File).should_receive(:exists?).with(file).and_return true
64
- flexmock(File).should_receive(:read).with(file).and_return "foo { cool_method }"
65
-
66
- contexts = Adhearsion::VoIP::DSL::Dialplan::DialplanParser.get_contexts
67
-
68
- contexts.each_pair do |name, struct|
69
- contexts.meta_def(name) { struct.code }
70
- end
71
-
72
- # Simulate incoming request
73
- contexts = contexts.clone
74
-
75
- call_variables = { "callerid" => "14445556666", "context" => "foo" }
76
-
77
- call_variables.each_pair do |key, value|
78
- contexts.meta_def(key) { value }
79
- contexts.instance_variable_set "@#{key}", value
80
- end
81
-
82
- # TODO
83
- # dispatcher = DSL::Dialplan::CommandDispatcher.new
84
-
85
- end
86
-
87
- end
@@ -1,39 +0,0 @@
1
- require File.dirname(__FILE__) + "/../../test_helper"
2
- require 'adhearsion/voip/freeswitch/basic_connection_manager'
3
-
4
- include Adhearsion::VoIP::FreeSwitch
5
-
6
- context "FreeSwitch BasicConnectionManager" do
7
- attr_reader :manager, :io
8
- setup do
9
- @io = StringIO.new
10
- @manager = BasicConnectionManager.new io
11
- end
12
-
13
- test "<<() should add two newlines" do
14
- manager << "foobar"
15
- io.string.should == "foobar\n\n"
16
- end
17
-
18
- end
19
-
20
- context "FreeSwitch BasicConnectionManager's header parser" do
21
- test "YAML-like headers are read properly" do
22
- header = {
23
- "Foo-Bar" => "bar",
24
- "Qaz-Monkey-Charlie-Zebra" => "qwerty"
25
- }
26
-
27
- string_header = header.inject("") do |string, (key, value)|
28
- string + "#{key}: #{value}\n"
29
- end
30
-
31
- string_header << "\n"
32
-
33
- manager = BasicConnectionManager.new StringIO.new(string_header)
34
- manager.get_raw_header.should == string_header.strip
35
-
36
- manager = BasicConnectionManager.new StringIO.new(string_header)
37
- manager.get_header.should == header
38
- end
39
- end
@@ -1,39 +0,0 @@
1
- require File.dirname(__FILE__) + "/../../test_helper"
2
- require 'adhearsion/voip/freeswitch/inbound_connection_manager'
3
- include Adhearsion::VoIP::FreeSwitch
4
-
5
- context "A FreeSwitch InboundConnectionManager" do
6
-
7
- test "authenticatating with the given password" do
8
- manager = InboundConnectionManager.new io_mock
9
- manager.login password
10
- end
11
-
12
- test "a hash is accepted when creating a new InboundConnectionManager" do
13
- host, port = "myhost.mydomain", 31337
14
-
15
- flexmock(TCPSocket).should_receive(:new).once.with(host, port).and_return io_mock
16
-
17
- InboundConnectionManager.new :host => host, :port => port, :pass => password
18
- end
19
-
20
- test "an IO is accepted when creating a new InboundConnectionManager"
21
-
22
- private
23
- def io_mock
24
- @io_mock ||=
25
- begin
26
- io_mock = StringIO.new
27
- flexmock(io_mock) do |io|
28
- io.should_receive(:write).with("auth #{password}\n\n")
29
- io.should_receive(:gets).and_return "connection: kthnx\n",
30
- "\n", "login: +OK\n", "\n"
31
- end
32
- io_mock
33
- end
34
- end
35
-
36
- def password
37
- "supersecret"
38
- end
39
- end
@@ -1,9 +0,0 @@
1
- require File.dirname(__FILE__) + "/../../test_helper"
2
- require File.dirname(__FILE__) + "/../dsl/dispatcher_spec_helper"
3
- require 'adhearsion/voip/freeswitch/oes_server'
4
-
5
-
6
- describe "Adhearsion::VoIP::FreeSwitch::OesServer::OesDispatcher" do
7
- include StandardDispatcherBehavior
8
- setup { @dispatcher_class = Adhearsion::VoIP::FreeSwitch::OesServer::OesDispatcher }
9
- end
@@ -1,127 +0,0 @@
1
- require File.dirname(__FILE__) + '/../test_helper'
2
-
3
- context "Call routing rule generation" do
4
- include CallRoutingTestHelper
5
-
6
- attr_reader :provider_one, :provider_two, :patterns
7
-
8
- setup do
9
- @provider_one = provider_named(:one)
10
- @provider_two = provider_named(:two)
11
- @patterns = [/pattern/, /does not/, /matter/]
12
- end
13
-
14
- test "specifying a single pattern routed to a single provider properly stores that pattern and its provider in the generated route rule" do
15
- pattern = %r(does not matter)
16
- rule = route(pattern, :to => provider_one)
17
- rule.patterns.should.equal [pattern]
18
- rule.providers.should.equal [provider_one]
19
- end
20
-
21
- test "specifying multiple patterns routed to a single provider stores all of them in the generated route rule" do
22
- first, second, third = patterns
23
- rule = route(first, second, third, :to => provider_one)
24
- rule.patterns.should.equal [*patterns]
25
- rule.providers.should.equal [provider_one]
26
- end
27
-
28
- test "specifying multiple patterns routed to multiple providers stores all of them in the generated route rule, listing providers in the ordered specified" do
29
- first, second, third = patterns
30
- rule = route(first, second, third, :to => [provider_one, provider_two])
31
- rule.patterns.should.equal [*patterns]
32
- rule.providers.should.equal [provider_one, provider_two]
33
- end
34
- end
35
-
36
- context "Route calculation" do
37
- include CallRoutingTestHelper
38
- attr_reader :provider_one, :provider_two
39
-
40
- setup do
41
- rules.clear
42
- @provider_one = provider_named(:one)
43
- @provider_two = provider_named(:two)
44
- end
45
-
46
- test "Defining a rule adds it to the router rules" do
47
- provider = provider_one
48
- pattern = /123/
49
- define_rules do
50
- route pattern, :to => provider
51
- end
52
- rules.size.should.equal 1
53
- rule = rules.first
54
- rule.providers.should.equal [provider]
55
- rule.patterns.should.equal [pattern]
56
- end
57
-
58
- test "Definiting multiple rules adds them to the router rules" do
59
- provider_for_rule_1 = provider_one
60
- provider_for_rule_2 = provider_two
61
- pattern_for_rule_1 = /123/
62
- pattern_for_rule_2 = /987/
63
-
64
- define_rules do
65
- route pattern_for_rule_1, :to => provider_for_rule_1
66
- route pattern_for_rule_2, :to => provider_for_rule_2
67
- end
68
-
69
- rules.size.should.equal 2
70
-
71
- rule_1 = rules.first
72
- rule_1.providers.should.equal [provider_for_rule_1]
73
- rule_1.patterns.should.equal [pattern_for_rule_1]
74
-
75
- rule_2 = rules.last
76
- rule_2.providers.should.equal [provider_for_rule_2]
77
- rule_2.patterns.should.equal [pattern_for_rule_2]
78
- end
79
-
80
- test "Provider is found in the simplest case of having only one pattern and one provider" do
81
- target_provider = provider_one
82
- define_rules do
83
- route /123/, :to => target_provider
84
- end
85
- calculate_route_for(1234).should.equal [target_provider]
86
- end
87
-
88
- test "Provider is found when the specified pattern matches a rule that is not the first rule" do
89
- provider_for_rule_1 = provider_one
90
- provider_for_rule_2 = provider_two
91
- pattern_for_rule_1 = /123/
92
- pattern_for_rule_2 = /987/
93
-
94
- define_rules do
95
- route pattern_for_rule_1, :to => provider_for_rule_1
96
- route pattern_for_rule_2, :to => provider_for_rule_2
97
- end
98
-
99
- target_provider = provider_for_rule_2
100
- calculate_route_for(9876).should.equal [target_provider]
101
- end
102
- end
103
-
104
- BEGIN {
105
- module CallRoutingTestHelper
106
- private
107
- def route(*args, &block)
108
- Adhearsion::VoIP::CallRouting::Rule.new(*args, &block)
109
- end
110
-
111
- def provider_named(name)
112
- Adhearsion::VoIP::DSL::DialingDSL::ProviderDefinition.new(name)
113
- end
114
-
115
- def define_rules(&block)
116
- Adhearsion::VoIP::CallRouting::Router.define(&block)
117
- end
118
-
119
- def calculate_route_for(end_point)
120
- Adhearsion::VoIP::CallRouting::Router.calculate_route_for(end_point)
121
- end
122
-
123
- def rules
124
- Adhearsion::VoIP::CallRouting::Router.rules
125
- end
126
- end
127
- }
@@ -1,372 +0,0 @@
1
- require File.dirname(__FILE__) + "/../test_helper"
2
- require 'adhearsion/voip/dsl/dialplan/parser'
3
-
4
- context "Dialplan::Manager handling" do
5
-
6
- include DialplanTestingHelper
7
-
8
- attr_accessor :manager, :call, :context_name, :mock_context
9
-
10
- before do
11
- @context_name = :some_context_name
12
- @mock_context = flexmock('a context')
13
-
14
- hack_to_work_around_parser_coupling
15
- mock_dial_plan_lookup_for_context_name
16
- flexmock(Adhearsion::DialPlan::Loader).should_receive(:load_dial_plan).and_return{flexmock("loaded contexts", :contexts => nil)}
17
- @manager = Adhearsion::DialPlan::Manager.new
18
- @call = new_call_for_context context_name
19
-
20
- # Sanity check context name being set
21
- call.context.should.equal context_name
22
- end
23
-
24
- test "Given a Call, the manager finds the call's desired entry point/context" do
25
- manager.entry_point_for(call).should.equal mock_context
26
- end
27
-
28
- test "The manager handles a call by executing the proper context" do
29
- flexmock(Adhearsion::DialPlan::ExecutionEnvironment).new_instances.should_receive(:run).once
30
- manager.handle(call)
31
- end
32
-
33
- test "should raise a NoContextError exception if the targeted context is not found" do
34
- the_following_code {
35
- flexmock(manager).should_receive(:entry_point_for).and_return nil
36
- manager.handle call
37
- }.should.raise(Adhearsion::DialPlan::Manager::NoContextError)
38
- end
39
-
40
- test 'should send :answer to the execution environment if Adhearsion::AHN_CONFIG.automatically_answer_incoming_calls is set' do
41
- mock_ahn_config = flexmock 'a mock of the Adhearsion::Configuration object that is normally set when an app is initialized'
42
- mock_ahn_config.should_receive(:automatically_answer_incoming_calls).once.and_return true
43
- flexmock(Adhearsion::Configuration).should_receive(:new).once.and_return(mock_ahn_config)
44
- flexmock(Adhearsion::DialPlan::ExecutionEnvironment).new_instances.should_receive(:answer).once.and_throw :answered_call!
45
- Adhearsion::Configuration.configure
46
- the_following_code {
47
- manager.handle(call)
48
- }.should.throw :answered_call!
49
- end
50
-
51
- test 'should not send :answer to the executuon environment if Adhearsion::AHN_CONFIG.automatically_answer_incoming_calls is NOT set' do
52
-
53
- mock_ahn_config = flexmock 'a mock of the Adhearsion::Configuration object that is normally set when an app is initialized'
54
- mock_ahn_config.should_receive(:automatically_answer_incoming_calls).once.and_return false
55
-
56
- entry_point = Adhearsion::DialPlan::DialplanContextProc.new(:does_not_matter) {}
57
- flexmock(manager).should_receive(:entry_point_for).once.with(call).and_return(entry_point)
58
-
59
- flexmock(Adhearsion::Configuration).should_receive(:new).once.and_return(mock_ahn_config)
60
- flexmock(Adhearsion::DialPlan::ExecutionEnvironment).new_instances.should_receive(:entry_point).and_return entry_point
61
- flexmock(Adhearsion::DialPlan::ExecutionEnvironment).new_instances.should_receive(:answer).never
62
- flexmock(Adhearsion::DialPlan::ExecutionEnvironment).new_instances.should_receive(:instance_eval).and_throw :doing_dialplan
63
-
64
- Adhearsion::Configuration.configure
65
- manager.handle(call)
66
- end
67
-
68
- private
69
- def hack_to_work_around_parser_coupling
70
- flexmock(Adhearsion::Paths).should_receive(:manager_for?).and_return(true)
71
- flexmock(Adhearsion::VoIP::DSL::Dialplan::DialplanParser).should_receive(:all_dialplans).and_return([])
72
- end
73
-
74
- def mock_dial_plan_lookup_for_context_name
75
- flexmock(Adhearsion::DialPlan).new_instances.should_receive(:lookup).with(context_name).and_return(mock_context)
76
- end
77
- end
78
-
79
- context "DialPlan::Manager's handling a failed call" do
80
-
81
- include DialplanTestingHelper
82
-
83
- test 'should check if the call has failed and then instruct it to extract the reason from the environment' do
84
- flexmock(Adhearsion::DialPlan::ExecutionEnvironment).new_instances.should_receive(:variable).with("REASON").once.and_return '3'
85
- call = Adhearsion::Call.new(nil, {'extension' => "failed"})
86
- call.should.be.failed_call
87
- flexmock(Adhearsion::DialPlan).should_receive(:new).once.and_return flexmock("bogus DialPlan which should never be used")
88
- begin
89
- Adhearsion::DialPlan::Manager.handle(call)
90
- rescue Adhearsion::FailedExtensionCallException => error
91
- error.call.failed_reason.should == Adhearsion::Call::ASTERISK_FRAME_STATES[3]
92
- end
93
- end
94
- end
95
-
96
- context "DialPlan::Manager's handling a hungup call" do
97
-
98
- include DialplanTestingHelper
99
-
100
- test 'should check if the call was a hangup meta-AGI call and then raise a HangupExtensionCallException' do
101
- call = Adhearsion::Call.new(nil, {'extension' => "h"})
102
- call.should.be.hungup_call
103
- flexmock(Adhearsion::DialPlan).should_receive(:new).once.and_return flexmock("bogus DialPlan which should never be used")
104
- the_following_code {
105
- Adhearsion::DialPlan::Manager.handle(call)
106
- }.should.raise Adhearsion::HungupExtensionCallException
107
- end
108
-
109
- end
110
-
111
- context "DialPlan" do
112
-
113
- attr_accessor :loader, :loader_instance, :dial_plan
114
-
115
- before do
116
- @loader = Adhearsion::DialPlan::Loader
117
- @loader_instance = @loader.new
118
- flexmock(Adhearsion::DialPlan::Loader).should_receive(:load_dial_plan).once.and_return(@loader_instance)
119
- @dial_plan = Adhearsion::DialPlan.new(Adhearsion::DialPlan::Loader)
120
- end
121
-
122
- test "When a dial plan is instantiated, the dialplans are loaded and stored for lookup" do
123
- dial_plan.instance_variable_get("@entry_points").should.not.be.nil
124
- end
125
-
126
- test "Can look up an entry point from a dial plan" do
127
- context_name = 'this_context_is_better_than_your_context'
128
- loader_instance.contexts[context_name] = lambda { puts "o hai" }
129
- dial_plan.lookup(context_name).should.not.be.nil
130
- end
131
- end
132
-
133
- context "DialPlan loader" do
134
-
135
- include DialplanTestingHelper
136
-
137
- test "loading a single context" do
138
- loader = load(<<-DIAL_PLAN)
139
- one {
140
- raise 'this block should not be evaluated'
141
- }
142
- DIAL_PLAN
143
-
144
- loader.contexts.keys.size.should.equal 1
145
- loader.contexts.keys.first.should.equal :one
146
- end
147
-
148
- test "loading multiple contexts loads all contexts" do
149
- loader = load(<<-DIAL_PLAN)
150
- one {
151
- raise 'this block should not be evaluated'
152
- }
153
-
154
- two {
155
- raise 'this other block should not be evaluated either'
156
- }
157
- DIAL_PLAN
158
-
159
- loader.contexts.keys.size.should.equal 2
160
- loader.contexts.keys.map(&:to_s).sort.should.equal %w(one two)
161
- end
162
-
163
- test 'loading a dialplan with a syntax error' do
164
- the_following_code {
165
- load "foo { &@(*!&(*@*!@^!^%@%^! }"
166
- }.should.raise SyntaxError
167
- end
168
-
169
- test "loading a dial plan from a file" do
170
- loader = nil
171
- the_following_code {
172
- AHN_ROOT.using_base_path(File.expand_path(File.dirname(__FILE__) + '/../fixtures')) do
173
- loader = Adhearsion::DialPlan::Loader.load_dial_plan
174
- end
175
- }.should.not.raise
176
-
177
- loader.contexts.keys.size.should.equal 1
178
- loader.contexts.keys.first.should.equal :sample_context
179
- end
180
-
181
- end
182
-
183
- context "The inbox-related dialplan methods" do
184
-
185
- include DialplanTestingHelper
186
-
187
- test "with_next_message should execute its block with the message from the inbox" do
188
- mock_call = new_call_for_context :entrance
189
- [:one, :two, :three].each { |message| mock_call.inbox << message }
190
-
191
- dialplan = %{ entrance { with_next_message { |message| throw message } } }
192
- executing_dialplan(:entrance => dialplan, :call => mock_call).should.throw :one
193
- end
194
-
195
-
196
- test "messages_waiting? should return false if the inbox is empty" do
197
- mock_call = new_call_for_context :entrance
198
- dialplan = %{ entrance { throw messages_waiting? ? :yes : :no } }
199
- executing_dialplan(:entrance => dialplan, :call => mock_call).should.throw :no
200
- end
201
-
202
- test "messages_waiting? should return false if the inbox is not empty" do
203
- mock_call = new_call_for_context :entrance
204
- mock_call.inbox << Object.new
205
- dialplan = %{ entrance { throw messages_waiting? ? :yes : :no } }
206
- executing_dialplan(:entrance => dialplan, :call => mock_call).should.throw :yes
207
- end
208
-
209
- end
210
-
211
-
212
- context "ExecutionEnvironemnt" do
213
- attr_accessor :call, :entry_point
214
-
215
- include DialplanTestingHelper
216
-
217
- before do
218
- variables = { :context => "zomgzlols", :caller_id => "Ponce de Leon" }
219
- @call = Adhearsion::Call.new(nil, variables)
220
- @entry_point = lambda {}
221
- end
222
-
223
- test "On initialization, ExecutionEnvironments extend themselves with behavior specific to the voip platform which originated the call" do
224
- Adhearsion::DialPlan::ExecutionEnvironment.included_modules.should.not.include(Adhearsion::VoIP::Asterisk::Commands)
225
- execution_environent = Adhearsion::DialPlan::ExecutionEnvironment.new(call, entry_point)
226
- execution_environent.metaclass.included_modules.should.include(Adhearsion::VoIP::Asterisk::Commands)
227
- end
228
-
229
- test "An executed context should raise a NameError error when a missing constant is referenced" do
230
- the_following_code do
231
- call = new_call_for_context :context_with_missing_constant
232
- mock_dialplan_with "context_with_missing_constant { ThisConstantDoesntExist }"
233
- manager = new_manager_with_entry_points_loaded_from_dialplan_contexts
234
- manager.handle call
235
- end.should.raise NameError
236
-
237
- end
238
-
239
- test "should define variables accessors within itself" do
240
- environment = Adhearsion::DialPlan::ExecutionEnvironment.new(@call, entry_point)
241
- call.variables.should.not.be.empty
242
- call.variables.each do |key, value|
243
- environment.send(key).should.equal value
244
- end
245
- end
246
-
247
- test "should define accessors for other contexts in the dialplan" do
248
- call = new_call_for_context :am_not_for_kokoa!
249
- bogus_dialplan = <<-DIALPLAN
250
- am_not_for_kokoa! {}
251
- icanhascheezburger? {}
252
- these_context_names_do_not_really_matter {}
253
- DIALPLAN
254
-
255
- mock_dialplan_with bogus_dialplan
256
- manager = Adhearsion::DialPlan::Manager.new
257
- manager.dial_plan.entry_points = manager.dial_plan.loader.load_dial_plan.contexts
258
- manager.dial_plan.entry_points.should.not.be.empty
259
-
260
- manager.handle call
261
-
262
- %w(these_context_names_do_not_really_matter icanhascheezburger? am_not_for_kokoa!).each do |context_name|
263
- manager.context.respond_to?(context_name).should.equal true
264
- end
265
- end
266
-
267
- end
268
-
269
- context "Dialplan control statements" do
270
-
271
- include DialplanTestingHelper
272
-
273
- test "Manager should catch ControlPassingExceptions" do
274
- dialplan = %{
275
- foo { raise Adhearsion::VoIP::DSL::Dialplan::ControlPassingException.new(bar) }
276
- bar {}
277
- }
278
- executing_dialplan(:foo => dialplan).should.not.raise
279
- end
280
-
281
- test "Proc#+@ should not return to its originating context" do
282
- dialplan = %{
283
- andere {}
284
- zuerst {
285
- +andere
286
- throw :after_control_statement
287
- }
288
- }
289
- executing_dialplan(:zuerst => dialplan).should.not.throw
290
- end
291
- test "All dialplan contexts should be available at context execution time" do
292
- dialplan = %{
293
- context_defined_first {
294
- throw :i_see_it if context_defined_second
295
- }
296
- context_defined_second {}
297
- }
298
- executing_dialplan(:context_defined_first => dialplan).should.throw :i_see_it
299
- end
300
- test "Proc#+@ should execute the other context" do
301
- dialplan = %{
302
- eins {
303
- +zwei
304
- throw :eins
305
- }
306
- zwei {
307
- throw :zwei
308
- }
309
- }
310
- executing_dialplan(:eins => dialplan).should.throw :zwei
311
- end
312
-
313
- test "new constants should still be accessible within the dialplan" do
314
- ::Jicksta = :Jicksta
315
- dialplan = %{
316
- constant_test {
317
- Jicksta.should.equal:Jicksta
318
- }
319
- }
320
- executing_dialplan(:constant_test => dialplan).should.not.raise
321
- end
322
-
323
- end
324
-
325
- context "VoIP platform operations" do
326
- test "can map a platform name to a module which holds its platform-specific operations" do
327
- Adhearsion::VoIP::Commands.for(:asterisk).should == Adhearsion::VoIP::Asterisk::Commands
328
- end
329
- end
330
-
331
- context 'ContextNameCollector' do
332
- test '::build should raise a SyntaxError when the dialplan String contains one' do
333
- the_following_code {
334
- Adhearsion::DialPlan::Loader::ContextNameCollector.build "foo { ((((( *@!^*@&*^!^@ }"
335
- }.should.raise SyntaxError
336
- end
337
- end
338
-
339
- BEGIN {
340
- module DialplanTestingHelper
341
- def load(dial_plan_as_string)
342
- Adhearsion::DialPlan::Loader.load(dial_plan_as_string)
343
- end
344
-
345
- def mock_dialplan_with(string)
346
- flexstub(Adhearsion::DialPlan::Loader).should_receive(:read_dialplan_file).and_return(string)
347
- end
348
-
349
- def new_manager_with_entry_points_loaded_from_dialplan_contexts
350
- returning Adhearsion::DialPlan::Manager.new do |manager|
351
- manager.dial_plan.entry_points = manager.dial_plan.loader.load_dial_plan.contexts
352
- end
353
- end
354
-
355
- def executing_dialplan(options)
356
- call = options.delete(:call)
357
- context_name = options.keys.first
358
- dialplan = options[context_name]
359
- call ||= new_call_for_context context_name
360
-
361
- mock_dialplan_with dialplan
362
- lambda do
363
- Adhearsion::DialPlan::Manager.new.handle call
364
- end
365
- end
366
-
367
- def new_call_for_context(context)
368
- Adhearsion::Call.new(StringIO.new, :context => context)
369
- end
370
- end
371
-
372
- }