sevenscale-adhearsion 0.7.1000
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +3 -0
- data/LICENSE +456 -0
- data/Manifest.txt +149 -0
- data/README.txt +6 -0
- data/Rakefile +48 -0
- data/ahn_generators/component/USAGE +5 -0
- data/ahn_generators/component/component_generator.rb +57 -0
- data/ahn_generators/component/templates/configuration.rb +0 -0
- data/ahn_generators/component/templates/lib/lib.rb.erb +3 -0
- data/ahn_generators/component/templates/test/test.rb.erb +12 -0
- data/ahn_generators/component/templates/test/test_helper.rb +14 -0
- data/app_generators/ahn/USAGE +5 -0
- data/app_generators/ahn/ahn_generator.rb +76 -0
- data/app_generators/ahn/templates/.ahnrc +12 -0
- data/app_generators/ahn/templates/README +8 -0
- data/app_generators/ahn/templates/Rakefile +3 -0
- data/app_generators/ahn/templates/components/simon_game/configuration.rb +0 -0
- data/app_generators/ahn/templates/components/simon_game/lib/simon_game.rb +61 -0
- data/app_generators/ahn/templates/components/simon_game/test/test_helper.rb +14 -0
- data/app_generators/ahn/templates/components/simon_game/test/test_simon_game.rb +31 -0
- data/app_generators/ahn/templates/config/startup.rb +53 -0
- data/app_generators/ahn/templates/dialplan.rb +4 -0
- data/bin/ahn +28 -0
- data/bin/ahnctl +68 -0
- data/bin/jahn +32 -0
- data/lib/adhearsion/blank_slate.rb +5 -0
- data/lib/adhearsion/cli.rb +106 -0
- data/lib/adhearsion/component_manager.rb +277 -0
- data/lib/adhearsion/core_extensions/all.rb +9 -0
- data/lib/adhearsion/core_extensions/array.rb +0 -0
- data/lib/adhearsion/core_extensions/custom_daemonizer.rb +45 -0
- data/lib/adhearsion/core_extensions/global.rb +1 -0
- data/lib/adhearsion/core_extensions/guid.rb +5 -0
- data/lib/adhearsion/core_extensions/hash.rb +0 -0
- data/lib/adhearsion/core_extensions/metaprogramming.rb +17 -0
- data/lib/adhearsion/core_extensions/numeric.rb +4 -0
- data/lib/adhearsion/core_extensions/proc.rb +0 -0
- data/lib/adhearsion/core_extensions/pseudo_uuid.rb +11 -0
- data/lib/adhearsion/core_extensions/publishable.rb +73 -0
- data/lib/adhearsion/core_extensions/relationship_properties.rb +40 -0
- data/lib/adhearsion/core_extensions/string.rb +26 -0
- data/lib/adhearsion/core_extensions/thread.rb +13 -0
- data/lib/adhearsion/core_extensions/thread_safety.rb +7 -0
- data/lib/adhearsion/core_extensions/time.rb +0 -0
- data/lib/adhearsion/distributed/gateways/dbus_gateway.rb +0 -0
- data/lib/adhearsion/distributed/gateways/osa_gateway.rb +0 -0
- data/lib/adhearsion/distributed/gateways/rest_gateway.rb +9 -0
- data/lib/adhearsion/distributed/gateways/soap_gateway.rb +9 -0
- data/lib/adhearsion/distributed/gateways/xmlrpc_gateway.rb +9 -0
- data/lib/adhearsion/distributed/peer_finder.rb +0 -0
- data/lib/adhearsion/distributed/remote_cli.rb +0 -0
- data/lib/adhearsion/hooks.rb +57 -0
- data/lib/adhearsion/host_definitions.rb +63 -0
- data/lib/adhearsion/initializer/asterisk.rb +59 -0
- data/lib/adhearsion/initializer/configuration.rb +202 -0
- data/lib/adhearsion/initializer/database.rb +92 -0
- data/lib/adhearsion/initializer/drb.rb +25 -0
- data/lib/adhearsion/initializer/freeswitch.rb +22 -0
- data/lib/adhearsion/initializer/paths.rb +55 -0
- data/lib/adhearsion/initializer/rails.rb +40 -0
- data/lib/adhearsion/initializer.rb +217 -0
- data/lib/adhearsion/logging.rb +92 -0
- data/lib/adhearsion/services/scheduler.rb +5 -0
- data/lib/adhearsion/tasks/database.rb +5 -0
- data/lib/adhearsion/tasks/generating.rb +20 -0
- data/lib/adhearsion/tasks/lint.rb +4 -0
- data/lib/adhearsion/tasks/testing.rb +37 -0
- data/lib/adhearsion/tasks.rb +15 -0
- data/lib/adhearsion/version.rb +9 -0
- data/lib/adhearsion/voip/asterisk/agi_server.rb +78 -0
- data/lib/adhearsion/voip/asterisk/ami/actions.rb +238 -0
- data/lib/adhearsion/voip/asterisk/ami/machine.rb +871 -0
- data/lib/adhearsion/voip/asterisk/ami/machine.rl +109 -0
- data/lib/adhearsion/voip/asterisk/ami/parser.rb +262 -0
- data/lib/adhearsion/voip/asterisk/ami.rb +147 -0
- data/lib/adhearsion/voip/asterisk/commands.rb +1186 -0
- data/lib/adhearsion/voip/asterisk/config_generators/agents.conf.rb +140 -0
- data/lib/adhearsion/voip/asterisk/config_generators/config_generator.rb +101 -0
- data/lib/adhearsion/voip/asterisk/config_generators/queues.conf.rb +250 -0
- data/lib/adhearsion/voip/asterisk/config_generators/voicemail.conf.rb +240 -0
- data/lib/adhearsion/voip/asterisk/config_manager.rb +71 -0
- data/lib/adhearsion/voip/asterisk/special_dial_plan_managers.rb +80 -0
- data/lib/adhearsion/voip/asterisk.rb +4 -0
- data/lib/adhearsion/voip/call.rb +402 -0
- data/lib/adhearsion/voip/call_routing.rb +64 -0
- data/lib/adhearsion/voip/commands.rb +9 -0
- data/lib/adhearsion/voip/constants.rb +39 -0
- data/lib/adhearsion/voip/conveniences.rb +18 -0
- data/lib/adhearsion/voip/dial_plan.rb +205 -0
- data/lib/adhearsion/voip/dsl/dialing_dsl/dialing_dsl_monkey_patches.rb +37 -0
- data/lib/adhearsion/voip/dsl/dialing_dsl.rb +151 -0
- data/lib/adhearsion/voip/dsl/dialplan/control_passing_exception.rb +27 -0
- data/lib/adhearsion/voip/dsl/dialplan/dispatcher.rb +124 -0
- data/lib/adhearsion/voip/dsl/dialplan/parser.rb +75 -0
- data/lib/adhearsion/voip/dsl/dialplan/thread_mixin.rb +16 -0
- data/lib/adhearsion/voip/dsl/numerical_string.rb +117 -0
- data/lib/adhearsion/voip/freeswitch/basic_connection_manager.rb +48 -0
- data/lib/adhearsion/voip/freeswitch/event_handler.rb +58 -0
- data/lib/adhearsion/voip/freeswitch/freeswitch_dialplan_command_factory.rb +129 -0
- data/lib/adhearsion/voip/freeswitch/inbound_connection_manager.rb +38 -0
- data/lib/adhearsion/voip/freeswitch/oes_server.rb +195 -0
- data/lib/adhearsion/voip/menu_state_machine/calculated_match.rb +80 -0
- data/lib/adhearsion/voip/menu_state_machine/matchers.rb +123 -0
- data/lib/adhearsion/voip/menu_state_machine/menu_builder.rb +58 -0
- data/lib/adhearsion/voip/menu_state_machine/menu_class.rb +149 -0
- data/lib/adhearsion.rb +31 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/spec/fixtures/dialplan.rb +3 -0
- data/spec/initializer/test_configuration.rb +267 -0
- data/spec/initializer/test_loading.rb +162 -0
- data/spec/initializer/test_paths.rb +43 -0
- data/spec/silence.rb +10 -0
- data/spec/test_ahn_command.rb +149 -0
- data/spec/test_code_quality.rb +87 -0
- data/spec/test_component_manager.rb +97 -0
- data/spec/test_constants.rb +8 -0
- data/spec/test_drb.rb +104 -0
- data/spec/test_helper.rb +94 -0
- data/spec/test_hooks.rb +37 -0
- data/spec/test_host_definitions.rb +79 -0
- data/spec/test_initialization.rb +105 -0
- data/spec/test_logging.rb +80 -0
- data/spec/test_relationship_properties.rb +54 -0
- data/spec/voip/asterisk/ami_response_definitions.rb +23 -0
- data/spec/voip/asterisk/config_file_generators/test_agents.rb +253 -0
- data/spec/voip/asterisk/config_file_generators/test_queues.rb +325 -0
- data/spec/voip/asterisk/config_file_generators/test_voicemail.rb +306 -0
- data/spec/voip/asterisk/menu_command/test_calculated_match.rb +111 -0
- data/spec/voip/asterisk/menu_command/test_matchers.rb +98 -0
- data/spec/voip/asterisk/mock_ami_server.rb +176 -0
- data/spec/voip/asterisk/test_agi_server.rb +453 -0
- data/spec/voip/asterisk/test_ami.rb +227 -0
- data/spec/voip/asterisk/test_commands.rb +2006 -0
- data/spec/voip/asterisk/test_config_manager.rb +129 -0
- data/spec/voip/dsl/dispatcher_spec_helper.rb +45 -0
- data/spec/voip/dsl/test_dialing_dsl.rb +268 -0
- data/spec/voip/dsl/test_dispatcher.rb +82 -0
- data/spec/voip/dsl/test_parser.rb +87 -0
- data/spec/voip/freeswitch/test_basic_connection_manager.rb +39 -0
- data/spec/voip/freeswitch/test_inbound_connection_manager.rb +39 -0
- data/spec/voip/freeswitch/test_oes_server.rb +9 -0
- data/spec/voip/test_call_routing.rb +127 -0
- data/spec/voip/test_dialplan_manager.rb +372 -0
- data/spec/voip/test_numerical_string.rb +48 -0
- data/spec/voip/test_phone_number.rb +36 -0
- data/test/test_ahn_generator.rb +59 -0
- data/test/test_component_generator.rb +52 -0
- data/test/test_generator_helper.rb +20 -0
- metadata +254 -0
@@ -0,0 +1,9 @@
|
|
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
|
@@ -0,0 +1,127 @@
|
|
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
|
+
}
|
@@ -0,0 +1,372 @@
|
|
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
|
+
}
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/../test_helper"
|
2
|
+
|
3
|
+
require 'adhearsion/voip/dsl/numerical_string'
|
4
|
+
require 'adhearsion/voip/constants'
|
5
|
+
|
6
|
+
context "A NumericalString" do
|
7
|
+
test "NumericalString should appear to be behave like a Fixnum in a case statement" do
|
8
|
+
assert 123 === numerical_string_for("123")
|
9
|
+
assert 987 === numerical_string_for("0987")
|
10
|
+
end
|
11
|
+
|
12
|
+
test "NumericalString should appear to behave like a String in a case statement" do
|
13
|
+
assert "123" === numerical_string_for("123")
|
14
|
+
assert "0987" === numerical_string_for("0987")
|
15
|
+
end
|
16
|
+
|
17
|
+
test "when compared against a Range that contains the numeric equivalent, the NumericalString is seen as a member" do
|
18
|
+
assert((100..200) === numerical_string_for("150"))
|
19
|
+
assert((100..200) === numerical_string_for("0150"))
|
20
|
+
assert !((100..200) === numerical_string_for("1000000"))
|
21
|
+
end
|
22
|
+
|
23
|
+
test "comparing against a regular expression works" do
|
24
|
+
assert %r|^\d+$| === numerical_string_for("027316287")
|
25
|
+
end
|
26
|
+
|
27
|
+
test "checking if a string representation of a number starts with a leading zero" do
|
28
|
+
with_leading_zeros = %w(01 01234 01.23 01.2)
|
29
|
+
without_leading_zeros = %w(1 1.2 0 0.0)
|
30
|
+
|
31
|
+
with_leading_zeros.each do |number|
|
32
|
+
assert numerical_string.starts_with_leading_zero?(number), number
|
33
|
+
end
|
34
|
+
|
35
|
+
without_leading_zeros.each do |number|
|
36
|
+
assert !numerical_string.starts_with_leading_zero?(number), number
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
def numerical_string
|
42
|
+
Adhearsion::VoIP::DSL::NumericalString
|
43
|
+
end
|
44
|
+
|
45
|
+
def numerical_string_for(string)
|
46
|
+
numerical_string.new(string)
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/../test_helper"
|
2
|
+
require 'adhearsion/voip/constants'
|
3
|
+
require 'adhearsion/voip/dsl/numerical_string'
|
4
|
+
|
5
|
+
|
6
|
+
# Use cases...
|
7
|
+
# case extension
|
8
|
+
# when US_NUMBER
|
9
|
+
# when (100..200)
|
10
|
+
# when _('12Z')
|
11
|
+
# when 123
|
12
|
+
# when "123"
|
13
|
+
# end
|
14
|
+
|
15
|
+
describe "A PhoneNumber" do
|
16
|
+
|
17
|
+
it "should have an ISN pattern-matching method" do
|
18
|
+
!! Adhearsion::VoIP::DSL::PhoneNumber.new("0115544332211").isn?.should == false
|
19
|
+
!! Adhearsion::VoIP::DSL::PhoneNumber.new("1*548").isn?.should == false
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should have a US local number pattern-matching method" do
|
23
|
+
!! Adhearsion::VoIP::DSL::PhoneNumber.new("18887776665555").local_number?.should == false
|
24
|
+
!! Adhearsion::VoIP::DSL::PhoneNumber.new("18887776665555").national_number?.should == false
|
25
|
+
|
26
|
+
!! Adhearsion::VoIP::DSL::PhoneNumber.new("8887776665555").local_number?.should == false
|
27
|
+
!! Adhearsion::VoIP::DSL::PhoneNumber.new("8887776665555").national_number?.should == true
|
28
|
+
|
29
|
+
!! Adhearsion::VoIP::DSL::PhoneNumber.new("4445555").local_number?.should == true
|
30
|
+
!! Adhearsion::VoIP::DSL::PhoneNumber.new("4445555").national_number?.should == false
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should convert from vanity numbers properly" do
|
34
|
+
Adhearsion::VoIP::DSL::PhoneNumber.from_vanity("1-800-FUDGEME").should == "18003834363"
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "test_generator_helper.rb")
|
2
|
+
|
3
|
+
class TestAhnGenerator < Test::Unit::TestCase
|
4
|
+
include RubiGen::GeneratorTestHelper
|
5
|
+
|
6
|
+
def setup
|
7
|
+
bare_setup
|
8
|
+
end
|
9
|
+
|
10
|
+
def teardown
|
11
|
+
bare_teardown
|
12
|
+
end
|
13
|
+
|
14
|
+
# Some generator-related assertions:
|
15
|
+
# assert_generated_file(name, &block) # block passed the file contents
|
16
|
+
# assert_directory_exists(name)
|
17
|
+
# assert_generated_class(name, &block)
|
18
|
+
# assert_generated_module(name, &block)
|
19
|
+
# assert_generated_test_for(name, &block)
|
20
|
+
# The assert_generated_(class|module|test_for) &block is passed the body of the class/module within the file
|
21
|
+
# assert_has_method(body, *methods) # check that the body has a list of methods (methods with parentheses not supported yet)
|
22
|
+
#
|
23
|
+
# Other helper methods are:
|
24
|
+
# app_root_files - put this in teardown to show files generated by the test method (e.g. p app_root_files)
|
25
|
+
# bare_setup - place this in setup method to create the APP_ROOT folder for each test
|
26
|
+
# bare_teardown - place this in teardown method to destroy the TMP_ROOT or APP_ROOT folder after each test
|
27
|
+
|
28
|
+
def test_generator_without_options
|
29
|
+
run_generator('ahn', [APP_ROOT], sources)
|
30
|
+
assert_directory_exists "components/simon_game/lib"
|
31
|
+
assert_directory_exists "components/simon_game/test"
|
32
|
+
assert_directory_exists "config"
|
33
|
+
|
34
|
+
assert_generated_file "components/simon_game/configuration.rb"
|
35
|
+
assert_generated_file "components/simon_game/lib/simon_game.rb"
|
36
|
+
assert_generated_file "components/simon_game/test/test_helper.rb"
|
37
|
+
assert_generated_file "components/simon_game/test/test_simon_game.rb"
|
38
|
+
assert_generated_file "config/startup.rb"
|
39
|
+
assert_generated_file "dialplan.rb"
|
40
|
+
assert_generated_file "README"
|
41
|
+
assert_generated_file "Rakefile"
|
42
|
+
|
43
|
+
assert_generated_class "components/simon_game/lib/simon_game" do |body|
|
44
|
+
assert_has_method body, "initialize"
|
45
|
+
assert_has_method body, "start"
|
46
|
+
assert_has_method body, "random_number"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
def sources
|
52
|
+
[RubiGen::PathSource.new(:test, File.join(File.dirname(__FILE__),"..", generator_path))
|
53
|
+
]
|
54
|
+
end
|
55
|
+
|
56
|
+
def generator_path
|
57
|
+
"app_generators"
|
58
|
+
end
|
59
|
+
end
|