summaryrefslogtreecommitdiff
path: root/test/ruby
diff options
context:
space:
mode:
authorSamuel Williams <samuel.williams@oriontransfer.co.nz>2021-07-02 22:41:16 +1200
committerSamuel Williams <samuel.williams@oriontransfer.co.nz>2021-11-10 19:21:05 +1300
commit4b8903421828cb9d4de139180563ae8d8f04e1ab (patch)
tree21a0d02ba22afad6a4ce1c042acf6d74767dc5a2 /test/ruby
parent56b90cf94465ce347a3d9a779363c78ce3deb180 (diff)
IO::Buffer for scheduler interface.
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/4621
Diffstat (limited to 'test/ruby')
-rw-r--r--test/ruby/test_io_buffer.rb131
1 files changed, 131 insertions, 0 deletions
diff --git a/test/ruby/test_io_buffer.rb b/test/ruby/test_io_buffer.rb
new file mode 100644
index 0000000000..ec10d2e1e6
--- /dev/null
+++ b/test/ruby/test_io_buffer.rb
@@ -0,0 +1,131 @@
+# frozen_string_literal: false
+
+class TestIOBuffer < Test::Unit::TestCase
+ def assert_negative(value)
+ assert(value < 0, "Expected #{value} to be negative!")
+ end
+
+ def assert_positive(value)
+ assert(value > 0, "Expected #{value} to be positive!")
+ end
+
+ def test_flags
+ assert_equal 0, IO::Buffer::EXTERNAL
+ assert_equal 1, IO::Buffer::INTERNAL
+ assert_equal 2, IO::Buffer::MAPPED
+
+ assert_equal 16, IO::Buffer::LOCKED
+ assert_equal 32, IO::Buffer::PRIVATE
+
+ assert_equal 64, IO::Buffer::IMMUTABLE
+ end
+
+ def test_endian
+ assert_equal 4, IO::Buffer::LITTLE_ENDIAN
+ assert_equal 8, IO::Buffer::BIG_ENDIAN
+ assert_equal 8, IO::Buffer::NETWORK_ENDIAN
+
+ assert_include [IO::Buffer::LITTLE_ENDIAN, IO::Buffer::BIG_ENDIAN], IO::Buffer::HOST_ENDIAN
+ end
+
+ def test_new_internal
+ buffer = IO::Buffer.new(1024, IO::Buffer::INTERNAL)
+ assert_equal 1024, buffer.size
+ refute buffer.external?
+ assert buffer.internal?
+ refute buffer.mapped?
+ end
+
+ def test_new_mapped
+ buffer = IO::Buffer.new(1024, IO::Buffer::MAPPED)
+ assert_equal 1024, buffer.size
+ refute buffer.external?
+ refute buffer.internal?
+ assert buffer.mapped?
+ end
+
+ def test_file_mapped
+ buffer = File.open(__FILE__) {|file| IO::Buffer.map(file)}
+ assert_include buffer.to_str, "Hello World"
+ end
+
+ def test_resize
+ buffer = IO::Buffer.new(1024, IO::Buffer::MAPPED)
+ buffer.resize(2048, 0)
+ assert_equal 2048, buffer.size
+ end
+
+ def test_resize_preserve
+ message = "Hello World"
+ buffer = IO::Buffer.new(1024, IO::Buffer::MAPPED)
+ buffer.copy(message, 0)
+ buffer.resize(2048, 1024)
+ assert_equal message, buffer.to_str(0, message.bytesize)
+ end
+
+ def test_compare_same_size
+ buffer1 = IO::Buffer.new(1)
+ assert_equal buffer1, buffer1
+
+ buffer2 = IO::Buffer.new(1)
+ buffer1.set(:U8, 0, 0x10)
+ buffer2.set(:U8, 0, 0x20)
+
+ assert_negative buffer1 <=> buffer2
+ assert_positive buffer2 <=> buffer1
+ end
+
+ def test_compare_different_size
+ buffer1 = IO::Buffer.new(3)
+ buffer2 = IO::Buffer.new(5)
+
+ assert_negative buffer1 <=> buffer2
+ assert_positive buffer2 <=> buffer1
+ end
+
+ def test_slice
+ buffer = IO::Buffer.new(128)
+ slice = buffer.slice(8, 32)
+ slice.copy("Hello World", 0)
+ assert_equal("Hello World", buffer.to_str(8, 11))
+ end
+
+ def test_slice_bounds
+ buffer = IO::Buffer.new(128)
+
+ # What is best exception class?
+ assert_raise RuntimeError do
+ buffer.slice(128, 10)
+ end
+
+ # assert_raise RuntimeError do
+ # pp buffer.slice(-10, 10)
+ # end
+ end
+
+ def test_invalidation
+ input, output = IO.pipe
+
+ # (1) rb_write_internal creates IO::Buffer object,
+ buffer = IO::Buffer.new(128)
+
+ # (2) it is passed to (malicious) scheduler
+ # (3) scheduler starts a thread which call system call with the buffer object
+ thread = Thread.new{buffer.locked{input.read}}
+
+ Thread.pass until thread.stop?
+
+ # (4) scheduler returns
+ # (5) rb_write_internal invalidate the buffer object
+ assert_raise RuntimeError do
+ buffer.free
+ end
+
+ # (6) the system call access the memory area after invalidation
+ output.write("Hello World")
+ output.close
+ thread.join
+
+ input.close
+ end
+end