Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test with JRuby #22

Merged
merged 18 commits into from
Feb 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
25 changes: 25 additions & 0 deletions .github/workflows/jruby.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: jruby

on: [push, pull_request]

jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
ruby: [ 'jruby-head', 'jruby-9.2' ]
steps:
- name: git config
run: |
git config --global core.autocrlf false
git config --global core.eol lf
git config --global advice.detachedHead 0
- uses: actions/checkout@master
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
- name: Install dependencies
run: bundle install
- name: Run test
run: rake
9 changes: 6 additions & 3 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,13 @@ Rake::TestTask.new(:test) do |t|
t.test_files = FileList["test/**/test_*.rb"]
end

require 'rake/extensiontask'
Rake::ExtensionTask.new(name)
if RUBY_ENGINE == "ruby"
require 'rake/extensiontask'
Rake::ExtensionTask.new(name)
task :test => :compile
end

task :default => [:compile, :test]
task :default => :test

task "build" => "date_epoch"
task "build" => "build:java"
Expand Down
16 changes: 8 additions & 8 deletions io-console.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ Gem::Specification.new do |s|
if Gem::Platform === s.platform and s.platform =~ 'java'
s.files.delete_if {|f| f.start_with?("ext/")}
s.extensions.clear
s.require_paths.unshift("jruby")
s.files.concat(%w[
jruby/io/console.rb
jruby/io/console/bsd_console.rb
jruby/io/console/common.rb
jruby/io/console/linux_console.rb
jruby/io/console/native_console.rb
jruby/io/console/stty_console.rb
jruby/io/console/stub_console.rb
lib/io/console.rb
lib/io/console/ffi/bsd_console.rb
lib/io/console/ffi/common.rb
lib/io/console/ffi/console.rb
lib/io/console/ffi/linux_console.rb
lib/io/console/ffi/native_console.rb
lib/io/console/ffi/stty_console.rb
lib/io/console/ffi/stub_console.rb
])
end

Expand Down
5 changes: 5 additions & 0 deletions lib/io/console.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
if RUBY_ENGINE == 'ruby'
require_relative 'console.so'
else
require_relative 'console/ffi/console'
end
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ class Termios < FFI::Struct
:c_oflag, :tcflag_t,
:c_cflag, :tcflag_t,
:c_lflag, :tcflag_t,
:cc_c, [ :uchar, NCCS ],
:c_cc, [ :uchar, NCCS ],
:c_ispeed, :speed_t,
:c_ospeed, :speed_t
end
Expand Down
4 changes: 2 additions & 2 deletions jruby/io/console/common.rb → lib/io/console/ffi/common.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Methods common to all backend impls
class IO
def getch(*)
raw do
def getch(*, **opts)
raw(**opts) do
getc
end
end
Expand Down
10 changes: 5 additions & 5 deletions jruby/io/console.rb → lib/io/console/ffi/console.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,19 @@

require 'rbconfig'

require_relative 'console/common'
require_relative 'common'

# If Windows, always use the stub version
if RbConfig::CONFIG['host_os'] =~ /(mswin)|(win32)|(ming)/
require_relative 'console/stub_console'
require_relative 'stub_console'
else

# If Linux or BSD, try to load the native version
if RbConfig::CONFIG['host_os'].downcase =~ /darwin|openbsd|freebsd|netbsd|linux/
begin

# Attempt to load the native Linux and BSD console logic
require_relative 'console/native_console'
require_relative 'native_console'
ready = true

rescue Exception => ex
Expand All @@ -48,7 +48,7 @@
if !ready
begin

require_relative 'console/stty_console'
require_relative 'stty_console'
ready = true

rescue Exception
Expand All @@ -61,7 +61,7 @@

# If still not ready, just use stubbed version
if !ready
require_relative 'console/stub_console'
require_relative 'stub_console'
end

