Skip to content

Commit

Permalink
Add tests for ReadConsole
Browse files Browse the repository at this point in the history
  • Loading branch information
straight-shoota committed Aug 20, 2023
1 parent fec6e1c commit 24cf0f1
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 12 deletions.
57 changes: 50 additions & 7 deletions spec/std/io/file_descriptor_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -83,26 +83,69 @@ describe IO::FileDescriptor do
describe "Windows console handle", focus: true do
it do
IO.pipe do |read, write|
fd = Win32ConsoleDileDescriptor.new(read)
write << "zażółć gęślą jaźń\n".to_utf16
fd = Win32ConsoleFileDescriptor.new(read.fd)
write.write "zażółć gęślą jaźń\n".to_utf16.unsafe_slice_of(UInt8)
fd.gets.should eq "zażółć gęślą jaźń"
end
end
it "empty" do
IO.pipe do |read, write|
fd = Win32ConsoleFileDescriptor.new(read.fd)
write.close
fd.gets.should eq nil
end
end

it "read 1 byte" do
IO.pipe do |read, write|
fd = Win32ConsoleFileDescriptor.new(read.fd)
write.write "ż".to_utf16.unsafe_slice_of(UInt8)
fd.gets(1).should eq "\xC5"
end
end

it "read 2 bytes" do
IO.pipe do |read, write|
fd = Win32ConsoleFileDescriptor.new(read.fd)
write.write "ż".to_utf16.unsafe_slice_of(UInt8)
fd.gets(2).should eq "ż"
end
end

it "read 3 bytes" do
IO.pipe do |read, write|
fd = Win32ConsoleFileDescriptor.new(read.fd)
write.write "\u{10000}".to_utf16.unsafe_slice_of(UInt8)
fd.gets(3).should eq "\xF0\x90\x80"
end
end

it "read 4 bytes" do
IO.pipe do |read, write|
fd = Win32ConsoleFileDescriptor.new(read.fd)
write.write "\u{10000}".to_utf16.unsafe_slice_of(UInt8)
fd.gets(4).should eq "\u{10000}"
end
end
end
{% end %}
end

{% if flag?(:win32) %}
class Win32ConsoleDileDescriptor < IO::FileDescriptor
private def console_mode?
class Win32ConsoleFileDescriptor < IO::FileDescriptor
private def console_mode?(handle)
true
end

private def read_console(hConsoleInput, lpBuffer, nNumberOfCharsToRead, lpNumberOfCharsRead, pInputControl)
lpNumberOfCharsRead.value = blocking_read(Slice.new(lpBuffer, nNumberOfCharsToRead))
0
rescue
bytesBuffer = lpBuffer[0, nNumberOfCharsToRead].unsafe_slice_of(UInt8)
bytes_read = blocking_read(bytesBuffer)
p! nNumberOfCharsToRead, bytes_read
lpNumberOfCharsRead.value = bytes_read.to_u32 // 2
p! bytesBuffer[0, bytes_read]
1
rescue
0
end
end
{% end %}
11 changes: 6 additions & 5 deletions src/crystal/system/win32/file_descriptor.cr
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ module Crystal::System::FileDescriptor
@console_units = Slice(UInt16).empty
@console_units_buffer : Slice(UInt16)?

private def console_mode?
private def console_mode?(handle)
LibC.GetConsoleMode(handle, out _) != 0
end

Expand All @@ -35,10 +35,10 @@ module Crystal::System::FileDescriptor

private def unbuffered_read(slice : Bytes)
handle = windows_handle
if console_mode?
if console_mode?(handle)
read_console(handle, slice)
elsif system_blocking?
blocking_read
blocking_read(slice)
else
overlapped_operation(handle, "ReadFile", read_timeout) do |overlapped|
ret = LibC.ReadFile(handle, slice, slice.size, out byte_count, overlapped)
Expand All @@ -50,7 +50,7 @@ module Crystal::System::FileDescriptor
private def unbuffered_write(slice : Bytes)
handle = windows_handle
until slice.empty?
if console_mode?
if console_mode?(handle)
bytes_written = write_console(handle, slice)
elsif system_blocking?
bytes_written = LibC._write(fd, slice, slice.size)
Expand Down Expand Up @@ -326,7 +326,8 @@ module Crystal::System::FileDescriptor
units_to_read = slice.size if slice.size < units_to_read

# Reads code units from console.
if 0 == read_console(handle, units_buffer + @console_units.size, units_to_read, out units_read, nil)
units_read = uninitialized LibC::DWORD
if 0 == read_console(handle, units_buffer + @console_units.size, units_to_read, pointerof(units_read), nil)
raise IO::Error.from_winerror("ReadConsoleW")
end
return bytes_read if units_read == 0
Expand Down

0 comments on commit 24cf0f1

Please sign in to comment.