freeswitcher 0.4.2 → 0.4.3

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.
@@ -4,13 +4,22 @@ require 'fsr/listener/header_and_content_response'
4
4
  describe FSL::HeaderAndContentResponse do
5
5
  HCR = FSL::HeaderAndContentResponse
6
6
 
7
- it "is initializable with 2 hash arguments" do
7
+ before do
8
8
  header = {:foo => "bar", :jumbo => "shrimp"}
9
- content = {:response => "w00t"}
10
- hcr = HCR.new({:headers => header, :content => content})
11
- hcr.headers.should.include? :foo
12
- hcr.content.should.include? :response
9
+ content = {:response => "w00t\n"}
10
+ @hcr = HCR.new({:headers => header, :content => content})
13
11
  end
12
+
13
+ it "is initializable with 2 hash arguments" do
14
+ @hcr.headers.should.include? :foo
15
+ @hcr.content.should.include? :response
16
+ end
17
+
18
+ it "strips newlines from content values" do
19
+ @hcr.content[:response].should == "w00t"
20
+ end
21
+ end
22
+
14
23
  =begin manveru's future specs
15
24
 
16
25
  it "can be created with headers" do
@@ -45,4 +54,3 @@ describe FSL::HeaderAndContentResponse do
45
54
  end
46
55
 
47
56
  =end
48
- end
@@ -1,30 +1,39 @@
1
1
  require 'spec/helper'
2
+ require 'lib/fsr'
2
3
  require "fsr/listener"
3
4
  require "fsr/listener/inbound"
4
- gem "tmm1-em-spec"
5
5
  require "em/spec"
6
6
 
7
7
  # Bare class to use for testing
8
8
  class InboundListener < FSR::Listener::Inbound
9
9
  attr_accessor :test_event
10
10
 
11
+ # Stub error? out
12
+ def error?
13
+ false
14
+ end
15
+
11
16
  def initialize(*args)
12
17
  super(*args)
13
18
  @test_event = nil
14
19
  end
15
20
 
16
- def on_event(event)
21
+ def on_event
17
22
  recvd_event << event
18
23
  end
19
24
 
20
25
  def recvd_event
21
26
  @recvd_event ||= []
22
27
  end
28
+ end
23
29
 
30
+ class InboundListener2 < InboundListener
31
+ def before_session
32
+ add_event(:TEST_EVENT) {recvd_event << event}
33
+ end
24
34
  end
25
35
 
26
36
  describe "Testing FSR::Listener::Inbound" do
27
-
28
37
  it "defines #post_init" do
29
38
  FSR::Listener::Inbound.method_defined?(:post_init).should == true
30
39
  end
@@ -35,13 +44,12 @@ describe "Testing FSR::Listener::Inbound" do
35
44
  FSL::Inbound.del_event_hook(:CHANNEL_CREATE)
36
45
  FSL::Inbound::HOOKS.size.should == 0
37
46
  end
38
-
39
47
  end
40
48
 
41
49
  EM.describe InboundListener do
42
-
43
50
  before do
44
- @listener = InboundListener.new("test", {:auth => 'SecretPassword'})
51
+ @listener = InboundListener.new(1234, {:auth => 'SecretPassword'})
52
+ @listener2 = InboundListener2.new(1234, {:auth => 'SecretPassword'})
45
53
  end
46
54
 
47
55
  should "be able to receive an event and call the on_event callback method" do
@@ -50,8 +58,15 @@ EM.describe InboundListener do
50
58
  done
51
59
  end
52
60
 
61
+ should "be able to add custom event hooks in the pre_session" do
62
+ @listener2.receive_data("Content-Length: 22\n\nEvent-Name: TEST_EVENT\n\n")
63
+ @listener2.recvd_event.first.content[:event_name].should.equal "TEST_EVENT"
64
+ done
65
+ end
66
+
53
67
  should "be able to add custom event hooks" do
54
- FSL::Inbound.add_event_hook(:HANGUP_EVENT) {|event| @listener.test_event = event}
68
+ listener = @listener
69
+ FSL::Inbound.add_event_hook(:HANGUP_EVENT) {listener.test_event = event}
55
70
  @listener.test_event.should.equal nil
