test-cmd.rb 2.7.2 → 2.7.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a9c323a0dbc2f142481d09008829ca2f3e6d8dc53d4f4c3dcf1efacc3096f58b
4
- data.tar.gz: d3ff8c6062fe90054e4953a5ea69c6aacb4048b420c6b6344b6985ebee751e29
3
+ metadata.gz: ebd8bbe187c652c283e033bc54cf6a554109d62d22128b74de7ed0516a204bc0
4
+ data.tar.gz: 87f78b09e391dd44747f8e8dd3fae3d253fcaee670567910fc529712145bd8ea
5
5
  SHA512:
6
- metadata.gz: 13e73947059bbb45f6c9c6af29619e7d22751af6dda7574aa5c2b87485786d0c8e2f2e88f2739c9c4087c88e55536c6f18e617ce033fd2a0616494e72fea185b
7
- data.tar.gz: 6556f3ff5a3bc05f71ecbb4242ed3cccdfd7aa5f3dc528ca09daf6c850e797595cf1de6c3c426b7a4e1061145588c84215ba034a09228fe09f5a9a51ea059d1b
6
+ metadata.gz: 49ae5a3149609423350bced41594b20de66d99806a4057484524040ca5cda1a2f3711a7d3460aa3dd21ad130ad94e1b1b8d2570a2a6856afb8f2b36741d313ab
7
+ data.tar.gz: 815de1cbad72d10fddfb422e2deedcc506f19236fdc28378d86eeac0f31c7a1fb58cd067acbf63a3070692e743c3ab20afa296d9a95256b70e9484ff6c9c7873
@@ -4,5 +4,5 @@ end unless defined?(Test)
4
4
  class Test::Command
5
5
  ##
6
6
  # @string [String]
7
- VERSION = "2.7.2"
7
+ VERSION = "2.7.3"
8
8
  end
data/lib/test/command.rb CHANGED
@@ -5,6 +5,7 @@ end unless defined?(Test)
5
5
  # test-cmd.rb provides an object oriented interface
6
6
  # for spawning a command
7
7
  class Test::Command
8
+ require "rbconfig"
8
9
  require_relative "command/version"
9
10
 
10
11
  ##
@@ -104,8 +105,7 @@ class Test::Command
104
105
  @stderr = read_limited(@err.r, @limit[:stderr])
105
106
  @status = Process.waitpid2(@pid).last
106
107
  rescue Errno::ECHILD
107
- errpid = Process.spawn("false")
108
- @status = Process.waitpid2(errpid).last
108
+ @status = failed_status
109
109
  ensure
110
110
  @out.r.close
111
111
  @err.r.close
@@ -118,7 +118,7 @@ class Test::Command
118
118
  # Close the read end of any input pipe so a pending
119
119
  # writer thread does not block forever.
120
120
  @in_r.close unless @in_r.equal?(IO::NULL)
121
- @status = Process.waitpid2(Process.spawn("false")).last
121
+ @status = failed_status
122
122
  self
123
123
  end
124
124
 
@@ -324,4 +324,13 @@ class Test::Command
324
324
  return unless @producer&.alive?
325
325
  @producer.join
326
326
  end
327
+
328
+ ##
329
+ # Returns a failed status that works across Unix and Windows.
330
+ # @return [Process::Status]
331
+ def failed_status
332
+ ruby = [RbConfig.ruby, "-e", "exit 1"]
333
+ _, status = Process.waitpid2 Process.spawn(*ruby)
334
+ status
335
+ end
327
336
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: test-cmd.rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.7.2
4
+ version: 2.7.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Gleeson
@@ -91,21 +91,11 @@ executables: []
91
91
  extensions: []
92
92
  extra_rdoc_files: []
93
93
  files:
94
- - ".github/workflows/specs.yml"
95
- - ".gitignore"
96
- - ".projectile"
97
- - ".rubocop.yml"
98
- - Gemfile
99
94
  - LICENSE
100
95
  - README.md
101
- - Rakefile.rb
102
96
  - lib/test-cmd.rb
103
97
  - lib/test/command.rb
104
98
  - lib/test/command/version.rb
105
- - rubydev.svg
106
- - test-cmd.rb.gemspec
107
- - test/cmd_test.rb
108
- - test/setup.rb
109
99
  homepage: https://github.com/r-uby-dev/test-cmd.rb#readme
110
100
  licenses:
111
101
  - MIT
