adhearsion 2.1.3 → 2.2.0

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 (61) hide show
  1. data/CHANGELOG.md +87 -0
  2. data/Guardfile +1 -1
  3. data/Rakefile +1 -2
  4. data/adhearsion.gemspec +1 -1
  5. data/features/cli_create.feature +1 -0
  6. data/features/step_definitions/cli_steps.rb +0 -10
  7. data/lib/adhearsion.rb +11 -0
  8. data/lib/adhearsion/call.rb +27 -12
  9. data/lib/adhearsion/call_controller.rb +1 -1
  10. data/lib/adhearsion/call_controller/dial.rb +3 -1
  11. data/lib/adhearsion/call_controller/input.rb +4 -4
  12. data/lib/adhearsion/call_controller/menu_dsl.rb +1 -0
  13. data/lib/adhearsion/call_controller/menu_dsl/array_match_calculator.rb +26 -0
  14. data/lib/adhearsion/call_controller/menu_dsl/fixnum_match_calculator.rb +2 -14
  15. data/lib/adhearsion/call_controller/menu_dsl/string_match_calculator.rb +6 -6
  16. data/lib/adhearsion/call_controller/output.rb +20 -14
  17. data/lib/adhearsion/call_controller/output/abstract_player.rb +5 -5
  18. data/lib/adhearsion/call_controller/output/formatter.rb +68 -68
  19. data/lib/adhearsion/call_controller/record.rb +91 -28
  20. data/lib/adhearsion/call_controller/utility.rb +12 -5
  21. data/lib/adhearsion/calls.rb +1 -1
  22. data/lib/adhearsion/configuration.rb +4 -0
  23. data/lib/adhearsion/events.rb +2 -1
  24. data/lib/adhearsion/generators/app/app_generator.rb +2 -2
  25. data/lib/adhearsion/generators/app/templates/Gemfile.erb +4 -0
  26. data/lib/adhearsion/generators/app/templates/Rakefile +5 -0
  27. data/lib/adhearsion/generators/app/templates/lib/simon_game.rb +3 -0
  28. data/lib/adhearsion/generators/app/templates/rspec +2 -0
  29. data/lib/adhearsion/generators/app/templates/spec/call_controllers/simon_game_spec.rb +142 -0
  30. data/lib/adhearsion/generators/controller/templates/lib/controller.rb +1 -1
  31. data/lib/adhearsion/generators/controller/templates/spec/controller_spec.rb +2 -0
  32. data/lib/adhearsion/initializer.rb +3 -2
  33. data/lib/adhearsion/outbound_call.rb +5 -2
  34. data/lib/adhearsion/router/route.rb +13 -2
  35. data/lib/adhearsion/rspec.rb +1 -1
  36. data/lib/adhearsion/statistics.rb +138 -0
  37. data/lib/adhearsion/tasks/environment.rb +1 -1
  38. data/lib/adhearsion/version.rb +1 -1
  39. data/spec/adhearsion/call_controller/dial_spec.rb +26 -0
  40. data/spec/adhearsion/call_controller/input_spec.rb +13 -1
  41. data/spec/adhearsion/call_controller/menu_dsl/array_match_calculator_spec.rb +76 -0
  42. data/spec/adhearsion/call_controller/menu_dsl/fixnum_match_calculator_spec.rb +8 -6
  43. data/spec/adhearsion/call_controller/menu_dsl/range_match_calculator_spec.rb +4 -4
  44. data/spec/adhearsion/call_controller/menu_dsl/string_match_calculator_spec.rb +6 -6
  45. data/spec/adhearsion/call_controller/output/formatter_spec.rb +3 -5
  46. data/spec/adhearsion/call_controller/output_spec.rb +59 -25
  47. data/spec/adhearsion/call_controller/record_spec.rb +123 -2
  48. data/spec/adhearsion/call_controller/utility_spec.rb +31 -11
  49. data/spec/adhearsion/call_spec.rb +77 -36
  50. data/spec/adhearsion/calls_spec.rb +13 -0
  51. data/spec/adhearsion/initializer_spec.rb +7 -0
  52. data/spec/adhearsion/outbound_call_spec.rb +14 -0
  53. data/spec/adhearsion/punchblock_plugin_spec.rb +5 -2
  54. data/spec/adhearsion/router/openended_route_spec.rb +2 -1
  55. data/spec/adhearsion/router/route_spec.rb +9 -1
  56. data/spec/adhearsion/router/unaccepting_route_spec.rb +2 -1
  57. data/spec/adhearsion/statistics/dump_spec.rb +38 -0
  58. data/spec/adhearsion/statistics_spec.rb +61 -0
  59. data/spec/adhearsion_spec.rb +21 -1
  60. data/spec/spec_helper.rb +2 -0
  61. metadata +16 -7
