test-cmd.rb 0.11.1 → 0.12.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 82a43ee0666fd9baea96c1974997092b1a739f730327e0a30ffa5d2e5b48cdaa
4
- data.tar.gz: 2ca5079265f236de839baa8c6731433f99a9b0650c60e7c122db03c2b1a5e7bc
3
+ metadata.gz: 67a69e56d58ed586edecb9b4792bbc54913f2044a6468ce6d098744142cf78a0
4
+ data.tar.gz: 713bd38cbe6812e61e8847e156e16732cdcfc72026f206bd9df70c03c6d8a946
5
5
  SHA512:
6
- metadata.gz: 4a6ec40cdce6d791ca2e4880cd6bc31af6151706bb92dd467c0d2b99ce3551e2dd13efd2ecea46d32c2e2feb30995466ade1b16529e93d52e2321b2b29233788
7
- data.tar.gz: 3b286a1f7e87e1066837b4a6c5f61421409637becb71792ab06919b5b7620759bd0f6b036e6694cc1f18e14144733bdefb117bd98a61f2c66a4b9f540661f52d
6
+ metadata.gz: b8f1e8928b018372d5d6247300509f249bb3f7934a04b4a7356beff15d9c223a396657e1bb5e050bb7777b36185f2cf106618330f73df6939204c430a25eb584
7
+ data.tar.gz: 1f76220a3ab003bf434ab2dd7d604f7abe0577543abd5d86afee3b0a1fb82c3f164f8e6ba62489c1cacb9193c44860cd3fb152e93c3bcf4491400584805dde41
@@ -12,7 +12,7 @@ jobs:
12
12
  fail-fast: false
13
13
  matrix:
14
14
  os: [ubuntu-latest, macos-latest]
15
- ruby: [3.1, 3.2]
15
+ ruby: [3.1, 3.2, 3.3]
16
16
  runs-on: ${{ matrix.os }}
17
17
  steps:
18
18
  - uses: actions/checkout@v2
data/README.md CHANGED
@@ -8,8 +8,8 @@ a command.
8
8
  ### Callbacks
9
9
 
10
10
  The success and failure callbacks provide hooks for when