@@ -1,23 +0,0 @@
1
- name: test-cmd.rb
2
-
3
- on:
4
- push:
5
- branches: [ main ]
6
- pull_request:
7
- branches: [ main ]
8
-
9
- jobs:
10
- specs:
11
- strategy:
12
- fail-fast: false
13
- matrix:
14
- os: [ubuntu-latest, macos-latest]
15
- ruby: [3.1, 3.2, 3.3, 4.0]
16
- runs-on: ${{ matrix.os }}
17
- steps:
18
- - uses: actions/checkout@v2
19
- - uses: ruby/setup-ruby@v1
20
- with:
21
- ruby-version: ${{ matrix.ruby }}
22
- - run: bundle install
23
- - run: bundle exec ruby test/*_test.rb
data/.gitignore DELETED
@@ -1,7 +0,0 @@
1
- *.gem
2
- .gems
3
- .bundle
4
- Gemfile.lock
5
- .yardoc/
6
- doc/
7
- pkg/
data/.projectile DELETED
@@ -1 +0,0 @@
1
- -.gems/
data/.rubocop.yml DELETED
@@ -1,27 +0,0 @@
1
- ##
2
- # Plugins
3
- require:
4
- - standard
5
-
6
- ##
7
- # Defaults: standard-rb
8
- inherit_gem:
9
- standard: config/base.yml
10
-
11
- ##
12
- # Enabled
13
- AllCops:
14
- TargetRubyVersion: 3.1
15
- Include:
16
- - 'lib/**/*.rb'
17
- - 'test/**/*.rb'
18
-
19
- ##
20
- # Disabled
21
- Layout/MultilineMethodCallIndentation:
22
- Exclude:
23
- - 'test/*.rb'
24
- Layout/ArgumentAlignment:
25
- Enabled: false
26
- Style/MultilineIfModifier:
27
- Enabled: false
data/Gemfile DELETED
@@ -1,2 +0,0 @@
1
- source "https://rubygems.org"
2
- gemspec
data/Rakefile.rb DELETED
@@ -1,10 +0,0 @@
1
- require "bundler/setup"
2
- require "bundler/gem_tasks"
3
- require "rake/testtask"
4
-
5
- Rake::TestTask.new do |t|
6
- t.test_files = FileList['test/*_test.rb']
7
- t.verbose = true
8
- t.warning = false
9
- end
10
- task default: :test
data/rubydev.svg DELETED
@@ -1,257 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 560 220" role="img" aria-labelledby="title desc">
2
- <title id="title">r.uby.dev</title>
3
- <desc id="desc">A wide r.uby.dev wordmark with ruby, sapphire, and emerald gemstones moving around the text.</desc>
4
- <defs>
5
- <linearGradient id="body" x1="45" y1="35" x2="211" y2="224" gradientUnits="userSpaceOnUse">
6
- <stop offset="0" stop-color="#e0796f"/>
7
- <stop offset="0.42" stop-color="#a7312b"/>
8
- <stop offset="1" stop-color="#5b090d"/>
9
- </linearGradient>
10
- <linearGradient id="table" x1="75" y1="31" x2="166" y2="104" gradientUnits="userSpaceOnUse">
11
- <stop offset="0" stop-color="#fff3ec"/>
12
- <stop offset="0.26" stop-color="#d9867d"/>
13
- <stop offset="1" stop-color="#a32d2a"/>
14
- </linearGradient>
15
- <linearGradient id="right" x1="150" y1="59" x2="219" y2="195" gradientUnits="userSpaceOnUse">
16
- <stop offset="0" stop-color="#911b20"/>
17
- <stop offset="1" stop-color="#3c0407"/>
18
- </linearGradient>
19
- <linearGradient id="center" x1="99" y1="104" x2="146" y2="226" gradientUnits="userSpaceOnUse">
20
- <stop offset="0" stop-color="#c8554f"/>
21
- <stop offset="0.48" stop-color="#992522"/>
22
- <stop offset="1" stop-color="#6d1315"/>
23
- </linearGradient>
24
- <radialGradient id="glow" cx="38%" cy="22%" r="66%">
25
- <stop offset="0" stop-color="#fff8ed" stop-opacity="0.68"/>
26
- <stop offset="0.42" stop-color="#d89a92" stop-opacity="0.18"/>
27
- <stop offset="1" stop-color="#d89a92" stop-opacity="0"/>
28
- </radialGradient>
29
- <linearGradient id="body-blue" x1="45" y1="35" x2="211" y2="224" gradientUnits="userSpaceOnUse">
30
- <stop offset="0" stop-color="#7aa5d9"/>
31
- <stop offset="0.42" stop-color="#35669e"/>
32
- <stop offset="1" stop-color="#162f4a"/>
33
- </linearGradient>
34
- <linearGradient id="table-blue" x1="75" y1="31" x2="166" y2="104" gradientUnits="userSpaceOnUse">
35
- <stop offset="0" stop-color="#edf4ff"/>
36
- <stop offset="0.26" stop-color="#7d9ed9"/>
37
- <stop offset="1" stop-color="#2a5ca3"/>
38
- </linearGradient>
39
- <linearGradient id="right-blue" x1="150" y1="59" x2="219" y2="195" gradientUnits="userSpaceOnUse">
40
- <stop offset="0" stop-color="#1f4a91"/>
41
- <stop offset="1" stop-color="#071b3c"/>
42
- </linearGradient>
43
- <linearGradient id="center-blue" x1="99" y1="104" x2="146" y2="226" gradientUnits="userSpaceOnUse">
44
- <stop offset="0" stop-color="#4f78c8"/>
45
- <stop offset="0.48" stop-color="#254a99"/>
46
- <stop offset="1" stop-color="#132a6d"/>
47
- </linearGradient>
48
- <radialGradient id="glow-blue" cx="38%" cy="22%" r="66%">
49
- <stop offset="0" stop-color="#edf6ff" stop-opacity="0.68"/>
50
- <stop offset="0.42" stop-color="#92aed9" stop-opacity="0.18"/>
51
- <stop offset="1" stop-color="#92aed9" stop-opacity="0"/>
52
- </radialGradient>
53
- <linearGradient id="body-green" x1="45" y1="35" x2="211" y2="224" gradientUnits="userSpaceOnUse">
54
- <stop offset="0" stop-color="#79d9a0"/>
55
- <stop offset="0.42" stop-color="#359e66"/>
56
- <stop offset="1" stop-color="#164a2f"/>
57
- </linearGradient>
58
- <linearGradient id="table-green" x1="75" y1="31" x2="166" y2="104" gradientUnits="userSpaceOnUse">
59
- <stop offset="0" stop-color="#edfff4"/>
60
- <stop offset="0.26" stop-color="#7dd9a5"/>
61
- <stop offset="1" stop-color="#2aa360"/>
62
- </linearGradient>
63
- <linearGradient id="right-green" x1="150" y1="59" x2="219" y2="195" gradientUnits="userSpaceOnUse">
64
- <stop offset="0" stop-color="#1b9147"/>
65
- <stop offset="1" stop-color="#043c1c"/>
66
- </linearGradient>
67
- <linearGradient id="center-green" x1="99" y1="104" x2="146" y2="226" gradientUnits="userSpaceOnUse">
68
- <stop offset="0" stop-color="#4fc87d"/>
69
- <stop offset="0.48" stop-color="#259950"/>
70
- <stop offset="1" stop-color="#136d30"/>
71
- </linearGradient>
72
- <radialGradient id="glow-green" cx="38%" cy="22%" r="66%">
73
- <stop offset="0" stop-color="#edfff4" stop-opacity="0.68"/>
74
- <stop offset="0.42" stop-color="#92d9b0" stop-opacity="0.18"/>
75
- <stop offset="1" stop-color="#92d9b0" stop-opacity="0"/>
76
- </radialGradient>
77
- <linearGradient id="wordmark" x1="0" y1="76" x2="0" y2="138" gradientUnits="userSpaceOnUse">
78
- <stop offset="0" stop-color="#ffffff"/>
79
- <stop offset="0.48" stop-color="#e1e4e8"/>
80
- <stop offset="1" stop-color="#aeb8c2"/>
81
- </linearGradient>
82
- <linearGradient id="accentLine" x1="90" y1="0" x2="470" y2="0" gradientUnits="userSpaceOnUse">
83
- <stop offset="0" stop-color="#30363d"/>
84
- <stop offset="0.5" stop-color="#a7312b"/>
85
- <stop offset="1" stop-color="#30363d"/>
86
- </linearGradient>
87
- <filter id="shadow" x="-18%" y="-18%" width="136%" height="146%">
88
- <feDropShadow dx="0" dy="10" stdDeviation="9" flood-color="#000" flood-opacity="0.34"/>
89
- </filter>
90
- <filter id="textShadow" x="-20%" y="-45%" width="140%" height="190%">
91
- <feDropShadow dx="0" dy="7" stdDeviation="6" flood-color="#000" flood-opacity="0.55"/>
92
- </filter>
93
- <symbol id="gemstone" viewBox="0 0 256 256">
94
- <path d="M33 91 78 30h100l45 61-95 134Z" fill="url(#body)" stroke="#250507" stroke-width="7" stroke-linejoin="round"/>
95
- <path d="M78 30h100l-50 61Z" fill="url(#table)" stroke="#250507" stroke-width="4" stroke-linejoin="round"/>
96
- <path d="M33 91h95l-52 44Z" fill="#b03a33" stroke="#250507" stroke-width="4" stroke-linejoin="round"/>
97
- <path d="M223 91h-95l52 44Z" fill="url(#right)" stroke="#250507" stroke-width="4" stroke-linejoin="round"/>
98
- <path d="M76 135 128 225 33 91Z" fill="#7a1a1b" stroke="#250507" stroke-width="4" stroke-linejoin="round"/>
99
- <path d="M180 135 128 225 223 91Z" fill="#62080d" stroke="#250507" stroke-width="4" stroke-linejoin="round"/>
100
- <path d="M76 135h104l-52 90Z" fill="url(#center)" stroke="#250507" stroke-width="4" stroke-linejoin="round"/>
101
- <path d="M78 30 128 91 76 135 33 91Z" fill="#a32d29" opacity="0.72"/>
102
- <path d="M178 30 128 91 180 135 223 91Z" fill="#6f1416" opacity="0.72"/>
103
- <path d="M128 91 76 135h104Z" fill="#c44f47" opacity="0.5"/>
104
- <path d="M49 91 84 43h43L86 96Z" fill="url(#glow)"/>
105
- <path d="M85 62 101 43h35L93 87Z" fill="#fff6eb" opacity="0.52"/>
106
- <path d="M97 153h62" fill="none" stroke="#cf8d85" stroke-width="4" stroke-linecap="round" opacity="0.25"/>
107
- </symbol>
108
- <symbol id="gemstone-blue" viewBox="0 0 256 256">
109
- <path d="M33 91 78 30h100l45 61-95 134Z" fill="url(#body-blue)" stroke="#250507" stroke-width="7" stroke-linejoin="round"/>
110
- <path d="M78 30h100l-50 61Z" fill="url(#table-blue)" stroke="#250507" stroke-width="4" stroke-linejoin="round"/>
111
- <path d="M33 91h95l-52 44Z" fill="#336fb0" stroke="#250507" stroke-width="4" stroke-linejoin="round"/>
112
- <path d="M223 91h-95l52 44Z" fill="url(#right-blue)" stroke="#250507" stroke-width="4" stroke-linejoin="round"/>
113
- <path d="M76 135 128 225 33 91Z" fill="#1a3a7a" stroke="#250507" stroke-width="4" stroke-linejoin="round"/>
114
- <path d="M180 135 128 225 223 91Z" fill="#081a62" stroke="#250507" stroke-width="4" stroke-linejoin="round"/>
115
- <path d="M76 135h104l-52 90Z" fill="url(#center-blue)" stroke="#250507" stroke-width="4" stroke-linejoin="round"/>
116
- <path d="M78 30 128 91 76 135 33 91Z" fill="#2d5ba3" opacity="0.72"/>
117
- <path d="M178 30 128 91 180 135 223 91Z" fill="#142d6f" opacity="0.72"/>
118
- <path d="M128 91 76 135h104Z" fill="#4774c4" opacity="0.5"/>
119
- <path d="M49 91 84 43h43L86 96Z" fill="url(#glow-blue)"/>
120
- <path d="M85 62 101 43h35L93 87Z" fill="#edf4ff" opacity="0.52"/>
121
- <path d="M97 153h62" fill="none" stroke="#85a5cf" stroke-width="4" stroke-linecap="round" opacity="0.25"/>
122
- </symbol>
123
- <symbol id="gemstone-green" viewBox="0 0 256 256">
124
- <path d="M33 91 78 30h100l45 61-95 134Z" fill="url(#body-green)" stroke="#250507" stroke-width="7" stroke-linejoin="round"/>
125
- <path d="M78 30h100l-50 61Z" fill="url(#table-green)" stroke="#250507" stroke-width="4" stroke-linejoin="round"/>
126
- <path d="M33 91h95l-52 44Z" fill="#33b070" stroke="#250507" stroke-width="4" stroke-linejoin="round"/>
127
- <path d="M223 91h-95l52 44Z" fill="url(#right-green)" stroke="#250507" stroke-width="4" stroke-linejoin="round"/>
128
- <path d="M76 135 128 225 33 91Z" fill="#1a7a4b" stroke="#250507" stroke-width="4" stroke-linejoin="round"/>
129
- <path d="M180 135 128 225 223 91Z" fill="#086220" stroke="#250507" stroke-width="4" stroke-linejoin="round"/>
130
- <path d="M76 135h104l-52 90Z" fill="url(#center-green)" stroke="#250507" stroke-width="4" stroke-linejoin="round"/>
131
- <path d="M78 30 128 91 76 135 33 91Z" fill="#2da36a" opacity="0.72"/>
132
- <path d="M178 30 128 91 180 135 223 91Z" fill="#146f3d" opacity="0.72"/>
133
- <path d="M128 91 76 135h104Z" fill="#47c478" opacity="0.5"/>
134
- <path d="M49 91 84 43h43L86 96Z" fill="url(#glow-green)"/>
135
- <path d="M85 62 101 43h35L93 87Z" fill="#edfff4" opacity="0.52"/>
136
- <path d="M97 153h62" fill="none" stroke="#85cf9f" stroke-width="4" stroke-linecap="round" opacity="0.25"/>
137
- </symbol>
138
- </defs>
139
- <style>
140
- svg {
141
- color-scheme: light dark;
142
- --wordmark-fill: #24292f;
143
- --wordmark-halo: #ffffff;
144
- --wordmark-outline: #d0d7de;
145
- --rule: #d0d7de;
146
- --rule-strong: #8c959f;
147
- --accent-shadow: #d0d7de;
148
- }
149
- .wordmark-halo {
150
- fill: none;
151
- stroke: var(--wordmark-halo);
152
- stroke-width: 16;
153
- stroke-linejoin: round;
154
- paint-order: stroke;
155
- }
156
- .wordmark-outline {
157
- fill: none;
158
- stroke: var(--wordmark-outline);
159
- stroke-width: 8;
160
- stroke-linejoin: round;
161
- paint-order: stroke;
162
- }
163
- .wordmark-fill {
164
- fill: var(--wordmark-fill);
165
- }
166
- .tagline {
167
- fill: var(--wordmark-fill);
168
- opacity: 0.78;
169
- }
170
- .rule {
171
- stroke: var(--rule);
172
- }
173
- .rule-strong {
174
- stroke: var(--rule-strong);
175
- }
176
- .accent-shadow {
177
- stroke: var(--accent-shadow);
178
- }
179
- .gem {
180
- animation-duration: 6.5s;
181
- animation-iteration-count: infinite;
182
- animation-timing-function: ease-in-out;
183
- }
184
- .gem-a { animation-name: gem-a; }
185
- .gem-b { animation-name: gem-b; animation-duration: 7.5s; }
186
- .gem-c { animation-name: gem-c; animation-duration: 8s; }
187
- .gem-front {
188
- opacity: 0;
189
- animation-duration: 12s;
190
- animation-iteration-count: infinite;
191
- animation-timing-function: ease-in-out;
192
- }
193
- .gem-front-a { animation-name: gem-front-a; }
194
- .gem-front-b { animation-name: gem-front-b; animation-delay: -4s; }
195
- .gem-front-c { animation-name: gem-front-c; animation-delay: -8s; }
196
- @keyframes gem-a {
197
- 0%, 100% { transform: translate(42px, 82px) rotate(-10deg); }
198
- 35% { transform: translate(66px, 45px) rotate(5deg); }
199
- 70% { transform: translate(84px, 118px) rotate(-18deg); }
200
- }
201
- @keyframes gem-b {
202
- 0%, 100% { transform: translate(236px, 13px) rotate(3deg); }
203
- 33% { transform: translate(192px, 28px) rotate(-9deg); }
204
- 66% { transform: translate(292px, 24px) rotate(12deg); }
205
- }
206
- @keyframes gem-c {
207
- 0%, 100% { transform: translate(430px, 78px) rotate(8deg); }
208
- 38% { transform: translate(397px, 45px) rotate(-4deg); }
209
- 72% { transform: translate(446px, 117px) rotate(16deg); }
210
- }
211
- @media (prefers-reduced-motion: reduce) {
212
- .gem { animation: none; }
213
- .gem-front { animation: none; opacity: 0; }
214
- .gem-a { transform: translate(42px, 82px) rotate(-10deg); }
215
- .gem-b { transform: translate(236px, 13px) rotate(3deg); }
216
- .gem-c { transform: translate(430px, 78px) rotate(8deg); }
217
- }
218
- @keyframes gem-front-a {
219
- 0%, 42%, 51%, 100% { opacity: 0; }
220
- 45%, 48% { opacity: 0.9; }
221
- }
222
- @keyframes gem-front-b {
223
- 0%, 57%, 66%, 100% { opacity: 0; }
224
- 60%, 63% { opacity: 0.86; }
225
- }
226
- @keyframes gem-front-c {
227
- 0%, 72%, 81%, 100% { opacity: 0; }
228
- 75%, 78% { opacity: 0.88; }
229
- }
230
- </style>
231
-
232
- <g opacity="0.92">
233
- <g class="gem gem-a"><use href="#gemstone" width="78" height="78"/></g>
234
- <g class="gem gem-b"><use href="#gemstone-blue" width="84" height="84"/></g>
235
- <g class="gem gem-c"><use href="#gemstone-green" width="78" height="78"/></g>
236
- </g>
237
-
238
- <g font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif" text-anchor="middle">
239
- <text class="wordmark-halo" x="280" y="126" fill="none" stroke="#ffffff"
240
- font-size="72" font-weight="800"
241
- filter="url(#textShadow)">r.uby.dev</text>
242
- <text class="wordmark-outline" x="280" y="126" fill="none" stroke="#d0d7de"
243
- font-size="72" font-weight="800">r.uby.dev</text>
244
- <text class="wordmark-fill" x="280" y="126" fill="#24292f"
245
- font-size="72" font-weight="800">r.uby.dev</text>
246
- </g>
247
-
248
- <g>
249
- <g class="gem gem-a"><use class="gem-front gem-front-a" href="#gemstone" width="78" height="78"/></g>
250
- <g class="gem gem-b"><use class="gem-front gem-front-b" href="#gemstone-blue" width="84" height="84"/></g>
251
- <g class="gem gem-c"><use class="gem-front gem-front-c" href="#gemstone-green" width="78" height="78"/></g>
252
- </g>
253
-
254
- <text class="tagline" x="280" y="204"
255
- font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif"
256
- text-anchor="middle" font-size="18" font-weight="650">Building cool stuff with Ruby</text>
257
- </svg>
data/test/cmd_test.rb DELETED
@@ -1,306 +0,0 @@
1
- require_relative "setup"
2
-
3
- class Test::Command
4
- class Test < Test::Unit::TestCase
5
- private
6
-
7
- def ruby(str)
8
- ::Test::Command.new "ruby", "-e", str
9
- end
10
-
11
- ##
12
- # macos-specific env vars that are always set
13
- # @return [String]
14
- def macos
15
- if ENV["__CF_USER_TEXT_ENCODING"]
16
- "__CF_USER_TEXT_ENCODING\n"
17
- else
18
- ""
19
- end
20
- end
21
- end
22
- end
23
-
24
- class Test::Command
25
- ##
26
- # Test::Command#arguments
27
- class ArgumentsTest < Test
28
- def test_ruby_arguments
29
- assert_equal "42\n", ::Test::Command.new("ruby")
30
- .arguments("-e", "warn 42")
31
- .stderr
32
- end
33
-
34
- def test_ruby_arguments_to_s
35
- arg = Object.new
36
- def arg.to_s = "-e"
37
- assert_equal "42\n", ::Test::Command.new("ruby")
38
- .arguments(arg, "warn 42")
39
- .stderr
40
- end
41
-
42
- def test_ruby_arguments_argv_alias
43
- assert_equal "42\n", ::Test::Command.new("ruby")
44
- .argv("-e", "warn 42")
45
- .stderr
46
- end
47
- end
48
-
49
- ##
50
- # Test::Command#env
51
- class EnvTest < Test
52
- def test_ruby_env
53
- assert_equal "42\n",
54
- ::Test::Command.new("ruby", "-e", "puts ENV['FOO']")
55
- .env("FOO" => "42")
56
- .stdout
57
- end
58
-
59
- def test_ruby_env_only_given_keys
60
- assert_equal "BAR\nFOO\nPATH\n#{macos}",
61
- ::Test::Command.new("ruby", "-e", "puts ENV.keys.sort")
62
- .env("FOO" => "42", "BAR" => "7")
63
- .stdout
64
- end
65
-
66
- def test_ruby_env_empty_is_empty_env
67
- assert_equal "PATH\n#{macos}",
68
- ::Test::Command.new("ruby", "-e", "puts ENV.keys.sort")
69
- .env({})
70
- .stdout
71
- end
72
-
73
- def test_ruby_env_does_not_leak_inherited
74
- assert_equal "true",
75
- ::Test::Command.new("ruby", "-e", "print ENV.key?('PATH')")
76
- .stdout
77
- end
78
-
79
- def test_ruby_env_path_carries_over_inherited
80
- parent_path = ENV["PATH"]
81
- assert_equal parent_path,
82
- ::Test::Command.new("ruby", "-e", "print ENV['PATH']")
83
- .stdout
84
- end
85
-
86
- def test_ruby_env_path_carries_over_empty
87
- parent_path = ENV["PATH"]
88
- assert_equal parent_path,
89
- ::Test::Command.new("ruby", "-e", "print ENV['PATH']")
90
- .env({})
91
- .stdout
92
- end
93
- end
94
-
95
- ##
96
- # Test::Command#stdin
97
- class StdinTest < Test
98
- def test_ruby_stdin_string
99
- assert_equal "hello world",
100
- ::Test::Command.new("cat")
101
- .stdin("hello world")
102
- .stdout
103
- end
104
-
105
- def test_ruby_stdin_command
106
- assert_equal "42\n",
107
- ::Test::Command.new("cat")
108
- .stdin(ruby("puts 42"))
109
- .stdout
110
- end
111
- end
112
-
113
- ##
114
- # Test::Command#limit
115
- class LimitTest < Test
116
- def test_ruby_limit_stdout
117
- assert_equal "happy",
118
- ::Test::Command.new("printf", "%s", "happy days")
119
- .limit(stdout: 5)
120
- .stdout
121
- end
122
-
123
- def test_ruby_limit_stderr
124
- assert_equal "smile",
125
- ::Test::Command.new("sh", "-c", "echo smile >&2")
126
- .limit(stderr: 5)
127
- .stderr
128
- end
129
-
130
- def test_ruby_limit_nil_is_unlimited
131
- expect = "a" * 20_000
132
- assert_equal expect,
133
- ::Test::Command.new("ruby", "-e", "print 'a' * 20_000")
134
- .stdout
135
- end
136
-
137
- def test_ruby_limit_drains_remaining_output
138
- cmd = ::Test::Command.new("sh", "-c", "printf 'happy days'")
139
- .limit(stdout: 5)
140
- .spawn
141
- assert_equal true, cmd.spawned?
142
- ##
143
- # A full pipe would block forever: the
144
- # drain lets the child finish and capture
145
- # its status
146
- assert_equal 0, cmd.exit_status
147
- end
148
- end
149
-
150
- ##
151
- # Test::Command#{exit_status, status, success?}
152
- class ExitStatusTest < Test
153
- def test_ruby_exit_status_success
154
- assert_equal 0, ruby("exit 0").exit_status
155
- end
156
-
157
- def test_ruby_exit_status_failure
158
- assert_equal 1, ruby("exit 1").exit_status
159
- end
160
-
161
- def test_ruby_exit_status_predicates
162
- assert_equal true, ruby("exit 0").status.success?
163
- assert_equal true, ruby("exit 0").success?
164
- end
165
-
166
- def test_nonexistent_command
167
- assert_equal false, ::Test::Command.new("/a/path/that/is/not/found").success?
168
- end
169
- end
170
-
171
- ##
172
- # Test::Command#{stdout,stderr}
173
- class OutputTest < Test
174
- def test_ruby_stdout
175
- assert_equal "42\n", ruby("puts 42").stdout
176
- end
177
-
178
- def test_ruby_stderr
179
- assert_equal "42\n", ruby("warn 42").stderr
180
- end
181
-
182
- def test_ruby_stdout_fork
183
- code = <<-CODE.each_line.map { _1.chomp.strip }.join(";")
184
- $stdout.sync = true
185
- fork do
186
- sleep(1)
187
- puts "bar"
188
- end
189
- puts "foo"
190
- Process.wait
191
- CODE
192
- assert_equal "foo\nbar\n", ruby(code).stdout
193
- end
194
-
195
- def test_nonexistent_command
196
- assert_equal "No such file or directory - /a/path/that/is/not/found",
197
- ::Test::Command.new("/a/path/that/is/not/found").stderr
198
- end
199
- end
200
-
201
- ##
202
- # Test::Command#{success, failure}
203
- class CallbackTest < Test
204
- def test_ruby_success_callback
205
- call_ok, call_fail = [false, false]
206
- ruby("exit 0")
207
- .success { call_ok = true }
208
- .failure { call_fail = true }
209
- assert_equal true, call_ok
210
- assert_equal false, call_fail
211
- end
212
-
213
- def test_ruby_failure_callback
214
- call_ok, call_fail = [false, false]
215
- ruby("exit 1")
216
- .success { call_ok = true }
217
- .failure { call_fail = true }
218
- assert_equal true, call_fail
219
- assert_equal false, call_ok
220
- end
221
- end
222
-
223
- ##
224
- # Test::Command#spawned?
225
- class SpawnedTest < Test
226
- def test_spawned_before_spawn
227
- assert_equal false, ruby("puts 42").spawned?
228
- end
229
-
230
- def test_spawned_after_spawn
231
- assert_equal true, ruby("puts 42").tap(&:spawn).spawned?
232
- end
233
- end
234
-
235
- ##
236
- # Test::Command#command_not_found?
237
- class CommandNotFoundTest < Test
238
- def test_command_not_found
239
- assert_equal true, ::Test::Command.new("/a/path/that/is/not/found").command_not_found?
240
- assert_equal true, ::Test::Command.new("/a/path/that/is/not/found").not_found?
241
- end
242
-
243
- def test_spawn_returns_self_when_not_found
244
- command = ::Test::Command.new("/a/path/that/is/not/found")
245
- assert_equal command, command.spawn
246
- end
247
-
248
- def test_spawn_sets_not_found_on_self
249
- command = ::Test::Command.new("/a/path/that/is/not/found")
250
- command.spawn
251
- assert_equal true, command.not_found?
252
- end
253
-
254
- def test_stdout_when_not_found
255
- command = ::Test::Command.new("/a/path/that/is/not/found")
256
- assert_equal "", command.stdout
257
- end
258
-
259
- def test_stderr_when_not_found
260
- command = ::Test::Command.new("/a/path/that/is/not/found")
261
- assert_equal "No such file or directory - /a/path/that/is/not/found",
262
- command.stderr
263
- end
264
- end
265
- end
266
-
267
- class Test::Command
268
- ##
269
- # A command's status belongs to the command, and is not taken from
270
- # another child that happens to be ready to be reaped.
271
- #
272
- # A bare `Process.wait` reaps whichever child is ready, so a child
273
- # that has exited and been reaped by nobody - another test's, another
274
- # thread's - could answer for a command that never spawned it.
275
- class StatusTest < Test
276
- def test_failure_is_not_answered_by_a_successful_decoy
277
- decoy = Process.spawn("true")
278
- sleep 0.1
279
- assert_equal false, ::Test::Command.new("false").success?
280
- ensure
281
- reap(decoy)
282
- end
283
-
284
- def test_success_is_not_answered_by_a_failing_decoy
285
- decoy = Process.spawn("false")
286
- sleep 0.1
287
- assert_equal true, ::Test::Command.new("true").success?
288
- ensure
289
- reap(decoy)
290
- end
291
-
292
- private
293
-
294
- ##
295
- # Reaps a decoy the command left alone, and says nothing when the
296
- # command took it: the test that got there first is the point of
297
- # these.
298
- # @param [Integer, nil] pid
299
- # @return [void]
300
- def reap(pid)
301
- Process.waitpid(pid) if pid
302
- rescue Errno::ECHILD
303
- nil
304
- end
305
- end
306
- end
data/test/setup.rb DELETED
@@ -1,3 +0,0 @@
1
- require "bundler/setup"
2
- require "test/unit"
3
- require "test-cmd"
data/test-cmd.rb.gemspec DELETED
@@ -1,30 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require File.join(__dir__, "lib", "test", "command", "version.rb")
4
-
5
- Gem::Specification.new do |gem|
6
- gem.name = "test-cmd.rb"
7
- gem.authors = ["Robert Gleeson"]
8
- gem.email = ["robert@r.uby.dev"]
9
- gem.homepage = "https://github.com/r-uby-dev/test-cmd.rb#readme"
10
- gem.version = Test::Command::VERSION
11
- gem.required_ruby_version = ">= 3.0"
12
- gem.licenses = ["MIT"]
13
- gem.files = `git ls-files`.split($/)
14
- gem.require_paths = ["lib"]
15
- gem.summary = <<~SUMMARY
16
- test-cmd.rb is a Go-inspired, object-oriented interface for running
17
- commands on UNIX-like systems, in the spirit of Go's `os/exec`. A
18
- command can be built by chaining multiple method calls that impact
19
- different command attributes. The environment the command executes
20
- with can be set, its standard input stream can be written to, and
21
- the standard output and standard error streams are captured so the
22
- parent process can read them.
23
- SUMMARY
24
- gem.description = gem.summary
25
- gem.add_development_dependency "test-unit", "~> 3.5.7"
26
- gem.add_development_dependency "yard", "~> 0.9"
27
- gem.add_development_dependency "redcarpet", "~> 3.5"
28
- gem.add_development_dependency "standard", "~> 1.24"
29
- gem.add_development_dependency "rake", "~> 13.1"
30
- end