end
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ class Termios < FFI::Struct
:c_cflag, :tcflag_t,
:c_lflag, :tcflag_t,
:c_line, :uchar,
:cc_c, [ :uchar, NCCS ],
:c_cc, [ :uchar, NCCS ],
:c_ispeed, :speed_t,
:c_ospeed, :speed_t
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,38 +13,47 @@ class IO
def ttymode
termios = LibC::Termios.new
if LibC.tcgetattr(self.fileno, termios) != 0
raise SystemCallError.new("tcgetattr", FFI.errno)
raise SystemCallError.new(path, FFI.errno)
end

if block_given?
yield tmp = termios.dup
if LibC.tcsetattr(self.fileno, LibC::TCSADRAIN, tmp) != 0
raise SystemCallError.new("tcsetattr", FFI.errno)
if LibC.tcsetattr(self.fileno, LibC::TCSANOW, tmp) != 0
raise SystemCallError.new(path, FFI.errno)
end
end
termios
end
private :ttymode

def ttymode_yield(block, &setup)
def ttymode_yield(block, **opts, &setup)
begin
orig_termios = ttymode { |t| setup.call(t) }
orig_termios = ttymode { |t| setup.call(t, **opts) }
block.call(self)
ensure
if orig_termios && LibC.tcsetattr(self.fileno, LibC::TCSADRAIN, orig_termios) != 0
raise SystemCallError.new("tcsetattr", FFI.errno)
if orig_termios && LibC.tcsetattr(self.fileno, LibC::TCSANOW, orig_termios) != 0
raise SystemCallError.new(path, FFI.errno)
end
end
end
private :ttymode_yield

TTY_RAW = Proc.new do |t|
TTY_RAW = Proc.new do |t, min: 1, time: nil, intr: nil|
LibC.cfmakeraw(t)
t[:c_lflag] &= ~(LibC::ECHOE|LibC::ECHOK)
if min >= 0
t[:c_cc][LibC::VMIN] = min
end
t[:c_cc][LibC::VTIME] = (time&.to_i || 0) * 10
if intr
t[:c_iflag] |= LibC::BRKINT
t[:c_lflag] |= LibC::ISIG
t[:c_oflag] |= LibC::OPOST
end
end

def raw(*, &block)
ttymode_yield(block, &TTY_RAW)
def raw(*, **kwargs, &block)
ttymode_yield(block, **kwargs, &TTY_RAW)
end

def raw!(*)
Expand Down Expand Up @@ -93,13 +102,25 @@ def winsize
end

def winsize=(size)
size = size.to_ary unless size.kind_of?(Array)
sizelen = size.size

if sizelen != 2 && sizelen != 4
raise ArgumentError.new("wrong number of arguments (given #{sizelen}, expected 2 or 4)")
end

row, col, xpixel, ypixel = size

ws = LibC::Winsize.new
if LibC.ioctl(self.fileno, LibC::TIOCGWINSZ, :pointer, ws.pointer) != 0
raise SystemCallError.new("ioctl(TIOCGWINSZ)", FFI.errno)
end

ws[:ws_row] = size[0]
ws[:ws_col] = size[1]
ws[:ws_row] = row
ws[:ws_col] = col
ws[:ws_xpixel] = xpixel&.to_i || 0
ws[:ws_ypixel] = ypixel&.to_i || 0

if LibC.ioctl(self.fileno, LibC::TIOCSWINSZ, :pointer, ws.pointer) != 0
raise SystemCallError.new("ioctl(TIOCSWINSZ)", FFI.errno)
end
Expand All @@ -117,6 +138,80 @@ def ioflush
raise SystemCallError.new("tcflush(TCIOFLUSH)", FFI.errno) unless LibC.tcflush(self.fileno, LibC::TCIOFLUSH) == 0
end

def cursor
raw do
syswrite "\e[6n"

