sleepy_penguin 3.4.1 → 3.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/.document +1 -0
- data/.olddoc.yml +3 -4
- data/GIT-VERSION-GEN +1 -1
- data/LICENSE +3 -3
- data/README +7 -4
- data/TODO +1 -0
- data/ext/sleepy_penguin/cfr.c +62 -0
- data/ext/sleepy_penguin/epoll.c +34 -24
- data/ext/sleepy_penguin/eventfd.c +6 -5
- data/ext/sleepy_penguin/extconf.rb +6 -0
- data/ext/sleepy_penguin/init.c +83 -12
- data/ext/sleepy_penguin/inotify.c +48 -36
- data/ext/sleepy_penguin/kqueue.c +22 -21
- data/ext/sleepy_penguin/sendfile.c +120 -0
- data/ext/sleepy_penguin/sleepy_penguin.h +15 -28
- data/ext/sleepy_penguin/sp_copy.h +33 -0
- data/ext/sleepy_penguin/splice.c +174 -0
- data/ext/sleepy_penguin/timerfd.c +1 -5
- data/ext/sleepy_penguin/util.c +12 -0
- data/lib/sleepy_penguin.rb +28 -0
- data/lib/sleepy_penguin/cfr.rb +29 -0
- data/lib/sleepy_penguin/epoll.rb +13 -10
- data/lib/sleepy_penguin/kqueue.rb +6 -6
- data/lib/sleepy_penguin/sp.rb +1 -1
- data/lib/sleepy_penguin/splice.rb +125 -0
- data/pkg.mk +5 -12
- data/sleepy_penguin.gemspec +13 -15
- data/test/helper.rb +2 -7
- data/test/test_cfr.rb +35 -0
- data/test/test_constants.rb +2 -4
- data/test/test_epoll.rb +35 -6
- data/test/test_epoll_gc.rb +2 -5
- data/test/test_epoll_io.rb +3 -6
- data/test/test_epoll_optimizations.rb +2 -2
- data/test/test_eventfd.rb +2 -5
- data/test/test_inotify.rb +2 -4
- data/test/test_kqueue.rb +35 -7
- data/test/test_kqueue_io.rb +2 -5
- data/test/test_pipesize.rb +22 -0
- data/test/test_sendfile.rb +26 -0
- data/test/test_splice.rb +250 -0
- data/test/test_splice_eintr.rb +31 -0
- data/test/test_timerfd.rb +2 -5
- metadata +27 -34
- data/lib/sleepy_penguin/epoll/io.rb +0 -28
- data/lib/sleepy_penguin/kqueue/io.rb +0 -30
data/pkg.mk
CHANGED
@@ -13,14 +13,6 @@ RUBY_VERSION := $(shell $(RUBY) -e 'puts RUBY_VERSION')
|
|
13
13
|
RUBY_ENGINE := $(shell $(RUBY) -e 'puts((RUBY_ENGINE rescue "ruby"))')
|
14
14
|
lib := lib
|
15
15
|
|
16
|
-
ifeq ($(shell test -f script/isolate_for_tests && echo t),t)
|
17
|
-
isolate_libs := tmp/isolate/$(RUBY_ENGINE)-$(RUBY_VERSION)/isolate.mk
|
18
|
-
$(isolate_libs): script/isolate_for_tests
|
19
|
-
@$(RUBY) script/isolate_for_tests
|
20
|
-
-include $(isolate_libs)
|
21
|
-
lib := $(lib):$(ISOLATE_LIBS)
|
22
|
-
endif
|
23
|
-
|
24
16
|
ext := $(firstword $(wildcard ext/*))
|
25
17
|
ifneq ($(ext),)
|
26
18
|
ext_pfx := tmp/ext/$(RUBY_ENGINE)-$(RUBY_VERSION)
|
@@ -94,7 +86,7 @@ fix-perms:
|
|
94
86
|
gem: $(pkggem)
|
95
87
|
|
96
88
|
install-gem: $(pkggem)
|
97
|
-
gem install $(CURDIR)/$<
|
89
|
+
gem install --local $(CURDIR)/$<
|
98
90
|
|
99
91
|
$(pkggem): manifest fix-perms
|
100
92
|
gem build $(rfpackage).gemspec
|
@@ -121,9 +113,10 @@ gem install-gem: GIT-VERSION-FILE
|
|
121
113
|
$(MAKE) $@ VERSION=$(GIT_VERSION)
|
122
114
|
endif
|
123
115
|
|
124
|
-
all::
|
116
|
+
all:: check
|
125
117
|
test_units := $(wildcard test/test_*.rb)
|
126
|
-
test:
|
118
|
+
test: check
|
119
|
+
check: test-unit
|
127
120
|
test-unit: $(test_units)
|
128
121
|
$(test_units): build
|
129
122
|
$(RUBY) -I $(lib) $@ $(RUBY_TEST_OPTS)
|
@@ -153,5 +146,5 @@ $(PLACEHOLDERS):
|
|
153
146
|
echo olddoc_placeholder > $@
|
154
147
|
endif
|
155
148
|
|
156
|
-
.PHONY: all .FORCE-GIT-VERSION-FILE doc test $(test_units) manifest
|
149
|
+
.PHONY: all .FORCE-GIT-VERSION-FILE doc check test $(test_units) manifest
|
157
150
|
.PHONY: check-warnings
|
data/sleepy_penguin.gemspec
CHANGED
@@ -1,24 +1,22 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require 'olddoc'
|
4
|
-
extend Olddoc::Gemspec
|
5
|
-
name, summary, title = readme_metadata
|
1
|
+
manifest = File.exist?('.manifest') ?
|
2
|
+
IO.readlines('.manifest').map!(&:chomp!) : `git ls-files`.split("\n")
|
6
3
|
|
7
4
|
Gem::Specification.new do |s|
|
8
5
|
s.name = %q{sleepy_penguin}
|
9
|
-
s.version = ENV[
|
10
|
-
s.homepage =
|
11
|
-
s.authors = [
|
12
|
-
s.description =
|
6
|
+
s.version = (ENV['VERSION'] || '3.5.0').dup
|
7
|
+
s.homepage = 'https://bogomips.org/sleepy_penguin/'
|
8
|
+
s.authors = ['sleepy_penguin hackers']
|
9
|
+
s.description = File.read('README').split("\n\n")[1]
|
13
10
|
s.email = %q{sleepy-penguin@bogomips.org}
|
14
|
-
s.extra_rdoc_files = extra_rdoc_files(manifest)
|
15
11
|
s.files = manifest
|
16
|
-
s.summary =
|
12
|
+
s.summary = 'Linux I/O events for Ruby'
|
17
13
|
s.test_files = Dir['test/test_*.rb']
|
18
14
|
s.extensions = %w(ext/sleepy_penguin/extconf.rb)
|
19
|
-
s.
|
20
|
-
|
15
|
+
s.extra_rdoc_files = IO.readlines('.document').map!(&:chomp!).keep_if do |f|
|
16
|
+
File.exist?(f)
|
17
|
+
end
|
18
|
+
s.add_development_dependency('test-unit', '~> 3.0')
|
21
19
|
s.add_development_dependency('strace_me', '~> 1.0')
|
22
|
-
|
23
|
-
s.licenses = %w(
|
20
|
+
s.required_ruby_version = '>= 2.0'
|
21
|
+
s.licenses = %w(LGPL-2.1+)
|
24
22
|
end
|
data/test/helper.rb
CHANGED
@@ -1,11 +1,6 @@
|
|
1
1
|
$-w = $stdout.sync = $stderr.sync = Thread.abort_on_exception = true
|
2
|
-
|
3
|
-
require '
|
4
|
-
Testcase = begin
|
5
|
-
Minitest::Test # minitest 5
|
6
|
-
rescue NameError
|
7
|
-
Minitest::Unit::TestCase # minitest 4
|
8
|
-
end
|
2
|
+
require 'test/unit'
|
3
|
+
require 'sleepy_penguin'
|
9
4
|
|
10
5
|
def check_cloexec(io)
|
11
6
|
pipe = IO.pipe
|
data/test/test_cfr.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# -*- encoding: binary -*-
|
2
|
+
require_relative 'helper'
|
3
|
+
require 'tempfile'
|
4
|
+
|
5
|
+
class TestCfr < Test::Unit::TestCase
|
6
|
+
def test_copy_file_range
|
7
|
+
str = 'abcde'
|
8
|
+
size = 5
|
9
|
+
src = Tempfile.new('ruby_cfr_src')
|
10
|
+
dst = Tempfile.new('ruby_cfr_dst')
|
11
|
+
assert_equal 5, src.syswrite(str)
|
12
|
+
src.sysseek(0)
|
13
|
+
begin
|
14
|
+
nr = SleepyPenguin.copy_file_range(src, dst, size)
|
15
|
+
rescue Errno::EINVAL
|
16
|
+
warn 'copy_file_range not supported (requires Linux 4.5+)'
|
17
|
+
warn "We have: #{`uname -a`}"
|
18
|
+
return
|
19
|
+
end
|
20
|
+
assert_equal nr, 5
|
21
|
+
dst.sysseek(0)
|
22
|
+
assert_equal str, dst.sysread(5)
|
23
|
+
|
24
|
+
nr = SleepyPenguin.copy_file_range(src, dst, size, off_in: 1, off_out: 0)
|
25
|
+
assert_equal 4, nr
|
26
|
+
dst.sysseek(0)
|
27
|
+
assert_equal 'bcde', dst.sysread(4)
|
28
|
+
|
29
|
+
nr = SleepyPenguin.copy_file_range(src, dst, size, off_in: 9)
|
30
|
+
assert_equal 0, nr, 'no EOFError'
|
31
|
+
ensure
|
32
|
+
dst.close!
|
33
|
+
src.close!
|
34
|
+
end
|
35
|
+
end if SleepyPenguin.respond_to?(:copy_file_range)
|
data/test/test_constants.rb
CHANGED
@@ -1,9 +1,7 @@
|
|
1
|
-
require './test/helper'
|
2
|
-
$-w = true
|
3
|
-
Thread.abort_on_exception = true
|
4
1
|
require 'sleepy_penguin/sp'
|
2
|
+
require_relative 'helper'
|
5
3
|
|
6
|
-
class TestConstants <
|
4
|
+
class TestConstants < Test::Unit::TestCase
|
7
5
|
def test_constants
|
8
6
|
assert_equal SleepyPenguin::SLEEPY_PENGUIN_VERSION,
|
9
7
|
SP::SLEEPY_PENGUIN_VERSION
|
data/test/test_epoll.rb
CHANGED
@@ -1,13 +1,9 @@
|
|
1
|
-
|
1
|
+
require_relative 'helper'
|
2
2
|
require 'fcntl'
|
3
3
|
require 'socket'
|
4
4
|
require 'thread'
|
5
|
-
$-w = true
|
6
|
-
Thread.abort_on_exception = true
|
7
5
|
|
8
|
-
|
9
|
-
|
10
|
-
class TestEpoll < Testcase
|
6
|
+
class TestEpoll < Test::Unit::TestCase
|
11
7
|
include SleepyPenguin
|
12
8
|
|
13
9
|
def setup
|
@@ -343,6 +339,13 @@ class TestEpoll < Testcase
|
|
343
339
|
@ep.close
|
344
340
|
io = Epoll.new(Epoll::CLOEXEC).to_io
|
345
341
|
assert((io.fcntl(Fcntl::F_GETFD) & Fcntl::FD_CLOEXEC) == Fcntl::FD_CLOEXEC)
|
342
|
+
io.close
|
343
|
+
|
344
|
+
# prettier, slower, but more memory efficient due to lack of caching
|
345
|
+
# due to the constant cache:
|
346
|
+
io = Epoll.new(:CLOEXEC).to_io
|
347
|
+
|
348
|
+
assert((io.fcntl(Fcntl::F_GETFD) & Fcntl::FD_CLOEXEC) == Fcntl::FD_CLOEXEC)
|
346
349
|
end
|
347
350
|
|
348
351
|
def test_new
|
@@ -531,4 +534,30 @@ class TestEpoll < Testcase
|
|
531
534
|
end
|
532
535
|
@ep.wait(1) { |flags, io| assert_equal(first[0], io) }
|
533
536
|
end
|
537
|
+
|
538
|
+
def test_epoll_nest
|
539
|
+
ep2 = Epoll.new
|
540
|
+
r, w = IO.pipe
|
541
|
+
@ep.add(@rd, :IN)
|
542
|
+
@ep.add(@wr, :OUT)
|
543
|
+
ep2.add(r, :IN)
|
544
|
+
ep2.add(w, :OUT)
|
545
|
+
w.write('.')
|
546
|
+
@wr.write('.')
|
547
|
+
outer = []
|
548
|
+
inner = []
|
549
|
+
nr = 0
|
550
|
+
@ep.wait(2) do |_, io|
|
551
|
+
outer << io
|
552
|
+
ep2.wait(2) do |_, io2|
|
553
|
+
(inner[nr] ||= []) << io2
|
554
|
+
end
|
555
|
+
nr += 1
|
556
|
+
end
|
557
|
+
assert_equal [ @rd, @wr ].sort_by(&:fileno), outer.sort_by(&:fileno)
|
558
|
+
exp = [ r, w ].sort_by(&:fileno)
|
559
|
+
assert_equal [ exp, exp ], inner.map { |x| x.sort_by(&:fileno) }
|
560
|
+
ensure
|
561
|
+
[ r, w, ep2 ].compact.each(&:close)
|
562
|
+
end
|
534
563
|
end if defined?(SleepyPenguin::Epoll)
|
data/test/test_epoll_gc.rb
CHANGED
data/test/test_epoll_io.rb
CHANGED
@@ -1,12 +1,9 @@
|
|
1
|
-
|
1
|
+
require_relative 'helper'
|
2
2
|
require 'fcntl'
|
3
3
|
require 'socket'
|
4
4
|
require 'thread'
|
5
|
-
$-w = true
|
6
|
-
Thread.abort_on_exception = true
|
7
|
-
require 'sleepy_penguin'
|
8
5
|
|
9
|
-
class TestEpollIO <
|
6
|
+
class TestEpollIO < Test::Unit::TestCase
|
10
7
|
include SleepyPenguin
|
11
8
|
|
12
9
|
def setup
|
@@ -23,7 +20,7 @@ class TestEpollIO < Testcase
|
|
23
20
|
|
24
21
|
class EpSub < Epoll::IO
|
25
22
|
def self.new
|
26
|
-
super(
|
23
|
+
super(:CLOEXEC)
|
27
24
|
end
|
28
25
|
end
|
29
26
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
require_relative 'helper'
|
2
2
|
begin
|
3
3
|
require 'strace'
|
4
4
|
rescue LoadError
|
@@ -7,7 +7,7 @@ $-w = true
|
|
7
7
|
|
8
8
|
require 'sleepy_penguin'
|
9
9
|
|
10
|
-
class TestEpollOptimizations <
|
10
|
+
class TestEpollOptimizations < Test::Unit::TestCase
|
11
11
|
include SleepyPenguin
|
12
12
|
IO_PURGATORY = []
|
13
13
|
|
data/test/test_eventfd.rb
CHANGED
data/test/test_inotify.rb
CHANGED
@@ -1,11 +1,9 @@
|
|
1
|
-
|
1
|
+
require_relative 'helper'
|
2
2
|
require 'fcntl'
|
3
3
|
require 'tempfile'
|
4
4
|
require 'set'
|
5
|
-
$-w = true
|
6
|
-
require 'sleepy_penguin'
|
7
5
|
|
8
|
-
class TestInotify <
|
6
|
+
class TestInotify < Test::Unit::TestCase
|
9
7
|
include SleepyPenguin
|
10
8
|
attr_reader :ino
|
11
9
|
|
data/test/test_kqueue.rb
CHANGED
@@ -1,9 +1,6 @@
|
|
1
|
-
|
2
|
-
$-w = true
|
3
|
-
Thread.abort_on_exception = true
|
4
|
-
require 'sleepy_penguin'
|
1
|
+
require_relative 'helper'
|
5
2
|
|
6
|
-
class TestKqueue <
|
3
|
+
class TestKqueue < Test::Unit::TestCase
|
7
4
|
include SleepyPenguin
|
8
5
|
|
9
6
|
def test_kqueue
|
@@ -71,5 +68,36 @@ class TestKqueue < Testcase
|
|
71
68
|
ensure
|
72
69
|
kq.close
|
73
70
|
end
|
74
|
-
|
75
|
-
|
71
|
+
|
72
|
+
def test_epoll_nest
|
73
|
+
kq1 = Kqueue.new
|
74
|
+
kq2 = Kqueue.new
|
75
|
+
r1, w1 = IO.pipe
|
76
|
+
r2, w2 = IO.pipe
|
77
|
+
w1.write '.'
|
78
|
+
w2.write '.'
|
79
|
+
kq1.kevent([
|
80
|
+
Kevent[r1.fileno, EvFilt::READ, Ev::ADD, 0, 0, r1],
|
81
|
+
Kevent[w1.fileno, EvFilt::WRITE, Ev::ADD, 0, 0, w1]
|
82
|
+
])
|
83
|
+
kq2.kevent([
|
84
|
+
Kevent[r2.fileno, EvFilt::READ, Ev::ADD, 0, 0, r2],
|
85
|
+
Kevent[w2.fileno, EvFilt::WRITE, Ev::ADD, 0, 0, w2]
|
86
|
+
])
|
87
|
+
outer = []
|
88
|
+
inner = []
|
89
|
+
nr = 0
|
90
|
+
kq1.kevent(nil, 2) do |kev1|
|
91
|
+
outer << kev1.udata
|
92
|
+
kq2.kevent(nil, 2) do |kev2|
|
93
|
+
(inner[nr] ||= []) << kev2.udata
|
94
|
+
end
|
95
|
+
nr += 1
|
96
|
+
end
|
97
|
+
assert_equal [ r1, w1 ].sort_by(&:fileno), outer.sort_by(&:fileno)
|
98
|
+
exp = [ r2, w2 ].sort_by(&:fileno)
|
99
|
+
assert_equal [ exp, exp ], inner.map { |x| x.sort_by(&:fileno) }
|
100
|
+
ensure
|
101
|
+
[ r1, w1, r2, w2, kq1, kq2 ].compact.each(&:close)
|
102
|
+
end
|
103
|
+
end if defined?(SleepyPenguin::Kqueue)
|
data/test/test_kqueue_io.rb
CHANGED
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: binary -*-
|
2
|
+
require_relative 'helper'
|
3
|
+
require 'fcntl'
|
4
|
+
|
5
|
+
class TestPipesize < Test::Unit::TestCase
|
6
|
+
def test_pipe_size
|
7
|
+
return unless RUBY_PLATFORM =~ /linux/
|
8
|
+
[ :F_GETPIPE_SZ, :F_SETPIPE_SZ ].each do |c|
|
9
|
+
return unless SleepyPenguin.const_defined?(c)
|
10
|
+
end
|
11
|
+
r, w = pipe = IO.pipe
|
12
|
+
nr = r.fcntl(SleepyPenguin::F_GETPIPE_SZ)
|
13
|
+
assert_kind_of Integer, nr
|
14
|
+
assert_operator nr, :>, 0
|
15
|
+
|
16
|
+
set = 131072
|
17
|
+
r.fcntl(SleepyPenguin::F_SETPIPE_SZ, set)
|
18
|
+
assert_equal set, r.fcntl(SleepyPenguin::F_GETPIPE_SZ)
|
19
|
+
ensure
|
20
|
+
pipe.each(&:close) if pipe
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding: binary -*-
|
2
|
+
require_relative 'helper'
|
3
|
+
require 'tempfile'
|
4
|
+
require 'socket'
|
5
|
+
|
6
|
+
class TestSendfile < Test::Unit::TestCase
|
7
|
+
def test_linux_sendfile
|
8
|
+
rd, wr = UNIXSocket.pair
|
9
|
+
size = 5
|
10
|
+
src = Tempfile.new('ruby_sf_src')
|
11
|
+
assert_equal 0, SleepyPenguin.linux_sendfile(wr, src, size)
|
12
|
+
str = 'abcde'.freeze
|
13
|
+
assert_equal str.bytesize, src.syswrite(str)
|
14
|
+
assert_equal 0, SleepyPenguin.linux_sendfile(wr, src, size)
|
15
|
+
src.sysseek(0, IO::SEEK_SET)
|
16
|
+
assert_equal str.bytesize,
|
17
|
+
SleepyPenguin.linux_sendfile(wr, src, size, offset: 0)
|
18
|
+
assert_equal str, rd.read(size)
|
19
|
+
assert_equal 0, src.sysseek(0, IO::SEEK_CUR), 'handle offset not changed'
|
20
|
+
assert_equal 3, SleepyPenguin.linux_sendfile(wr, src, 3)
|
21
|
+
assert_equal 3, src.sysseek(0, IO::SEEK_CUR), 'handle offset changed'
|
22
|
+
ensure
|
23
|
+
[ rd, wr ].compact.each(&:close)
|
24
|
+
src.close! if src
|
25
|
+
end
|
26
|
+
end
|
data/test/test_splice.rb
ADDED
@@ -0,0 +1,250 @@
|
|
1
|
+
# -*- encoding: binary -*-
|
2
|
+
require_relative 'helper'
|
3
|
+
require 'tempfile'
|
4
|
+
require 'socket'
|
5
|
+
require 'io/nonblock'
|
6
|
+
require 'timeout'
|
7
|
+
|
8
|
+
class TestSplice < Test::Unit::TestCase
|
9
|
+
|
10
|
+
def test_splice
|
11
|
+
str = 'abcde'
|
12
|
+
size = 5
|
13
|
+
rd, wr = IO.pipe
|
14
|
+
tmp = Tempfile.new('ruby_splice')
|
15
|
+
|
16
|
+
assert_equal 5, tmp.syswrite(str)
|
17
|
+
tmp.sysseek(0)
|
18
|
+
|
19
|
+
nr = SleepyPenguin.splice(tmp.fileno, wr.fileno, size)
|
20
|
+
assert_equal size, nr
|
21
|
+
assert_equal str, rd.sysread(size)
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_splice_io
|
25
|
+
str = 'abcde'
|
26
|
+
size = 5
|
27
|
+
rd, wr = IO.pipe
|
28
|
+
tmp = Tempfile.new('ruby_splice')
|
29
|
+
|
30
|
+
assert_equal 5, tmp.syswrite(str)
|
31
|
+
tmp.sysseek(0)
|
32
|
+
|
33
|
+
nr = SleepyPenguin.splice(tmp, wr, size)
|
34
|
+
assert_equal size, nr
|
35
|
+
assert_equal str, rd.sysread(size)
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_splice_io_noflags
|
39
|
+
str = 'abcde'
|
40
|
+
size = 5
|
41
|
+
rd, wr = IO.pipe
|
42
|
+
tmp = Tempfile.new('ruby_splice')
|
43
|
+
|
44
|
+
assert_equal 5, tmp.syswrite(str)
|
45
|
+
tmp.sysseek(0)
|
46
|
+
|
47
|
+
nr = SleepyPenguin.splice(tmp, wr, size)
|
48
|
+
assert_equal size, nr
|
49
|
+
assert_equal str, rd.sysread(size)
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_trysplice_io_noflags
|
53
|
+
str = 'abcde'
|
54
|
+
size = 5
|
55
|
+
rd, wr = IO.pipe
|
56
|
+
tmp = Tempfile.new('ruby_splice')
|
57
|
+
|
58
|
+
assert_equal 5, tmp.syswrite(str)
|
59
|
+
tmp.sysseek(0)
|
60
|
+
|
61
|
+
nr = SleepyPenguin.splice(tmp, wr, size, :nonblock, exception: false)
|
62
|
+
assert_equal size, nr
|
63
|
+
assert_equal str, rd.sysread(size)
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_splice_io_ish
|
67
|
+
str = 'abcde'
|
68
|
+
size = 5
|
69
|
+
rd, wr = IO.pipe
|
70
|
+
tmp = Tempfile.new('ruby_splice')
|
71
|
+
io_ish = [ tmp ]
|
72
|
+
def io_ish.to_io
|
73
|
+
first.to_io
|
74
|
+
end
|
75
|
+
|
76
|
+
assert_equal 5, tmp.syswrite(str)
|
77
|
+
tmp.sysseek(0)
|
78
|
+
|
79
|
+
nr = SleepyPenguin.splice(io_ish, wr, size)
|
80
|
+
assert_equal size, nr
|
81
|
+
assert_equal str, rd.sysread(size)
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_splice_in_offset
|
85
|
+
str = 'abcde'
|
86
|
+
off = 3
|
87
|
+
len = 2
|
88
|
+
rd, wr = IO.pipe
|
89
|
+
tmp = Tempfile.new('ruby_splice')
|
90
|
+
|
91
|
+
assert_equal 5, tmp.syswrite(str)
|
92
|
+
tmp.sysseek(0)
|
93
|
+
|
94
|
+
nr = SleepyPenguin.splice(tmp.fileno, wr.fileno, len, off_in: off)
|
95
|
+
assert_equal len, nr
|
96
|
+
assert_equal 'de', rd.sysread(len)
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_splice_out_offset
|
100
|
+
str = 'abcde'
|
101
|
+
rd, wr = IO.pipe
|
102
|
+
tmp = Tempfile.new('ruby_splice')
|
103
|
+
|
104
|
+
assert_equal 5, wr.syswrite(str)
|
105
|
+
nr = SleepyPenguin.splice(rd.fileno, tmp.fileno, str.size, off_out: 3)
|
106
|
+
assert_equal 5, nr
|
107
|
+
tmp.sysseek(0)
|
108
|
+
assert_equal "\0\0\0abcde", tmp.sysread(9)
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_splice_nonblock
|
112
|
+
rd, wr = IO.pipe
|
113
|
+
tmp = Tempfile.new('ruby_splice')
|
114
|
+
|
115
|
+
assert_raises(Errno::EAGAIN) {
|
116
|
+
SleepyPenguin.splice(rd.fileno, tmp.fileno, 5, :nonblock, off_out: 0)
|
117
|
+
}
|
118
|
+
end
|
119
|
+
|
120
|
+
def test_trysplice_nonblock
|
121
|
+
rd, wr = IO.pipe
|
122
|
+
tmp = Tempfile.new('ruby_splice')
|
123
|
+
assert_equal :EAGAIN, SleepyPenguin.splice(rd, tmp, 5, :nonblock,
|
124
|
+
off_out: 0, exception: false)
|
125
|
+
end
|
126
|
+
|
127
|
+
def test_trysplice_nonblock_noargs
|
128
|
+
rd, wr = IO.pipe
|
129
|
+
tmp = Tempfile.new('ruby_splice')
|
130
|
+
assert_equal :EAGAIN, SleepyPenguin.splice(rd, tmp, 5, :nonblock,
|
131
|
+
off_out: 0, exception: false)
|
132
|
+
assert_equal :EAGAIN, SleepyPenguin.splice(rd, tmp, 5, [:more,:nonblock],
|
133
|
+
off_out: 0,
|
134
|
+
exception: false)
|
135
|
+
end
|
136
|
+
|
137
|
+
def test_splice_eof
|
138
|
+
rd, wr = IO.pipe
|
139
|
+
tmp = Tempfile.new('ruby_splice')
|
140
|
+
wr.syswrite 'abc'
|
141
|
+
wr.close
|
142
|
+
|
143
|
+
nr = SleepyPenguin.splice(rd.fileno, tmp.fileno, 5, :nonblock, off_out: 0)
|
144
|
+
assert_equal 3, nr
|
145
|
+
assert_raises(EOFError) {
|
146
|
+
SleepyPenguin.splice(rd.fileno, tmp.fileno, 5, :nonblock, off_out: 0)
|
147
|
+
}
|
148
|
+
end
|
149
|
+
|
150
|
+
def test_trysplice_eof
|
151
|
+
rd, wr = IO.pipe
|
152
|
+
tmp = Tempfile.new('ruby_splice')
|
153
|
+
wr.syswrite 'abc'
|
154
|
+
wr.close
|
155
|
+
|
156
|
+
nr = SleepyPenguin.splice(rd, tmp, 5, off_out: 0, exception: false)
|
157
|
+
assert_equal 3, nr
|
158
|
+
assert_nil SleepyPenguin.splice(rd, tmp, 5, :nonblock,
|
159
|
+
off_out: 0, exception: false)
|
160
|
+
end
|
161
|
+
|
162
|
+
def test_splice_nonblock_socket
|
163
|
+
server = TCPServer.new('127.0.0.1', 0)
|
164
|
+
port = server.addr[1]
|
165
|
+
rp, wp = IO.pipe
|
166
|
+
rs = TCPSocket.new('127.0.0.1', port)
|
167
|
+
rs.nonblock = true
|
168
|
+
assert_raises(Errno::EAGAIN) {
|
169
|
+
SleepyPenguin.splice(rs, wp, 1024)
|
170
|
+
}
|
171
|
+
rs.close
|
172
|
+
server.close
|
173
|
+
end
|
174
|
+
|
175
|
+
def test_tee
|
176
|
+
str = 'abcde'
|
177
|
+
size = 5
|
178
|
+
rda, wra = IO.pipe
|
179
|
+
rdb, wrb = IO.pipe
|
180
|
+
|
181
|
+
assert_equal 5, wra.syswrite(str)
|
182
|
+
nr = SleepyPenguin.tee(rda.fileno, wrb.fileno, size)
|
183
|
+
assert_equal 5, nr
|
184
|
+
assert_equal str, rdb.sysread(5)
|
185
|
+
assert_equal str, rda.sysread(5)
|
186
|
+
end
|
187
|
+
|
188
|
+
def test_trytee
|
189
|
+
str = 'abcde'
|
190
|
+
size = 5
|
191
|
+
rda, wra = IO.pipe
|
192
|
+
rdb, wrb = IO.pipe
|
193
|
+
|
194
|
+
assert_equal 5, wra.syswrite(str)
|
195
|
+
nr = SleepyPenguin.tee(rda, wrb, size, :nonblock, exception: false)
|
196
|
+
assert_equal 5, nr
|
197
|
+
assert_equal str, rdb.sysread(5)
|
198
|
+
assert_equal str, rda.sysread(5)
|
199
|
+
end
|
200
|
+
|
201
|
+
def test_tee_eof
|
202
|
+
rda, wra = IO.pipe
|
203
|
+
rdb, wrb = IO.pipe
|
204
|
+
wra.close
|
205
|
+
assert_raises(EOFError) {
|
206
|
+
SleepyPenguin.tee(rda.fileno, wrb.fileno, 4096)
|
207
|
+
}
|
208
|
+
end
|
209
|
+
|
210
|
+
def test_trytee_eof
|
211
|
+
rda, wra = IO.pipe
|
212
|
+
rdb, wrb = IO.pipe
|
213
|
+
wra.close
|
214
|
+
assert_nil SleepyPenguin.tee(rda, wrb, 4096, :nonblock, exception: false)
|
215
|
+
end
|
216
|
+
|
217
|
+
def test_tee_nonblock
|
218
|
+
rda, wra = IO.pipe
|
219
|
+
rdb, wrb = IO.pipe
|
220
|
+
assert_raises(Errno::EAGAIN) {
|
221
|
+
SleepyPenguin.tee(rda.fileno, wrb.fileno, 4096, SleepyPenguin::F_NONBLOCK)
|
222
|
+
}
|
223
|
+
end
|
224
|
+
|
225
|
+
def test_trytee_nonblock
|
226
|
+
rda, wra = IO.pipe
|
227
|
+
rdb, wrb = IO.pipe
|
228
|
+
assert_equal :EAGAIN, SleepyPenguin.tee(rda, wrb, 4096, :nonblock,
|
229
|
+
exception: false)
|
230
|
+
end
|
231
|
+
|
232
|
+
def test_tee_io
|
233
|
+
str = 'abcde'
|
234
|
+
size = 5
|
235
|
+
rda, wra = IO.pipe
|
236
|
+
rdb, wrb = IO.pipe
|
237
|
+
|
238
|
+
assert_equal 5, wra.syswrite(str)
|
239
|
+
nr = SleepyPenguin.tee(rda, wrb, size)
|
240
|
+
assert_equal 5, nr
|
241
|
+
assert_equal str, rdb.sysread(5)
|
242
|
+
assert_equal str, rda.sysread(5)
|
243
|
+
end
|
244
|
+
|
245
|
+
def test_constants
|
246
|
+
%w(move nonblock more).each { |x|
|
247
|
+
assert Integer === SleepyPenguin.const_get("F_#{x.upcase}")
|
248
|
+
}
|
249
|
+
end
|
250
|
+
end if SleepyPenguin.respond_to?(:splice)
|