@@ -83,6 +83,19 @@ module Adhearsion
83
83
  end
84
84
  end
85
85
 
86
+ describe "when a call in the collection terminates cleanly" do
87
+ it "is removed from the collection" do
88
+ call_id = call.id
89
+ size_before = subject.size
90
+
91
+ subject << call
92
+ call.terminate
93
+
94
+ subject.size.should be == size_before
95
+ subject[call_id].should be_nil
96
+ end
97
+ end
98
+
86
99
  describe "when a call in the collection crashes" do
87
100
  let(:wrapped_object) { call.wrapped_object }
88
101
 
@@ -34,6 +34,13 @@ describe Adhearsion::Initializer do
34
34
  end
35
35
  end
36
36
 
37
+ it "should start the stats aggregator" do
38
+ flexmock(Adhearsion).should_receive(:statistics).at_least.once
39
+ stub_behavior_for_initializer_with_no_path_changing_behavior do
40
+ Adhearsion::Initializer.start
41
+ end
42
+ end
43
+
37
44
  it "should create a pid file in the app's path when given 'true' as the pid_file hash key argument" do
38
45
  stub_behavior_for_initializer_with_no_path_changing_behavior do
39
46
  flexmock(File).should_receive(:open).with(File.join(path, 'adhearsion.pid'), 'w', Proc).at_least.once
@@ -58,6 +58,15 @@ module Adhearsion
58
58
  call << Punchblock::Event::Answered.new
59
59
  sleep 0.5
60
60
  end
61
+
62
+ context "with controller metadata specified" do
63
+ it "should set the metadata on the controller" do
64
+ flexmock(mock_call).should_receive(:dial).once.with(to, {})
65
+ flexmock(mock_call).should_receive(:execute_controller).once.with(FlexMock.on { |c| c.is_a?(controller) && c.metadata == {:foo => 'bar'}}, Proc)
66
+ call = OutboundCall.originate to, :controller => controller, :controller_metadata => {:foo => 'bar'}
67
+ call << Punchblock::Event::Answered.new
68
+ end
69
+ end
61
70
  end
62
71
 
63
72
  context "when given a block" do
@@ -137,6 +146,11 @@ module Adhearsion
137
146
  Adhearsion.active_calls[call_id].should be subject
138
147
  end
139
148
 
149
+ it "should immediately fire the :call_dialed event giving the call" do
150
+ flexmock(Adhearsion::Events).should_receive(:trigger_immediately).once.with(:call_dialed, subject)
151
+ subject.dial to, :from => from
152
+ end
153
+
140
154
  it "should not modify the provided options" do
141
155
  options = {:from => from}
142
156
  original_options = Marshal.load(Marshal.dump(options))
@@ -13,16 +13,19 @@ module Adhearsion
13
13
  describe '#execute_component' do
14
14
  let(:message) { Punchblock::Command::Accept.new }
15
15
  let(:response) { :foo }
16
- let(:mock_client) { flexmock 'Client', :execute_command => true }
16
+ let(:mock_client) { flexmock 'Client' }
17
+
18
+ let(:execute_expectation) { PunchblockPlugin.client.should_receive(:execute_command).once }
17
19
 
18
20
  before do
19
21
  PunchblockPlugin::Initializer.client = mock_client
20
22
  flexmock message, :execute! => true
21
23
  message.response = response
24
+ execute_expectation
22
25
  end
23
26
 
24
27
  it "writes a command to the client" do
25
- flexmock(PunchblockPlugin.client).should_receive(:execute_command).once.with(message, :async => true)
28
+ execute_expectation.with(message, :async => true)
26
29
  PunchblockPlugin.execute_component message
27
30
  end
28
31
 
@@ -26,7 +26,8 @@ module Adhearsion
26
26
 
27
27
  it "should accept the call" do
28
28
  flexmock(call).should_receive(:accept).once
