livebook/test/livebook/runtime/evaluator/object_tracker_test.exs
2024-07-26 20:29:17 +02:00

79 lines
2.7 KiB
Elixir

defmodule Livebook.Runtime.Evaluator.ObjectTrackerTest do
use ExUnit.Case, async: true
alias Livebook.Runtime.Evaluator.ObjectTracker
setup do
{:ok, object_tracker} = start_supervised(ObjectTracker)
%{object_tracker: object_tracker}
end
test "monitor/5 returns an error when the given object doesn't exist",
%{object_tracker: object_tracker} do
assert {:error, :bad_object} =
ObjectTracker.monitor(object_tracker, :object1, self(), :object1_released, false)
end
test "sends scheduled monitor messages when all object references are released",
%{object_tracker: object_tracker} do
ObjectTracker.add_reference(object_tracker, :object1, {self(), :ref1})
ObjectTracker.add_reference(object_tracker, :object1, {self(), :ref2})
ObjectTracker.monitor(object_tracker, :object1, self(), :object1_released, false)
ObjectTracker.remove_reference_sync(object_tracker, {self(), :ref1})
ObjectTracker.remove_reference_sync(object_tracker, {self(), :ref2})
assert_received :object1_released
end
test "does not execute hooks when other references still point to the object",
%{object_tracker: object_tracker} do
ObjectTracker.add_reference(object_tracker, :object1, {self(), :ref1})
ObjectTracker.add_reference(object_tracker, :object1, {self(), :ref2})
ObjectTracker.monitor(object_tracker, :object1, self(), :object1_released, false)
ObjectTracker.remove_reference_sync(object_tracker, {self(), :ref1})
refute_received :object1_released
end
test "remove_reference_sync/2 awaits for monitor acknowledgments",
%{object_tracker: object_tracker} do
ObjectTracker.add_reference(object_tracker, :object1, {self(), :ref1})
ObjectTracker.monitor(object_tracker, :object1, self(), :object1_released1, true)
ObjectTracker.monitor(object_tracker, :object1, self(), :object1_released2, false)
myself = self()
spawn_link(fn ->
ObjectTracker.remove_reference_sync(object_tracker, {myself, :ref1})
send(myself, :removed)
end)
assert_receive {:object1_released1, ^object_tracker, reply_as}
assert_receive :object1_released2
refute_receive :removed
send(object_tracker, reply_as)
assert_receive :removed
end
test "removes a reference if its process terminates", %{object_tracker: object_tracker} do
reference_pid =
spawn(fn ->
receive do
:stop -> :ok
end
end)
ObjectTracker.add_reference(object_tracker, :object1, {reference_pid, :ref1})
ObjectTracker.monitor(object_tracker, :object1, self(), :object1_released, false)
send(reference_pid, :stop)
assert_receive :object1_released
end
end