process-group 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 372a5e01e0eec6598278b7b6d9d7752f59190b66
4
+ data.tar.gz: ef2061f5503a85c60a0e56a81efaff25b1d95dc6
5
+ SHA512:
6
+ metadata.gz: ffff6097b47894fef08ad2e083d0a5834929393d278085b00c3e6a5dfc508801266c0a2752f437feea24b7b1f43fcc9f368584df45d3dbcdf00fd04e87c97dcb
7
+ data.tar.gz: bff7b9a0140d6e6c5655824ac4b7110b75a2095b281a1d5e143870dac6dfc6454d792e7a21f4fc1403de4bae53243863796296afd75bf9906521ba887fea878c
data/Rakefile CHANGED
@@ -1,9 +1,6 @@
1
1
  require "bundler/gem_tasks"
2
- require "rake/testtask"
2
+ require "rspec/core/rake_task"
3
3
 
4
- Rake::TestTask.new do |t|
5
- t.libs << 'test'
6
- end
4
+ RSpec::Core::RakeTask.new(:spec)
7
5
 
8
- desc "Run tests"
9
- task :default => :test
6
+ task :default => :spec
@@ -0,0 +1,43 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Copyright, 2014, by Samuel G. D. Williams. <http://www.codeotaku.com>
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+ require_relative '../lib/process/group'
24
+
25
+ group = Process::Group.new
26
+
27
+ 5.times do
28
+ Fiber.new do
29
+ result = group.fork do
30
+ begin
31
+ sleep 1 while true
32
+ rescue Interrupt
33
+ puts "Interrupted in child #{Process.pid}"
34
+ end
35
+ end
36
+ end.resume
37
+ end
38
+
39
+ begin
40
+ group.wait
41
+ rescue Interrupt
42
+ puts "Interrupted in parent #{Process.pid}"
43
+ end
@@ -1,5 +1,25 @@
1
+ # Copyright, 2014, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
1
21
  module Process
2
22
  class Group
3
- VERSION = "0.2.0"
23
+ VERSION = "0.2.1"
4
24
  end
5
25
  end
@@ -21,7 +21,6 @@ Gem::Specification.new do |spec|
21
21
  spec.require_paths = ["lib"]
22
22
 
23
23
  spec.add_development_dependency "bundler", "~> 1.3"
24
+ spec.add_development_dependency "rspec", "~> 3.0.0.rc1"
24
25
  spec.add_development_dependency "rake"
25
- spec.add_development_dependency "betatest"
26
- spec.add_development_dependency "mocha"
27
26
  end