29
- route.dispatch call
29
+ route.dispatch call, lambda { latch.countdown! }
30
+ latch.wait(2).should be true
30
31
  end
31
32
 
32
33
  it "should instruct the call to use an instance of the controller" do
@@ -115,9 +115,17 @@ module Adhearsion
115
115
  let(:controller) { CallController }
116
116
  let(:route) { Route.new 'foobar', controller }
117
117
 
118
+ it "should immediately fire the :call_routed event giving the call and route" do
119
+ flexmock(Adhearsion::Events).should_receive(:trigger_immediately).once.with(:call_routed, call: call, route: route)
120
+ flexmock(call).should_receive(:hangup).once
121
+ route.dispatch call, lambda { latch.countdown! }
122
+ latch.wait(2).should be true
123
+ end
124
+
118
125
  it "should accept the call" do
119
126
  flexmock(call).should_receive(:accept).once
120
- route.dispatch call
127
+ route.dispatch call, lambda { latch.countdown! }
128
+ latch.wait(2).should be true
121
129
  end
122
130
 
123
131
  it "should instruct the call to use an instance of the controller" do
@@ -26,7 +26,8 @@ module Adhearsion
26
26
 
27
27
  it "should not accept the call" do
28
28
  flexmock(call).should_receive(:accept).never
29
- route.dispatch call
29
+ route.dispatch call, lambda { latch.countdown! }
30
+ latch.wait(2).should be true
30
31
  end
31
32
 
32
33
  it "should instruct the call to use an instance of the controller" do
@@ -0,0 +1,38 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Adhearsion::Statistics::Dump do
6
+ it "should have a timestamp" do
7
+ origin_time = Time.now
8
+ dump = Adhearsion::Statistics::Dump.new timestamp: origin_time
9
+ dump.timestamp.should == origin_time
10
+ end
11
+
12
+ it "should have a hash of call counts" do
13
+ counts = {dialed: 0, offered: 0, routed: 0, rejected: 0, active: 0}
14
+ dump = Adhearsion::Statistics::Dump.new call_counts: counts
15
+ dump.call_counts.should == counts
16
+ end
17
+
18
+ it "should have a hash of call counts by route" do
19
+ counts = {"my route" => 1, "your route" => 10}
20
+ dump = Adhearsion::Statistics::Dump.new calls_by_route: counts
21
+ dump.calls_by_route.should == counts
22
+ end
23
+
24
+ it "should be equal to another dump if they share the same timestamp" do
25
+ origin_time = Time.now
26
+ dump1 = Adhearsion::Statistics::Dump.new timestamp: origin_time
27
+ dump2 = Adhearsion::Statistics::Dump.new timestamp: origin_time
28
+ dump1.should be == dump2
29
+ end
30
+
31
+ it "should compare based on the timestamp" do
32
+ origin_time = Time.now
33
+ dump1 = Adhearsion::Statistics::Dump.new timestamp: origin_time
34
+ dump2 = Adhearsion::Statistics::Dump.new timestamp: (origin_time + 1)
35
+ dump1.should be < dump2
36
+ dump2.should be > dump1
37
+ end
38
+ end
@@ -0,0 +1,61 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Adhearsion::Statistics do
6
+ before do
7
+ subject.setup_event_handlers
8
+ flexmock(Adhearsion.active_calls).should_receive(:count).and_return 0
9
+ end
10
+
11
+ after do
12
+ Adhearsion.router = nil
13
+ end
14
+
15
+ describe "#dump" do
16
+ it "should report 0 calls offered, routed, rejected, active & completed" do
17
+ subject.dump.call_counts.should == {dialed: 0, offered: 0, routed: 0, rejected: 0, active: 0}
18
+ end
19
+
20
+ it "should report 0 calls for each route in the router" do
21
+ subject.dump.calls_by_route.should == {}
22
+ Adhearsion.router.route 'your route', Adhearsion::CallController
23
+ Adhearsion.router.route 'my route', Adhearsion::CallController
24
+ subject.dump.calls_by_route.should == {'your route' => 0, 'my route' => 0}
25
+ end
26
+ end
27
+
28
+ it "should listen for dialed call events and increment the dialed call count" do
29
+ Adhearsion::Events.trigger_immediately :call_dialed, :foo_call
30
+ subject.dump.call_counts.should == {dialed: 1, offered: 0, routed: 0, rejected: 0, active: 0}
31
+ end
32
+
33
+ it "should listen for call offer events and increment the offered call count" do
34
+ Adhearsion::Events.trigger_immediately :punchblock, Punchblock::Event::Offer.new
35
+ subject.dump.call_counts.should == {dialed: 0, offered: 1, routed: 0, rejected: 0, active: 0}
36
+ end
37
+
38
+ context "when call_routed events are triggered" do
39
+ let(:route) { Adhearsion::Router::Route.new('my route') }
40
+
41
+ before do
42
+ Adhearsion.router.route 'your route', Adhearsion::CallController
43
+ Adhearsion.router.route 'my route', Adhearsion::CallController
44
+
45
+ Adhearsion::Events.trigger_immediately :call_routed, call: :foo, route: route
46
+ end
47
+
48
+ it "should increment the routed call count" do
49
+ subject.dump.call_counts.should == {dialed: 0, offered: 0, routed: 1, rejected: 0, active: 0}
50
+ end
51
+
52
+ it "should increment the calls_by_route counter for the route matched" do
53
+ subject.dump.calls_by_route.should == {'your route' => 0, 'my route' => 1}
54
+ end
55
+ end
56
+
57
+ it "should listen for rejected call events and increment the rejected call count" do
58
+ Adhearsion::Events.trigger_immediately :call_rejected, call: :foo, reason: :bar
59
+ subject.dump.call_counts.should == {dialed: 0, offered: 0, routed: 0, rejected: 1, active: 0}
60
+ end
61
+ end
@@ -14,7 +14,7 @@ describe Adhearsion do
14
14
  Adhearsion.config[:platform].root.should be_nil
