From 9561ec5474be68655b32bd952a601d857d4a3eea Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 26 Jan 2022 14:51:58 -0500 Subject: [PATCH] [Distributed] Set stdin to devnull before closing it 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. (cherry picked from commit 64a86f9bca119db3a64e02294f9da16ed6b50a07) --- stdlib/Distributed/src/cluster.jl | 5 ++++- stdlib/Distributed/test/distributed_exec.jl | 6 +++++- stdlib/REPL/src/TerminalMenus/util.jl | 10 +++++----- .../TerminalMenus/legacytests/old_multiselect_menu.jl | 4 ++-- .../test/TerminalMenus/legacytests/old_radio_menu.jl | 6 +++--- stdlib/REPL/test/TerminalMenus/multiselect_menu.jl | 4 ++-- .../test/TerminalMenus/multiselect_with_skip_menu.jl | 4 ++-- stdlib/REPL/test/TerminalMenus/radio_menu.jl | 8 +++++--- stdlib/REPL/test/TerminalMenus/runtests.jl | 11 ++++++----- 9 files changed, 34 insertions(+), 24 deletions(-) diff --git a/stdlib/Distributed/src/cluster.jl b/stdlib/Distributed/src/cluster.jl index fff26710ac973..80e5d6283cdbc 100644 --- a/stdlib/Distributed/src/cluster.jl +++ b/stdlib/Distributed/src/cluster.jl @@ -230,7 +230,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) diff --git a/stdlib/Distributed/test/distributed_exec.jl b/stdlib/Distributed/test/distributed_exec.jl index 1192afca26975..4f0db3ad7d0b2 100644 --- a/stdlib/Distributed/test/distributed_exec.jl +++ b/stdlib/Distributed/test/distributed_exec.jl @@ -1619,7 +1619,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 diff --git a/stdlib/REPL/src/TerminalMenus/util.jl b/stdlib/REPL/src/TerminalMenus/util.jl index 8ad9ec0e4100d..91e336070d2cf 100644 --- a/stdlib/REPL/src/TerminalMenus/util.jl +++ b/stdlib/REPL/src/TerminalMenus/util.jl @@ -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 diff --git a/stdlib/REPL/test/TerminalMenus/legacytests/old_multiselect_menu.jl b/stdlib/REPL/test/TerminalMenus/legacytests/old_multiselect_menu.jl index 49dbcc42c3095..9902a992ea081 100644 --- a/stdlib/REPL/test/TerminalMenus/legacytests/old_multiselect_menu.jl +++ b/stdlib/REPL/test/TerminalMenus/legacytests/old_multiselect_menu.jl @@ -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]) diff --git a/stdlib/REPL/test/TerminalMenus/legacytests/old_radio_menu.jl b/stdlib/REPL/test/TerminalMenus/legacytests/old_radio_menu.jl index 9438808a847d6..248d5cd6a3183 100644 --- a/stdlib/REPL/test/TerminalMenus/legacytests/old_radio_menu.jl +++ b/stdlib/REPL/test/TerminalMenus/legacytests/old_radio_menu.jl @@ -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 diff --git a/stdlib/REPL/test/TerminalMenus/multiselect_menu.jl b/stdlib/REPL/test/TerminalMenus/multiselect_menu.jl index d625554c813b0..d6568fb6b04c1 100644 --- a/stdlib/REPL/test/TerminalMenus/multiselect_menu.jl +++ b/stdlib/REPL/test/TerminalMenus/multiselect_menu.jl @@ -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]) diff --git a/stdlib/REPL/test/TerminalMenus/multiselect_with_skip_menu.jl b/stdlib/REPL/test/TerminalMenus/multiselect_with_skip_menu.jl index 84f259ad7642c..609b168c2ddba 100644 --- a/stdlib/REPL/test/TerminalMenus/multiselect_with_skip_menu.jl +++ b/stdlib/REPL/test/TerminalMenus/multiselect_with_skip_menu.jl @@ -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]) diff --git a/stdlib/REPL/test/TerminalMenus/radio_menu.jl b/stdlib/REPL/test/TerminalMenus/radio_menu.jl index 28a19fa7d9ac0..5ca6422717425 100644 --- a/stdlib/REPL/test/TerminalMenus/radio_menu.jl +++ b/stdlib/REPL/test/TerminalMenus/radio_menu.jl @@ -45,8 +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(radio_menu, 'b') == 2 diff --git a/stdlib/REPL/test/TerminalMenus/runtests.jl b/stdlib/REPL/test/TerminalMenus/runtests.jl index fab105244d0a1..e5e5f0ac431ce 100644 --- a/stdlib/REPL/test/TerminalMenus/runtests.jl +++ b/stdlib/REPL/test/TerminalMenus/runtests.jl @@ -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")