dia 2.0.0 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,24 +1,29 @@
1
1
  module Dia
2
2
 
3
+
4
+ # The SharedFeatures module implements methods which are shared by
5
+ # {Dia::Application Dia::Application} and {Dia::RubyBlock Dia::RubyBlock}.
6
+ # This module shoudln't be interacted with directly.
3
7
  module SharedFeatures
4
-
5
- # @return [Fixnum, nil] Returns the Process ID(PID) of the last child process that was
6
- # used to execute a sandbox.
7
- # Returns nil if #run or #run_nonblock has not been called yet.
8
+
9
+ attr_reader :pid
10
+
11
+ # @return [Fixnum] Returns the Process ID(PID) of the last child process to execute a
12
+ # a sandbox.
13
+ #
14
+ # @return [nil] Returns nil if #run or #run_nonblock have not been called.
8
15
  def pid
9
16
  @pid
10
17
  end
11
18
 
12
- # The exit_status method will return the exit status of your sandbox.
13
- # This method *will* block until the child process(your sandbox) exits
14
- # when being used with #run_nonblock.
19
+ # The exit_status method will return the exit status of the child process
20
+ # used to execute a sandbox.
21
+ # This method blocks until the spawned process exits when being used with #run_nonblock.
22
+ #
23
+ # @return [Fixnum] Returns the exit status as a Fixnum.
24
+ #
25
+ # @return [nil] Returns nil if #run or #run_nonblock have not been called.
15
26
  #
16
- # @return [Fixnum, nil] Returns the exit status of your sandbox as a
17
- # Fixnum.
18
- # Returns nil if #run or #run_nonblock has not
19
- # been called yet.
20
- # Returns nil if the process hasn't exited yet and
21
- # #run is being used.
22
27
  # @since 1.5
23
28
  def exit_status()
24
29
  unless @exit_status.nil?
@@ -27,22 +32,14 @@ module Dia
27
32
  end
28
33
  end
29
34
 
30
- # The terminate method will send the SIGKILL signal to your sandbox.
31
- #
32
- # To prevent the possible accumulation of zombies, this method will
33
- # wait to collect the exit status of your sandbox if it doesn't appear
34
- # to have left the process table after sending SIGKILL.
35
+ # The terminate method will terminate the child process executing a sandbox.
35
36
  #
36
- # This is a rare event, and when it does happen #terminate shouldn't block
37
- # for more than one second.
37
+ # @raise [SystemCallError] It could raise a number of subclasses of SystemCallError
38
+ # if a signal could not be sent to the child process.
38
39
  #
39
- # @raise [SystemCallError] It may raise a number of subclasses of
40
- # SystemCallError if a call to Process.kill
41
- # was unsuccessful
40
+ # @return [Fixnum] Returns 1 when successful.
42
41
  #
43
- # @return [Fixnum, nil] Returns 1 when successful.
44
- # Returns nil if #run or #run_nonblock has not
45
- # been called yet.
42
+ # @return [nil] Returns nil if #run or #run_nonblock has not been called.
46
43
  def terminate()
47
44
  ret = Process.kill('SIGKILL', @pid) unless @pid.nil?
48
45
  # precaution against the collection of zombie processes.
@@ -50,15 +47,17 @@ module Dia
50
47
  ret
51
48
  end
52
49
 
53
- # This method will tell you if your sandbox is still running by returning a boolean.
50
+ # This method can tell you whether the child process used to execute your sandbox is
51
+ # running or not.
52
+ #
53
+ # @raise [SystemCallError] It could raise a number of subclasses of SystemCallError
54
+ # if a signal could not be sent to the child process.
55
+ #
56
+ # @return [true] Returns true when the child process is running.
54
57
  #
55
- # @raise [SystemCallError] It may raise a number of subclasses of SystemCallError
56
- # if a signal cannot be sent to the process running
57
- # a sandbox.
58
+ # @return [false] Returns false when the child process is not running.
58
59
  #
