test-cmd.rb 0.12.4 → 1.0.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +8 -4
- data/Gemfile +0 -0
- data/README.md +14 -7
- data/Rakefile.rb +0 -0
- data/lib/test/cmd.rb +112 -56
- data/test-cmd.rb.gemspec +3 -4
- metadata +7 -12
- data/.gitlab-ci.yml +0 -16
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ceedd530e04b4429280815527f9c18213db595390d6c554854a843c9c9a7717e
|
|
4
|
+
data.tar.gz: 98ad59766cd5aa84d4fbed39ca8d2465fd6be4fa3d7895707f6341fbad37e6c4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f25e60111e111074f5dd1cdba6ba10f7074a5a2fbe9ddbf57ef08a3d1ecc1096e4119331c98ab74736b689aedf8c5f4b784cd18db7255bb7df01de314a1b1dd5
|
|
7
|
+
data.tar.gz: 368188e8228ea2974e2db19d284efabb70ce3a0a2c773d73e372078a82034fa93e69ff9e586c62fc570b49039f4bc759d1b0da1cf8e240ac7f3b631893d5dff3
|
data/.rubocop.yml
CHANGED
|
@@ -8,16 +8,20 @@ require:
|
|
|
8
8
|
inherit_gem:
|
|
9
9
|
standard: config/base.yml
|
|
10
10
|
|
|
11
|
+
##
|
|
12
|
+
# Enabled
|
|
11
13
|
AllCops:
|
|
12
14
|
TargetRubyVersion: 3.1
|
|
13
15
|
Include:
|
|
14
16
|
- 'lib/**/*.rb'
|
|
15
17
|
- 'test/**/*.rb'
|
|
16
18
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
- 'lib/test-cmd.rb'
|
|
20
|
-
|
|
19
|
+
##
|
|
20
|
+
# Disabled
|
|
21
21
|
Layout/MultilineMethodCallIndentation:
|
|
22
22
|
Exclude:
|
|
23
23
|
- 'test/*.rb'
|
|
24
|
+
Layout/ArgumentAlignment:
|
|
25
|
+
Enabled: false
|
|
26
|
+
Style/MultilineIfModifier:
|
|
27
|
+
Enabled: false
|
data/Gemfile
CHANGED
|
File without changes
|
data/README.md
CHANGED
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
## About
|
|
2
2
|
|
|
3
3
|
test-cmd.rb provides an object-oriented interface for spawning
|
|
4
|
-
a command.
|
|
4
|
+
a command on UNIX-like operating systems. The library is intended
|
|
5
|
+
to be simple, lightweight, and easy to use.
|
|
5
6
|
|
|
6
7
|
## Examples
|
|
7
8
|
|
|
8
|
-
###
|
|
9
|
+
### Commands
|
|
10
|
+
|
|
11
|
+
#### Callbacks
|
|
9
12
|
|
|
10
13
|
The success and failure callbacks provide hooks for when
|
|
11
14
|
a command exits successfully or unsuccessfully. The callbacks
|
|
12
15
|
are passed an instance of
|
|
13
|
-
[Test::Cmd](https://0x1eef.github.io/x/test-cmd.rb/Test/Cmd.html)
|
|
16
|
+
[Test::Cmd](https://0x1eef.github.io/x/test-cmd.rb/Test/Cmd.html)
|
|
17
|
+
that has access to the command's process ID, exit status,
|
|
18
|
+
standard ouput stream, and standard error stream:
|
|
14
19
|
|
|
15
20
|
``` ruby
|
|
16
21
|
require "test-cmd"
|
|
@@ -19,12 +24,14 @@ cmd("ruby", "-e", "exit 0")
|
|
|
19
24
|
.failure { print "The command [#{_1.pid}] was unsuccessful", "\n" }
|
|
20
25
|
```
|
|
21
26
|
|
|
22
|
-
|
|
27
|
+
#### Assertions
|
|
23
28
|
|
|
24
29
|
The following example demonstrates how tests might be written with
|
|
25
30
|
test-unit from the standard library. The
|
|
26
31
|
[`cmd`](https://0x1eef.github.io/x/test-cmd.rb/Kernel.html#cmd-instance_method)
|
|
27
|
-
method takes the name or path of a command, alongside any arguments
|
|
32
|
+
method takes the name or path of a command, alongside any arguments. The tests
|
|
33
|
+
assert against the exit status, standard output stream, and standard error
|
|
34
|
+
stream of the spawned ruby process:
|
|
28
35
|
|
|
29
36
|
```ruby
|
|
30
37
|
require "test/unit"
|
|
@@ -68,8 +75,8 @@ test-cmd.rb can be installed via rubygems.org:
|
|
|
68
75
|
|
|
69
76
|
## Sources
|
|
70
77
|
|
|
71
|
-
* [
|
|
72
|
-
* [
|
|
78
|
+
* [github.com/@0x1eef](https://github.com/0x1eef/test-cmd.rb#readme)
|
|
79
|
+
* [gitlab.com/@0x1eef](https://gitlab.com/0x1eef/test-cmd.rb#about)
|
|
73
80
|
|
|
74
81
|
## License
|
|
75
82
|
|
data/Rakefile.rb
CHANGED
|
File without changes
|
data/lib/test/cmd.rb
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
end
|
|
4
|
-
end
|
|
1
|
+
module Test
|
|
2
|
+
end unless defined?(Test)
|
|
5
3
|
|
|
6
4
|
##
|
|
7
5
|
# test-cmd.rb provides an object oriented interface
|
|
8
|
-
# for spawning a command
|
|
6
|
+
# for spawning a command
|
|
9
7
|
class Test::Cmd
|
|
10
8
|
##
|
|
11
9
|
# @api private
|
|
@@ -48,51 +46,19 @@ class Test::Cmd
|
|
|
48
46
|
# @return [Test::Cmd]
|
|
49
47
|
def spawn
|
|
50
48
|
return self if @spawned
|
|
51
|
-
|
|
52
49
|
tap do
|
|
53
|
-
out, err = Pipe.pair, Pipe.pair
|
|
54
50
|
@spawned = true
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
Process.wait
|
|
58
|
-
@status = $?
|
|
59
|
-
rescue Errno::ENOENT => ex
|
|
60
|
-
@cmd, @argv, @stderr = "false", [], ex.message
|
|
61
|
-
@enoent = true
|
|
62
|
-
retry
|
|
63
|
-
end
|
|
64
|
-
loop do
|
|
65
|
-
io, _ = IO.select([out.r, err.r], nil, nil, 0.01)
|
|
66
|
-
io&.include?(out.r) ? @stdout << out.r.read(1) : nil
|
|
67
|
-
io&.include?(err.r) ? @stderr << err.r.read(1) : nil
|
|
68
|
-
break unless t.alive? || IO.select([out.r, err.r], nil, nil, 0.01)
|
|
69
|
-
end
|
|
70
|
-
ensure
|
|
71
|
-
[out, err].each(&:close)
|
|
51
|
+
@out, @err = Pipe.pair, Pipe.pair
|
|
52
|
+
produce(@out, @err)
|
|
72
53
|
end
|
|
73
54
|
end
|
|
74
55
|
|
|
75
|
-
##
|
|
76
|
-
# @return [String]
|
|
77
|
-
# Returns the contents of stdout
|
|
78
|
-
def stdout
|
|
79
|
-
spawn
|
|
80
|
-
@stdout
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
##
|
|
84
|
-
# @return [String]
|
|
85
|
-
# Returns the contents of stderr
|
|
86
|
-
def stderr
|
|
87
|
-
spawn
|
|
88
|
-
@stderr
|
|
89
|
-
end
|
|
90
|
-
|
|
91
56
|
##
|
|
92
57
|
# @return [Process::Status]
|
|
93
58
|
# Returns the status of a process
|
|
94
59
|
def status
|
|
95
60
|
spawn
|
|
61
|
+
consume(@producer, @out, @err)
|
|
96
62
|
@status
|
|
97
63
|
end
|
|
98
64
|
|
|
@@ -111,6 +77,31 @@ class Test::Cmd
|
|
|
111
77
|
end
|
|
112
78
|
alias_method :exitstatus, :exit_status
|
|
113
79
|
|
|
80
|
+
##
|
|
81
|
+
# @group IO
|
|
82
|
+
|
|
83
|
+
##
|
|
84
|
+
# @return [String]
|
|
85
|
+
# Returns the contents of stdout
|
|
86
|
+
def stdout
|
|
87
|
+
spawn
|
|
88
|
+
consume(@producer, @out, @err)
|
|
89
|
+
@stdout
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
##
|
|
93
|
+
# @return [String]
|
|
94
|
+
# Returns the contents of stderr
|
|
95
|
+
def stderr
|
|
96
|
+
spawn
|
|
97
|
+
consume(@producer, @out, @err)
|
|
98
|
+
@stderr
|
|
99
|
+
end
|
|
100
|
+
# @endgroup
|
|
101
|
+
|
|
102
|
+
##
|
|
103
|
+
# @group Predicates
|
|
104
|
+
|
|
114
105
|
##
|
|
115
106
|
# @return [Boolean]
|
|
116
107
|
# Returns true when a command exited successfully
|
|
@@ -119,52 +110,117 @@ class Test::Cmd
|
|
|
119
110
|
end
|
|
120
111
|
|
|
121
112
|
##
|
|
122
|
-
#
|
|
123
|
-
#
|
|
113
|
+
# @return [Boolean]
|
|
114
|
+
# Returns true when a command has been spawned
|
|
115
|
+
def spawned?
|
|
116
|
+
@spawned
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
##
|
|
120
|
+
# @return [Boolean]
|
|
121
|
+
# Returns true when a command is running
|
|
122
|
+
def alive?
|
|
123
|
+
@producer&.alive?
|
|
124
|
+
end
|
|
125
|
+
alias_method :running?, :alive?
|
|
126
|
+
|
|
127
|
+
##
|
|
128
|
+
# Sends SIGKILL to a running command
|
|
129
|
+
# @return [void]
|
|
130
|
+
def kill!
|
|
131
|
+
return unless alive?
|
|
132
|
+
Process.kill("SIGKILL", @pid)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
##
|
|
136
|
+
# @return [Boolean]
|
|
137
|
+
# Returns true when a command can't be found
|
|
138
|
+
def command_not_found?
|
|
139
|
+
spawn
|
|
140
|
+
consume(@producer, @out, @err)
|
|
141
|
+
@enoent
|
|
142
|
+
end
|
|
143
|
+
alias_method :not_found?, :command_not_found?
|
|
144
|
+
# @endgroup
|
|
145
|
+
|
|
146
|
+
##
|
|
147
|
+
# @group Callbacks
|
|
148
|
+
|
|
149
|
+
##
|
|
150
|
+
# @yieldparam [Test::Cmd] cmd
|
|
151
|
+
# Yields an instance of {Test::Cmd Test::Cmd}
|
|
124
152
|
# @example
|
|
125
153
|
# cmd("ruby", "-e", "exit 0")
|
|
126
154
|
# .success { print "Command [#{_1.pid}] exited successfully", "\n" }
|
|
127
155
|
# .failure { }
|
|
128
|
-
#
|
|
129
156
|
# @return [Test::Cmd]
|
|
130
157
|
def success
|
|
131
158
|
tap do
|
|
132
159
|
spawn
|
|
160
|
+
consume(@producer, @out, @err)
|
|
133
161
|
status.success? ? yield(self) : nil
|
|
134
162
|
end
|
|
135
163
|
end
|
|
136
164
|
|
|
137
165
|
##
|
|
138
|
-
#
|
|
139
|
-
#
|
|
166
|
+
# @yieldparam [Test::Cmd] cmd
|
|
167
|
+
# Yields an instance of {Test::Cmd Test::Cmd}
|
|
140
168
|
# @example
|
|
141
169
|
# cmd("ruby", "-e", "exit 1")
|
|
142
170
|
# .success { }
|
|
143
171
|
# .failure { print "Command [#{_1.pid}] exited unsuccessfully", "\n" }
|
|
144
|
-
#
|
|
145
172
|
# @return [Test::Cmd]
|
|
146
173
|
def failure
|
|
147
174
|
tap do
|
|
148
175
|
spawn
|
|
176
|
+
consume(@producer, @out, @err)
|
|
149
177
|
status.success? ? nil : yield(self)
|
|
150
178
|
end
|
|
151
179
|
end
|
|
180
|
+
# @endgroup
|
|
181
|
+
|
|
182
|
+
private
|
|
152
183
|
|
|
153
184
|
##
|
|
154
|
-
# @
|
|
155
|
-
#
|
|
156
|
-
|
|
157
|
-
|
|
185
|
+
# @param [Test::Cmd::Pipe] out
|
|
186
|
+
# A pipe for stdout
|
|
187
|
+
# @param [Test::Cmd::Pipe] err
|
|
188
|
+
# A pipe for stderr
|
|
189
|
+
# @return [Thread]
|
|
190
|
+
# Returns a thread for a spawned command
|
|
191
|
+
def produce(out, err)
|
|
192
|
+
@producer = Thread.new do
|
|
193
|
+
@pid = Process.spawn(@cmd, *@argv, {out: out.w, err: err.w})
|
|
194
|
+
Process.wait
|
|
195
|
+
@status = $?
|
|
196
|
+
rescue Errno::ENOENT => ex
|
|
197
|
+
@cmd, @argv, @stderr = "false", [], ex.message
|
|
198
|
+
@enoent = true
|
|
199
|
+
retry
|
|
200
|
+
end
|
|
158
201
|
end
|
|
159
202
|
|
|
160
203
|
##
|
|
161
|
-
# @
|
|
162
|
-
#
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
204
|
+
# @param [Thread] thread
|
|
205
|
+
# A thread for a spawned command
|
|
206
|
+
# @param [Test::Cmd::Pipe] out
|
|
207
|
+
# A pipe for stdout
|
|
208
|
+
# @param [Test::Cmd::Pipe] err
|
|
209
|
+
# A pipe for stderr
|
|
210
|
+
# @return [void]
|
|
211
|
+
def consume(thread, out, err)
|
|
212
|
+
return if @consumed
|
|
213
|
+
sleep 0.01 while thread.alive?
|
|
214
|
+
loop do
|
|
215
|
+
io, _ = IO.select([out.r, err.r], nil, nil, 0.01)
|
|
216
|
+
io&.include?(out.r) ? @stdout << out.r.read(1) : nil
|
|
217
|
+
io&.include?(err.r) ? @stderr << err.r.read(1) : nil
|
|
218
|
+
break unless thread.alive? || IO.select([out.r, err.r], nil, nil, 0.01)
|
|
219
|
+
end
|
|
220
|
+
ensure
|
|
221
|
+
[out, err].each(&:close)
|
|
222
|
+
@consumed = true
|
|
166
223
|
end
|
|
167
|
-
alias_method :not_found?, :command_not_found?
|
|
168
224
|
end
|
|
169
225
|
|
|
170
226
|
module Kernel
|
data/test-cmd.rb.gemspec
CHANGED
|
@@ -4,14 +4,13 @@ Gem::Specification.new do |gem|
|
|
|
4
4
|
gem.name = "test-cmd.rb"
|
|
5
5
|
gem.authors = ["0x1eef"]
|
|
6
6
|
gem.email = ["0x1eef@protonmail.com"]
|
|
7
|
-
gem.homepage = "https://github.com/
|
|
8
|
-
gem.version = "0.
|
|
7
|
+
gem.homepage = "https://github.com/1robertrb/test-cmd.rb#readme"
|
|
8
|
+
gem.version = "1.0.0"
|
|
9
9
|
gem.required_ruby_version = ">= 3.0"
|
|
10
10
|
gem.licenses = ["0BSD"]
|
|
11
11
|
gem.files = `git ls-files`.split($/)
|
|
12
12
|
gem.require_paths = ["lib"]
|
|
13
|
-
gem.summary = "
|
|
14
|
-
gem.metadata = { "documentation_uri" => "https://0x1eef.github.io/x/test-cmd.rb/" }
|
|
13
|
+
gem.summary = "test-cmd.rb provides an object-oriented interface for spawning a command"
|
|
15
14
|
gem.description = gem.summary
|
|
16
15
|
gem.add_development_dependency "test-unit", "~> 3.5.7"
|
|
17
16
|
gem.add_development_dependency "yard", "~> 0.9"
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: test-cmd.rb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 1.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- '0x1eef'
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: test-unit
|
|
@@ -80,7 +79,7 @@ dependencies:
|
|
|
80
79
|
- - "~>"
|
|
81
80
|
- !ruby/object:Gem::Version
|
|
82
81
|
version: '13.1'
|
|
83
|
-
description:
|
|
82
|
+
description: test-cmd.rb provides an object-oriented interface for spawning a command
|
|
84
83
|
email:
|
|
85
84
|
- 0x1eef@protonmail.com
|
|
86
85
|
executables: []
|
|
@@ -89,7 +88,6 @@ extra_rdoc_files: []
|
|
|
89
88
|
files:
|
|
90
89
|
- ".github/workflows/specs.yml"
|
|
91
90
|
- ".gitignore"
|
|
92
|
-
- ".gitlab-ci.yml"
|
|
93
91
|
- ".projectile"
|
|
94
92
|
- ".rubocop.yml"
|
|
95
93
|
- Gemfile
|
|
@@ -101,12 +99,10 @@ files:
|
|
|
101
99
|
- test-cmd.rb.gemspec
|
|
102
100
|
- test/cmd_test.rb
|
|
103
101
|
- test/setup.rb
|
|
104
|
-
homepage: https://github.com/
|
|
102
|
+
homepage: https://github.com/1robertrb/test-cmd.rb#readme
|
|
105
103
|
licenses:
|
|
106
104
|
- 0BSD
|
|
107
|
-
metadata:
|
|
108
|
-
documentation_uri: https://0x1eef.github.io/x/test-cmd.rb/
|
|
109
|
-
post_install_message:
|
|
105
|
+
metadata: {}
|
|
110
106
|
rdoc_options: []
|
|
111
107
|
require_paths:
|
|
112
108
|
- lib
|
|
@@ -121,8 +117,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
121
117
|
- !ruby/object:Gem::Version
|
|
122
118
|
version: '0'
|
|
123
119
|
requirements: []
|
|
124
|
-
rubygems_version:
|
|
125
|
-
signing_key:
|
|
120
|
+
rubygems_version: 4.0.6
|
|
126
121
|
specification_version: 4
|
|
127
|
-
summary:
|
|
122
|
+
summary: test-cmd.rb provides an object-oriented interface for spawning a command
|
|
128
123
|
test_files: []
|
data/.gitlab-ci.yml
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
stages:
|
|
2
|
-
- test
|
|
3
|
-
|
|
4
|
-
test-ruby31:
|
|
5
|
-
stage: test
|
|
6
|
-
image: ruby:3.1.2
|
|
7
|
-
script:
|
|
8
|
-
- bundle install
|
|
9
|
-
- bundle exec ruby test/*_test.rb
|
|
10
|
-
|
|
11
|
-
test-ruby32:
|
|
12
|
-
stage: test
|
|
13
|
-
image: ruby:3.2.0
|
|
14
|
-
script:
|
|
15
|
-
- bundle install
|
|
16
|
-
- bundle exec ruby test/*_test.rb
|