56
71
  @listener.receive_data("Content-Length: 24\n\nEvent-Name: HANGUP_EVENT\n\n")
57
72
  @listener.test_event.content[:event_name].should.equal "HANGUP_EVENT"
@@ -62,5 +77,4 @@ EM.describe InboundListener do
62
77
  @listener.auth.should.equal 'SecretPassword'
63
78
  done
64
79
  end
65
-
66
80
  end
@@ -1,12 +1,12 @@
1
1
  require "lib/fsr"
2
2
  require FSR::ROOT/".."/:spec/:helper
3
3
  require FSR::ROOT/:fsr/:listener/:outbound
4
- gem "tmm1-em-spec"
5
4
  require "em/spec"
6
5
 
7
6
  # Bare class to use for testing
8
7
  class MyListener < FSR::Listener::Outbound
9
- attr_accessor :recvd_reply, :state_machine_test
8
+ attr_accessor :recvd_reply, :state_machine_test, :state_machine_test2
9
+ attr_reader :queue
10
10
 
11
11
  def session_initiated
12
12
  end
@@ -31,6 +31,10 @@ class MyListener < FSR::Listener::Outbound
31
31
  @queue.unshift block if block_given?
32
32
  end
33
33
 
34
+ def set(var, value, &block)
35
+ @queue.unshift(block_given? ? block : lambda {})
36
+ end
37
+
34
38
  def test_state_machine
35
39
  @state_machine_test = nil
36
40
  do_something do
@@ -46,6 +50,12 @@ class MyListener < FSR::Listener::Outbound
46
50
  end
47
51
  end
48
52
 
53
+ def test_state_machine_without_blocks
54
+ answer
55
+ set("test", "test1")
56
+ set("another_one", "bites_the_dust")
57
+ end
58
+
49
59
  end
50
60
 
51
61
  # Begin testing MyListener
@@ -106,6 +116,20 @@ EM.describe MyListener do
106
116
  done
107
117
  end
108
118
 
119
+ should "use implicit blocks to 'fake' I/O blocking and wait for a response before calling the next implicit block" do
120
+ @listener.receive_data("Content-Length: 0\nEstablished-Session: session\n\n")
121
+ @listener.test_state_machine_without_blocks
122
+ @listener.queue.size.should.equal 3
123
+ @listener.receive_data("Content-Length: 3\n\nOk\n\n")
124
+ @listener.queue.size.should.equal 2
125
+ @listener.receive_data("Content-Length: 3\n\nOk\n\n")
126
+ @listener.queue.size.should.equal 1
127
+ @listener.receive_data("Content-Length: 3\n\nOk\n\n")
128
+ @listener.queue.empty?.should.equal true
129
+ done
130
+ end
131
+
132
+
109
133
  should "be able to update an existing session" do
110
134
  @listener.receive_data("Content-Length: 0\nUnique-ID: abcd-1234-efgh-5678\n\n")
111
135
  @listener.session.headers[:unique_id].should.equal "abcd-1234-efgh-5678"
data/spec/fsr/loading.rb CHANGED
@@ -4,7 +4,7 @@ require 'spec/helper'
4
4
  describe "Testing FSR module loading methods" do
5
5
  # When you add applications you must modify the expected apps_loaded behavior
6
6
  it "Loads all applications" do
7
- all_apps = [:play_and_get_digits, :uuid_dump, :uuid_setvar, :uuid_getvar, :read, :set, :transfer, :speak, :fs_sleep, :playback, :answer, :fifo, :bridge, :hangup, :conference, :fs_break, :log, :limit]
7
+ all_apps = [:play_and_get_digits, :uuid_dump, :uuid_setvar, :uuid_getvar, :read, :set, :transfer, :speak, :fs_sleep, :playback, :answer, :fifo, :bridge, :hangup, :conference, :fs_break, :log, :limit, :bind_meta_app, :execute_app]
8
8
  # Add any apps which will load to this set
9
9
  apps_loaded = FSR.load_all_applications
10
10
  apps_loaded.kind_of?(Array).should == true
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: freeswitcher
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.4.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jayson Vaughn
@@ -12,7 +12,7 @@ autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
14
 
