io-extra 1.4.0 → 1.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
- checksums.yaml.gz.sig +0 -0
- data/{CHANGES → CHANGES.md} +22 -17
- data/Gemfile +2 -0
- data/LICENSE +177 -0
- data/{MANIFEST → MANIFEST.md} +4 -4
- data/README.md +114 -0
- data/Rakefile +102 -0
- data/certs/djberg96_pub.pem +26 -0
- data/doc/io_extra.txt +85 -0
- data/examples/example_io_extra.rb +53 -0
- data/examples/example_pread.rb +24 -0
- data/examples/writev_benchmark.rb +19 -0
- data/ext/extra.bundle.dSYM/Contents/Info.plist +20 -0
- data/ext/extra.bundle.dSYM/Contents/Resources/Relocations/aarch64/extra.bundle.yml +5 -0
- data/ext/io/extra.c +172 -81
- data/io-extra.gemspec +51 -0
- data/lib/io-extra.rb +3 -1
- data/spec/io_extra_spec.rb +179 -0
- data.tar.gz.sig +0 -0
- metadata +74 -15
- metadata.gz.sig +0 -0
- data/README +0 -97
- data/test/test_io_extra.rb +0 -148
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
################################################################################
|
|
2
|
+
# io_extra_spec.rb
|
|
3
|
+
#
|
|
4
|
+
# Tests for the io-extra library. These should be run via the 'rake spec' task.
|
|
5
|
+
################################################################################
|
|
6
|
+
require 'rspec'
|
|
7
|
+
require 'rbconfig'
|
|
8
|
+
require 'io/nonblock'
|
|
9
|
+
require 'io-extra'
|
|
10
|
+
require 'fileutils'
|
|
11
|
+
|
|
12
|
+
describe IO do
|
|
13
|
+
let(:linux) { RbConfig::CONFIG['host_os'] =~ /linux/i }
|
|
14
|
+
let(:osx) { RbConfig::CONFIG['host_os'] =~ /darwin/i }
|
|
15
|
+
|
|
16
|
+
before do
|
|
17
|
+
@file = 'delete_this.txt'
|
|
18
|
+
@fh = File.open(@file, 'w+')
|
|
19
|
+
@fh.puts "The quick brown fox jumped over the lazy dog's back"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
after do
|
|
23
|
+
@fh.close rescue nil
|
|
24
|
+
@fh = nil
|
|
25
|
+
FileUtils.rm_f(@file)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
context 'constants' do
|
|
29
|
+
example 'EXTRA_VERSION' do
|
|
30
|
+
expect(IO::EXTRA_VERSION).to eq('1.5.0')
|
|
31
|
+
expect(IO::EXTRA_VERSION).to be_frozen
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
example 'DIRECT' do
|
|
35
|
+
skip 'Skipped unless Linux' unless linux
|
|
36
|
+
# O_DIRECT value varies by architecture (e.g., 040000 on x86_64, 0100000 on others)
|
|
37
|
+
# Just verify it's defined and is a valid flag (positive integer)
|
|
38
|
+
expect(IO::DIRECT).to be_a(Integer)
|
|
39
|
+
expect(IO::DIRECT).to be > 0
|
|
40
|
+
expect(IO::DIRECT).to eq(File::DIRECT)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
example 'DIRECTIO_ON and DIRECTIO_OFF' do
|
|
44
|
+
expect(IO::DIRECTIO_ON).not_to be_nil
|
|
45
|
+
expect(IO::DIRECTIO_OFF).not_to be_nil
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
example 'IOV_MAX_constant' do
|
|
49
|
+
expect(IO::IOV_MAX).to be_a(Integer)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
context 'flags' do
|
|
54
|
+
example 'DIRECT flag' do
|
|
55
|
+
skip 'Skipped unless Linux' unless linux
|
|
56
|
+
expect { File.open(@fh.path, IO::RDWR | IO::DIRECT).close }.not_to raise_error
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
example 'directio? method' do
|
|
60
|
+
expect(@fh).to respond_to(:directio?)
|
|
61
|
+
expect{ @fh.directio? }.not_to raise_error
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
example 'set DIRECTIO_ON' do
|
|
65
|
+
expect(@fh).to respond_to(:directio=)
|
|
66
|
+
expect{ @fh.directio = 99 }.to raise_error(StandardError)
|
|
67
|
+
expect{ @fh.directio = IO::DIRECTIO_ON }.not_to raise_error
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
context 'fdwalk' do
|
|
72
|
+
example 'fdwalk basic functionality' do
|
|
73
|
+
expect(IO).to respond_to(:fdwalk)
|
|
74
|
+
expect{ IO.fdwalk(0){} }.not_to raise_error
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
example 'fdwalk_honors_lowfd' do
|
|
78
|
+
IO.fdwalk(1){ |f| expect(f.fileno >= 1).to be(true) }
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
context 'closefrom' do
|
|
83
|
+
example 'closefrom' do
|
|
84
|
+
expect(IO).to respond_to(:closefrom)
|
|
85
|
+
expect{ IO.closefrom(3) }.not_to raise_error
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
context 'pread' do
|
|
90
|
+
example 'pread basic functionality' do
|
|
91
|
+
@fh.close rescue nil
|
|
92
|
+
@fh = File.open(@file)
|
|
93
|
+
expect(IO).to respond_to(:pread)
|
|
94
|
+
expect(IO.pread(@fh, 5, 4)).to eq('quick')
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
example 'pread works in binary mode' do
|
|
98
|
+
@fh.close rescue nil
|
|
99
|
+
@fh = File.open(@file, 'ab')
|
|
100
|
+
@fh.binmode
|
|
101
|
+
size = @fh.stat.size
|
|
102
|
+
expect { @fh.syswrite("FOO\0HELLO") }.not_to raise_error
|
|
103
|
+
@fh.close rescue nil
|
|
104
|
+
@fh = File.open(@file)
|
|
105
|
+
expect(IO.pread(@fh, 3, size + 2)).to eq("O\0H")
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
example 'pread with offset works as expected' do
|
|
109
|
+
@fh.close rescue nil
|
|
110
|
+
@fh = File.open(@file)
|
|
111
|
+
size = @fh.stat.size
|
|
112
|
+
expect(IO.pread(@fh, 5, size - 3)).to eq("ck\n")
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
context 'pwrite' do
|
|
117
|
+
example 'pwrite basic functionality' do
|
|
118
|
+
expect(IO).to respond_to(:pwrite)
|
|
119
|
+
expect{ IO.pwrite(@fh, 'HAL', 0) }.not_to raise_error
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
context 'writev' do
|
|
124
|
+
example 'writev' do
|
|
125
|
+
expect(IO).to respond_to(:writev)
|
|
126
|
+
expect(IO.writev(@fh, %w[hello world])).to eq(10)
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
context 'writev_retry' do
|
|
131
|
+
skip 'no /dev/urandom found, skipping' unless File.exist?('/dev/urandom')
|
|
132
|
+
# rubocop:disable Metrics/BlockLength
|
|
133
|
+
example 'writev with retry works as expected' do
|
|
134
|
+
empty = ''
|
|
135
|
+
|
|
136
|
+
if empty.respond_to?(:force_encoding)
|
|
137
|
+
empty.force_encoding(Encoding::BINARY)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# bs * count should be > PIPE_BUF
|
|
141
|
+
[true, false].each do |nonblock|
|
|
142
|
+
[[512, 512], [131073, 3], [4098, 64]].each do |(bs, count)|
|
|
143
|
+
rd, wr = IO.pipe
|
|
144
|
+
wr.nonblock = nonblock
|
|
145
|
+
buf = File.open('/dev/urandom', 'rb') { |fp| fp.sysread(bs) }
|
|
146
|
+
vec = (1..count).map { buf }
|
|
147
|
+
|
|
148
|
+
pid = fork do
|
|
149
|
+
wr.close
|
|
150
|
+
tmp = []
|
|
151
|
+
sleep 0.1
|
|
152
|
+
loop do
|
|
153
|
+
tmp << rd.readpartial(8192, buf)
|
|
154
|
+
rescue EOFError
|
|
155
|
+
break
|
|
156
|
+
end
|
|
157
|
+
ok = (vec.join(empty) == tmp.join(empty))
|
|
158
|
+
exit! ok
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
expect { rd.close }.not_to raise_error
|
|
162
|
+
expect(IO.writev(wr.fileno, vec)).to eq(bs * count)
|
|
163
|
+
expect { wr.close }.not_to raise_error
|
|
164
|
+
_, status = Process.waitpid2(pid)
|
|
165
|
+
expect(status.success?).to be(true)
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
# rubocop:enable Metrics/BlockLength
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
example 'ttyname' do
|
|
173
|
+
expect(@fh).to respond_to(:ttyname)
|
|
174
|
+
expect(@fh.ttyname).to be_nil
|
|
175
|
+
|
|
176
|
+
skip 'skipping ttyname spec in CI environment' if ENV['CI']
|
|
177
|
+
expect($stdout.ttyname).to be_a(String)
|
|
178
|
+
end
|
|
179
|
+
end
|
data.tar.gz.sig
CHANGED
|
Binary file
|
metadata
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: io-extra
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Daniel J. Berger
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain:
|
|
11
10
|
- |
|
|
@@ -35,22 +34,64 @@ cert_chain:
|
|
|
35
34
|
ORVCZpRuCPpmC8qmqxUnARDArzucjaclkxjLWvCVHeFa9UP7K3Nl9oTjJNv+7/jM
|
|
36
35
|
WZs4eecIcUc4tKdHxcAJ0MO/Dkqq7hGaiHpwKY76wQ1+8xAh
|
|
37
36
|
-----END CERTIFICATE-----
|
|
38
|
-
date:
|
|
37
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
39
38
|
dependencies:
|
|
40
39
|
- !ruby/object:Gem::Dependency
|
|
41
|
-
name:
|
|
40
|
+
name: rake
|
|
41
|
+
requirement: !ruby/object:Gem::Requirement
|
|
42
|
+
requirements:
|
|
43
|
+
- - ">="
|
|
44
|
+
- !ruby/object:Gem::Version
|
|
45
|
+
version: '0'
|
|
46
|
+
type: :development
|
|
47
|
+
prerelease: false
|
|
48
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
49
|
+
requirements:
|
|
50
|
+
- - ">="
|
|
51
|
+
- !ruby/object:Gem::Version
|
|
52
|
+
version: '0'
|
|
53
|
+
- !ruby/object:Gem::Dependency
|
|
54
|
+
name: rspec
|
|
42
55
|
requirement: !ruby/object:Gem::Requirement
|
|
43
56
|
requirements:
|
|
44
57
|
- - "~>"
|
|
45
58
|
- !ruby/object:Gem::Version
|
|
46
|
-
version: '3.
|
|
59
|
+
version: '3.9'
|
|
47
60
|
type: :development
|
|
48
61
|
prerelease: false
|
|
49
62
|
version_requirements: !ruby/object:Gem::Requirement
|
|
50
63
|
requirements:
|
|
51
64
|
- - "~>"
|
|
52
65
|
- !ruby/object:Gem::Version
|
|
53
|
-
version: '3.
|
|
66
|
+
version: '3.9'
|
|
67
|
+
- !ruby/object:Gem::Dependency
|
|
68
|
+
name: rubocop
|
|
69
|
+
requirement: !ruby/object:Gem::Requirement
|
|
70
|
+
requirements:
|
|
71
|
+
- - ">="
|
|
72
|
+
- !ruby/object:Gem::Version
|
|
73
|
+
version: '0'
|
|
74
|
+
type: :development
|
|
75
|
+
prerelease: false
|
|
76
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
77
|
+
requirements:
|
|
78
|
+
- - ">="
|
|
79
|
+
- !ruby/object:Gem::Version
|
|
80
|
+
version: '0'
|
|
81
|
+
- !ruby/object:Gem::Dependency
|
|
82
|
+
name: rubocop-rspec
|
|
83
|
+
requirement: !ruby/object:Gem::Requirement
|
|
84
|
+
requirements:
|
|
85
|
+
- - ">="
|
|
86
|
+
- !ruby/object:Gem::Version
|
|
87
|
+
version: '0'
|
|
88
|
+
type: :development
|
|
89
|
+
prerelease: false
|
|
90
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
91
|
+
requirements:
|
|
92
|
+
- - ">="
|
|
93
|
+
- !ruby/object:Gem::Version
|
|
94
|
+
version: '0'
|
|
54
95
|
description: |2
|
|
55
96
|
Adds the IO.closefrom, IO.fdwalk, IO.pread, IO.pwrite, and IO.writev
|
|
56
97
|
singleton methods as well as the IO#directio, IO#directio? and IO#ttyname
|
|
@@ -60,23 +101,42 @@ executables: []
|
|
|
60
101
|
extensions:
|
|
61
102
|
- ext/extconf.rb
|
|
62
103
|
extra_rdoc_files:
|
|
63
|
-
- CHANGES
|
|
64
|
-
-
|
|
65
|
-
-
|
|
104
|
+
- CHANGES.md
|
|
105
|
+
- MANIFEST.md
|
|
106
|
+
- README.md
|
|
66
107
|
- ext/io/extra.c
|
|
67
108
|
files:
|
|
109
|
+
- CHANGES.md
|
|
110
|
+
- Gemfile
|
|
111
|
+
- LICENSE
|
|
112
|
+
- MANIFEST.md
|
|
113
|
+
- README.md
|
|
114
|
+
- Rakefile
|
|
115
|
+
- certs/djberg96_pub.pem
|
|
116
|
+
- doc/io_extra.txt
|
|
117
|
+
- examples/example_io_extra.rb
|
|
118
|
+
- examples/example_pread.rb
|
|
119
|
+
- examples/writev_benchmark.rb
|
|
120
|
+
- ext/extconf.rb
|
|
121
|
+
- ext/extra.bundle.dSYM/Contents/Info.plist
|
|
122
|
+
- ext/extra.bundle.dSYM/Contents/Resources/Relocations/aarch64/extra.bundle.yml
|
|
123
|
+
- ext/io/extra.c
|
|
124
|
+
- io-extra.gemspec
|
|
68
125
|
- lib/io-extra.rb
|
|
126
|
+
- spec/io_extra_spec.rb
|
|
69
127
|
homepage: https://github.com/djberg96/io-extra
|
|
70
128
|
licenses:
|
|
71
129
|
- Apache-2.0
|
|
72
130
|
metadata:
|
|
73
131
|
homepage_uri: https://github.com/djberg96/io-extra
|
|
74
132
|
bug_tracker_uri: https://github.com/djberg96/io-extra/issues
|
|
75
|
-
changelog_uri: https://github.com/djberg96/io-extra/blob/
|
|
133
|
+
changelog_uri: https://github.com/djberg96/io-extra/blob/main/CHANGES.md
|
|
76
134
|
documentation_uri: https://github.com/djberg96/io-extra/wiki
|
|
77
135
|
source_code_uri: https://github.com/djberg96/io-extra
|
|
78
136
|
wiki_uri: https://github.com/djberg96/io-extra/wiki
|
|
79
|
-
|
|
137
|
+
rubygems_mfa_required: 'true'
|
|
138
|
+
github_repo: https://github.com/djberg96/io-extra
|
|
139
|
+
funding_uri: https://github.com/sponsors/djberg96
|
|
80
140
|
rdoc_options: []
|
|
81
141
|
require_paths:
|
|
82
142
|
- lib
|
|
@@ -84,16 +144,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
84
144
|
requirements:
|
|
85
145
|
- - ">="
|
|
86
146
|
- !ruby/object:Gem::Version
|
|
87
|
-
version:
|
|
147
|
+
version: '0'
|
|
88
148
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
89
149
|
requirements:
|
|
90
150
|
- - ">="
|
|
91
151
|
- !ruby/object:Gem::Version
|
|
92
152
|
version: '0'
|
|
93
153
|
requirements: []
|
|
94
|
-
rubygems_version: 3.
|
|
95
|
-
signing_key:
|
|
154
|
+
rubygems_version: 3.6.9
|
|
96
155
|
specification_version: 4
|
|
97
156
|
summary: Adds extra methods to the IO class
|
|
98
157
|
test_files:
|
|
99
|
-
-
|
|
158
|
+
- spec/io_extra_spec.rb
|
metadata.gz.sig
CHANGED
|
Binary file
|
data/README
DELETED
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
= Description
|
|
2
|
-
The io-extra library provides a few extra IO methods that you may find
|
|
3
|
-
handy. They are IO.closefrom, IO.fdwalk, IO.pread, IO.pread_ptr, IO.pwrite,
|
|
4
|
-
IO.writev, IO#directio? and IO#directio=.
|
|
5
|
-
|
|
6
|
-
This library is not supported on MS Windows.
|
|
7
|
-
|
|
8
|
-
Support for OS X is limited. See below for details.
|
|
9
|
-
|
|
10
|
-
= Installation
|
|
11
|
-
gem install io-extra
|
|
12
|
-
|
|
13
|
-
= Synopsis
|
|
14
|
-
require 'io-extra' # Do not use 'io/extra'
|
|
15
|
-
|
|
16
|
-
# Close all file descriptors from 3 up.
|
|
17
|
-
IO.closefrom(3)
|
|
18
|
-
|
|
19
|
-
# Inspect all the open handles
|
|
20
|
-
IO.fdwalk(0){ |handle|
|
|
21
|
-
puts "=" * 40
|
|
22
|
-
p handle
|
|
23
|
-
p handle.fileno
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
# Write an array to an IO object efficiently
|
|
27
|
-
IO.writev(fh.fileno, %w[a b c])
|
|
28
|
-
|
|
29
|
-
= Developer's Notes
|
|
30
|
-
The "require 'io-extra'" is preferred over 'io/extra' because this is a mix
|
|
31
|
-
of pure Ruby and C extension. The former require's the latter, so that way
|
|
32
|
-
you get all the methods and constants that you expect.
|
|
33
|
-
|
|
34
|
-
You might be wondering what the difference is between my implementation of
|
|
35
|
-
IO.closefrom and a pure Ruby version that looks something like this:
|
|
36
|
-
|
|
37
|
-
def IO.closefrom(n)
|
|
38
|
-
0.upto(n) do |fd|
|
|
39
|
-
IO.for_fd(fd).close
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
The primary difference is that this walks all file descriptors, rather
|
|
44
|
-
than only open file descriptors. However, I should note that this only
|
|
45
|
-
applies if your platform supports the closefrom() function. In that case,
|
|
46
|
-
the only advantage is speed.
|
|
47
|
-
|
|
48
|
-
You might also be wondering what the difference is between my implementation
|
|
49
|
-
of IO.fdwalk and a pure Ruby version that looks something like this:
|
|
50
|
-
|
|
51
|
-
def IO.fdwalk(n)
|
|
52
|
-
ObjectSpace.each_object(File){ |f|
|
|
53
|
-
yield f if f.fileno >= n
|
|
54
|
-
}
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
The primary difference is that this only closes Ruby file objects, not
|
|
58
|
-
necessarily every file handle opened by the Ruby process. For example, handles
|
|
59
|
-
opened via system() calls.
|
|
60
|
-
|
|
61
|
-
= Note to OS X Users
|
|
62
|
-
The OS X platform does not support closefrom() or fdwalk(). The hand-
|
|
63
|
-
crafted IO.closefrom function will not work because the getrlimit()
|
|
64
|
-
function on OS X does not work. Patches welcome.
|
|
65
|
-
|
|
66
|
-
= Documentation
|
|
67
|
-
For further documentation, see the io_extra.txt file or the inline
|
|
68
|
-
documentation that was generated by RDoc (if you did a gem install).
|
|
69
|
-
|
|
70
|
-
= Known Issues
|
|
71
|
-
The IO.writev tests fail on Solaris. Short test scripts seem to work,
|
|
72
|
-
however. We're not sure what the issue is yet. Help wanted.
|
|
73
|
-
|
|
74
|
-
Update: As of 2018 Solaris is basically dead, so I'm not going to worry
|
|
75
|
-
about supporting Solaris unless there's an outcry.
|
|
76
|
-
|
|
77
|
-
Please file any bug reports on the project page at
|
|
78
|
-
https://github.com/djberg96/io-extra
|
|
79
|
-
|
|
80
|
-
= Acknowledgements
|
|
81
|
-
Eric Wong for some great work on Linux compatibility and other fixes, as
|
|
82
|
-
well as the code for the IO.writev method.
|
|
83
|
-
|
|
84
|
-
= License
|
|
85
|
-
Apache-2.0
|
|
86
|
-
|
|
87
|
-
= Copyright
|
|
88
|
-
(C) 2003-2020 Daniel J. Berger
|
|
89
|
-
All Rights Reserved
|
|
90
|
-
|
|
91
|
-
= Warranty
|
|
92
|
-
This package is provided "as is" and without any express or
|
|
93
|
-
implied warranties, including, without limitation, the implied
|
|
94
|
-
warranties of merchantability and fitness for a particular purpose.
|
|
95
|
-
|
|
96
|
-
= Author
|
|
97
|
-
Daniel J. Berger
|
data/test/test_io_extra.rb
DELETED
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
###########################################################################
|
|
2
|
-
# test_io_extra.rb
|
|
3
|
-
#
|
|
4
|
-
# Test suite for the io-extra library. This test should be run via the
|
|
5
|
-
# 'rake test' task.
|
|
6
|
-
###########################################################################
|
|
7
|
-
require 'test-unit'
|
|
8
|
-
require 'rbconfig'
|
|
9
|
-
require 'io/nonblock'
|
|
10
|
-
require 'io-extra'
|
|
11
|
-
|
|
12
|
-
class TC_IO_Extra < Test::Unit::TestCase
|
|
13
|
-
def setup
|
|
14
|
-
@file = 'delete_this.txt'
|
|
15
|
-
@fh = File.open(@file, 'w+')
|
|
16
|
-
@fh.puts "The quick brown fox jumped over the lazy dog's back"
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def test_version
|
|
20
|
-
assert_equal('1.4.0', IO::EXTRA_VERSION)
|
|
21
|
-
assert_true(IO::EXTRA_VERSION.frozen?)
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def test_open_direct
|
|
25
|
-
omit_unless(RbConfig::CONFIG['host_os'] =~ /linux/i, 'Linux-only')
|
|
26
|
-
assert_nothing_raised do
|
|
27
|
-
fh = File.open(@fh.path, IO::RDWR|IO::DIRECT)
|
|
28
|
-
fh.close
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def test_directio
|
|
33
|
-
assert_respond_to(@fh, :directio?)
|
|
34
|
-
assert_nothing_raised{ @fh.directio? }
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
def test_directio_set
|
|
38
|
-
assert_respond_to(@fh, :directio=)
|
|
39
|
-
assert_raises(StandardError){ @fh.directio = 99 }
|
|
40
|
-
assert_nothing_raised{ @fh.directio = IO::DIRECTIO_ON }
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def test_constants
|
|
44
|
-
assert_not_nil(IO::DIRECTIO_ON)
|
|
45
|
-
assert_not_nil(IO::DIRECTIO_OFF)
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
def test_IOV_MAX_constant
|
|
49
|
-
assert_kind_of(Integer, IO::IOV_MAX)
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def test_fdwalk
|
|
53
|
-
omit_if(RbConfig::CONFIG['host_os'] =~ /darwin/i, 'unsupported')
|
|
54
|
-
assert_respond_to(IO, :fdwalk)
|
|
55
|
-
assert_nothing_raised{ IO.fdwalk(0){ } }
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def test_fdwalk_honors_lowfd
|
|
59
|
-
omit_if(RbConfig::CONFIG['host_os'] =~ /darwin/i, 'unsupported')
|
|
60
|
-
IO.fdwalk(1){ |f| assert_true(f.fileno >= 1) }
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
def test_closefrom
|
|
64
|
-
assert_respond_to(IO, :closefrom)
|
|
65
|
-
assert_nothing_raised{ IO.closefrom(3) }
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
def test_pread
|
|
69
|
-
@fh.close rescue nil
|
|
70
|
-
@fh = File.open(@file)
|
|
71
|
-
assert_respond_to(IO, :pread)
|
|
72
|
-
assert_equal("quick", IO.pread(@fh, 5, 4))
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
def test_pread_binary
|
|
76
|
-
@fh.close rescue nil
|
|
77
|
-
@fh = File.open(@file, "ab")
|
|
78
|
-
@fh.binmode
|
|
79
|
-
size = @fh.stat.size
|
|
80
|
-
assert_nothing_raised { @fh.syswrite("FOO\0HELLO") }
|
|
81
|
-
@fh.close rescue nil
|
|
82
|
-
@fh = File.open(@file)
|
|
83
|
-
assert_equal("O\0H", IO.pread(@fh, 3, size + 2))
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
def test_pread_last
|
|
87
|
-
@fh.close rescue nil
|
|
88
|
-
@fh = File.open(@file)
|
|
89
|
-
size = @fh.stat.size
|
|
90
|
-
assert_equal("ck\n", IO.pread(@fh, 5, size - 3))
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
def test_pwrite
|
|
94
|
-
assert_respond_to(IO, :pwrite)
|
|
95
|
-
assert_nothing_raised{ IO.pwrite(@fh, "HAL", 0) }
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
def test_writev
|
|
99
|
-
assert_respond_to(IO, :writev)
|
|
100
|
-
assert_equal(10, IO.writev(@fh, %w[hello world]))
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
def test_writev_retry
|
|
104
|
-
empty = ""
|
|
105
|
-
if empty.respond_to?(:force_encoding)
|
|
106
|
-
empty.force_encoding(Encoding::BINARY)
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
# bs * count should be > PIPE_BUF
|
|
110
|
-
[ true, false ].each do |nonblock|
|
|
111
|
-
[ [ 512, 512 ], [ 131073, 3 ], [ 4098, 64 ] ].each do |(bs,count)|
|
|
112
|
-
rd, wr = IO.pipe
|
|
113
|
-
wr.nonblock = nonblock
|
|
114
|
-
buf = File.open("/dev/urandom", "rb") { |fp| fp.sysread(bs) }
|
|
115
|
-
vec = (1..count).map { buf }
|
|
116
|
-
pid = fork do
|
|
117
|
-
wr.close
|
|
118
|
-
tmp = []
|
|
119
|
-
sleep 0.1
|
|
120
|
-
begin
|
|
121
|
-
tmp << rd.readpartial(8192, buf)
|
|
122
|
-
rescue EOFError
|
|
123
|
-
break
|
|
124
|
-
end while true
|
|
125
|
-
ok = (vec.join(empty) == tmp.join(empty))
|
|
126
|
-
exit! ok
|
|
127
|
-
end
|
|
128
|
-
assert_nothing_raised { rd.close }
|
|
129
|
-
assert_equal(bs * count, IO.writev(wr.fileno, vec))
|
|
130
|
-
assert_nothing_raised { wr.close }
|
|
131
|
-
_, status = Process.waitpid2(pid)
|
|
132
|
-
assert status.success?
|
|
133
|
-
end
|
|
134
|
-
end
|
|
135
|
-
end
|
|
136
|
-
|
|
137
|
-
def test_ttyname
|
|
138
|
-
assert_respond_to(@fh, :ttyname)
|
|
139
|
-
assert_nil(@fh.ttyname)
|
|
140
|
-
assert_kind_of(String, STDOUT.ttyname)
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
def teardown
|
|
144
|
-
@fh.close rescue nil
|
|
145
|
-
@fh = nil
|
|
146
|
-
File.delete(@file) if File.exist?(@file)
|
|
147
|
-
end
|
|
148
|
-
end
|