test-cmd.rb 0.11.1 → 0.12.1

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: 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