15
- date: 2009-07-03 00:00:00 -05:00
15
+ date: 2009-11-18 00:00:00 -06:00
16
16
  default_executable:
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
@@ -25,7 +25,94 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: "0"
27
27
  version:
28
- description: &id001 |
28
+ description: "========================================================= FreeSWITCHeR Copyright (c) 2009 The Rubyists (Jayson Vaughn, Tj Vanderpoel, Michael Fellinger, Kevin Berry) Distributed under the terms of the MIT License. ========================================================== ABOUT ----- A ruby library for interacting with the \"FreeSWITCH\" (http://www.freeswitch.org) opensource telephony platform REQUIREMENTS ------------ * ruby (>= 1.8) * eventmachine (If you wish to use Outbound and Inbound listener) USAGE ----- An Outbound Event Listener Example that reads and returns DTMF input: -------------------------------------------------------------------- Simply just create a subclass of FSR::Listner::Outbound and all new calls/sessions will invoke the \"session_initiated\" callback method. <b>NOTE</b>: FSR uses blocks within the 'session_inititated' method to ensure that the next \"freeswich command\" is not executed until the previous \"Freeswitch command\" has finished. (Basically a continuation) This is kicked off by \"answer do\". #!/usr/bin/ruby require 'fsr' require 'fsr/listener/outbound' class OutboundDemo < FSR::Listener::Outbound def session_initiated exten = @session.headers[:caller_caller_id_number] FSR::Log.info \"*** Answering incoming call from #{exten}\" answer do FSR::Log.info \"***Reading DTMF from #{exten}\" read(\"/home/freeswitch/freeswitch/sounds/music/8000/sweet.wav\", 4, 10, \"input\", 7000) do |read_var| FSR::Log.info \"***Success, grabbed #{read_var.to_s.strip} from #{exten}\" # Tell the caller what they entered speak(\"Got the DTMF of: #{read_var.to_s.strip}\") do #Hangup the call hangup end end end end end FSR.start_oes! OutboundDemo, :port => 8084, :host => \"127.0.0.1\" An Inbound Event Socket Listener example using FreeSWITCHeR's hook system: -------------------------------------------------------------------------- #!/usr/bin/ruby require 'pp' require 'fsr' require \"fsr/listener/inbound\" # EXAMPLE 1 # This adds a hook on CHANNEL_CREATE events. You can also create a method to handle the event you're after. See the next example FSL::Inbound.add_event_hook(:CHANNEL_CREATE) { FSR::Log.info \"*** [#{event.content[:unique_id]}] Channel created - greetings from the hook!\" } # EXAMPLE 2 # Define a method to handle CHANNEL_HANGUP events. def custom_channel_hangup_handler(event) FSR::Log.info \"*** [#{event.content[:unique_id]}] Channel hangup. The event:\" pp event end # This adds a hook for EXAMPLE 2 FSL::Inbound.add_event_hook(:CHANNEL_HANGUP) { custom_channel_hangup_handler(event) } # Start FSR Inbound Listener FSR.start_ies!(FSL::Inbound, :host => \"localhost\", :port => 8021) An Inbound Event Socket Listener example using the on_event callback method instead of hooks: --------------------------------------------------------------------------------------------- #!/usr/bin/ruby require 'pp' require 'fsr' require \"fsr/listener/inbound\" class IesDemo < FSR::Listener::Inbound def on_event pp event.headers pp event.content[:event_name] end end FSR.start_ies!(IesDemo, :host => \"localhost\", :port => 8021, :auth => \"ClueCon\") An example of using FSR::CommandSocket to originate a new call in irb: ---------------------------------------------------------------------- irb(main):001:0> require 'fsr' => true irb(main):002:0> FSR.load_all_commands => [:sofia, :originate] irb(main):003:0> sock = FSR::CommandSocket.new => #<FSR::CommandSocket:0xb7a89104 @server=\"127.0.0.1\", @socket=#<TCPSocket:0xb7a8908c>, @port=\"8021\", @auth=\"ClueCon\"> irb(main):007:0> sock.originate(:target => 'sofia/gateway/carlos/8179395222', :endpoint => FSR::App::Bridge.new(\"user/bougyman\")).run => {\"Job-UUID\"=>\"732075a4-7dd5-4258-b124-6284a82a5ae7\", \"body\"=>\"\", \"Content-Type\"=>\"command/reply\", \"Reply-Text\"=>\"+OK Job-UUID: 732075a4-7dd5-4258-b124-6284a82a5ae7\"} SUPPORT ------- Home page at http://code.rubyists.com/projects/fs #rubyists on FreeNode"
29
+ email: FreeSWITCHeR@rubyists.com
30
+ executables: []
31
+
32
+ extensions: []
33
+
34
+ extra_rdoc_files: []
35
+
36
+ files:
37
+ - .gitignore
38
+ - AUTHORS
39
+ - CHANGELOG
40
+ - License.txt
41
+ - MANIFEST
42
+ - NEWS
43
+ - README
44
+ - Rakefile
45
+ - examples/inbound_event_socket.rb
46
+ - examples/inbound_socket_events.rb
47
+ - examples/outbound_event_socket.rb
48
+ - freeswitcher.gemspec
49
+ - lib/fsr.rb
50
+ - lib/fsr/app.rb
51
+ - lib/fsr/app/answer.rb
52
+ - lib/fsr/app/bind_meta_app.rb
53
+ - lib/fsr/app/bridge.rb
54
+ - lib/fsr/app/conference.rb
55
+ - lib/fsr/app/execute_app.rb
56
+ - lib/fsr/app/fifo.rb
57
+ - lib/fsr/app/fs_break.rb
58
+ - lib/fsr/app/fs_sleep.rb
59
+ - lib/fsr/app/hangup.rb
60
+ - lib/fsr/app/limit.rb
61
+ - lib/fsr/app/log.rb
62
+ - lib/fsr/app/play_and_get_digits.rb
63
+ - lib/fsr/app/playback.rb
64
+ - lib/fsr/app/read.rb
65
+ - lib/fsr/app/set.rb
66
+ - lib/fsr/app/speak.rb
67
+ - lib/fsr/app/transfer.rb
68
+ - lib/fsr/app/uuid_dump.rb
69
+ - lib/fsr/app/uuid_getvar.rb
70
+ - lib/fsr/app/uuid_setvar.rb
71
+ - lib/fsr/cmd.rb
72
+ - lib/fsr/cmd/calls.rb
73
+ - lib/fsr/cmd/fsctl.rb
74
+ - lib/fsr/cmd/originate.rb
75
+ - lib/fsr/cmd/sofia.rb
76
+ - lib/fsr/cmd/sofia/profile.rb
77
+ - lib/fsr/cmd/sofia/status.rb
78
+ - lib/fsr/cmd/sofia_contact.rb
79
+ - lib/fsr/cmd/status.rb
80
+ - lib/fsr/cmd/uuid_dump.rb
81
+ - lib/fsr/command_socket.rb
82
+ - lib/fsr/database.rb
83
+ - lib/fsr/database/call_limit.rb
84
+ - lib/fsr/database/core.rb
85
+ - lib/fsr/database/sofia_reg_external.rb
86
+ - lib/fsr/database/sofia_reg_internal.rb
87
+ - lib/fsr/database/voicemail_default.rb
88
+ - lib/fsr/event_socket.rb
89
+ - lib/fsr/fake_socket.rb
90
+ - lib/fsr/listener.rb
91
+ - lib/fsr/listener/header_and_content_response.rb
92
+ - lib/fsr/listener/inbound.rb
93
+ - lib/fsr/listener/inbound/event.rb
94
+ - lib/fsr/listener/mock.rb
95
+ - lib/fsr/listener/outbound.rb
96
+ - lib/fsr/model/call.rb
97
+ - lib/fsr/version.rb
98
+ - tasks/authors.rake
99
+ - tasks/bacon.rake
100
+ - tasks/changelog.rake
101
+ - tasks/copyright.rake
102
+ - tasks/gem.rake
103
+ - tasks/gem_installer.rake
104
+ - tasks/install_dependencies.rake
105
+ - tasks/manifest.rake
106
+ - tasks/release.rake
107
+ - tasks/reversion.rake
108
+ - tasks/setup.rake
109
+ - tasks/spec.rake
110
+ - tasks/yard.rake
111
+ - spec/helper.rb
112
+ - spec/fsr_listener_helper.rb
113
+ has_rdoc: false
114
+ homepage: http://code.rubyists.com/projects/fs
115
+ post_install_message: |
29
116
  =========================================================
