test-cmd.rb 2.4.0 → 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.
- checksums.yaml +4 -4
- data/README.md +9 -0
- data/lib/test/command/version.rb +1 -1
- data/lib/test/command.rb +41 -2
- data/test/cmd_test.rb +37 -0
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a0790a7e8e68709204aeb42611543db79e3575615d6ed77ee0b166fff7827825
|
|
4
|
+
data.tar.gz: 7965cd9baf53560ff8648f0652876b3d31a969528b1419b5b975406ec37c13fc
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f0f7c63d381cbbd8c603c8fc7a1c22e7c73509b0a51965107c2fe2c23adf3c2b8cf5f243712b4f297f90aeb0535c01477ddd4518c10be6afd6a29b248c30af18
|
|
7
|
+
data.tar.gz: aee5d21c5948e17b29f0df43636bb18d396d6919efdc3a0fe6c03628ba85d5f3ae0e04cd03e61e51c33ad30aa88a2e7a840051cc704d3ac384957ea75d6f1cd1
|
data/README.md
CHANGED
|
@@ -60,6 +60,15 @@ p Test::Command
|
|
|
60
60
|
.new("tr", "a-z", "A-Z")
|
|
61
61
|
.stdin("hello")
|
|
62
62
|
.stdout # => "HELLO"
|
|
63
|
+
|
|
64
|
+
##
|
|
65
|
+
# Limit how much data is read from stdout and
|
|
66
|
+
# stderr. At most 20k chars is read from both:
|
|
67
|
+
p Test::Command
|
|
68
|
+
.new("git")
|
|
69
|
+
.limit(stdout: 20_000, stderr: 20_000)
|
|
70
|
+
.argv("diff", "--cached")
|
|
71
|
+
.stdout
|
|
63
72
|
```
|
|
64
73
|
|
|
65
74
|
<details>
|
data/lib/test/command/version.rb
CHANGED
data/lib/test/command.rb
CHANGED
|
@@ -34,6 +34,7 @@ class Test::Command
|
|
|
34
34
|
@stdout = ""
|
|
35
35
|
@stderr = ""
|
|
36
36
|
@enoent = false
|
|
37
|
+
@limit = {stdout: nil, stderr: nil}
|
|
37
38
|
end
|
|
38
39
|
|
|
39
40
|
##
|
|
@@ -67,6 +68,19 @@ class Test::Command
|
|
|
67
68
|
tap { @stdin = data }
|
|
68
69
|
end
|
|
69
70
|
|
|
71
|
+
##
|
|
72
|
+
# Limits how many bytes of each stream are captured.
|
|
73
|
+
# A stream output beyond the limit is discarded, keeping
|
|
74
|
+
# memory bounded even for a command that streams a lot.
|
|
75
|
+
# @param [Integer, nil] stdout
|
|
76
|
+
# Max bytes of stdout to read, or nil for unlimited
|
|
77
|
+
# @param [Integer, nil] stderr
|
|
78
|
+
# Max bytes of stderr to read, or nil for unlimited
|
|
79
|
+
# @return [Test::Command]
|
|
80
|
+
def limit(stdout: nil, stderr: nil)
|
|
81
|
+
tap { @limit = {stdout:, stderr:} }
|
|
82
|
+
end
|
|
83
|
+
|
|
70
84
|
##
|
|
71
85
|
# Spawns a command
|
|
72
86
|
# @return [Test::Command]
|
|
@@ -85,8 +99,8 @@ class Test::Command
|
|
|
85
99
|
@out.w.close
|
|
86
100
|
@err.w.close
|
|
87
101
|
@producer = Thread.new do
|
|
88
|
-
@stdout = @out.r
|
|
89
|
-
@stderr = @err.r
|
|
102
|
+
@stdout = read_limited(@out.r, @limit[:stdout])
|
|
103
|
+
@stderr = read_limited(@err.r, @limit[:stderr])
|
|
90
104
|
Process.wait
|
|
91
105
|
@status = $?
|
|
92
106
|
ensure
|
|
@@ -232,6 +246,31 @@ class Test::Command
|
|
|
232
246
|
|
|
233
247
|
private
|
|
234
248
|
|
|
249
|
+
##
|
|
250
|
+
# Reads up to +max+ bytes from a stream, then drains
|
|
251
|
+
# the remainder so a child writing more than the limit
|
|
252
|
+
# does not block on a full pipe. When +max+ is nil the
|
|
253
|
+
# entire stream is read.
|
|
254
|
+
# @param [IO] io
|
|
255
|
+
# @param [Integer, nil] max
|
|
256
|
+
# @return [String]
|
|
257
|
+
def read_limited(io, max)
|
|
258
|
+
return io.read if max.nil?
|
|
259
|
+
buf = +""
|
|
260
|
+
remaining = max
|
|
261
|
+
while remaining > 0 && (chunk = io.read(remaining))
|
|
262
|
+
buf << chunk
|
|
263
|
+
remaining -= chunk.bytesize
|
|
264
|
+
end
|
|
265
|
+
##
|
|
266
|
+
# Drain whatever is left so the child can exit:
|
|
267
|
+
# the drained bytes are discarded, keeping memory
|
|
268
|
+
# bounded.
|
|
269
|
+
while (chunk = io.read(16_384))
|
|
270
|
+
end
|
|
271
|
+
buf
|
|
272
|
+
end
|
|
273
|
+
|
|
235
274
|
##
|
|
236
275
|
# Returns a pipe pair used for the command's
|
|
237
276
|
# standard input. When no input is set, the child
|
data/test/cmd_test.rb
CHANGED
|
@@ -58,6 +58,43 @@ class Test::Command
|
|
|
58
58
|
end
|
|
59
59
|
end
|
|
60
60
|
|
|
61
|
+
##
|
|
62
|
+
# Test::Command#limit
|
|
63
|
+
class LimitTest < Test
|
|
64
|
+
def test_ruby_limit_stdout
|
|
65
|
+
assert_equal "happy",
|
|
66
|
+
::Test::Command.new("printf", "%s", "happy days")
|
|
67
|
+
.limit(stdout: 5)
|
|
68
|
+
.stdout
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def test_ruby_limit_stderr
|
|
72
|
+
assert_equal "smile",
|
|
73
|
+
::Test::Command.new("sh", "-c", "echo smile >&2")
|
|
74
|
+
.limit(stderr: 5)
|
|
75
|
+
.stderr
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def test_ruby_limit_nil_is_unlimited
|
|
79
|
+
expect = "a" * 20_000
|
|
80
|
+
assert_equal expect,
|
|
81
|
+
::Test::Command.new("ruby", "-e", "print 'a' * 20_000")
|
|
82
|
+
.stdout
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def test_ruby_limit_drains_remaining_output
|
|
86
|
+
cmd = ::Test::Command.new("sh", "-c", "printf 'happy days'")
|
|
87
|
+
.limit(stdout: 5)
|
|
88
|
+
.spawn
|
|
89
|
+
assert_equal true, cmd.spawned?
|
|
90
|
+
##
|
|
91
|
+
# A full pipe would block forever: the
|
|
92
|
+
# drain lets the child finish and capture
|
|
93
|
+
# its status
|
|
94
|
+
assert_equal 0, cmd.exit_status
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
61
98
|
##
|
|
62
99
|
# Test::Command#{exit_status, status, success?}
|
|
63
100
|
class ExitStatusTest < Test
|