59
- # @return [Boolean,nil] Returns true, false, or nil.
60
- # Returns nil if #run or #run_nonblock has
61
- # not been called yet.
60
+ # @return [nil] Returns nil if #run or #run_nonblock have not been called.
62
61
  def running?()
63
62
  if @pid.nil?
64
63
  nil
@@ -0,0 +1,21 @@
1
+ suite('Application') do
2
+ suite('#initialize') do
3
+ suite('Raises') do
4
+
5
+ exercise("When the Dia::Profiles::NO_OS_SERVICES profile is supplied to #initialize.") do
6
+ begin
7
+ dia = Dia::Application.new(Dia::Profiles::NO_OS_SERVICES, "touch /tmp/bar")
8
+ rescue ArgumentError => e
9
+ @result = true
10
+ else
11
+ @result = false
12
+ end
13
+ end
14
+
15
+ verify('#initialize will raise an ArgumentError.') do
16
+ @result
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,16 @@
1
+ suite('Application') do
2
+ suite('#run') do
3
+ suite('Return values') do
4
+
5
+ exercise('When #run has finished executing.') do
6
+ dia = Dia::Application.new(Dia::Profiles::NO_INTERNET, "touch /tmp/bar")
7
+ @result = dia.run
8
+ end
9
+
10
+ verify('It returns the Process ID of the spawned process.') do
11
+ @result.class == Fixnum
12
+ end
13
+
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ suite('Application') do
2
+ suite('#run_nonblock') do
3
+ suite('Return values') do
4
+
5
+ exercise('When #run_nonblock has finished executing.') do
6
+ dia = Dia::Application.new(Dia::Profiles::NO_INTERNET, "touch /tmp/bar")
7
+ @result = dia.run
8
+ end
9
+
10
+ verify('It returns the Process ID of the spawned process.') do
11
+ @result.class == Fixnum
12
+ end
13
+
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,46 @@
1
+ suite('RubyBlock') do
2
+ suite('#exception') do
3
+ suite('Return values') do
4
+
5
+ exercise('When exceptions are being captured, and an exception is raised.') do
6
+ dia = Dia::RubyBlock.new(Dia::Profiles::NO_INTERNET) do
7
+ raise(StandardError, "raised")
8
+ end
9
+
10
+ dia.rescue_exception = true
11
+ dia.run
12
+ @result = dia.exception
13
+ end
14
+
15
+ verify('#exception returns a Dia::ExceptionStruct object.') do
16
+ @result.class == Dia::ExceptionStruct
17
+ end
18
+
19
+ exercise('When exceptions are being captured, and no exception is raised.') do
20
+ dia = Dia::RubyBlock.new(Dia::Profiles::NO_INTERNET) { }
21
+ dia.rescue_exception = true
22
+ dia.run
23
+ @result = dia.exception
24
+ end
25
+
26
+ verify('#exception returns nil as no exception is available.') do
27
+ @result == nil
28
+ end
29
+
30
+ exercise('When exceptions are not being captured, and an exception is raised.') do
31
+ dia = Dia::RubyBlock.new(Dia::Profiles::NO_INTERNET) do
32
+ raise(StandardError, "raised")
33
+ end
34
+ dia.redirect_stderr = true # I don't want the test output to be flooded with a backtrace.
35
+ dia.rescue_exception = false # default, but lets be explicit.
36
+ dia.run
37
+ @result = dia.exception
38
+ end
39
+
40
+ verify('#exception returns nil.') do
41
+ @result == nil
42
+ end
43
+
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,45 @@
1
+ suite('RubyBlock') do
2
+ suite('#exception_raised?') do
3
+ suite('Return values') do
4
+
5
+ exercise('When an exception has been raised.') do
6
+ dia = Dia::RubyBlock.new(Dia::Profiles::NO_INTERNET) do
7
+ raise(StandardError, "raised")
8
+ end
9
+ dia.rescue_exception = true
10
+ dia.run
11
+ @result = dia.exception_raised?
12
+ end
13
+
14
+ verify('#exception_raised? returns true.') do
15
+ @result == true
16
+ end
17
+
18
+ exercise('When an exception has not been raised.') do
19
+ dia = Dia::RubyBlock.new(Dia::Profiles::NO_INTERNET) { }
20
+ dia.rescue_exception = true
21
+ dia.run
22
+ @result = dia.exception_raised?
23
+ end
24
+
25
+ verify('#exception_raised? returns false.') do
26
+ @result == false
27
+ end
28
+
29
+ exercise('When exceptions are not being captured, and an exception has been raised.') do
30
+ dia = Dia::RubyBlock.new(Dia::Profiles::NO_INTERNET) do
31
+ raise(StandardError, "raised")
32
+ end
33
+ dia.rescue_exception = false # default, but lets be explicit.
34
+ dia.redirect_stderr = true # I don't want the tests to be flooded with a backtrace.
35
+ dia.run
36
+ @result = dia.exception_raised?
37
+ end
38
+
39
+ verify('#exception_raised? returns false') do
40
+ @result == false
41
+ end
42
+
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,27 @@
1
+ suite('RubyBlock') do
2
+ suite('#redirect_stderr?') do
3
+ suite('Return values') do
4
+
5
+ exercise('When stderr output is being redirected.') do
6
+ dia = Dia::RubyBlock.new(Dia::Profiles::NO_INTERNET) { }
7
+ dia.redirect_stderr = true
8
+ @result = dia.redirect_stderr?
9
+ end
10
+
11
+ verify('#redirect_stderr? returns true.') do
12
+ @result == true
13
+ end
14
+
15
+ exercise('When stderr output is not being redirected.') do
16
+ dia = Dia::RubyBlock.new(Dia::Profiles::NO_INTERNET) { }
17
+ dia.redirect_stderr = false
18
+ @result = dia.redirect_stderr?
19
+ end
20
+
21
+ verify('#redirect_stderr? returns false.') do
22
+ @result == false
23
+ end
24
+
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,27 @@
1
+ suite('RubyBlock') do
2
+ suite('#redirect_stdout?') do
3
+ suite('Return values') do
4
+
5
+ exercise('When stdout is being redirected.') do
6
+ dia = Dia::RubyBlock.new(Dia::Profiles::NO_INTERNET) { }
7
+ dia.redirect_stdout = true
8
+ @result = dia.redirect_stdout?
9
+ end
10
+
11
+ verify('#redirect_stdout? returns true.') do
12
+ @result == true
13
+ end
14
+
15
+ exercise('When stdout is not being redirected.') do
16
+ dia = Dia::RubyBlock.new(Dia::Profiles::NO_INTERNET) { }
17
+ dia.redirect_stdout = false
18
+ @result = dia.redirect_stdout?
19
+ end
20
+
21
+ verify('#redirect_stdout? returns false.') do
22
+ @result == false
23
+ end
24
+
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,28 @@
1
+ suite('RubyBlock') do
2
+ suite('#rescue_exception?') do
3
+ suite('Return values') do
4
+
5
+ exercise('When exceptions are being captured.') do
6
+ dia = Dia::RubyBlock.new(Dia::Profiles::NO_INTERNET) { }
7
+ dia.rescue_exception = true
8
+ @result = dia.rescue_exception?
9
+ end
10
+
11
+ verify('#rescue_exception? returns true') do
12
+ @result == true
13
+ end
14
+
15
+ exercise('When exceptions are not being captured.') do
16
+ dia = Dia::RubyBlock.new(Dia::Profiles::NO_INTERNET) { }
17
+ dia.rescue_exception = false # default, but lets be explicit.
18
+ @result = dia.rescue_exception?
19
+ end
20
+
21
+ verify('#rescue_exception? returns false') do
22
+ @result == false
23
+ end
24
+
25
+ end
26
+ end
27
+ end
28
+
@@ -0,0 +1,135 @@
1
+ suite('RubyBlock') do
2
+ suite('#run') do
3
+ suite('Return values') do
4
+
5
+ exercise('When #run has finished executing.') do
6
+ dia = Dia::RubyBlock.new(Dia::Profiles::NO_INTERNET) { }
7
+ @result = dia.run
8
+ end
9
+
10
+ verify('It returns the Process ID of the spawned process.') do
11
+ @result.class == Fixnum
12
+ end
13
+
14
+ end
15
+
16
+ suite('Behavior') do
17
+
18
+ setup do
19
+ @result = nil
20
+ @reader, @writer = IO.pipe
21
+ end
22
+
23
+ exercise('Confirm the profile ' \
24
+ 'Dia::Profiles::NO_INTERNET ' \
25
+ 'is creating a working sandbox environment.') do
26
+ sandbox = Dia::RubyBlock.new(Dia::Profiles::NO_INTERNET) do
27
+ begin
28
+ @reader.close
29
+ TCPSocket.open('http://www.google.com', 80)
30
+ @writer.write('false')
31
+ rescue SocketError, SystemCallError => e
32
+ @writer.write('true')
33
+ ensure
34
+ @writer.close
35
+ end
36
+ end
37
+
38
+ sandbox.run
39
+
40
+ @writer.close
41
+ @result = @reader.gets
42
+ @reader.close
43
+ end
44
+
45
+ verify(nil) do
46
+ @result == 'true'
47
+ end
48
+
49
+ exercise('Confirm the profile ' \
50
+ 'Dia::Profiles::NO_FILESYSTEM_WRITE ' \
51
+ 'is creating a working sandbox environment.') do
52
+
53
+ sandbox = Dia::RubyBlock.new(Dia::Profiles::NO_FILESYSTEM_WRITE) do
54
+ begin
55
+ @reader.close
56
+ File.open('/tmp/foo.txt', 'w') { |f| f.puts('fail') }
57
+ @writer.write('false')
58
+ rescue SocketError, SystemCallError => e
59
+ @writer.write('true')
60
+ ensure
61
+ @writer.close
62
+ end
63
+ end
64
+
65
+
66
+ sandbox.run
67
+
68
+ @writer.close
69
+ @result = @reader.gets
70
+ @reader.close
71
+ end
72
+
73
+ verify(nil) do
74
+ @result == 'true'
75
+ end
76
+
77
+ exercise('Confirm the profile ' \
78
+ 'Dia::Profiles::NO_FILESYSTEM_WRITE_EXCEPT_TMP ' \
79
+ 'is creating a working sandbox environment. ') do
80
+ sandbox = Dia::RubyBlock.new(Dia::Profiles::NO_FILESYSTEM_WRITE_EXCEPT_TMP) do
81
+ begin
82
+ @reader.close
83
+ out = Time.now.to_s
84
+ File.open('/tmp/%s.dia_test' % [ out ] , 'w') { |f| f.puts('success') }
85
+ File.open(File.join(ENV['HOME'], 'fail.txt')) { |f| f.puts('fail') }
86
+ @writer.write('false')
87
+ rescue SocketError, SystemCallError => e
88
+ if File.exists?('/tmp/%s.dia_test' % [ out ])
89
+ @writer.write('true')
90
+ else
91
+ @writer.write('false')
92
+ end
93
+ ensure
94
+ @writer.close
95
+ end
96
+ end
97
+
98
+ sandbox.run
99
+
100
+ @writer.close
101
+ @result = @reader.gets
102
+ @reader.close
103
+ end
104
+
105
+ verify(nil) do
106
+ @result == 'true'
107
+ end
108
+
109
+ exercise('Confirm the profile ' \
110
+ 'Dia::Profiles::NO_NETWORKING ' \
111
+ 'is creating a working sandbox environment') do
112
+ sandbox = Dia::RubyBlock.new(Dia::Profiles::NO_NETWORKING) do
113
+ begin
114
+ @reader.close
115
+ TCPSocket.open('http://www.youtube.com', 80)
116
+ @writer.write('false')
117
+ rescue SocketError => e
118
+ @writer.write('true')
119
+ end
120
+ end
121
+
122
+ sandbox.run
123
+
124
+ @writer.close
125
+ @result = @reader.gets
126
+ @reader.close
127
+ end
128
+
129
+ verify(nil) do
130
+ @result == 'true'
131
+ end
132
+
133
+ end
134
+ end
135
+ end