30
117
  FreeSWITCHeR
31
118
  Copyright (c) 2009 The Rubyists (Jayson Vaughn, Tj Vanderpoel, Michael Fellinger, Kevin Berry)
@@ -50,7 +137,7 @@ description: &id001 |
50
137
  Simply just create a subclass of FSR::Listner::Outbound and all
51
138
  new calls/sessions will invoke the "session_initiated" callback method.
52
139
 
53
- <b>NOTE</b>: FSR uses blocks within the 'session_inititated' method to ensure that the next "freeswich command" is not executed until the previous "Freeswitch command" has finished. This is kicked off by "answer do"
140
+ <b>NOTE</b>: FSR uses blocks within the 'session_inititated' method to ensure that the next "freeswich command" is not executed until the previous "Freeswitch command" has finished. (Basically a continuation) This is kicked off by "answer do".
54
141
 
55
142
  #!/usr/bin/ruby
56
143
  require 'fsr'
@@ -65,9 +152,9 @@ description: &id001 |
65
152
  answer do
66
153
  FSR::Log.info "***Reading DTMF from #{exten}"
67
154
  read("/home/freeswitch/freeswitch/sounds/music/8000/sweet.wav", 4, 10, "input", 7000) do |read_var|
68
- FSR::Log.info "***Success, grabbed #{read_var.strip} from #{exten}"
155
+ FSR::Log.info "***Success, grabbed #{read_var.to_s.strip} from #{exten}"
69
156
  # Tell the caller what they entered