11
- a command exits successfully or unsuccessfully. The callback
12
- is passed an instance of
11
+ a command exits successfully or unsuccessfully. The callbacks
12
+ are passed an instance of
13
13
  [Test::Cmd](https://0x1eef.github.io/x/test-cmd.rb/Test/Cmd.html):
14
14
 
15
15
  ``` ruby
@@ -55,46 +55,6 @@ class CmdTest < Test::Unit::TestCase
55
55
  end
56
56
  ```
57
57
 
58
- ### IO#sync
59
-
60
- Sometimes it can be neccessary to bypass Ruby's internal buffer and flush
61
- output to the operating system immediately, otherwise there can be unexpected
62
- results. Consider the following example, where the output will be
63
- `bar\nfoo\n` rather than `foo\nbar\n`:
64
-
65
- ``` ruby
66
- ##
67
- # test.rb
68
- fork do
69
- sleep(1)
70
- puts "bar"
71
- end
72
- puts "foo"
73
- Process.wait
74
-
75
- ##
76
- # cmd.rb
77
- p cmd("ruby", "test.rb").stdout # => "bar\nfoo\n"
78
- ```
79
-
80
- And with output flushed to the operating system immediately:
81
-
82
- ``` ruby
83
- ##
84
- # test.rb
85
- $stdout.sync = true
86
- fork do
87
- sleep(1)
88
- puts "bar"
89
- end
90
- puts "foo"
91
- Process.wait
92
-
93
- ##
94
- # cmd.rb
95
- p cmd("ruby", "test.rb").stdout # => "foo\nbar\n"
96
- ```
97
-
98
58
  ## Documentation
99
59
 
100
60
  A complete API reference is available at
@@ -102,8 +62,6 @@ A complete API reference is available at
102
62
 
103
63
  ## Install
104
64
 
105
- **Rubygems.org**
106
-
107
65
  test-cmd.rb can be installed via rubygems.org:
108
66
 
109
67
  gem install test-cmd.rb
data/lib/test/cmd.rb CHANGED
@@ -1,12 +1,23 @@
1
- module Test
2
- end unless defined?(Test)
1
+ unless defined?(Test)
2
+ module Test
3
+ end
4
+ end
3
5
 
4
6
  ##
5
7
  # test-cmd.rb provides an object oriented interface
6
8
  # for spawning a command.
7
9
  class Test::Cmd
8
- require "tempfile"
9
- require "securerandom"
10
+ ##
11
+ # @api private
12
+ class Pipe < Struct.new(:r, :w)
13
+ def self.pair
14
+ new(*IO.pipe)
15
+ end
16
+
17
+ def close
18
+ [r, w].each(&:close)
19
+ end
20
+ end
10
21
 
11
22
  ##
12
23
  # @param [String] cmd
@@ -19,6 +30,8 @@ class Test::Cmd
19
30
  @argv = argv.dup
20
31
  @status = nil
21
32
  @spawned = false
33
+ @stdout = ""
34
+ @stderr = ""
22
35
  end
23
36
 
24
37
  ##
@@ -36,13 +49,21 @@ class Test::Cmd
36
49
  return self if @spawned
37
50
 
38
51
  tap do
52
+ out, err = Pipe.pair, Pipe.pair
39
53
  @spawned = true
40
- @out_io, @err_io = spawn_io
41
- Process.spawn(@cmd, *@argv, {out: @out_io, err: @err_io})
42
- Process.wait
43
- @status = $?
54
+ t = Thread.new do
55
+ Process.spawn(@cmd, *@argv, {out: out.w, err: err.w})
56
+ Process.wait
57
+ @status = $?
58
+ end
59
+ loop do
60
+ break unless t.alive?
61
+ io, _ = IO.select([out.r, err.r], nil, nil, 0.01)
62
+ io&.include?(out.r) ? @stdout << out.r.read(1) : nil
63
+ io&.include?(err.r) ? @stderr << err.r.read(1) : nil
64
+ end
44
65
  ensure
45
- [stdout, stderr]
66
+ [out, err].each(&:close)
46
67
  end
47
68
  end
48
69
 
@@ -50,24 +71,16 @@ class Test::Cmd
50
71
  # @return [String]
51
72
  # Returns the contents of stdout
52
73
  def stdout
53
- @stdout ||= begin
54
- spawn
55
- out_io.tap(&:rewind).read.tap { out_io.close }
56
- rescue IOError
57
- @stdout
58
- end
74
+ spawn
75
+ @stdout
59
76
  end
60
77
 
61
78
  ##
62
79
  # @return [String]
63
80
  # Returns the contents of stderr
64
81
  def stderr
65
- @stderr ||= begin
66
- spawn
67
- err_io.tap(&:rewind).read.tap { err_io.close }
68
- rescue IOError
69
- @stderr
70
- end
82
+ spawn
83
+ @stderr
71
84
  end
72
85
 
73
86
  ##
@@ -137,27 +150,6 @@ class Test::Cmd
137
150
  def spawned?
138
151
  @spawned
139
152
  end
140
-
141
- private
142
-
143
- attr_reader :out_io, :err_io
144
-
145
- def spawn_io
146
- [
147
- [".testcmd.stdout.#{ns}.", SecureRandom.alphanumeric(3)],
148
- [".testcmd.stderr.#{ns}.", SecureRandom.alphanumeric(3)]
149
- ].map do
150
- Tempfile.new(_1).tap do |file|
151
- File.chmod(0, file.path)
152
- ensure
153
- file.unlink
154
- end
155
- end
156
- end
157
-
158
- def ns
159
- [Process.pid, object_id].join(".")
160
- end
161
153
  end
162
154
 
163
155
  module Kernel
@@ -3,6 +3,7 @@ require_relative "setup"
3
3
  class Test::Cmd
4
4
  class Test < Test::Unit::TestCase
5
5
  private
6
+
6
7
  def ruby(str)
7
8
  cmd "ruby", "-e", str
8
9
  end
@@ -57,7 +58,7 @@ class Test::Cmd
57
58
  end
58
59
  puts "foo"
59
60
  Process.wait
60
- CODE
61
+ CODE
61
62
  assert_equal "foo\nbar\n", ruby(code).stdout
62
63
  end
63
64
  end
@@ -84,29 +85,6 @@ class Test::Cmd
84
85
  end
85
86
  end
86
87
 
87
- ##
88
- # Test::Cmd#spawn
89
- class SpawnTest < Test
90
- def test_io_closed_after_spawn
91
- %i[out_io err_io].each do |io|
92
- assert_equal true, spawned_command.send(io).closed?
93
- end
94
- end
95
-
96
- def test_io_unlink_after_spawn
97
- %i[out_io err_io].each do |io|
98
- path = spawned_command.send(io).__getobj__.path
99
- assert_equal false, File.exist?(path)
100
- end
101
- end
102
-
103
- private
104
-
105
- def spawned_command
106
- ruby("puts 42").spawn
107
- end
108
- end
109
-
110
88
  ##
111
89
  # Test::Cmd#spawned?
112
90
  class SpawnedTest < Test
data/test-cmd.rb.gemspec CHANGED
@@ -5,7 +5,7 @@ Gem::Specification.new do |gem|
5
5
  gem.authors = ["0x1eef"]
6
6
  gem.email = ["0x1eef@protonmail.com"]
7
7
  gem.homepage = "https://github.com/0x1eef/test-cmd.rb#readme"
8
- gem.version = "0.11.1"
8
+ gem.version = "0.12.1"
9
9
  gem.required_ruby_version = ">= 3.0"
10
10
  gem.licenses = ["0BSD"]
11
11
  gem.files = `git ls-files`.split($/)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: test-cmd.rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.1
4
+ version: 0.12.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - '0x1eef'
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-05-17 00:00:00.000000000 Z
11
+ date: 2024-06-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: test-unit
@@ -99,8 +99,8 @@ files:
99
99
  - lib/test-cmd.rb
100
100
  - lib/test/cmd.rb
101
101
  - test-cmd.rb.gemspec
102
+ - test/cmd_test.rb
102
103
  - test/setup.rb
103
- - test/test_cmd_test.rb
104
104
  homepage: https://github.com/0x1eef/test-cmd.rb#readme
105
105
  licenses:
106
106
  - 0BSD