systemu 2.4.2 → 2.5.0
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/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:
|