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.
Files changed (150) hide show
  1. data/CHANGELOG +3 -0
  2. data/LICENSE +456 -0
  3. data/Manifest.txt +149 -0
  4. data/README.txt +6 -0
  5. data/Rakefile +48 -0
  6. data/ahn_generators/component/USAGE +5 -0
  7. data/ahn_generators/component/component_generator.rb +57 -0
  8. data/ahn_generators/component/templates/configuration.rb +0 -0
  9. data/ahn_generators/component/templates/lib/lib.rb.erb +3 -0
  10. data/ahn_generators/component/templates/test/test.rb.erb +12 -0
  11. data/ahn_generators/component/templates/test/test_helper.rb +14 -0
  12. data/app_generators/ahn/USAGE +5 -0
  13. data/app_generators/ahn/ahn_generator.rb +76 -0
  14. data/app_generators/ahn/templates/.ahnrc +12 -0
  15. data/app_generators/ahn/templates/README +8 -0
  16. data/app_generators/ahn/templates/Rakefile +3 -0
  17. data/app_generators/ahn/templates/components/simon_game/configuration.rb +0 -0
  18. data/app_generators/ahn/templates/components/simon_game/lib/simon_game.rb +61 -0
  19. data/app_generators/ahn/templates/components/simon_game/test/test_helper.rb +14 -0
  20. data/app_generators/ahn/templates/components/simon_game/test/test_simon_game.rb +31 -0
  21. data/app_generators/ahn/templates/config/startup.rb +53 -0
  22. data/app_generators/ahn/templates/dialplan.rb +4 -0
  23. data/bin/ahn +28 -0
  24. data/bin/ahnctl +68 -0
  25. data/bin/jahn +32 -0
  26. data/lib/adhearsion/blank_slate.rb +5 -0
  27. data/lib/adhearsion/cli.rb +106 -0
  28. data/lib/adhearsion/component_manager.rb +277 -0
  29. data/lib/adhearsion/core_extensions/all.rb +9 -0
  30. data/lib/adhearsion/core_extensions/array.rb +0 -0
  31. data/lib/adhearsion/core_extensions/custom_daemonizer.rb +45 -0
  32. data/lib/adhearsion/core_extensions/global.rb +1 -0
  33. data/lib/adhearsion/core_extensions/guid.rb +5 -0
  34. data/lib/adhearsion/core_extensions/hash.rb +0 -0
  35. data/lib/adhearsion/core_extensions/metaprogramming.rb +17 -0
  36. data/lib/adhearsion/core_extensions/numeric.rb +4 -0
  37. data/lib/adhearsion/core_extensions/proc.rb +0 -0
  38. data/lib/adhearsion/core_extensions/pseudo_uuid.rb +11 -0
  39. data/lib/adhearsion/core_extensions/publishable.rb +73 -0
  40. data/lib/adhearsion/core_extensions/relationship_properties.rb +40 -0
  41. data/lib/adhearsion/core_extensions/string.rb +26 -0
  42. data/lib/adhearsion/core_extensions/thread.rb +13 -0
  43. data/lib/adhearsion/core_extensions/thread_safety.rb +7 -0
  44. data/lib/adhearsion/core_extensions/time.rb +0 -0
  45. data/lib/adhearsion/distributed/gateways/dbus_gateway.rb +0 -0
  46. data/lib/adhearsion/distributed/gateways/osa_gateway.rb +0 -0
  47. data/lib/adhearsion/distributed/gateways/rest_gateway.rb +9 -0
  48. data/lib/adhearsion/distributed/gateways/soap_gateway.rb +9 -0
  49. data/lib/adhearsion/distributed/gateways/xmlrpc_gateway.rb +9 -0
  50. data/lib/adhearsion/distributed/peer_finder.rb +0 -0
  51. data/lib/adhearsion/distributed/remote_cli.rb +0 -0
  52. data/lib/adhearsion/hooks.rb +57 -0
  53. data/lib/adhearsion/host_definitions.rb +63 -0
  54. data/lib/adhearsion/initializer/asterisk.rb +59 -0
  55. data/lib/adhearsion/initializer/configuration.rb +202 -0
  56. data/lib/adhearsion/initializer/database.rb +92 -0
  57. data/lib/adhearsion/initializer/drb.rb +25 -0
  58. data/lib/adhearsion/initializer/freeswitch.rb +22 -0
  59. data/lib/adhearsion/initializer/paths.rb +55 -0
  60. data/lib/adhearsion/initializer/rails.rb +40 -0
  61. data/lib/adhearsion/initializer.rb +217 -0
  62. data/lib/adhearsion/logging.rb +92 -0
  63. data/lib/adhearsion/services/scheduler.rb +5 -0
  64. data/lib/adhearsion/tasks/database.rb +5 -0
  65. data/lib/adhearsion/tasks/generating.rb +20 -0
  66. data/lib/adhearsion/tasks/lint.rb +4 -0
  67. data/lib/adhearsion/tasks/testing.rb +37 -0
  68. data/lib/adhearsion/tasks.rb +15 -0
  69. data/lib/adhearsion/version.rb +9 -0
  70. data/lib/adhearsion/voip/asterisk/agi_server.rb +78 -0
  71. data/lib/adhearsion/voip/asterisk/ami/actions.rb +238 -0
  72. data/lib/adhearsion/voip/asterisk/ami/machine.rb +871 -0
  73. data/lib/adhearsion/voip/asterisk/ami/machine.rl +109 -0
  74. data/lib/adhearsion/voip/asterisk/ami/parser.rb +262 -0
  75. data/lib/adhearsion/voip/asterisk/ami.rb +147 -0
  76. data/lib/adhearsion/voip/asterisk/commands.rb +1186 -0
  77. data/lib/adhearsion/voip/asterisk/config_generators/agents.conf.rb +140 -0
  78. data/lib/adhearsion/voip/asterisk/config_generators/config_generator.rb +101 -0
  79. data/lib/adhearsion/voip/asterisk/config_generators/queues.conf.rb +250 -0
  80. data/lib/adhearsion/voip/asterisk/config_generators/voicemail.conf.rb +240 -0
  81. data/lib/adhearsion/voip/asterisk/config_manager.rb +71 -0
  82. data/lib/adhearsion/voip/asterisk/special_dial_plan_managers.rb +80 -0
  83. data/lib/adhearsion/voip/asterisk.rb +4 -0
  84. data/lib/adhearsion/voip/call.rb +402 -0
  85. data/lib/adhearsion/voip/call_routing.rb +64 -0
  86. data/lib/adhearsion/voip/commands.rb +9 -0
  87. data/lib/adhearsion/voip/constants.rb +39 -0
  88. data/lib/adhearsion/voip/conveniences.rb +18 -0
  89. data/lib/adhearsion/voip/dial_plan.rb +205 -0
  90. data/lib/adhearsion/voip/dsl/dialing_dsl/dialing_dsl_monkey_patches.rb +37 -0
  91. data/lib/adhearsion/voip/dsl/dialing_dsl.rb +151 -0
  92. data/lib/adhearsion/voip/dsl/dialplan/control_passing_exception.rb +27 -0
  93. data/lib/adhearsion/voip/dsl/dialplan/dispatcher.rb +124 -0
  94. data/lib/adhearsion/voip/dsl/dialplan/parser.rb +75 -0
  95. data/lib/adhearsion/voip/dsl/dialplan/thread_mixin.rb +16 -0
  96. data/lib/adhearsion/voip/dsl/numerical_string.rb +117 -0
  97. data/lib/adhearsion/voip/freeswitch/basic_connection_manager.rb +48 -0
  98. data/lib/adhearsion/voip/freeswitch/event_handler.rb +58 -0
  99. data/lib/adhearsion/voip/freeswitch/freeswitch_dialplan_command_factory.rb +129 -0
  100. data/lib/adhearsion/voip/freeswitch/inbound_connection_manager.rb +38 -0
  101. data/lib/adhearsion/voip/freeswitch/oes_server.rb +195 -0
  102. data/lib/adhearsion/voip/menu_state_machine/calculated_match.rb +80 -0
  103. data/lib/adhearsion/voip/menu_state_machine/matchers.rb +123 -0
  104. data/lib/adhearsion/voip/menu_state_machine/menu_builder.rb +58 -0
  105. data/lib/adhearsion/voip/menu_state_machine/menu_class.rb +149 -0
  106. data/lib/adhearsion.rb +31 -0
  107. data/script/destroy +14 -0
  108. data/script/generate +14 -0
  109. data/spec/fixtures/dialplan.rb +3 -0
  110. data/spec/initializer/test_configuration.rb +267 -0
  111. data/spec/initializer/test_loading.rb +162 -0
  112. data/spec/initializer/test_paths.rb +43 -0
  113. data/spec/silence.rb +10 -0
  114. data/spec/test_ahn_command.rb +149 -0
  115. data/spec/test_code_quality.rb +87 -0
  116. data/spec/test_component_manager.rb +97 -0
  117. data/spec/test_constants.rb +8 -0
  118. data/spec/test_drb.rb +104 -0
  119. data/spec/test_helper.rb +94 -0
  120. data/spec/test_hooks.rb +37 -0
  121. data/spec/test_host_definitions.rb +79 -0
  122. data/spec/test_initialization.rb +105 -0
  123. data/spec/test_logging.rb +80 -0
  124. data/spec/test_relationship_properties.rb +54 -0
  125. data/spec/voip/asterisk/ami_response_definitions.rb +23 -0
  126. data/spec/voip/asterisk/config_file_generators/test_agents.rb +253 -0
  127. data/spec/voip/asterisk/config_file_generators/test_queues.rb +325 -0
  128. data/spec/voip/asterisk/config_file_generators/test_voicemail.rb +306 -0
  129. data/spec/voip/asterisk/menu_command/test_calculated_match.rb +111 -0
  130. data/spec/voip/asterisk/menu_command/test_matchers.rb +98 -0
  131. data/spec/voip/asterisk/mock_ami_server.rb +176 -0
  132. data/spec/voip/asterisk/test_agi_server.rb +453 -0
  133. data/spec/voip/asterisk/test_ami.rb +227 -0
  134. data/spec/voip/asterisk/test_commands.rb +2006 -0
  135. data/spec/voip/asterisk/test_config_manager.rb +129 -0
  136. data/spec/voip/dsl/dispatcher_spec_helper.rb +45 -0
  137. data/spec/voip/dsl/test_dialing_dsl.rb +268 -0
  138. data/spec/voip/dsl/test_dispatcher.rb +82 -0
  139. data/spec/voip/dsl/test_parser.rb +87 -0
  140. data/spec/voip/freeswitch/test_basic_connection_manager.rb +39 -0
  141. data/spec/voip/freeswitch/test_inbound_connection_manager.rb +39 -0
  142. data/spec/voip/freeswitch/test_oes_server.rb +9 -0
  143. data/spec/voip/test_call_routing.rb +127 -0
  144. data/spec/voip/test_dialplan_manager.rb +372 -0
  145. data/spec/voip/test_numerical_string.rb +48 -0
  146. data/spec/voip/test_phone_number.rb +36 -0
  147. data/test/test_ahn_generator.rb +59 -0
  148. data/test/test_component_generator.rb +52 -0
  149. data/test/test_generator_helper.rb +20 -0
  150. 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