systemu 2.4.2 → 2.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +2 -1
- data/lib/systemu.rb +33 -27
- data/systemu.gemspec +5 -2
- data/test/systemu_test.rb +64 -0
- data/test/testing.rb +195 -0
- metadata +4 -2
data/README
CHANGED
data/lib/systemu.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
#
|
1
|
+
# encoding: utf-8
|
2
|
+
|
2
3
|
require 'tmpdir'
|
3
4
|
require 'socket'
|
4
5
|
require 'fileutils'
|
@@ -13,7 +14,7 @@ class SystemUniversal
|
|
13
14
|
#
|
14
15
|
# constants
|
15
16
|
#
|
16
|
-
SystemUniversal::VERSION = '2.
|
17
|
+
SystemUniversal::VERSION = '2.5.0' unless SystemUniversal.send(:const_defined?, :VERSION)
|
17
18
|
def SystemUniversal.version() SystemUniversal::VERSION end
|
18
19
|
def version() SystemUniversal::VERSION end
|
19
20
|
#
|
@@ -76,7 +77,7 @@ class SystemUniversal
|
|
76
77
|
line = pipe.gets
|
77
78
|
case line
|
78
79
|
when %r/^pid: \d+$/
|
79
|
-
cid = Integer line[%r/\d+/]
|
80
|
+
cid = Integer line[%r/\d+/]
|
80
81
|
else
|
81
82
|
begin
|
82
83
|
buf = pipe.read
|
@@ -120,12 +121,12 @@ class SystemUniversal
|
|
120
121
|
SystemUniversal.quote(*args, &block)
|
121
122
|
end
|
122
123
|
|
123
|
-
def new_thread cid, block
|
124
|
+
def new_thread cid, block
|
124
125
|
q = Queue.new
|
125
|
-
Thread.new(cid) do |cid|
|
126
|
-
current = Thread.current
|
126
|
+
Thread.new(cid) do |cid|
|
127
|
+
current = Thread.current
|
127
128
|
current.abort_on_exception = true
|
128
|
-
q.push current
|
129
|
+
q.push current
|
129
130
|
block.call cid
|
130
131
|
end
|
131
132
|
q.pop
|
@@ -150,10 +151,10 @@ class SystemUniversal
|
|
150
151
|
c['argv'] = @argv
|
151
152
|
c['env'] = @env
|
152
153
|
c['cwd'] = @cwd
|
153
|
-
c['stdin'] = stdin
|
154
|
-
c['stdout'] = stdout
|
155
|
-
c['stderr'] = stderr
|
156
|
-
c['program'] = program
|
154
|
+
c['stdin'] = stdin
|
155
|
+
c['stdout'] = stdout
|
156
|
+
c['stderr'] = stderr
|
157
|
+
c['program'] = program
|
157
158
|
open(config, 'w'){|f| Marshal.dump(c, f)}
|
158
159
|
|
159
160
|
open(program, 'w'){|f| f.write child_program(config)}
|
@@ -171,6 +172,8 @@ class SystemUniversal
|
|
171
172
|
|
172
173
|
def child_program config
|
173
174
|
<<-program
|
175
|
+
# encoding: utf-8
|
176
|
+
|
174
177
|
PIPE = STDOUT.dup
|
175
178
|
begin
|
176
179
|
config = Marshal.load(IO.read('#{ config }'))
|
@@ -190,7 +193,7 @@ class SystemUniversal
|
|
190
193
|
STDERR.reopen stderr
|
191
194
|
|
192
195
|
PIPE.puts "pid: \#{ Process.pid }"
|
193
|
-
PIPE.flush ### the process is ready yo!
|
196
|
+
PIPE.flush ### the process is ready yo!
|
194
197
|
PIPE.close
|
195
198
|
|
196
199
|
exec *argv
|
@@ -221,9 +224,9 @@ class SystemUniversal
|
|
221
224
|
tmp = File.join d, "systemu_#{ @host }_#{ @ppid }_#{ @pid }_#{ rand }_#{ i += 1 }"
|
222
225
|
|
223
226
|
begin
|
224
|
-
Dir.mkdir tmp
|
227
|
+
Dir.mkdir tmp
|
225
228
|
rescue Errno::EEXIST
|
226
|
-
raise if i >= max
|
229
|
+
raise if i >= max
|
227
230
|
next
|
228
231
|
end
|
229
232
|
|
@@ -232,7 +235,7 @@ class SystemUniversal
|
|
232
235
|
begin
|
233
236
|
b.call tmp
|
234
237
|
ensure
|
235
|
-
FileUtils.rm_rf tmp unless SystemU.turd
|
238
|
+
FileUtils.rm_rf tmp unless SystemU.turd
|
236
239
|
end
|
237
240
|
else
|
238
241
|
tmp
|
@@ -260,36 +263,39 @@ end
|
|
260
263
|
if defined? JRUBY_VERSION
|
261
264
|
require 'jruby'
|
262
265
|
java_import org.jruby.RubyProcess
|
263
|
-
|
266
|
+
|
264
267
|
class SystemUniversal
|
265
268
|
def systemu
|
266
269
|
split_argv = JRuby::PathHelper.smart_split_command @argv
|
267
270
|
process = java.lang.Runtime.runtime.exec split_argv.to_java(:string)
|
268
|
-
|
271
|
+
|
269
272
|
stdout, stderr = [process.input_stream, process.error_stream].map do |stream|
|
270
273
|
StreamReader.new(stream)
|
271
274
|
end
|
272
275
|
|
273
276
|
exit_code = process.wait_for
|
277
|
+
field = process.get_class.get_declared_field("pid")
|
278
|
+
field.set_accessible(true)
|
279
|
+
pid = field.get(process)
|
274
280
|
[
|
275
|
-
RubyProcess::RubyStatus.new_process_status(JRuby.runtime, exit_code),
|
276
|
-
stdout.join,
|
281
|
+
RubyProcess::RubyStatus.new_process_status(JRuby.runtime, exit_code, pid),
|
282
|
+
stdout.join,
|
277
283
|
stderr.join
|
278
284
|
]
|
279
285
|
end
|
280
|
-
|
286
|
+
|
281
287
|
class StreamReader
|
282
288
|
def initialize(stream)
|
283
289
|
@data = ""
|
284
290
|
@thread = Thread.new do
|
285
291
|
reader = java.io.BufferedReader.new java.io.InputStreamReader.new(stream)
|
286
|
-
|
292
|
+
|
287
293
|
while line = reader.read_line
|
288
294
|
@data << line << "\n"
|
289
295
|
end
|
290
296
|
end
|
291
297
|
end
|
292
|
-
|
298
|
+
|
293
299
|
def join
|
294
300
|
@thread.join
|
295
301
|
@data
|
@@ -297,7 +303,7 @@ if defined? JRUBY_VERSION
|
|
297
303
|
end
|
298
304
|
end
|
299
305
|
end
|
300
|
-
|
306
|
+
|
301
307
|
|
302
308
|
|
303
309
|
SystemU = SystemUniversal unless defined? SystemU
|
@@ -333,20 +339,20 @@ if $0 == __FILE__
|
|
333
339
|
# sleep
|
334
340
|
#
|
335
341
|
sleep = %q( ruby -e" p(sleep(1)) " )
|
336
|
-
status, stdout, stderr = systemu sleep
|
342
|
+
status, stdout, stderr = systemu sleep
|
337
343
|
p [status, stdout, stderr]
|
338
344
|
|
339
345
|
sleep = %q( ruby -e" p(sleep(42)) " )
|
340
346
|
status, stdout, stderr = systemu(sleep){|cid| Process.kill 9, cid}
|
341
347
|
p [status, stdout, stderr]
|
342
348
|
#
|
343
|
-
# env
|
349
|
+
# env
|
344
350
|
#
|
345
351
|
env = %q( ruby -e" p ENV['A'] " )
|
346
|
-
status, stdout, stderr = systemu env, :env => {'A' => 42}
|
352
|
+
status, stdout, stderr = systemu env, :env => {'A' => 42}
|
347
353
|
p [status, stdout, stderr]
|
348
354
|
#
|
349
|
-
# cwd
|
355
|
+
# cwd
|
350
356
|
#
|
351
357
|
env = %q( ruby -e" p Dir.pwd " )
|
352
358
|
status, stdout, stderr = systemu env, :cwd => Dir.tmpdir
|
data/systemu.gemspec
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
Gem::Specification::new do |spec|
|
5
5
|
spec.name = "systemu"
|
6
|
-
spec.version = "2.
|
6
|
+
spec.version = "2.5.0"
|
7
7
|
spec.platform = Gem::Platform::RUBY
|
8
8
|
spec.summary = "systemu"
|
9
9
|
spec.description = "description: systemu kicks the ass"
|
@@ -22,7 +22,10 @@ Gem::Specification::new do |spec|
|
|
22
22
|
"samples/d.rb",
|
23
23
|
"samples/e.rb",
|
24
24
|
"samples/f.rb",
|
25
|
-
"systemu.gemspec"
|
25
|
+
"systemu.gemspec",
|
26
|
+
"test",
|
27
|
+
"test/systemu_test.rb",
|
28
|
+
"test/testing.rb"]
|
26
29
|
|
27
30
|
spec.executables = []
|
28
31
|
|
@@ -0,0 +1,64 @@
|
|
1
|
+
|
2
|
+
Testing SystemU do
|
3
|
+
|
4
|
+
##
|
5
|
+
#
|
6
|
+
testing 'that simple usage works' do
|
7
|
+
status, stdout, stderr = assert{ systemu :bin/:ls }
|
8
|
+
assert{ status == 0 }
|
9
|
+
assert{ stdout['lib'] }
|
10
|
+
assert{ stderr.strip.empty? }
|
11
|
+
end
|
12
|
+
|
13
|
+
testing 'program with stdin' do
|
14
|
+
stdin = '42'
|
15
|
+
status, stdout, stderr = assert{ systemu :bin/:cat, :stdin => stdin }
|
16
|
+
assert{ status == 0 }
|
17
|
+
assert{ stdout == stdin }
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
|
26
|
+
BEGIN {
|
27
|
+
|
28
|
+
# silly hax to build commands we can shell out to on any platform. since
|
29
|
+
# tests might run on windoze we assume only that 'ruby' is available and build
|
30
|
+
# other command-line programs from it.
|
31
|
+
#
|
32
|
+
module Kernel
|
33
|
+
private
|
34
|
+
def bin(which, options = {}, &block)
|
35
|
+
case which.to_s
|
36
|
+
when 'ls'
|
37
|
+
%| ruby -e'puts Dir.glob("*").sort' |
|
38
|
+
|
39
|
+
when 'cat'
|
40
|
+
%| ruby -e'STDOUT.write(ARGF.read)' |
|
41
|
+
|
42
|
+
when 'find'
|
43
|
+
%| ruby -e'puts Dir.glob("**/**").sort' |
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# just let's us write: :bin/:ls
|
49
|
+
#
|
50
|
+
class Symbol
|
51
|
+
def / other, options = {}, &block
|
52
|
+
eval "#{ self }(:#{ other }, options, &block)"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
testdir = File.dirname(File.expand_path(__FILE__))
|
57
|
+
rootdir = File.dirname(testdir)
|
58
|
+
libdir = File.join(rootdir, 'lib')
|
59
|
+
require File.join(libdir, 'systemu')
|
60
|
+
require File.join(testdir, 'testing')
|
61
|
+
|
62
|
+
|
63
|
+
Dir.chdir(rootdir)
|
64
|
+
}
|
data/test/testing.rb
ADDED
@@ -0,0 +1,195 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
|
3
|
+
testdir = File.expand_path(File.dirname(__FILE__))
|
4
|
+
rootdir = File.dirname(testdir)
|
5
|
+
libdir = File.join(rootdir, 'lib')
|
6
|
+
|
7
|
+
STDOUT.sync = true
|
8
|
+
|
9
|
+
$:.unshift(testdir) unless $:.include?(testdir)
|
10
|
+
$:.unshift(libdir) unless $:.include?(libdir)
|
11
|
+
$:.unshift(rootdir) unless $:.include?(rootdir)
|
12
|
+
|
13
|
+
class Testing
|
14
|
+
class Slug < ::String
|
15
|
+
def Slug.for(*args)
|
16
|
+
string = args.flatten.compact.join('-')
|
17
|
+
words = string.to_s.scan(%r/\w+/)
|
18
|
+
words.map!{|word| word.gsub %r/[^0-9a-zA-Z_-]/, ''}
|
19
|
+
words.delete_if{|word| word.nil? or word.strip.empty?}
|
20
|
+
new(words.join('-').downcase)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class Context
|
25
|
+
attr_accessor :name
|
26
|
+
|
27
|
+
def initialize(name, *args)
|
28
|
+
@name = name
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_s
|
32
|
+
Slug.for(name)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def Testing(*args, &block)
|
38
|
+
Class.new(::Test::Unit::TestCase) do
|
39
|
+
|
40
|
+
## class methods
|
41
|
+
#
|
42
|
+
class << self
|
43
|
+
def contexts
|
44
|
+
@contexts ||= []
|
45
|
+
end
|
46
|
+
|
47
|
+
def context(*args, &block)
|
48
|
+
return contexts.last if(args.empty? and block.nil?)
|
49
|
+
|
50
|
+
context = Testing::Context.new(*args)
|
51
|
+
contexts.push(context)
|
52
|
+
|
53
|
+
begin
|
54
|
+
block.call(context)
|
55
|
+
ensure
|
56
|
+
contexts.pop
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def slug_for(*args)
|
61
|
+
string = [context, args].flatten.compact.join('-')
|
62
|
+
words = string.to_s.scan(%r/\w+/)
|
63
|
+
words.map!{|word| word.gsub %r/[^0-9a-zA-Z_-]/, ''}
|
64
|
+
words.delete_if{|word| word.nil? or word.strip.empty?}
|
65
|
+
words.join('-').downcase.sub(/_$/, '')
|
66
|
+
end
|
67
|
+
|
68
|
+
def name() const_get(:Name) end
|
69
|
+
|
70
|
+
def testno()
|
71
|
+
'%05d' % (@testno ||= 0)
|
72
|
+
ensure
|
73
|
+
@testno += 1
|
74
|
+
end
|
75
|
+
|
76
|
+
def testing(*args, &block)
|
77
|
+
method = ["test", testno, slug_for(*args)].delete_if{|part| part.empty?}.join('_')
|
78
|
+
define_method(method, &block)
|
79
|
+
end
|
80
|
+
|
81
|
+
def test(*args, &block)
|
82
|
+
testing(*args, &block)
|
83
|
+
end
|
84
|
+
|
85
|
+
def setup(&block)
|
86
|
+
define_method(:setup, &block) if block
|
87
|
+
end
|
88
|
+
|
89
|
+
def teardown(&block)
|
90
|
+
define_method(:teardown, &block) if block
|
91
|
+
end
|
92
|
+
|
93
|
+
def prepare(&block)
|
94
|
+
@prepare ||= []
|
95
|
+
@prepare.push(block) if block
|
96
|
+
@prepare
|
97
|
+
end
|
98
|
+
|
99
|
+
def cleanup(&block)
|
100
|
+
@cleanup ||= []
|
101
|
+
@cleanup.push(block) if block
|
102
|
+
@cleanup
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
## configure the subclass!
|
107
|
+
#
|
108
|
+
const_set(:Testno, '0')
|
109
|
+
slug = slug_for(*args).gsub(%r/-/,'_')
|
110
|
+
name = ['TESTING', '%03d' % const_get(:Testno), slug].delete_if{|part| part.empty?}.join('_')
|
111
|
+
name = name.upcase!
|
112
|
+
const_set(:Name, name)
|
113
|
+
const_set(:Missing, Object.new.freeze)
|
114
|
+
|
115
|
+
## instance methods
|
116
|
+
#
|
117
|
+
alias_method('__assert__', 'assert')
|
118
|
+
|
119
|
+
def assert(*args, &block)
|
120
|
+
if args.size == 1 and args.first.is_a?(Hash)
|
121
|
+
options = args.first
|
122
|
+
expected = getopt(:expected, options){ missing }
|
123
|
+
actual = getopt(:actual, options){ missing }
|
124
|
+
if expected == missing and actual == missing
|
125
|
+
actual, expected, *ignored = options.to_a.flatten
|
126
|
+
end
|
127
|
+
expected = expected.call() if expected.respond_to?(:call)
|
128
|
+
actual = actual.call() if actual.respond_to?(:call)
|
129
|
+
assert_equal(expected, actual)
|
130
|
+
end
|
131
|
+
|
132
|
+
if block
|
133
|
+
label = "assert(#{ args.join(' ') })"
|
134
|
+
result = nil
|
135
|
+
assert_nothing_raised{ result = block.call }
|
136
|
+
__assert__(result, label)
|
137
|
+
result
|
138
|
+
else
|
139
|
+
result = args.shift
|
140
|
+
label = "assert(#{ args.join(' ') })"
|
141
|
+
__assert__(result, label)
|
142
|
+
result
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def missing
|
147
|
+
self.class.const_get(:Missing)
|
148
|
+
end
|
149
|
+
|
150
|
+
def getopt(opt, hash, options = nil, &block)
|
151
|
+
[opt.to_s, opt.to_s.to_sym].each do |key|
|
152
|
+
return hash[key] if hash.has_key?(key)
|
153
|
+
end
|
154
|
+
default =
|
155
|
+
if block
|
156
|
+
block.call
|
157
|
+
else
|
158
|
+
options.is_a?(Hash) ? options[:default] : nil
|
159
|
+
end
|
160
|
+
return default
|
161
|
+
end
|
162
|
+
|
163
|
+
def subclass_of exception
|
164
|
+
class << exception
|
165
|
+
def ==(other) super or self > other end
|
166
|
+
end
|
167
|
+
exception
|
168
|
+
end
|
169
|
+
|
170
|
+
##
|
171
|
+
#
|
172
|
+
module_eval(&block)
|
173
|
+
|
174
|
+
self.setup()
|
175
|
+
self.prepare.each{|b| b.call()}
|
176
|
+
|
177
|
+
at_exit{
|
178
|
+
self.teardown()
|
179
|
+
self.cleanup.each{|b| b.call()}
|
180
|
+
}
|
181
|
+
|
182
|
+
self
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
|
187
|
+
if $0 == __FILE__
|
188
|
+
|
189
|
+
Testing 'Testing' do
|
190
|
+
testing('foo'){ assert true }
|
191
|
+
test{ assert true }
|
192
|
+
p instance_methods.grep(/test/)
|
193
|
+
end
|
194
|
+
|
195
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: systemu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.5.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2012-03-13 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: ! 'description: systemu kicks the ass'
|
15
15
|
email: ara.t.howard@gmail.com
|
@@ -29,6 +29,8 @@ files:
|
|
29
29
|
- samples/e.rb
|
30
30
|
- samples/f.rb
|
31
31
|
- systemu.gemspec
|
32
|
+
- test/systemu_test.rb
|
33
|
+
- test/testing.rb
|
32
34
|
homepage: https://github.com/ahoward/systemu
|
33
35
|
licenses: []
|
34
36
|
post_install_message:
|