@@ -0,0 +1,62 @@
1
+ # Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require 'process/group'
22
+
23
+ module Process::Group::ForkSpec
24
+ describe Process::Group do
25
+ it "should fork and write to pipe" do
26
+ group = Process::Group.new
27
+
28
+ input, output = IO.pipe
29
+
30
+ Fiber.new do
31
+ result = group.fork do
32
+ output.puts "Hello World"
33
+
34
+ exit(1)
35
+ end
36
+
37
+ expect(result.exitstatus).to be == 1
38
+ end.resume
39
+
40
+ output.close
41
+
42
+ group.wait
43
+
44
+ expect(input.read).to be == "Hello World\n"
45
+ end
46
+
47
+ it "should not throw interrupt from fork" do
48
+ group = Process::Group.new
49
+
50
+ Fiber.new do
51
+ result = group.fork do
52
+ raise Interrupt
53
+ end
54
+
55
+ expect(result.exitstatus).not_to be == 0
56
+ end.resume
57
+
58
+ # Shouldn't raise any errors:
59
+ group.wait
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,150 @@
1
+ # Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require 'process/group'
22
+
23
+ module Process::Group::InterruptSpec
24
+ describe Process::Group do
25
+ it "should raise interrupt exception" do
26
+ group = Process::Group.new
27
+ checkpoint = ""
28
+
29
+ Fiber.new do
30
+ checkpoint += 'X'
31
+
32
+ result = group.fork { sleep 0.1 }
33
+
34
+ expect(result).to be == 0
35
+
36
+ checkpoint += 'Y'
37
+
38
+ # Simulate the user pressing Ctrl-C after 0.5 seconds:
39
+ raise Interrupt
40
+ end.resume
41
+
42
+ Fiber.new do
43
+ checkpoint += 'A'
44
+
45
+ # This never returns:
46
+ result = group.fork { sleep 0.2 }
47
+
48
+ checkpoint += 'B'
49
+ end.resume
50
+
51
+ expect(group).to receive(:kill).with(:INT).once
52
+ expect(group).to receive(:kill).with(:TERM).once
53
+
54
+ expect do
55
+ group.wait
56
+ end.to raise_error(Interrupt)
57
+
58
+ expect(checkpoint).to be == 'XAY'
59
+ end
60
+
61
+ it "should raise an exception" do
62
+ group = Process::Group.new
63
+ checkpoint = ""
64
+
65
+ Fiber.new do
66
+ checkpoint += 'X'
67
+
68
+ result = group.fork { sleep 0.1 }
69
+ expect(result).to be == 0
70
+
71
+ checkpoint += 'Y'
72
+
73
+ # Raises a RuntimeError
74
+ fail "Error"
75
+ end.resume
76
+
77
+ Fiber.new do
78
+ checkpoint += 'A'
79
+
80
+ # This never returns:
81
+ result = group.fork { sleep 0.2 }
82
+
83
+ checkpoint += 'B'
84
+ end.resume
85
+
86
+ expect do
87
+ expect(group).to receive(:kill).with(:TERM).once
88
+
89
+ group.wait
90
+ end.to raise_error(RuntimeError)
91
+
92
+ expect(checkpoint).to be == 'XAY'
93
+ end
94
+
95
+ class Timeout < StandardError
96
+ end
97
+
98
+ it "should pass back out exceptions" do
99
+ group = Process::Group.new
100
+ checkpoint = ""
101
+
102
+ Fiber.new do
103
+ # Wait for 2 seconds, let other processes run:
104
+ group.fork { sleep 2 }
105
+ checkpoint += 'A'
106
+ #puts "Finished waiting #1..."
107
+
108
+ # If no other processes are running, we are done:
109
+ Fiber.yield unless group.running?
110
+ checkpoint += 'B'
111
+ #puts "Sending SIGINT..."
112
+
113
+ # Send SIGINT to currently running processes:
114
+ group.kill(:INT)
115
+
116
+ # Wait for 2 seconds, let other processes run:
117
+ group.fork { sleep 2 }
118
+ checkpoint += 'C'
119
+ #puts "Finished waiting #2..."
120
+
121
+ # If no other processes are running, we are done:
122
+ Fiber.yield unless group.running?
123
+ checkpoint += 'D'
124
+ #puts "Sending SIGTERM..."
125
+
126
+ # Send SIGTERM to currently running processes:
127
+ group.kill(:TERM)
128
+
129
+ # Raise an Timeout exception which is pased back out:
130
+ raise Timeout
131
+ end.resume
132
+
133
+ # Run some other long task:
134
+ group.run("sleep 10")
135
+
136
+ start_time = Time.now
137
+
138
+ # Wait for fiber to complete:
139
+ expect do
140
+ group.wait
141
+ checkpoint += 'E'
142
+ end.not_to raise_error
143
+
144
+ end_time = Time.now
145
+
146
+ expect(checkpoint).to be == 'ABCE'
147
+ expect(end_time - start_time).to be_within(0.1).of 4.0
148
+ end
149
+ end
150
+ end
@@ -18,45 +18,39 @@
18
18
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
19
  # THE SOFTWARE.
20
20
 
21
- require 'betatest/autorun'
22
-
23
21
  require 'process/group'
24
22
 
