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,129 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/../../test_helper"
|
2
|
+
require 'adhearsion/voip/asterisk/config_manager'
|
3
|
+
|
4
|
+
context "The configuration file parser behavior" do
|
5
|
+
|
6
|
+
include ConfigurationManagerTestHelper
|
7
|
+
|
8
|
+
test "should expose a sections array" do
|
9
|
+
manager = mock_config_manager
|
10
|
+
manager.sections.map(&:first).should.equal(["jicksta", "picard"])
|
11
|
+
end
|
12
|
+
|
13
|
+
test "should ignore comments" do
|
14
|
+
context_names = %w(monkey data)
|
15
|
+
tested_key_name, tested_key_value_before_comment = "bar", "baz"
|
16
|
+
manager = mock_config_manager_for <<-CONFIG
|
17
|
+
[monkey]
|
18
|
+
#{tested_key_name}=#{tested_key_value_before_comment};thiscommentshouldnotbehere
|
19
|
+
asdf=fdsa
|
20
|
+
;[data]
|
21
|
+
;ignored=asdf
|
22
|
+
CONFIG
|
23
|
+
manager.sections.map(&:first).should.equal [context_names.first]
|
24
|
+
manager[context_names.first].size.should.equal 2
|
25
|
+
manager[context_names.first][tested_key_name].should.equal tested_key_value_before_comment
|
26
|
+
end
|
27
|
+
|
28
|
+
test "should match context names with dashes and underscores" do
|
29
|
+
context_names = %w"foo-bar qaz_b-a-z"
|
30
|
+
definition_string = <<-CONFIG
|
31
|
+
[#{context_names.first}]
|
32
|
+
platypus=no
|
33
|
+
zebra=no
|
34
|
+
crappyconfig=yes
|
35
|
+
|
36
|
+
[#{context_names.last}]
|
37
|
+
callerid="Jay Phillips" <133>
|
38
|
+
CONFIG
|
39
|
+
mock_config_manager_for(definition_string).sections.map(&:first).should.equal context_names
|
40
|
+
end
|
41
|
+
|
42
|
+
test "should strip whitespace around keys and values" do
|
43
|
+
section_name = "hey-there-hot-momma"
|
44
|
+
tested_key_name, tested_key_value_before_comment = "bar", "i heart white space. SIKE!"
|
45
|
+
config_manager = mock_config_manager_for <<-CONFIG
|
46
|
+
\t[#{section_name}]
|
47
|
+
|
48
|
+
thereis = a lot of whitespace after these
|
49
|
+
|
50
|
+
#{tested_key_name} = \t\t\t #{tested_key_value_before_comment}
|
51
|
+
|
52
|
+
CONFIG
|
53
|
+
config_manager[section_name][tested_key_name].should.equal tested_key_value_before_comment
|
54
|
+
end
|
55
|
+
|
56
|
+
test "should return a Hash of properties when searching for an existing section" do
|
57
|
+
result = mock_config_manager["jicksta"]
|
58
|
+
result.should.be.kind_of Hash
|
59
|
+
result.size.should.equal 3
|
60
|
+
end
|
61
|
+
|
62
|
+
test "should return nil when searching for a non-existant section" do
|
63
|
+
mock_config_manager["i-so-dont-exist-dude"].should.be.nil
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
context "The configuration file writer" do
|
69
|
+
|
70
|
+
include ConfigurationManagerTestHelper
|
71
|
+
|
72
|
+
attr_reader :config_manager
|
73
|
+
|
74
|
+
setup do
|
75
|
+
@config_manager = mock_config_manager
|
76
|
+
end
|
77
|
+
|
78
|
+
test "should remove an old section when replacing it" do
|
79
|
+
config_manager.delete_section "picard"
|
80
|
+
config_manager.sections.map(&:first).should.equal ["jicksta"]
|
81
|
+
end
|
82
|
+
|
83
|
+
test "should add a new section to the end" do
|
84
|
+
section_name = "wittynamehere"
|
85
|
+
config_manager.new_section(section_name, :type => "friend",
|
86
|
+
:witty => "yes",
|
87
|
+
:shaken => "yes",
|
88
|
+
:stirred => "no")
|
89
|
+
new_section = config_manager.sections.last
|
90
|
+
new_section.first.should.equal section_name
|
91
|
+
new_section.last.size.should.equal 4
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context "The configuration file generator" do
|
96
|
+
end
|
97
|
+
|
98
|
+
BEGIN {
|
99
|
+
module ConfigurationManagerTestHelper
|
100
|
+
|
101
|
+
def mock_config_manager
|
102
|
+
mock_config_manager_for sample_standard_config
|
103
|
+
end
|
104
|
+
|
105
|
+
def mock_config_manager_for(config_string)
|
106
|
+
returning new_config_manager_with("bogus filename") do |manager|
|
107
|
+
flexmock(manager).should_receive(:execute).and_return(config_string)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def new_config_manager_with(filename)
|
112
|
+
Adhearsion::VoIP::Asterisk::ConfigurationManager.new(filename)
|
113
|
+
end
|
114
|
+
|
115
|
+
def sample_standard_config
|
116
|
+
<<-CONFIG
|
117
|
+
[jicksta]
|
118
|
+
foo=bar
|
119
|
+
qaz=qwerty
|
120
|
+
baz=zxcvb
|
121
|
+
[picard]
|
122
|
+
type=friend
|
123
|
+
insecure=very
|
124
|
+
host=dynamic
|
125
|
+
secret=blargh
|
126
|
+
CONFIG
|
127
|
+
end
|
128
|
+
end
|
129
|
+
}
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../test_helper'
|
2
|
+
|
3
|
+
require 'adhearsion/voip/dsl/dialplan/dispatcher'
|
4
|
+
|
5
|
+
module StandardDispatcherBehavior
|
6
|
+
def xtest_standard_dispatcher_behavior
|
7
|
+
#"This test looks bogus. Not finished? Let's not check in failing specs ever if we can help it."
|
8
|
+
returned_event_command = Adhearsion::VoIP::DSL::Dialplan::EventCommand.new "ilikesexypants"
|
9
|
+
linking_event_command = Adhearsion::VoIP::DSL::Dialplan::EventCommand.new "ihavesexypants" do
|
10
|
+
returned_event_command
|
11
|
+
end
|
12
|
+
|
13
|
+
dispatcher = @dispatcher_class.new MyFactory
|
14
|
+
dispatcher.should_receive(:dispatch!).with(linking_event_command, returned_event_command).and_return(linking_event_command, returned_event_command)
|
15
|
+
# returned_event_command.should_receive(:command_block).and_return nil
|
16
|
+
dispatcher.dispatch! linking_event_command
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class NilDispatcher < Adhearsion::VoIP::DSL::Dialplan::CommandDispatcher
|
21
|
+
def dispatch!(string)
|
22
|
+
# Would send it off to the PBX here (or prepend something to the String)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class EvalDispatcher < Adhearsion::VoIP::DSL::Dialplan::CommandDispatcher
|
27
|
+
def dispatch!(event)
|
28
|
+
eval event.app.to_s
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class MyFactory
|
33
|
+
|
34
|
+
def initialize(context)
|
35
|
+
@context = context
|
36
|
+
end
|
37
|
+
|
38
|
+
def sequence
|
39
|
+
all = []
|
40
|
+
EventCommand.new("2", :response => Numeric) do |response|
|
41
|
+
all << response
|
42
|
+
all.size > 3 ? all : nil
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,268 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../test_helper'
|
2
|
+
require 'adhearsion/voip/dsl/dialing_dsl'
|
3
|
+
|
4
|
+
# Keep the monkey patches in a module and load that into Regexp
|
5
|
+
# eigenclasses during a before(:all) block?
|
6
|
+
|
7
|
+
describe "RouteRule Regexp assembling" do
|
8
|
+
|
9
|
+
test "should compile two Regexps" do
|
10
|
+
first, last = /jay/, /phillips/
|
11
|
+
r = first | last
|
12
|
+
r.patterns.should == [first, last]
|
13
|
+
end
|
14
|
+
|
15
|
+
test "should compile three or more Regexps" do
|
16
|
+
first, second, third = /lorem/, /ipsum/, /dolar/
|
17
|
+
r = first | second | third
|
18
|
+
r.patterns.should == [first, second, third]
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "RouteRule assembling with one provider definition" do
|
24
|
+
|
25
|
+
before :each do
|
26
|
+
@provider = Adhearsion::VoIP::DSL::DialingDSL::ProviderDefinition.new(:icanhascheezburger?)
|
27
|
+
end
|
28
|
+
|
29
|
+
test "should store one pattern properly" do
|
30
|
+
pattern = /lorem/
|
31
|
+
route = pattern >> @provider
|
32
|
+
route.patterns.should == [pattern]
|
33
|
+
end
|
34
|
+
|
35
|
+
test "should store three patterns properly" do
|
36
|
+
first, second, third = /lorem/, /ipsum/, /dolar/
|
37
|
+
route = first | second | third >> @provider
|
38
|
+
route.patterns.should == [first, second, third]
|
39
|
+
route.providers.should == [@provider]
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "RouteRule assembling with multiple patterns and multiple provider definitions" do
|
45
|
+
|
46
|
+
before:each do
|
47
|
+
1.upto 3 do |i|
|
48
|
+
instance_variable_set "@prov_#{i}",
|
49
|
+
Adhearsion::VoIP::DSL::DialingDSL::ProviderDefinition.new("prov_#{i}")
|
50
|
+
instance_variable_set "@pattern_#{i}", /^#{i * 100}$/
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
test "should store the patterns properly" do
|
55
|
+
route_1 = @pattern_1 | @pattern_2 | @pattern_3 >> @prov_1 >> @prov_2 >> @prov_3
|
56
|
+
route_1.patterns.should == [@pattern_1, @pattern_2, @pattern_3]
|
57
|
+
|
58
|
+
route_2 = @pattern_2 | @pattern_3 | @pattern_1 >> @prov_3 >> @prov_2 >> @prov_1
|
59
|
+
route_2.patterns.should == [@pattern_2, @pattern_3, @pattern_1]
|
60
|
+
end
|
61
|
+
|
62
|
+
test "should store the providers properly" do
|
63
|
+
route_1 = @pattern_1 | @pattern_2 | @pattern_3 >> @prov_1 >> @prov_2 >> @prov_3
|
64
|
+
route_1.providers.should == [@prov_1, @prov_2, @prov_3]
|
65
|
+
|
66
|
+
route_2 = @pattern_2 | @pattern_3 | @pattern_1 >> @prov_3 >> @prov_2 >> @prov_1
|
67
|
+
route_2.patterns.should == [@pattern_2, @pattern_3, @pattern_1]
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe "The DialingDSL class internals" do
|
72
|
+
|
73
|
+
test "should allow Asterisk-like patterns" do
|
74
|
+
Adhearsion::VoIP::DSL::DialingDSL.class_eval do
|
75
|
+
_('23XX')
|
76
|
+
end.should.be.instance_of Regexp
|
77
|
+
end
|
78
|
+
|
79
|
+
test "should define all of the VoIP constants" do
|
80
|
+
lambda do
|
81
|
+
Adhearsion::VoIP::Constants.constants.each do |constant|
|
82
|
+
eval "Adhearsion::VoIP::DSL::DialingDSL::#{constant}"
|
83
|
+
end
|
84
|
+
end.should.not.raise NameError
|
85
|
+
end
|
86
|
+
|
87
|
+
# test "should define a DUNDI constant"
|
88
|
+
|
89
|
+
test "should synchronize access to the trunking information for Thread safety"
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
describe "The provider DSL's 'provider' macro" do
|
94
|
+
|
95
|
+
test "should make the providers available in the order they were received" do
|
96
|
+
provider_holder = Class.new Adhearsion::VoIP::DSL::DialingDSL
|
97
|
+
provider_holder.class_eval do
|
98
|
+
provider(:tweedledee) {}
|
99
|
+
provider(:tweedledum) {}
|
100
|
+
end
|
101
|
+
provider_holder.providers.map { |x| x.name }.should == [:tweedledee, :tweedledum]
|
102
|
+
end
|
103
|
+
test "should define a singleton method for the provider name given" do
|
104
|
+
Class.new(Adhearsion::VoIP::DSL::DialingDSL).class_eval do
|
105
|
+
class_variable_get(:@@providers).size.should == 0
|
106
|
+
|
107
|
+
provider(:icanhascheezburger?) {}
|
108
|
+
|
109
|
+
should.respond_to(:icanhascheezburger?)
|
110
|
+
class_variable_get(:@@providers).size.should == 1
|
111
|
+
end
|
112
|
+
end
|
113
|
+
test "should not define a class-wide method for the provider name given" do
|
114
|
+
Class.new(Adhearsion::VoIP::DSL::DialingDSL).class_eval do
|
115
|
+
provider(:icanhascheezburger?) {}
|
116
|
+
end
|
117
|
+
Adhearsion::VoIP::DSL::DialingDSL.class_eval do
|
118
|
+
class_variable_defined?(:@@providers).should == false
|
119
|
+
should.not.respond_to(:icanhascheezburger?)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
test "should yield a ProviderDefinition object" do
|
123
|
+
possible_provider_definition = nil
|
124
|
+
Class.new(Adhearsion::VoIP::DSL::DialingDSL).class_eval do
|
125
|
+
provider(:blah) { |pd| possible_provider_definition = pd }
|
126
|
+
end
|
127
|
+
possible_provider_definition.should.be.a.kind_of(Adhearsion::VoIP::DSL::DialingDSL::ProviderDefinition)
|
128
|
+
end
|
129
|
+
test "should raise an error when no block is given" do
|
130
|
+
the_following_code do
|
131
|
+
Class.new(Adhearsion::VoIP::DSL::DialingDSL).class_eval do
|
132
|
+
provider :explode
|
133
|
+
end
|
134
|
+
end.should.raise ArgumentError
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
describe "The provider DSL's monkey patches to Regexp" do
|
139
|
+
test "should return a RouteRule when using Regexp#| with another Regexp" do
|
140
|
+
(// | //).should.be.a.kind_of(Adhearsion::VoIP::DSL::DialingDSL::RouteRule)
|
141
|
+
end
|
142
|
+
test "should return a RouteRule when chaining three Regexp's with the | operator" do
|
143
|
+
(// | // | //).should.be.a.kind_of(Adhearsion::VoIP::DSL::DialingDSL::RouteRule)
|
144
|
+
end
|
145
|
+
test "should return a RouteRule when Regexp#| is given a RouteRule" do
|
146
|
+
route_rule = Adhearsion::VoIP::DSL::DialingDSL::RouteRule.new :patterns => //
|
147
|
+
(// | route_rule).should.be.a.kind_of(Adhearsion::VoIP::DSL::DialingDSL::RouteRule)
|
148
|
+
end
|
149
|
+
test "should return a RouteRule when Regexp#>> is given a ProviderDefinition" do
|
150
|
+
(/1/ >> Adhearsion::VoIP::DSL::DialingDSL::ProviderDefinition.new(:foo)).
|
151
|
+
should.be.a.kind_of(Adhearsion::VoIP::DSL::DialingDSL::RouteRule)
|
152
|
+
end
|
153
|
+
test "should return a RouteRule when Regexp#>>() receives a ProviderDefinition" do
|
154
|
+
definition = Adhearsion::VoIP::DSL::DialingDSL::ProviderDefinition.new(:london)
|
155
|
+
(/foo/ >> definition).should.be.a.kind_of(Adhearsion::VoIP::DSL::DialingDSL::RouteRule)
|
156
|
+
end
|
157
|
+
test "should raise an exception when Regexp#| receives something other than a RouteRule" do
|
158
|
+
bad_args = [ 0..100, 20, 45.55, {}, [] ]
|
159
|
+
bad_args.each do |arg|
|
160
|
+
the_following_code { /foo/ | arg }.should.raise ArgumentError
|
161
|
+
end
|
162
|
+
end
|
163
|
+
test "should raise an exception when Regexp#>>() receives anything other than a ProviderDefintion or RouteRule" do
|
164
|
+
bad_args = [ 0..100, 20, 45.55, {}, [] ]
|
165
|
+
bad_args.each do |arg|
|
166
|
+
the_following_code { /foo/ >> arg }.should.raise ArgumentError
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
describe "A RouteRule" do
|
172
|
+
test "should expose chained ProviderDefinitions properly" do
|
173
|
+
one, two, three = definitions = %w"foo bar qaz".map do |name|
|
174
|
+
Adhearsion::VoIP::DSL::DialingDSL::ProviderDefinition.new name
|
175
|
+
end
|
176
|
+
route = /^911$/ >> one >> two >> three
|
177
|
+
route.should.be.kind_of(Adhearsion::VoIP::DSL::DialingDSL::RouteRule)
|
178
|
+
route.providers.should == definitions
|
179
|
+
end
|
180
|
+
test "should define attr_readers for providers and patterns" do
|
181
|
+
route = Adhearsion::VoIP::DSL::DialingDSL::RouteRule.new
|
182
|
+
route.should.respond_to(:patterns)
|
183
|
+
route.should.respond_to(:providers)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
describe "The provider order modifiers" do
|
188
|
+
disabled_test "should support randomizing trunks" do
|
189
|
+
dsl = Class.new Adhearsion::VoIP::DSL::DialingDSL
|
190
|
+
dsl.class_eval do
|
191
|
+
provider(:l33thost) {}
|
192
|
+
provider(:h4xxhost) {}
|
193
|
+
route /\d+\*548/ >> random(l33thost, h4xxhost)
|
194
|
+
end
|
195
|
+
dsl.routes.first.provider_definitions.first.should.be.a.kind_of(
|
196
|
+
Adhearsion::VoIP::DSL::DialingDSL::RandomRouteRule
|
197
|
+
)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
describe "The provider DSL's 'route' builder" do
|
202
|
+
test "should register routes in the order received" do
|
203
|
+
dsl = Class.new Adhearsion::VoIP::DSL::DialingDSL
|
204
|
+
dsl.class_eval do
|
205
|
+
provider(:kewlphone) {}
|
206
|
+
[/1?4445556666/, /123/, /\d+\*548/].each do |r|
|
207
|
+
route r >> kewlphone
|
208
|
+
end
|
209
|
+
end
|
210
|
+
dsl.routes.map { |x| x.patterns }.flatten.should == [/1?4445556666/, /123/, /\d+\*548/]
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
describe "A ProviderDefinition" do
|
215
|
+
test "should store any arbitrary property" do
|
216
|
+
definition = Adhearsion::VoIP::DSL::DialingDSL::ProviderDefinition.new :foo
|
217
|
+
definition.qaz = :something
|
218
|
+
definition.qaz.should == :something
|
219
|
+
end
|
220
|
+
test "should define a >>() method" do
|
221
|
+
Adhearsion::VoIP::DSL::DialingDSL::ProviderDefinition.new(:arghh).should.respond_to(:>>)
|
222
|
+
end
|
223
|
+
|
224
|
+
test "should format numbers properly" do
|
225
|
+
definition = Adhearsion::VoIP::DSL::DialingDSL::ProviderDefinition.new(:arghh)
|
226
|
+
definition.protocol = "SIP"
|
227
|
+
definition.format_number_for_platform("14445556666", :asterisk).should == "SIP/arghh/14445556666"
|
228
|
+
definition.protocol = "SCCP"
|
229
|
+
definition.format_number_for_platform("16663331111", :asterisk).should == "SCCP/arghh/16663331111"
|
230
|
+
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
describe "Routing with the interpreted route definitions" do
|
235
|
+
test "should use the first matching regular expression" do
|
236
|
+
dsl = Class.new Adhearsion::VoIP::DSL::DialingDSL
|
237
|
+
dsl.class_eval do
|
238
|
+
provider(:bad) {}
|
239
|
+
provider(:good) {}
|
240
|
+
route /^111$/ | /^222$/ | /^333$/ >> good >> bad
|
241
|
+
end
|
242
|
+
|
243
|
+
found = dsl.calculate_routes_for(333)
|
244
|
+
|
245
|
+
assert_equal 1, found.size
|
246
|
+
found.first.size.should.equal 2
|
247
|
+
end
|
248
|
+
|
249
|
+
end
|
250
|
+
|
251
|
+
# @example = Class.new Adhearsion::VoIP::DSL::DialingDSL
|
252
|
+
# @example.class_eval do
|
253
|
+
#
|
254
|
+
# provider:kewlphone do |trunk|
|
255
|
+
# trunk.protocol :sip
|
256
|
+
# trunk.host "voip.nufone.com"
|
257
|
+
# trunk.username "phonedude"
|
258
|
+
# trunk.password "secret"
|
259
|
+
# trunk.enters :internal
|
260
|
+
# end
|
261
|
+
#
|
262
|
+
# route US_NUMBER | US_LOCAL_NUMBER >> voip_ms >> nufone
|
263
|
+
#
|
264
|
+
# route INTL_NUMBER >> random(voip_ms, nufone)
|
265
|
+
#
|
266
|
+
# # route _('NXX') >> DUNDI
|
267
|
+
#
|
268
|
+
# end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/dispatcher_spec_helper'
|
2
|
+
require 'adhearsion/voip/dsl/dialplan/dispatcher'
|
3
|
+
|
4
|
+
|
5
|
+
describe "A EventCommand" do
|
6
|
+
|
7
|
+
test "should allow a block that's set to response_block()" do
|
8
|
+
block = lambda {}
|
9
|
+
cmd = Adhearsion::VoIP::DSL::Dialplan::EventCommand.new "foo", &block
|
10
|
+
cmd.response_block.should.equal(block)
|
11
|
+
end
|
12
|
+
|
13
|
+
test "should return specified return type with returns()" do
|
14
|
+
return_type = Numeric
|
15
|
+
cmd = Adhearsion::VoIP::DSL::Dialplan::EventCommand.new "foo", :returns => return_type
|
16
|
+
cmd.returns.should.equal(return_type)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "The abstract CommandDispatcher" do
|
22
|
+
|
23
|
+
test "should make an attribute reader for context()" do
|
24
|
+
context = "foo"
|
25
|
+
d = Adhearsion::VoIP::DSL::Dialplan::CommandDispatcher.new String, context
|
26
|
+
d.context.should.equal(context)
|
27
|
+
end
|
28
|
+
|
29
|
+
test "should instantiate a new instance of the specified factory" do
|
30
|
+
d = Adhearsion::VoIP::DSL::Dialplan::CommandDispatcher.new Hash
|
31
|
+
d.factory.should.be.kind_of(Hash)
|
32
|
+
end
|
33
|
+
|
34
|
+
test "should pass the context to the factory when instantiating it" do
|
35
|
+
context = "shazbot"
|
36
|
+
klass = flexmock "a class that has one argument in its constructor"
|
37
|
+
klass.should_receive(:new).with(context)
|
38
|
+
d = Adhearsion::VoIP::DSL::Dialplan::CommandDispatcher.new klass, context
|
39
|
+
end
|
40
|
+
|
41
|
+
test "should not allow calling dispatch!() directly" do
|
42
|
+
dispatcher = Adhearsion::VoIP::DSL::Dialplan::CommandDispatcher.new MyFactory
|
43
|
+
lambda do
|
44
|
+
dispatcher.dispatch! nil
|
45
|
+
end.should.raise(NotImplementedError)
|
46
|
+
end
|
47
|
+
|
48
|
+
test "should pass a method and any args onto its CommandFactory" do
|
49
|
+
|
50
|
+
weird_args = [1, 2, ["foo", nil], Object.new, 12.3..13.4]
|
51
|
+
|
52
|
+
bogus_command = Adhearsion::VoIP::DSL::Dialplan::EventCommand.new "123"
|
53
|
+
|
54
|
+
dispatcher = NilDispatcher.new MyFactory
|
55
|
+
flexmock(dispatcher.factory).should_receive(:monkey).with(*weird_args).and_return bogus_command
|
56
|
+
dispatcher.monkey(*weird_args)
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
test "should continue executing response_blocks until nil is returned" do
|
61
|
+
actual_executions, target_executions = 0, 5
|
62
|
+
response = Adhearsion::VoIP::DSL::Dialplan::EventCommand.new "1" do |response|
|
63
|
+
if response > target_executions
|
64
|
+
nil
|
65
|
+
else
|
66
|
+
actual_executions += 1
|
67
|
+
Adhearsion::VoIP::DSL::Dialplan::EventCommand.new(response + 1)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
mock_factory_class = Class.new do
|
71
|
+
def initialize(*args)
|
72
|
+
end
|
73
|
+
def testplz
|
74
|
+
response
|
75
|
+
end
|
76
|
+
end
|
77
|
+
dispatcher = EvalDispatcher.new(mock_factory_class)
|
78
|
+
flexmock(dispatcher.factory).should_receive(:testplz).and_return(response)
|
79
|
+
dispatcher.testplz
|
80
|
+
actual_executions.should.equal(target_executions)
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,87 @@
|
|
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
|
@@ -0,0 +1,39 @@
|
|
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
|
@@ -0,0 +1,39 @@
|
|
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
|