70
- speak("Got the DTMF of: #{read_var}") do
157
+ speak("Got the DTMF of: #{read_var.to_s.strip}") do
71
158
  #Hangup the call
72
159
  hangup
73
160
  end
@@ -90,7 +177,7 @@ description: &id001 |
90
177
 
91
178
  # EXAMPLE 1
92
179
  # This adds a hook on CHANNEL_CREATE events. You can also create a method to handle the event you're after. See the next example
93
- FSL::Inbound.add_event_hook(:CHANNEL_CREATE) {|event| FSR::Log.info "*** [#{event.content[:unique_id]}] Channel created - greetings from the hook!" }
180
+ FSL::Inbound.add_event_hook(:CHANNEL_CREATE) { FSR::Log.info "*** [#{event.content[:unique_id]}] Channel created - greetings from the hook!" }
94
181
 
95
182
  # EXAMPLE 2
96
183
  # Define a method to handle CHANNEL_HANGUP events.
@@ -100,7 +187,7 @@ description: &id001 |
100
187
  end
101
188
 
102
189
  # This adds a hook for EXAMPLE 2
103
- FSL::Inbound.add_event_hook(:CHANNEL_HANGUP) {|event| custom_channel_hangup_handler(event) }
190
+ FSL::Inbound.add_event_hook(:CHANNEL_HANGUP) { custom_channel_hangup_handler(event) }
104
191
 
105
192
 
106
193
  # Start FSR Inbound Listener
@@ -118,7 +205,7 @@ description: &id001 |
118
205
 
119
206
  class IesDemo < FSR::Listener::Inbound
120
207
 
121
- def on_event(event)
208
+ def on_event
122
209
  pp event.headers
123
210
  pp event.content[:event_name]
124
211
  end
@@ -150,93 +237,6 @@ description: &id001 |
150
237
  Home page at http://code.rubyists.com/projects/fs
151
238
  #rubyists on FreeNode
152
239
 
