From 64a86f9bca119db3a64e02294f9da16ed6b50a07 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. --- 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, 33 insertions(+), 25 deletions(-) diff --git a/stdlib/Distributed/src/cluster.jl b/stdlib/Distributed/src/cluster.jl index 4bfc3a0bf88c0..37f1660e19478 100644 --- a/stdlib/Distributed/src/cluster.jl +++ b/stdlib/Distributed/src/cluster.jl @@ -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) diff --git a/stdlib/Distributed/test/distributed_exec.jl b/stdlib/Distributed/test/distributed_exec.jl index 5a3c4bcdf9855..481d39c38d350 100644 --- a/stdlib/Distributed/test/distributed_exec.jl +++ b/stdlib/Distributed/test/distributed_exec.jl @@ -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 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 0fb3e5fa7acf9..2a78d18bfa739 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 082dc157d8556..61d2dba95a0b0 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 696be1324a8e3..5ca6422717425 100644 --- a/stdlib/REPL/test/TerminalMenus/radio_menu.jl +++ b/stdlib/REPL/test/TerminalMenus/radio_menu.jl @@ -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 diff --git a/stdlib/REPL/test/TerminalMenus/runtests.jl b/stdlib/REPL/test/TerminalMenus/runtests.jl index 62a91cc0a1256..c594958a36670 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")