adhearsion 1.0.1 → 1.0.2

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 (64) hide show
  1. data/.gitignore +10 -0
  2. data/CHANGELOG +8 -0
  3. data/README.markdown +33 -0
  4. data/Rakefile +28 -68
  5. data/adhearsion.gemspec +19 -133
  6. data/app_generators/ahn/templates/Gemfile +0 -4
  7. data/app_generators/ahn/templates/components/disabled/restful_rpc/spec/restful_rpc_spec.rb +4 -16
  8. data/lib/adhearsion/cli.rb +17 -0
  9. data/lib/adhearsion/component_manager/component_tester.rb +1 -3
  10. data/lib/adhearsion/component_manager/spec_framework.rb +4 -10
  11. data/lib/adhearsion/foundation/object.rb +10 -0
  12. data/lib/adhearsion/version.rb +1 -1
  13. data/spec/ahn_command_spec.rb +284 -0
  14. data/spec/component_manager_spec.rb +292 -0
  15. data/spec/constants_spec.rb +8 -0
  16. data/spec/drb_spec.rb +65 -0
  17. data/spec/fixtures/dialplan.rb +3 -0
  18. data/spec/foundation/event_socket_spec.rb +168 -0
  19. data/spec/host_definitions_spec.rb +79 -0
  20. data/spec/initialization_spec.rb +163 -0
  21. data/spec/initializer/configuration_spec.rb +270 -0
  22. data/spec/initializer/loading_spec.rb +149 -0
  23. data/spec/initializer/paths_spec.rb +74 -0
  24. data/spec/logging_spec.rb +86 -0
  25. data/spec/relationship_properties_spec.rb +54 -0
  26. data/spec/silence.rb +10 -0
  27. data/spec/spec_helper.rb +101 -0
  28. data/spec/voip/asterisk/agi_server_spec.rb +473 -0
  29. data/spec/voip/asterisk/ami/ami_spec.rb +549 -0
  30. data/spec/voip/asterisk/ami/lexer/ami_fixtures.yml +30 -0
  31. data/spec/voip/asterisk/ami/lexer/lexer_story +291 -0
  32. data/spec/voip/asterisk/ami/lexer/lexer_story.rb +241 -0
  33. data/spec/voip/asterisk/ami/lexer/story_helper.rb +124 -0
  34. data/spec/voip/asterisk/ami/old_tests.rb +204 -0
  35. data/spec/voip/asterisk/ami/super_manager/super_manager_story +25 -0
  36. data/spec/voip/asterisk/ami/super_manager/super_manager_story.rb +15 -0
  37. data/spec/voip/asterisk/ami/super_manager/super_manager_story_helper.rb +5 -0
  38. data/spec/voip/asterisk/commands_spec.rb +2179 -0
  39. data/spec/voip/asterisk/config_file_generators/agents_spec.rb +251 -0
  40. data/spec/voip/asterisk/config_file_generators/queues_spec.rb +323 -0
  41. data/spec/voip/asterisk/config_file_generators/voicemail_spec.rb +306 -0
  42. data/spec/voip/asterisk/config_manager_spec.rb +127 -0
  43. data/spec/voip/asterisk/menu_command/calculated_match_spec.rb +109 -0
  44. data/spec/voip/asterisk/menu_command/matchers_spec.rb +97 -0
  45. data/spec/voip/call_routing_spec.rb +125 -0
  46. data/spec/voip/dialplan_manager_spec.rb +468 -0
  47. data/spec/voip/dsl/dialing_dsl_spec.rb +270 -0
  48. data/spec/voip/dsl/dispatcher_spec.rb +82 -0
  49. data/spec/voip/dsl/dispatcher_spec_helper.rb +45 -0
  50. data/spec/voip/dsl/parser_spec.rb +69 -0
  51. data/spec/voip/freeswitch/basic_connection_manager_spec.rb +39 -0
  52. data/spec/voip/freeswitch/inbound_connection_manager_spec.rb +39 -0
  53. data/spec/voip/freeswitch/oes_server_spec.rb +9 -0
  54. data/spec/voip/numerical_string_spec.rb +61 -0
  55. data/spec/voip/phone_number_spec.rb +45 -0
  56. data/theatre-spec/dsl_examples/dynamic_stomp.rb +7 -0
  57. data/theatre-spec/dsl_examples/simple_before_call.rb +7 -0
  58. data/theatre-spec/dsl_spec.rb +43 -0
  59. data/theatre-spec/invocation_spec.rb +167 -0
  60. data/theatre-spec/namespace_spec.rb +125 -0
  61. data/theatre-spec/spec_helper.rb +37 -0
  62. data/theatre-spec/spec_helper_spec.rb +28 -0
  63. data/theatre-spec/theatre_class_spec.rb +150 -0
  64. metadata +171 -34
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+
3
+ describe "The Adhearsion module" do
4
+ # This it is of questionable benefit
5
+ it "should have a VERSION constant" do
6
+ Adhearsion.const_defined?(:VERSION).should be true
7
+ end
8
+ end
@@ -0,0 +1,65 @@
1
+ require 'spec_helper'
2
+
3
+ module DRbTestHelper
4
+
5
+ def new_drb_rpc_object
6
+ Object.new.tap do |obj|
7
+ @component_manager.extend_object_with(obj, :rpc)
8
+ end
9
+ end
10
+
11
+ def add_rpc_methods(code)
12
+ @component_manager.load_code "methods_for(:rpc) do; #{code}; end"
13
+ end
14
+
15
+ end
16
+
17
+ describe "Invoking an interface method via DRb" do
18
+ include DRbTestHelper
19
+
20
+ it "should raise an exception if the method is not found" do
21
+ the_following_code do
22
+ new_drb_rpc_object.this_method_doesnt_exist
23
+ end.should raise_error NoMethodError
24
+ end
25
+
26
+ before(:all) { require 'drb' }
27
+
28
+ before :each do
29
+ @component_manager = Adhearsion::Components::ComponentManager.new("/path/doesnt/matter")
30
+ @door = DRb.start_service "druby://127.0.0.1:#{37832 + rand(1500)}", new_drb_rpc_object
31
+ end
32
+
33
+ after :each do
34
+ @door.stop_service
35
+ @door.thread.kill
36
+ end
37
+
38
+ it "should return normal Ruby data structures properly over DRb" do
39
+ add_rpc_methods <<-RUBY
40
+ def bar
41
+ [3,2,1]
42
+ end
43
+ RUBY
44
+ client = DRbObject.new nil, DRb.uri
45
+ client.bar.should == [3, 2, 1]
46
+ end
47
+
48
+ it "should raise an exception for a non-existent interface" do
49
+ client = DRbObject.new nil, DRb.uri
50
+ the_following_code do
51
+ client.interface.bad_interface.should be [3, 2, 1]
52
+ end.should raise_error NoMethodError
53
+ end
54
+
55
+ it "should raise an exception for a non-existent method" do
56
+ client = DRbObject.new nil, DRb.uri
57
+ the_following_code do
58
+ client.interface.interface.foobar.equal [3, 2, 1]
59
+ end.should raise_error NoMethodError
60
+ end
61
+
62
+ after do
63
+ DRb.stop_service
64
+ end
65
+ end
@@ -0,0 +1,3 @@
1
+ sample_context {
2
+ raise 'the body of this context should not have been evaluated'
3
+ }
@@ -0,0 +1,168 @@
1
+ require 'spec_helper'
2
+
3
+ module EventSocketTestHelper
4
+ def mock_handler_object
5
+ flexmock.tap do |handler|
6
+ flexstub(handler).should_receive(:connected)
7
+ flexstub(handler).should_receive(:receive_data)
8
+ flexstub(handler).should_receive(:disconnected)
9
+ end
10
+ end
11
+ end
12
+
13
+ describe "a new EventSocket" do
14
+
15
+ include EventSocketTestHelper
16
+
17
+ it "instantiating a new EventSocket should not instantiate a TCPSocket yet" do
18
+ flexmock(TCPSocket).should_receive(:new).never
19
+ EventSocket.new("localhost", 1234, mock_handler_object)
20
+ end
21
+
22
+ it "instantiating a new EventSocket with both a block and a handler object" do
23
+ the_following_code {
24
+ EventSocket.new("localhost", 1234, mock_handler_object) {}
25
+ }.should raise_error ArgumentError
26
+ end
27
+
28
+ it "instantiating a new EventSocket with neither a block nor handler object" do
29
+ the_following_code {
30
+ EventSocket.new("localhost", 1234)
31
+ }.should raise_error ArgumentError
32
+ end
33
+
34
+ it "should have an initial state of :new" do
35
+ EventSocket.new("localhost", 1234, mock_handler_object).state.should be :new
36
+ end
37
+
38
+ it "the handler created when instantiating the EventSocket with a block" do
39
+ event_socket = EventSocket.new("foo", 123) do |handler|
40
+ handler.receive_data { throw :inside_receive_data }
41
+ handler.disconnected { throw :inside_disconnected}
42
+ handler.connected { throw :inside_connected }
43
+ end
44
+ handler = event_socket.send(:instance_variable_get, :@handler)
45
+ the_following_code {
46
+ handler.send :receive_data, ''
47
+ }.should throw_symbol :inside_receive_data
48
+
49
+ %w[disconnected connected].each do |callback|
50
+ the_following_code {
51
+ handler.send callback
52
+ }.should throw_symbol "inside_#{callback}".to_sym
53
+ end
54
+ end
55
+
56
+ it 'the handler created when instantiating the EventSocket with a block in which "def" is used to define callbacks' do
57
+ event_socket = EventSocket.new("foo", 123) do |handler|
58
+ def handler.receive_data
59
+ throw :inside_receive_data
60
+ end
61
+ def handler.disconnected
62
+ throw :inside_disconnected
63
+ end
64
+ def handler.connected
65
+ throw :inside_connected
66
+ end
67
+ end
68
+ handler = event_socket.send(:instance_variable_get, :@handler)
69
+ %w[receive_data disconnected connected].each do |callback|
70
+ the_following_code {
71
+ handler.send callback
72
+ }.should throw_symbol "inside_#{callback}".to_sym
73
+ end
74
+ end
75
+
76
+ end
77
+
78
+ describe "connecting an EventSocket" do
79
+
80
+ include EventSocketTestHelper
81
+
82
+ before :each do
83
+ flexmock(Mutex).new_instances.should_receive(:synchronize).zero_or_more_times.and_yield
84
+ end
85
+
86
+ it "should instantiate a new TCPSocket with the correct host and port" do
87
+ host, port = "google.com", 80
88
+ mock_socket = flexmock "TCPSocket"
89
+ flexmock(TCPSocket).should_receive(:new).once.with(host, port)
90
+ EventSocket.new(host, port, mock_handler_object).connect!
91
+ end
92
+
93
+ it "should have a state of :connected if TCPSocket instantiates without error" do
94
+ host, port = "google.com", 80
95
+ mock_socket = flexmock "TCPSocket"
96
+ flexmock(TCPSocket).should_receive(:new).once.with(host, port)
97
+ event_socket = EventSocket.new(host, port, mock_handler_object)
98
+ event_socket.connect!
99
+ # Avoid race condition in JRuby where state may return nil
100
+ sleep(0.1)
101
+ event_socket.state.should be :connected
102
+ end
103
+
104
+ it "should have a state of :failed after ECONNREFUSED is raised" do
105
+ host, port = "google.com", 80
106
+ flexmock(TCPSocket).should_receive(:new).once.with(host, port).and_raise(Errno::ECONNREFUSED)
107
+ event_socket = EventSocket.new(host, port, mock_handler_object)
108
+
109
+ the_following_code {
110
+ event_socket.connect!
111
+ }.should raise_error Errno::ECONNREFUSED
112
+
113
+ event_socket.state.should be :failed
114
+ end
115
+
116
+ it "should instantiate a new Thread which calls EventSocket#reader_loop" do
117
+ flexmock(TCPSocket).should_receive(:new).once
118
+ flexmock(Thread).should_receive(:new).and_yield
119
+ the_following_code {
120
+ event_socket = EventSocket.new("foo", 123, mock_handler_object)
121
+ flexmock(event_socket).should_receive(:reader_loop).once.and_throw :in_thread_loop
122
+ event_socket.connect!
123
+ }.should throw_symbol :in_thread_loop
124
+ end
125
+
126
+ end
127
+
128
+ describe "the reader_loop method" do
129
+
130
+ include EventSocketTestHelper
131
+
132
+ it "should call readpartial() on the TCPSocket and pass that to the receive_data method of handler" do
133
+ mock_handler = flexmock "mock handler object"
134
+ mock_socket = flexmock "TCPSocket"
135
+ data = "Jay Phillips " * 25
136
+
137
+ mock_handler.should_receive(:connected).and_return
138
+ mock_handler.should_receive(:disconnected).and_return
139
+ mock_handler.should_receive(:receive_data).once.with(data).and_throw :done_testing
140
+
141
+ mock_socket.should_receive(:readpartial).once.with(EventSocket::MAX_CHUNK_SIZE).and_return data
142
+
143
+ flexmock(TCPSocket).should_receive(:new).once.and_return mock_socket
144
+ flexmock(Thread).should_receive(:new).and_yield
145
+
146
+ the_following_code {
147
+ EventSocket.new("foo", 123, mock_handler).connect!
148
+ }.should throw_symbol :done_testing
149
+ end
150
+
151
+ it "should set the state to :connection_dropped when an EOFError is raised by readpartial" do
152
+ mock_socket = flexmock "TCPSocket"
153
+ mock_socket.should_receive(:readpartial).once.and_raise EOFError
154
+ flexmock(TCPSocket).should_receive(:new).once.and_return mock_socket
155
+
156
+ flexmock(Thread).should_receive(:new).and_yield
157
+
158
+ event_socket = EventSocket.new("foo", 123, mock_handler_object)
159
+
160
+ event_socket.connect!
161
+ event_socket.state.should be :connection_dropped
162
+ end
163
+
164
+ end
165
+
166
+ describe "the writer_loop method" do
167
+
168
+ end
@@ -0,0 +1,79 @@
1
+ require 'spec_helper'
2
+ require 'adhearsion/host_definitions'
3
+
4
+ describe 'HostDefinition' do
5
+
6
+ after :each do
7
+ Adhearsion::HostDefinition.clear_definitions!
8
+ end
9
+
10
+ it 'when loading from a YAML array, it should pass each nested Hash to the constructor' do
11
+ hosts = [
12
+ {:host => "hostname1", :username => "user", :password => "password"},
13
+ {:host => "hostname2", :username => "user", :password => "password"},
14
+ {:host => "hostname3", :username => "user", :password => "password"}
15
+ ]
16
+ flexmock(Adhearsion::HostDefinition).should_receive(:new).once.with(hosts[0])
17
+ flexmock(Adhearsion::HostDefinition).should_receive(:new).once.with(hosts[1])
18
+ flexmock(Adhearsion::HostDefinition).should_receive(:new).once.with(hosts[2])
19
+ Adhearsion::HostDefinition.import_from_yaml hosts.to_yaml
20
+ end
21
+
22
+ it 'should set the @name property to a new UUID when no name is given' do
23
+ definition = {:host => "hostname", :username => "user", :password => "pass"}
24
+ Adhearsion::HostDefinition.new(definition).name.should =~ /^[a-z0-9]{8}-([a-z0-9]{4}-){3}[a-z0-9]{12}$/i
25
+ end
26
+
27
+ it 'when loading from YAML keys, it should pass each nested Hash to the constructor with the key as :name' do
28
+ definitions = { :pbx1 => {},
29
+ :pbx2 => {},
30
+ :pbx3 => {} }
31
+ definitions.each_pair do |key,value|
32
+ flexmock(Adhearsion::HostDefinition).should_receive(:new).once.with(value.merge(:name => key))
33
+ end
34
+ Adhearsion::HostDefinition.import_from_data_structure(definitions)
35
+ end
36
+
37
+ it 'should have an Array class variable named definitions' do
38
+ Adhearsion::HostDefinition.definitions.should be_a_kind_of Array
39
+ end
40
+
41
+ it 'should add each HostDefinition to a class variable named @@definitions when instantiated' do
42
+ Adhearsion::HostDefinition.definitions.size.should be 0
43
+ Adhearsion::HostDefinition.new :name => "foobar", :host => "hostname", :username => "user", :password => "password"
44
+ Adhearsion::HostDefinition.definitions.size.should be 1
45
+ Adhearsion::HostDefinition.clear_definitions!
46
+ Adhearsion::HostDefinition.definitions.size.should be 0
47
+ end
48
+
49
+ it 'should raise a HostDefinitionException when a password and a key are given' do
50
+ the_following_code {
51
+ Adhearsion::HostDefinition.new(:username => "user", :host => "foobar", :key => "doesntmatter", :password => "pass")
52
+ }.should raise_error Adhearsion::HostDefinition::HostDefinitionException
53
+ end
54
+
55
+ it 'should raise a HostDefinitionException when no password or key is given' do
56
+ the_following_code {
57
+ Adhearsion::HostDefinition.new(:username => "user", :host => "foobar")
58
+ }.should raise_error Adhearsion::HostDefinition::HostDefinitionException
59
+ end
60
+
61
+ it 'should raise a HostDefinitionException when no username is given' do
62
+ the_following_code {
63
+ Adhearsion::HostDefinition.new(:host => "host", :password => "password")
64
+ }.should raise_error Adhearsion::HostDefinition::HostDefinitionException
65
+ end
66
+
67
+ it 'should raise a HostDefinitionException when no "host" key is given' do
68
+ the_following_code {
69
+ Adhearsion::HostDefinition.new(:username => "foobar", :password => "password")
70
+ }.should raise_error Adhearsion::HostDefinition::HostDefinitionException
71
+ end
72
+
73
+ it 'should raise a HostDefinitionException when an unrecognized key is given' do
74
+ the_following_code {
75
+ Adhearsion::HostDefinition.new(:username => "foobar", :password => "password", :host => "blah", :thiskeyisnotrecognized => nil)
76
+ }.should raise_error Adhearsion::HostDefinition::HostDefinitionException
77
+ end
78
+
79
+ end
@@ -0,0 +1,163 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Adhearsion::Initializer" do
4
+
5
+ include InitializerStubs
6
+ # TODO: create a specification for aliases
7
+
8
+ before :each do
9
+ Adhearsion.send(:remove_const, 'AHN_CONFIG') if Adhearsion.const_defined? 'AHN_CONFIG'
10
+ Adhearsion::AHN_CONFIG = Adhearsion::Configuration.new
11
+ end
12
+
13
+ after :each do
14
+ Adhearsion::Events.reinitialize_theatre!
15
+ end
16
+
17
+ it "initialization will start with only a path given" do
18
+ stub_behavior_for_initializer_with_no_path_changing_behavior do
19
+ Adhearsion::Initializer.start path
20
+ end
21
+ end
22
+
23
+ it "should create a pid file in the app's path when given 'true' as the pid_file hash key argument" do
24
+ stub_behavior_for_initializer_with_no_path_changing_behavior do
25
+ flexmock(File).should_receive(:open).with(File.join(path, 'adhearsion.pid'), 'w', Proc).at_least.once
26
+ ahn = Adhearsion::Initializer.start path, :pid_file => true
27
+ ahn.pid_file[0, path.length].should == path
28
+ end
29
+ end
30
+
31
+ it "should NOT create a pid file in the app's path when given 'false' as the pid_file hash key argument" do
32
+ stub_behavior_for_initializer_with_no_path_changing_behavior do
33
+ ahn = Adhearsion::Initializer.start path, :pid_file => false
34
+ ahn.pid_file.should be nil
35
+ end
36
+ end
37
+
38
+ it "should create a pid file in the app's path by default when daemonizing" do
39
+ stub_behavior_for_initializer_with_no_path_changing_behavior do
40
+ flexmock(File).should_receive(:open).once.with(File.join(path, 'adhearsion.pid'), 'w', Proc)
41
+ ahn = Adhearsion::Initializer.start path, :daemon => true
42
+ ahn.pid_file[0, path.size].should == path
43
+ end
44
+ end
45
+
46
+ it "should NOT create a pid file in the app's path when daemonizing and :pid_file is given as false" do
47
+ stub_behavior_for_initializer_with_no_path_changing_behavior do
48
+ ahn = Adhearsion::Initializer.start path, :daemon => true, :pid_file => false
49
+ ahn.pid_file.should be nil
50
+ end
51
+ end
52
+
53
+ it "should execute gem when .ahnrc contains gem names" do
54
+ stub_behavior_for_initializer_with_no_path_changing_behavior do
55
+ ahn_rc = {
56
+ "gems" => {
57
+ "activerecord" => { "version" => ">= 1.2.0" },
58
+ "twitter" => nil
59
+ },
60
+ # Paths are unnecessary except to make the other part of bootstrap_rc happy.
61
+ "paths"=>{"dialplan"=>"dialplan.rb", "init"=>"config/startup.rb", "events"=>"events.rb",
62
+ "models"=> "models/*.rb"}
63
+ }
64
+ ahn = Adhearsion::Initializer.new path
65
+ flexmock(Adhearsion::Initializer).should_receive(:get_rules_from).once.and_return ahn_rc
66
+ flexmock(ahn).should_receive(:gem).once.with("activerecord", ">= 1.2.0")
67
+ flexmock(ahn).should_receive(:gem).once.with("twitter")
68
+ ahn.start
69
+ end
70
+ end
71
+
72
+ it "should require() the lib when .ahnrc contains a require section with one name" do
73
+ stub_behavior_for_initializer_with_no_path_changing_behavior do
74
+ ahn_rc = {
75
+ "gems" => {
76
+ "twitter" => {
77
+ "require" => "sometwitterstuffs"
78
+ }
79
+ },
80
+ # Paths are unnecessary except to make the other part of bootstrap_rc happy.
81
+ "paths"=>{"dialplan"=>"dialplan.rb", "init"=>"config/startup.rb", "events"=>"events.rb",
82
+ "models"=>"models/*.rb"}
83
+ }
84
+ ahn = Adhearsion::Initializer.new path
85
+ flexmock(Adhearsion::Initializer).should_receive(:get_rules_from).once.and_return ahn_rc
86
+ flexstub(ahn).should_receive(:gem).once.with("twitter")
87
+ flexmock(ahn).should_receive(:require).once.with("sometwitterstuffs")
88
+ flexmock(ahn).should_receive(:require).at_least.once.with(String)
89
+ ahn.start
90
+ end
91
+ end
92
+
93
+ it "should create a designated pid file when supplied a String path as :pid_file" do
94
+ random_file = "/tmp/AHN_TEST_#{rand 100000}.pid"
95
+ stub_behavior_for_initializer_with_no_path_changing_behavior do
96
+ ahn = Adhearsion::Initializer.start path, :pid_file => random_file
97
+ ahn.pid_file.should be(random_file)
98
+ File.exists?(random_file).should be true
99
+ File.delete random_file
100
+ end
101
+ end
102
+
103
+ it "should initialze events properly" do
104
+ require 'theatre'
105
+ events_rb = Tempfile.new "events.rb"
106
+ initializer = Adhearsion::Initializer.new("/does/not/matter")
107
+ flexmock(Adhearsion::AHN_CONFIG).should_receive(:files_from_setting).at_least.once.with("paths", "events").
108
+ and_return([events_rb.path])
109
+ flexmock(Adhearsion::Events.framework_theatre).should_receive(:load_events_file).once.with events_rb.path
110
+ flexmock(Adhearsion::Events.framework_theatre).should_receive(:start!).once
111
+
112
+ initializer.send :init_events_subsystem
113
+ initializer.send :init_events_file
114
+ end
115
+
116
+ private
117
+ def path
118
+ '/any/ole/path'
119
+ end
120
+ end
121
+
122
+ describe "AHN_ROOT" do
123
+ include InitializerStubs
124
+ before(:each) do
125
+ Object.send(:remove_const, :AHN_ROOT) if defined? AHN_ROOT
126
+ end
127
+
128
+ it "initializing will create the AHN_ROOT" do
129
+ stub_behavior_for_initializer_with_no_path_changing_behavior do
130
+ ahn = Adhearsion::Initializer.start path
131
+ Object.constants.map(&:to_s).include?("AHN_ROOT").should be true
132
+ end
133
+ end
134
+
135
+ it "swapping out the base_path for the duration of the block" do
136
+ original_base_path = '.'
137
+ temporary_base = '/foo'
138
+
139
+ path = Adhearsion::PathString.new(original_base_path)
140
+ path.should == original_base_path
141
+
142
+ path.using_base_path temporary_base do
143
+ path.should == temporary_base
144
+ end
145
+ path.should == original_base_path
146
+ end
147
+
148
+ it "creating the AHN_ROOT will set defaults" do
149
+ stub_behavior_for_initializer_with_no_path_changing_behavior do
150
+ flexstub(Adhearsion::Initializer).new_instances.should_receive(:load).and_return
151
+ ahn = Adhearsion::Initializer.start path
152
+ full_path = File.expand_path(path)
153
+ AHN_ROOT.to_s.should == full_path
154
+ AHN_ROOT.component_path.should == File.join(full_path, "components")
155
+ AHN_ROOT.log_path.should == File.join(full_path, "logs")
156
+ AHN_ROOT.dialplan_path.should == full_path
157
+ end
158
+ end
159
+ private
160
+ def path
161
+ '/any/ole/path'
162
+ end
163
+ end