costan-zerg_support 0.0.9
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/CHANGELOG +17 -0
- data/LICENSE +21 -0
- data/Manifest +22 -0
- data/README +0 -0
- data/RUBYFORGE +40 -0
- data/Rakefile +26 -0
- data/lib/zerg_support/event_machine/connection_mocks.rb +46 -0
- data/lib/zerg_support/event_machine/frame_protocol.rb +68 -0
- data/lib/zerg_support/event_machine/object_protocol.rb +24 -0
- data/lib/zerg_support/gems.rb +60 -0
- data/lib/zerg_support/open_ssh.rb +104 -0
- data/lib/zerg_support/process.rb +225 -0
- data/lib/zerg_support/spawn.rb +185 -0
- data/lib/zerg_support.rb +21 -0
- data/test/fork_tree.rb +34 -0
- data/test/test_connection_mocks.rb +57 -0
- data/test/test_frame_protocol.rb +119 -0
- data/test/test_gems.rb +29 -0
- data/test/test_object_protocol.rb +55 -0
- data/test/test_open_ssh.rb +125 -0
- data/test/test_process.rb +78 -0
- data/test/test_spawn.rb +163 -0
- data/zerg_support.gemspec +41 -0
- metadata +125 -0
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'English'
|
2
|
+
require 'test/unit'
|
3
|
+
|
4
|
+
require 'zerg_support'
|
5
|
+
|
6
|
+
class TestProcess < Test::Unit::TestCase
|
7
|
+
def teardown
|
8
|
+
@pid_files.each { |f| File.delete f rescue nil } if @pid_files
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_process_info
|
13
|
+
info = Zerg::Support::Process.process_info($PID)
|
14
|
+
assert info, 'Failed to find current process'
|
15
|
+
|
16
|
+
$ARGV.each do |arg|
|
17
|
+
assert info[:command_line].index(arg),
|
18
|
+
"Command line for current process does not contain argument #{arg}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_process_list_contains_current_process
|
23
|
+
list = Zerg::Support::Process.processes_by_id
|
24
|
+
|
25
|
+
assert list[$PID], 'Process list does not contain current process'
|
26
|
+
end
|
27
|
+
|
28
|
+
# spawn 2^(exp+1)-1 children, and their command lines will contain "cookie"
|
29
|
+
def spawn_sleepers(exp, cookie)
|
30
|
+
Thread.new { system "ruby test/fork_tree.rb -- #{exp} 100 #{cookie}" }
|
31
|
+
on_windows = RUBY_PLATFORM =~ /win/ && RUBY_PLATFORM !~ /darwin/
|
32
|
+
sleep on_windows ? 0.5 : 0.1
|
33
|
+
pid_file = "#{cookie}.pid"
|
34
|
+
@pid_files ||= []
|
35
|
+
@pid_files << pid_file
|
36
|
+
pid = File.read(pid_file).to_i
|
37
|
+
sleep on_windows ? 0.4 : 0.5
|
38
|
+
return pid
|
39
|
+
end
|
40
|
+
|
41
|
+
def now_cookie
|
42
|
+
"zerg_test_#{Time.now.to_f}s"
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_process_tree
|
46
|
+
cookie = now_cookie
|
47
|
+
root_pid = spawn_sleepers 3, cookie
|
48
|
+
|
49
|
+
tree_processes = Zerg::Support::Process.process_tree root_pid
|
50
|
+
assert_equal 15, tree_processes.length, 'Missed some processes'
|
51
|
+
assert tree_processes.all? { |info| info[:command_line].index cookie },
|
52
|
+
'Got the wrong processes'
|
53
|
+
|
54
|
+
Zerg::Support::Process.kill_tree root_pid
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_kill
|
58
|
+
cookie = now_cookie
|
59
|
+
victim_pid = spawn_sleepers 0, cookie
|
60
|
+
|
61
|
+
Zerg::Support::Process.kill victim_pid
|
62
|
+
sleep 0.5
|
63
|
+
processes = Zerg::Support::Process.processes
|
64
|
+
assert_equal nil, processes[victim_pid], 'Victim was not killed'
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_kill_tree
|
68
|
+
cookie = now_cookie
|
69
|
+
root_pid = spawn_sleepers 3, cookie
|
70
|
+
|
71
|
+
Zerg::Support::Process.kill_tree root_pid
|
72
|
+
sleep 0.5
|
73
|
+
processes = Zerg::Support::Process.processes
|
74
|
+
escaped = processes.select { |info| info[:command_line].index cookie }
|
75
|
+
|
76
|
+
assert_equal [], escaped, 'Some process(es) escaped'
|
77
|
+
end
|
78
|
+
end
|
data/test/test_spawn.rb
ADDED
@@ -0,0 +1,163 @@
|
|
1
|
+
require 'digest/sha1'
|
2
|
+
require 'test/unit'
|
3
|
+
|
4
|
+
require 'zerg_support'
|
5
|
+
|
6
|
+
require 'rubygems'
|
7
|
+
require 'flexmock/test_unit'
|
8
|
+
|
9
|
+
class TestSpawn < Test::Unit::TestCase
|
10
|
+
def temp_file
|
11
|
+
now_cookie = "zerg_test_#{Time.now.to_f}s"
|
12
|
+
File.open(now_cookie, 'w') {}
|
13
|
+
return now_cookie
|
14
|
+
end
|
15
|
+
|
16
|
+
def setup
|
17
|
+
super
|
18
|
+
@in_file = temp_file
|
19
|
+
@out_file = temp_file
|
20
|
+
end
|
21
|
+
|
22
|
+
def teardown
|
23
|
+
File.delete @in_file rescue nil
|
24
|
+
File.delete @out_file rescue nil
|
25
|
+
super
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_stdout_redirect
|
29
|
+
pid = Zerg::Support::Process.spawn 'ruby', ['-e', 'print "1234\n"'],
|
30
|
+
STDOUT => @out_file
|
31
|
+
Process.waitpid pid
|
32
|
+
|
33
|
+
assert_equal "1234\n", File.read(@out_file)
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_stdin_redirect
|
37
|
+
File.open(@in_file, 'w') { |f| f.write "1234\n" }
|
38
|
+
|
39
|
+
pid = Zerg::Support::Process.spawn 'ruby', ['-e', "print gets"],
|
40
|
+
STDIN => @in_file, STDOUT => @out_file
|
41
|
+
Process.waitpid pid
|
42
|
+
assert_equal "1234\n", File.read(@out_file)
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_stderr_redirect
|
46
|
+
pid = Zerg::Support::Process.spawn 'ruby', ['-e', "raise 'zerg_stderr'"],
|
47
|
+
STDERR => @out_file
|
48
|
+
Process.waitpid pid
|
49
|
+
assert_equal "-e:1: zerg_stderr (RuntimeError)\n", File.read(@out_file)
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_redirect_cascade
|
53
|
+
pid = Zerg::Support::Process.spawn 'ruby',
|
54
|
+
['-e', "print 1; raise 'zerg_stderr'"],
|
55
|
+
STDOUT => @out_file, STDERR => STDOUT
|
56
|
+
Process.waitpid pid
|
57
|
+
assert_operator ["1-e:1: zerg_stderr (RuntimeError)\n",
|
58
|
+
"-e:1: zerg_stderr (RuntimeError)\n1"],
|
59
|
+
:include?, File.read(@out_file)
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_redirect_share
|
63
|
+
pid = Zerg::Support::Process.spawn 'ruby',
|
64
|
+
['-e', "print 1; raise 'zerg_stderr'"],
|
65
|
+
STDOUT => @out_file, STDERR => @out_file
|
66
|
+
Process.waitpid pid
|
67
|
+
assert_operator ["1-e:1: zerg_stderr (RuntimeError)\n",
|
68
|
+
"-e:1: zerg_stderr (RuntimeError)\n1"],
|
69
|
+
:include?, File.read(@out_file)
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_async
|
73
|
+
t0 = Time.now
|
74
|
+
pid = Zerg::Support::Process.spawn 'ruby', ['-e', 'sleep 0.5']
|
75
|
+
t1 = Time.now
|
76
|
+
Process.waitpid pid
|
77
|
+
t2 = Time.now
|
78
|
+
|
79
|
+
assert_operator t1 - t0, :<, 0.2, 'Spawning is not asynchronous'
|
80
|
+
assert_operator t2 - t0, :>, 0.5,
|
81
|
+
'The spawned program did not sleep for 1 second'
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_set_environment
|
85
|
+
pid = Zerg::Support::Process.spawn 'ruby', ['-e', 'print ENV[\'XA\']'],
|
86
|
+
STDOUT => @out_file, :env => {'XA' => "1234\n"}
|
87
|
+
Process.waitpid pid
|
88
|
+
assert_equal "1234\n", File.read(@out_file)
|
89
|
+
|
90
|
+
pid = Zerg::Support::Process.spawn 'ruby', ['-e', 'print ENV[\'PATH\']'],
|
91
|
+
STDOUT => @in_file, :env => {'XA' => "1234\n"}, :unsetenv_others => true
|
92
|
+
Process.waitpid pid
|
93
|
+
# clearing the environment will reset PATH, so ruby might not run at all
|
94
|
+
output = File.read(@in_file)
|
95
|
+
assert output == 'nil' || output == '', 'The environment was not cleared'
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_close_fd
|
99
|
+
in_file = File.open(@in_file, 'w')
|
100
|
+
in_file.sync = true
|
101
|
+
in_file.write "1234\n"
|
102
|
+
in_file.close
|
103
|
+
|
104
|
+
in_file = File.open(@in_file, 'r')
|
105
|
+
|
106
|
+
in_fd = in_file.fileno
|
107
|
+
read_fd_code = "File.open(#{in_fd}).read"
|
108
|
+
assert_equal "1234\n", eval(read_fd_code), 'File reading code is broken'
|
109
|
+
|
110
|
+
pid = Zerg::Support::Process.spawn 'ruby', ['-e', "print #{read_fd_code}"],
|
111
|
+
STDOUT => @out_file, STDERR => STDOUT
|
112
|
+
Process.waitpid pid
|
113
|
+
in_file.close
|
114
|
+
|
115
|
+
assert_equal "-e:1:", File.read(@out_file)[0, 5],
|
116
|
+
'Spawn does not close file descriptors'
|
117
|
+
end
|
118
|
+
|
119
|
+
def test_rlimit_processing
|
120
|
+
if RUBY_PLATFORM =~ /win/ and RUBY_PLATFORM !~ /darwin/
|
121
|
+
Process.const_set :RLIMIT_CPU, 'rlimit_cpu'
|
122
|
+
Process.const_set :RLIMIT_RSS, 'rlimit_rss'
|
123
|
+
end
|
124
|
+
|
125
|
+
flexmock(Process).should_receive(:setrlimit).
|
126
|
+
with(Process::RLIMIT_CPU, 1, 5).once.and_return(nil)
|
127
|
+
flexmock(Process).should_receive(:setrlimit).
|
128
|
+
with(Process::RLIMIT_RSS, 64 * 1024 * 1024).once.
|
129
|
+
and_return(nil)
|
130
|
+
|
131
|
+
Zerg::Support::Process::Helpers.set_rlimits :rlimit_cpu => [1, 5],
|
132
|
+
:rlimit_rss => 64 * 1024 * 1024
|
133
|
+
end
|
134
|
+
|
135
|
+
def test_process_group_processing
|
136
|
+
flexmock(Process).should_receive(:setpgid).with(0, 42).once.and_return(nil)
|
137
|
+
flexmock(Process).should_receive(:setsid).with().once.and_return(nil)
|
138
|
+
|
139
|
+
Zerg::Support::Process::Helpers.set_process_group :pgroup => 42
|
140
|
+
Zerg::Support::Process::Helpers.set_process_group :pgroup => true
|
141
|
+
end
|
142
|
+
|
143
|
+
def test_process_group
|
144
|
+
pid = Zerg::Support::Process.spawn 'ruby', ['-e', "sleep 0.5"],
|
145
|
+
:pgroup => true
|
146
|
+
pinfo = Zerg::Support::Process::process_info pid
|
147
|
+
Process.waitpid pid
|
148
|
+
|
149
|
+
assert pinfo[:state].index('s'), 'Failed to become session leader'
|
150
|
+
end
|
151
|
+
|
152
|
+
def test_rlimits
|
153
|
+
t0 = Time.now
|
154
|
+
pid = Zerg::Support::Process.spawn 'ruby',
|
155
|
+
['-e', "i = 0; t0 = Time.now; i += 1 while Time.now - t0 < 3.0"],
|
156
|
+
:rlimit_cpu => 1
|
157
|
+
Process.waitpid pid
|
158
|
+
t1 = Time.now
|
159
|
+
|
160
|
+
assert_operator t1 - t0, :>=, 0.95, 'Spawning failed'
|
161
|
+
assert_operator t1 - t0, :<=, 2.0, 'Failed to apply rlimit_cpu'
|
162
|
+
end
|
163
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{zerg_support}
|
5
|
+
s.version = "0.0.9"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Victor Costan"]
|
9
|
+
s.date = %q{2009-03-28}
|
10
|
+
s.description = %q{Support libraries used by Zergling.Net deployment code.}
|
11
|
+
s.email = %q{victor@zergling.net}
|
12
|
+
s.extra_rdoc_files = ["CHANGELOG", "lib/zerg_support/event_machine/connection_mocks.rb", "lib/zerg_support/event_machine/frame_protocol.rb", "lib/zerg_support/event_machine/object_protocol.rb", "lib/zerg_support/gems.rb", "lib/zerg_support/open_ssh.rb", "lib/zerg_support/process.rb", "lib/zerg_support/spawn.rb", "lib/zerg_support.rb", "LICENSE", "README"]
|
13
|
+
s.files = ["CHANGELOG", "lib/zerg_support/event_machine/connection_mocks.rb", "lib/zerg_support/event_machine/frame_protocol.rb", "lib/zerg_support/event_machine/object_protocol.rb", "lib/zerg_support/gems.rb", "lib/zerg_support/open_ssh.rb", "lib/zerg_support/process.rb", "lib/zerg_support/spawn.rb", "lib/zerg_support.rb", "LICENSE", "Manifest", "Rakefile", "README", "RUBYFORGE", "test/fork_tree.rb", "test/test_connection_mocks.rb", "test/test_frame_protocol.rb", "test/test_gems.rb", "test/test_object_protocol.rb", "test/test_open_ssh.rb", "test/test_process.rb", "test/test_spawn.rb", "zerg_support.gemspec"]
|
14
|
+
s.has_rdoc = true
|
15
|
+
s.homepage = %q{http://www.zergling.net}
|
16
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Zerg_support", "--main", "README"]
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
s.rubyforge_project = %q{zerglings}
|
19
|
+
s.rubygems_version = %q{1.3.1}
|
20
|
+
s.summary = %q{Support libraries used by Zergling.Net deployment code.}
|
21
|
+
s.test_files = ["test/test_connection_mocks.rb", "test/test_frame_protocol.rb", "test/test_gems.rb", "test/test_object_protocol.rb", "test/test_open_ssh.rb", "test/test_process.rb", "test/test_spawn.rb"]
|
22
|
+
|
23
|
+
if s.respond_to? :specification_version then
|
24
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
25
|
+
s.specification_version = 2
|
26
|
+
|
27
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
28
|
+
s.add_development_dependency(%q<echoe>, [">= 3.0.2"])
|
29
|
+
s.add_development_dependency(%q<event_machine>, [">= 0.12.2"])
|
30
|
+
s.add_development_dependency(%q<flexmock>, [">= 0.8.3"])
|
31
|
+
else
|
32
|
+
s.add_dependency(%q<echoe>, [">= 3.0.2"])
|
33
|
+
s.add_dependency(%q<event_machine>, [">= 0.12.2"])
|
34
|
+
s.add_dependency(%q<flexmock>, [">= 0.8.3"])
|
35
|
+
end
|
36
|
+
else
|
37
|
+
s.add_dependency(%q<echoe>, [">= 3.0.2"])
|
38
|
+
s.add_dependency(%q<event_machine>, [">= 0.12.2"])
|
39
|
+
s.add_dependency(%q<flexmock>, [">= 0.8.3"])
|
40
|
+
end
|
41
|
+
end
|
metadata
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: costan-zerg_support
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.9
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Victor Costan
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-03-28 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: echoe
|
17
|
+
type: :development
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 3.0.2
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: event_machine
|
27
|
+
type: :development
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.12.2
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: flexmock
|
37
|
+
type: :development
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 0.8.3
|
44
|
+
version:
|
45
|
+
description: Support libraries used by Zergling.Net deployment code.
|
46
|
+
email: victor@zergling.net
|
47
|
+
executables: []
|
48
|
+
|
49
|
+
extensions: []
|
50
|
+
|
51
|
+
extra_rdoc_files:
|
52
|
+
- CHANGELOG
|
53
|
+
- lib/zerg_support/event_machine/connection_mocks.rb
|
54
|
+
- lib/zerg_support/event_machine/frame_protocol.rb
|
55
|
+
- lib/zerg_support/event_machine/object_protocol.rb
|
56
|
+
- lib/zerg_support/gems.rb
|
57
|
+
- lib/zerg_support/open_ssh.rb
|
58
|
+
- lib/zerg_support/process.rb
|
59
|
+
- lib/zerg_support/spawn.rb
|
60
|
+
- lib/zerg_support.rb
|
61
|
+
- LICENSE
|
62
|
+
- README
|
63
|
+
files:
|
64
|
+
- CHANGELOG
|
65
|
+
- lib/zerg_support/event_machine/connection_mocks.rb
|
66
|
+
- lib/zerg_support/event_machine/frame_protocol.rb
|
67
|
+
- lib/zerg_support/event_machine/object_protocol.rb
|
68
|
+
- lib/zerg_support/gems.rb
|
69
|
+
- lib/zerg_support/open_ssh.rb
|
70
|
+
- lib/zerg_support/process.rb
|
71
|
+
- lib/zerg_support/spawn.rb
|
72
|
+
- lib/zerg_support.rb
|
73
|
+
- LICENSE
|
74
|
+
- Manifest
|
75
|
+
- Rakefile
|
76
|
+
- README
|
77
|
+
- RUBYFORGE
|
78
|
+
- test/fork_tree.rb
|
79
|
+
- test/test_connection_mocks.rb
|
80
|
+
- test/test_frame_protocol.rb
|
81
|
+
- test/test_gems.rb
|
82
|
+
- test/test_object_protocol.rb
|
83
|
+
- test/test_open_ssh.rb
|
84
|
+
- test/test_process.rb
|
85
|
+
- test/test_spawn.rb
|
86
|
+
- zerg_support.gemspec
|
87
|
+
has_rdoc: true
|
88
|
+
homepage: http://www.zergling.net
|
89
|
+
post_install_message:
|
90
|
+
rdoc_options:
|
91
|
+
- --line-numbers
|
92
|
+
- --inline-source
|
93
|
+
- --title
|
94
|
+
- Zerg_support
|
95
|
+
- --main
|
96
|
+
- README
|
97
|
+
require_paths:
|
98
|
+
- lib
|
99
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: "0"
|
104
|
+
version:
|
105
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: "1.2"
|
110
|
+
version:
|
111
|
+
requirements: []
|
112
|
+
|
113
|
+
rubyforge_project: zerglings
|
114
|
+
rubygems_version: 1.2.0
|
115
|
+
signing_key:
|
116
|
+
specification_version: 2
|
117
|
+
summary: Support libraries used by Zergling.Net deployment code.
|
118
|
+
test_files:
|
119
|
+
- test/test_connection_mocks.rb
|
120
|
+
- test/test_frame_protocol.rb
|
121
|
+
- test/test_gems.rb
|
122
|
+
- test/test_object_protocol.rb
|
123
|
+
- test/test_open_ssh.rb
|
124
|
+
- test/test_process.rb
|
125
|
+
- test/test_spawn.rb
|