Skip to content

Commit

Permalink
[Distributed] Set stdin to devnull before closing it
Browse files Browse the repository at this point in the history
Distributed closes and destroys stdin, but some tests attempted to
explicitly use it, leading to test problems. We previously interpreted
this as passing devnull, but this is better to be explicit.
  • Loading branch information
vtjnash authored and DilumAluthge committed Apr 12, 2022
1 parent c0c60e8 commit 64a86f9
Show file tree
Hide file tree
Showing 9 changed files with 33 additions and 25 deletions.
5 changes: 4 additions & 1 deletion stdlib/Distributed/src/cluster.jl
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,10 @@ start_worker(cookie::AbstractString=readline(stdin); kwargs...) = start_worker(s
function start_worker(out::IO, cookie::AbstractString=readline(stdin); close_stdin::Bool=true, stderr_to_stdout::Bool=true)
init_multi()

close_stdin && close(stdin) # workers will not use it
if close_stdin # workers will not use it
redirect_stdin(devnull)
close(stdin)
end
stderr_to_stdout && redirect_stderr(stdout)

init_worker(cookie)
Expand Down
6 changes: 5 additions & 1 deletion stdlib/Distributed/test/distributed_exec.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1616,7 +1616,11 @@ cluster_cookie("")
for close_stdin in (true, false), stderr_to_stdout in (true, false)
local npids = addprocs_with_testenv(RetainStdioTester(close_stdin,stderr_to_stdout))
@test remotecall_fetch(myid, npids[1]) == npids[1]
@test close_stdin != remotecall_fetch(()->isopen(stdin), npids[1])
if close_stdin
@test remotecall_fetch(()->stdin === devnull && !isreadable(stdin), npids[1])
else
@test remotecall_fetch(()->stdin !== devnull && isopen(stdin) && isreadable(stdin), npids[1])
end
@test stderr_to_stdout == remotecall_fetch(()->(stderr === stdout), npids[1])
rmprocs(npids)
end
Expand Down
10 changes: 5 additions & 5 deletions stdlib/REPL/src/TerminalMenus/util.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,24 @@ readbyte(stream::IO=stdin) = read(stream, Char)
# Read the next key from stdin. It is also able to read several bytes for
# escaped keys such as the arrow keys, home/end keys, etc.
# Escaped keys are returned using the `Key` enum.
readkey(stream::Base.LibuvStream=stdin) = UInt32(_readkey(stream))
function _readkey(stream::Base.LibuvStream=stdin)
readkey(stream::IO=stdin) = UInt32(_readkey(stream))
function _readkey(stream::IO=stdin)
c = readbyte(stream)

# Escape characters
if c == '\x1b'
stream.buffer.size < 2 && return '\x1b'
bytesavailable(stream) < 1 && return '\x1b'
esc_a = readbyte(stream)
esc_a == 'v' && return PAGE_UP # M-v
esc_a == '<' && return HOME_KEY # M-<
esc_a == '>' && return END_KEY # M->

stream.buffer.size < 3 && return '\x1b'
bytesavailable(stream) < 1 && return '\x1b'
esc_b = readbyte(stream)

if esc_a == '[' || esc_a == 'O'
if esc_b >= '0' && esc_b <= '9'
stream.buffer.size < 4 && return '\x1b'
bytesavailable(stream) < 1 && return '\x1b'
esc_c = readbyte(stream)
if esc_c == '~'
esc_b == '1' && return HOME_KEY
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,6 @@ TerminalMenus.writeLine(buf, multi_menu, 1, true)

# Test SDTIN
multi_menu = MultiSelectMenu(string.(1:10), warn=false)
@test simulate_input(Set([1,2]), multi_menu, :enter, :down, :enter, 'd')
@test simulate_input(multi_menu, :enter, :down, :enter, 'd') == Set([1,2])
multi_menu = MultiSelectMenu(["single option"], warn=false)
@test simulate_input(Set([1]), multi_menu, :up, :up, :down, :enter, 'd')
@test simulate_input(multi_menu, :up, :up, :down, :enter, 'd') == Set([1])
6 changes: 3 additions & 3 deletions stdlib/REPL/test/TerminalMenus/legacytests/old_radio_menu.jl
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ TerminalMenus.writeLine(buf, radio_menu, 1, true)

# Test using stdin
radio_menu = RadioMenu(string.(1:10), warn=false)
@test simulate_input(3, radio_menu, :down, :down, :enter)
@test simulate_input(radio_menu, :down, :down, :enter) == 3
radio_menu = RadioMenu(["single option"], warn=false)
@test simulate_input(1, radio_menu, :up, :up, :down, :up, :enter)
@test simulate_input(radio_menu, :up, :up, :down, :up, :enter) == 1
radio_menu = RadioMenu(string.(1:3), pagesize=1, warn=false)
@test simulate_input(3, radio_menu, :down, :down, :down, :down, :enter)
@test simulate_input(radio_menu, :down, :down, :down, :down, :enter) == 3
4 changes: 2 additions & 2 deletions stdlib/REPL/test/TerminalMenus/multiselect_menu.jl
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,6 @@ end

# Test SDTIN
multi_menu = MultiSelectMenu(string.(1:10), charset=:ascii)
@test simulate_input(Set([1,2]), multi_menu, :enter, :down, :enter, 'd')
@test simulate_input(multi_menu, :enter, :down, :enter, 'd') == Set([1,2])
multi_menu = MultiSelectMenu(["single option"], charset=:ascii)
@test simulate_input(Set([1]), multi_menu, :up, :up, :down, :enter, 'd')
@test simulate_input(multi_menu, :up, :up, :down, :enter, 'd') == Set([1])
4 changes: 2 additions & 2 deletions stdlib/REPL/test/TerminalMenus/multiselect_with_skip_menu.jl
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,10 @@ menu = MultiSelectWithSkipMenu(string.(1:5), selected=[2, 3])
buf = IOBuffer()
TerminalMenus.printmenu(buf, menu, 1; init=true)
@test occursin("2 items selected", String(take!(buf)))
@test simulate_input(Set([2, 3, 4]), menu, 'n', :enter, 'd')
@test simulate_input(menu, 'n', :enter, 'd') == Set([2, 3, 4])
buf = IOBuffer()
TerminalMenus.printmenu(buf, menu, 1; init=true)
@test occursin("3 items selected", String(take!(buf)))

menu = MultiSelectWithSkipMenu(string.(1:5), selected=[2, 3])
@test simulate_input(Set([2]), menu, 'P', :enter, 'd', cursor=5)
@test simulate_input(menu, 'P', :enter, 'd', cursor=5) == Set([2])
8 changes: 4 additions & 4 deletions stdlib/REPL/test/TerminalMenus/radio_menu.jl
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ end

# Test using stdin
radio_menu = RadioMenu(string.(1:10); charset=:ascii)
@test simulate_input(3, radio_menu, :down, :down, :enter)
@test simulate_input(radio_menu, :down, :down, :enter) == 3
radio_menu = RadioMenu(["single option"], charset=:ascii)
@test simulate_input(1, radio_menu, :up, :up, :down, :up, :enter)
@test simulate_input(radio_menu, :up, :up, :down, :up, :enter) == 1
radio_menu = RadioMenu(string.(1:3), pagesize=1, charset=:ascii)
@test simulate_input(3, radio_menu, :down, :down, :down, :down, :enter)
@test simulate_input(radio_menu, :down, :down, :down, :down, :enter) == 3
radio_menu = RadioMenu(["apple", "banana", "cherry"]; keybindings=collect('a':'c'), charset=:ascii)
@test simulate_input(2, radio_menu, 'b')
@test simulate_input(radio_menu, 'b') == 2
11 changes: 6 additions & 5 deletions stdlib/REPL/test/TerminalMenus/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,22 @@ import REPL
using REPL.TerminalMenus
using Test

function simulate_input(expected, menu::TerminalMenus.AbstractMenu, keys...;
kwargs...)
function simulate_input(menu::TerminalMenus.AbstractMenu, keys...; kwargs...)
keydict = Dict(:up => "\e[A",
:down => "\e[B",
:enter => "\r")

new_stdin = Base.BufferStream()
for key in keys
if isa(key, Symbol)
write(stdin.buffer, keydict[key])
write(new_stdin, keydict[key])
else
write(stdin.buffer, "$key")
write(new_stdin, "$key")
end
end
TerminalMenus.terminal.in_stream = new_stdin

request(menu; suppress_output=true, kwargs...) == expected
return request(menu; suppress_output=true, kwargs...)
end

include("radio_menu.jl")
Expand Down

0 comments on commit 64a86f9

Please sign in to comment.