15
15
  end
16
16
  end
17
-
17
+
18
18
  describe "#root" do
19
19
  it "should return the set root" do
20
20
  Adhearsion.root = "./"
@@ -92,6 +92,26 @@ describe Adhearsion do
92
92
  end
93
93
  end
94
94
 
95
+ describe "#statistics" do
96
+ it "should be a statistics aggregator" do
97
+ Adhearsion.statistics.should be_a Adhearsion::Statistics
98
+ end
99
+
100
+ it "should return the same instance each time" do
101
+ Adhearsion.statistics.should be Adhearsion.statistics
102
+ end
103
+
104
+ it "should create a new aggregator if the existing one dies" do
105
+ original = Adhearsion.statistics
106
+ original.terminate
107
+ original.should_not be_alive
108
+
109
+ current = Adhearsion.statistics
110
+ current.should be_alive
111
+ current.should_not be original
112
+ end
113
+ end
114
+
95
115
  describe "#status" do
96
116
  it "should be the process status name" do
97
117
  Adhearsion.status.should be == :booting
@@ -1,5 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
+ $testing = true
4
+
3
5
  unless ENV['SKIP_RCOV']
4
6
  require 'simplecov'
5
7
  require 'simplecov-rcov'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: adhearsion
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.3
4
+ version: 2.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2012-10-11 00:00:00.000000000 Z
15
+ date: 2012-12-17 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: activesupport
@@ -171,7 +171,7 @@ dependencies:
171
171
  requirements:
172
172
  - - ~>
173
173
  - !ruby/object:Gem::Version
174
- version: '1.1'
174
+ version: '1.5'
175
175
  type: :runtime
176
176
  prerelease: false
177
177
  version_requirements: !ruby/object:Gem::Requirement
@@ -179,7 +179,7 @@ dependencies:
179
179
  requirements:
180
180
  - - ~>
181
181
  - !ruby/object:Gem::Version
182
- version: '1.1'
182
+ version: '1.5'
183
183
  - !ruby/object:Gem::Dependency
184
184
  name: logging
185
185
  requirement: !ruby/object:Gem::Requirement
@@ -493,6 +493,7 @@ files:
493
493
  - lib/adhearsion/call_controller/dial.rb
494
494
  - lib/adhearsion/call_controller/input.rb
495
495
  - lib/adhearsion/call_controller/menu_dsl.rb
496
+ - lib/adhearsion/call_controller/menu_dsl/array_match_calculator.rb
496
497
  - lib/adhearsion/call_controller/menu_dsl/calculated_match.rb
497
498
  - lib/adhearsion/call_controller/menu_dsl/calculated_match_collection.rb
