mirror of
https://github.com/livebook-dev/livebook.git
synced 2025-11-09 13:44:53 +08:00
* Add password input * Save empty string for password in .livemd file * Update lib/livebook_web/live/session_live/cell_component.ex * Changed radio button it to select * Changed radio button it to select * Moved select it to the top * Keep the elements in the select ordered * Update lib/livebook_web/helpers.ex Co-authored-by: Jonatan Kłosko <jonatanklosko@gmail.com> * Update lib/livebook_web/live/session_live/input_cell_settings_component.ex Co-authored-by: Jonatan Kłosko <jonatanklosko@gmail.com> * Update lib/livebook_web/live/session_live/input_cell_settings_component.ex Co-authored-by: Jonatan Kłosko <jonatanklosko@gmail.com> * Add textarea input * Add textarea input * Added operation in the io_proxy to IO.getn * Update lib/livebook/evaluator/io_proxy.ex Co-authored-by: José Valim <jose.valim@gmail.com> * Update lib/livebook_web/live/session_live/cell_component.ex Co-authored-by: José Valim <jose.valim@gmail.com> * Update lib/livebook_web/live/session_live/cell_component.ex Co-authored-by: José Valim <jose.valim@gmail.com> * Support for utf8 characters in getn function * Support for utf8 characters in getn function * Perform test with special characters * Accepting latin1 and unicode values * Update lib/livebook/evaluator/io_proxy.ex Co-authored-by: Jonatan Kłosko <jonatanklosko@gmail.com> * Added split_at function for better performance * Update lib/livebook/evaluator/io_proxy.ex Co-authored-by: Jonatan Kłosko <jonatanklosko@gmail.com> Co-authored-by: José Valim <jose.valim@gmail.com>
176 lines
4.8 KiB
Elixir
176 lines
4.8 KiB
Elixir
defmodule Livebook.Evaluator.IOProxyTest do
|
|
use ExUnit.Case, async: true
|
|
|
|
alias Livebook.Evaluator.IOProxy
|
|
|
|
setup do
|
|
{:ok, io} = IOProxy.start_link()
|
|
IOProxy.configure(io, self(), :ref)
|
|
%{io: io}
|
|
end
|
|
|
|
describe ":stdio interoperability" do
|
|
test "IO.puts", %{io: io} do
|
|
IO.puts(io, "hey")
|
|
assert_receive {:evaluation_output, :ref, "hey\n"}
|
|
end
|
|
|
|
test "IO.write", %{io: io} do
|
|
IO.write(io, "hey")
|
|
assert_receive {:evaluation_output, :ref, "hey"}
|
|
end
|
|
|
|
test "IO.inspect", %{io: io} do
|
|
IO.inspect(io, %{}, [])
|
|
assert_receive {:evaluation_output, :ref, "%{}\n"}
|
|
end
|
|
|
|
test "IO.read", %{io: io} do
|
|
pid =
|
|
spawn_link(fn ->
|
|
reply_to_input_request(:ref, "", :error, 1)
|
|
end)
|
|
|
|
IOProxy.configure(io, pid, :ref)
|
|
|
|
assert IO.read(io, :all) == {:error, "no matching Livebook input found"}
|
|
end
|
|
|
|
test "IO.gets", %{io: io} do
|
|
pid =
|
|
spawn_link(fn ->
|
|
reply_to_input_request(:ref, "name: ", {:ok, "Jake Peralta"}, 1)
|
|
end)
|
|
|
|
IOProxy.configure(io, pid, :ref)
|
|
|
|
assert IO.gets(io, "name: ") == "Jake Peralta"
|
|
end
|
|
|
|
test "IO.gets with no matching input", %{io: io} do
|
|
pid =
|
|
spawn_link(fn ->
|
|
reply_to_input_request(:ref, "name: ", :error, 1)
|
|
end)
|
|
|
|
IOProxy.configure(io, pid, :ref)
|
|
|
|
assert IO.gets(io, "name: ") == {:error, "no matching Livebook input found"}
|
|
end
|
|
end
|
|
|
|
test "consumes the given input only once", %{io: io} do
|
|
pid =
|
|
spawn_link(fn ->
|
|
reply_to_input_request(:ref, "name: ", {:ok, "Jake Peralta\nAmy Santiago\n"}, 1)
|
|
end)
|
|
|
|
IOProxy.configure(io, pid, :ref)
|
|
|
|
assert IO.gets(io, "name: ") == "Jake Peralta\n"
|
|
assert IO.gets(io, "name: ") == "Amy Santiago\n"
|
|
assert IO.gets(io, "name: ") == :eof
|
|
end
|
|
|
|
test "clear_input_buffers/1 clears all buffered input information", %{io: io} do
|
|
pid =
|
|
spawn_link(fn ->
|
|
reply_to_input_request(:ref, "name: ", {:ok, "Jake Peralta"}, 2)
|
|
end)
|
|
|
|
IOProxy.configure(io, pid, :ref)
|
|
|
|
assert IO.gets(io, "name: ") == "Jake Peralta"
|
|
IOProxy.clear_input_buffers(io)
|
|
assert IO.gets(io, "name: ") == "Jake Peralta"
|
|
end
|
|
|
|
test "buffers rapid output", %{io: io} do
|
|
IO.puts(io, "hey")
|
|
IO.puts(io, "hey")
|
|
assert_receive {:evaluation_output, :ref, "hey\nhey\n"}
|
|
end
|
|
|
|
test "respects CR as line cleaner", %{io: io} do
|
|
IO.write(io, "hey")
|
|
IO.write(io, "\roverride\r")
|
|
assert_receive {:evaluation_output, :ref, "\roverride\r"}
|
|
end
|
|
|
|
test "flush/1 synchronously sends buffer contents", %{io: io} do
|
|
IO.puts(io, "hey")
|
|
IOProxy.flush(io)
|
|
assert_received {:evaluation_output, :ref, "hey\n"}
|
|
end
|
|
|
|
test "supports direct livebook output forwarding", %{io: io} do
|
|
put_livebook_output(io, {:text, "[1, 2, 3]"})
|
|
|
|
assert_received {:evaluation_output, :ref, {:text, "[1, 2, 3]"}}
|
|
end
|
|
|
|
test "flush_widgets/1 returns new widget pids", %{io: io} do
|
|
widget1_pid = IEx.Helpers.pid(0, 0, 0)
|
|
widget2_pid = IEx.Helpers.pid(0, 0, 1)
|
|
|
|
put_livebook_output(io, {:vega_lite_dynamic, widget1_pid})
|
|
put_livebook_output(io, {:vega_lite_dynamic, widget2_pid})
|
|
put_livebook_output(io, {:vega_lite_dynamic, widget1_pid})
|
|
|
|
assert IOProxy.flush_widgets(io) == MapSet.new([widget1_pid, widget2_pid])
|
|
assert IOProxy.flush_widgets(io) == MapSet.new()
|
|
end
|
|
|
|
test "getn/1 return first character", %{io: io} do
|
|
pid =
|
|
spawn_link(fn ->
|
|
reply_to_input_request(:ref, "name: ", {:ok, "🐈 test\n"}, 1)
|
|
end)
|
|
|
|
IOProxy.configure(io, pid, :ref)
|
|
|
|
assert IO.getn(io, "name: ") == "🐈"
|
|
end
|
|
|
|
test "getn/2 returns the number of defined characters ", %{io: io} do
|
|
pid =
|
|
spawn_link(fn ->
|
|
reply_to_input_request(:ref, "name: ", {:ok, "Jake Peralta\nAmy Santiago\n"}, 1)
|
|
end)
|
|
|
|
IOProxy.configure(io, pid, :ref)
|
|
|
|
assert IO.getn(io, "name: ", 13) == "Jake Peralta\n"
|
|
assert IO.getn(io, "name: ", 13) == "Amy Santiago\n"
|
|
assert IO.getn(io, "name: ", 13) == :eof
|
|
end
|
|
|
|
test "getn/2 all characters", %{io: io} do
|
|
pid =
|
|
spawn_link(fn ->
|
|
reply_to_input_request(:ref, "name: ", {:ok, "Jake Peralta\nAmy Santiago\n"}, 1)
|
|
end)
|
|
|
|
IOProxy.configure(io, pid, :ref)
|
|
|
|
assert IO.getn(io, "name: ", 10_000) == "Jake Peralta\nAmy Santiago\n"
|
|
end
|
|
|
|
# Helpers
|
|
|
|
defp reply_to_input_request(_ref, _prompt, _reply, 0), do: :ok
|
|
|
|
defp reply_to_input_request(ref, prompt, reply, times) do
|
|
receive do
|
|
{:evaluation_input, ^ref, reply_to, ^prompt} ->
|
|
send(reply_to, {:evaluation_input_reply, reply})
|
|
reply_to_input_request(ref, prompt, reply, times - 1)
|
|
end
|
|
end
|
|
|
|
defp put_livebook_output(io, output) do
|
|
ref = make_ref()
|
|
send(io, {:io_request, self(), ref, {:livebook_put_output, output}})
|
|
assert_receive {:io_reply, ^ref, :ok}
|
|
end
|
|
end
|