return nil if getbyte != 0x1b
return nil if getbyte != ?[.ord

num = 0
result = []

while b = getbyte
c = b.to_i
if c == ?;.ord
result.push num
num = 0
elsif c >= ?0.ord && c <= ?9.ord
num = num * 10 + c - ?0.ord
#elsif opt && c == opt
else
last = c
result.push num
b = last.chr
return nil unless b == ?R
break
end
end

result.map(&:pred)
end
end

def cursor=(pos)
pos = pos.to_ary if !pos.kind_of?(Array)

raise "expected 2D coordinates" unless pos.size == 2

x, y = pos
syswrite(format("\x1b[%d;%dH", x + 1, y + 1))

self
end

def cursor_down(n)
raw do
syswrite "\x1b[#{n}B"
end

self
end

def cursor_right(n)
raw do
syswrite "\x1b[#{n}C"
end

self
end

def cursor_left(n)
raw do
syswrite "\x1b[#{n}D"
end

self
end

def cursor_up(n)
raw do
syswrite "\x1b[#{n}A"
end

self
end

# TODO: Windows version uses "conin$" and "conout$" instead of /dev/tty
def self.console(sym = nil, *args)
raise TypeError, "expected Symbol, got #{sym.class}" unless sym.nil? || sym.kind_of?(Symbol)
Expand All @@ -141,8 +236,13 @@ def self.console(sym = nil, *args)
end
end

if !con && $stdin.tty?
con = File.open('/dev/tty', 'r+')
if !con
begin
con = File.open('/dev/tty', 'r+')
rescue
return nil
end

con.sync = true
@console = con
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,20 @@ def winsize
end

def winsize=(size)
stty("rows #{size[0]} cols #{size[1]}")
size = size.to_ary unless size.kind_of?(Array)
sizelen = size.size

if sizelen != 2 && sizelen != 4
raise ArgumentError.new("wrong number of arguments (given #{sizelen}, expected 2 or 4)")
end

row, col, xpixel, ypixel = size

if sizelen == 4
warn "stty io/console does not support pixel winsize"
end

stty("rows #{row} cols #{col}")
end

def iflush
Expand Down
File renamed without changes.
12 changes: 7 additions & 5 deletions test/io/console/test_io_console.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
end

class TestIO_Console < Test::Unit::TestCase
PATHS = $LOADED_FEATURES.grep(%r"/io/console(?:\.#{RbConfig::CONFIG['DLEXT']}|/\w+\.rb)\z") {$`}
PATHS = $LOADED_FEATURES.grep(%r"/io/console(?:\.#{RbConfig::CONFIG['DLEXT']}|\.rb|/\w+\.rb)\z") {$`}
PATHS.uniq!

# FreeBSD seems to hang on TTOU when running parallel tests
Expand Down Expand Up @@ -35,7 +35,7 @@ def test_failed_path
Errno.const_get(e) if Errno.const_defined?(e)
}
exceptions.compact!
skip if exceptions.empty?
omit if exceptions.empty?
File.open(IO::NULL) do |f|
e = assert_raise(*exceptions) do
f.echo?
Expand Down Expand Up @@ -226,7 +226,7 @@ def test_setecho2
end

def test_getpass
skip unless IO.method_defined?("getpass")
omit unless IO.method_defined?("getpass")
run_pty("p IO.console.getpass('> ')") do |r, w|
assert_equal("> ", r.readpartial(10))
sleep 0.1
Expand Down Expand Up @@ -410,7 +410,7 @@ def test_sync
def helper
m, s = PTY.open
rescue RuntimeError
skip $!
omit $!
else
yield m, s
ensure
Expand All @@ -419,9 +419,11 @@ def helper
end

def run_pty(src, n = 1)
pend("PTY.spawn cannot control terminal on JRuby") if RUBY_ENGINE == 'jruby'

r, w, pid = PTY.spawn(EnvUtil.rubybin, "-I#{TestIO_Console::PATHS.join(File::PATH_SEPARATOR)}", "-rio/console", "-e", src)
rescue RuntimeError
skip $!
omit $!
else
if block_given?
yield r, w, pid
Expand Down