csd 0.1.9 → 0.1.10
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.
- data/.gitignore +5 -1
- data/Rakefile +7 -7
- data/VERSION +1 -1
- data/bin/ai +1 -1
- data/csd.gemspec +21 -9
- data/lib/csd.rb +15 -8
- data/lib/csd/application/decklink.rb +27 -0
- data/lib/csd/application/decklink/about.yml +7 -0
- data/lib/csd/application/decklink/base.rb +62 -0
- data/lib/csd/application/default.rb +5 -1
- data/lib/csd/application/default/base.rb +10 -0
- data/lib/csd/application/minisip.rb +8 -5
- data/lib/csd/application/minisip/about.yml +1 -1
- data/lib/csd/application/minisip/base.rb +29 -90
- data/lib/csd/application/minisip/component.rb +8 -0
- data/lib/csd/application/minisip/component/core.rb +288 -0
- data/lib/csd/application/minisip/component/ffmpeg.rb +78 -0
- data/lib/csd/application/minisip/component/gnome.rb +48 -0
- data/lib/csd/application/minisip/component/hdviper.rb +49 -0
- data/lib/csd/application/minisip/component/plugins.rb +53 -0
- data/lib/csd/application/minisip/component/x264.rb +42 -0
- data/lib/csd/application/minisip/error.rb +11 -5
- data/lib/csd/application/minisip/options/common.rb +4 -4
- data/lib/csd/application/minisip/options/compile.rb +10 -16
- data/lib/csd/application/minisip/unix.rb +19 -159
- data/lib/csd/application/minisip/unix/darwin.rb +1 -11
- data/lib/csd/application/minisip/unix/linux.rb +1 -1
- data/lib/csd/application/minisip/unix/linux/debian.rb +6 -14
- data/lib/csd/application/minisip/unix/linux/debian/ubuntu10.rb +6 -4
- data/lib/csd/applications.rb +16 -21
- data/lib/csd/commands.rb +34 -7
- data/lib/csd/error.rb +27 -11
- data/lib/csd/extensions/core/kernel.rb +9 -19
- data/lib/csd/extensions/core/object.rb +1 -0
- data/lib/csd/extensions/core/string.rb +1 -1
- data/lib/csd/extensions/gem/platform.rb +9 -3
- data/lib/csd/options_parser.rb +3 -3
- data/lib/csd/user_interface/base.rb +8 -5
- data/lib/csd/user_interface/cli.rb +9 -1
- data/lib/csd/user_interface/silent.rb +7 -4
- data/lib/csd/vendor/zentest/zentest_assertions.rb +39 -35
- data/test/application/test_minisip.rb +65 -26
- data/test/functional/test_applications.rb +4 -4
- data/test/functional/test_commands.rb +26 -2
- data/test/helper.rb +9 -5
- data/test/unit/test_pathname.rb +1 -1
- data/test/unit/test_platform.rb +30 -0
- metadata +18 -6
|
@@ -6,14 +6,14 @@ module CSD
|
|
|
6
6
|
module Minisip
|
|
7
7
|
class Ubuntu10 < Debian
|
|
8
8
|
|
|
9
|
-
def
|
|
9
|
+
def after_aptitude
|
|
10
10
|
fix_ubuntu_10_04
|
|
11
|
-
exit if Options.only_fix_giomm
|
|
12
11
|
super
|
|
13
12
|
end
|
|
14
13
|
|
|
15
14
|
def fix_ubuntu_10_04
|
|
16
|
-
|
|
15
|
+
UI.info "Fixing broken Debian libraries (Ubuntu 10.04 only)".green.bold
|
|
16
|
+
if Path.giomm_header_backup.file? and !Options.reveal
|
|
17
17
|
UI.warn "giomm-2.4 seems to be fixed already, I won't touch it now. Delete #{Path.giomm_header_backup.enquote} to enforce it."
|
|
18
18
|
else
|
|
19
19
|
Path.new_giomm_header = File.join(Dir.mktmpdir, 'giomm.h')
|
|
@@ -22,11 +22,13 @@ module CSD
|
|
|
22
22
|
r.replace '#include <giomm/socket.h>', "/* ----- AI COMMENTING OUT START ----- \n#include <giomm/socket.h>"
|
|
23
23
|
r.replace '#include <giomm/tcpconnection.h>', "#include <giomm/tcpconnection.h>\n ----- AI COMMENTING OUT END ----- */"
|
|
24
24
|
end
|
|
25
|
+
# We cannot use Cmd.copy here, because Cmd.copy has no superuser privileges.
|
|
26
|
+
# And since we are for sure on Ubuntu, these commands will work.
|
|
25
27
|
Cmd.run("sudo cp #{Path.giomm_header} #{Path.giomm_header_backup}")
|
|
26
28
|
Cmd.run("sudo cp #{Path.new_giomm_header} #{Path.giomm_header}")
|
|
27
29
|
end
|
|
28
30
|
end
|
|
29
|
-
|
|
31
|
+
|
|
30
32
|
end
|
|
31
33
|
end
|
|
32
34
|
end
|
data/lib/csd/applications.rb
CHANGED
|
@@ -7,54 +7,49 @@ module CSD
|
|
|
7
7
|
# A convenience wrapper to get information about the available applications
|
|
8
8
|
#
|
|
9
9
|
class Applications
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
# Returns the application module instance of +app_name+. Returns +nil+ if the application could not be found or loaded.
|
|
12
12
|
#
|
|
13
13
|
def self.find(app_name)
|
|
14
14
|
return nil if app_name.to_s.empty?
|
|
15
15
|
begin
|
|
16
|
-
UI.debug "
|
|
16
|
+
UI.debug "#{self}.find got a request to see whether `#{app_name}´ is a valid application or not"
|
|
17
17
|
require File.join(Path.applications, app_name.to_s)
|
|
18
|
-
UI.debug "
|
|
18
|
+
UI.debug "#{self}.find tries to initialize the loaded application `#{app_name}´ now"
|
|
19
19
|
"CSD::Application::#{app_name.to_s.camelize}".constantize
|
|
20
20
|
rescue LoadError => e
|
|
21
|
-
UI.debug "
|
|
22
|
-
UI.debug " Reason: #{e}"
|
|
21
|
+
UI.debug "#{self}.find could not load `#{app_name}´ in #{e.to_s.gsub('no such file to load -- ', '').enquote}"
|
|
23
22
|
nil
|
|
24
23
|
end
|
|
25
24
|
end
|
|
26
|
-
|
|
25
|
+
|
|
26
|
+
# This method returns instantiated modules of all valid applications in an +Array+ or in a block.
|
|
27
|
+
#
|
|
27
28
|
def self.all(&block)
|
|
28
29
|
result = []
|
|
29
30
|
Dir.directories(Path.applications) do |dir|
|
|
30
31
|
next if dir == 'default'
|
|
31
|
-
UI.debug "Applications.all: Identified application directory `#{dir}´."
|
|
32
32
|
if app = find(dir)
|
|
33
|
-
UI.debug "Applications.all: The application `#{dir}´ is valid."
|
|
34
33
|
block_given? ? yield(app) : result << app
|
|
35
34
|
end
|
|
36
35
|
end
|
|
37
36
|
result
|
|
38
37
|
end
|
|
39
38
|
|
|
40
|
-
|
|
41
|
-
list.include?(name)
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
# This method identifies the desired application and initializes it in to +@@current+.
|
|
45
|
-
# It is meant to be very robust, we expect the application to be any one of the first three arguments.
|
|
39
|
+
# This method holds the desired application and initializes its module into +@@current+.
|
|
46
40
|
#
|
|
47
41
|
def self.current
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
42
|
+
# In testmode we don't want to perform caching
|
|
43
|
+
return choose_current if Options.testmode
|
|
44
|
+
# Otherwise we choose and cache the current application module here
|
|
45
|
+
@@current ||= choose_current
|
|
51
46
|
end
|
|
52
47
|
|
|
53
|
-
#
|
|
48
|
+
# This method identifies the desired application. No caching takes place here.
|
|
49
|
+
# It is meant to be very robust, we expect the application to be any one of the first three arguments.
|
|
54
50
|
#
|
|
55
|
-
def self.
|
|
56
|
-
|
|
57
|
-
current
|
|
51
|
+
def self.choose_current
|
|
52
|
+
Applications.find(ARGV.first) || Applications.find(ARGV.second) || Applications.find(ARGV.third)
|
|
58
53
|
end
|
|
59
54
|
|
|
60
55
|
end
|
data/lib/csd/commands.rb
CHANGED
|
@@ -87,6 +87,31 @@ module CSD
|
|
|
87
87
|
result
|
|
88
88
|
end
|
|
89
89
|
|
|
90
|
+
# Creates a new file and writes content to it. Truncates the file if it already had content.
|
|
91
|
+
#
|
|
92
|
+
def touch_and_replace_content(target, content='', params={})
|
|
93
|
+
default_params = { :die_on_failure => true, :internal => false }
|
|
94
|
+
params = default_params.merge(params)
|
|
95
|
+
target = target.pathnamify
|
|
96
|
+
result = CommandResult.new
|
|
97
|
+
unless params[:internal]
|
|
98
|
+
UI.info "Writing content into file #{target} as follows:".cyan
|
|
99
|
+
UI.info "#{content}"
|
|
100
|
+
end
|
|
101
|
+
if Options.reveal
|
|
102
|
+
result.success = true
|
|
103
|
+
else
|
|
104
|
+
begin
|
|
105
|
+
File.open(target, 'w') { |f| f << content }
|
|
106
|
+
result.success = target.file? # TODO: Maybe check for the actual content of the created file here
|
|
107
|
+
rescue Exception => e
|
|
108
|
+
result.reason = "Cannot write to file `#{target}´. Reason: #{e.message}"
|
|
109
|
+
params[:die_on_failure] ? raise(CSD::Error::Command::TouchAndReplaceContentFailed, result.reason) : UI.error(result.reason)
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
result
|
|
113
|
+
end
|
|
114
|
+
|
|
90
115
|
# Copies one or several files to the destination
|
|
91
116
|
#
|
|
92
117
|
def copy(src, dest, params={})
|
|
@@ -151,9 +176,9 @@ module CSD
|
|
|
151
176
|
default_params = { :die_on_failure => true }
|
|
152
177
|
params = default_params.merge(params)
|
|
153
178
|
begin
|
|
154
|
-
UI.info "
|
|
179
|
+
UI.info " Replacing".yellow
|
|
155
180
|
UI.info " `#{pattern}´".blue
|
|
156
|
-
UI.info "
|
|
181
|
+
UI.info " with".yellow
|
|
157
182
|
UI.info " `#{substitution.to_s.gsub("\n", "\n ")}´".white
|
|
158
183
|
new_file_content = File.read(self.filepath).gsub(pattern.to_s, substitution.to_s)
|
|
159
184
|
File.open(self.filepath, 'w+') { |file| file << new_file_content } unless Options.reveal
|
|
@@ -177,26 +202,28 @@ module CSD
|
|
|
177
202
|
#
|
|
178
203
|
# The following options can be passed as a hash.
|
|
179
204
|
#
|
|
180
|
-
# [+:die_on_failure+] If the
|
|
205
|
+
# [+:die_on_failure+] If the status code of the command was not 0, raise an Command::RunFailed exception (default: +true+).
|
|
181
206
|
# [+:announce_pwd+] Before running the command, announce in which path the command will be executed (default: +true+).
|
|
182
207
|
# [+:verbose+] Instead of printing just one `.´ per command output line, print the full command output lines (default: +false+).
|
|
183
208
|
# [+:internal+] If this parameter is +true+, there will be no output what-so-ever for running this command. (default: +false+).
|
|
209
|
+
# [+:force_in_reveal+] If this parameter is +true+, the command will be executed, even in <tt>--reveal</tt> mode (default: +false+).
|
|
184
210
|
#
|
|
185
211
|
# ==== Returns
|
|
186
212
|
#
|
|
187
213
|
# This method returns a CommandResult object with the following values:
|
|
188
214
|
#
|
|
189
|
-
# [+
|
|
190
|
-
# [+
|
|
215
|
+
# [+output?+] The command's output as a +String+ (with newline delimiters). Note that the status code can be accessed via the global variable <tt>$?</tt>.
|
|
216
|
+
# [+status?+] Contains <tt>$?</tt> and all the methods Ruby provides for it.
|
|
217
|
+
# [+success?+] +true+ if the command was successful, +nil+ if not (internally <tt>$?.success?</tt> is called).
|
|
191
218
|
#
|
|
192
219
|
def run(cmd, params={})
|
|
193
|
-
default_params = { :die_on_failure => true, :announce_pwd => true, :verbose => Options.verbose, :internal => false }
|
|
220
|
+
default_params = { :die_on_failure => true, :announce_pwd => true, :verbose => Options.verbose, :internal => false, :force_in_reveal => false }
|
|
194
221
|
params = default_params.merge(params)
|
|
195
222
|
result = CommandResult.new
|
|
196
223
|
cmd = cmd.to_s
|
|
197
224
|
UI.info "Running command in #{pwd}".yellow if params[:announce_pwd] and !params[:internal]
|
|
198
225
|
UI.info cmd.cyan unless params[:internal]
|
|
199
|
-
if Options.reveal
|
|
226
|
+
if Options.reveal and !params[:force_in_reveal]
|
|
200
227
|
result.success = true
|
|
201
228
|
return result
|
|
202
229
|
end
|
data/lib/csd/error.rb
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
# -*- encoding: UTF-8 -*-
|
|
2
2
|
|
|
3
3
|
module CSD
|
|
4
|
-
# In this module we will keep all types of errors in a readable hierarchy
|
|
4
|
+
# In this module we will keep all types of errors in a readable hierarchy.
|
|
5
|
+
# The application modules are assigned the following individual error ranges:
|
|
6
|
+
#
|
|
7
|
+
# * +minisip+ has been assigned error status codes 200-280
|
|
8
|
+
# * +decklink+ has been assigned error status codes 280-299
|
|
5
9
|
#
|
|
6
10
|
module Error
|
|
7
11
|
|
|
8
|
-
# All Exceptions raised by CSD must be children of this class.
|
|
12
|
+
# All Exceptions raised by CSD must be children of this class.
|
|
9
13
|
#
|
|
10
14
|
class CSDError < StandardError
|
|
11
15
|
def self.status_code(code = nil)
|
|
@@ -18,29 +22,41 @@ module CSD
|
|
|
18
22
|
end
|
|
19
23
|
end
|
|
20
24
|
|
|
25
|
+
# Errors in this module are caused by internal AI failures.
|
|
26
|
+
#
|
|
27
|
+
module Internal
|
|
28
|
+
# Somebody tried to run the CSD::Extensions::Core::Pathname.pathnamify method on +nil+. This probably happened in the test-suite when a +Path+ is not set.
|
|
29
|
+
class PathnamifyingNil < CSDError; status_code(1000); end
|
|
30
|
+
end
|
|
31
|
+
|
|
21
32
|
# Errors in this module are related to command-line options
|
|
22
33
|
#
|
|
23
34
|
module Argument
|
|
24
|
-
|
|
25
|
-
class
|
|
26
|
-
|
|
35
|
+
# The <tt>--help</tt> parameter was given, thus the AI quitted after showing the help.
|
|
36
|
+
class HelpWasRequested < CSDError; status_code(2); end
|
|
37
|
+
# The <tt>--version</tt> parameter was given, thus the AI quitted after showing the AI version number.
|
|
38
|
+
class VersionWasRequested < CSDError; status_code(3); end
|
|
39
|
+
class NoApplication < CSDError; status_code(11); end
|
|
40
|
+
class NoAction < CSDError; status_code(12); end
|
|
41
|
+
class InvalidOption < CSDError; status_code(50); end
|
|
27
42
|
end
|
|
28
43
|
|
|
29
44
|
# Errors in this module are raised by the Command module
|
|
30
45
|
#
|
|
31
46
|
module Command
|
|
32
|
-
class RunFailed
|
|
33
|
-
class CdFailed
|
|
34
|
-
class CopyFailed
|
|
35
|
-
class MoveFailed
|
|
47
|
+
class RunFailed < CSDError; status_code(60); end
|
|
48
|
+
class CdFailed < CSDError; status_code(61); end
|
|
49
|
+
class CopyFailed < CSDError; status_code(62); end
|
|
50
|
+
class MoveFailed < CSDError; status_code(63); end
|
|
36
51
|
class ReplaceFailed < CSDError; status_code(64); end
|
|
37
|
-
class MkdirFailed
|
|
52
|
+
class MkdirFailed < CSDError; status_code(65); end
|
|
53
|
+
class TouchAndReplaceContentFailed < CSDError; status_code(66); end
|
|
38
54
|
end
|
|
39
55
|
|
|
40
56
|
# Errors in this module are related to the Application Module Framework
|
|
41
57
|
#
|
|
42
58
|
module Application
|
|
43
|
-
class OptionsSyntax
|
|
59
|
+
class OptionsSyntax < CSDError; status_code(100); end
|
|
44
60
|
class NoInstanceMethod < CSDError; status_code(101); end
|
|
45
61
|
end
|
|
46
62
|
|
|
@@ -1,23 +1,13 @@
|
|
|
1
1
|
# -*- encoding: UTF-8 -*-
|
|
2
2
|
|
|
3
|
-
module
|
|
4
|
-
|
|
5
|
-
module Core
|
|
6
|
-
# This module comprises extensions to the Kernel module
|
|
7
|
-
#
|
|
8
|
-
module Kernel
|
|
9
|
-
|
|
10
|
-
# Checks whether the AI was executed with superuser rights (a.k.a. +sudo+). Returns +true+ or +false+.
|
|
11
|
-
#
|
|
12
|
-
def superuser?
|
|
13
|
-
Process.uid == 0
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
|
|
3
|
+
# This module extends the original Kernel module. Note that methods cannot be added via the +include+ method in this case.
|
|
4
|
+
#
|
|
21
5
|
module Kernel #:nodoc:
|
|
22
|
-
|
|
6
|
+
|
|
7
|
+
# Checks whether the AI was executed with superuser rights (a.k.a. +sudo+). Returns +true+ or +false+.
|
|
8
|
+
#
|
|
9
|
+
def superuser?
|
|
10
|
+
Process.uid == 0
|
|
11
|
+
end
|
|
12
|
+
|
|
23
13
|
end
|
|
@@ -16,16 +16,22 @@ module CSD
|
|
|
16
16
|
"#{os} (#{cpu}#{version_string})"
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
+
# Determines whether the OS is Debian or Ubuntu. Returns +true+ or +false+.
|
|
20
|
+
#
|
|
21
|
+
def debian?
|
|
22
|
+
kernel_version and kernel_version =~ /Debian|Ubuntu/
|
|
23
|
+
end
|
|
24
|
+
|
|
19
25
|
# On linux systems, this method returns the current kernel version.
|
|
20
26
|
#
|
|
21
27
|
def kernel_version
|
|
22
|
-
Cmd.run('uname --kernel-version', :internal => true).output.to_s.chop if os == 'linux'
|
|
28
|
+
Cmd.run('uname --kernel-version', :internal => true, :force_in_reveal => true).output.to_s.chop if os == 'linux'
|
|
23
29
|
end
|
|
24
30
|
|
|
25
31
|
# On linux systems, this method returns the current kernel release.
|
|
26
32
|
#
|
|
27
33
|
def kernel_release
|
|
28
|
-
Cmd.run('uname --kernel-release', :internal => true).output.to_s.chop if os == 'linux'
|
|
34
|
+
Cmd.run('uname --kernel-release', :internal => true, :force_in_reveal => true).output.to_s.chop if os == 'linux'
|
|
29
35
|
end
|
|
30
36
|
|
|
31
37
|
end
|
|
@@ -33,7 +39,7 @@ module CSD
|
|
|
33
39
|
end
|
|
34
40
|
end
|
|
35
41
|
|
|
36
|
-
module Gem
|
|
42
|
+
module Gem #:nodoc:
|
|
37
43
|
class Platform #:nodoc:
|
|
38
44
|
include CSD::Extensions::Gem::Platform
|
|
39
45
|
end
|
data/lib/csd/options_parser.rb
CHANGED
|
@@ -26,10 +26,10 @@ module CSD
|
|
|
26
26
|
def define_actions_and_scopes
|
|
27
27
|
if Applications.current
|
|
28
28
|
# Here we overwrite the default supported actions and scopes with the application specific ones
|
|
29
|
-
UI.debug "
|
|
29
|
+
UI.debug "#{self.class} loads the actions of #{Applications.current} now"
|
|
30
30
|
self.actions = Applications.current.actions
|
|
31
31
|
# At this point we know that the first argument is no option, but *some* action (may it be valid or not)
|
|
32
|
-
UI.debug "
|
|
32
|
+
UI.debug "#{self.class} loads the scopes of #{Applications.current} now"
|
|
33
33
|
self.scopes = Applications.current.scopes(self.action)
|
|
34
34
|
end
|
|
35
35
|
end
|
|
@@ -130,7 +130,7 @@ module CSD
|
|
|
130
130
|
end
|
|
131
131
|
opts.on_tail("-v", "--version", "Show the version of this AI") do
|
|
132
132
|
puts "CSD Gem Version: #{CSD::Version}".blue
|
|
133
|
-
|
|
133
|
+
raise Error::Argument::VersionWasRequested
|
|
134
134
|
end
|
|
135
135
|
self.helptext = opts.help
|
|
136
136
|
end.parse!
|
|
@@ -13,19 +13,22 @@ module CSD
|
|
|
13
13
|
|
|
14
14
|
def indicate_activity
|
|
15
15
|
end
|
|
16
|
-
|
|
16
|
+
|
|
17
|
+
def ask_yes_no(question, default=nil)
|
|
18
|
+
end
|
|
19
|
+
|
|
17
20
|
def debug(message)
|
|
18
21
|
end
|
|
19
|
-
|
|
22
|
+
|
|
20
23
|
def info(message)
|
|
21
24
|
end
|
|
22
|
-
|
|
25
|
+
|
|
23
26
|
def warn(message)
|
|
24
27
|
end
|
|
25
|
-
|
|
28
|
+
|
|
26
29
|
def error(message)
|
|
27
30
|
end
|
|
28
|
-
|
|
31
|
+
|
|
29
32
|
end
|
|
30
33
|
end
|
|
31
34
|
end
|
|
@@ -4,7 +4,7 @@ require 'csd/user_interface/base'
|
|
|
4
4
|
module CSD
|
|
5
5
|
module UserInterface
|
|
6
6
|
class CLI < Base
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
include Gem::UserInteraction
|
|
9
9
|
|
|
10
10
|
def separator
|
|
@@ -16,6 +16,14 @@ module CSD
|
|
|
16
16
|
$stdout.flush
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
+
# Be careful, this function writes to +STDOUT+ and not to <tt>$stdout</tt>. In other words,
|
|
20
|
+
# the output cannot be hidden from the end-user, and thus, for example, not be properly
|
|
21
|
+
# tested in the test suite. ask_yes_no is provided by Gem::UserInteraction.
|
|
22
|
+
#
|
|
23
|
+
def continue?
|
|
24
|
+
ask_yes_no("Continue?".red.bold, true)
|
|
25
|
+
end
|
|
26
|
+
|
|
19
27
|
def debug(message)
|
|
20
28
|
$stdout.puts "DEBUG: #{message}".magenta if Options.debug
|
|
21
29
|
end
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
# -*- encoding: UTF-8 -*-
|
|
2
|
+
require 'test/unit/assertions'
|
|
3
|
+
|
|
4
|
+
# This module is part of the Zentest framework released under the MIT license.
|
|
5
|
+
# It comprises extra assertions for Test::Unit
|
|
2
6
|
#
|
|
3
7
|
# (The MIT License)
|
|
4
8
|
#
|
|
@@ -22,41 +26,41 @@
|
|
|
22
26
|
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
23
27
|
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
24
28
|
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
29
|
+
#
|
|
30
|
+
module Test #:nodoc:
|
|
31
|
+
module Unit #:nodoc:
|
|
32
|
+
module Assertions #:nodoc:
|
|
33
|
+
|
|
34
|
+
# Captures $stdout and $stderr to StringIO objects and returns them.
|
|
35
|
+
# Restores $stdout and $stderr when done.
|
|
36
|
+
#
|
|
37
|
+
# Usage:
|
|
38
|
+
# def test_puts
|
|
39
|
+
# out, err = capture do
|
|
40
|
+
# puts 'hi'
|
|
41
|
+
# STDERR.puts 'bye!'
|
|
42
|
+
# end
|
|
43
|
+
# assert_equal "hi\n", out.string
|
|
44
|
+
# assert_equal "bye!\n", err.string
|
|
45
|
+
# end
|
|
46
|
+
#
|
|
47
|
+
def capture
|
|
48
|
+
require 'stringio'
|
|
49
|
+
orig_stdout = $stdout.dup
|
|
50
|
+
orig_stderr = $stderr.dup
|
|
51
|
+
captured_stdout = StringIO.new
|
|
52
|
+
captured_stderr = StringIO.new
|
|
53
|
+
$stdout = captured_stdout
|
|
54
|
+
$stderr = captured_stderr
|
|
55
|
+
yield
|
|
56
|
+
captured_stdout.rewind
|
|
57
|
+
captured_stderr.rewind
|
|
58
|
+
return captured_stdout.string, captured_stderr.string
|
|
59
|
+
ensure
|
|
60
|
+
$stdout = orig_stdout
|
|
61
|
+
$stderr = orig_stderr
|
|
62
|
+
end
|
|
25
63
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
# Extra assertions for Test::Unit
|
|
29
|
-
|
|
30
|
-
module Test::Unit::Assertions
|
|
31
|
-
|
|
32
|
-
# Captures $stdout and $stderr to StringIO objects and returns them.
|
|
33
|
-
# Restores $stdout and $stderr when done.
|
|
34
|
-
#
|
|
35
|
-
# Usage:
|
|
36
|
-
# def test_puts
|
|
37
|
-
# out, err = capture do
|
|
38
|
-
# puts 'hi'
|
|
39
|
-
# STDERR.puts 'bye!'
|
|
40
|
-
# end
|
|
41
|
-
# assert_equal "hi\n", out.string
|
|
42
|
-
# assert_equal "bye!\n", err.string
|
|
43
|
-
# end
|
|
44
|
-
#
|
|
45
|
-
def capture
|
|
46
|
-
require 'stringio'
|
|
47
|
-
orig_stdout = $stdout.dup
|
|
48
|
-
orig_stderr = $stderr.dup
|
|
49
|
-
captured_stdout = StringIO.new
|
|
50
|
-
captured_stderr = StringIO.new
|
|
51
|
-
$stdout = captured_stdout
|
|
52
|
-
$stderr = captured_stderr
|
|
53
|
-
yield
|
|
54
|
-
captured_stdout.rewind
|
|
55
|
-
captured_stderr.rewind
|
|
56
|
-
return captured_stdout.string, captured_stderr.string
|
|
57
|
-
ensure
|
|
58
|
-
$stdout = orig_stdout
|
|
59
|
-
$stderr = orig_stderr
|
|
64
|
+
end
|
|
60
65
|
end
|
|
61
|
-
|
|
62
66
|
end
|