sleepy_penguin 3.4.1 → 3.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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)
|