498
499
  - lib/adhearsion/call_controller/menu_dsl/fixnum_match_calculator.rb
@@ -533,6 +534,7 @@ files:
533
534
  - lib/adhearsion/generators/app/templates/lib/simon_game.rb
534
535
  - lib/adhearsion/generators/app/templates/rspec
535
536
  - lib/adhearsion/generators/app/templates/script/ahn
537
+ - lib/adhearsion/generators/app/templates/spec/call_controllers/simon_game_spec.rb
536
538
  - lib/adhearsion/generators/app/templates/spec/spec_helper.rb
537
539
  - lib/adhearsion/generators/controller/controller_generator.rb
538
540
  - lib/adhearsion/generators/controller/templates/lib/controller.rb
@@ -567,6 +569,7 @@ files:
567
569
  - lib/adhearsion/router/unaccepting_route.rb
568
570
  - lib/adhearsion/rspec.rb
569
571
  - lib/adhearsion/script_ahn_loader.rb
572
+ - lib/adhearsion/statistics.rb
570
573
  - lib/adhearsion/tasks.rb
571
574
  - lib/adhearsion/tasks/configuration.rb
572
575
  - lib/adhearsion/tasks/debugging.rb
@@ -576,6 +579,7 @@ files:
576
579
  - pre-commit
577
580
  - spec/adhearsion/call_controller/dial_spec.rb
578
581
  - spec/adhearsion/call_controller/input_spec.rb
582
+ - spec/adhearsion/call_controller/menu_dsl/array_match_calculator_spec.rb
579
583
  - spec/adhearsion/call_controller/menu_dsl/calculated_match_collection_spec.rb
580
584
  - spec/adhearsion/call_controller/menu_dsl/calculated_match_spec.rb
581
585
  - spec/adhearsion/call_controller/menu_dsl/fixnum_match_calculator_spec.rb
@@ -609,6 +613,8 @@ files:
609
613
  - spec/adhearsion/router/route_spec.rb
610
614
  - spec/adhearsion/router/unaccepting_route_spec.rb
611
615
  - spec/adhearsion/router_spec.rb
616
+ - spec/adhearsion/statistics/dump_spec.rb
617
+ - spec/adhearsion/statistics_spec.rb
612
618
  - spec/adhearsion_spec.rb
613
619
  - spec/capture_warnings.rb
614
620
  - spec/spec_helper.rb
@@ -630,7 +636,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
630
636
  version: '0'
631
637
  segments:
632
638
  - 0
633
- hash: -4325641181526579229
639
+ hash: -4557802099463492271
634
640
  required_rubygems_version: !ruby/object:Gem::Requirement
635
641
  none: false
636
642
  requirements:
@@ -639,10 +645,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
639
645
  version: '0'
640
646
  segments:
641
647
  - 0
642
- hash: -4325641181526579229
648
+ hash: -4557802099463492271
643
649
  requirements: []
644
650
  rubyforge_project:
645
- rubygems_version: 1.8.23
651
+ rubygems_version: 1.8.24
646
652
  signing_key:
647
653
  specification_version: 3
648
654
  summary: Adhearsion, open-source telephony development framework
@@ -664,6 +670,7 @@ test_files:
664
670
  - features/support/utils.rb
665
671
  - spec/adhearsion/call_controller/dial_spec.rb
666
672
  - spec/adhearsion/call_controller/input_spec.rb
673
+ - spec/adhearsion/call_controller/menu_dsl/array_match_calculator_spec.rb
667
674
  - spec/adhearsion/call_controller/menu_dsl/calculated_match_collection_spec.rb
668
675
  - spec/adhearsion/call_controller/menu_dsl/calculated_match_spec.rb
669
676
  - spec/adhearsion/call_controller/menu_dsl/fixnum_match_calculator_spec.rb
@@ -697,6 +704,8 @@ test_files:
697
704
  - spec/adhearsion/router/route_spec.rb
698
705
  - spec/adhearsion/router/unaccepting_route_spec.rb
699
706
  - spec/adhearsion/router_spec.rb
707
+ - spec/adhearsion/statistics/dump_spec.rb
708
+ - spec/adhearsion/statistics_spec.rb
700
709
  - spec/adhearsion_spec.rb
701
710
  - spec/capture_warnings.rb
702
711
  - spec/spec_helper.rb