dia 2.0.0 → 2.0.1

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.
@@ -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