25
- class TestFork < Betatest::Test
26
- def test_fork_io
27
- group = Process::Group.new
23
+ module Process::Group::IOSpec
24
+ describe Process::Group do
25
+ it "should read line on separate thread" do
26
+ group = Process::Group.new
28
27
 
29
- input, output = IO.pipe
28
+ input, output = IO.pipe
30
29
 
31
- Fiber.new do
32
- result = group.fork do
33
- output.puts "Hello World"
30
+ Fiber.new do
31
+ result = group.fork do
32
+ 3.times do
33
+ output.puts "Hello World"
34
+ sleep 0.1
35
+ end
34
36
 
35
- exit(1)
36
- end
37
+ exit(0)
38
+ end
39
+
40
+ expect(result).to be == 0
41
+ end.resume
37
42
 
38
- assert_equal 1, result.exitstatus
39
- end.resume
40
-
41
- output.close
42
-
43
- group.wait
44
-
45
- assert_equal "Hello World\n", input.read
46
- end
47
-
48
- def test_fork_interrupt
49
- group = Process::Group.new
50
-
51
- Fiber.new do
52
- result = group.fork do
53
- raise Interrupt
43
+ output.close
44
+
45
+ lines = nil
46
+ io_thread = Thread.new do
47
+ lines = input.read
54
48
  end
55
49
 
56
- refute_equal 0, result.exitstatus
57
- end.resume
58
-
59
- # Shouldn't raise any errors:
60
- group.wait
50
+ group.wait
51
+
52
+ io_thread.join
53
+ expect(lines).to be == ("Hello World\n" * 3)
54
+ end
61
55
  end
62
56
  end
@@ -0,0 +1,109 @@
1
+ # Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require 'process/group'
22
+
23
+ module Process::Group::SpawnSpec
24
+ describe Process::Group do
25
+ it "should execute fibers concurrently" do
26
+ group = Process::Group.new
27
+
28
+ start_time = Time.now
29
+
30
+ Fiber.new do
31
+ result = group.fork { sleep 1.0 }
32
+
33
+ expect(result).to be == 0
34
+ end.resume
35
+
36
+ Fiber.new do
37
+ result = group.fork { sleep 2.0 }
38
+
39
+ expect(result).to be == 0
40
+ end.resume
41
+
42
+ group.wait
43
+
44
+ end_time = Time.now
45
+
46
+ # Check that the execution time was roughly 2 seconds:
47
+ expect(end_time - start_time).to be_within(0.1).of(2.0)
48
+ end
49
+
50
+ it "should kill commands" do
51
+ group = Process::Group.new
52
+
53
+ start_time = Time.now
54
+
55
+ group.run("sleep 1") do |exit_status|
56
+ expect(exit_status).to_not be 0
57
+ end
58
+
59
+ group.run("sleep 2") do |exit_status|
60
+ expect(exit_status).to_not be 0
61
+ end
62
+
63
+ group.kill(:KILL)
64
+
65
+ group.wait
66
+
67
+ end_time = Time.now
68
+
69
+ # Check that processes killed almost immediately:
70
+ expect(end_time - start_time).to be < 0.2
71
+ end
72
+
73
+ it "should pass environment to child process" do
74
+ group = Process::Group.new
75
+
76
+ env = {'FOO' => 'BAR'}
77
+
78
+ # Make a pipe to receive output from child process:
79
+ input, output = IO.pipe
80
+
81
+ group.run(env, "echo $FOO", out: output) do |exit_status|
82
+ output.close
83
+ end
84
+
85
+ group.wait
86
+
87
+ expect(input.read).to be == "BAR\n"
88
+ end
89
+
90
+ it "should yield exit status" do
91
+ group = Process::Group.new
92
+
93
+ start_time = Time.now
94
+
95
+ group.run("sleep 1")
96
+
97
+ group.run("sleep 1") do |exit_status|
98
+ expect(exit_status).to be == 0
99
+ end
100
+
101
+ group.wait
102
+
103
+ end_time = Time.now
104
+
105
+ # Check that the execution time was roughly 1 second:
106
+ expect(end_time - start_time).to be_within(0.1).of(1.0)
107
+ end
108
+ end
109
+ end
metadata CHANGED
@@ -1,81 +1,58 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: process-group
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
5
- prerelease:
4
+ version: 0.2.1
6
5
  platform: ruby
