eric-adhearsion 0.7.999

Sign up to get free protection for your applications and to get access to all the features.
Files changed (150) hide show
  1. data/CHANGELOG +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 +1182 -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 +391 -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 +451 -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,162 @@
1
+ require File.dirname(__FILE__) + "/../test_helper"
2
+ require 'adhearsion/initializer/database'
3
+ require 'adhearsion/initializer/asterisk'
4
+ require 'adhearsion/initializer/rails'
5
+ require 'active_record'
6
+
7
+ context "The database initializer" do
8
+
9
+ include DatabaseInitializationTestHelper
10
+
11
+ test "starts a connection through ActiveRecord" do
12
+ connection_options = { :adapter => "sqlite3",
13
+ :dbfile => "foo.sqlite3" }
14
+ flexmock(Adhearsion::Initializer::DatabaseInitializer).should_receive(:require_models).once
15
+ flexmock(ActiveRecord::Base).should_receive(:establish_connection).with(connection_options)
16
+
17
+ start_database_initializer_with_options connection_options
18
+ end
19
+
20
+ test "should make any required models available in the main namespace" do
21
+ bogus_model = tempfile_with_contents sample_user_model
22
+ flexmock(Adhearsion::Initializer::DatabaseInitializer).should_receive(:all_models).and_return([bogus_model.path])
23
+ start_database_initializer
24
+ User.superclass.should.equal ActiveRecord::Base
25
+ end
26
+
27
+ test 'should enable ActiveRecord concurrency' do
28
+ bogus_model = tempfile_with_contents sample_user_model
29
+ flexmock(Adhearsion::Initializer::DatabaseInitializer).should_receive(:all_models).and_return([bogus_model.path])
30
+ start_database_initializer
31
+ ActiveRecord::Base.send(:class_variable_get, :@@allow_concurrency).should.be true
32
+ end
33
+
34
+ end
35
+
36
+ context "The Asterisk initializer" do
37
+
38
+ include AsteriskInitializerTestHelper
39
+
40
+ test "starts the AGI server" do
41
+ initialize_asterisk_with_defaults
42
+ flexmock(Adhearsion::VoIP::Asterisk::AGI::Server).new_instances.should_receive(:start).once
43
+ end
44
+
45
+ test "starts the AGI server with any overridden settings" do
46
+ overrides = {:host => "127.0.0.1", :port => 7788}
47
+ config_overrides = {:listening_host => overrides[:host], :listening_port => overrides[:port]}
48
+ initialize_asterisk_with_options config_overrides
49
+ flexmock(Adhearsion::VoIP::Asterisk::AGI::Server).new_instances.should_receive(:start).once.with(overrides)
50
+ end
51
+
52
+ end
53
+
54
+ context "The Rails initializer" do
55
+
56
+ include RailsInitializerTestHelper
57
+
58
+ test "should load the config/environment.rb file within the rails_root path" do
59
+ rails_root = "/path/to/rails/app"
60
+ environment_rb = rails_root + '/config/environment.rb'
61
+ flexmock(Adhearsion::Initializer::RailsInitializer).should_receive(:require).once.with environment_rb
62
+ stub_file_checking_methods!
63
+ stub_before_call_hook!
64
+ initialize_rails_with_options :rails_root => rails_root, :environment => :development
65
+ end
66
+
67
+ test "should raise an exception if the database is initialized at the same time" do
68
+ flexmock(Adhearsion::AHN_CONFIG).should_receive(:database_enabled?).and_return true
69
+ flexmock(Adhearsion::Initializer::RailsInitializer).should_receive(:require).and_return
70
+ stub_file_checking_methods!
71
+ stub_before_call_hook!
72
+ the_following_code {
73
+ initialize_rails_with_options :rails_root => '/tmp', :environment => :development
74
+ }.should.raise
75
+ end
76
+
77
+ test "should set the RAILS_ENV to be the argument passed in" do
78
+ flexmock(ENV).should_receive(:[]=).once.with("RAILS_ENV", "development")
79
+ flexmock(Adhearsion::Initializer::RailsInitializer).should_receive(:require).once.and_return
80
+ stub_file_checking_methods!
81
+ stub_before_call_hook!
82
+ initialize_rails_with_options :rails_root => '/tmp', :environment => :development
83
+ end
84
+
85
+ test 'should enable ActiveRecord concurrency' do
86
+ flexstub(Adhearsion::Initializer::RailsInitializer).should_receive :require
87
+ flexstub(Adhearsion::Initializer::RailsInitializer).should_receive :load_rails
88
+ stub_file_checking_methods!
89
+ stub_before_call_hook!
90
+ initialize_rails_with_options :rails_root => '/path/somewhere', :environment => :development
91
+ ActiveRecord::Base.send(:class_variable_get, :@@allow_concurrency).should.equal true
92
+ end
93
+
94
+ test 'should create a BeforeCall hook (presumably to verify the active connections)' do
95
+ flexstub(Adhearsion::Initializer::RailsInitializer).should_receive :require
96
+ flexstub(Adhearsion::Initializer::RailsInitializer).should_receive :load_rails
97
+ stub_file_checking_methods!
98
+ flexmock(Adhearsion::Hooks::BeforeCall).should_receive(:create_hook).once
99
+ initialize_rails_with_options :rails_root => '/path/somewhere', :environment => :development
100
+ end
101
+
102
+ end
103
+
104
+ BEGIN {
105
+ module DatabaseInitializationTestHelper
106
+
107
+ def start_database_initializer
108
+ start_database_initializer_with_options :adapter => "sqlite3", :dbfile => "foobar.sqlite3"
109
+ end
110
+
111
+ def start_database_initializer_with_options(options)
112
+ Adhearsion::Configuration.configure { |config| config.enable_database(options) }
113
+ Adhearsion::Initializer::DatabaseInitializer.start
114
+ end
115
+
116
+ def tempfile_with_contents(contents)
117
+ returning Tempfile.new("bogus_model") do |file|
118
+ file.puts contents
119
+ file.flush
120
+ end
121
+ end
122
+
123
+ def sample_user_model
124
+ <<-CODE
125
+ class User < ActiveRecord::Base
126
+ validates_uniqueness_of :name
127
+ end
128
+ CODE
129
+ end
130
+ end
131
+
132
+ module AsteriskInitializerTestHelper
133
+ def initialize_asterisk_with_defaults
134
+ initialize_asterisk_with_options Hash.new
135
+ end
136
+ def initialize_asterisk_with_options(options)
137
+ flexmock(Adhearsion::Initializer::AsteriskInitializer).should_receive(:join_server_thread_after_initialized)
138
+ Adhearsion::Configuration.configure { |config| config.enable_asterisk(options) }
139
+ Adhearsion::Initializer::AsteriskInitializer.start
140
+ end
141
+ end
142
+
143
+ module RailsInitializerTestHelper
144
+
145
+ def initialize_rails_with_options(options)
146
+ rails_options = flexmock "Rails options mock", options
147
+ flexstub(Adhearsion::AHN_CONFIG).should_receive(:rails).once.and_return(rails_options)
148
+ Adhearsion::Initializer::RailsInitializer.start
149
+ end
150
+
151
+ def stub_file_checking_methods!
152
+ flexstub(File).should_receive(:directory?).and_return true
153
+ flexstub(File).should_receive(:exists?).and_return true
154
+ end
155
+
156
+ def stub_before_call_hook!
157
+ flexstub(Adhearsion::Hooks::BeforeCall).should_receive :create_hook
158
+ end
159
+
160
+ end
161
+
162
+ }
@@ -0,0 +1,43 @@
1
+ require File.dirname(__FILE__) + "/../test_helper"
2
+
3
+ describe "Adhearsion::Paths" do
4
+
5
+ #TODO: All this crap will go away
6
+ disabled_test "should find all files when given a glob" do
7
+ inside_initialized_app do |path|
8
+ tmps = %w"foo.rb BA\ R.gem _q_a_z_.c"
9
+ tmps.each { |f| FileUtils.touch "#{path}/helpers/#{f}" }
10
+ found_helpers = all_helpers
11
+ all_helpers.should.not.be.empty
12
+ all_helpers.map! {|f| File.basename f }
13
+ all_helpers.each { |f| all_helpers.should.include(f) }
14
+ end
15
+ end
16
+ test "should find files when several globs are given"
17
+
18
+ test "should allow the removal of path managers" do
19
+ Adhearsion::Paths.manager_for :helpers, :directory => "helpers"
20
+ Adhearsion::Paths.remove_manager_for :helpers
21
+ end
22
+ end
23
+
24
+ describe "The .ahnrc " do
25
+ test "should allow ERb"
26
+ test "should create methods for every path declared"
27
+ test "should add all_x and x_path methods to main namespace and pluralize names" do
28
+ Adhearsion::Paths.manager_for "helper", :directory => "helpers"
29
+ should.respond_to(:all_helpers)
30
+ should.respond_to(:helper_path)
31
+ end
32
+ test "should have an init key"
33
+ test "should allow a String to the init key"
34
+ test "should default the init key to config/startup.rb"
35
+ test "should allow an Array to the init key"
36
+ end
37
+
38
+ describe "Adhearsion's paths syntax sugar" do
39
+ test "should calculate helper paths properly"
40
+ test "should find log files properly"
41
+ test "should find helper config paths properly"
42
+ test "should return the configuration for a helper properly"
43
+ end
data/spec/silence.rb ADDED
@@ -0,0 +1,10 @@
1
+ #
2
+ # Seeing the dump of pending specs every time you run them is distracting.
3
+ # This file lets you skip pending specs.
4
+ class Test::Unit::TestResult
5
+ def add_disabled(name)
6
+ #nothing!
7
+ end
8
+ end
9
+
10
+ Adhearsion::Logging.silence!
@@ -0,0 +1,149 @@
1
+ require File.dirname(__FILE__) + "/test_helper"
2
+ require 'adhearsion/cli'
3
+
4
+ module AhnCommandSpecHelper
5
+ def simulate_args(*args)
6
+ ARGV.clear
7
+ ARGV.concat args
8
+ end
9
+
10
+ def capture_stdout(&block)
11
+ old = $stdout
12
+ $stdout = io = StringIO.new
13
+ yield
14
+ ensure
15
+ $stdout = old
16
+ return io.string
17
+ end
18
+
19
+ def new_tmp_dir(filename=String.random)
20
+ File.join Dir.tmpdir, filename
21
+ end
22
+
23
+
24
+ end
25
+
26
+ context 'The Ahn Command helper' do
27
+
28
+ include AhnCommandSpecHelper
29
+
30
+ test "args are simulated properly" do
31
+ before = ARGV.clone
32
+ simulate_args "create", "/tmp/blah"
33
+ ARGV.should.not.equal before
34
+ end
35
+
36
+ test "STDOUT should be captured" do
37
+ capture_stdout do
38
+ puts "wee"
39
+ end.should.equal "wee\n"
40
+ end
41
+
42
+ end
43
+
44
+ context "A simulated use of the 'ahn' command" do
45
+
46
+ include AhnCommandSpecHelper
47
+
48
+ test "USAGE is defined" do
49
+ assert Adhearsion::CLI::AhnCommand.const_defined?('USAGE')
50
+ end
51
+
52
+ test "arguments to 'create' are executed properly properly" do
53
+ some_path = "/path/somewhere"
54
+ simulate_args "create", some_path
55
+ flexmock(Adhearsion::CLI::AhnCommand::CommandHandler).should_receive(:create).once.with(some_path, :default)
56
+ capture_stdout { Adhearsion::CLI::AhnCommand.execute! }
57
+ end
58
+
59
+ test "arguments to 'start' are executed properly properly" do
60
+ some_path = "/tmp/blargh"
61
+ simulate_args "start", some_path
62
+ flexmock(Adhearsion::CLI::AhnCommand::CommandHandler).should_receive(:start).once.with(some_path, false, nil)
63
+ Adhearsion::CLI::AhnCommand.execute!
64
+ end
65
+
66
+ test "should execute arguments to 'start' for daemonizing properly" do
67
+ somewhere = "/tmp/blarghh"
68
+ simulate_args "start", 'daemon', somewhere
69
+ flexmock(Adhearsion::CLI::AhnCommand::CommandHandler).should_receive(:start).once.with(somewhere, true, nil)
70
+ Adhearsion::CLI::AhnCommand.execute!
71
+ end
72
+
73
+ test 'parse_arguments should recognize start with daemon properly' do
74
+ path = '/path/to/somesuch'
75
+ arguments = ["start", 'daemon', path]
76
+ Adhearsion::CLI::AhnCommand.parse_arguments(arguments).should == [:start, path, true, nil]
77
+ end
78
+
79
+ test 'should recognize start with daemon and pid file properly' do
80
+ project_path = '/second/star/on/the/right'
81
+ pid_file_path = '/straight/on/til/morning'
82
+ arguments = ["start", "daemon", project_path, "--pid-file=#{pid_file_path}"]
83
+ Adhearsion::CLI::AhnCommand.parse_arguments(arguments).should == [:start, project_path, true, pid_file_path]
84
+ end
85
+
86
+ test 'parse_arguments should recognize start without daemon properly' do
87
+ path = '/path/to/somewhere'
88
+ arguments = ['start', path]
89
+ Adhearsion::CLI::AhnCommand.parse_arguments(arguments).should == [:start, path, false, nil]
90
+ end
91
+
92
+ test "if no path is provided, running Ahn command blows up" do
93
+ the_following_code {
94
+ Adhearsion::CLI::AhnCommand.parse_arguments(['start'])
95
+ }.should.raise Adhearsion::CLI::AhnCommand::CommandHandler::UnknownCommand
96
+ end
97
+
98
+ test "printing the version" do
99
+ capture_stdout do
100
+ simulate_args 'version'
101
+ Adhearsion::CLI::AhnCommand.execute!
102
+ end.should =~ Regexp.new(Regexp.escape(Adhearsion::VERSION::STRING))
103
+ end
104
+
105
+ test "printing the help" do
106
+ capture_stdout do
107
+ simulate_args 'help'
108
+ Adhearsion::CLI::AhnCommand.execute!
109
+ end.should =~ Regexp.new(Regexp.escape(Adhearsion::CLI::AhnCommand::USAGE))
110
+ end
111
+
112
+ test "reacting to unrecognized commands" do
113
+ the_following_code {
114
+ simulate_args "alpha", "beta"
115
+ Adhearsion::CLI::AhnCommand.execute!
116
+ }.should.raise(Adhearsion::CLI::AhnCommand::CommandHandler::UnknownCommand)
117
+ end
118
+
119
+ test "giving a path that doesn't contain a project raises an exception" do
120
+ the_following_code {
121
+ simulate_args "start", "/asjdfas/sndjfabsdfbqwb/qnjwejqbwh"
122
+ Adhearsion::CLI::AhnCommand.execute!
123
+ }.should.raise(Adhearsion::CLI::AhnCommand::CommandHandler::PathInvalid)
124
+ end
125
+
126
+ test "giving an unrecognized project name raises an exception" do
127
+ the_following_code {
128
+ nonexistent_app_name, nonexistent_path = "a2n8y3gny2", "/tmp/qjweqbwas"
129
+ simulate_args "create:#{nonexistent_app_name}", nonexistent_path
130
+ Adhearsion::CLI::AhnCommand.execute!
131
+ }.should.raise Adhearsion::CLI::AhnCommand::CommandHandler::UnknownProject
132
+ end
133
+ end
134
+
135
+ context 'A real use of the "ahn" command' do
136
+
137
+ include AhnCommandSpecHelper
138
+
139
+ test "the 'create' command" do
140
+ the_following_code {
141
+ tmp_path = new_tmp_dir
142
+ simulate_args "create", tmp_path
143
+ RubiGen::Base.default_options.merge! :quiet => true
144
+ capture_stdout { Adhearsion::CLI::AhnCommand.execute! }
145
+ File.exists?(File.join(tmp_path, ".ahnrc")).should.be true
146
+ }.should.not.raise
147
+ end
148
+
149
+ end
@@ -0,0 +1,87 @@
1
+ # #!/usr/bin/env spec
2
+ #
3
+ # # TODO: Forget regexps. Use Rubinius.
4
+ # # This spec is somewhat unique. It essentially reads the code
5
+ # # and ensures the best practices are followed.
6
+ #
7
+ # # TODO: Create a be_a_proper_method_definition assertion
8
+ # # TODO: Create a syntax checking spec
9
+ # # TODO: Report code that has spaces between the dot when defining the method on an object
10
+ #
11
+ # module CodeQualityHelper
12
+ # # TODO: Allow strings with a Hash in them before it
13
+ #
14
+ # BadMethodRegexp = /def\s+([$@]?[a-zA-Z_][\w_]*\s*\.\s*)?[a-zA-Z_][\w_]*[=!?]?[^(^\Z]/
15
+ # @root = File.dirname(__FILE__) + "/.."
16
+ #
17
+ # def ruby_files
18
+ # @ruby_files ||= Dir[@root + "/**/*.rb"].map { |f| File.expand_path f }
19
+ # end
20
+ #
21
+ # end
22
+ #
23
+ # describe "My 'bad method definition' finding regular expression" do
24
+ #
25
+ # # ATTENTION: If this spec ever blows up for a method definition it shouldn't,
26
+ # # please add the definition that caused it to explode here as an assertion.
27
+ # # It would also be nice to fix the regular expression too :)
28
+ #
29
+ # include CodeQualityHelper
30
+ #
31
+ # it "should NOT match method definitions with no arguments" do
32
+ # "def foo".should !~ CodeQualityHelper::BadMethodRegexp
33
+ # " def monkey ".should !~ CodeQualityHelper::BadMethodRegexp
34
+ # ' unless "#{bar}".empty? then def @zebra.spock '.should !~ CodeQualityHelper::BadMethodRegexp
35
+ # end
36
+ #
37
+ # it "should NOT match method definitions with arguments and parenthesis" do
38
+ # "def foo(bar)".should !~ CodeQualityHelper::BadMethodRegexp
39
+ # "\tdef $MONKEY . foo( bar, qaz = blam!) ".should !~ CodeQualityHelper::BadMethodRegexp
40
+ # "if(this) then def $MONKEY . foo( qaz = blam!, *args, &b) ".should !~ CodeQualityHelper::BadMethodRegexp
41
+ # " @something.each do |x| def something".should !~ CodeQualityHelper::BadMethodRegexp
42
+ # end
43
+ #
44
+ # it "should match method definitions with a space between the name and parenthesis" do
45
+ # "def foo (bar)".should =~ CodeQualityHelper::BadMethodRegexp
46
+ # "def \t m \t (*args)".should =~ CodeQualityHelper::BadMethodRegexp
47
+ # end
48
+ #
49
+ # it "should match method definitions with no parenthesis around its arguments" do
50
+ # "def foo bar".should =~ CodeQualityHelper::BadMethodRegexp
51
+ # "\tif $x then def foo bar # Commentacular".should =~ CodeQualityHelper::BadMethodRegexp
52
+ # end
53
+ # end
54
+ #
55
+ # describe "All method definitions" do
56
+ #
57
+ # include CodeQualityHelper
58
+ #
59
+ # before:all do
60
+ # @root = File.dirname(__FILE__) + "/.."
61
+ # end
62
+ #
63
+ # it "should have parenthesis around their arguments" do
64
+ # ruby_files.each do |file|
65
+ # puts file
66
+ # File.read(file).grep(CodeQualityHelper::BadMethodRegexp).should be_empty
67
+ # end
68
+ # end
69
+ # end
70
+ #
71
+ # # describe "The syntax of all Ruby source files" do
72
+ # #
73
+ # # include CodeQualityHelper
74
+ # #
75
+ # # before:all do
76
+ # # @root = File.dirname(__FILE__) + "/.."
77
+ # # end
78
+ # #
79
+ # # it "should be valid" do
80
+ # # incorrect = ruby_files.map { |f| File.expand_path f }.select do |file|
81
+ # # `ruby -c #{file}`
82
+ # # not $?.success?
83
+ # # end
84
+ # #
85
+ # # incorrect.should be_empty
86
+ # # end
87
+ # # end
@@ -0,0 +1,97 @@
1
+ require File.dirname(__FILE__) + "/test_helper"
2
+
3
+ context "Adding call context to components" do
4
+ include CallContextComponentTestHelpers
5
+
6
+ attr_reader :sample_component
7
+
8
+ setup do
9
+ @sample_component = new_componenet_class_named(sample_component_name)
10
+ end
11
+
12
+ test "Component name is added to list of components that will have call contexts injected into them" do
13
+ components_with_call_context.should.be.empty
14
+ the_following_code {
15
+ sample_component.add_call_context
16
+ }.should.not.raise
17
+
18
+ components_with_call_context.should.not.be.empty
19
+ Adhearsion::ComponentManager.components_with_call_context[sample_component_name].component_class.should.equal sample_component
20
+ end
21
+
22
+ private
23
+ def components_with_call_context
24
+ Adhearsion::ComponentManager.components_with_call_context.keys
25
+ end
26
+
27
+ def sample_component_name
28
+ 'SampleComponent'
29
+ end
30
+ end
31
+
32
+ context "Referencing a component class in a dial plan context" do
33
+ include CallContextComponentTestHelpers
34
+
35
+ test "the class constant should be available in the scope of a call context" do
36
+ sample_component_class = new_componenet_class_named('SampleComponent2')
37
+ sample_component_class.add_call_context
38
+
39
+ loader = load_dial_plan(<<-DIAL_PLAN)
40
+ some_context {
41
+ SampleComponent2
42
+ }
43
+ DIAL_PLAN
44
+
45
+ flexmock(Adhearsion::DialPlan::Loader).should_receive(:load_dial_plan).and_return(loader)
46
+ tested_call = Adhearsion::Call.new(nil, :context => :some_context)
47
+ mock_config = flexmock 'a Configuration which communicates automatically_answer_incoming_calls properly',
48
+ :automatically_answer_incoming_calls => false
49
+ flexmock(Adhearsion::Configuration).should_receive(:new).once.and_return mock_config
50
+ Adhearsion::Configuration.configure
51
+
52
+ the_following_code {
53
+ handle(tested_call)
54
+ }.should.not.raise
55
+ end
56
+
57
+ test "the call context is injected into any instances of the component class" do
58
+ sample_component_class = new_componenet_class_named('SampleComponent3')
59
+ sample_component_class.add_call_context :as => :call_context_variable_name
60
+
61
+ loader = load_dial_plan(<<-DIAL_PLAN)
62
+ some_context {
63
+ new_sample_component3.call_context_variable_name
64
+ }
65
+ DIAL_PLAN
66
+
67
+ flexmock(Adhearsion::DialPlan::Loader).should_receive(:load_dial_plan).and_return(loader)
68
+ sample_call = Adhearsion::Call.new(nil, :context => :some_context)
69
+ mock_config = flexmock 'a Configuration which communicates automatically_answer_incoming_calls properly',
70
+ :automatically_answer_incoming_calls => false
71
+ flexmock(Adhearsion::Configuration).should_receive(:new).once.and_return mock_config
72
+ Adhearsion::Configuration.configure
73
+
74
+ the_following_code {
75
+ handle(sample_call)
76
+ }.should.not.raise
77
+ end
78
+
79
+ private
80
+ def load_dial_plan(dial_plan_as_string)
81
+ Adhearsion::DialPlan::Loader.load(dial_plan_as_string)
82
+ end
83
+
84
+ def handle(call)
85
+ Adhearsion::DialPlan::Manager.handle(call)
86
+ end
87
+ end
88
+
89
+ BEGIN {
90
+ module CallContextComponentTestHelpers
91
+ def new_componenet_class_named(component_name)
92
+ component_namespace = Adhearsion::Components::ComponentModule.new('passed in component does not matter here')
93
+ Adhearsion::Components::Component.prepare_component_class(component_namespace, component_name)
94
+ component_namespace.const_get(component_name)
95
+ end
96
+ end
97
+ }
@@ -0,0 +1,8 @@
1
+ require File.dirname(__FILE__) + "/test_helper"
2
+
3
+ context "The Adhearsion module" do
4
+ # This test is of questionable benefit
5
+ test "should have a VERSION constant" do
6
+ assert(Adhearsion.const_defined?(:VERSION), "VERSION constant should be defined")
7
+ end
8
+ end
data/spec/test_drb.rb ADDED
@@ -0,0 +1,104 @@
1
+ require File.dirname(__FILE__) + "/test_helper"
2
+
3
+ # The way I envisoned publishing this DRb:
4
+ #
5
+ # publish :globally do/end
6
+ # publish :with => :drb do/end
7
+
8
+ context "Publishing an interface" do
9
+ test "should be allowed with a class method" do
10
+ Class.new.class_eval do
11
+ include Adhearsion::Publishable
12
+ publish :through => :interface do
13
+ def self.bar
14
+ [1, 2, 3]
15
+ end
16
+ end
17
+ end
18
+ Adhearsion::DrbDoor.instance.interface.bar.should.equal [1, 2, 3]
19
+ end
20
+
21
+ test "should be allowed with an alternate interface" do
22
+ Class.new.class_eval do
23
+ include Adhearsion::Publishable
24
+ publish :through => :api do
25
+ def self.bar
26
+ [2, 3, 4]
27
+ end
28
+ end
29
+ end
30
+ Adhearsion::DrbDoor.instance.api.bar.should.equal [2, 3, 4]
31
+ end
32
+
33
+ test "should be allowed with a metaclass block" do
34
+ Class.new.class_eval do
35
+ include Adhearsion::Publishable
36
+ publish :through => :interface do
37
+ class << self
38
+ def bar
39
+ [3, 2, 1]
40
+ end
41
+ end
42
+ end
43
+ end
44
+ Adhearsion::DrbDoor.instance.interface.bar.should.equal [3, 2, 1]
45
+ end
46
+
47
+ test "should be allowed from within the metaclass block" do
48
+ # Class.new.class_eval do
49
+ # include Publishable
50
+ # class << self
51
+ # publish :through => :interface do
52
+ # def baz
53
+ # [4, 5, 6]
54
+ # end
55
+ # end
56
+ # end
57
+ # end
58
+ # Adhearsion::DrbDoor.instance.interface.baz.should.equal [4, 5, 6]
59
+ end
60
+ end
61
+
62
+ context "Invoking an interface" do
63
+ test "should raise an exception if the method is not found" do
64
+ the_following_code do
65
+ Adhearsion::DrbDoor.instance.interface.foobar.should.equal [1, 2, 3]
66
+ end.should.raise NoMethodError
67
+ end
68
+
69
+ test "should raise an exception if the interface is not found" do
70
+ the_following_code do
71
+ Adhearsion::DrbDoor.instance.bad_interface.bar.should.equal [1, 2, 3]
72
+ end.should.raise NoMethodError
73
+ end
74
+ end
75
+
76
+ context "Invoking an interface method via DRb" do
77
+ require 'drb'
78
+ before do
79
+ @door = DRb.start_service "druby://127.0.0.1:9050", Adhearsion::DrbDoor.instance
80
+ end
81
+
82
+ test "should return the proper result" do
83
+ client = DRbObject.new nil, DRb.uri
84
+ client.interface.bar.should.equal [3, 2, 1]
85
+ end
86
+
87
+ test "should raise an exception for a non-existent interface" do
88
+ client = DRbObject.new nil, DRb.uri
89
+ the_following_code do
90
+ client.interface.bad_interface.should.equal [3, 2, 1]
91
+ end.should.raise NoMethodError
92
+ end
93
+
94
+ test "should raise an exception for a non-existent method" do
95
+ client = DRbObject.new nil, DRb.uri
96
+ the_following_code do
97
+ client.interface.interface.foobar.equal [3, 2, 1]
98
+ end.should.raise NoMethodError
99
+ end
100
+
101
+ after do
102
+ DRb.stop_service
103
+ end
104
+ end