153
- email: FreeSWITCHeR@rubyists.com
154
- executables: []
155
-
156
- extensions: []
157
-
158
- extra_rdoc_files: []
159
-
160
- files:
161
- - .gitignore
162
- - AUTHORS
163
- - CHANGELOG
164
- - License.txt
165
- - MANIFEST
166
- - NEWS
167
- - README
168
- - Rakefile
169
- - examples/inbound_event_socket.rb
170
- - examples/inbound_socket_events.rb
171
- - examples/outbound_event_socket.rb
172
- - freeswitcher.gemspec
173
- - lib/fsr.rb
174
- - lib/fsr/app.rb
175
- - lib/fsr/app/answer.rb
176
- - lib/fsr/app/bridge.rb
177
- - lib/fsr/app/conference.rb
178
- - lib/fsr/app/fifo.rb
179
- - lib/fsr/app/fs_break.rb
180
- - lib/fsr/app/fs_sleep.rb
181
- - lib/fsr/app/hangup.rb
182
- - lib/fsr/app/limit.rb
183
- - lib/fsr/app/log.rb
184
- - lib/fsr/app/play_and_get_digits.rb
185
- - lib/fsr/app/playback.rb
186
- - lib/fsr/app/read.rb
187
- - lib/fsr/app/set.rb
188
- - lib/fsr/app/speak.rb
189
- - lib/fsr/app/transfer.rb
190
- - lib/fsr/app/uuid_dump.rb
191
- - lib/fsr/app/uuid_getvar.rb
192
- - lib/fsr/app/uuid_setvar.rb
193
- - lib/fsr/cmd.rb
194
- - lib/fsr/cmd/calls.rb
195
- - lib/fsr/cmd/fsctl.rb
196
- - lib/fsr/cmd/originate.rb
197
- - lib/fsr/cmd/sofia.rb
198
- - lib/fsr/cmd/sofia/profile.rb
199
- - lib/fsr/cmd/sofia/status.rb
200
- - lib/fsr/cmd/sofia_contact.rb
201
- - lib/fsr/cmd/status.rb
202
- - lib/fsr/cmd/uuid_dump.rb
203
- - lib/fsr/command_socket.rb
204
- - lib/fsr/database.rb
205
- - lib/fsr/database/call_limit.rb
206
- - lib/fsr/database/core.rb
207
- - lib/fsr/database/sofia_reg_external.rb
208
- - lib/fsr/database/sofia_reg_internal.rb
209
- - lib/fsr/database/voicemail_default.rb
210
- - lib/fsr/event_socket.rb
211
- - lib/fsr/fake_socket.rb
212
- - lib/fsr/listener.rb
213
- - lib/fsr/listener/header_and_content_response.rb
214
- - lib/fsr/listener/inbound.rb
215
- - lib/fsr/listener/inbound/event.rb
216
- - lib/fsr/listener/mock.rb
217
- - lib/fsr/listener/outbound.rb
218
- - lib/fsr/model/call.rb
219
- - lib/fsr/version.rb
220
- - tasks/authors.rake
221
- - tasks/bacon.rake
222
- - tasks/changelog.rake
223
- - tasks/copyright.rake
224
- - tasks/gem.rake
225
- - tasks/gem_installer.rake
226
- - tasks/install_dependencies.rake
227
- - tasks/manifest.rake
228
- - tasks/release.rake
229
- - tasks/reversion.rake
230
- - tasks/setup.rake
231
- - tasks/spec.rake
232
- - tasks/yard.rake
233
- - spec/helper.rb
234
- - spec/fsr_listener_helper.rb
235
- has_rdoc: true
236
- homepage: http://code.rubyists.com/projects/fs
237
- licenses: []
238
-
239
- post_install_message: *id001
240
240
  rdoc_options: []
241
241
 
242
242
  require_paths:
@@ -256,15 +256,17 @@ required_rubygems_version: !ruby/object:Gem::Requirement
256
256
  requirements: []
257
257
 
258
258
  rubyforge_project: freeswitcher
259
- rubygems_version: 1.3.4
259
+ rubygems_version: 1.3.1
260
260
  signing_key:
261
- specification_version: 3
261
+ specification_version: 2
262
262
  summary: A library for interacting with the "FreeSWITCH":http://freeswitch.org telephony platform
263
263
  test_files:
264
264
  - spec/fsr/app.rb
265
265
  - spec/fsr/app/answer.rb
266
+ - spec/fsr/app/bind_meta_app.rb
266
267
  - spec/fsr/app/bridge.rb
267
268
  - spec/fsr/app/conference.rb
269
+ - spec/fsr/app/execute_app.rb
268
270
  - spec/fsr/app/fifo.rb
269
271
  - spec/fsr/app/fs_break.rb
270
272
  - spec/fsr/app/fs_sleep.rb