7
6
  authors:
8
7
  - Samuel Williams
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2014-05-18 00:00:00.000000000 Z
11
+ date: 2014-06-04 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: bundler
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ~>
17
+ - - "~>"
20
18
  - !ruby/object:Gem::Version
21
19
  version: '1.3'
22
20
  type: :development
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ~>
24
+ - - "~>"
28
25
  - !ruby/object:Gem::Version
29
26
  version: '1.3'
30
27
  - !ruby/object:Gem::Dependency
31
- name: rake
28
+ name: rspec
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ! '>='
31
+ - - "~>"
36
32
  - !ruby/object:Gem::Version
37
- version: '0'
33
+ version: 3.0.0.rc1
38
34
  type: :development
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ! '>='
38
+ - - "~>"
44
39
  - !ruby/object:Gem::Version
45
- version: '0'
40
+ version: 3.0.0.rc1
46
41
  - !ruby/object:Gem::Dependency
47
- name: betatest
48
- requirement: !ruby/object:Gem::Requirement
49
- none: false
50
- requirements:
51
- - - ! '>='
52
- - !ruby/object:Gem::Version
53
- version: '0'
54
- type: :development
55
- prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
- requirements:
59
- - - ! '>='
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- - !ruby/object:Gem::Dependency
63
- name: mocha
42
+ name: rake
64
43
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
44
  requirements:
67
- - - ! '>='
45
+ - - ">="
68
46
  - !ruby/object:Gem::Version
69
47
  version: '0'
70
48
  type: :development
71
49
  prerelease: false
72
50
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
51
  requirements:
75
- - - ! '>='
52
+ - - ">="
76
53
  - !ruby/object:Gem::Version
77
54
  version: '0'
78
- description: ! "\tManages a unix process group for running multiple processes, keeps
55
+ description: "\tManages a unix process group for running multiple processes, keeps
79
56
  track of multiple processes and leverages fibers to provide predictable behaviour
80
57
  in complicated process-based scripts.\n"
81
58
  email:
@@ -84,43 +61,45 @@ executables: []
84
61
  extensions: []
85
62
  extra_rdoc_files: []
86
63
  files:
87
- - .gitignore
88
- - .travis.yml
64
+ - ".gitignore"
65
+ - ".travis.yml"
89
66
  - Gemfile
90
67
  - README.md
91
68
  - Rakefile
69
+ - examples/terminal.rb
92
70
  - lib/process/group.rb
93
71
  - lib/process/group/version.rb
94
72
  - process-group.gemspec
95
- - test/test_fork.rb
96
- - test/test_interrupt.rb
97
- - test/test_spawn.rb
73
+ - spec/process/group/fork_spec.rb
74
+ - spec/process/group/interrupt_spec.rb
75
+ - spec/process/group/io_spec.rb
76
+ - spec/process/group/spawn_spec.rb
98
77
  homepage: ''
99
78
  licenses:
100
79
  - MIT
80
+ metadata: {}
101
81
  post_install_message:
102
82
  rdoc_options: []
103
83
  require_paths:
104
84
  - lib
105
85
  required_ruby_version: !ruby/object:Gem::Requirement
106
- none: false
107
86
  requirements:
108
- - - ! '>='
87
+ - - ">="
109
88
  - !ruby/object:Gem::Version
110
89
  version: '0'
111
90
  required_rubygems_version: !ruby/object:Gem::Requirement
112
- none: false
113
91
  requirements:
114
- - - ! '>='
92
+ - - ">="
115
93
  - !ruby/object:Gem::Version
