io_splice 2.2.0 → 2.2.0.18.g3025
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.
- data/.document +1 -0
- data/.gitignore +2 -0
- data/.wrongdoc.yml +5 -0
- data/GNUmakefile +7 -193
- data/README +2 -2
- data/Rakefile +20 -106
- data/ext/io_splice/io_splice_ext.c +129 -36
- data/io_splice.gemspec +12 -24
- data/lib/io/splice.rb +95 -101
- data/pkg.mk +168 -0
- data/test/test_io_splice.rb +99 -50
- metadata +37 -13
data/io_splice.gemspec
CHANGED
@@ -1,38 +1,26 @@
|
|
1
1
|
# -*- encoding: binary -*-
|
2
|
-
|
3
2
|
ENV["VERSION"] or abort "VERSION= must be specified"
|
4
3
|
manifest = File.readlines('.manifest').map! { |x| x.chomp! }
|
5
|
-
|
4
|
+
require 'wrongdoc'
|
5
|
+
extend Wrongdoc::Gemspec
|
6
|
+
name, summary, title = readme_metadata
|
6
7
|
|
7
8
|
Gem::Specification.new do |s|
|
8
9
|
s.name = %q{io_splice}
|
9
|
-
s.version = ENV["VERSION"]
|
10
|
-
|
11
|
-
s.authors = ["io_splice hackers"]
|
10
|
+
s.version = ENV["VERSION"].dup
|
11
|
+
s.authors = ["Ruby io_splice hackers"]
|
12
12
|
s.date = Time.now.utc.strftime('%Y-%m-%d')
|
13
|
-
s.description =
|
13
|
+
s.description = readme_description
|
14
14
|
s.email = %q{ruby.io.splice@librelist.com}
|
15
15
|
s.extensions = %w(ext/io_splice/extconf.rb)
|
16
|
-
|
17
|
-
s.extra_rdoc_files = File.readlines('.document').map! do |x|
|
18
|
-
x.chomp!
|
19
|
-
if File.directory?(x)
|
20
|
-
manifest.grep(%r{\A#{x}/})
|
21
|
-
elsif File.file?(x)
|
22
|
-
x
|
23
|
-
else
|
24
|
-
nil
|
25
|
-
end
|
26
|
-
end.flatten.compact
|
27
|
-
|
16
|
+
s.extra_rdoc_files = extra_rdoc_files(manifest)
|
28
17
|
s.files = manifest
|
29
|
-
s.homepage =
|
30
|
-
s.summary =
|
31
|
-
s.rdoc_options =
|
32
|
-
s.require_paths = %w(lib)
|
18
|
+
s.homepage = Wrongdoc.config[:rdoc_url]
|
19
|
+
s.summary = summary
|
20
|
+
s.rdoc_options = rdoc_options
|
33
21
|
s.rubyforge_project = %q{qrp}
|
34
|
-
|
35
|
-
s.
|
22
|
+
s.test_files = Dir['test/test_*.rb']
|
23
|
+
s.add_development_dependency('wrongdoc', '~> 1.5')
|
36
24
|
|
37
25
|
# s.licenses = %w(LGPL) # accessor not compatible with older RubyGems
|
38
26
|
end
|
data/lib/io/splice.rb
CHANGED
@@ -1,120 +1,114 @@
|
|
1
1
|
# -*- encoding: binary -*-
|
2
2
|
require 'io_splice_ext'
|
3
3
|
|
4
|
-
|
4
|
+
module IO::Splice
|
5
5
|
|
6
|
-
|
6
|
+
# the version of IO::Splice, currently 2.2.0
|
7
|
+
VERSION = '2.2.0'
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
rd.close
|
29
|
-
n
|
30
|
-
end
|
9
|
+
# The maximum default capacity of the pipe in bytes.
|
10
|
+
# Under stock Linux, this is 65536 bytes as of 2.6.11, and 4096 before
|
11
|
+
# We detect this at runtime as it is easy to recompile the kernel
|
12
|
+
# and set a new value.
|
13
|
+
# Starting with Linux 2.6.35, pipe capacity will be tunable
|
14
|
+
# and this will only represent the default capacity of a
|
15
|
+
# newly-created pipe.
|
16
|
+
PIPE_CAPA = begin
|
17
|
+
rd, wr = IO.pipe
|
18
|
+
buf = ' ' * PIPE_BUF
|
19
|
+
n = 0
|
20
|
+
begin
|
21
|
+
n += wr.write_nonblock(buf)
|
22
|
+
rescue Errno::EAGAIN
|
23
|
+
break
|
24
|
+
end while true
|
25
|
+
wr.close
|
26
|
+
rd.close
|
27
|
+
n
|
28
|
+
end
|
31
29
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
30
|
+
# copies the contents of the IO object given by +src+ to +dst+
|
31
|
+
# If +len+ is specified, then only +len+ bytes are copied and
|
32
|
+
# +EOFError+ is raised if fewer than +len+ bytes could be copied.
|
33
|
+
# Otherwise the copy will be until EOF is reached on the +src+.
|
34
|
+
# +src+ and +dst+ must be IO objects or respond to +to_io+
|
35
|
+
def self.copy_stream(src, dst, len = nil, src_offset = nil)
|
36
|
+
close = []
|
37
|
+
src.kind_of?(String) and close << (src = File.open(src))
|
38
|
+
dst.kind_of?(String) and close << (dst = File.open(dst, "w"))
|
39
|
+
src, dst = src.to_io, dst.to_io
|
40
|
+
rv = len
|
41
|
+
src.sysseek(src_offset) if src_offset
|
42
|
+
select_args = selectable(src, dst)
|
44
43
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
44
|
+
if src.stat.pipe? || dst.stat.pipe?
|
45
|
+
if len
|
46
|
+
len -= full(src, dst, len, select_args) until len == 0
|
47
|
+
else
|
48
|
+
rv = 0
|
49
|
+
while n = partial(src, dst, PIPE_CAPA, select_args)
|
50
|
+
rv += n
|
51
|
+
end
|
52
|
+
end
|
53
|
+
else
|
54
|
+
r, w = tmp = IO.pipe
|
55
|
+
close.concat(tmp)
|
56
|
+
if len
|
57
|
+
while len != 0 && n = partial(src, w, len, select_args)
|
58
|
+
len -= full(r, dst, n, select_args)
|
55
59
|
end
|
56
60
|
else
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
while len != 0
|
61
|
-
nr = partial(src, w, len, select_args)
|
62
|
-
len -= full(r, dst, nr, select_args)
|
63
|
-
end
|
64
|
-
else
|
65
|
-
rv = 0
|
66
|
-
begin
|
67
|
-
nr = partial(src, w, PIPE_CAPA, select_args)
|
68
|
-
rv += full(r, dst, nr, select_args)
|
69
|
-
rescue EOFError
|
70
|
-
break
|
71
|
-
end while true
|
61
|
+
rv = 0
|
62
|
+
while n = partial(src, w, PIPE_CAPA, select_args)
|
63
|
+
rv += full(r, dst, n, select_args)
|
72
64
|
end
|
73
65
|
end
|
74
|
-
|
75
|
-
rv
|
76
|
-
ensure
|
77
|
-
close.each { |io| io.close }
|
78
66
|
end
|
79
67
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
# bytes. Returns the nubmer of bytes actually spliced (always +len+)
|
85
|
-
# The +_select_args+ parameter is reserved for internal use and
|
86
|
-
# may be removed in future versions. Do not write code that
|
87
|
-
# depends on +_select_args+.
|
88
|
-
def Splice.full(src, dst, len, _select_args = selectable(src, dst))
|
89
|
-
nr = len
|
90
|
-
nr -= partial(src, dst, nr, _select_args) until nr == 0
|
91
|
-
len
|
92
|
-
end
|
68
|
+
rv
|
69
|
+
ensure
|
70
|
+
close.each { |io| io.close }
|
71
|
+
end
|
93
72
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
73
|
+
# splice the full amount specified from +src+ to +dst+
|
74
|
+
# Either +dst+ or +src+ must be a pipe. +dst+ and +src+
|
75
|
+
# may BOTH be pipes in Linux 2.6.31 or later.
|
76
|
+
# This will block and wait for IO completion of +len+
|
77
|
+
# Raises +EOFError+ if end of file is reached.
|
78
|
+
# bytes. Returns the number of bytes actually spliced (always +len+)
|
79
|
+
# The +_select_args+ parameter is reserved for internal use and
|
80
|
+
# may be removed in future versions. Do not write code that
|
81
|
+
# depends on +_select_args+.
|
82
|
+
def self.full(src, dst, len, _select_args = selectable(src, dst))
|
83
|
+
nr = len
|
84
|
+
while nr > 0
|
85
|
+
n = partial(src, dst, nr, _select_args) or
|
86
|
+
raise EOFError, "end of file reached"
|
87
|
+
nr -= n
|
109
88
|
end
|
89
|
+
len
|
90
|
+
end
|
110
91
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
92
|
+
# splice up to +len+ bytes from +src+ to +dst+.
|
93
|
+
# Either +dst+ or +src+ must be a pipe. +dst+ and +src+
|
94
|
+
# may BOTH be pipes in Linux 2.6.31 or later.
|
95
|
+
# Returns the number of bytes actually spliced.
|
96
|
+
# Like IO#readpartial, this never returns Errno::EAGAIN
|
97
|
+
# The +_select_args+ parameter is reserved for internal use and
|
98
|
+
# may be removed in future versions. Do not write code that
|
99
|
+
# depends on +_select_args+.
|
100
|
+
def self.partial(src, dst, len, _select_args = selectable(src, dst))
|
101
|
+
begin
|
102
|
+
rv = IO.trysplice(src, nil, dst, nil, len, F_MOVE)
|
103
|
+
end while rv == :EAGAIN and IO.select(*_select_args)
|
104
|
+
rv
|
105
|
+
end
|
118
106
|
|
107
|
+
# returns an array suitable for splat-ing to IO.select for blocking I/O
|
108
|
+
def self.selectable(src, dst)
|
109
|
+
rv = []
|
110
|
+
src.stat.pipe? or rv[0] = [ src ]
|
111
|
+
dst.stat.pipe? or rv[1] = [ dst ]
|
112
|
+
rv
|
119
113
|
end
|
120
114
|
end
|
data/pkg.mk
ADDED
@@ -0,0 +1,168 @@
|
|
1
|
+
RUBY = ruby
|
2
|
+
RAKE = rake
|
3
|
+
RSYNC = rsync
|
4
|
+
WRONGDOC = wrongdoc
|
5
|
+
|
6
|
+
GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
|
7
|
+
@./GIT-VERSION-GEN
|
8
|
+
-include GIT-VERSION-FILE
|
9
|
+
-include local.mk
|
10
|
+
DLEXT := $(shell $(RUBY) -rrbconfig -e 'puts RbConfig::CONFIG["DLEXT"]')
|
11
|
+
RUBY_VERSION := $(shell $(RUBY) -e 'puts RUBY_VERSION')
|
12
|
+
RUBY_ENGINE := $(shell $(RUBY) -e 'puts((RUBY_ENGINE rescue "ruby"))')
|
13
|
+
lib := lib
|
14
|
+
|
15
|
+
ifeq ($(shell test -f script/isolate_for_tests && echo t),t)
|
16
|
+
isolate_libs := tmp/isolate/$(RUBY_ENGINE)-$(RUBY_VERSION)/isolate.mk
|
17
|
+
$(isolate_libs): script/isolate_for_tests
|
18
|
+
@$(RUBY) script/isolate_for_tests
|
19
|
+
-include $(isolate_libs)
|
20
|
+
lib := $(lib):$(ISOLATE_LIBS)
|
21
|
+
endif
|
22
|
+
|
23
|
+
ext := $(firstword $(wildcard ext/*))
|
24
|
+
ifneq ($(ext),)
|
25
|
+
ext_pfx := tmp/ext/$(RUBY_ENGINE)-$(RUBY_VERSION)
|
26
|
+
ext_h := $(wildcard $(ext)/*/*.h $(ext)/*.h)
|
27
|
+
ext_src := $(wildcard $(ext)/*.c $(ext_h))
|
28
|
+
ext_pfx_src := $(addprefix $(ext_pfx)/,$(ext_src))
|
29
|
+
ext_d := $(ext_pfx)/$(ext)/.d
|
30
|
+
$(ext)/extconf.rb: $(wildcard $(ext)/*.h)
|
31
|
+
@>> $@
|
32
|
+
$(ext_d):
|
33
|
+
@mkdir -p $(@D)
|
34
|
+
@> $@
|
35
|
+
$(ext_pfx)/$(ext)/%: $(ext)/% $(ext_d)
|
36
|
+
install -m 644 $< $@
|
37
|
+
$(ext_pfx)/$(ext)/Makefile: $(ext)/extconf.rb $(ext_d) $(ext_h)
|
38
|
+
$(RM) -f $(@D)/*.o
|
39
|
+
cd $(@D) && $(RUBY) $(CURDIR)/$(ext)/extconf.rb
|
40
|
+
ext_sfx := _ext.$(DLEXT)
|
41
|
+
ext_dl := $(ext_pfx)/$(ext)/$(notdir $(ext)_ext.$(DLEXT))
|
42
|
+
$(ext_dl): $(ext_src) $(ext_pfx_src) $(ext_pfx)/$(ext)/Makefile
|
43
|
+
@echo $^ == $@
|
44
|
+
$(MAKE) -C $(@D)
|
45
|
+
lib := $(lib):$(ext_pfx)/$(ext)
|
46
|
+
build: $(ext_dl)
|
47
|
+
endif
|
48
|
+
|
49
|
+
pkg_extra := GIT-VERSION-FILE NEWS ChangeLog LATEST
|
50
|
+
ChangeLog: GIT-VERSION-FILE .wrongdoc.yml
|
51
|
+
$(WRONGDOC) prepare
|
52
|
+
|
53
|
+
manifest:
|
54
|
+
$(RM) .manifest
|
55
|
+
$(MAKE) .manifest
|
56
|
+
|
57
|
+
.manifest: ChangeLog
|
58
|
+
(git ls-files && for i in $@ $(pkg_extra); do echo $$i; done) | \
|
59
|
+
LC_ALL=C sort > $@+
|
60
|
+
cmp $@+ $@ || mv $@+ $@
|
61
|
+
$(RM) $@+
|
62
|
+
|
63
|
+
doc:: .document .wrongdoc.yml
|
64
|
+
find lib -type f -name '*.rbc' -exec rm -f '{}' ';'
|
65
|
+
-find ext -type f -name '*.rbc' -exec rm -f '{}' ';'
|
66
|
+
$(RM) -r doc
|
67
|
+
$(WRONGDOC) all
|
68
|
+
install -m644 COPYING doc/COPYING
|
69
|
+
install -m644 $(shell grep '^[A-Z]' .document) doc/
|
70
|
+
|
71
|
+
ifneq ($(VERSION),)
|
72
|
+
pkggem := pkg/$(rfpackage)-$(VERSION).gem
|
73
|
+
pkgtgz := pkg/$(rfpackage)-$(VERSION).tgz
|
74
|
+
release_notes := release_notes-$(VERSION)
|
75
|
+
release_changes := release_changes-$(VERSION)
|
76
|
+
|
77
|
+
release-notes: $(release_notes)
|
78
|
+
release-changes: $(release_changes)
|
79
|
+
$(release_changes):
|
80
|
+
$(WRONGDOC) release_changes > $@+
|
81
|
+
$(VISUAL) $@+ && test -s $@+ && mv $@+ $@
|
82
|
+
$(release_notes):
|
83
|
+
$(WRONGDOC) release_notes > $@+
|
84
|
+
$(VISUAL) $@+ && test -s $@+ && mv $@+ $@
|
85
|
+
|
86
|
+
# ensures we're actually on the tagged $(VERSION), only used for release
|
87
|
+
verify:
|
88
|
+
test x"$(shell umask)" = x0022
|
89
|
+
git rev-parse --verify refs/tags/v$(VERSION)^{}
|
90
|
+
git diff-index --quiet HEAD^0
|
91
|
+
test $$(git rev-parse --verify HEAD^0) = \
|
92
|
+
$$(git rev-parse --verify refs/tags/v$(VERSION)^{})
|
93
|
+
|
94
|
+
fix-perms:
|
95
|
+
-git ls-tree -r HEAD | awk '/^100644 / {print $$NF}' | xargs chmod 644
|
96
|
+
-git ls-tree -r HEAD | awk '/^100755 / {print $$NF}' | xargs chmod 755
|
97
|
+
|
98
|
+
gem: $(pkggem)
|
99
|
+
|
100
|
+
install-gem: $(pkggem)
|
101
|
+
gem install $(CURDIR)/$<
|
102
|
+
|
103
|
+
$(pkggem): manifest fix-perms
|
104
|
+
gem build $(rfpackage).gemspec
|
105
|
+
mkdir -p pkg
|
106
|
+
mv $(@F) $@
|
107
|
+
|
108
|
+
$(pkgtgz): distdir = $(basename $@)
|
109
|
+
$(pkgtgz): HEAD = v$(VERSION)
|
110
|
+
$(pkgtgz): manifest fix-perms
|
111
|
+
@test -n "$(distdir)"
|
112
|
+
$(RM) -r $(distdir)
|
113
|
+
mkdir -p $(distdir)
|
114
|
+
tar cf - $$(cat .manifest) | (cd $(distdir) && tar xf -)
|
115
|
+
cd pkg && tar cf - $(basename $(@F)) | gzip -9 > $(@F)+
|
116
|
+
mv $@+ $@
|
117
|
+
|
118
|
+
package: $(pkgtgz) $(pkggem)
|
119
|
+
|
120
|
+
test-release:: verify package $(release_notes) $(release_changes)
|
121
|
+
# make tgz release on RubyForge
|
122
|
+
@echo rubyforge add_release -f \
|
123
|
+
-n $(release_notes) -a $(release_changes) \
|
124
|
+
$(rfproject) $(rfpackage) $(VERSION) $(pkgtgz)
|
125
|
+
@echo gem push $(pkggem)
|
126
|
+
@echo rubyforge add_file \
|
127
|
+
$(rfproject) $(rfpackage) $(VERSION) $(pkggem)
|
128
|
+
release:: verify package $(release_notes) $(release_changes)
|
129
|
+
# make tgz release on RubyForge
|
130
|
+
rubyforge add_release -f -n $(release_notes) -a $(release_changes) \
|
131
|
+
$(rfproject) $(rfpackage) $(VERSION) $(pkgtgz)
|
132
|
+
# push gem to RubyGems.org
|
133
|
+
gem push $(pkggem)
|
134
|
+
# in case of gem downloads from RubyForge releases page
|
135
|
+
rubyforge add_file \
|
136
|
+
$(rfproject) $(rfpackage) $(VERSION) $(pkggem)
|
137
|
+
else
|
138
|
+
gem install-gem: GIT-VERSION-FILE
|
139
|
+
$(MAKE) $@ VERSION=$(GIT_VERSION)
|
140
|
+
endif
|
141
|
+
|
142
|
+
all:: test
|
143
|
+
test_units := $(wildcard test/test_*.rb)
|
144
|
+
test: test-unit
|
145
|
+
test-unit: $(test_units)
|
146
|
+
$(test_units): build
|
147
|
+
$(RUBY) -I $(lib) $@
|
148
|
+
|
149
|
+
# this requires GNU coreutils variants
|
150
|
+
ifneq ($(RSYNC_DEST),)
|
151
|
+
publish_doc:
|
152
|
+
-git set-file-times
|
153
|
+
$(MAKE) doc
|
154
|
+
find doc/images -type f | \
|
155
|
+
TZ=UTC xargs touch -d '1970-01-01 00:00:06' doc/rdoc.css
|
156
|
+
$(MAKE) doc_gz
|
157
|
+
$(RSYNC) -av doc/ $(RSYNC_DEST)/
|
158
|
+
git ls-files | xargs touch
|
159
|
+
endif
|
160
|
+
|
161
|
+
# Create gzip variants of the same timestamp as the original so nginx
|
162
|
+
# "gzip_static on" can serve the gzipped versions directly.
|
163
|
+
doc_gz: docs = $(shell find doc -type f ! -regex '^.*\.\(gif\|jpg\|png\|gz\)$$')
|
164
|
+
doc_gz:
|
165
|
+
for i in $(docs); do \
|
166
|
+
gzip --rsyncable -9 < $$i > $$i.gz; touch -r $$i $$i.gz; done
|
167
|
+
|
168
|
+
.PHONY: all .FORCE-GIT-VERSION-FILE doc test $(test_units) manifest
|
data/test/test_io_splice.rb
CHANGED
@@ -7,48 +7,6 @@ require 'timeout'
|
|
7
7
|
$-w = true
|
8
8
|
require 'io/splice'
|
9
9
|
|
10
|
-
# unused_port provides an unused port on +addr+ usable for TCP that is
|
11
|
-
# guaranteed to be unused across all unicorn builds on that system. It
|
12
|
-
# prevents race conditions by using a lock file other unicorn builds
|
13
|
-
# will see. This is required if you perform several builds in parallel
|
14
|
-
# with a continuous integration system or run tests in parallel via
|
15
|
-
# gmake. This is NOT guaranteed to be race-free if you run other
|
16
|
-
# processes that bind to random ports for testing (but the window
|
17
|
-
# for a race condition is very small).
|
18
|
-
def unused_port(addr = '127.0.0.1')
|
19
|
-
retries = 100
|
20
|
-
base = 5000
|
21
|
-
port = sock = nil
|
22
|
-
begin
|
23
|
-
begin
|
24
|
-
port = base + rand(32768 - base)
|
25
|
-
while port == 8080
|
26
|
-
port = base + rand(32768 - base)
|
27
|
-
end
|
28
|
-
|
29
|
-
sock = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
|
30
|
-
sock.bind(Socket.pack_sockaddr_in(port, addr))
|
31
|
-
sock.listen(5)
|
32
|
-
rescue Errno::EADDRINUSE, Errno::EACCES
|
33
|
-
sock.close rescue nil
|
34
|
-
retry if (retries -= 1) >= 0
|
35
|
-
end
|
36
|
-
|
37
|
-
# since we'll end up closing the random port we just got, there's a race
|
38
|
-
# condition could allow the random port we just chose to reselect itself
|
39
|
-
# when running tests in parallel with gmake. Create a lock file while
|
40
|
-
# we have the port here to ensure that does not happen .
|
41
|
-
lock_path = "#{Dir::tmpdir}/unicorn_test.#{addr}:#{port}.lock"
|
42
|
-
lock = File.open(lock_path, File::WRONLY|File::CREAT|File::EXCL, 0600)
|
43
|
-
at_exit { File.unlink(lock_path) rescue nil }
|
44
|
-
rescue Errno::EEXIST
|
45
|
-
sock.close rescue nil
|
46
|
-
retry
|
47
|
-
end
|
48
|
-
sock.close rescue nil
|
49
|
-
port
|
50
|
-
end
|
51
|
-
|
52
10
|
class Test_IO_Splice < Test::Unit::TestCase
|
53
11
|
|
54
12
|
def test_splice
|
@@ -83,6 +41,38 @@ class Test_IO_Splice < Test::Unit::TestCase
|
|
83
41
|
assert_equal str, rd.sysread(size)
|
84
42
|
end
|
85
43
|
|
44
|
+
def test_splice_io_noflags
|
45
|
+
str = 'abcde'
|
46
|
+
size = 5
|
47
|
+
rd, wr = IO.pipe
|
48
|
+
tmp = Tempfile.new('ruby_io_splice')
|
49
|
+
|
50
|
+
assert_nothing_raised {
|
51
|
+
tmp.syswrite(str)
|
52
|
+
tmp.sysseek(0)
|
53
|
+
}
|
54
|
+
|
55
|
+
nr = IO.splice(tmp, nil, wr, nil, size)
|
56
|
+
assert_equal size, nr
|
57
|
+
assert_equal str, rd.sysread(size)
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_trysplice_io_noflags
|
61
|
+
str = 'abcde'
|
62
|
+
size = 5
|
63
|
+
rd, wr = IO.pipe
|
64
|
+
tmp = Tempfile.new('ruby_io_splice')
|
65
|
+
|
66
|
+
assert_nothing_raised {
|
67
|
+
tmp.syswrite(str)
|
68
|
+
tmp.sysseek(0)
|
69
|
+
}
|
70
|
+
|
71
|
+
nr = IO.trysplice(tmp, nil, wr, nil, size)
|
72
|
+
assert_equal size, nr
|
73
|
+
assert_equal str, rd.sysread(size)
|
74
|
+
end
|
75
|
+
|
86
76
|
def test_splice_io_ish
|
87
77
|
str = 'abcde'
|
88
78
|
size = 5
|
@@ -141,6 +131,20 @@ class Test_IO_Splice < Test::Unit::TestCase
|
|
141
131
|
}
|
142
132
|
end
|
143
133
|
|
134
|
+
def test_trysplice_nonblock
|
135
|
+
rd, wr = IO.pipe
|
136
|
+
tmp = Tempfile.new('ruby_io_splice')
|
137
|
+
assert_equal :EAGAIN,
|
138
|
+
IO.trysplice(rd, nil, tmp, 0, 5, IO::Splice::F_NONBLOCK)
|
139
|
+
end
|
140
|
+
|
141
|
+
def test_trysplice_nonblock_noargs
|
142
|
+
rd, wr = IO.pipe
|
143
|
+
tmp = Tempfile.new('ruby_io_splice')
|
144
|
+
assert_equal :EAGAIN, IO.trysplice(rd, nil, tmp, 0, 5)
|
145
|
+
assert_equal :EAGAIN, IO.trysplice(rd, nil, tmp, 0, 5, IO::Splice::F_MORE)
|
146
|
+
end
|
147
|
+
|
144
148
|
def test_splice_eof
|
145
149
|
rd, wr = IO.pipe
|
146
150
|
tmp = Tempfile.new('ruby_io_splice')
|
@@ -154,9 +158,20 @@ class Test_IO_Splice < Test::Unit::TestCase
|
|
154
158
|
}
|
155
159
|
end
|
156
160
|
|
161
|
+
def test_trysplice_eof
|
162
|
+
rd, wr = IO.pipe
|
163
|
+
tmp = Tempfile.new('ruby_io_splice')
|
164
|
+
wr.syswrite 'abc'
|
165
|
+
wr.close
|
166
|
+
|
167
|
+
nr = IO.trysplice(rd, nil, tmp, 0, 5, IO::Splice::F_NONBLOCK)
|
168
|
+
assert_equal 3, nr
|
169
|
+
assert_nil IO.trysplice(rd, nil, tmp, 0, 5, IO::Splice::F_NONBLOCK)
|
170
|
+
end
|
171
|
+
|
157
172
|
def test_splice_nonblock_socket
|
158
|
-
|
159
|
-
|
173
|
+
server = TCPServer.new('127.0.0.1', 0)
|
174
|
+
port = server.addr[1]
|
160
175
|
rp, wp = IO.pipe
|
161
176
|
rs = TCPSocket.new('127.0.0.1', port)
|
162
177
|
rs.nonblock = true
|
@@ -178,6 +193,19 @@ class Test_IO_Splice < Test::Unit::TestCase
|
|
178
193
|
assert_equal str, rda.sysread(5)
|
179
194
|
end
|
180
195
|
|
196
|
+
def test_trytee
|
197
|
+
str = 'abcde'
|
198
|
+
size = 5
|
199
|
+
rda, wra = IO.pipe
|
200
|
+
rdb, wrb = IO.pipe
|
201
|
+
|
202
|
+
assert_nothing_raised { wra.syswrite(str) }
|
203
|
+
nr = IO.trytee(rda, wrb, size, 0)
|
204
|
+
assert_equal 5, nr
|
205
|
+
assert_equal str, rdb.sysread(5)
|
206
|
+
assert_equal str, rda.sysread(5)
|
207
|
+
end
|
208
|
+
|
181
209
|
def test_tee_eof
|
182
210
|
rda, wra = IO.pipe
|
183
211
|
rdb, wrb = IO.pipe
|
@@ -185,6 +213,13 @@ class Test_IO_Splice < Test::Unit::TestCase
|
|
185
213
|
assert_raises(EOFError) { IO.tee(rda.fileno, wrb.fileno, 4096, 0) }
|
186
214
|
end
|
187
215
|
|
216
|
+
def test_trytee_eof
|
217
|
+
rda, wra = IO.pipe
|
218
|
+
rdb, wrb = IO.pipe
|
219
|
+
wra.close
|
220
|
+
assert_nil IO.trytee(rda, wrb, 4096)
|
221
|
+
end
|
222
|
+
|
188
223
|
def test_tee_nonblock
|
189
224
|
rda, wra = IO.pipe
|
190
225
|
rdb, wrb = IO.pipe
|
@@ -193,6 +228,12 @@ class Test_IO_Splice < Test::Unit::TestCase
|
|
193
228
|
}
|
194
229
|
end
|
195
230
|
|
231
|
+
def test_trytee_nonblock
|
232
|
+
rda, wra = IO.pipe
|
233
|
+
rdb, wrb = IO.pipe
|
234
|
+
assert_equal :EAGAIN, IO.trytee(rda, wrb, 4096)
|
235
|
+
end
|
236
|
+
|
196
237
|
def test_tee_io
|
197
238
|
str = 'abcde'
|
198
239
|
size = 5
|
@@ -214,6 +255,14 @@ class Test_IO_Splice < Test::Unit::TestCase
|
|
214
255
|
assert_equal data.join(''), r.readpartial(16384)
|
215
256
|
end
|
216
257
|
|
258
|
+
def test_vmsplice_noflags
|
259
|
+
data = %w(hello world how are you today)
|
260
|
+
r, w = IO.pipe
|
261
|
+
n = IO.vmsplice(w, data)
|
262
|
+
assert_equal data.join('').size, n
|
263
|
+
assert_equal data.join(''), r.readpartial(16384)
|
264
|
+
end
|
265
|
+
|
217
266
|
def test_vmsplice_string
|
218
267
|
r, w = IO.pipe
|
219
268
|
assert_equal 5, IO.vmsplice(w, 'hello', 0)
|
@@ -344,8 +393,8 @@ class Test_IO_Splice < Test::Unit::TestCase
|
|
344
393
|
end
|
345
394
|
|
346
395
|
def test_copy_stream_nonblock_src
|
347
|
-
|
348
|
-
|
396
|
+
server = TCPServer.new('127.0.0.1', 0)
|
397
|
+
port = server.addr[1]
|
349
398
|
rp, wp = IO.pipe
|
350
399
|
rs = TCPSocket.new('127.0.0.1', port)
|
351
400
|
rs.nonblock = true
|
@@ -359,8 +408,8 @@ class Test_IO_Splice < Test::Unit::TestCase
|
|
359
408
|
end
|
360
409
|
|
361
410
|
def test_copy_stream_nonblock_dst
|
362
|
-
|
363
|
-
|
411
|
+
server = TCPServer.new('127.0.0.1', 0)
|
412
|
+
port = server.addr[1]
|
364
413
|
rp, wp = IO.pipe
|
365
414
|
rs = TCPSocket.new('127.0.0.1', port)
|
366
415
|
rs.nonblock = true
|
@@ -395,10 +444,10 @@ class Test_IO_Splice < Test::Unit::TestCase
|
|
395
444
|
|
396
445
|
def test_pipe_size
|
397
446
|
r, w = IO.pipe
|
398
|
-
|
447
|
+
assert_kind_of Integer, r.pipe_size
|
399
448
|
assert(r.pipe_size >= 512)
|
400
449
|
assert_nothing_raised { w.pipe_size = 8192 }
|
401
|
-
|
450
|
+
assert_equal 8192, r.pipe_size
|
402
451
|
|
403
452
|
w.write('*' * 4097)
|
404
453
|
assert_raises(Errno::EBUSY) { r.pipe_size = 4096 }
|