116
94
  version: '0'
117
95
  requirements: []
118
96
  rubyforge_project:
119
- rubygems_version: 1.8.23
97
+ rubygems_version: 2.2.2
120
98
  signing_key:
121
- specification_version: 3
99
+ specification_version: 4
122
100
  summary: Run processes concurrently in separate fibers with predictable behaviour.
123
101
  test_files:
124
- - test/test_fork.rb
125
- - test/test_interrupt.rb
126
- - test/test_spawn.rb
102
+ - spec/process/group/fork_spec.rb
103
+ - spec/process/group/interrupt_spec.rb
104
+ - spec/process/group/io_spec.rb
105
+ - spec/process/group/spawn_spec.rb
@@ -1,151 +0,0 @@
1
- # Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
- #
3
- # Permission is hereby granted, free of charge, to any person obtaining a copy
4
- # of this software and associated documentation files (the "Software"), to deal
5
- # in the Software without restriction, including without limitation the rights
6
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- # copies of the Software, and to permit persons to whom the Software is
8
- # furnished to do so, subject to the following conditions:
9
- #
10
- # The above copyright notice and this permission notice shall be included in
11
- # all copies or substantial portions of the Software.
12
- #
13
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
- # THE SOFTWARE.
20
-
21
- require 'betatest/autorun'
22
-
23
- require 'process/group'
24
-
25
- class TestInterrupt < Betatest::Test
26
- def test_raise_interrupt
27
- group = Process::Group.new
28
- checkpoint = ""
29
-
30
- Fiber.new do
31
- checkpoint += 'X'
32
-
33
- result = group.fork { sleep 0.1 }
34
-
35
- assert_equal 0, result
36
-
37
- checkpoint += 'Y'
38
-
39
- # Simulate the user pressing Ctrl-C after 0.5 seconds:
40
- raise Interrupt
41
- end.resume
42
-
43
- Fiber.new do
44
- checkpoint += 'A'
45
-
46
- # This never returns:
47
- result = group.fork { sleep 0.2 }
48
-
49
- checkpoint += 'B'
50
- end.resume
51
-
52
- #group.expects(:kill).with(:INT).once
53
- #group.expects(:kill).with(:TERM).once
54
-
55
- assert_raises Interrupt do
56
- group.wait
57
- end
58
-
59
- assert_equal 'XAY', checkpoint
60
- end
61
-
62
- def test_raise_exception
63
- group = Process::Group.new
64
- checkpoint = ""
65
-
66
- Fiber.new do
67
- checkpoint += 'X'
68
-
69
- result = group.fork { sleep 0.1 }
70
- assert_equal 0, result
71
-
72
- checkpoint += 'Y'
73
-
74
- # Raises a RuntimeError
75
- fail "Error"
76
- end.resume
77
-
78
- Fiber.new do
79
- checkpoint += 'A'
80
-
81
- # This never returns:
82
- result = group.fork { sleep 0.2 }
83
-
84
- checkpoint += 'B'
85
- end.resume
86
-
87
- assert_raises RuntimeError do
88
- #group.expects(:kill).with(:TERM).once
89
-
90
- group.wait
91
- end
92
-
93
- assert_equal 'XAY', checkpoint
94
- end
95
-
96
- class Timeout < StandardError
97
- end
98
-
99
- def test_timeout
100
- group = Process::Group.new
101
- checkpoint = ""
102
-
103
- Fiber.new do
104
- # Wait for 2 seconds, let other processes run:
105
- group.fork { sleep 2 }
106
- checkpoint += 'A'
107
- #puts "Finished waiting #1..."
108
-
109
- # If no other processes are running, we are done:
110
- Fiber.yield unless group.running?
111
- checkpoint += 'B'
112
- #puts "Sending SIGINT..."
113
-
114
- # Send SIGINT to currently running processes:
115
- group.kill(:INT)
116
-
117
- # Wait for 2 seconds, let other processes run:
118
- group.fork { sleep 2 }
119
- checkpoint += 'C'
120
- #puts "Finished waiting #2..."
121
-
122
- # If no other processes are running, we are done:
123
- Fiber.yield unless group.running?
124
- checkpoint += 'D'
125
- #puts "Sending SIGTERM..."
126
-
127
- # Send SIGTERM to currently running processes:
128
- group.kill(:TERM)
129
-
130
- # Raise an Timeout exception which is based back out:
131
- raise Timeout
132
- end.resume
133
-
134
- # Run some other long task:
135
- group.run("sleep 10")
136
-
137
- start_time = Time.now
138
-
139
- # Wait for fiber to complete:
140
- #assert_nothing_raised Timeout do
141
- group.wait
142
- checkpoint += 'E'
143
- #end
144
-
145
- end_time = Time.now
146
-
147
- assert_equal 'ABCE', checkpoint
148
-
149
- assert (3.8..4.2).include?(end_time - start_time), "Process took approximately 4 seconds: #{end_time - start_time}"
150
- end
151
- end
@@ -1,108 +0,0 @@
1
- # Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
- #
3
- # Permission is hereby granted, free of charge, to any person obtaining a copy
4
- # of this software and associated documentation files (the "Software"), to deal
5
- # in the Software without restriction, including without limitation the rights
6
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- # copies of the Software, and to permit persons to whom the Software is
8
- # furnished to do so, subject to the following conditions:
9
- #
10
- # The above copyright notice and this permission notice shall be included in
11
- # all copies or substantial portions of the Software.
12
- #
13
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
- # THE SOFTWARE.
20
-
21
- require 'betatest/autorun'
22
-
23
- require 'process/group'
24
-
25
- class TestSpawn < Betatest::Test
26
- def test_fibers
27
- group = Process::Group.new
28
-
29
- start_time = Time.now
30
-
31
- Fiber.new do
32
- result = group.fork { sleep 1.0 }
33
-
34
- assert_equal 0, result
35
- end.resume
36
-
37
- Fiber.new do
38
- result = group.fork { sleep 2.0 }
39
-
40
- assert_equal 0, result
41
- end.resume
42
-
43
- group.wait
44
-
45
- end_time = Time.now
46
-
47
- # Check that the execution time was roughly 2 seconds:
48
- assert (1.9..2.1).include?(end_time - start_time)
49
- end
50
-
51
- def test_kill_commands
52
- group = Process::Group.new
53
-
54
- start_time = Time.now
55
-
56
- group.run("sleep 1") do |exit_status|
57
- refute_equal 0, exit_status
58
- end
59
-
60
- group.run("sleep 2") do |exit_status|
61
- refute_equal 0, exit_status
62
- end
63
-
64
- group.kill(:KILL)
65
-
66
- group.wait
67
-
68
- end_time = Time.now
69
-
70
- # Check that processes killed almost immediately:
71
- assert (end_time - start_time) < 0.2, "Process exited quickly #{end_time - start_time}"
72
- end
73
-
74
- def test_environment_options
75
- group = Process::Group.new
76
-
77
- env = {'FOO' => 'BAR'}
78
-
79
- # Make a pipe to receive output from child process:
80
- input, output = IO.pipe
81
-
82
- group.run(env, "echo $FOO", out: output) do |exit_status|
83
- output.close
84
- end
85
-
86
- group.wait
87
-
88
- assert_equal "BAR\n", input.read
89
- end
90
-
91
- def test_yield
92
- group = Process::Group.new
93
-
94
- start_time = Time.now
95
-
96
- group.run("sleep 1")
97
-
98
- group.run("sleep 1") do |exit_status|
99
- end
100
-
101
- group.wait
102
-
103
- end_time = Time.now
104
-
105
- # Check that the execution time was roughly 1 second:
106
- assert (0.9..1.1).include?(end_time - start_time)
107
- end
108
- end